📄 usrfslib.c
字号:
*/STATUS copy ( const char *in, /* name of file to read (if NULL assume stdin) */ const char *out /* name of file to write (if NULL assume stdout) */ ) { int inFd = ERROR; int outFd = ERROR; int status; struct stat fileStat; /* structure to fill with data */ struct utimbuf fileTime; /* open input file */ inFd = in ? open (in, O_RDONLY, 0) : STD_IN; if (inFd == ERROR) { printErr ("Can't open input file \"%s\" errno = %p\n", in, (void *)errno ); return (ERROR); } /* Is this a directory or a file, can't write to a directory! */ if (nameIsDir(out)) { errnoSet(S_ioLib_CANT_OVERWRITE_DIR); close(inFd); return(ERROR); } /* creat output file */ outFd = out ? creat (out, O_WRONLY) : STD_OUT; if (outFd == ERROR) { printErr ("Can't write to \"%s\", errno %p\n", out, (void *)errno); if (in) close( inFd ); return (ERROR); } /* copy data */ status = copyStreams (inFd, outFd); ioctl (inFd, FIOFSTATGET, (int) &fileStat); fileTime.actime = fileStat.st_atime; fileTime.modtime = fileStat.st_mtime; ioctl (outFd, FIOTIMESET, (int) &fileTime); if (in) close (inFd); /* close could cause buffers flushing */ if (out && close (outFd) == ERROR) status = ERROR; return (status); }/********************************************************************************* chkdsk - perform consistency checking on a MS-DOS file system** This function invokes the integral consistency checking built* into the dosFsLib file system, via FIOCHKDSK ioctl.* During the test, the file system will be blocked from application code* access, and will emit messages describing any inconsistencies found on* the disk, as well as some statistics, depending on the value of the* <verbose> argument.* Depending the value of <repairLevel>, the inconsistencies will be* repaired, and changes written to disk.** These are the values for <repairLevel>:* .iP 0* Same as DOS_CHK_ONLY (1)* .IP "DOS_CHK_ONLY (1)"* Only report errors, do not modify disk.* .IP "DOS_CHK_REPAIR (2)"* Repair any errors found.** These are the values for <verbose>:* .iP 0* similar to DOS_CHK_VERB_1* .iP "DOS_CHK_VERB_SILENT (0xff00)"* Do not emit any messages, except errors encountered.* .iP "DOS_CHK_VERB_1 (0x0100)"* Display some volume statistics when done testing, as well* as errors encountered during the test.* .iP "DOS_CHK_VERB_2 (0x0200)"* In addition to the above option, display path of every file, while it* is being checked. This option may significantly slow down* the test process.** Note that the consistency check procedure will* .I unmount* the file system, meaning the all currently open file descriptors will* be deemed unusable.** RETURNS: OK or ERROR if device can not be checked or could not be repaired.**/STATUS chkdsk ( const char * pDevName, /* device name */ u_int repairLevel, /* how to fix errors */ u_int verbose /* verbosity level */ ) { int fd = open (pDevName, O_RDONLY, 0); STATUS retStat; if (fd == ERROR) { perror (pDevName); return ERROR; } repairLevel &= 0x0f; if ((verbose & 0xff00) != 0) verbose &= 0xff00; else if ((verbose & 0xff) != 0) verbose <<= 8; else /* default is 1 */ verbose = 0x0100; retStat = ioctl (fd, FIOCHKDSK, repairLevel | verbose); close (fd); return retStat; } /* chkDsk() *//********************************************************************************* dirListPattern - match file name pattern with an actual file name** <pat> is a pattern consisting with '?' and '*' wildcard characters,* which is matched against the <name> filename, and TRUE is returned* if they match, or FALSE if do not match. Both arguments must be* null terminated strings.* The pattern matching is case insensitive.** NOTE: we're using EOS as integral part of the pattern and name.*/LOCAL BOOL dirListPattern ( char * pat, char * name ) { FAST char * pPat; FAST char * pNext; const char anyOne = '?'; const char anyMany = '*'; pPat = pat ; for (pNext = name ; * pNext != EOS ; pNext ++) { /* DEBUG- logMsg("pattern %s, name %s\n", pPat, pNext, 0,0,0,0);*/ if (*pPat == anyOne) { pPat ++ ; } else if (*pPat == anyMany) { if (pNext[0] == '.') /* '*' dont match . .. and .xxx */ return FALSE ; if (toupper(pPat[1]) == toupper(pNext[1])) pPat ++ ; else if (toupper(pPat[1]) == toupper(pNext[0])) pPat += 2 ; else continue ; } else if (toupper(*pPat) != toupper(*pNext)) { return FALSE ; } else { pPat ++ ; } } /* loop is done, let's see if there is anything left */ if ((*pPat == EOS) || (pPat[0] == anyMany && pPat[1] == EOS)) return TRUE ; else return FALSE ; }/********************************************************************************* dirListEnt - list one file or directory** List one particular file or directory entry.** NOMANUAL*/LOCAL STATUS dirListEnt ( int fd, /* file descriptor for output */ char * fileName, /* file name */ struct stat * fileStat, /* stat() structure */ char * prefix, /* prefix for short output */ BOOL doLong /* do Long listing format */ ) { time_t now; /* current clock */ struct tm nowDate; /* current date & time */ struct tm fileDate; /* file date/time (long listing) */ const char *monthNames[] = {"???", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; char fType, modbits[10] ; char suffix = ' '; /* print '/' after directory name */ if(doLong) { /* Break down file modified time */ time( &now ); localtime_r (&now, &nowDate); localtime_r (&fileStat->st_mtime, &fileDate); if (fileStat->st_attrib & DOS_ATTR_RDONLY) fileStat->st_mode &= ~(S_IWUSR|S_IWGRP|S_IWOTH); if (S_ISDIR (fileStat->st_mode)) { fType = 'd' ; suffix = '/'; } else if (S_ISREG (fileStat->st_mode)) fType = '-' ; else fType = '?' ; strcpy( modbits, "---------" ); modbits[0] = (fileStat->st_mode & S_IRUSR)? 'r':'-'; modbits[1] = (fileStat->st_mode & S_IWUSR)? 'w':'-'; modbits[2] = (fileStat->st_mode & S_IXUSR)? 'x':'-'; modbits[3] = (fileStat->st_mode & S_IRGRP)? 'r':'-'; modbits[4] = (fileStat->st_mode & S_IWGRP)? 'w':'-'; modbits[5] = (fileStat->st_mode & S_IXGRP)? 'x':'-'; modbits[6] = (fileStat->st_mode & S_IROTH)? 'r':'-'; modbits[7] = (fileStat->st_mode & S_IWOTH)? 'w':'-'; modbits[8] = (fileStat->st_mode & S_IXOTH)? 'x':'-'; if (fileStat->st_attrib & DOS_ATTR_ARCHIVE) modbits[6] = 'A'; if(fileStat->st_attrib & DOS_ATTR_SYSTEM) modbits[7] = 'S'; if(fileStat->st_attrib & DOS_ATTR_HIDDEN) modbits[8] = 'H'; modbits[9] = EOS ; /* print file mode */ fdprintf(fd, "%c%9s", fType, modbits); /* fake links, user and group fields */ fdprintf(fd, " %2d %-7d %-7d ", fileStat->st_nlink, fileStat->st_uid, fileStat->st_gid ); /* print file size - XXX: add 64 bit file size support */ fdprintf(fd, " %9lu ", fileStat->st_size ); /* print date */ if (fileDate.tm_year == nowDate.tm_year) { fdprintf(fd, "%s %2d %02d:%02d ", monthNames [fileDate.tm_mon + 1],/* month */ fileDate.tm_mday, /* day of month */ fileDate.tm_hour, /* hour */ fileDate.tm_min /* minute */ ); } else { fdprintf(fd, "%s %2d %04d ", monthNames [fileDate.tm_mon + 1],/* month */ fileDate.tm_mday, /* day of month */ fileDate.tm_year+1900 /* year */ ); } } /* if doLong */ else { /* short listing */ if (strcmp(prefix , ".") == 0 || prefix[0] == EOS) /* dint print "." prefix */ ; else if (prefix != NULL && prefix [ strlen(prefix) -1 ] != '/') fdprintf(fd, "%s/", prefix); else if (prefix != NULL) fdprintf(fd, prefix); } /* last, print file name */ if (fdprintf(fd, "%s%c\n", fileName, suffix ) == ERROR) return ERROR; return OK ; }/********************************************************************************* dirList - list contents of a directory (multi-purpose)** This command is similar to UNIX ls. It lists the contents of a directory* in one of two formats. If <doLong> is FALSE, only the names of the files* (or subdirectories) in the specified directory are displayed. If <doLong>* is TRUE, then the file name, size, date, and time are displayed.* If <doTree> flag is TRUE, then each subdirectory encountered* will be listed as well (i.e. the listing will be recursive).** The <dirName> parameter specifies the directory to be listed.* If <dirName> is omitted or NULL, the current working directory will be* listed. <dirName> may contain wildcard characters to list some* of the directory's contents.** LIMITATIONS* .iP -* With dosFsLib file systems, MS-DOS volume label entries are not reported.* .iP -* Although an output format very similar to UNIX "ls" is employed,* some information items have no particular meaning on some* file systems.* .iP -* Some file systems which do not support the POSIX compliant dirLib()* interface, can not support the <doLong> and <doTree> options.** RETURNS: OK or ERROR.** SEE ALSO: dirLib, dosFsLib, ls(), ll(), lsr(), llr()*/STATUS dirList ( int fd, /* file descriptor to write on */ char * dirName, /* name of the directory to be listed */ BOOL doLong, /* if TRUE, do long listing */ BOOL doTree /* if TRUE, recurse into subdirs */ ) { FAST STATUS status; /* return status */ FAST DIR *pDir; /* ptr to directory descriptor */ FAST struct dirent *pDirEnt; /* ptr to dirent */ struct stat fileStat; /* file status info (long listing) */ char *pPattern; /* wildcard pattern */ char fileName [MAX_FILENAME_LENGTH]; /* buffer for building file name */ /* If no directory name specified, use "." */ if (dirName == NULL) dirName = "."; /* try to do a netDrv listing first, hacky way to know its a local FS */ if (_func_netLsByName != NULL) { if ((*_func_netLsByName) (dirName) == OK) return (OK); else if (errno != S_netDrv_UNKNOWN_REQUEST) return (ERROR); } pDir = NULL ; pPattern = NULL ; /* Open dir */ pDir = opendir (dirName) ; /* could not opendir: last component may be a wildcard pattern */ if (pDir == NULL) { pPattern = rindex(dirName, '/'); if ( pPattern != NULL && pPattern != dirName && dirNameWildcard(pPattern)) { /* dir and pattern e.g. dir1/a*.c */ *pPattern++ = EOS ; pDir = opendir (dirName) ; } else if (dirNameWildcard( dirName )) { /* just pattern e.g. *.c or abc.? */ pPattern = dirName ; dirName = "." ; pDir = opendir (dirName) ; } } /* count not opendir: no can do ! */ if (pDir == NULL) goto _nodir ; status = OK; /* print directory name as header */ if (dirName == ".") dirName = "" ; else if (doLong) fdprintf(fd,"\nListing Directory %s:\n", dirName); do { errno = OK; pDirEnt = readdir (pDir); if (pDirEnt != NULL) { if (pPattern != NULL && dirListPattern( pPattern, pDirEnt->d_name) == FALSE) continue ; if (doLong) /* if doing long listing */ { /* Construct path/filename for stat */ usrPathCat( dirName, pDirEnt->d_name, fileName ); /* Get and print file status info */ if (stat (fileName, &fileStat) != OK) { /* stat() error, mark the file questionable and continue */ bzero( (caddr_t) &fileStat, sizeof(fileStat)); } } if (dirListEnt(fd, pDirEnt->d_name, &fileStat, dirName, doLong ) == ERROR) status = ERROR; } else /* readdir returned NULL */ { if (errno != OK) /* if real error, not dir end */ { fdprintf (fd, "error reading dir %s, errno: %x\n", dirName, errno) ; status = ERROR; } } } while (pDirEnt != NULL); /* until end of dir */ /* Close dir */ status |= closedir (pDir); if (! doTree) return (status); /* do recursion into each subdir AFTER all files and subdir are listed */ if (dirName[0] == EOS) pDir = opendir (".") ; else pDir = opendir (dirName) ; if (pDir == NULL) goto _nodir ; do { errno = OK; pDirEnt = readdir (pDir); if (pDirEnt != NULL) { if (pPattern != NULL && dirListPattern( pPattern, pDirEnt->d_name) == FALSE) continue ; /* Construct path/filename for stat */ usrPathCat( dirName, pDirEnt->d_name, fileName ); /* Get and print file status info */ if (stat (fileName, &fileStat) != OK) { /* stat() error, mark the file questionable and continue */ bzero( (caddr_t) &fileStat, sizeof(fileStat)); } /* recurse into subdir, but not "." or ".." */ if (S_ISDIR (fileStat.st_mode) && strcmp(pDirEnt->d_name,"." ) && strcmp(pDirEnt->d_name,".." )) { status = dirList( fd, fileName, doLong, doTree ); /* maybe count files ?? */ } } else /* readdir returned NULL */ { if (errno != OK) /* if real error, not dir end */ { fdprintf (fd, "error reading dir %s, errno: %x\n", dirName, errno) ; status = ERROR; } } } while (pDirEnt != NULL); /* until end of dir */ /* Close dir */ status |= closedir (pDir); return (status);_nodir: fdprintf (fd, "Can't open \"%s\".\n", dirName); return (ERROR); }/********************************************************************************* ls - generate a brief listing of a directory** This function is simply a front-end for dirList(), intended for
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -