⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fatdir.c

📁 xdos源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************/
/*                                                              */
/*                          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 + -