📄 fatdir.c
字号:
/****************************************************************/
/* */
/* fatdir.c */
/* DOS-C */
/* */
/* FAT File System dir Functions */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#include "../../hdr/portab.h"
#include "globals.h"
/* $Logfile: C:/dos-c/src/fs/fatdir.c_v $ */
#ifdef VERSION_STRINGS
static BYTE *fatdirRcsId = "$Header: C:/dos-c/src/fs/fatdir.c_v 1.9 22 Jan 1998 4:09:00 patv $";
#endif
/* $Log: C:/dos-c/src/fs/fatdir.c_v $
*
* Rev 1.9 22 Jan 1998 4:09:00 patv
* Fixed pointer problems affecting SDA
*
* Rev 1.8 04 Jan 1998 23:14:36 patv
* Changed Log for strip utility
*
* Rev 1.7 03 Jan 1998 8:36:02 patv
* Converted data area to SDA format
*
* Rev 1.6 16 Jan 1997 12:46:30 patv
* pre-Release 0.92 feature additions
*
* Rev 1.5 29 May 1996 21:15:18 patv
* bug fixes for v0.91a
*
* Rev 1.4 19 Feb 1996 3:20:12 patv
* Added NLS, int2f and config.sys processing
*
* Rev 1.2 01 Sep 1995 17:48:38 patv
* First GPL release.
*
* Rev 1.1 30 Jul 1995 20:50:24 patv
* Eliminated version strings in ipl
*
* Rev 1.0 02 Jul 1995 8:04:34 patv
* Initial revision.
*/
/* $EndLog$ */
VOID pop_dmp(dmatch FAR *, struct f_node FAR *);
struct f_node FAR *
dir_open (BYTE FAR *dirname)
{
struct f_node FAR *fnp;
COUNT drive;
BYTE *p;
WORD i;
BYTE *s, *pszPath = &TempCDS.cdsCurrentPath[2];
/* Allocate an fnode if possible - error return (0) if not. */
if((fnp = get_f_node()) == (struct f_node FAR *)0)
{
return (struct f_node FAR *)NULL;
}
/* Force the fnode into read-write mode */
fnp -> f_mode = RDWR;
/* and initialize temporary CDS */
TempCDS.cdsFlags = 0;
/* determine what drive we are using... */
dirname = adjust_far(dirname);
ParseDosName(dirname, &drive, (BYTE *)0, (BYTE *)0, (BYTE *)0);
/* If the drive was specified, drive is non-negative and */
/* corresponds to the one passed in, i.e., 0 = A, 1 = B, etc. */
/* We use that and skip the "D:" part of the string. */
/* Otherwise, just use the default drive */
if(drive >= 0)
{
dirname += 2; /* Assume FAT style drive */
TempCDS.cdsDpb = &blk_devices[drive];
}
else
{
TempCDS.cdsDpb = &blk_devices[drive = default_drive];
}
fnp -> f_dpb = (struct dpb *)TempCDS.cdsDpb;
TempCDS.cdsCurrentPath[0] = 'A' + drive;
TempCDS.cdsCurrentPath[1] = ':';
TempCDS.cdsJoinOffset = 2;
if (drive >= nblkdev)
{
release_f_node(fnp);
return NULL;
}
/* Generate full path name */
ParseDosPath(dirname,
(COUNT *)0, pszPath, (BYTE *)TempCDS.cdsDpb -> dpb_path);
/* Perform all directory common handling after all special */
/* handling has been performed. */
++TempCDS.cdsDpb -> dpb_count;
if(media_check((struct dpb *)TempCDS.cdsDpb) < 0)
{
--TempCDS.cdsDpb -> dpb_count;
release_f_node(fnp);
return (struct f_node FAR *)0;
}
fnp -> f_diroff = 0l;
fnp -> f_flags.f_dmod = FALSE; /* a brand new fnode */
fnp -> f_flags.f_dnew = TRUE;
fnp -> f_dsize = DIRENT_SIZE * TempCDS.cdsDpb -> dpb_dirents;
/* Walk the directory tree to find the starting cluster */
/* */
/* Set the root flags since we always start from the root */
fnp -> f_flags.f_droot = TRUE;
for(p = pszPath; *p != '\0'; )
{
/* skip all path seperators */
while(*p == '\\')
++p;
/* don't continue if we're at the end */
if(*p == '\0')
break;
/* Convert the name into an absolute name for */
/* comparison... */
/* first the file name with trailing spaces... */
for(i = 0; i < FNAME_SIZE; i++)
{
if(*p != '\0' && *p != '.' && *p != '/' && *p != '\\')
TempBuffer[i] = *p++;
else
break;
}
for( ; i < FNAME_SIZE; i++)
TempBuffer[i] = ' ';
/* and the extension (don't forget to */
/* add trailing spaces)... */
if(*p == '.')
++p;
for(i = 0; i < FEXT_SIZE; i++)
{
if(*p != '\0' && *p != '.' && *p != '/' && *p != '\\')
TempBuffer[i+FNAME_SIZE] = *p++;
else
break;
}
for( ; i < FEXT_SIZE; i++)
TempBuffer[i+FNAME_SIZE] = ' ';
/* Now search through the directory to */
/* find the entry... */
i = FALSE;
upMem((BYTE FAR *)TempBuffer, FNAME_SIZE+FEXT_SIZE);
while(dir_read(fnp) == DIRENT_SIZE)
{
if(fnp -> f_dir.dir_name[0] != '\0' && fnp -> f_dir.dir_name[0] != DELETED)
{
if(fcmp((BYTE FAR *)TempBuffer, (BYTE FAR *)fnp -> f_dir.dir_name, FNAME_SIZE+FEXT_SIZE))
{
i = TRUE;
break;
}
}
}
if(!i || !(fnp -> f_dir.dir_attrib & D_DIR))
{
--TempCDS.cdsDpb -> dpb_count;
release_f_node(fnp);
return (struct f_node FAR *)0;
}
else
{
/* make certain we've moved off */
/* root */
fnp -> f_flags.f_droot = FALSE;
fnp -> f_flags.f_ddir = TRUE;
/* set up for file read/write */
fnp -> f_offset = 0l;
fnp -> f_highwater = 0l;
fnp -> f_cluster = fnp -> f_dir.dir_start;
fnp -> f_dirstart = fnp -> f_dir.dir_start;
/* reset the directory flags */
fnp -> f_diroff = 0l;
fnp -> f_flags.f_dmod = FALSE;
fnp -> f_flags.f_dnew = TRUE;
fnp -> f_dsize = DIRENT_SIZE * TempCDS.cdsDpb -> dpb_dirents;
}
}
return fnp;
}
COUNT
dir_read (REG struct f_node FAR *fnp)
{
REG i, j;
struct buffer FAR *bp;
/* 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)
fnp -> f_flags.f_dnew = FALSE;
else
fnp -> f_diroff += DIRENT_SIZE;
/* 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, */
/* but only for root directories */
if(!(fnp -> f_flags.f_droot)
&& fnp -> f_diroff >= fnp -> f_dsize)
{
fnp -> f_diroff -= DIRENT_SIZE;
return 0;
}
else
{
if(fnp -> f_flags.f_droot)
{
if((fnp -> f_diroff / fnp -> f_dpb -> dpb_secsize
+ fnp -> f_dpb -> dpb_dirstrt)
>= fnp -> f_dpb -> dpb_data)
{
fnp -> f_flags.f_dfull = TRUE;
return 0;
}
bp = getblock((LONG)(fnp -> f_diroff / fnp -> f_dpb -> dpb_secsize
+ fnp -> f_dpb -> dpb_dirstrt),
fnp -> f_dpb -> dpb_unit);
bp -> b_flag &= ~(BFR_DATA | BFR_FAT);
bp -> b_flag |= BFR_DIR;
}
else
{
REG UWORD secsize = fnp -> f_dpb -> dpb_secsize;
/* Do a "seek" to the directory position */
fnp -> f_offset = fnp -> f_diroff;
/* Search through the FAT to find the block */
/* that this entry is in. */
if(map_cluster(fnp, XFR_READ) != SUCCESS)
{
fnp -> f_flags.f_dfull = TRUE;
return 0;
}
/* If the returned cluster is FREE, return zero */
/* bytes read. */
if(fnp -> f_cluster == FREE)
return 0;
/* If the returned cluster is LAST_CLUSTER or */
/* LONG_LAST_CLUSTER, return zero bytes read */
/* and set the directory as full. */
if(last_link(fnp))
{
fnp -> f_diroff -= DIRENT_SIZE;
fnp -> f_flags.f_dfull = TRUE;
return 0;
}
/* Compute the block within the cluster and the */
/* offset within the block. */
fnp -> f_sector =
(fnp -> f_offset / secsize)
& fnp -> f_dpb -> dpb_clsmask;
fnp -> f_boff = fnp -> f_offset % secsize;
/* Get the block we need from cache */
bp = getblock(
(LONG)clus2phys(fnp -> f_cluster,
fnp -> f_dpb -> dpb_clssize,
fnp -> f_dpb -> dpb_data)
+ fnp -> f_sector,
fnp -> f_dpb -> dpb_unit);
bp -> b_flag &= ~(BFR_DATA | BFR_FAT);
bp -> b_flag |= BFR_DIR;
}
/* Now that we have the block for our entry, get the */
/* directory entry. */
if(bp != NULL)
getdirent((BYTE FAR *)&bp -> b_buffer[fnp -> f_diroff % fnp -> f_dpb -> dpb_secsize],
(struct dirent FAR *)&fnp -> f_dir);
else
{
fnp -> f_flags.f_dfull = TRUE;
return 0;
}
/* Update the fnode's directory info */
fnp -> f_flags.f_dfull = FALSE;
fnp -> f_flags.f_dmod = FALSE;
/* and for efficiency, stop when we hit the first */
/* unused entry. */
if(fnp -> f_dir.dir_name[0] == '\0')
return 0;
else
return DIRENT_SIZE;
}
}
#ifndef IPL
COUNT
dir_write (REG struct f_node FAR *fnp)
{
struct buffer FAR *bp;
/* Update the entry if it was modified by a write or create... */
if(fnp -> f_flags.f_dmod)
{
/* Root is a consecutive set of blocks, so handling is */
/* simple. */
if(fnp -> f_flags.f_droot)
{
bp =
getblock(
(LONG)(fnp -> f_diroff / fnp -> f_dpb -> dpb_secsize
+ fnp -> f_dpb -> dpb_dirstrt),
fnp -> f_dpb -> dpb_unit);
bp -> b_flag &= ~(BFR_DATA | BFR_FAT);
bp -> b_flag |= BFR_DIR;
}
/* All other directories are just files. The only */
/* special handling is resetting the offset so that we */
/* can continually update the same directory entry. */
else
{
REG UWORD secsize = fnp -> f_dpb -> dpb_secsize;
/* Do a "seek" to the directory position */
/* and convert the fnode to a directory fnode. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -