abcscnge@csuna.csun.edu (Scott "The Pseudo-Hacker" Neugroschl) (08/01/89)
For those people who want a curdir(3) function, but can't seem to find the library, I have one available. It uses the directory(3X) functions, but I put #ifdef'ed code in to simulate it for those without <dirent.h>. Send me E-mail if you want it; if enough people ask, I'll post. Note, I wrote it to be as portable as possible, only assumption is that if you don't have <dirent.h>, you have a SystemV type file system (16 bytes per directory entry). Scott (Send email here, or to ...!csun!litvax!abctdev!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!!!
abcscnge@csuna.csun.edu (Scott "The Pseudo-Hacker" Neugroschl) (08/07/89)
Several people have mailed and asked for the source to my curdir function, so (as it is now easier to post than reply), here it is. I apologize if this is the wrong news group, please do not flame... I am posting here because this is where I made the original comment... ---- cut here ---- /* ** if your system does not support the directory(3X) functions, i.e. no ** <dirent.h>, then define _NO_DIRENT_H_ at the top of the file. */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #ifndef _NO_DIRENT_H_ #include <dirent.h> #else #include <sys/dir.h> typedef int DIR; struct dirent { long d_ino; off_t d_off; unsigned short d_reclen; char d_name[DIRSIZ+2]; }; static DIR *opendir(); static struct dirent *readdir(); static long telldir(); static void seekdir(); static int closedir(); #define rewinddir(dirp) seekdir(dirp,0L); #endif curdir(str) char str[]; { static char tmpstr[BUFSIZ]; static char openpath[BUFSIZ+BUFSIZ]; static char tmpnam[BUFSIZ+BUFSIZ]; struct stat buf, rootbuf, tmpstat; DIR *dirp; struct dirent *dp; int l; if (stat("/",&rootbuf) == -1) return(-1); if (stat(".",&buf) == -1) return(-1); openpath[0] = tmpstr[0] = '\0'; strcpy(openpath,".."); while (buf.st_dev != rootbuf.st_dev || buf.st_ino != rootbuf.st_ino) { if ((dirp = opendir(openpath)) == NULL) return(-1); while ((dp = readdir(dirp)) != NULL) { sprintf(tmpnam,"%s/%s",openpath,dp->d_name); if (stat(tmpnam,&tmpstat) == -1) { closedir(dirp); return(-1); } if (tmpstat.st_dev == buf.st_dev && tmpstat.st_ino == buf.st_ino) break; } closedir(dirp); if (dp == NULL) return(-1); append(dp->d_name,tmpstr); if (stat(openpath,&buf) == -1) return(-1); sprintf(openpath,"../%s",openpath); } strcpy(str,"/"); strcat(str,tmpstr); if (str[l = (strlen(str) - 1)] == '/') str[l] = '\0'; return(0); } 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 static off_t curoff = ((off_t) 0); 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 = open(name,0)) == -1) { free(dp); return(NULL); } curoff = (off_t)0; return(dp); } static struct dirent *readdir(dirp) register DIR *dirp; { static struct dirent dp; struct direct dir; if (read(*dirp,&dir,sizeof(dir)) != sizeof(dir)) return(NULL); dp.d_ino = (long) dir.d_ino; dp.d_off = curoff; curoff += sizeof(dir); dp.d_reclen = sizeof(dir); strncpy(dp.d_name,dir.d_name,DIRSIZ); dp.d_name[DIRSIZ] = '\0'; return(&dp); } static long telldir(dp) register DIR *dp; { long lseek(); return((long)(curoff = (off_t) lseek(*dp,0L,1))); } static void seekdir(dp,offset) register DIR *dp; register long offset; { long lseek(); curoff = (off_t)lseek(*dp,offset,0); } static int closedir(dp) register DIR *dp; { close(*dp); free(dp); return(0); } #endif --- cut here --- -- 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!!!
abcscnge@csuna.csun.edu (Scott "The Pseudo-Hacker" Neugroschl) (08/10/89)
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 ** <dirent.h>, then define _NO_DIRENT_H_ at the top of the file. */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #ifndef _NO_DIRENT_H_ #include <dirent.h> #else /* dirent.h is not present. Dummy up the defs in dirent.h */ #include <sys/dir.h> 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!!!