[comp.sources.misc] v07i029: CRISP release 1.9 part 08/32

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (06/12/89)

Posting-number: Volume 7, Issue 29
Submitted-by: fox@marlow.UUCP (Paul Fox)
Archive-name: crisp1.9/part09



#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
# This is part 1 of a multipart archive                                    
# do not concatenate these parts, unpack them in order with /bin/sh        
#
#	Run the following text with /bin/sh to create:
#	  LIB.README
#	  dirlib/Makefile
#	  dirlib/INSTALL
#	  dirlib/NOTES
#	  dirlib/closedir.c
#	  dirlib/directory.3c
#	  dirlib/dirent.4
#	  dirlib/dirent.h
#	  dirlib/getdents.2
#	  dirlib/getdents.c
#	  dirlib/opendir.c
#	  dirlib/readdir.c
#	  dirlib/rewinddir.c
#	  dirlib/seekdir.c
#	  dirlib/sys._dir.h
#	  dirlib/sys.dirent.h
#	  dirlib/telldir.c
#	  dirlib/testdir.c
#	  dirlib/vmsdir.h
#	  dirlib/vmsdir.c
#	  foxlib/Makefile
#	  foxlib/chk_alloc.h
#	  foxlib/ansi.c
#	  foxlib/atol.c
#	  foxlib/bsearch.c
#	  foxlib/chk_alloc.c
#	  foxlib/dname.c
#	  foxlib/expand.c
#	  foxlib/instr.c
#	  foxlib/memcpy.c
#	  foxlib/putenv.c
#	  foxlib/rename.c
#	  foxlib/sname.c
#	  foxlib/strdup.c
#	  foxlib/strtok.c
#	  foxlib/tell.c
#	  foxlib/vmslib.c
#	  llist/Makefile
#	  llist/llist.h
#	  llist/ll_alloc.c
#	  llist/ll_append.c
#	  llist/ll_clear.c
#	  llist/ll_delete.c
#	  llist/ll_elem.c
#	  llist/ll_first.c
#	  llist/ll_free.c
#	  llist/ll_hook.c
#	  llist/ll_init.c
#	  llist/ll_insert.c
#	  llist/ll_lookup.c
#	  llist/ll_magic.c
#	  llist/ll_next.c
#	  llist/ll_prev.c
#	  llist/ll_push.c
#	  llist/ll_remove.c
#	  llist/ll_unhook.c
#	  splay/Makefile
#	  splay/sptree.h
#	  splay/splay.c
#	  splay/spstats.c
#	  splay/sptree.c
#	  splay/test.c
#	  utils/kbd.c
#	  utils/getcwd.c
#	  utils/keys
#	  utils/keys.sv386
#	  utils/m286.malloc
#	  utils/strings
#	  utils/termcap
#
if test -r s2_seq_.tmp
then echo "Must unpack archives in sequence!"
     next=`cat s2_seq_.tmp`; echo "Please unpack part $next next"
     exit 1; fi
echo "x - extracting LIB.README (Text)"
sed 's/^X//' << 'SHAR_EOF' > LIB.README &&
XThis is the README file for the GRIEF support libraries.
X===
XFile                            Version
X============                    =======
X
X
Xdirlib/INSTALL                  1.2
Xdirlib/Makefile                 1.3
Xdirlib/NOTES                    1.2
Xdirlib/closedir.c               1.4
Xdirlib/directory.3c             1.2
Xdirlib/dirent.4                 1.2
Xdirlib/dirent.h                 1.2
Xdirlib/getdents.c               1.2
Xdirlib/opendir.c                1.2
Xdirlib/readdir.c                1.2
Xdirlib/rewinddir.c              1.2
Xdirlib/seekdir.c                1.2
Xdirlib/sys._dir.h               1.2
Xdirlib/sys.dirent.h             1.2
Xdirlib/telldir.c                1.2
Xdirlib/testdir.c                1.2
X
X
X
X
X
X
X
X
SHAR_EOF
chmod 0444 LIB.README || echo "restore of LIB.README fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/Makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/Makefile &&
XSRC = Makefile INSTALL NOTES closedir.c directory.3c dirent.4 dirent.h \
X	getdents.2 getdents.c opendir.c readdir.c rewinddir.c \
X	seekdir.c sys._dir.h sys.dirent.h telldir.c testdir.c \
X	vmsdir.h vmsdir.c
X
Xdist:
X	sccs update < /dev/null
Xdist-list:
X	@echo $(SRC)
SHAR_EOF
chmod 0444 dirlib/Makefile || echo "restore of dirlib/Makefile fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/INSTALL (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/INSTALL &&
X
X
X			INSTALLATION INSTRUCTIONS
X
X
XThe following instructions are for systems resembling Ninth Edition UNIX, with
Xhints about dealing with variations you may encounter for your specific system.
XInstallation should be done only by someone who is comfortable with modifying
Xthe standard C library and header files.
X
XIf your system already includes directory access routines, you should replace
Xthem with this package.  We're trying to get this standardized; see the
Xdiscussion in the NOTES file.
X
XI have tried to make the source code as generic as possible, but if your system
Xpredates Seventh Edition UNIX you will have problems.
X
XDISCLAIMER:  Although I believe the code and procedures described here to be
Xcorrect, I make no warranty of any kind, and you are advised to perform your
Xown careful testing before making any substantial change like this to your
Xprogramming environment.
X
X
X0)  For antique systems that do not support C's "void" data type, edit the file
X    sys.dirent.h to add the following:
X
X	typedef int		void;	/* good enough for govt work */
X
X    If for some reason your <sys/types.h> doesn't define them, add the
X    following to sys.dirent.h:
X
X	typedef unsigned short	ino_t;	/* (assuming original UFS) */
X	typedef long		off_t;	/* long is forced by lseek() */
X
X    None of this should be necessary for any modern UNIX system.
X
X1)  Copy the file dirent.h to /usr/include/dirent.h and copy the file
X    sys.dirent.h to /usr/include/sys/dirent.h.  (The file sys._dir.h is also
X    provided for the BRL UNIX System V emulation for 4.nBSD.  That environment
X    uses different directory names for everything.)
X
X2)  Copy the file directory.3c to /usr/man/man3/directory.3 and copy the file
X    dirent.4 to /usr/man/man5/dirent.5; edit the new file
X    /usr/man/man3/directory.3 to change the "SEE ALSO" reference from dirent(4)
X    to dirent(5) and to change the 3C on the first line to 3; edit the new file
X    /usr/man/man5/dirent.5 to change the 4 on the first line to 5; then print
X    the manual pages via the command
X
X	man directory dirent
X
X    to see what the new routines are like.  (If you have a "catman" style of
X    on-line manual, adapt these instructions accordingly.  Manual entries are
X    kept in directories with other names on some systems such as UNIX System V.
X    On systems that already had a directory library documented in some other
X    manual entry, remove the superseded manual entry; if the description of the
X    native filesystem directory format found by "man dir" refers to a directory
X    library, modify it to simply refer to the entry for "dirent".)
X
X3)  Copy the files closedir.c, opendir.c, readdir.c, rewinddir.c, seekdir.c,
X    and telldir.c to the "gen" or "port/gen" subdirectory of your C library
X    source directory.  If you do not have a getdents() system call, copy the
X    file getdents.c to the "sys" or "port/sys" subdirectory and copy the file
X    getdents.2 to /usr/man/man2/getdents.2 (actually you may prefer to put this
X    file in section 3 and adjust the references in the other manual entries
X    accordingly; also adjust the references to dirent(4) to be to dirent(5) if
X    that's where the entry is).  Edit the C library makefile(s) to include the
X    new object modules in the C library.  (See the comments at the beginning of
X    getdents.c for symbols that must be defined to configure getdents.c.)  Then
X    remake and reinstall the C library.  Alternatively, you can just compile
X    the new sources and insert their objects near the front of the C library
X    /lib/libc.a using the "ar" utility (seekdir.o should precede readdir.o,
X    which in turn should precede getdents.o).  On some systems you then need to
X    use the "ranlib" utility to update the archive symbol table.
X
X4)  After the C library has been updated, delete /usr/include/ndir.h or any
X    other header used with a previous directory library to prevent inadvertent
X    use of the superseded directory access interface.  Also delete any
X    corresponding library such as /usr/lib/libndir.a.
X
X5)  To verify installation, try compiling, linking, and running the program
X    testdir.c.  This program searches the current directory "." for each file
X    named as a program argument and prints `"FOO" found.' or `"FOO" not found.'
X    where FOO is of course replaced by the name being sought in the directory.
X    Try something like
X
X	cd /usr/bin			# a multi-block directory
X	WHEREVER/testdir FOO lint BAR f77 XYZZY
X
X    which should produce the output
X
X	"FOO" not found.
X	"lint" found.
X	"BAR" not found.
X	"f77" found.
X	"XYZZY" not found.
X
X    A more thorough test would be
X
X	cd /usr/bin			# a multi-block directory
X	WHEREVER/testdir `ls -a` | grep 'not found'
X
X    This program does not test the seekdir() and telldir() functions.
X
X6)  Notify your programmers that all directory access must be made through the
X    new interface, and that documentation is available via
X
X	man directory dirent
X
X    Make the NOTES file available to those programmers who might want to
X    understand what this is all about.
X
X7)  Change all system sources that were accessing directories to use the new
X    routines.  Nearly all such sources contain the line
X
X	#include <sys/dir.h>
X    or
X	#include <ndir.h>
X
X    so they should be easy to find.  (If you earlier removed some other header
X    file, that is, if this package superseded an earlier version of the
X    directory access library, look for its name too.  See the conversion
X    instructions in the NOTES file.)
SHAR_EOF
chmod 0444 dirlib/INSTALL || echo "restore of dirlib/INSTALL fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/NOTES (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/NOTES &&
X
X
XNOTES FOR NEARLY-POSIX-COMPATIBLE C LIBRARY DIRECTORY-ACCESS ROUTINES
X
X
XOlder UNIX C libraries lacked support for reading directories, so historically
Xprograms had knowledge of UNIX directory structure hard-coded into them.  When
XBerkeley changed the format of directories for 4.2BSD, it became necessary to
Xchange programs to work with the new structure.  Fortunately, Berkeley designed
Xa small set of directory access routines to encapsulate knowledge of the new
Xdirectory format so that user programs could deal with directory entries as an
Xabstract data type.  (Unfortunately, they didn't get it quite right.)  The
Xinterface to these routines was nearly independent of the particular
Ximplementation of directories on any given UNIX system; this has become a
Xparticularly important requirement with the advent of heterogeneous network
Xfilesystems such as NFS.
X
XIt has consequently become possible to write portable applications that search
Xdirectories by restricting all directory access to use these new interface
Xroutines.  The sources supplied here are a total rewrite of Berkeley's code,
Xincorporating ideas from a variety of sources and conforming as closely to
Xpublished standards as possible, and are in the PUBLIC DOMAIN to encourage
Xtheir widespread adoption.  They support four methods of access to system
Xdirectories: the original UNIX filesystem via read(), the 4.2BSD filesystem via
Xread(), NFS and native filesystems via getdirentries(), and SVR3 getdents().
XThe other three types are accomplished by appropriate emulation of the SVR3
Xgetdents() system call, which attains portability at the cost of slightly more
Xdata movement than absolutely necessary for some systems.  These routines
Xshould be added to the standard C library on all UNIX systems, and all existing
Xand future applications should be changed to use this interface.  Once this is
Xdone, there should be no portability problems due to differences in underlying
Xdirectory structures among UNIX systems.  (When porting your applications to
Xother UNIX systems, you can always carry this package around with you.)
X
XAn additional benefit of these routines is that they buffer directory input,
Xwhich provides improved access speed over raw read()s of one entry at a time.
X
XOne annoying compatibility problem has arisen along the way, namely that the
Xoriginal Berkeley interface used the same name, struct direct, for the new data
Xstructure as had been used for the original UNIX filesystem directory record
Xstructure.  This name was changed by the IEEE 1003.1 (POSIX) Working Group to
X"struct dirent" and was picked up for SVR3 under the new name; it is also the
Xname used in this portable package.  I believe it is necessary to bite the
Xbullet and adopt the new non-conflicting name.  Code using a 4.2BSD-compatible
Xpackage needs to be slightly revised to work with this new package, as follows:
X	Change
X		#include <ndir.h>	/* Ninth Edition UNIX */
X	or
X		#include <sys/dir.h>	/* 4.2BSD */
X	or
X		#include <dir.h>	/* BRL System V emulation */
X	to
X		#include <sys/types.h>	/* if not already #included */
X		#include <dirent.h>
X
X	Change
X		struct direct
X	to
X		struct dirent
X
X	Change
X		(anything)->d_namlen
X	to
X		strlen( (anything)->d_name )
X
XThere is a minor compatibility problem in that the closedir() function was
Xoriginally defined to have type void, but IEEE 1003.1 changed this to type int,
Xwhich is what this implementation supports (even though I disagree with the
Xchange).  However, the difference does not affect most applications.
X
XAnother minor problem is that IEEE 1003.1 defined the d_name member of a struct
Xdirent to be an array of maximum length; this does not permit use of compact
Xvariable-length entries directly from a directory block buffer.  This part of
Xthe specification is incompatible with efficient use of the getdents() system
Xcall, and I have therefore chosen to follow the SVID specification instead of
XIEEE 1003.1 (which I hope is changed for the final-use standard).  This
Xdeviation should have little or no impact on sensibly-coded applications, since
Xthe relevant d_name length is that given by strlen(), not the declared array
Xsize.
X
XError handling is not completely satisfactory, due to the variety of possible
Xfailure modes in a general setting.  For example, the rewinddir() function
Xmight fail, but there is no good way to indicate this.  I have tried to
Xfollow the specifications in IEEE 1003.1 and the SVID as closely as possible,
Xbut there are minor deviations in this regard.  Applications should not rely
Xtoo heavily on exact failure mode semantics.
X
XPlease do not change the new standard interface in any way, as that would
Xdefeat the major purpose of this package!  (It's okay to alter the internal
Ximplementation if you really have to, although I tried to make this unnecessary
Xfor the vast majority of UNIX variants.)
X
XInstallation instructions can be found in the file named INSTALL.
X
XThis implementation is provided by:
X
X	Douglas A. Gwyn
X	U.S. Army Ballistic Research Laboratory
X	SLCBR-VL-V
X	Aberdeen Proving Ground, MD 21005-5066
X
X	(301)278-6647
X
X	Gwyn@BRL.MIL or seismo!brl!gwyn
X
XThis is UNSUPPORTED, use-at-your-own-risk, free software in the public domain.
XHowever, I would appreciate hearing of any actual bugs you find in this
Ximplementation and/or any improvements you come up with.
SHAR_EOF
chmod 0444 dirlib/NOTES || echo "restore of dirlib/NOTES fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/closedir.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/closedir.c &&
X
XPlease replace closedir.c in my recent posting of the public-domain
Xdirectory access routine sources with the following:
X
X/*
X	closedir -- close a directory stream
X
X	last edit:	11-Nov-1988	D A Gwyn
X*/
X
X#include	<sys/errno.h>
X#include	<sys/types.h>
X#include	<dirent.h>
X
Xtypedef char	*pointer;		/* (void *) if you have it */
X
Xextern void	free();
Xextern int	close();
X
Xextern int	errno;
X
X#ifndef NULL
X#define	NULL	0
X#endif
X
Xint
Xclosedir( dirp )
X	register DIR	*dirp;		/* stream from opendir() */
X	{
X	register int	fd;
X
X	if ( dirp == NULL || dirp->dd_buf == NULL )
X		{
X		errno = EFAULT;
X		return -1;		/* invalid pointer */
X		}
X
X	fd = dirp->dd_fd;		/* bug fix thanks to R. Salz */
X	free( (pointer)dirp->dd_buf );
X	free( (pointer)dirp );
X	return close( fd );
X	}
X
X
SHAR_EOF
chmod 0444 dirlib/closedir.c || echo "restore of dirlib/closedir.c fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/directory.3c (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/directory.3c &&
X.TH DIRECTORY 3C "Standard Extension"
X.SH NAME
Xopendir, readdir, telldir, seekdir, rewinddir, closedir \- directory operations
X.SH SYNOPSIS
X.B "#include <sys/types.h>"
X.br
X.B "#include <dirent.h>"
X.P
X.B "DIR \(**opendir (dirname)"
X.br
X.B "char \(**dirname;"
X.P
X.B "struct dirent \(**readdir (dirp)"
X.br
X.B "DIR \(**dirp;"
X.P
X.B "off_t telldir (dirp)"
X.br
X.B "DIR \(**dirp;"
X.P
X.B "void seekdir (dirp, loc)"
X.br
X.B "DIR \(**dirp;"
X.br
X.B "off_t loc;"
X.P
X.B "void rewinddir (dirp)"
X.br
X.B "DIR \(**dirp;"
X.P
X.B "int closedir (dirp)"
X.br
X.B "DIR \(**dirp;"
X.SH DESCRIPTION
X.I Opendir
Xestablishes a connection between
Xthe directory named by
X.I dirname
Xand a unique object of type
X.SM DIR
Xknown as a
X.I "directory stream"
Xthat it creates.
X.I Opendir
Xreturns a pointer to be used to identify the
Xdirectory stream
Xin subsequent operations.
XA
X.SM NULL
Xpointer is returned if
X.I dirname
Xcannot be accessed or is not a directory,
Xor if
X.I opendir
Xis unable to create the
X.SM DIR
Xobject
X(perhaps due to insufficient memory).
X.P
X.I Readdir
Xreturns a pointer to an internal structure
Xcontaining information about the next active directory entry.
XNo inactive entries are reported.
XThe internal structure may be overwritten by
Xanother operation on the same
Xdirectory stream;
Xthe amount of storage needed to hold a copy
Xof the internal structure is given by the value of a macro,
X.IR DIRENTSIZ(strlen(direntp\->d_name)) ,
Xnot by
X.I "sizeof(struct\ dirent)"
Xas one might expect.
XA
X.SM NULL
Xpointer is returned
Xupon reaching the end of the directory,
Xupon detecting an invalid location in the directory,
Xor upon occurrence of an error while reading the directory.
X.P
X.I Telldir
Xreturns the current position associated with the named
Xdirectory stream
Xfor later use as an argument to
X.IR seekdir .
X.P
X.I Seekdir
Xsets the position of the next
X.I readdir
Xoperation on the named
Xdirectory stream.
XThe new position reverts to the one associated with the
Xdirectory stream
Xwhen the
X.I telldir
Xoperation from which
X.I loc
Xwas obtained was performed.
X.P
X.I Rewinddir
Xresets the position of the named
Xdirectory stream
Xto the beginning of the directory.
XAll buffered data for the directory stream is discarded,
Xthereby guaranteeing that the actual
Xfile system directory will be referred to for the next
X.I readdir
Xon the
Xdirectory stream.
X.P
X.I Closedir
Xcloses the named
Xdirectory stream;
Xinternal resources used for the
Xdirectory stream are liberated,
Xand subsequent use of the associated
X.SM DIR
Xobject is no longer valid.
X.I Closedir
Xreturns a value of zero if no error occurs,
X\-1 otherwise.
X.P
XThere are several possible errors that can occur
Xas a result of these operations;
Xthe external integer variable
X.I errno
Xis set to indicate the specific error.
X.RI ( Readdir 's
Xdetection of the normal end of a directory
Xis not considered to be an error.)
X.SH EXAMPLE
XSample code which searches the current working directory for entry
X.IR name :
X.P
X.ft B
X	dirp = opendir( "." );
X.br
X	while ( (dp = readdir( dirp )) != NULL )
X.br
X		if ( strcmp( dp\->d_name, name ) == 0 )
X.br
X			{
X.br
X			(void) closedir( dirp );
X.br
X			return FOUND;
X.br
X			}
X.br
X	(void) closedir( dirp );
X.br
X	return NOT_FOUND;
X.ft P
X.SH "SEE ALSO"
Xgetdents(2), dirent(4).
X.SH WARNINGS
XEntries for "." and ".."
Xmay not be reported for some file system types.
X.P
XThe value returned by
X.I telldir
Xneed not have any simple interpretation
Xand should only be used as an argument to
X.IR seekdir .
XSimilarly,
Xthe
X.I loc
Xargument to
X.I seekdir
Xmust be obtained from a previous
X.I telldir
Xoperation on the same
Xdirectory stream.
X.P
X.I Telldir
Xand
X.I seekdir
Xare unreliable when used in conjunction with
Xfile systems that perform directory compaction or expansion
Xor when the directory stream has been closed and reopened.
XIt is best to avoid using
X.I telldir
Xand
X.I seekdir
Xaltogether.
X.P
XThe exact set of
X.I errno
Xvalues and meanings may vary among implementations.
X.P
XBecause directory entries can dynamically
Xappear and disappear,
Xand because directory contents are buffered
Xby these routines,
Xan application may need to continually rescan
Xa directory to maintain an accurate picture
Xof its active entries.
SHAR_EOF
chmod 0444 dirlib/directory.3c || echo "restore of dirlib/directory.3c fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/dirent.4 (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/dirent.4 &&
X.TH DIRENT 4 "Standard Extension"
X.SH NAME
Xdirent \- file system independent directory entry
X.SH SYNOPSIS
X.B "#include <sys/types.h>"
X.br
X.B "#include <sys/dirent.h>"
X.SH DESCRIPTION
XDifferent file system types
Xmay have different directory entries.
XThe
X.I dirent
Xstructure defines a
Xfile system independent directory entry,
Xwhich contains information common to
Xdirectory entries in different file system types.
XA set of these structures is returned by the
X.IR getdents (2)
Xsystem call.
X.P
XThe
X.I dirent
Xstructure is defined below.
X.br
Xstruct	dirent	{
X.br
X			long			d_ino;
X.br
X			off_t			d_off;
X.br
X			unsigned short		d_reclen;
X.br
X			char			d_name[1];
X.br
X		};
X.P
XThe field
X.I d_ino
Xis a number which is unique
Xfor each file in the file system.
XThe field
X.I d_off\^
Xrepresents an offset of that directory entry
Xin the actual file system directory.
XThe field
X.I d_name
Xis the beginning of the character array
Xgiving the name of the directory entry.
XThis name is null terminated
Xand may have at most
X.SM NAME_MAX
Xcharacters in addition to the null terminator.
XThis results in file system independent directory entries
Xbeing variable-length entities.
XThe value of
X.I d_reclen
Xis the record length of this entry.
XThis length is defined to be the number of bytes
Xbetween the beginning of the current entry and the next one,
Xadjusted so that the next entry
Xwill start on a long boundary.
X.SH FILES
X/usr/include/sys/dirent.h
X.SH "SEE ALSO"
Xgetdents(2).
X.SH WARNING
XThe field
X.I d_off\^
Xdoes not have a simple interpretation
Xfor some file system types
Xand should not be used directly by applications.
SHAR_EOF
chmod 0444 dirlib/dirent.4 || echo "restore of dirlib/dirent.4 fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/dirent.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/dirent.h &&
X/*
X	<dirent.h> -- definitions for SVR3 directory access routines
X
X	last edit:	25-Apr-1987	D A Gwyn
X
X	Prerequisite:	<sys/types.h>
X*/
X
X#include	<sys/dirent.h>
X
X#define	DIRBUF		8192		/* buffer size for fs-indep. dirs */
X	/* must in general be larger than the filesystem buffer size */
X
Xtypedef struct
X	{
X	int	dd_fd;			/* file descriptor */
X	int	dd_loc;			/* offset in block */
X	int	dd_size;		/* amount of valid data */
X	char	*dd_buf;		/* -> directory block */
X	}	DIR;			/* stream data from opendir() */
X
Xextern DIR		*opendir();
Xextern struct dirent	*readdir();
Xextern off_t		telldir();
Xextern void		seekdir();
Xextern void		rewinddir();
Xextern int		closedir();
X
X#ifndef NULL
X#define	NULL	0			/* DAG -- added for convenience */
X#endif
SHAR_EOF
chmod 0444 dirlib/dirent.h || echo "restore of dirlib/dirent.h fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/getdents.2 (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/getdents.2 &&
X.TH GETDENTS 2 "Standard Extension"
X.SH NAME
Xgetdents \- get directory entries in a file system independent format
X.SH SYNOPSIS
X.B "#include <sys/types.h>"
X.br
X.B "#include <sys/dirent.h>"
X.P
X.B "int getdents (fildes, buf, nbyte)"
X.br
X.B "int fildes;"
X.br
X.B "char \(**buf;"
X.br
X.B "unsigned nbyte;"
X.SH DESCRIPTION
X.I Fildes
Xis a file descriptor obtained from an
X.IR open (2)
Xor
X.IR dup (2)
Xsystem call.
X.P
X.I Getdents
Xattempts to read
X.I nbyte
Xbytes from the directory associated with
X.I fildes
Xand to format them as
Xfile system independent entries
Xin the buffer pointed to by
X.IR buf .
XSince the file system independent directory entries
Xare of variable length,
Xin most cases the actual number of bytes returned
Xwill be less than
X.IR nbyte .
X.P
XThe file system independent directory entry is specified by the
X.I dirent
Xstructure.
XFor a description of this see
X.IR dirent (4).
X.P
XOn devices capable of seeking,
X.I getdents
Xstarts at a position in the file given by
Xthe file pointer associated with
X.IR fildes .
XUpon return from
X.IR getdents ,
Xthe file pointer has been incremented
Xto point to the next directory entry.
X.P
XThis system call was developed in order to implement the
X.I readdir
Xroutine
X[for a description see
X.IR directory (3C)]
Xand should not be used for other purposes.
X.SH "SEE ALSO"
Xdirectory(3C), dirent(4).
X.SH DIAGNOSTICS
XUpon successful completion
Xa non-negative integer is returned
Xindicating the number of bytes of
X.I buf\^
Xactually filled.
X(This need not be the number actually used
Xin the actual directory file.)\|\|
XA value of zero
Xindicates the end of the directory has been reached.
XIf
X.I getdents
Xfails for any other reason,
Xa value of \-1 is returned and
Xthe external integer variable
X.I errno
Xis set to indicate the error.
X.SH WARNINGS
XEntries for "." and ".."
Xmay not be reported for some file system types.
X.P
XThe exact set of
X.I errno
Xvalues and meanings may vary among implementations.
SHAR_EOF
chmod 0644 dirlib/getdents.2 || echo "restore of dirlib/getdents.2 fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/getdents.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/getdents.c &&
X/*
X	getdents -- get directory entries in a file system independent format
X			(SVR3 system call emulation)
X
X	last edit:	06-Jul-1987	D A Gwyn
X
X	This single source file supports several different methods of
X	getting directory entries from the operating system.  Define
X	whichever one of the following describes your system:
X
X	UFS	original UNIX filesystem (14-character name limit)
X	BFS	4.2BSD (also 4.3BSD) native filesystem (long names)
X	NFS	getdirentries() system call
X
X	Also define any of the following that are pertinent:
X
X	ATT_SPEC	check user buffer address for longword alignment
X	BSD_SYSV	BRL UNIX System V emulation environment on 4.nBSD
X	UNK		have _getdents() system call, but kernel may not
X			support it
X
X	If your C library has a getdents() system call interface, but you
X	can't count on all kernels on which your application binaries may
X	run to support it, change the system call interface name to
X	_getdents() and define "UNK" to enable the system-call validity
X	test in this "wrapper" around _getdents().
X
X	If your system has a getdents() system call that is guaranteed 
X	to always work, you shouldn't be using this source file at all.
X*/
X
X#include	<sys/errno.h>
X#include	<sys/types.h>
X#ifdef BSD_SYSV
X#include	<sys/_dir.h>		/* BSD flavor, not System V */
X#else
X#include	<sys/dir.h>
X#undef	MAXNAMLEN			/* avoid conflict with SVR3 */
X	/* Good thing we don't need to use the DIRSIZ() macro! */
X#ifdef d_ino				/* 4.3BSD/NFS using d_fileno */
X#undef	d_ino				/* (not absolutely necessary) */
X#else
X#define	d_fileno	d_ino		/* (struct direct) member */
X#endif
X#endif
X#include	<sys/dirent.h>
X#include	<sys/stat.h>
X#ifdef UNK
X#ifndef UFS
X#include "***** ERROR ***** UNK applies only to UFS"
X/* One could do something similar for getdirentries(), but I didn't bother. */
X#endif
X#include	<signal.h>
X#endif
X
X#if defined(UFS) + defined(BFS) + defined(NFS) != 1	/* sanity check */
X#include "***** ERROR ***** exactly one of UFS, BFS, or NFS must be defined"
X#endif
X
X#ifdef UFS
X#define	RecLen( dp )	(sizeof(struct direct))	/* fixed-length entries */
X#else	/* BFS || NFS */
X#define	RecLen( dp )	((dp)->d_reclen)	/* variable-length entries */
X#endif
X
X#ifdef NFS
X#ifdef BSD_SYSV
X#define	getdirentries	_getdirentries	/* package hides this system call */
X#endif
Xextern int	getdirentries();
Xstatic long	dummy;			/* getdirentries() needs basep */
X#define	GetBlock( fd, buf, n )	getdirentries( fd, buf, (unsigned)n, &dummy )
X#else	/* UFS || BFS */
X#ifdef BSD_SYSV
X#define read	_read			/* avoid emulation overhead */
X#endif
Xextern int	read();
X#define	GetBlock( fd, buf, n )	read( fd, buf, (unsigned)n )
X#endif
X
X#ifdef UNK
Xextern int	_getdents();		/* actual system call */
X#endif
X
Xextern char	*strncpy();
Xextern int	fstat();
Xextern off_t	lseek();
X
Xextern int	errno;
X
X#ifndef DIRBLKSIZ
X#define	DIRBLKSIZ	4096		/* directory file read buffer size */
X#endif
X
X#ifndef NULL
X#define	NULL	0
X#endif
X
X#ifndef SEEK_CUR
X#define	SEEK_CUR	1
X#endif
X
X#ifndef S_ISDIR				/* macro to test for directory file */
X#define	S_ISDIR( mode )		(((mode) & S_IFMT) == S_IFDIR)
X#endif
X
X#ifdef UFS
X
X/*
X	The following routine is necessary to handle DIRSIZ-long entry names.
X	Thanks to Richard Todd for pointing this out.
X*/
X
Xstatic int
XNameLen( name )				/* return # chars in embedded name */
X	char		name[];		/* -> name embedded in struct direct */
X	{
X	register char	*s;		/* -> name[.] */
X	register char	*stop = &name[DIRSIZ];	/* -> past end of name field */
X
X	for ( s = &name[1];		/* (empty names are impossible) */
X	      *s != '\0'		/* not NUL terminator */
X	   && ++s < stop;		/* < DIRSIZ characters scanned */
X	    )
X		;
X
X	return s - name;		/* # valid characters in name */
X	}
X
X#else	/* BFS || NFS */
X
Xextern int	strlen();
X
X#define	NameLen( name )	strlen( name )	/* names are always NUL-terminated */
X
X#endif
X
X#ifdef UNK
Xstatic enum	{ maybe, no, yes }	state = maybe;
X					/* does _getdents() work? */
X
X/*ARGSUSED*/
Xstatic void
Xsig_catch( sig )
X	int	sig;			/* must be SIGSYS */
X	{
X	state = no;			/* attempted _getdents() faulted */
X	}
X#endif
X
Xint
Xgetdents( fildes, buf, nbyte )		/* returns # bytes read;
X					   0 on EOF, -1 on error */
X	int			fildes;	/* directory file descriptor */
X	char			*buf;	/* where to put the (struct dirent)s */
X	unsigned		nbyte;	/* size of buf[] */
X	{
X	int			serrno;	/* entry errno */
X	off_t			offset;	/* initial directory file offset */
X	struct stat		statb;	/* fstat() info */
X	union	{
X		char		dblk[DIRBLKSIZ];
X					/* directory file block buffer */
X		struct direct	dummy;	/* just for alignment */
X		}	u;		/* (avoids having to malloc()) */
X	register struct direct	*dp;	/* -> u.dblk[.] */
X	register struct dirent	*bp;	/* -> buf[.] */
X
X#ifdef UNK
X	switch ( state )
X		{
X		void		(*shdlr)();	/* entry SIGSYS handler */
X		register int	retval;	/* return from _getdents() if any */
X
X	case yes:			/* _getdents() is known to work */
X		return _getdents( fildes, buf, nbyte );
X
X	case maybe:			/* first time only */
X		shdlr = signal( SIGSYS, sig_catch );
X		retval = _getdents( fildes, buf, nbyte );	/* try it */
X		(void)signal( SIGSYS, shdlr );
X
X		if ( state == maybe )	/* SIGSYS did not occur */
X			{
X			state = yes;	/* so _getdents() must have worked */
X			return retval;
X			}
X		/* else fall through into emulation */
X
X/*	case no:	/* fall through into emulation */
X		}
X#endif
X
X	if ( buf == NULL
X#ifdef ATT_SPEC
X	  || (unsigned long)buf % sizeof(long) != 0	/* ugh */
X#endif
X	   )	{
X		errno = EFAULT;		/* invalid pointer */
X		return -1;
X		}
X
X	if ( fstat( fildes, &statb ) != 0 )
X		return -1;		/* errno set by fstat() */
X
X	if ( !S_ISDIR( statb.st_mode ) )
X		{
X		errno = ENOTDIR;	/* not a directory */
X		return -1;
X		}
X
X	if ( (offset = lseek( fildes, (off_t)0, SEEK_CUR )) < 0 )
X		return -1;		/* errno set by lseek() */
X
X#ifdef BFS				/* no telling what remote hosts do */
X	if ( (unsigned long)offset % DIRBLKSIZ != 0 )
X		{
X		errno = ENOENT;		/* file pointer probably misaligned */
X		return -1;
X		}
X#endif
X
X	serrno = errno;			/* save entry errno */
X
X	for ( bp = (struct dirent *)buf; bp == (struct dirent *)buf; )
X		{			/* convert next directory block */
X		int	size;
X
X		do	size = GetBlock( fildes, u.dblk, DIRBLKSIZ );
X		while ( size == -1 && errno == EINTR );
X
X		if ( size <= 0 )
X			return size;	/* EOF or error (EBADF) */
X
X		for ( dp = (struct direct *)u.dblk;
X		      (char *)dp < &u.dblk[size];
X		      dp = (struct direct *)((char *)dp + RecLen( dp ))
X		    )	{
X#ifndef UFS
X			if ( dp->d_reclen <= 0 )
X				{
X				errno = EIO;	/* corrupted directory */
X				return -1;
X				}
X#endif
X
X			if ( dp->d_fileno != 0 )
X				{	/* non-empty; copy to user buffer */
X				register int	reclen =
X					DIRENTSIZ( NameLen( dp->d_name ) );
X
X				if ( (char *)bp + reclen > &buf[nbyte] )
X					{
X					errno = EINVAL;
X					return -1;	/* buf too small */
X					}
X
X				bp->d_ino = dp->d_fileno;
X				bp->d_off = offset + ((char *)dp - u.dblk);
X				bp->d_reclen = reclen;
X				(void)strncpy( bp->d_name, dp->d_name,
X					       reclen - DIRENTBASESIZ
X					     );	/* adds NUL padding */
X
X				bp = (struct dirent *)((char *)bp + reclen);
X				}
X			}
X
X#ifndef BFS	/* 4.2BSD screwed up; fixed in 4.3BSD */
X		if ( (char *)dp > &u.dblk[size] )
X			{
X			errno = EIO;	/* corrupted directory */
X			return -1;
X			}
X#endif
X		}
X
X	errno = serrno;			/* restore entry errno */
X	return (char *)bp - buf;	/* return # bytes read */
X	}
SHAR_EOF
chmod 0444 dirlib/getdents.c || echo "restore of dirlib/getdents.c fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/opendir.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/opendir.c &&
X/*
X	opendir -- open a directory stream
X
X	last edit:	16-Jun-1987	D A Gwyn
X*/
X
X#include	<sys/errno.h>
X#include	<sys/types.h>
X#include	<sys/stat.h>
X#include	<dirent.h>
X
X#ifdef BSD_SYSV
X#define open	_open			/* avoid emulation overhead */
X#endif
X
Xtypedef char	*pointer;		/* (void *) if you have it */
X
Xextern void	free();
Xextern pointer	malloc();
Xextern int	open(), close(), fstat();
X
Xextern int	errno;
X
X#ifndef NULL
X#define	NULL	0
X#endif
X
X#ifndef O_RDONLY
X#define	O_RDONLY	0
X#endif
X
X#ifndef S_ISDIR				/* macro to test for directory file */
X#define	S_ISDIR( mode )		(((mode) & S_IFMT) == S_IFDIR)
X#endif
X
XDIR *
Xopendir( dirname )
X	char		*dirname;	/* name of directory */
X	{
X	register DIR	*dirp;		/* -> malloc'ed storage */
X	register int	fd;		/* file descriptor for read */
X	struct stat	sbuf;		/* result of fstat() */
X
X	if ( (fd = open( dirname, O_RDONLY )) < 0 )
X		return NULL;		/* errno set by open() */
X
X	if ( fstat( fd, &sbuf ) != 0 || !S_ISDIR( sbuf.st_mode ) )
X		{
X		(void)close( fd );
X		errno = ENOTDIR;
X		return NULL;		/* not a directory */
X		}
X
X	if ( (dirp = (DIR *)malloc( sizeof(DIR) )) == NULL
X	  || (dirp->dd_buf = (char *)malloc( (unsigned)DIRBUF )) == NULL
X	   )	{
X		register int	serrno = errno;
X					/* errno set to ENOMEM by sbrk() */
X
X		if ( dirp != NULL )
X			free( (pointer)dirp );
X
X		(void)close( fd );
X		errno = serrno;
X		return NULL;		/* not enough memory */
X		}
X
X	dirp->dd_fd = fd;
X	dirp->dd_loc = dirp->dd_size = 0;	/* refill needed */
X
X	return dirp;
X	}
SHAR_EOF
chmod 0444 dirlib/opendir.c || echo "restore of dirlib/opendir.c fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/readdir.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/readdir.c &&
X/*
X	readdir -- read next entry from a directory stream
X
X	last edit:	25-Apr-1987	D A Gwyn
X*/
X
X#include	<sys/errno.h>
X#include	<sys/types.h>
X#include	<dirent.h>
X
Xextern int	getdents();		/* SVR3 system call, or emulation */
X
Xextern int	errno;
X
X#ifndef NULL
X#define	NULL	0
X#endif
X
Xstruct dirent *
Xreaddir( dirp )
X	register DIR		*dirp;	/* stream from opendir() */
X	{
X	register struct dirent	*dp;	/* -> directory data */
X
X	if ( dirp == NULL || dirp->dd_buf == NULL )
X		{
X		errno = EFAULT;
X		return NULL;		/* invalid pointer */
X		}
X
X	do	{
X		if ( dirp->dd_loc >= dirp->dd_size )	/* empty or obsolete */
X			dirp->dd_loc = dirp->dd_size = 0;
X
X		if ( dirp->dd_size == 0	/* need to refill buffer */
X		  && (dirp->dd_size =
X			getdents( dirp->dd_fd, dirp->dd_buf, (unsigned)DIRBUF )
X		     ) <= 0
X		   )
X			return NULL;	/* EOF or error */
X
X		dp = (struct dirent *)&dirp->dd_buf[dirp->dd_loc];
X		dirp->dd_loc += dp->d_reclen;
X		}
X	while ( dp->d_ino == 0L );	/* don't rely on getdents() */
X
X	return dp;
X	}
SHAR_EOF
chmod 0444 dirlib/readdir.c || echo "restore of dirlib/readdir.c fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/rewinddir.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/rewinddir.c &&
X/*
X	rewinddir -- rewind a directory stream
X
X	last edit:	25-Apr-1987	D A Gwyn
X
X	This is not simply a call to seekdir(), because seekdir()
X	will use the current buffer whenever possible and we need
X	rewinddir() to forget about buffered data.
X*/
X
X#include	<sys/errno.h>
X#include	<sys/types.h>
X#include	<dirent.h>
X
Xextern off_t	lseek();
X
Xextern int	errno;
X
X#ifndef NULL
X#define	NULL	0
X#endif
X
X#ifndef SEEK_SET
X#define	SEEK_SET	0
X#endif
X
Xvoid
Xrewinddir( dirp )
X	register DIR		*dirp;	/* stream from opendir() */
X	{
X	if ( dirp == NULL || dirp->dd_buf == NULL )
X		{
X		errno = EFAULT;
X		return;			/* invalid pointer */
X		}
X
X	dirp->dd_loc = dirp->dd_size = 0;	/* invalidate buffer */
X	(void)lseek( dirp->dd_fd, (off_t)0, SEEK_SET );	/* may set errno */
X	}
SHAR_EOF
chmod 0444 dirlib/rewinddir.c || echo "restore of dirlib/rewinddir.c fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/seekdir.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/seekdir.c &&
X/*
X	seekdir -- reposition a directory stream
X
X	last edit:	24-May-1987	D A Gwyn
X
X	An unsuccessful seekdir() will in general alter the current
X	directory position; beware.
X
X	NOTE:	4.nBSD directory compaction makes seekdir() & telldir()
X		practically impossible to do right.  Avoid using them!
X*/
X
X#include	<sys/errno.h>
X#include	<sys/types.h>
X#include	<dirent.h>
X
Xextern off_t	lseek();
X
Xextern int	errno;
X
X#ifndef NULL
X#define	NULL	0
X#endif
X
X#ifndef SEEK_SET
X#define	SEEK_SET	0
X#endif
X
Xtypedef int	bool;			/* Boolean data type */
X#define	false	0
X#define	true	1
X
Xvoid
Xseekdir( dirp, loc )
X	register DIR	*dirp;		/* stream from opendir() */
X	register off_t	loc;		/* position from telldir() */
X	{
X	register bool	rewind;		/* "start over when stymied" flag */
X
X	if ( dirp == NULL || dirp->dd_buf == NULL )
X		{
X		errno = EFAULT;
X		return;			/* invalid pointer */
X		}
X
X	/* A (struct dirent)'s d_off is an invented quantity on 4.nBSD
X	   NFS-supporting systems, so it is not safe to lseek() to it. */
X
X	/* Monotonicity of d_off is heavily exploited in the following. */
X
X	/* This algorithm is tuned for modest directory sizes.  For
X	   huge directories, it might be more efficient to read blocks
X	   until the first d_off is too large, then back up one block,
X	   or even to use binary search on the directory blocks.  I
X	   doubt that the extra code for that would be worthwhile. */
X
X	if ( dirp->dd_loc >= dirp->dd_size	/* invalid index */
X	  || ((struct dirent *)&dirp->dd_buf[dirp->dd_loc])->d_off > loc
X					/* too far along in buffer */
X	   )
X		dirp->dd_loc = 0;	/* reset to beginning of buffer */
X	/* else save time by starting at current dirp->dd_loc */
X
X	for ( rewind = true; ; )
X		{
X		register struct dirent	*dp;
X
X		/* See whether the matching entry is in the current buffer. */
X
X		if ( (dirp->dd_loc < dirp->dd_size	/* valid index */
X		   || readdir( dirp ) != NULL	/* next buffer read */
X		   && (dirp->dd_loc = 0, true)	/* beginning of buffer set */
X		     )
X		  && (dp = (struct dirent *)&dirp->dd_buf[dirp->dd_loc])->d_off
X			<= loc		/* match possible in this buffer */
X		   )	{
X			for ( /* dp initialized above */ ;
X			      (char *)dp < &dirp->dd_buf[dirp->dd_size];
X			      dp = (struct dirent *)((char *)dp + dp->d_reclen)
X			    )
X				if ( dp->d_off == loc )
X					{	/* found it! */
X					dirp->dd_loc =
X						(char *)dp - dirp->dd_buf;
X					return;
X					}
X
X			rewind = false;	/* no point in backing up later */
X			dirp->dd_loc = dirp->dd_size;	/* set end of buffer */
X			}
X		else			/* whole buffer past matching entry */
X			if ( !rewind )
X				{	/* no point in searching further */
X				errno = EINVAL;
X				return;	/* no entry at specified loc */
X				}
X			else	{	/* rewind directory and start over */
X				rewind = false;	/* but only once! */
X
X				dirp->dd_loc = dirp->dd_size = 0;
X
X				if ( lseek( dirp->dd_fd, (off_t)0, SEEK_SET )
X					!= 0
X				   )
X					return;	/* errno already set (EBADF) */
X
X				if ( loc == 0 )
X					return; /* save time */
X				}
X		}
X	}
SHAR_EOF
chmod 0444 dirlib/seekdir.c || echo "restore of dirlib/seekdir.c fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/sys._dir.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/sys._dir.h &&
X/*
X	<sys/_dir.h> -- definitions for 4.2,4.3BSD directories
X
X	last edit:	25-Apr-1987	D A Gwyn
X
X	A directory consists of some number of blocks of DIRBLKSIZ bytes each,
X	where DIRBLKSIZ is chosen such that it can be transferred to disk in a
X	single atomic operation (e.g., 512 bytes on most machines).
X
X	Each DIRBLKSIZ-byte block contains some number of directory entry
X	structures, which are of variable length.  Each directory entry has the
X	beginning of a (struct direct) at the front of it, containing its
X	filesystem-unique ident number, the length of the entry, and the length
X	of the name contained in the entry.  These are followed by the NUL-
X	terminated name padded to a (long) boundary with 0 bytes.  The maximum
X	length of a name in a directory is MAXNAMELEN.
X
X	The macro DIRSIZ(dp) gives the amount of space required to represent a
X	directory entry.  Free space in a directory is represented by entries
X	that have dp->d_reclen > DIRSIZ(dp).  All DIRBLKSIZ bytes in a
X	directory block are claimed by the directory entries; this usually
X	results in the last entry in a directory having a large dp->d_reclen.
X	When entries are deleted from a directory, the space is returned to the
X	previous entry in the same directory block by increasing its
X	dp->d_reclen.  If the first entry of a directory block is free, then
X	its dp->d_fileno is set to 0; entries other than the first in a
X	directory do not normally have 	dp->d_fileno set to 0.
X
X	prerequisite:	<sys/types.h>
X*/
X
X#if defined(accel) || defined(sun) || defined(vax)
X#define	DIRBLKSIZ	512		/* size of directory block */
X#else
X#ifdef alliant
X#define	DIRBLKSIZ	4096		/* size of directory block */
X#else
X#ifdef gould
X#define	DIRBLKSIZ	1024		/* size of directory block */
X#else
X#ifdef ns32000	/* Dynix System V */
X#define	DIRBLKSIZ	2600		/* size of directory block */
X#else	/* be conservative; multiple blocks are okay but fractions are not */
X#define	DIRBLKSIZ	4096		/* size of directory block */
X#endif
X#endif
X#endif
X#endif
X
X#define	MAXNAMELEN	255		/* maximum filename length */
X/* NOTE:  not MAXNAMLEN, which has been preempted by SVR3 <dirent.h> */
X
Xstruct direct				/* data from read()/_getdirentries() */
X	{
X	unsigned long	d_fileno;	/* unique ident of entry */
X	unsigned short	d_reclen;	/* length of this record */
X	unsigned short	d_namlen;	/* length of string in d_name */
X	char		d_name[MAXNAMELEN+1];	/* NUL-terminated filename */
X	/* typically shorter */
X	};
X
X/*
X	The DIRSIZ macro gives the minimum record length which will hold the
X	directory entry.  This requires the amount of space in a (struct
X	direct) without the d_name field, plus enough space for the name with a
X	terminating NUL character, rounded up to a (long) boundary.
X
X	(Note that Berkeley didn't properly compensate for struct padding,
X	but we nevertheless have to use the same size as the actual system.)
X*/
X
X#define	DIRSIZ( dp )	((sizeof(struct direct) - (MAXNAMELEN+1) \
X			+ sizeof(long) + (dp)->d_namlen) \
X			/ sizeof(long) * sizeof(long))
SHAR_EOF
chmod 0444 dirlib/sys._dir.h || echo "restore of dirlib/sys._dir.h fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/sys.dirent.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/sys.dirent.h &&
X/*
X	<sys/dirent.h> -- file system independent directory entry (SVR3)
X
X	last edit:	25-Apr-1987	D A Gwyn
X
X	prerequisite:	<sys/types.h>
X*/
X
Xstruct dirent				/* data from getdents()/readdir() */
X	{
X	long		d_ino;		/* inode number of entry */
X	off_t		d_off;		/* offset of disk directory entry */
X	unsigned short	d_reclen;	/* length of this record */
X	char		d_name[1];	/* name of file */	/* non-POSIX */
X	};
X
X/* The following nonportable ugliness could have been avoided by defining
X   DIRENTSIZ and DIRENTBASESIZ to also have (struct dirent *) arguments. */
X#define	DIRENTBASESIZ		(((struct dirent *)0)->d_name \
X				- (char *)&((struct dirent *)0)->d_ino)
X#define	DIRENTSIZ( namlen )	((DIRENTBASESIZ + sizeof(long) + (namlen)) \
X				/ sizeof(long) * sizeof(long))
X
X/* DAG -- the following was moved from <dirent.h>, which was the wrong place */
X#define	MAXNAMLEN	512		/* maximum filename length */
X
X#ifndef NAME_MAX
X#define	NAME_MAX	(MAXNAMLEN - 1)	/* DAG -- added for POSIX */
X#endif
SHAR_EOF
chmod 0444 dirlib/sys.dirent.h || echo "restore of dirlib/sys.dirent.h fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/telldir.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/telldir.c &&
X/*
X	telldir -- report directory stream position
X
X	last edit:	25-Apr-1987	D A Gwyn
X
X	NOTE:	4.nBSD directory compaction makes seekdir() & telldir()
X		practically impossible to do right.  Avoid using them!
X*/
X
X#include	<sys/errno.h>
X#include	<sys/types.h>
X#include	<dirent.h>
X
Xextern off_t	lseek();
X
Xextern int	errno;
X
X#ifndef SEEK_CUR
X#define	SEEK_CUR	1
X#endif
X
Xoff_t
Xtelldir( dirp )				/* return offset of next entry */
X	DIR	*dirp;			/* stream from opendir() */
X	{
X	if ( dirp == NULL || dirp->dd_buf == NULL )
X		{
X		errno = EFAULT;
X		return -1;		/* invalid pointer */
X		}
X
X	if ( dirp->dd_loc < dirp->dd_size )	/* valid index */
X		return ((struct dirent *)&dirp->dd_buf[dirp->dd_loc])->d_off;
X	else				/* beginning of next directory block */
X		return lseek( dirp->dd_fd, (off_t)0, SEEK_CUR );
X	}
SHAR_EOF
chmod 0444 dirlib/telldir.c || echo "restore of dirlib/telldir.c fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/testdir.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/testdir.c &&
X/*
X	testdir -- basic test for C library directory access routines
X
X	last edit:	25-Apr-1987	D A Gwyn
X*/
X
X#include	<sys/types.h>
X#include	<stdio.h>
X#include	<dirent.h>
X
Xextern void	exit();
Xextern int	strcmp();
X
Xmain( argc, argv )
X	int			argc;
X	register char		**argv;
X	{
X	register DIR		*dirp;
X	register struct dirent	*dp;
X	int			nerrs = 0;	/* total not found */
X
X	if ( (dirp = opendir( "." )) == NULL )
X		{
X		(void)fprintf( stderr, "Cannot open \".\" directory\n" );
X		exit( 1 );
X		}
X
X	while ( --argc > 0 )
X		{
X		++argv;
X
X		while ( (dp = readdir( dirp )) != NULL )
X			if ( strcmp( dp->d_name, *argv ) == 0 )
X				{
X				(void)printf( "\"%s\" found.\n", *argv );
X				break;
X				}
X
X		if ( dp == NULL )
X			{
X			(void)printf( "\"%s\" not found.\n", *argv );
X			++nerrs;
X			}
X
X		rewinddir( dirp );
X		}
X
X	(void)closedir( dirp );
X	exit( nerrs );
X	}
SHAR_EOF
chmod 0444 dirlib/testdir.c || echo "restore of dirlib/testdir.c fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/vmsdir.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/vmsdir.h &&
X/*
X * Files-11 Ver. 2 directory structure (VMS V4.x - long names)
X */
X#ifndef DIR$K_LENGTH
X
X#define	DIR$C_FID	0
X#define	DIR$C_LINKNAME	1
X#define	DIR$K_LENGTH	6
X#define	DIR$C_LENGTH	6
X#define	DIR$S_DIRDEF	6
X#define	DIR$W_SIZE	0
X#define	DIR$W_VERLIMIT	2
X#define	DIR$B_FLAGS	4
X#define	DIR$S_TYPE	3
X#define	DIR$V_TYPE	0
X#define	DIR$V_NEXTREC	6
X#define	DIR$V_PREVREC	7
X#define	DIR$B_NAMECOUNT	5
X#define	DIR$S_NAME	80
X#define	DIR$T_NAME	6
X
X#define	DIR$K_VERSION	8
X#define	DIR$C_VERSION	8
X#define	DIR$S_DIRDEF1	8
X#define	DIR$W_VERSION	0
X#define	DIR$S_FID	6
X#define	DIR$W_FID	2
X#define	DIR$W_FID_NUM	2
X#define	DIR$W_FID_SEQ	4
X#define	DIR$W_FID_RVN	6
X#define	DIR$B_FID_RVN	6
X#define	DIR$B_FID_NMX	7
X
X#define	DIR$S_DIRDEF2	1
X#define	DIR$T_LINKNAME	0
X
Xtypedef struct dir$_name {
X/*  short dir$w_size;		/* if you read with RMS, it eats this... */
X  short dir$w_verlimit;			/* maximum number of versions */
X  union {
X    unsigned char dir_b_flags;
X#define dir$b_flags dir__b_flags.dir_b_flags
X    struct {
X      unsigned char dir_v_type: DIR$S_TYPE;
X#define dir$v_type dir__b_flags.dir___b_flags.dir_v_type
X      unsigned char: 3;
X      unsigned char dir_v_nextrec: 1;
X#define dir$v_nextrec dir__b_flags.dir___b_flags.dir_v_nextrec
X      unsigned char dir_v_prevrec: 1;
X#define dir$v_prevrec dir__b_flags.dir___b_flags.dir_v_prevrec
X    } dir___b_flags;
X  } dir__b_flags;
X  unsigned char dir$b_namecount;
X  char dir$t_name[];
X} dir$_dirdef;		/* only the fixed first part */
X
Xtypedef struct dir$_version {
X  short dir$w_version;
X  short dir$w_fid_num;
X  short dir$w_fid_seq;
X  union {
X    short dir_w_fid_rvn;
X#define dir$w_fid_rvn dir__w_fid_rvn.dir_w_fid_rvn
X    struct {
X      char dir_b_fid_rvn;
X#define dir$b_fid_rvn dir__w_fid_rvn.dir___w_fid_rvn.dir_b_fid_rvn
X      char dir_b_fid_nmx;
X#define dir$b_fid_nmx dir__w_fid_rvn.dir___w_fid_rvn.dir_b_fid_nmx
X    } dir___w_fid_rvn;
X  } dir__w_fid_rvn;
X} dir$_dirdef1;		/* one for each version of the file */
X
Xtypedef
Xstruct dir$_linkname {
X  char    dir$t_linkname[];
X} dir$_dirdef2;
X
X#endif
X/*
X	<dir.h> -- definitions for 4.2BSD-compatible directory access
X
X	last edit:	09-Jul-1983	D A Gwyn
X*/
X
X#ifndef FAB$C_BID
X#	include <fab.h>
X#endif
X#ifndef NAM$C_BID
X#	include <nam.h>
X#endif
X#ifndef RMS$_SUC
X#	include <rmsdef.h>
X#endif
X
X#define DIRBLKSIZ	512		/* size of directory block */
X#define MAXNAMLEN	(DIR$S_NAME + 7) /* 80 plus room for version #.  */
X#define MAXFULLSPEC	NAM$C_MAXRSS /* Maximum full spec */
X
Xstruct direct				/* data from readdir() */
X	{
X	long		d_ino;		/* inode number of entry */
X	unsigned short	d_reclen;	/* length of this record */
X	unsigned short	d_namlen;	/* length of string in d_name */
X	char		d_name[MAXNAMLEN+1];	/* name of file */
X	};
X
Xtypedef struct
X	{
X	int	dd_fd;			/* file descriptor */
X	int	dd_loc;			/* offset in block */
X	int	dd_size;		/* amount of valid data */
X	char	dd_buf[DIRBLKSIZ];	/* directory block */
X	}	DIR;			/* stream data from opendir() */
X
Xextern DIR		*opendir();
Xextern struct direct	*readdir();
Xextern long		telldir();
Xextern void		seekdir();
Xextern void		closedir();
X
X#define rewinddir( dirp )	seekdir( dirp, 0L )
X
SHAR_EOF
chmod 0644 dirlib/vmsdir.h || echo "restore of dirlib/vmsdir.h fails"
mkdir dirlib >/dev/null 2>&1
echo "x - extracting dirlib/vmsdir.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > dirlib/vmsdir.c &&
X/* Interfaces to system-dependent kernel and library entries.
SHAR_EOF
echo "End of part 1"
echo "File dirlib/vmsdir.c is continued in part 2"
echo "2" > s2_seq_.tmp
exit 0
-- 
=====================			Reuters Ltd PLC, 
Tel: +44 628 891313 x. 212		 Westthorpe House,
UUCP:     fox%marlow.uucp@idec.stc.co.uk  Little Marlow,
					   Bucks, England SL7 3RQ