[comp.bugs.4bsd] 4.3 Tahoe rrestore bug

cyrus@pprg.unm.edu (Tait Cyrus) (11/21/88)

I am trying to get the  4.3 Tahoe dump/restore/rmt stuff to run
uder SunOS 3.5.  rdump seems to work fine, but rrestore does not.

In dirs.c around line 108 there is the code:
		if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) {
			(void) fclose(df);
			dirp = opendir(dirfile);
			if (dirp == NULL) 
				perror("opendir");
			if (mf != NULL)
				(void) fclose(mf);
			i = dirlookup(".");

Two problems I see here.  
	1) dirfile is NOT a directory but a file (created by rrestore)
	2) If dirp == NULL, then in addtion to  the perror call, exit
	   should also be called.

My question then is why is the code trying to open a directory that
does NOT exist.

Thanks for any help/suggestions/bug fixes etc...

---
    @__________@    W. Tait Cyrus   (505) 277-0806
   /|         /|    University of New Mexico
  / |        / |    Dept of ECE - Parallel Processing Research Group
 @__|_______@  |    Albuquerque, New Mexico 87131
 |  |       |  |
 |  |  hc   |  |    e-mail:
 |  @.......|..@       cyrus@pprg.unm.edu
 | /        | /
 @/_________@/

dpz@dorm.rutgers.edu (David P. Zimmerman) (11/21/88)

In article <23669@pprg.unm.edu> cyrus@pprg.unm.edu (Tait Cyrus) writes:

> I am trying to get the  4.3 Tahoe dump/restore/rmt stuff to run
> uder SunOS 3.5.  rdump seems to work fine, but rrestore does not.

Well, that doesn't make it a bug, does it?  BSD4.3 and SunOS 3.x are
different beasts, right down to the opendir() library call.  Here's my
fixes to the 4.3BSD [r]restore to make it work under SunOS3.x (and
also on Celerity 1200s and Pyramids).  You can see what I've changed,
and a bit of examination will explain why (RTFSC :-).

						David

:	This is a shell archive.
:	Remove everything above this line and
:	run the following text with /bin/sh to create:
:	README
:	Makefile.diff
:	dirs.c.diff
:	dumprestore.h.diff
:	interactive.c.diff
:	main.c.diff
:	restore.h.diff
:	tape.c.diff
:	opendir.c
:	telldir.c
: This archive created: Sun Nov 20 19:24:15 1988
cat << 'SHAR_EOF' > README
dpz's changes to the standard 4.3BSD restore for compatible Sun SunOS
3.x, Sun SunOS 4.0, Pyramid OSx4.1, and Celerity 3.4 restores:

	- replacing various #include files with equivalents
	- adding DIRBLKSIZ #define, making it largest DEV_BSIZE of all
	  architectures
	- copying DIR struct definition to RST_DIR, changing char
	  *dd_buf in it to char dd_buf[DIRBLKSIZ], changing all
	  routines that use DIR to use RST_DIR
	- copying 4.3 opendir() to rst_4_3_opendir() and changing
	  appropriate routines to call that instead of opendir()
	- copying 4.3 telldir() to rst_4_3_telldir(), changing
	  appropriate routines to call that instead of telldir()

	- compile on Sun SunOS 4.0 with -DSUNOS4 in Makefile and link
	  statically
	- generalizing "struct direct" to a typedef, since SunOS 4.0
	  has a field in it that doesn't exist on disk

	- adding/modifying /usr/include/protocols/dumprestore.h:
		- have TP_BSIZE equal the largest disk block size
		  across all three architectures (2048 in this case)
		- adjusting NTREC and HIGHDENSITYTREC down to balance
		  my higher TP_BSIZE
		- adjusting DUMPOUTFMT and DUMPINFMT to have the 
		  highest number across all three architectures for %XXs
		- adding CARTRIDGETREC for some reason

Frills:
	- modifying Makefile so ${CFLAGS} is included in final .o combining
	- adding Gary Winiger's epoch dump date mod (his comments below)
	- adding Gary Winiger's interactive.c seg violation mods (cmts below)

From: gww@elxsi.UUCP (Gary Winiger)

When restore lists the dates the the dump encompases such as with the
-t option, it will list the epoch date for the from date of a level 0
dump.

From: gww@elxsi.UUCP (Gary Winiger)

When running /etc/restore in interactive mode, any attempt to
reference a subdirectory will cause a segmentation violation on
systems that do not permit dereferencing a NULL pointer.
SHAR_EOF
cat << 'SHAR_EOF' > Makefile.diff
*** Makefile.ORIG	Sat Jan  9 16:27:02 1988
--- Makefile	Sat Jan  9 16:26:58 1988
***************
*** 16,22 ****
  	cc ${LDFLAGS} ${CFLAGS} -o restore ${OBJS} tape.o
  
  rrestore: ${OBJS} rtape.o dumprmt.o
! 	cc ${LDFLAGS} -o rrestore ${OBJS} rtape.o dumprmt.o
  
  rtape.o: tape.c
  	cp tape.c rtape.c
--- 16,22 ----
  	cc ${LDFLAGS} ${CFLAGS} -o restore ${OBJS} tape.o
  
  rrestore: ${OBJS} rtape.o dumprmt.o
! 	cc ${LDFLAGS} ${CFLAGS} -o rrestore ${OBJS} rtape.o dumprmt.o
  
  rtape.o: tape.c
  	cp tape.c rtape.c
SHAR_EOF
cat << 'SHAR_EOF' > dirs.c.diff
*** dirs.c.ORIG	Sat Jan  9 16:27:02 1988
--- dirs.c	Wed Aug 17 17:39:13 1988
***************
*** 43,53 ****
   */
  static daddr_t	seekpt;
  static FILE	*df, *mf;
! static DIR	*dirp;
  static char	dirfile[32] = "#";	/* No file */
  static char	modefile[32] = "#";	/* No file */
  extern ino_t	search();
! struct direct 	*rst_readdir();
  extern void 	rst_seekdir();
  
  /*
--- 43,54 ----
   */
  static daddr_t	seekpt;
  static FILE	*df, *mf;
! static RST_DIR	*dirp;
  static char	dirfile[32] = "#";	/* No file */
  static char	modefile[32] = "#";	/* No file */
  extern ino_t	search();
! RST_DIR		*rst_4_3_opendir();
! UNIXDIRECT 	*rst_readdir();
  extern void 	rst_seekdir();
  
  /*
***************
*** 71,77 ****
  	register int i;
  	register struct dinode *ip;
  	struct inotab *itp;
! 	struct direct nulldir;
  	int putdir(), null();
  
  	vprintf(stdout, "Extract directories from tape\n");
--- 72,78 ----
  	register int i;
  	register struct dinode *ip;
  	struct inotab *itp;
! 	UNIXDIRECT nulldir;
  	int putdir(), null();
  
  	vprintf(stdout, "Extract directories from tape\n");
***************
*** 105,111 ****
  		ip = curfile.dip;
  		if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) {
  			(void) fclose(df);
! 			dirp = opendir(dirfile);
  			if (dirp == NULL)
  				perror("opendir");
  			if (mf != NULL)
--- 106,112 ----
  		ip = curfile.dip;
  		if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) {
  			(void) fclose(df);
! 			dirp = rst_4_3_opendir(dirfile);
  			if (dirp == NULL)
  				perror("opendir");
  			if (mf != NULL)
***************
*** 144,150 ****
  	long (*todo)();
  {
  	register struct inotab *itp;
! 	register struct direct *dp;
  	register struct entry *np;
  	int namelen;
  	daddr_t bpt;
--- 145,151 ----
  	long (*todo)();
  {
  	register struct inotab *itp;
! 	register UNIXDIRECT *dp;
  	register struct entry *np;
  	int namelen;
  	daddr_t bpt;
***************
*** 182,188 ****
  	else
  		fprintf(stderr, "Warning: `..' missing from directory %s\n",
  			pname);
! 	bpt = telldir(dirp);
  	/*
  	 * a zero inode signals end of directory
  	 */
--- 183,189 ----
  	else
  		fprintf(stderr, "Warning: `..' missing from directory %s\n",
  			pname);
! 	bpt = rst_4_3_telldir(dirp);
  	/*
  	 * a zero inode signals end of directory
  	 */
***************
*** 197,203 ****
  			rst_seekdir(dirp, bpt, itp->t_seekpt);
  		}
  		dp = rst_readdir(dirp);
! 		bpt = telldir(dirp);
  	}
  	if (dp == NULL)
  		fprintf(stderr, "corrupted directory: %s.\n", locname);
--- 198,204 ----
  			rst_seekdir(dirp, bpt, itp->t_seekpt);
  		}
  		dp = rst_readdir(dirp);
! 		bpt = rst_4_3_telldir(dirp);
  	}
  	if (dp == NULL)
  		fprintf(stderr, "corrupted directory: %s.\n", locname);
***************
*** 246,252 ****
  	ino_t	inum;
  	char	*cp;
  {
! 	register struct direct *dp;
  	register struct inotab *itp;
  	int len;
  
--- 247,253 ----
  	ino_t	inum;
  	char	*cp;
  {
! 	register UNIXDIRECT *dp;
  	register struct inotab *itp;
  	int len;
  
***************
*** 270,279 ****
  	char *buf;
  	int size;
  {
! 	struct direct cvtbuf;
  	register struct odirect *odp;
  	struct odirect *eodp;
! 	register struct direct *dp;
  	long loc, i;
  	extern int Bcvt;
  
--- 271,280 ----
  	char *buf;
  	int size;
  {
! 	UNIXDIRECT cvtbuf;
  	register struct odirect *odp;
  	struct odirect *eodp;
! 	register UNIXDIRECT *dp;
  	long loc, i;
  	extern int Bcvt;
  
***************
*** 286,292 ****
  			}
  	} else {
  		for (loc = 0; loc < size; ) {
! 			dp = (struct direct *)(buf + loc);
  			if (Bcvt) {
  				swabst("l2s", (char *) dp);
  			}
--- 287,293 ----
  			}
  	} else {
  		for (loc = 0; loc < size; ) {
! 			dp = (UNIXDIRECT *)(buf + loc);
  			if (Bcvt) {
  				swabst("l2s", (char *) dp);
  			}
***************
*** 314,324 ****
   * add a new directory entry to a file.
   */
  putent(dp)
! 	struct direct *dp;
  {
  	dp->d_reclen = DIRSIZ(dp);
  	if (dirloc + dp->d_reclen > DIRBLKSIZ) {
! 		((struct direct *)(dirbuf + prev))->d_reclen =
  		    DIRBLKSIZ - prev;
  		(void) fwrite(dirbuf, 1, DIRBLKSIZ, df);
  		dirloc = 0;
--- 315,325 ----
   * add a new directory entry to a file.
   */
  putent(dp)
! 	UNIXDIRECT *dp;
  {
  	dp->d_reclen = DIRSIZ(dp);
  	if (dirloc + dp->d_reclen > DIRBLKSIZ) {
! 		((UNIXDIRECT *)(dirbuf + prev))->d_reclen =
  		    DIRBLKSIZ - prev;
  		(void) fwrite(dirbuf, 1, DIRBLKSIZ, df);
  		dirloc = 0;
***************
*** 334,340 ****
  flushent()
  {
  
! 	((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev;
  	(void) fwrite(dirbuf, (int)dirloc, 1, df);
  	seekpt = ftell(df);
  	dirloc = 0;
--- 335,341 ----
  flushent()
  {
  
! 	((UNIXDIRECT *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev;
  	(void) fwrite(dirbuf, (int)dirloc, 1, df);
  	seekpt = ftell(df);
  	dirloc = 0;
***************
*** 342,348 ****
  
  dcvt(odp, ndp)
  	register struct odirect *odp;
! 	register struct direct *ndp;
  {
  
  	bzero((char *)ndp, (long)(sizeof *ndp));
--- 343,349 ----
  
  dcvt(odp, ndp)
  	register struct odirect *odp;
! 	register UNIXDIRECT *ndp;
  {
  
  	bzero((char *)ndp, (long)(sizeof *ndp));
***************
*** 354,360 ****
  
  /*
   * Seek to an entry in a directory.
!  * Only values returned by ``telldir'' should be passed to rst_seekdir.
   * This routine handles many directories in a single file.
   * It takes the base of the directory in the file, plus
   * the desired seek offset into it.
--- 355,361 ----
  
  /*
   * Seek to an entry in a directory.
!  * Only values returned by ``rst_4_3_telldir'' should be passed to rst_seekdir.
   * This routine handles many directories in a single file.
   * It takes the base of the directory in the file, plus
   * the desired seek offset into it.
***************
*** 361,371 ****
   */
  void
  rst_seekdir(dirp, loc, base)
! 	register DIR *dirp;
  	daddr_t loc, base;
  {
  
! 	if (loc == telldir(dirp))
  		return;
  	loc -= base;
  	if (loc < 0)
--- 362,372 ----
   */
  void
  rst_seekdir(dirp, loc, base)
! 	register RST_DIR *dirp;
  	daddr_t loc, base;
  {
  
! 	if (loc == rst_4_3_telldir(dirp))
  		return;
  	loc -= base;
  	if (loc < 0)
***************
*** 379,389 ****
  /*
   * get next entry in a directory.
   */
! struct direct *
  rst_readdir(dirp)
! 	register DIR *dirp;
  {
! 	register struct direct *dp;
  
  	for (;;) {
  		if (dirp->dd_loc == 0) {
--- 380,390 ----
  /*
   * get next entry in a directory.
   */
! UNIXDIRECT *
  rst_readdir(dirp)
! 	register RST_DIR *dirp;
  {
! 	register UNIXDIRECT *dp;
  
  	for (;;) {
  		if (dirp->dd_loc == 0) {
***************
*** 398,404 ****
  			dirp->dd_loc = 0;
  			continue;
  		}
! 		dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc);
  		if (dp->d_reclen == 0 ||
  		    dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) {
  			dprintf(stderr, "corrupted directory: bad reclen %d\n",
--- 399,405 ----
  			dirp->dd_loc = 0;
  			continue;
  		}
! 		dp = (UNIXDIRECT *)(dirp->dd_buf + dirp->dd_loc);
  		if (dp->d_reclen == 0 ||
  		    dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) {
  			dprintf(stderr, "corrupted directory: bad reclen %d\n",
***************
*** 417,426 ****
  	}
  }
  
  /*
   * Simulate the opening of a directory
   */
! DIR *
  rst_opendir(name)
  	char *name;
  {
--- 418,431 ----
  	}
  }
  
+ #include "opendir.c"
+ 
+ #include "telldir.c"
+ 
  /*
   * Simulate the opening of a directory
   */
! RST_DIR *
  rst_opendir(name)
  	char *name;
  {
SHAR_EOF
cat << 'SHAR_EOF' > dumprestore.h.diff
*** dumprestore.h.ORIG	Mon Apr 18 21:33:00 1988
--- dumprestore.h	Tue Aug 16 17:08:45 1988
***************
*** 13,26 ****
   * NTREC is the number of TP_BSIZE blocks that are written
   * in each tape record. HIGHDENSITYTREC is the number of
   * TP_BSIZE blocks that are written in each tape record on
!  * 6250 BPI or higher density tapes.
   *
   * TP_NINDIR is the number of indirect pointers in a TS_INODE
   * or TS_ADDR record. Note that it must be a power of two.
   */
! #define TP_BSIZE	1024
! #define NTREC   	10
! #define HIGHDENSITYTREC	32
  #define TP_NINDIR	(TP_BSIZE/2)
  
  #define TS_TAPE 	1
--- 13,29 ----
   * NTREC is the number of TP_BSIZE blocks that are written
   * in each tape record. HIGHDENSITYTREC is the number of
   * TP_BSIZE blocks that are written in each tape record on
!  * 6250 BPI or higher density tapes.  CARTRIDGETREC is the
!  * number of TP_BSIZE blocks that are written in each tape
!  * record on cartridge tapes.
   *
   * TP_NINDIR is the number of indirect pointers in a TS_INODE
   * or TS_ADDR record. Note that it must be a power of two.
   */
! #define TP_BSIZE	2048
! #define NTREC   	5
! #define HIGHDENSITYTREC	16
! #define CARTRIDGETREC	31
  #define TP_NINDIR	(TP_BSIZE/2)
  
  #define TS_TAPE 	1
***************
*** 52,57 ****
  
  #define spcl u_spcl.s_spcl
  
! #define	DUMPOUTFMT	"%-16s %c %s"		/* for printf */
  						/* name, incno, ctime(date) */
! #define	DUMPINFMT	"%16s %c %[^\n]\n"	/* inverse for scanf */
--- 55,60 ----
  
  #define spcl u_spcl.s_spcl
  
! #define	DUMPOUTFMT	"%-22s %c %s"		/* for printf */
  						/* name, incno, ctime(date) */
! #define	DUMPINFMT	"%22s %c %[^\n]\n"	/* inverse for scanf */
SHAR_EOF
cat << 'SHAR_EOF' > interactive.c.diff
*** interactive.c.ORIG	Sat Jan  9 16:27:01 1988
--- interactive.c	Tue Jul 12 17:00:11 1988
***************
*** 398,409 ****
  	register struct arglist *ap;
  {
  	static struct afile single;
  	int size;
  
  	ap->head = ap->last = (struct afile *)0;
  	size = expand(arg, 0, ap);
  	if (size == 0) {
! 		single.fnum = lookupname(arg)->e_ino;
  		single.fname = savename(arg);
  		ap->head = &single;
  		ap->last = ap->head + 1;
--- 398,411 ----
  	register struct arglist *ap;
  {
  	static struct afile single;
+ 	struct entry *ep;
  	int size;
  
  	ap->head = ap->last = (struct afile *)0;
  	size = expand(arg, 0, ap);
  	if (size == 0) {
! 	        ep = lookupname(arg);
! 		single.fnum = ep != NIL ? ep->e_ino : 0;
  		single.fname = savename(arg);
  		ap->head = &single;
  		ap->last = ap->head + 1;
***************
*** 423,432 ****
  	int		count, size;
  	char		dir = 0;
  	char		*rescan = 0;
! 	DIR		*dirp;
  	register char	*s, *cs;
  	int		sindex, rindex, lindex;
! 	struct direct	*dp;
  	register char	slash; 
  	register char	*rs; 
  	register char	c;
--- 425,434 ----
  	int		count, size;
  	char		dir = 0;
  	char		*rescan = 0;
! 	RST_DIR		*dirp;
  	register char	*s, *cs;
  	int		sindex, rindex, lindex;
! 	UNIXDIRECT	*dp;
  	register char	slash; 
  	register char	*rs; 
  	register char	c;
***************
*** 571,577 ****
   * Construct a matched name.
   */
  addg(dp, as1, as3, ap)
! 	struct direct	*dp;
  	char		*as1, *as3;
  	struct arglist	*ap;
  {
--- 573,579 ----
   * Construct a matched name.
   */
  addg(dp, as1, as3, ap)
! 	UNIXDIRECT	*dp;
  	char		*as1, *as3;
  	struct arglist	*ap;
  {
***************
*** 609,618 ****
  	char *basename;
  {
  	register struct afile *fp;
! 	register struct direct *dp;
  	static struct arglist alist = { 0, 0, 0, 0, "ls" };
  	struct afile single;
! 	DIR *dirp;
  
  	if ((dirp = rst_opendir(name)) == NULL) {
  		single.fnum = ino;
--- 611,620 ----
  	char *basename;
  {
  	register struct afile *fp;
! 	register UNIXDIRECT *dp;
  	static struct arglist alist = { 0, 0, 0, 0, "ls" };
  	struct afile single;
! 	RST_DIR *dirp;
  
  	if ((dirp = rst_opendir(name)) == NULL) {
  		single.fnum = ino;
SHAR_EOF
cat << 'SHAR_EOF' > main.c.diff
*** main.c.ORIG	Sat Jan  9 16:27:00 1988
--- main.c	Tue Jul 12 16:39:19 1988
***************
*** 58,64 ****
--- 58,66 ----
  	char *inputdev = "/dev/rmt8";
  	char *symtbl = "./restoresymtable";
  	char name[MAXPATHLEN];
+ #ifndef SUNOS4
  	int (*signal())();
+ #endif
  	extern int onintr();
  
  	if (signal(SIGINT, onintr) == SIG_IGN)
SHAR_EOF
cat << 'SHAR_EOF' > restore.h.diff
*** restore.h.ORIG	Sat Jan  9 16:27:01 1988
--- restore.h	Tue Jul 12 17:02:25 1988
***************
*** 8,17 ****
  
  #include <stdio.h>
  #include <sys/param.h>
! #include <sys/inode.h>
! #include <sys/fs.h>
  #include <sys/dir.h>
  
  /*
   * Flags
   */
--- 8,42 ----
  
  #include <stdio.h>
  #include <sys/param.h>
! #include <sys/time.h>
! #include <sys/vnode.h>
! #include <ufs/inode.h>
! #include <ufs/fs.h>
  #include <sys/dir.h>
  
+ #ifdef SUNOS4
+ typedef struct {
+ 	u_long	d_fileno;		/* file number of entry */
+ 	u_short	d_reclen;		/* length of this record */
+ 	u_short	d_namlen;		/* length of string in d_name */
+ 	char	d_name[MAXNAMLEN + 1];	/* name (up to MAXNAMLEN + 1) */
+ } UNIXDIRECT;
+ #else
+ typedef struct direct UNIXDIRECT;
+ #endif
+ 
+ #define DIRBLKSIZ       2048
+ 
+ typedef struct _rstdirdesc {
+         int     dd_fd;
+         long    dd_loc;
+         long    dd_size;
+ 	long	dd_bbase;
+ 	long	dd_entno;
+ 	long	dd_bsize;
+         char    dd_buf[DIRBLKSIZ];
+ } RST_DIR;
+ 
  /*
   * Flags
   */
***************
*** 76,83 ****
  extern char *flagvalues();
  extern ino_t lowerbnd();
  extern ino_t upperbnd();
! extern DIR *rst_opendir();
! extern struct direct *rst_readdir();
  #define NIL ((struct entry *)(0))
  /*
   * Constants associated with entry structs
--- 101,108 ----
  extern char *flagvalues();
  extern ino_t lowerbnd();
  extern ino_t upperbnd();
! extern RST_DIR *rst_opendir();
! extern UNIXDIRECT *rst_readdir();
  #define NIL ((struct entry *)(0))
  /*
   * Constants associated with entry structs
SHAR_EOF
cat << 'SHAR_EOF' > tape.c.diff
*** tape.c.ORIG	Sat Jan  9 16:27:03 1988
--- tape.c	Sun May 29 19:09:30 1988
***************
*** 153,159 ****
  	}
  	if (vflag || command == 't') {
  		fprintf(stdout, "Dump   date: %s", ctime(&spcl.c_date));
! 		fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate));
  	}
  	dumptime = spcl.c_ddate;
  	dumpdate = spcl.c_date;
--- 153,161 ----
  	}
  	if (vflag || command == 't') {
  		fprintf(stdout, "Dump   date: %s", ctime(&spcl.c_date));
! 		fprintf(stdout, "Dumped from: %s",
! 			(spcl.c_ddate == (time_t)0)
! 			? "the epoch\n" : ctime(&spcl.c_ddate));
  	}
  	dumptime = spcl.c_ddate;
  	dumpdate = spcl.c_date;
SHAR_EOF
cat << 'SHAR_EOF' > opendir.c
/*
 * Copyright (c) 1983 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/*
 * open a directory.
 */
RST_DIR *
rst_4_3_opendir(name)
	char *name;
{
	register RST_DIR *dirp;
	register int fd;

	if ((fd = open(name, 0)) == -1)
		return NULL;
	if ((dirp = (RST_DIR *)malloc(sizeof(RST_DIR))) == NULL) {
		close (fd);
		return NULL;
	}
	dirp->dd_fd = fd;
	dirp->dd_loc = 0;
	return dirp;
}
SHAR_EOF
cat << 'SHAR_EOF' > telldir.c
/*
 * Copyright (c) 1983 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/*
 * return a pointer into a directory
 */
long
rst_4_3_telldir(dirp)
	RST_DIR *dirp;
{
	extern long lseek();

	return (lseek(dirp->dd_fd, 0L, 1) - dirp->dd_size + dirp->dd_loc);
}
SHAR_EOF
:	End of shell archive
exit 0
-- 
David P. Zimmerman, the Dorm Networking Pilot Project, the UUCP Project, etc
dpz@dorm.rutgers.edu          rutgers!dpz          dpzimmerman@zodiac.bitnet

vixie@decwrl.dec.com (Paul Vixie) (11/21/88)

# 	1) dirfile is NOT a directory but a file (created by rrestore)

I don't know about the rest of your article, but this I can answer: it knows
it's trying to open a dirfile, it just copied it in from the tape.  The ndir(3)
routines don't care if it's really a directory, just as long as the format is
compatible.  The routines are read-only since they run in user-mode; if you
point 'em at a file that happens to look like a directory, they work fine.

(on my 4.3bsd machine:)
===
vixie@beast-> /bin/cp . foo
cp: .: Is a directory (copying as plain file).
vixie@beast-> /bin/ls -f foo
.            .rhosts      .profile     .mh_profile  .uwmrc       foo
..           ueg          .joverc      .signature   ftpd
Etc          .cshrc       .mailrc      .Xres        routed
===
-- 
Paul Vixie
Work:    vixie@decwrl.dec.com    decwrl!vixie    +1 415 853 6600
Play:    paul@vixie.sf.ca.us     vixie!paul      +1 415 864 7013

guy@auspex.UUCP (Guy Harris) (11/23/88)

># 	1) dirfile is NOT a directory but a file (created by rrestore)
>
>I don't know about the rest of your article, but this I can answer: it knows
>it's trying to open a dirfile, it just copied it in from the tape.  The ndir(3)
>routines don't care if it's really a directory, just as long as the format is
>compatible.  The routines are read-only since they run in user-mode; if you
>point 'em at a file that happens to look like a directory, they work fine.

Note that under SunOS:

	1) The directory library routines use "getdirentries()" in 2.x
	   and 3.x releases, and "getdents()" in 4.0.

	2) Those routines transform the contents of the file; they are
	   not equivalent to "read()" on a directory file.

	3) I don't know whether those routines work on non-directory
	   files.

	4) In any case, "opendir()" returns an error when you try to
	   open a file that isn't a directory.

The bottom line is that the format isn't compatible, so you can't point
the directory library routines at a non-directory, even if it happens to
look like one.

The SunOS version of "restore" contains what amounts to a copy of the
"old" directory library (the one that directly reads the directory file).

vixie@decwrl.dec.com (Paul Vixie) (11/24/88)

In article <486@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
# [...]
# Note that under SunOS:
# 
# 	1) The directory library routines use "getdirentries()" in 2.x
# 	   and 3.x releases, and "getdents()" in 4.0.
# [...]
# The SunOS version of "restore" contains what amounts to a copy of the
# "old" directory library (the one that directly reads the directory file).

Thanks, Guy.  It looks like you're *still* the best Usenet info source about
SunOS even though you don't post from Sun anymore.

One question, if you (or anyone else) knows: why was this change made?  I
know Sun would never, ever make a gratuitous, incompatible change to the
semantics of a library routine.  What was the motive (this time)?
-- 
Paul Vixie
Work:    vixie@decwrl.dec.com    decwrl!vixie    +1 415 853 6600
Play:    paul@vixie.sf.ca.us     vixie!paul      +1 415 864 7013

guy@auspex.UUCP (Guy Harris) (11/26/88)

>One question, if you (or anyone else) knows: why was this change made?

Which change?  The change to use "getdirentries()" or the change to use
"getdents()"?

The former change was made so that directory reads could be
distinguished from plain reads of a directory file.  Directory reads
should return information in some standard format, regardless of how the
actual directory file is represented. 

An alternative would have been to make the "read" system call, when
executed on a directory, act like "getdirentries()" or "getdents()";
this would actually have broken more existing binaries than adding
"getdirentries()" (at least with a new system call, old binaries could
continue to read UFS directories, although they might fall apart on
directories read over NFS, or directories read from a V7/S5 file system,
or...).  You have to return a "directory cookie" with each directory
entry, so that the system can give you the "directory cookie" when you
do a "telldir"; you can't assume that the underlying directory works
like a UFS directory (i.e., that you can calculate how much some
internal seek pointer has moved, based purely on the data you got back
from the "read"). 

The latter change was made because "getdents()" has a better interface
than "getdirentries()"; instead of returning one directory "cookie" that
gives an "address" within the directory, it returns one for each entry,
so that the software doesn't have to assume it "knows" how directory
cookies work.  The NFS "readdir" operation resembles "getdents()" more
than it resembles "getdirentries()" (for that reason). 

gwyn@smoke.BRL.MIL (Doug Gwyn ) (11/26/88)

In article <936@bacchus.dec.com> vixie@decwrl.dec.com (Paul Vixie) writes:
>In article <486@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
># 	1) The directory library routines use "getdirentries()" in 2.x
># 	   and 3.x releases, and "getdents()" in 4.0.
>One question, if you (or anyone else) knows: why was this change made?  I
>know Sun would never, ever make a gratuitous, incompatible change to the
>semantics of a library routine.  What was the motive (this time)?

getdirentries() and getdents() are two system call interfaces that perform
essentially the same function.  One was invented by one organization and
the other by another company.  getdents() is the UNIX SVR3 flavor.

My public-domain implementation of the directory routines isolates all the
UNIX system vagaries in a (possibly emulated) getdents() function; when
getdirentries() is available, the getdents() emulation uses it.  On
systems without sufficient kernel support, the getdents() emulation reads
the directory file directly (two flavors of that: one for the original
UNIX file system and one for the 4.2BSD long-entry-name file system).
The direct-reading scheme would not work right for so-called "transparent"
network file systems unless the network file system maps the directory
entries to the local format.  Most don't do this but some do.

ed@mtxinu.UUCP (Ed Gould) (11/27/88)

># 	1) The directory library routines use "getdirentries()" in 2.x
># 	   and 3.x releases, and "getdents()" in 4.0.

>One question, if you (or anyone else) knows: why was this change made?  I
>know Sun would never, ever make a gratuitous, incompatible change to the
>semantics of a library routine.  What was the motive (this time)?

The change was made for NFS, since the format of a directory on a remote
system can not be assumed to be the same as the local system.  Thus,
the NFS protocol passes directory information around in a standard
format, and it is up to the local system to interpret it in a sensible
way.  The library *interface* is unchanged, and its behaviour when pointed
to a directory is likewise unchanged.  Only when the new library routines
are pointed to a non-directory is anything different.  I don't believe the
4.2 directory routines' behaviour were defined for non-directories.

-- 
Ed Gould                    mt Xinu, 2560 Ninth St., Berkeley, CA  94710  USA
{ucbvax,uunet}!mtxinu!ed    +1 415 644 0146

"I'll fight them as a woman, not a lady.  I'll fight them as an engineer."