Force near fnode use to use either fnode[0] or fnode[1] instead of the

allocation scheme. This eliminates the checks done in inthndlr.c because
the f_count field is no longer checked.


git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@1389 6ac86273-5f31-0410-b378-82cca8765d1b
This commit is contained in:
Bart Oldeman 2009-05-20 18:13:37 +00:00
parent 24b9d0e61e
commit 2092745236
6 changed files with 58 additions and 128 deletions

View File

@ -56,14 +56,13 @@ VOID dir_init_fnode(f_node_ptr fnp, CLUSTER dirstart)
fnp->f_cluster = fnp->f_dirstart = dirstart; fnp->f_cluster = fnp->f_dirstart = dirstart;
} }
f_node_ptr dir_open(register const char *dirname) f_node_ptr dir_open(register const char *dirname, f_node_ptr fnp)
{ {
f_node_ptr fnp;
int i; int i;
char fcbname[FNAME_SIZE + FEXT_SIZE]; char fcbname[FNAME_SIZE + FEXT_SIZE];
/* Allocate an fnode if possible - error return (0) if not. */ /* Allocate an fnode if possible - error return (0) if not. */
if ((fnp = get_f_node()) == (f_node_ptr) 0) if ((fnp = get_f_node(fnp)) == (f_node_ptr) 0)
{ {
return (f_node_ptr) 0; return (f_node_ptr) 0;
} }
@ -399,7 +398,7 @@ COUNT dos_findfirst(UCOUNT attr, BYTE * name)
{ {
char tmp = name[i]; char tmp = name[i];
name[i] = '\0'; name[i] = '\0';
if ((fnp = dir_open(name)) == NULL) if ((fnp = dir_open(name, &fnode[0])) == NULL)
return DE_PATHNOTFND; return DE_PATHNOTFND;
name[i] = tmp; name[i] = tmp;
} }
@ -462,7 +461,7 @@ COUNT dos_findnext(void)
REG dmatch *dmp = &sda_tmp_dm; REG dmatch *dmp = &sda_tmp_dm;
/* Allocate an fnode if possible - error return (0) if not. */ /* Allocate an fnode if possible - error return (0) if not. */
if ((fnp = get_f_node()) == (f_node_ptr) 0) if ((fnp = get_f_node(&fnode[0])) == (f_node_ptr) 0)
{ {
return DE_NFILES; return DE_NFILES;
} }

View File

@ -40,8 +40,7 @@ BYTE *RcsId = "$Id$";
f_node_ptr xlt_fd(COUNT); f_node_ptr xlt_fd(COUNT);
COUNT xlt_fnp(f_node_ptr); COUNT xlt_fnp(f_node_ptr);
STATIC void save_far_f_node(f_node_ptr fnp); STATIC void save_far_f_node(f_node_ptr fnp);
STATIC f_node_ptr get_near_f_node(void); STATIC f_node_ptr split_path(char *, char *, f_node_ptr fnp);
STATIC f_node_ptr split_path(char *, char *);
STATIC BOOL find_fname(f_node_ptr, char *, int); STATIC BOOL find_fname(f_node_ptr, char *, int);
/* /// Added - Ron Cemer */ /* /// Added - Ron Cemer */
STATIC void merge_file_changes(f_node_ptr fnp, int collect); STATIC void merge_file_changes(f_node_ptr fnp, int collect);
@ -149,7 +148,7 @@ long dos_open(char *path, unsigned flags, unsigned attrib)
/* next split the passed dir into comopnents (i.e. - path to */ /* next split the passed dir into comopnents (i.e. - path to */
/* new directory and name of new directory. */ /* new directory and name of new directory. */
if ((fnp = split_path(path, fcbname)) == NULL) if ((fnp = split_path(path, fcbname, &fnode[0])) == NULL)
return DE_PATHNOTFND; return DE_PATHNOTFND;
/* Check that we don't have a duplicate name, so if we */ /* Check that we don't have a duplicate name, so if we */
@ -296,10 +295,9 @@ COUNT dos_commit(COUNT fd)
/* note: an invalid fd is indicated by a 0 return */ /* note: an invalid fd is indicated by a 0 return */
if (fnp == (f_node_ptr) 0) if (fnp == (f_node_ptr) 0)
return DE_INVLDHNDL; return DE_INVLDHNDL;
fnp2 = get_f_node(); fnp2 = get_f_node(&fnode[1]);
if (fnp2 == (f_node_ptr) 0) if (fnp2 == (f_node_ptr) 0)
{ {
release_near_f_node(fnp);
return DE_INVLDHNDL; return DE_INVLDHNDL;
} }
@ -307,17 +305,14 @@ COUNT dos_commit(COUNT fd)
is updated etc, but we keep our old info */ is updated etc, but we keep our old info */
memcpy(fnp2, fnp, sizeof(*fnp)); memcpy(fnp2, fnp, sizeof(*fnp));
save_far_f_node(fnp2); save_far_f_node(fnp2);
release_near_f_node(fnp);
return dos_close(xlt_fnp(fnp2)); return dos_close(xlt_fnp(fnp2));
} }
/* */ /* */
/* split a path into it's component directory and file name */ /* split a path into it's component directory and file name */
/* */ /* */
f_node_ptr split_path(char * path, char * fcbname) f_node_ptr split_path(char * path, char * fcbname, f_node_ptr fnp)
{ {
REG f_node_ptr fnp;
/* Start off by parsing out the components. */ /* Start off by parsing out the components. */
int dirlength = ParseDosName(path, fcbname, FALSE); int dirlength = ParseDosName(path, fcbname, FALSE);
@ -348,7 +343,7 @@ f_node_ptr split_path(char * path, char * fcbname)
{ {
char tmp = path[dirlength]; char tmp = path[dirlength];
path[dirlength] = '\0'; path[dirlength] = '\0';
fnp = dir_open(path); fnp = dir_open(path, fnp);
path[dirlength] = tmp; path[dirlength] = tmp;
} }
@ -370,7 +365,7 @@ BOOL dir_exists(char * path)
REG f_node_ptr fnp; REG f_node_ptr fnp;
char fcbname[FNAME_SIZE + FEXT_SIZE]; char fcbname[FNAME_SIZE + FEXT_SIZE];
if ((fnp = split_path(path, fcbname)) == NULL) if ((fnp = split_path(path, fcbname, &fnode[0])) == NULL)
return FALSE; return FALSE;
dir_close(fnp); dir_close(fnp);
@ -451,7 +446,7 @@ STATIC void merge_file_changes(f_node_ptr fnp, int collect)
return; return;
fd = xlt_fnp(fnp); fd = xlt_fnp(fnp);
fnp2 = get_near_f_node(); fnp2 = &fnode[1];
for (i = 0; i < f_nodes_cnt; i++) for (i = 0; i < f_nodes_cnt; i++)
{ {
fmemcpy(fnp2, &f_nodes[i], sizeof(*fnp2)); fmemcpy(fnp2, &f_nodes[i], sizeof(*fnp2));
@ -479,7 +474,6 @@ STATIC void merge_file_changes(f_node_ptr fnp, int collect)
} }
} }
} }
release_near_f_node(fnp2);
} }
/* /// Added - Ron Cemer */ /* /// Added - Ron Cemer */
@ -538,7 +532,7 @@ COUNT dos_delete(BYTE * path, int attrib)
/* first split the passed dir into components (i.e. - */ /* first split the passed dir into components (i.e. - */
/* path to new directory and name of new directory */ /* path to new directory and name of new directory */
if ((fnp = split_path(path, fcbname)) == NULL) if ((fnp = split_path(path, fcbname, &fnode[0])) == NULL)
{ {
return DE_PATHNOTFND; return DE_PATHNOTFND;
} }
@ -581,7 +575,7 @@ COUNT dos_rmdir(BYTE * path)
/* next, split the passed dir into components (i.e. - */ /* next, split the passed dir into components (i.e. - */
/* path to new directory and name of new directory */ /* path to new directory and name of new directory */
if ((fnp = split_path(path, fcbname)) == NULL) if ((fnp = split_path(path, fcbname, &fnode[0])) == NULL)
{ {
return DE_PATHNOTFND; return DE_PATHNOTFND;
} }
@ -611,7 +605,7 @@ COUNT dos_rmdir(BYTE * path)
/* Check that the directory is empty. Only the */ /* Check that the directory is empty. Only the */
/* "." and ".." are permissable. */ /* "." and ".." are permissable. */
fnp->f_flags &= ~F_DMOD; fnp->f_flags &= ~F_DMOD;
fnp1 = dir_open(path); fnp1 = dir_open(path, &fnode[1]);
if (fnp1 == NULL) if (fnp1 == NULL)
{ {
dir_close(fnp); dir_close(fnp);
@ -683,7 +677,7 @@ COUNT dos_rename(BYTE * path1, BYTE * path2, int attrib)
/* first split the passed target into compnents (i.e. - path to */ /* first split the passed target into compnents (i.e. - path to */
/* new file name and name of new file name */ /* new file name and name of new file name */
if ((fnp2 = split_path(path2, fcbname)) == NULL) if ((fnp2 = split_path(path2, fcbname, &fnode[1])) == NULL)
{ {
return DE_PATHNOTFND; return DE_PATHNOTFND;
} }
@ -698,7 +692,7 @@ COUNT dos_rename(BYTE * path1, BYTE * path2, int attrib)
/* next split the passed source into compnents (i.e. - path to */ /* next split the passed source into compnents (i.e. - path to */
/* old file name and name of old file name */ /* old file name and name of old file name */
if ((fnp1 = split_path(path1, fcbname)) == NULL) if ((fnp1 = split_path(path1, fcbname, &fnode[0])) == NULL)
{ {
dir_close(fnp2); dir_close(fnp2);
return DE_PATHNOTFND; return DE_PATHNOTFND;
@ -816,7 +810,7 @@ STATIC int alloc_find_free(f_node_ptr fnp, char *path, char *fcbname)
{ {
fnp->f_flags &= ~F_DMOD; fnp->f_flags &= ~F_DMOD;
dir_close(fnp); dir_close(fnp);
fnp = split_path(path, fcbname); fnp = split_path(path, fcbname, fnp);
/* Get a free f_node pointer so that we can use */ /* Get a free f_node pointer so that we can use */
/* it in building the new file. */ /* it in building the new file. */
@ -891,7 +885,6 @@ COUNT dos_getftime(COUNT fd, date FAR * dp, time FAR * tp)
*dp = fnp->f_dir.dir_date; *dp = fnp->f_dir.dir_date;
*tp = fnp->f_dir.dir_time; *tp = fnp->f_dir.dir_time;
release_near_f_node(fnp);
return SUCCESS; return SUCCESS;
} }
@ -940,7 +933,6 @@ ULONG dos_getfsize(COUNT fd)
return (ULONG)-1l; return (ULONG)-1l;
/* Return the file size */ /* Return the file size */
release_near_f_node(fnp);
return fnp->f_dir.dir_size; return fnp->f_dir.dir_size;
} }
@ -1053,7 +1045,7 @@ COUNT dos_mkdir(BYTE * dir)
/* first split the passed dir into components (i.e. - */ /* first split the passed dir into components (i.e. - */
/* path to new directory and name of new directory */ /* path to new directory and name of new directory */
if ((fnp = split_path(dir, fcbname)) == NULL) if ((fnp = split_path(dir, fcbname, &fnode[0])) == NULL)
{ {
return DE_PATHNOTFND; return DE_PATHNOTFND;
} }
@ -1824,7 +1816,6 @@ LONG dos_lseek(COUNT fd, LONG foffset, COUNT origin)
/* default to an invalid function */ /* default to an invalid function */
default: default:
release_near_f_node(fnp);
return (LONG) DE_INVLDFUNC; return (LONG) DE_INVLDFUNC;
} }
save_far_f_node(fnp); save_far_f_node(fnp);
@ -1883,7 +1874,7 @@ int dos_cd(char * PathName)
return DE_INVLDDRV; return DE_INVLDDRV;
/* now test for its existance. If it doesn't, return an error. */ /* now test for its existance. If it doesn't, return an error. */
if ((fnp = dir_open(PathName)) == NULL) if ((fnp = dir_open(PathName, &fnode[0])) == NULL)
return DE_PATHNOTFND; return DE_PATHNOTFND;
/* problem: RBIL table 01643 does not give a FAT32 field for the /* problem: RBIL table 01643 does not give a FAT32 field for the
@ -1894,48 +1885,21 @@ int dos_cd(char * PathName)
} }
#endif #endif
/* try to allocate a near f_node */
/* (there are just two of them, in the SDA) */
f_node_ptr get_near_f_node(void)
{
f_node_ptr fnp = fnode;
if (fnp->f_count == 0)
fnp->f_count++;
else
{
fnp++;
if (fnp->f_count == 0)
fnp->f_count++;
else
{
fnp = (f_node_ptr) 0;
panic("more than two near fnodes requested at the same time!\n");
}
}
return fnp;
}
/* Try to allocate an f_node from the available files array */ /* Try to allocate an f_node from the available files array */
f_node_ptr get_f_node(void) f_node_ptr get_f_node(f_node_ptr fnp)
{ {
REG int i; REG int i;
f_node_ptr fnp = get_near_f_node();
if (fnp != (f_node_ptr)0) for (i = 0; i < f_nodes_cnt; i++)
{ {
for (i = 0; i < f_nodes_cnt; i++) if (f_nodes[i].f_count == 0)
{ {
if (f_nodes[i].f_count == 0) ++f_nodes[i].f_count;
{ fnp->f_count = 1;
++f_nodes[i].f_count; fnode_fd[fnp - fnode] = i;
fnode_fd[fnp - fnode] = i; return fnp;
return fnp;
}
} }
release_near_f_node(fnp);
} }
return (f_node_ptr) 0; return (f_node_ptr) 0;
} }
@ -1948,7 +1912,6 @@ VOID release_f_node(f_node_ptr fnp)
--fp->f_count; --fp->f_count;
else else
fp->f_count = 0; fp->f_count = 0;
release_near_f_node(fnp);
} }
#ifndef IPL #ifndef IPL
@ -1962,7 +1925,6 @@ COUNT dos_getfattr_fd(COUNT fd)
if (fnp == (f_node_ptr) 0) if (fnp == (f_node_ptr) 0)
return DE_TOOMANY; return DE_TOOMANY;
release_near_f_node(fnp);
return fnp->f_dir.dir_attrib; return fnp->f_dir.dir_attrib;
} }
@ -2191,36 +2153,28 @@ COUNT xlt_fnp(f_node_ptr fnp)
return fnode_fd[fnp - fnode]; return fnode_fd[fnp - fnode];
} }
/* allocate a near fnode and copy the far fd fnode to it */ /* copy the far fnode fd into the first near fnode */
f_node_ptr xlt_fd(int fd) f_node_ptr xlt_fd(int fd)
{ {
f_node_ptr fnp = (f_node_ptr) 0;
/* If the fd was invalid because it was out of range or the */ /* If the fd was invalid because it was out of range or the */
/* requested file was not open, tell the caller and exit */ /* requested file was not open, tell the caller and exit */
/* note: an invalid fd is indicated by a 0 return */ /* note: an invalid fd is indicated by a 0 return */
if (fd < f_nodes_cnt) if (fd < f_nodes_cnt)
{ {
fnp = get_near_f_node(); fmemcpy(&fnode[0], &f_nodes[fd], sizeof(fnode[0]));
if (fnp != (f_node_ptr)0) if (fnode[0].f_count > 0)
{ {
fmemcpy(fnp, &f_nodes[fd], sizeof(*fnp)); fnode_fd[0] = fd;
if (fnp->f_count == 0) return &fnode[0];
{
release_near_f_node(fnp);
fnp = (f_node_ptr) 0;
} else
fnode_fd[fnp - fnode] = fd;
} }
} }
return fnp; return NULL;
} }
/* copy a near fnode to the corresponding far one and release it */ /* copy a near fnode to the corresponding far one */
STATIC void save_far_f_node(f_node_ptr fnp) STATIC void save_far_f_node(f_node_ptr fnp)
{ {
fmemcpy(&f_nodes[xlt_fnp(fnp)], fnp, sizeof(*fnp)); fmemcpy(&f_nodes[xlt_fnp(fnp)], fnp, sizeof(*fnp));
release_near_f_node(fnp);
} }
/* TE /* TE

View File

@ -425,5 +425,13 @@ void ASMCFUNC DosIdle_hlt(void); /* dosidle.asm */
GLOBAL BYTE ReturnAnyDosVersionExpected; GLOBAL BYTE ReturnAnyDosVersionExpected;
GLOBAL BYTE ASM HaltCpuWhileIdle; GLOBAL BYTE ASM HaltCpuWhileIdle;
/* near fnodes:
* fnode[0] is used internally for almost all cases.
* fnode[1] is only used for:
* 1) rename (target)
* 2) rmdir (checks if the directory to remove is empty)
* 3) commit (copies, than closes fnode[0])
* 3) merge_file_changes (for SHARE)
*/
GLOBAL struct f_node fnode[2]; GLOBAL struct f_node fnode[2];
GLOBAL int fnode_fd[2]; GLOBAL int fnode_fd[2];

View File

@ -426,28 +426,23 @@ dispatch:
} }
/* Clear carry by default for these functions */ /* Clear carry by default for these functions */
/* We force clear the near fnodes, /*
On a normal int21h entry these are unused, so should already what happened:
be clear, thus this code is effectively redundant. Application does FindFirst("I:\*.*");
However when re-entering int21h, such as a device driver this fails, and causes Int24
(e.g. shsufdrv), the fnodes may contain the values of the this sets ErrorMode, and calls Int24
in progress call; as long as the driver/tsr causing the Application decides NOT to return to DOS,
reentrancey saves and restores the SDA across the call then but instead pop the stack and return to itself
any changes we do (ie clearing these) should go unnoticed (this is legal; see RBIL/INT 24 description
and if the cause of the reentrancy does not save/restore the
SDA then the caller should expected the unexpected. *) errormode NEVER gets set back to 0 until exit()
Failure to do this will at a minimal result in the extra
output indicating fnodes not 0 (and possibly clearing at end I have NO idea how real DOS handles this;
of call) when the re-entered int21h call completes, but could the appended patch cures the worst symptoms
result in the re-entered call to fail with no free near fnodes */
if both are already in use by the original int21h call (?bug 1879?).
See also PATCH TE 5 jul 04 explanation at end
*/
if (/*ErrorMode && */lr.AH > 0x0c && lr.AH != 0x30 && lr.AH != 0x59) if (/*ErrorMode && */lr.AH > 0x0c && lr.AH != 0x30 && lr.AH != 0x59)
{ {
/*if (ErrorMode)*/ ErrorMode = 0; /*if (ErrorMode)*/ ErrorMode = 0;
fnode[0].f_count = 0; /* don't panic - THEY ARE unused !! */
fnode[1].f_count = 0;
} }
/* Check for Ctrl-Break */ /* Check for Ctrl-Break */
if (break_ena || (lr.AH >= 1 && lr.AH <= 5) || (lr.AH >= 8 && lr.AH <= 0x0b)) if (break_ena || (lr.AH >= 1 && lr.AH <= 5) || (lr.AH >= 8 && lr.AH <= 0x0b))
@ -1573,31 +1568,6 @@ exit_dispatch:
r->ES = lr.ES; r->ES = lr.ES;
real_exit:; real_exit:;
/* PATCH !! TE 5 JUL 04
what happened:
Application does FindFirst("I:\*.*");
this fails, and causes Int24
this sets ErrorMode, and calls Int24
Application decides NOT to return to DOS,
but instead pop the stack and return to itself
(this is legal; see RBIL/INT 24 description
a) now the alloc()'ed fnode[0] never gets free()'ed
b) errormode NEVER gets set back to 0 unyil exit()
I have NO idea how real DOS handles this;
the appended patch cures the worst symptoms
*/
if (fnode[0].f_count != 0 ||
fnode[1].f_count != 0 )
{
if (ErrorMode == 0)
put_string("near_fnodes not 0"); /* panic ?? */
fnode[0].f_count = 0; /* don't panic - THEY ARE unused !! */
fnode[1].f_count = 0;
}
/* PATCH !! END TE 5 JUL 04 */
#ifdef DEBUG #ifdef DEBUG
if (bDumpRegs) if (bDumpRegs)
{ {

View File

@ -50,7 +50,7 @@ VOID unicode_to_lfn(UNICODE FAR **name, struct lfn_entry FAR *lep);
*/ */
COUNT lfn_allocate_inode(VOID) COUNT lfn_allocate_inode(VOID)
{ {
f_node_ptr fnp = get_f_node(); f_node_ptr fnp = get_f_node(&fnode[0]);
struct dpb FAR *dpbp; struct dpb FAR *dpbp;
COUNT handle; COUNT handle;
if (fnp == 0) return LHE_NOFREEHNDL; if (fnp == 0) return LHE_NOFREEHNDL;

View File

@ -138,7 +138,7 @@ VOID fatal(BYTE * err_msg);
/* fatdir.c */ /* fatdir.c */
VOID dir_init_fnode(f_node_ptr fnp, CLUSTER dirstart); VOID dir_init_fnode(f_node_ptr fnp, CLUSTER dirstart);
f_node_ptr dir_open(const char *dirname); f_node_ptr dir_open(const char *dirname, f_node_ptr fnp);
COUNT dir_read(REG f_node_ptr fnp); COUNT dir_read(REG f_node_ptr fnp);
BOOL dir_write(REG f_node_ptr fnp); BOOL dir_write(REG f_node_ptr fnp);
VOID dir_close(REG f_node_ptr fnp); VOID dir_close(REG f_node_ptr fnp);
@ -180,9 +180,8 @@ VOID trim_path(BYTE FAR * s);
int dos_cd(char * PathName); int dos_cd(char * PathName);
f_node_ptr get_f_node(void); f_node_ptr get_f_node(f_node_ptr fnp);
VOID release_f_node(f_node_ptr fnp); VOID release_f_node(f_node_ptr fnp);
#define release_near_f_node(fnp) ((fnp)->f_count = 0)
COUNT dos_getfattr_fd(COUNT fd); COUNT dos_getfattr_fd(COUNT fd);
COUNT dos_getfattr(BYTE * name); COUNT dos_getfattr(BYTE * name);
COUNT dos_setfattr(BYTE * name, UWORD attrp); COUNT dos_setfattr(BYTE * name, UWORD attrp);