opendir(), POSIX, Doug Gwyn and dirent.h

Doug Gwyn gwyn at smoke.BRL.MIL
Tue Jun 27 06:08:10 AEST 1989


In article <1509 at naucse.UUCP> jdc at naucse.UUCP (John Campbell) writes:
>======start of doug's dirent.h======

Here is the current version:

/*
	<sys/dirent.h> -- file system independent directory entry (SVR3)

	last edit:	27-Oct-1988	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-ANSI */
	};

#ifdef BSD_SYSV				/* (e.g., when compiling getdents.c) */
extern struct dirent	__dirent;	/* (not actually used) */
/* The following is portable, although rather silly. */
#define	DIRENTBASESIZ		(__dirent.d_name - (char *)&__dirent.d_ino)

#else
/* The following nonportable ugliness could have been avoided by defining
   DIRENTSIZ and DIRENTBASESIZ to also have (struct dirent *) arguments.
   There shouldn't be any problem if you avoid using the DIRENTSIZ() macro. */

#define	DIRENTBASESIZ		(((struct dirent *)0)->d_name \
				- (char *)&((struct dirent *)0)->d_ino)
#endif

#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

>What this means is that memcpy (x, y, sizeof (struct dirent)) ...

It is strongly implied by the POSIX spec that readdir() "owns" the
contents of this struct; an attempt to keep it from getting overwritten
by making a copy of it is doomed, because there is no portable way to
know how big the actual allocation for the struct dirent is; IEEE 1003.1
specifically states that the character array d_name is of unspecified
size, and this was done deliberately to allow implementations such as
mine.  In some drafts we had required d_name to be a char* rather than
an array (thus the "non-POSIX" comment in the version you posted).
After Section 5.1 had gotten straightened out, taking into account my
feedback, some more comments (from Berkeley, I think) were received and
further changes were made, unfortunately with no opportunity for further
review.  (This was a generic problem with the 1003.1 balloting process.)
There are a lot of things that needed to be more clearly specified.  For
example, can a DIR be copied to make a separate but equal handle on a
directory stream?  (The answer is "no", but it's not specified in
IEEE Std 1003.1.)

The way to save a directory entry is to either copy the name string,
using strlen() to determine the proper size, or to use the (non-POSIX)
telldir() function to obtain a position for a later seekdir().  I
recommend not using telldir()/seekdir() for reasons other than their
being nonstandard.  Note that d_name is the only member of a struct
dirent that POSIX mentions; therefore it's the only part you can
portably use anyway.

>My question (great, now he gets to it) is, "Is this the best way to
>build a portable opendir(), readdir(), etc. package?"

Certainly I think so.  The only system dependency (apart from
stretching the limits of the C language) is isolated in the getdents()
function, which is either a system call (SVR3) or an emulation of one.
Thus porting the package to a previously unsupported environment
consists almost entirely of devising a working getdents() emulation.

By the way, the reason for my using DIRENTBASESIZ etc. as you see them
is that the SVR3 implementors had done so, and my package is intended
to be usable as a direct replacement for SVR3's.  The comment in the
code explains how it could be done better were SVR3 compatibility not
a requirement.  (Actually, much of the SVR3 implementation appears to
have been based on an earlier version of my package.  Very strange
feedback loops we have operating here!)



More information about the Comp.unix.questions mailing list