Curdir(3X) repost -- this time with comments!
Scott "The Pseudo-Hacker" Neugroschl
abcscnge at csuna.csun.edu
Thu Aug 10 12:06:18 AEST 1989
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!!!
More information about the Comp.unix.questions
mailing list