Path: utzoo!utgpu!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!rutgers!elbereth.rutgers.edu!dorm.rutgers.edu!dpz From: dpz@dorm.rutgers.edu (David P. Zimmerman) Newsgroups: comp.bugs.4bsd Subject: Re: 4.3 Tahoe rrestore bug Keywords: 4.3,tahoe,restore Message-ID: Date: 21 Nov 88 00:26:14 GMT References: <23669@pprg.unm.edu> Organization: Rutgers University Lines: 769 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 #include ! #include ! #include #include /* * Flags */ --- 8,42 ---- #include #include ! #include ! #include ! #include ! #include #include + #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