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

📄 paxdir.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	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 + -