mirror of https://github.com/FDOS/kernel.git
dir_read() no longer updates the diroff counter. This eliminates the NEW
field, simplifies remove_lfn_entries(), and avoids a bug if you delete the first entry in the root directory on FAT32. git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@911 6ac86273-5f31-0410-b378-82cca8765d1b
This commit is contained in:
parent
976efed7a5
commit
ecfcb9be29
|
@ -54,9 +54,8 @@ struct f_node {
|
|||
};
|
||||
|
||||
#define F_DMOD 1 /* directory has been modified */
|
||||
#define F_DNEW 2 /* fnode is new and needs fill */
|
||||
#define F_DDIR 4 /* fnode is assigned to dir */
|
||||
#define F_DDATE 8 /* date set using setdate */
|
||||
#define F_DDIR 2 /* fnode is assigned to dir */
|
||||
#define F_DDATE 4 /* date set using setdate */
|
||||
|
||||
typedef struct f_node *f_node_ptr;
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ static BYTE *fatdirRcsId =
|
|||
VOID dir_init_fnode(f_node_ptr fnp, CLUSTER dirstart)
|
||||
{
|
||||
/* reset the directory flags */
|
||||
fnp->f_flags = F_DDIR | F_DNEW;
|
||||
fnp->f_flags = F_DDIR;
|
||||
fnp->f_diroff = 0;
|
||||
fnp->f_offset = 0l;
|
||||
fnp->f_cluster_offset = 0;
|
||||
|
@ -143,6 +143,7 @@ f_node_ptr dir_open(register const char *dirname)
|
|||
i = TRUE;
|
||||
break;
|
||||
}
|
||||
fnp->f_diroff++;
|
||||
}
|
||||
|
||||
if (!i || !(fnp->f_dir.dir_attrib & D_DIR))
|
||||
|
@ -198,22 +199,11 @@ COUNT dir_read(REG f_node_ptr fnp)
|
|||
{
|
||||
struct buffer FAR *bp;
|
||||
REG UWORD secsize = fnp->f_dpb->dpb_secsize;
|
||||
unsigned new_diroff = fnp->f_diroff;
|
||||
|
||||
/* can't have more than 65535 directory entries
|
||||
remove lfn entries may call us with new_diroff == -1
|
||||
for root directories though */
|
||||
if (fnp->f_dirstart != 0 && new_diroff >= 65535U)
|
||||
/* can't have more than 65535 directory entries */
|
||||
if (fnp->f_diroff >= 65535U)
|
||||
return DE_SEEK;
|
||||
|
||||
/* Directories need to point to their current offset, not for */
|
||||
/* next op. Therefore, if it is anything other than the first */
|
||||
/* directory entry, we will update the offset on entry rather */
|
||||
/* than wait until exit. If it was new, clear the special new */
|
||||
/* flag. */
|
||||
if (!(fnp->f_flags & F_DNEW))
|
||||
new_diroff++;
|
||||
|
||||
/* Determine if we hit the end of the directory. If we have, */
|
||||
/* bump the offset back to the end and exit. If not, fill the */
|
||||
/* dirent portion of the fnode, clear the f_dmod bit and leave, */
|
||||
|
@ -221,10 +211,10 @@ COUNT dir_read(REG f_node_ptr fnp)
|
|||
|
||||
if (fnp->f_dirstart == 0)
|
||||
{
|
||||
if (new_diroff >= fnp->f_dpb->dpb_dirents)
|
||||
if (fnp->f_diroff >= fnp->f_dpb->dpb_dirents)
|
||||
return DE_SEEK;
|
||||
|
||||
bp = getblock(new_diroff / (secsize / DIRENT_SIZE)
|
||||
bp = getblock(fnp->f_diroff / (secsize / DIRENT_SIZE)
|
||||
+ fnp->f_dpb->dpb_dirstrt, fnp->f_dpb->dpb_unit);
|
||||
#ifdef DISPLAY_GETBLOCK
|
||||
printf("DIR (dir_read)\n");
|
||||
|
@ -233,7 +223,7 @@ COUNT dir_read(REG f_node_ptr fnp)
|
|||
else
|
||||
{
|
||||
/* Do a "seek" to the directory position */
|
||||
fnp->f_offset = new_diroff * (ULONG)DIRENT_SIZE;
|
||||
fnp->f_offset = fnp->f_diroff * (ULONG)DIRENT_SIZE;
|
||||
|
||||
/* Search through the FAT to find the block */
|
||||
/* that this entry is in. */
|
||||
|
@ -258,14 +248,13 @@ COUNT dir_read(REG f_node_ptr fnp)
|
|||
bp->b_flag |= BFR_DIR | BFR_VALID;
|
||||
|
||||
getdirent((BYTE FAR *) & bp->
|
||||
b_buffer[(new_diroff * DIRENT_SIZE) % fnp->f_dpb->dpb_secsize],
|
||||
b_buffer[(fnp->f_diroff * DIRENT_SIZE) % fnp->f_dpb->dpb_secsize],
|
||||
&fnp->f_dir);
|
||||
|
||||
swap_deleted(fnp->f_dir.dir_name);
|
||||
|
||||
/* Update the fnode's directory info */
|
||||
fnp->f_flags &= ~(F_DMOD | F_DNEW);
|
||||
fnp->f_diroff = new_diroff;
|
||||
fnp->f_flags &= ~F_DMOD;
|
||||
|
||||
/* and for efficiency, stop when we hit the first */
|
||||
/* unused entry. */
|
||||
|
@ -278,9 +267,6 @@ COUNT dir_read(REG f_node_ptr fnp)
|
|||
* situation fnode is released.
|
||||
* The caller should set
|
||||
* 1. F_DMOD flag if original directory entry was modified.
|
||||
* 2. F_DMOD & F_DNEW flags if new directory entry is created. In this
|
||||
* case the reserved fields is cleared, but only if new dentry isn't
|
||||
* a LFN entry (has D_LFN attribute).
|
||||
* Return value.
|
||||
* TRUE - all OK.
|
||||
* FALSE - error occured (fnode is released).
|
||||
|
@ -348,9 +334,6 @@ BOOL dir_write(REG f_node_ptr fnp)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if ((fnp->f_flags & F_DNEW) && fnp->f_dir.dir_attrib != D_LFN)
|
||||
fmemset(&fnp->f_dir.dir_case, 0, 8);
|
||||
|
||||
swap_deleted(fnp->f_dir.dir_name);
|
||||
|
||||
putdirent(&fnp->f_dir, &bp->b_buffer[(fnp->f_diroff * DIRENT_SIZE) %
|
||||
|
@ -454,6 +437,7 @@ COUNT dos_findfirst(UCOUNT attr, BYTE * name)
|
|||
dir_close(fnp);
|
||||
return SUCCESS;
|
||||
}
|
||||
fnp->f_diroff++;
|
||||
}
|
||||
|
||||
/* Now that we've done our failed search, close it and */
|
||||
|
@ -509,17 +493,13 @@ COUNT dos_findnext(void)
|
|||
|
||||
/* Search through the directory to find the entry, but do a */
|
||||
/* seek first. */
|
||||
fnp->f_flags |= F_DNEW;
|
||||
if (dmp->dm_entry > 0)
|
||||
{
|
||||
fnp->f_diroff = dmp->dm_entry - 1;
|
||||
fnp->f_flags &= ~F_DNEW;
|
||||
}
|
||||
fnp->f_diroff = dmp->dm_entry;
|
||||
|
||||
/* Loop through the directory */
|
||||
while (dir_read(fnp) == 1)
|
||||
{
|
||||
++dmp->dm_entry;
|
||||
++fnp->f_diroff;
|
||||
if (fnp->f_dir.dir_name[0] != '\0' && fnp->f_dir.dir_name[0] != DELETED
|
||||
&& (fnp->f_dir.dir_attrib & D_VOLID) != D_VOLID)
|
||||
{
|
||||
|
|
|
@ -407,6 +407,7 @@ STATIC BOOL find_fname(f_node_ptr fnp, char *fcbname, int attr)
|
|||
{
|
||||
return TRUE;
|
||||
}
|
||||
fnp->f_diroff++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -428,10 +429,7 @@ COUNT remove_lfn_entries(f_node_ptr fnp)
|
|||
{
|
||||
if (fnp->f_diroff == 0)
|
||||
break;
|
||||
fnp->f_diroff -= 2;
|
||||
/* it cannot / should not get below 0 because of '.' and '..'
|
||||
* except for root directories... but then dir_read() makes it 0
|
||||
* again */
|
||||
fnp->f_diroff--;
|
||||
if (dir_read(fnp) <= 0) {
|
||||
dir_close(fnp);
|
||||
return DE_BLKINVLD;
|
||||
|
@ -442,7 +440,7 @@ COUNT remove_lfn_entries(f_node_ptr fnp)
|
|||
fnp->f_flags |= F_DMOD;
|
||||
if (!dir_write(fnp)) return DE_BLKINVLD;
|
||||
}
|
||||
fnp->f_diroff = original_diroff - 1;
|
||||
fnp->f_diroff = original_diroff;
|
||||
if (dir_read(fnp) <= 0) {
|
||||
dir_close(fnp);
|
||||
return DE_BLKINVLD;
|
||||
|
@ -642,6 +640,7 @@ COUNT dos_rmdir(BYTE * path)
|
|||
return DE_ACCESS;
|
||||
}
|
||||
|
||||
fnp1->f_diroff++;
|
||||
dir_read(fnp1);
|
||||
if (fnp1->f_dir.dir_name[0] != '.')
|
||||
{
|
||||
|
@ -652,18 +651,18 @@ COUNT dos_rmdir(BYTE * path)
|
|||
/* Now search through the directory and make certain */
|
||||
/* that there are no entries. */
|
||||
found = FALSE;
|
||||
fnp1->f_diroff++;
|
||||
while (dir_read(fnp1) == 1)
|
||||
{
|
||||
if (fnp1->f_dir.dir_name[0] == '\0')
|
||||
break;
|
||||
if (fnp1->f_dir.dir_name[0] == DELETED
|
||||
|| fnp1->f_dir.dir_attrib == D_LFN)
|
||||
continue;
|
||||
else
|
||||
if (fnp1->f_dir.dir_name[0] != DELETED
|
||||
&& fnp1->f_dir.dir_attrib != D_LFN)
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
fnp1->f_diroff++;
|
||||
}
|
||||
|
||||
dir_close(fnp1);
|
||||
|
@ -817,8 +816,11 @@ STATIC BOOL find_free(f_node_ptr fnp)
|
|||
COUNT rc;
|
||||
|
||||
while ((rc = dir_read(fnp)) == 1)
|
||||
{
|
||||
if (fnp->f_dir.dir_name[0] == DELETED)
|
||||
return TRUE;
|
||||
fnp->f_diroff++;
|
||||
}
|
||||
return rc >= 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue