Path: utzoo!censor!geac!jtsv16!uunet!tut.cis.ohio-state.edu!mailrus!ames!bionet!sdsu!csun!csuna!abcscnge From: abcscnge@csuna.csun.edu (Scott "The Pseudo-Hacker" Neugroschl) Newsgroups: comp.unix.questions Subject: Curdir(3X) repost -- this time with comments! Message-ID: <2124@csuna.csun.edu> Date: 10 Aug 89 02:06:18 GMT Reply-To: abcscnge@csuna.csun.edu (Scott Neugroschl) Distribution: usa Organization: California State University, Northridge Lines: 304 If you aren't interested in curdir, hit 'n' now. It has been brought to my attention that I posted my own quickly hacked version of curdir, and that it had no comments on what I was doing. This message is a repost. The functions are now documented. Thank you all for not flaming the uncommented code. ---- cut here -- /* ** if your system does not support the directory(3X) functions, i.e. no **, then define _NO_DIRENT_H_ at the top of the file. */ #include #include #include #ifndef _NO_DIRENT_H_ #include #else /* dirent.h is not present. Dummy up the defs in dirent.h */ #include typedef struct { int fd; /* file descriptor */ off_t offset; /* offset in file */ } DIR; struct dirent { /* stolen from directory(3X) in the Sys V manual */ long d_ino; off_t d_off; unsigned short d_reclen; char d_name[DIRSIZ+2]; }; /* declarations found in dirent.h */ static DIR *opendir(); static struct dirent *readdir(); static long telldir(); static void seekdir(); static int closedir(); #define rewinddir(dirp) seekdir(dirp,0L); #endif /* ** curdir() -- return the current directory ** ** INPUTS: NONE ** ** OUTPUTS: str -- string containing the current directory ** ** RETURNS: 0 if successful ** -1 if error */ curdir(str) char str[]; { static char tmpstr[BUFSIZ]; /* work space */ static char openpath[BUFSIZ+BUFSIZ]; /* more work space */ static char tmpnam[BUFSIZ+BUFSIZ]; /* yet more work space */ struct stat buf, rootbuf, tmpstat; DIR *dirp; /* current directory */ struct dirent *dp; /* current dir. entry */ int l; /* length of dir. ent */ /* get the root inode and device information */ if (stat("/",&rootbuf) == -1) return(-1); /* get the information for the current directory */ if (stat(".",&buf) == -1) return(-1); /* there is no path yet! */ openpath[0] = tmpstr[0] = '\0'; /* start by looking at parent directory */ strcpy(openpath,".."); /* while the parent isn't the root directory, loop */ while (buf.st_dev != rootbuf.st_dev || buf.st_ino != rootbuf.st_ino) { /* open the parent to search for the current directory */ if ((dirp = opendir(openpath)) == NULL) return(-1); /* read the parent directory */ while ((dp = readdir(dirp)) != NULL) { /* build the file to stat */ sprintf(tmpnam,"%s/%s",openpath,dp->d_name); /* stat the entry */ if (stat(tmpnam,&tmpstat) == -1) { /* couldn't stat! */ closedir(dirp); return(-1); } /* is the entry the same as the current one? */ if (tmpstat.st_dev == buf.st_dev && tmpstat.st_ino == buf.st_ino) break; } /* either we've found the current directory entry, or */ /* something is horribly wrong -- (readdir return NULL */ /* on EOF */ closedir(dirp); /* the current entry was not found!!!! */ if (dp == NULL) return(-1); /* build up the path to the current directory */ append(dp->d_name,tmpstr); /* the parent directory is now the current directory */ if (stat(openpath,&buf) == -1) return(-1); /* move up one level */ sprintf(openpath,"../%s",openpath); } /* prepend a leading "/" */ strcpy(str,"/"); strcat(str,tmpstr); /* check for "/path.../" */ if (str[l = (strlen(str) - 1)] == '/') str[l] = '\0'; /* strip trailing "/" */ /* successful return */ return(0); } /* append -- append "tail" to "head", and return the result in tail ** ** INPUTS: head -- leading path part ** tail -- trailing path part ** ** OUTPUTS: tail -- "head/tail" ** ** RETURNS: NONE ** */ static append(head,tail) char *head, *tail; { char tmpbuf[BUFSIZ+BUFSIZ]; strcpy(tmpbuf,head); strcat(tmpbuf,"/"); strcat(tmpbuf,tail); strcpy(tail,tmpbuf); } #ifdef _NO_DIRENT_H /* ** routines to simulate directory(3X) ** */ /* ** opendir -- open a directory ** ** INPUTS: name -- name of directory to open ** ** OUTPUTS: NONE ** ** RETURNS: pointer to DIR structure */ static DIR *opendir(name) int name; { char *malloc(); DIR *dp; struct stat buf; /* no file, or not a directory */ if (stat(name,&buf) == -1 || (buf.st_mode & S_IFMT) != S_IFDIR) return(NULL); /* no memory? */ if ((dp = (DIR *)malloc(sizeof(DIR))) == NULL) return(NULL); /* can't open? */ if ((dp->fd = open(name,0)) == -1) { free(dp); return(NULL); } /* at start of directory */ dp->offset = (off_t)0; return(dp); } /* ** readdir() -- read a directory entry ** ** INPUTS: dirp -- pointer to current DIR ** ** OUTPUTS: NONE ** ** RETURNS: pointer to struct dirent describing current directory entry ** NULL on EOF or error ** ** NOTES: RETURN VALUE POINTS TO STATIC DATA!!!!! ** */ static struct dirent *readdir(dirp) register DIR *dirp; { static struct dirent dp; struct direct dir; /* read the current directory entry */ if (read(dirp->fd,&dir,sizeof(dir)) != sizeof(dir)) return(NULL); /* build a dirent structure */ dp.d_ino = (long) dir.d_ino; dp.d_off = dirp->offset; dirp->offset += sizeof(dir); dp.d_reclen = sizeof(dir); strncpy(dp.d_name,dir.d_name,DIRSIZ); dp.d_name[DIRSIZ] = '\0'; /* return the dirent */ return(&dp); } /* ** telldir() -- return the current offset in the directory ** ** INPUTS: dp -- pointer to the DIR to examine ** ** OUTPUTS: NONE ** ** RETURNS: offset in the specified DIR ** */ static long telldir(dp) register DIR *dp; { return((long)dp->offset); } /* ** seekdir() -- seek to a specified offset in the directory ** ** INPUTS: dp -- pointer to the DIR to see k on ** offset -- offset to seek to ** ** OUTPUTS: NONE ** ** RETURNS: NONE */ static void seekdir(dp,offset) register DIR *dp; register long offset; { long lseek(); dp->offset = (off_t)lseek(dp->fd,offset,0); } /* ** closedir() -- close a DIR ** ** INPUTS: dp -- DIR to close ** ** OUTPUTS: NONE ** ** RETURNS: NONE */ static int closedir(dp) register DIR *dp; { /* close the directory file descriptor */ close(dp->fd); /* free up the allocated memory */ free(dp); return(0); } #endif --- cut here --- Scott -- Scott "The Pseudo-Hacker" Neugroschl UUCP: ...!sm.unisys.com!csun!csuna.csun.edu!abcscnge -- Beat me, Whip me, make me code in Ada -- Disclaimers? We don't need no stinking disclaimers!!!