Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 exptools 1/6/84; site ihu1h.UUCP Path: utzoo!watmath!clyde!burl!ulysses!mhuxl!ihnp4!ihu1h!steffen From: steffen@ihu1h.UUCP (Joe Steffen) Newsgroups: net.wanted,att.wanted Subject: Re: directory functions Message-ID: <292@ihu1h.UUCP> Date: Fri, 10-Aug-84 17:27:06 EDT Article-I.D.: ihu1h.292 Posted: Fri Aug 10 17:27:06 1984 Date-Received: Sat, 11-Aug-84 01:08:36 EDT References: <212@wnuxb.UUCP> Organization: AT&T Bell Labs, Naperville, IL Lines: 169 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#endif #define statdir(file, statp) fstat(file->dd_fd, statp) #else #ifndef DIRSIZ #include #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 /* used by stat.h */ #include /* stat */ #include /* direct */ #include /* ROOTINO */ #include /* 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