netnews@wnuxb.UUCP (Ron Heiby) (08/10/84)
I am running on Unix System V, and find myself in need of a copy of the functions for directory manipulation (opendir, readdir, closedir, other?) and their man pages (if possible). Thanks much. -- -- ________________ | __________ | from the overlapping windows | | ksh! | | of | |__________ | | | gmacs! | | Ronald W. Heiby | | _________ | AT&T Technologies, Inc. | | |dstar! | | Lisle, IL (CU-D21) | | | | | __ ...!ihnp4!wnuxa!heiby | --| | |_/ \_____ | --------- | /\ \_ | | \/ \+++ |TTY_______5620| / \ ---------------- (red) \___/
steffen@ihu1h.UUCP (Joe Steffen) (08/11/84)
I just ported 4 programs that read directories to BSD 4.2, so I recoded them to use the directory functions and then #include a file containing --------- #ifdef BSD4_2 #ifndef MAXNAMLEN #include <sys/dir.h> #endif #define statdir(file, statp) fstat(file->dd_fd, statp) #else #ifndef DIRSIZ #include <sys/dir.h> #endif #define MAXNAMLEN DIRSIZ #define DIR FILE #define opendir(name) fopen(name, "r") #define closedir(file) fclose(file) #define rewinddir(file) rewind(file) #define statdir(file, statp) fstat(fileno(file), statp) #define readdir(file) (struct direct *) \ (fread(entrybuf, (int) sizeof(struct direct), 1, file) == 1 ? \ entrybuf : NULL) /* allow for a terminating null on the name */ /* note: the last structure field must be the name */ static char entrybuf[sizeof(struct direct) + 1]; #endif --------- statdir() below is not a BSD routine but I found it useful when recoding fstat() calls on an open directory file descriptor. MAXNAMLEN replaces the use of DIRSIZ, which is a macro in BSD 4.2. The macros are better than functions because you don't lose any speed, which is important in a routine that figures out the current working directory. I have such a routine that is faster than getcwd(3), curdir() in -lPW, and even the getwd() posted recently to the net. There is no noticable pause when starting a program that calls this routine. For those interested here it is: --------- #ifndef BSD4_2 /* * getwd(dir) * * Get the full pathname of the current directory. * * returns: a pointer to dir on success. * NULL on failure. * * Current directory upon return from getwd: * * success: same as on entry * failure: If a failure is noted during processing getwd * backs out of it's traversal and restores the * current directory to what it was upon entry. * Of course there are pathological corruptions * to the file system which can totally confuse * getwd. * */ #include <sys/types.h> /* used by stat.h */ #include <sys/stat.h> /* stat */ #include <sys/dir.h> /* direct */ #include <sys/param.h> /* ROOTINO */ #include <stdio.h> /* NULL */ #include "ndir.h" /* directory access macros */ #define YES 1 #define NO 0 extern char *strcat(), *strcpy(), *strncpy(); char * getwd(dir) register char *dir; /* destination buffer for name so far */ { register DIR *dirfile; /* directory file descriptor */ char namebuf[256+1]; /* buffer for recursivly building path */ char cofp[MAXNAMLEN + 5]; /* child of parent name */ char *child; /* child name */ struct stat d_sb; /* current directory status */ struct stat dd_sb; /* parent directory status */ struct stat tmp_sb; /* temporary stat buffer */ int atmount = NO; /* at root of a mounted file system */ struct direct *p; if ((dirfile = opendir("..")) == NULL) return(NULL); if (stat(".", &d_sb) < 0 || statdir(dirfile, &dd_sb) < 0) { (void) closedir(dirfile); return(NULL); } /* * Determine if at a mount point or at the root of the root * file system. */ if (d_sb.st_ino == ROOTINO) { atmount = YES; if ((d_sb.st_ino == dd_sb.st_ino) && (d_sb.st_dev == dd_sb.st_dev)) { (void) strcpy(dir, "/"); /* start out right */ (void) closedir(dirfile); return(dir); /* start to unwind */ } } /* find the name of "." in ".." */ (void) strcpy(cofp, "../"); child = cofp + 3; for (;;) { if ((p = readdir(dirfile)) == NULL) { (void) closedir(dirfile); return(NULL); } if (p->d_ino == 0) continue; if (p->d_ino == d_sb.st_ino || atmount == YES) { (void) strcpy(child, p->d_name); /* * Must stat all the files in the parent * directory if the current directory is a mount * point because stat returns a different inode * number than is in the parent's directory. */ if (stat(cofp, &tmp_sb) < 0) { (void) closedir(dirfile); return(NULL); } if ((tmp_sb.st_ino == d_sb.st_ino) && (tmp_sb.st_dev == d_sb.st_dev)) break; /* found it */ } } (void) closedir(dirfile); if (chdir("..") < 0) return(NULL); /* namebuf used as destination for invoking child */ if (getwd(namebuf) == NULL) { /* failure - backout by changing to child directory */ (void) chdir(child); return(NULL); } else { /* * As the tail recursion unwinds add the current * directoriy's name to the end of 'namebuf', * and copy 'namebuf' to 'dir', while * descending the tree to the directory of * invocation. */ (void) strcpy(dir, namebuf); if (*(namebuf + strlen(namebuf) - 1) != '/') { /* previous call didn't find root */ (void) strcat(dir, "/"); } (void) strcat(dir, child); /* return to directory of invocation */ (void) chdir(child); return(dir); } } #endif -- Joe Steffen, AT&T Bell Labs, Naperville, IL, (312) 979-5381