opendir(), POSIX, Doug Gwyn and dirent.h
John Campbell
jdc at naucse.UUCP
Sun Jun 25 07:42:45 AEST 1989
A favorite program of mine, that works with Doug Gwyn's dirent
routines, was reposted and when built yielded the following:
RE - can't read RE
Ma - can't read Ma
with each file name truncated to two letters. It turns out that this
was due to the fact that Doug Gwyn's dirent.h file (at least my version)
refused to put a 14 character limit (or any limit) on file names. Instead
he defined the following (/usr/include/sys/dirent.h):
======start of doug's dirent.h======
/*
<sys/dirent.h> -- file system independent directory entry (SVR3)
last edit: 25-Apr-1987 D A Gwyn
prerequisite: <sys/types.h>
*/
struct dirent /* data from getdents()/readdir() */
{
long d_ino; /* inode number of entry */
off_t d_off; /* offset of disk directory entry */
unsigned short d_reclen; /* length of this record */
char d_name[1]; /* name of file */ /* non-POSIX */
};
/* The following nonportable ugliness could have been avoided by defining
DIRENTSIZ and DIRENTBASESIZ to also have (struct dirent *) arguments. */
#define DIRENTBASESIZ (((struct dirent *)0)->d_name \
- (char *)&((struct dirent *)0)->d_ino)
#define DIRENTSIZ( namlen ) ((DIRENTBASESIZ + sizeof(long) + (namlen)) \
/ sizeof(long) * sizeof(long))
/* DAG -- the following was moved from <dirent.h>, which was the wrong place */
#define MAXNAMLEN 512 /* maximum filename length */
#ifndef NAME_MAX
#define NAME_MAX (MAXNAMLEN - 1) /* DAG -- added for POSIX */
#endif
=========end of doug's dirent.h========
What this means is that memcpy (x, y, sizeof (struct dirent)) was only
copying two bytes of the name (structure alignment). Anyway, I made
patches based on DIRENTSIZ and DIRENTBASESIZ to work around this--but it
added a mess to the code and some #define DIRENTSIZ 0 lines for other unix
implementations.
My question (great, now he gets to it) is, "Is this the best way to
build a portable opendir(), readdir(), etc. package?" Handling arbitrary
length file names is always a bit more work. Also, I run on a 3b1 SYSV
(sort of) machine and I have another opendir() package by Scott Hazen
Muellyer (scott at zorch.uucp) that would have worked with the original code
since it assumes a fixed size for each directory entry (ndir.h):
======start of scott's ndir.h======
/* @(#)ndir.h 1.7 10/7/87 */
#if defined(HP9K5)
/* He should have included it instead of this, but prevent confusion */
#include <ndir.h>
#else /* other */
#ifndef DEV_BSIZE
#define DEV_BSIZE 512
#endif
#define DIRBLKSIZ DEV_BSIZE
#define MAXNAMLEN 255
struct directy {
long d_ino; /* inode number of entry */
short d_reclen; /* length of this record */
short d_namlen; /* length of string in d_name */
char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */
};
/*
* The DIRSIZ macro gives the minimum record length which will hold
* the directory entry. This requires the amount of space in struct directy
* without the d_name field, plus enough space for the name with a terminating
* null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
*/
#ifdef DIRSIZ
#undef DIRSIZ
#endif /* DIRSIZ */
#define DIRSIZ(dp) \
((sizeof (struct directy) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
/*
* Definitions for library routines operating on directories.
*/
typedef struct _dirdesc {
int dd_fd;
long dd_loc;
long dd_size;
char dd_buf[DIRBLKSIZ];
} DIR;
#ifndef NULL
#define NULL 0
#endif
extern DIR *opendir();
extern struct directy *readdir();
extern void closedir();
#define rewinddir(dirp) seekdir((dirp), (long)0)
#endif /* other */
======end of scott's ndir.h======
What is the consensus? Which way should the package work? I know
Doug's stuff is wide spread (and good), but is there a reason to
change it's implementation? What does POSIX say?
--
John Campbell ...!arizona!naucse!jdc
CAMPBELL at NAUVAX.bitnet
unix? Sure send me a dozen, all different colors.
More information about the Comp.unix.questions
mailing list