From affddaaf64e4c1f5b44ceb1eaf1613b3d2bf45ac Mon Sep 17 00:00:00 2001 From: Bart Oldeman Date: Sat, 23 May 2009 02:04:03 +0000 Subject: [PATCH] Handle dos_getfattr and dos_setfattr directly at the directory level, instead of opening the file, to avoid needing to claim SFTs in later changes. Clarify and implement parts of the correct SHARE behaviour. git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@1393 6ac86273-5f31-0410-b378-82cca8765d1b --- kernel/dosfns.c | 49 ++++++++++------------------------------------ kernel/fatfs.c | 52 +++++++++++++++++++++++++++++++------------------ 2 files changed, 43 insertions(+), 58 deletions(-) diff --git a/kernel/dosfns.c b/kernel/dosfns.c index 917f0dc..75c5804 100644 --- a/kernel/dosfns.c +++ b/kernel/dosfns.c @@ -1206,34 +1206,6 @@ COUNT DosGetFattr(BYTE FAR * name) if (result & IS_DEVICE) return DE_FILENOTFND; -/* /// Use truename()'s result, which we already have in PriPathName. - I copy it to tmp_name because PriPathName is global and seems - to get trashed somewhere in transit. - The reason for using truename()'s result is that dos_?etfattr() - are very low-level functions and don't handle full path expansion - or cleanup, such as converting "c:\a\b\.\c\.." to "C:\A\B". - - Ron Cemer -*/ -/* - memcpy(SecPathName,PriPathName,sizeof(SecPathName)); - return dos_getfattr(SecPathName, attrp); -*/ - /* no longer true. dos_getfattr() is - A) intelligent (uses dos_open) anyway - B) there are some problems with MAX_PARSE, i.e. if PATH ~= 64 - and TRUENAME adds a C:, which leeds to trouble. - - the problem was discovered, when VC did something like - - fd = DosOpen(filename,...) - jc can't_copy_dialog; - - attr = DosGetAttrib(filename); - jc can't_copy_dialog; - and suddenly, the filehandle stays open - shit. - tom - */ return dos_getfattr(PriPathName); } @@ -1254,17 +1226,16 @@ COUNT DosSetFattr(BYTE FAR * name, UWORD attrp) if (result & IS_DEVICE) return DE_FILENOTFND; -/* /// Use truename()'s result, which we already have in PriPathName. - I copy it to tmp_name because PriPathName is global and seems - to get trashed somewhere in transit. - - Ron Cemer -*/ -/* - memcpy(SecPathName,PriPathName,sizeof(SecPathName)); - return dos_setfattr(SecPathName, attrp); - - see DosGetAttr() -*/ + if (IsShareInstalled(TRUE)) + { + /* XXX SHARE should ideally close the file if it is opened in + * compatibility mode, else generate a critical error. + * Here just generate a critical error by opening in "rw compat" + * mode */ + if ((result = share_open_check(PriPathName, cu_psp, O_RDWR, 0)) < 0) + return result; + share_close_file(result); + } return dos_setfattr(PriPathName, attrp); } diff --git a/kernel/fatfs.c b/kernel/fatfs.c index d6c01ac..dee5704 100644 --- a/kernel/fatfs.c +++ b/kernel/fatfs.c @@ -501,6 +501,7 @@ STATIC void copy_file_changes(f_node_ptr src, f_node_ptr dst) dst->f_dir.dir_size = src->f_dir.dir_size; dst->f_dir.dir_date = src->f_dir.dir_date; dst->f_dir.dir_time = src->f_dir.dir_time; + dst->f_dir.dir_attrib = src->f_dir.dir_attrib; } STATIC COUNT delete_dir_entry(f_node_ptr fnp) @@ -1935,21 +1936,28 @@ COUNT dos_getfattr_fd(COUNT fd) COUNT dos_getfattr(BYTE * name) { - COUNT result, fd; + f_node_ptr fnp; + char fcbname[FNAME_SIZE + FEXT_SIZE]; + COUNT result; - fd = (short)dos_open(name, O_RDONLY | O_OPEN, 0); - if (fd < SUCCESS) - return fd; + /* split the passed dir into components (i.e. - path to */ + /* new directory and name of new directory. */ + if ((fnp = split_path(name, fcbname, &fnode[0])) == NULL) + return DE_PATHNOTFND; - result = dos_getfattr_fd(fd); - dos_close(fd); + if (find_fname(fnp, fcbname, D_ALL)) + result = fnp->f_dir.dir_attrib; + else + result = DE_FILENOTFND; + + dir_close(fnp); return result; } COUNT dos_setfattr(BYTE * name, UWORD attrp) { - COUNT fd; f_node_ptr fnp; + char fcbname[FNAME_SIZE + FEXT_SIZE]; /* JPP-If user tries to set VOLID or RESERVED bits, return error. We used to also check for D_DIR here, but causes issues with deltree @@ -1960,29 +1968,35 @@ COUNT dos_setfattr(BYTE * name, UWORD attrp) if ((attrp & (D_VOLID | 0xC0)) != 0) return DE_ACCESS; - fd = (short)dos_open(name, O_RDONLY | O_OPEN, 0); - if (fd < SUCCESS) - return fd; + /* split the passed dir into components (i.e. - path to */ + /* new directory and name of new directory. */ + if ((fnp = split_path(name, fcbname, &fnode[0])) == NULL) + return DE_PATHNOTFND; - fnp = xlt_fd(fd); - - /* Set the attribute from the fnode and return */ - /* clear all attributes but DIR and VOLID */ - fnp->f_dir.dir_attrib &= (D_VOLID | D_DIR); /* JPP */ + if (!find_fname(fnp, fcbname, D_ALL)) { + dir_close(fnp); + return DE_FILENOTFND; + } /* if caller tries to set DIR on non-directory, return error */ if ((attrp & D_DIR) && !(fnp->f_dir.dir_attrib & D_DIR)) { - dos_close(fd); + dir_close(fnp); return DE_ACCESS; } - + + /* Set the attribute from the fnode and return */ + /* clear all attributes but DIR and VOLID */ + fnp->f_dir.dir_attrib &= (D_VOLID | D_DIR); /* JPP */ + /* set attributes that user requested */ fnp->f_dir.dir_attrib |= attrp; /* JPP */ fnp->f_flags |= F_DMOD | F_DDATE; + + /* should really close the file instead of merge */ merge_file_changes(fnp, FALSE); - save_far_f_node(fnp); - dos_close(fd); + dir_write(fnp); + dir_close(fnp); return SUCCESS; } #endif