📄 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 "portab.h"#include "globals.h"#ifdef VERSION_STRINGSstatic BYTE *fatdirRcsId = "$Id: fatdir.c,v 1.47 2004/05/23 18:28:18 bartoldeman Exp $";#endif/* Description. * Initialize a fnode so that it will point to the directory with * dirstart starting cluster; in case of passing dirstart == 0 * fnode will point to the start of a root directory */VOID dir_init_fnode(f_node_ptr fnp, CLUSTER dirstart){ /* reset the directory flags */ fnp->f_flags = F_DDIR; fnp->f_diroff = 0; fnp->f_offset = 0l; fnp->f_cluster_offset = 0; /* root directory */#ifdef WITHFAT32 if (dirstart == 0) if (ISFAT32(fnp->f_dpb)) dirstart = fnp->f_dpb->dpb_xrootclst;#endif fnp->f_cluster = fnp->f_dirstart = dirstart;}f_node_ptr dir_open(register const char *dirname){ f_node_ptr fnp; int i; char fcbname[FNAME_SIZE + FEXT_SIZE]; /* Allocate an fnode if possible - error return (0) if not. */ if ((fnp = get_f_node()) == (f_node_ptr) 0) { return (f_node_ptr) 0; } /* Force the fnode into read-write mode */ fnp->f_mode = RDWR; /* determine what drive and dpb we are using... */ fnp->f_dpb = get_dpb(dirname[0]-'A'); /* Perform all directory common handling after all special */ /* handling has been performed. */ if (media_check(fnp->f_dpb) < 0) { release_f_node(fnp); return (f_node_ptr) 0; } /* Walk the directory tree to find the starting cluster */ /* */ /* Start from the root directory (dirstart = 0) */ /* The CDS's cdsStartCls may be used to shorten the search beginning at the CWD, see mapPath() and CDS.H in order to enable this behaviour there. -- 2001/09/04 ska*/ dir_init_fnode(fnp, 0); dirname += 2; /* Assume FAT style drive */ while(*dirname != '\0') { /* skip all path seperators */ while (*dirname == '\\') ++dirname; /* don't continue if we're at the end */ if (*dirname == '\0') break; /* Convert the name into an absolute name for */ /* comparison... */ memset(fcbname, ' ', FNAME_SIZE + FEXT_SIZE); for (i = 0; i < FNAME_SIZE + FEXT_SIZE; i++, dirname++) { char c = *dirname; if (c == '.') i = FNAME_SIZE - 1; else if (c != '\0' && c != '\\') fcbname[i] = c; else break; } /* Now search through the directory to */ /* find the entry... */ i = FALSE; while (dir_read(fnp) == 1) { if (!(fnp->f_dir.dir_attrib & D_VOLID) && fcbmatch(fcbname, fnp->f_dir.dir_name)) { i = TRUE; break; } fnp->f_diroff++; } if (!i || !(fnp->f_dir.dir_attrib & D_DIR)) { release_f_node(fnp); return (f_node_ptr) 0; } else { /* make certain we've moved off */ /* root */ dir_init_fnode(fnp, getdstart(fnp->f_dpb, &fnp->f_dir)); } } return fnp;}/* swap internal and external delete flags */STATIC void swap_deleted(char *name){ if (name[0] == DELETED || name[0] == EXT_DELETED) name[0] ^= EXT_DELETED - DELETED; /* 0xe0 */}STATIC struct buffer FAR *getblock_from_off(f_node_ptr fnp, unsigned secsize){ /* Compute the block within the cluster and the */ /* offset within the block. */ unsigned sector; sector = (UBYTE)(fnp->f_offset / secsize) & fnp->f_dpb->dpb_clsmask; /* Get the block we need from cache */ return getblock(clus2phys(fnp->f_cluster, fnp->f_dpb) + sector, fnp->f_dpb->dpb_unit);}/* Description. * Read next consequitive directory entry, pointed by fnp. * If some error occures the other critical * fields aren't changed, except those used for caching. * The fnp->f_diroff always corresponds to the directory entry * which has been read. * Return value. * 1 - all OK, directory entry having been read is not empty. * 0 - Directory entry is empty. * DE_SEEK - Attempt to read beyound the end of the directory. * DE_BLKINVLD - Invalid block. * Note. Empty directory entries always resides at the end of the directory. */COUNT dir_read(REG f_node_ptr fnp){ struct buffer FAR *bp; REG UWORD secsize = fnp->f_dpb->dpb_secsize; /* can't have more than 65535 directory entries */ if (fnp->f_diroff >= 65535U) return DE_SEEK; /* 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_dirstart == 0) { if (fnp->f_diroff >= fnp->f_dpb->dpb_dirents) return DE_SEEK; 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");#endif } else { /* Do a "seek" to the directory position */ fnp->f_offset = fnp->f_diroff * (ULONG)DIRENT_SIZE; /* Search through the FAT to find the block */ /* that this entry is in. */#ifdef DISPLAY_GETBLOCK printf("dir_read: ");#endif if (map_cluster(fnp, XFR_READ) != SUCCESS) return DE_SEEK; bp = getblock_from_off(fnp, secsize);#ifdef DISPLAY_GETBLOCK printf("DIR (dir_read)\n");#endif } /* Now that we have the block for our entry, get the */ /* directory entry. */ if (bp == NULL) return DE_BLKINVLD; bp->b_flag &= ~(BFR_DATA | BFR_FAT); bp->b_flag |= BFR_DIR | BFR_VALID; getdirent((BYTE FAR *) & bp-> 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; /* and for efficiency, stop when we hit the first */ /* unused entry. */ /* either returns 1 or 0 */ return (fnp->f_dir.dir_name[0] != '\0');}/* Description. * Writes directory entry pointed by fnp to disk. In case of erroneous * situation fnode is released. * The caller should set * 1. F_DMOD flag if original directory entry was modified. * Return value. * TRUE - all OK. * FALSE - error occured (fnode is released). */#ifndef IPLBOOL dir_write(REG f_node_ptr fnp){ struct buffer FAR *bp; REG UWORD secsize = fnp->f_dpb->dpb_secsize; if (!(fnp->f_flags & F_DDIR)) return FALSE; /* 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_dirstart == 0) { bp = getblock(fnp->f_diroff / (secsize / DIRENT_SIZE) + fnp->f_dpb->dpb_dirstrt, fnp->f_dpb->dpb_unit);#ifdef DISPLAY_GETBLOCK printf("DIR (dir_write)\n");#endif } /* 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 { /* Do a "seek" to the directory position */ /* and convert the fnode to a directory fnode. */ fnp->f_offset = fnp->f_diroff * (ULONG)DIRENT_SIZE; fnp->f_cluster = fnp->f_dirstart; fnp->f_cluster_offset = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -