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