[comp.lang.c] Readdir, Opendir,...

snguyen@nprdc.arpa (Son Nguyen) (12/20/88)

Does anyone know how to create these functions (readdir, opendir, seekdir,
telldir,...,rewinddir) with either TURBO-C or Microsoft C  ?
If so, can you send it a copy ?  

Thanks.

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/25/88)

In article <1198@arctic.nprdc.arpa> snguyen@nprdc.arpa (Son Nguyen) writes:
>Does anyone know how to create these functions (readdir, opendir, seekdir,
>telldir,...,rewinddir) with either TURBO-C or Microsoft C  ?
>If so, can you send it a copy ?  

These functions originated at Berkeley and helped in the transition to
the newer long-path-component filesystems, as well as more-or-less
transparent network file systems.  IEEE Std 1003.1 defines the current
standard for these functions.  I have a public-domain implementation
that I'll send you, but it's known to work only on UNIX (any flavor)
and ProDOS.  (A GS/OS generic version is in the works.)  Somebody
undoubtedly has adapted getdents() (the system-specific part of the
package) for MS-DOS, but I don't have that version.  (I would like to
receive one for unrestricted redistribution, though!)

edf@rocky2.rockefeller.edu (David MacKenzie) (12/26/88)

In article <9227@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>In article <1198@arctic.nprdc.arpa> snguyen@nprdc.arpa (Son Nguyen) writes:
>>Does anyone know how to create these functions (readdir, opendir, seekdir,
>>telldir,...,rewinddir) with either TURBO-C or Microsoft C  ?
>>If so, can you send it a copy ?  
>
>and ProDOS.  (A GS/OS generic version is in the works.)  Somebody
>undoubtedly has adapted getdents() (the system-specific part of the
>package) for MS-DOS, but I don't have that version.  (I would like to
>receive one for unrestricted redistribution, though!)

The GNU tar contains a public domain implementation of the BSD directory
functions, though I don't think it's based on getdents.

-----
David MacKenzie
Environmental Defense Fund
edf@rocky2.rockefeller.edu (...rutgers!cmcl2!rocky2!edf)

edf@rocky2.rockefeller.edu (David MacKenzie) (12/26/88)

My last message should have specified that the GNU tar contains a
public domain *MS-DOS* implementation of readdir, etc.  Matter of fact,
they're not that long, so here they are . . .

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by rocky2.rockefeller.edu!edf on Mon Dec 26 00:15:21 EST 1988
# Contents:  msd_dir.c msd_dir.h
 
echo x - msd_dir.c
sed 's/^@//' > "msd_dir.c" <<'@//E*O*F msd_dir.c//'
/*
 * @(#)msd_dir.c 1.4 87/11/06	Public Domain.
 *
 *  A public domain implementation of BSD directory routines for
 *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
 *  August 1897
 */

#include	<sys/types.h>
#include	<sys/stat.h>
#include	<sys/dir.h>
#include	<malloc.h>
#include	<string.h>
#include	<dos.h>

#ifndef	NULL
# define	NULL	0
#endif	/* NULL */

#ifndef	MAXPATHLEN
# define	MAXPATHLEN	255
#endif	/* MAXPATHLEN */

/* attribute stuff */
#define	A_RONLY		0x01
#define	A_HIDDEN	0x02
#define	A_SYSTEM	0x04
#define	A_LABEL		0x08
#define	A_DIR		0x10
#define	A_ARCHIVE	0x20

/* dos call values */
#define	DOSI_FINDF	0x4e
#define	DOSI_FINDN	0x4f
#define	DOSI_SDTA	0x1a

#define	Newisnull(a, t)		((a = (t *) malloc(sizeof(t))) == (t *) NULL)
/* #define	ATTRIBUTES		(A_DIR | A_HIDDEN | A_SYSTEM) */
#define ATTRIBUTES	(A_RONLY | A_SYSTEM | A_DIR)

/* what find first/next calls look use */
typedef struct {
	char		d_buf[21];
	char		d_attribute;
	unsigned short	d_time;
	unsigned short	d_date;
	long		d_size;
	char		d_name[13];
} Dta_buf;

static	char	*getdirent();
static	void	setdta();
static	void	free_dircontents();

static	Dta_buf		dtabuf;
static	Dta_buf		*dtapnt = &dtabuf;
static	union REGS	reg, nreg;

#if	defined(M_I86LM)
static	struct SREGS	sreg;
#endif

DIR	*
opendir(name)
	char	*name;
{
	struct	stat		statb;
	DIR			*dirp;
	char			c;
	char			*s;
	struct _dircontents	*dp;
	char			nbuf[MAXPATHLEN + 1];
	
	if (stat(name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
		return (DIR *) NULL;
	if (Newisnull(dirp, DIR))
		return (DIR *) NULL;
	if (*name && (c = name[strlen(name) - 1]) != '\\' && c != '/')
		(void) strcat(strcpy(nbuf, name), "\\*.*");
	else
		(void) strcat(strcpy(nbuf, name), "*.*");
	dirp->dd_loc = 0;
	setdta();
	dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) NULL;
	if ((s = getdirent(nbuf)) == (char *) NULL)
		return dirp;
	do {
		if (Newisnull(dp, struct _dircontents) || (dp->_d_entry =
			malloc((unsigned) (strlen(s) + 1))) == (char *) NULL)
		{
			if (dp)
				free((char *) dp);
			free_dircontents(dirp->dd_contents);
			return (DIR *) NULL;
		}
		if (dirp->dd_contents)
			dirp->dd_cp = dirp->dd_cp->_d_next = dp;
		else
			dirp->dd_contents = dirp->dd_cp = dp;
		(void) strcpy(dp->_d_entry, s);
		dp->_d_next = (struct _dircontents *) NULL;
	} while ((s = getdirent((char *) NULL)) != (char *) NULL);
	dirp->dd_cp = dirp->dd_contents;

	return dirp;
}

void
closedir(dirp)
	DIR	*dirp;
{
	free_dircontents(dirp->dd_contents);
	free((char *) dirp);
}

struct direct	*
readdir(dirp)
	DIR	*dirp;
{
	static	struct direct	dp;
	
	if (dirp->dd_cp == (struct _dircontents *) NULL)
		return (struct direct *) NULL;
	dp.d_namlen = dp.d_reclen =
		strlen(strcpy(dp.d_name, dirp->dd_cp->_d_entry));
	strlwr(dp.d_name);		/* JF */
	dp.d_ino = 0;
	dirp->dd_cp = dirp->dd_cp->_d_next;
	dirp->dd_loc++;

	return &dp;
}

void
seekdir(dirp, off)
	DIR	*dirp;
	long	off;
{
	long			i = off;
	struct _dircontents	*dp;

	if (off < 0)
		return;
	for (dp = dirp->dd_contents ; --i >= 0 && dp ; dp = dp->_d_next)
		;
	dirp->dd_loc = off - (i + 1);
	dirp->dd_cp = dp;
}

long
telldir(dirp)
	DIR	*dirp;
{
	return dirp->dd_loc;
}

static	void
free_dircontents(dp)
	struct	_dircontents	*dp;
{
	struct _dircontents	*odp;

	while (dp) {
		if (dp->_d_entry)
			free(dp->_d_entry);
		dp = (odp = dp)->_d_next;
		free((char *) odp);
	}
}

static	char	*
getdirent(dir)
	char	*dir;
{
	if (dir != (char *) NULL) {		/* get first entry */
		reg.h.ah = DOSI_FINDF;
		reg.h.cl = ATTRIBUTES;
#if	defined(M_I86LM)
		reg.x.dx = FP_OFF(dir);
		sreg.ds = FP_SEG(dir);
#else
		reg.x.dx = (unsigned) dir;
#endif
	} else {				/* get next entry */
		reg.h.ah = DOSI_FINDN;
#if	defined(M_I86LM)
		reg.x.dx = FP_OFF(dtapnt);
		sreg.ds = FP_SEG(dtapnt);
#else
		reg.x.dx = (unsigned) dtapnt;
#endif
	}
#if	defined(M_I86LM)
	intdosx(&reg, &nreg, &sreg);
#else
	intdos(&reg, &nreg);
#endif
	if (nreg.x.cflag)
		return (char *) NULL;

	return dtabuf.d_name;
}

static	void
setdta()
{
	reg.h.ah = DOSI_SDTA;
#if	defined(M_I86LM)
	reg.x.dx = FP_OFF(dtapnt);
	sreg.ds = FP_SEG(dtapnt);
	intdosx(&reg, &nreg, &sreg);
#else
	reg.x.dx = (int) dtapnt;
	intdos(&reg, &nreg);
#endif
}
@//E*O*F msd_dir.c//
chmod u=rw,g=r,o=r msd_dir.c
 
echo x - msd_dir.h
sed 's/^@//' > "msd_dir.h" <<'@//E*O*F msd_dir.h//'
/*
 * @(#)msd_dir.h 1.4 87/11/06	Public Domain.
 *
 *  A public domain implementation of BSD directory routines for
 *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
 *  August 1897
 */

#define	rewinddir(dirp)	seekdir(dirp, 0L)

#define	MAXNAMLEN	12

struct direct {
	ino_t	d_ino;			/* a bit of a farce */
	int	d_reclen;		/* more farce */
	int	d_namlen;		/* length of d_name */
	char	d_name[MAXNAMLEN + 1];		/* garentee null termination */
};

struct _dircontents {
	char	*_d_entry;
	struct _dircontents	*_d_next;
};

typedef struct _dirdesc {
	int		dd_id;	/* uniquely identify each open directory */
	long		dd_loc;	/* where we are in directory entry is this */
	struct _dircontents	*dd_contents;	/* pointer to contents of dir */
	struct _dircontents	*dd_cp;	/* pointer to current position */
} DIR;

extern	DIR		*opendir();
extern	struct direct	*readdir();
extern	void		seekdir();
extern	long		telldir();
extern	void		closedir();
@//E*O*F msd_dir.h//
chmod u=rw,g=r,o=r msd_dir.h
 
exit 0
-----
David MacKenzie
Environmental Defense Fund
edf@rocky2.rockefeller.edu (...rutgers!cmcl2!rocky2!edf)