📄 paxdir.c
字号:
/* opendir -- open a directory stream last edit: 16-Jun-1987 D A Gwyn*/#include <sys/errno.h>#include <sys/types.h>#include <sys/stat.h>#include "paxdir.h"#ifdef BSD_SYSV/* <sys/_dir.h> -- definitions for 4.2,4.3BSD directories last edit: 25-Apr-1987 D A Gwyn A directory consists of some number of blocks of DIRBLKSIZ bytes each, where DIRBLKSIZ is chosen such that it can be transferred to disk in a single atomic operation (e.g., 512 bytes on most machines). Each DIRBLKSIZ-byte block contains some number of directory entry structures, which are of variable length. Each directory entry has the beginning of a (struct direct) at the front of it, containing its filesystem-unique ident number, the length of the entry, and the length of the name contained in the entry. These are followed by the NUL- terminated name padded to a (long) boundary with 0 bytes. The maximum length of a name in a directory is MAXNAMELEN. The macro DIRSIZ(dp) gives the amount of space required to represent a directory entry. Free space in a directory is represented by entries that have dp->d_reclen > DIRSIZ(dp). All DIRBLKSIZ bytes in a directory block are claimed by the directory entries; this usually results in the last entry in a directory having a large dp->d_reclen. When entries are deleted from a directory, the space is returned to the previous entry in the same directory block by increasing its dp->d_reclen. If the first entry of a directory block is free, then its dp->d_fileno is set to 0; entries other than the first in a directory do not normally have dp->d_fileno set to 0. prerequisite: <sys/types.h>*/#if defined(accel) || defined(sun) || defined(vax)#define DIRBLKSIZ 512 /* size of directory block */#else#ifdef alliant#define DIRBLKSIZ 4096 /* size of directory block */#else#ifdef gould#define DIRBLKSIZ 1024 /* size of directory block */#else#ifdef ns32000 /* Dynix System V */#define DIRBLKSIZ 2600 /* size of directory block */#else /* be conservative; multiple blocks are okay * but fractions are not */#define DIRBLKSIZ 4096 /* size of directory block */#endif#endif#endif#endif#define MAXNAMELEN 255 /* maximum filename length *//* NOTE: not MAXNAMLEN, which has been preempted by SVR3 <dirent.h> */struct direct { /* data from read()/_getdirentries() */ unsigned long d_fileno; /* unique ident of entry */ unsigned short d_reclen; /* length of this record */ unsigned short d_namlen; /* length of string in d_name */ char d_name[MAXNAMELEN + 1]; /* NUL-terminated filename */};/* The DIRSIZ macro gives the minimum record length which will hold the directory entry. This requires the amount of space in a (struct direct) without the d_name field, plus enough space for the name with a terminating NUL character, rounded up to a (long) boundary. (Note that Berkeley didn't properly compensate for struct padding, but we nevertheless have to use the same size as the actual system.)*/#define DIRSIZ( dp ) ((sizeof(struct direct) - (MAXNAMELEN+1) \ + sizeof(long) + (dp)->d_namlen) \ / sizeof(long) * sizeof(long))#else#include <sys/dir.h>#ifdef SYSV3#undef MAXNAMLEN /* avoid conflict with SVR3 */#endif /* Good thing we don't need to use the DIRSIZ() macro! */#ifdef d_ino /* 4.3BSD/NFS using d_fileno */#undef d_ino /* (not absolutely necessary) */#else#define d_fileno d_ino /* (struct direct) member */#endif#endif#ifdef UNK#ifndef UFS#include "***** ERROR ***** UNK applies only to UFS"/* One could do something similar for getdirentries(), but I didn't bother. */#endif#include <signal.h>#endif#if defined(UFS) + defined(BFS) + defined(NFS) != 1 /* sanity check */#include "***** ERROR ***** exactly one of UFS, BFS, or NFS must be defined"#endif#ifdef UFS#define RecLen( dp ) (sizeof(struct direct)) /* fixed-length entries */#else /* BFS || NFS */#define RecLen( dp ) ((dp)->d_reclen) /* variable-length entries */#endif#ifdef NFS#ifdef BSD_SYSV#define getdirentries _getdirentries /* package hides this system call */#endifextern int getdirentries();static long dummy; /* getdirentries() needs basep */#define GetBlock( fd, buf, n ) getdirentries( fd, buf, (unsigned)n, &dummy )#else /* UFS || BFS */#ifdef BSD_SYSV#define read _read /* avoid emulation overhead */#endifextern int read();#define GetBlock( fd, buf, n ) read( fd, buf, (unsigned)n )#endif#ifdef UNKextern int _getdents(); /* actual system call */#endifextern char *strncpy();extern int fstat();extern OFFSET lseek();extern int errno;#ifndef DIRBLKSIZ#define DIRBLKSIZ 4096 /* directory file read buffer size */#endif#ifndef NULL#define NULL 0#endif#ifndef SEEK_CUR#define SEEK_CUR 1#endif#ifndef S_ISDIR /* macro to test for directory file */#define S_ISDIR( mode ) (((mode) & S_IFMT) == S_IFDIR)#endif#ifndef SEEK_CUR#define SEEK_CUR 1#endif#ifdef BSD_SYSV#define open _open /* avoid emulation overhead */#endifextern int getdents(); /* SVR3 system call, or emulation */typedef char *pointer; /* (void *) if you have it */extern void free();extern pointer malloc();extern intopen(), close(), fstat();extern int errno;extern OFFSET lseek();#ifndef SEEK_SET#define SEEK_SET 0#endiftypedef int bool; /* Boolean data type */#define false 0#define true 1#ifndef NULL#define NULL 0#endif#ifndef O_RDONLY#define O_RDONLY 0#endif#ifndef S_ISDIR /* macro to test for directory file */#define S_ISDIR( mode ) (((mode) & S_IFMT) == S_IFDIR)#endif#ifdef __STDC__DIR *opendir(char *dirname)#else DIR *opendir(dirname)char *dirname; /* name of directory */#endif{ register DIR *dirp; /* -> malloc'ed storage */ register int fd; /* file descriptor for read */ struct stat sbuf; /* result of fstat() */ if ((fd = open(dirname, O_RDONLY)) < 0) return ((DIR *)NULL); /* errno set by open() */ if (fstat(fd, &sbuf) != 0 || !S_ISDIR(sbuf.st_mode)) { close(fd); errno = ENOTDIR; return ((DIR *)NULL); /* not a directory */ } if ((dirp = (DIR *) malloc(sizeof(DIR))) == (DIR *)NULL || (dirp->dd_buf = (char *) malloc((unsigned) DIRBUF)) == (char *)NULL ) { register int serrno = errno; /* errno set to ENOMEM by sbrk() */ if (dirp != (DIR *)NULL) free((pointer) dirp); close(fd); errno = serrno; return ((DIR *)NULL); /* not enough memory */ } dirp->dd_fd = fd; dirp->dd_loc = dirp->dd_size = 0; /* refill needed */ return dirp;}/* * closedir -- close a directory stream * * last edit: 11-Nov-1988 D A Gwyn */#ifdef __STDC__int closedir(register DIR *dirp)#else int closedir(dirp)register DIR *dirp; /* stream from opendir() */#endif{ register int fd; if ( dirp == (DIR *)NULL || dirp->dd_buf == (char *)NULL ) { errno = EFAULT; return -1; /* invalid pointer */ } fd = dirp->dd_fd; /* bug fix thanks to R. Salz */ free( (pointer)dirp->dd_buf ); free( (pointer)dirp ); return close( fd );}/* readdir -- read next entry from a directory stream last edit: 25-Apr-1987 D A Gwyn*/#ifdef __STDC__struct dirent *readdir(register DIR *dirp)#else struct dirent *readdir(dirp)register DIR *dirp; /* stream from opendir() */#endif{ register struct dirent *dp; /* -> directory data */ if (dirp == (DIR *)NULL || dirp->dd_buf == (char *)NULL) { errno = EFAULT; return (struct dirent *)NULL; /* invalid pointer */ } do { if (dirp->dd_loc >= dirp->dd_size) /* empty or obsolete */ dirp->dd_loc = dirp->dd_size = 0; if (dirp->dd_size == 0 /* need to refill buffer */ && (dirp->dd_size = getdents(dirp->dd_fd, dirp->dd_buf, (unsigned) DIRBUF) ) <= 0 ) return ((struct dirent *)NULL); /* EOF or error */ dp = (struct dirent *) & dirp->dd_buf[dirp->dd_loc]; dirp->dd_loc += dp->d_reclen; } while (dp->d_ino == 0L); /* don't rely on getdents() */ return dp;}/* seekdir -- reposition a directory stream last edit: 24-May-1987 D A Gwyn An unsuccessful seekdir() will in general alter the current directory position; beware. NOTE: 4.nBSD directory compaction makes seekdir() & telldir() practically impossible to do right. Avoid using them!*/#ifdef __STDC__void seekdir(register DIR *dirp, register OFFSET loc)#else void seekdir(dirp, loc)register DIR *dirp; /* stream from opendir() */register OFFSET loc; /* position from telldir() */#endif{ register bool rewind; /* "start over when stymied" flag */ if (dirp == (DIR *)NULL || dirp->dd_buf == (char *)NULL) { errno = EFAULT; return; /* invalid pointer */ } /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -