- }
-}
-
-checkvol(b, t)
- struct s_spcl *b;
- int t;
-{
-
- if (b->c_volume == t)
- return(1);
- return(0);
-}
-
-readhdr(b)
- struct s_spcl *b;
-{
-
- if (gethead(b) == 0)
- return(0);
- if (checktype(b, TS_TAPE) == 0)
- return(0);
- return(1);
-}
-
-/*
- * read the tape into buf, then return whether or
- * or not it is a header block.
- */
-gethead(buf)
- struct s_spcl *buf;
-{
- union u_ospcl {
- char dummy[TP_BSIZE];
- struct s_ospcl {
- int c_type;
- time_t c_date;
- time_t c_ddate;
- int c_volume;
- daddr_t c_tapea;
- ino_t c_inumber;
- int c_magic;
- int c_checksum;
- struct odinode {
- unsigned short odi_mode;
- short odi_nlink;
- short odi_uid;
- short odi_gid;
- off_t odi_size;
- daddr_t odi_rdev;
- char odi_addr[36];
- time_t odi_atime;
- time_t odi_mtime;
- time_t odi_ctime;
- } c_dinode;
- int c_count;
- char c_addr[TP_NINDIR];
- } s_ospcl;
- } u_ospcl;
-
- if (!cvtflag) {
- readtape((char *)buf);
- if (buf->c_magic != NFS_MAGIC || checksum((int *)buf) == 0)
- return(0);
- return(1);
- }
- readtape((char *)(&u_ospcl.s_ospcl));
- if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC ||
- checksum((int *)(&u_ospcl.s_ospcl)) == 0)
- return(0);
- blkclr((char *)buf, TP_BSIZE);
- buf->c_type = u_ospcl.s_ospcl.c_type;
- buf->c_date = u_ospcl.s_ospcl.c_date;
- buf->c_ddate = u_ospcl.s_ospcl.c_ddate;
- buf->c_volume = u_ospcl.s_ospcl.c_volume;
- buf->c_tapea = u_ospcl.s_ospcl.c_tapea;
- buf->c_inumber = u_ospcl.s_ospcl.c_inumber;
- buf->c_magic = NFS_MAGIC;
- buf->c_checksum = u_ospcl.s_ospcl.c_checksum;
- buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode;
- buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink;
- buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid;
- buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid;
- buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size;
- buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev;
- buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime;
- buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime;
- buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime;
- buf->c_count = u_ospcl.s_ospcl.c_count;
- blkcpy(u_ospcl.s_ospcl.c_addr, buf->c_addr, TP_NINDIR);
- return(1);
-}
-
-/*
- * return whether or not the buffer contains a header block
- */
-ishead(buf)
- struct s_spcl *buf;
-{
-
- if (buf->c_magic != NFS_MAGIC)
- return(0);
- return(1);
-}
-
-checktype(b, t)
- struct s_spcl *b;
- int t;
-{
-
- return(b->c_type == t);
-}
-
-/*
- * read a bit mask from the tape into m.
- */
-readbits(mapp)
- char **mapp;
-{
- register int i;
- char *m;
-
- i = spcl.c_count;
-
- if (*mapp == 0)
- *mapp = (char *)calloc(i, (TP_BSIZE/(NBBY/BITS)));
- m = *mapp;
- while (i--) {
- readtape((char *) m);
- m += (TP_BSIZE/(NBBY/BITS));
- }
- while (gethead(&spcl) == 0)
- ;
-}
-
-checksum(b)
- register int *b;
-{
- register int i, j;
-
- j = sizeof(union u_spcl) / sizeof(int);
- i = 0;
- do
- i += *b++;
- while (--j);
- if (i != CHECKSUM) {
- fprintf(stderr, "Checksum error %o, ino %u\n", i, ino);
- return(0);
- }
- return(1);
-}
-
-/*
- * Check for access into each directory in the pathname of an extracted
- * file and create such a directory if needed in preparation for moving
- * the file to its proper home.
- */
-checkdir(name)
- register char *name;
-{
- register char *cp;
- int i;
-
- for (cp = name; *cp; cp++) {
- if (*cp == '/') {
- *cp = '\0';
- if (access(name, 01) < 0) {
- register int pid, rp;
-
- if ((pid = fork()) == 0) {
- execl("/bin/mkdir", "mkdir", name, 0);
- execl("/usr/bin/mkdir", "mkdir", name, 0);
- fprintf(stderr, "restor: cannot find mkdir!\n");
- done(0);
- }
- while ((rp = wait(&i)) >= 0 && rp != pid)
- ;
- }
- *cp = '/';
- }
- }
-}
-
-setdir(dev)
- char *dev;
-{
- struct fstab *fsp;
-
- if (setfsent() == 0) {
- fprintf(stderr, "Can't open checklist file: %s\n", FSTAB);
- done(1);
- }
- while ((fsp = getfsent()) != 0) {
- if (strcmp(fsp->fs_spec, dev) == 0) {
- fprintf(stderr, "%s mounted on %s\n", dev, fsp->fs_file);
- if (chdir(fsp->fs_file) >= 0)
- return;
- fprintf(stderr, "%s cannot chdir to %s\n",
- fsp->fs_file);
- done(1);
- }
- }
- fprintf(stderr, "%s not mounted\n", dev);
- done(1);
-}
-
-/*
- * These variables are "local" to the following two functions.
- */
-char dirbuf[DIRBLKSIZ];
-long dirloc = 0;
-long prev = 0;
-
-/*
- * add a new directory entry to a file.
- */
-putent(dp, wrtfunc)
- struct direct *dp;
- int (*wrtfunc)();
-{
-
- if (dp->d_ino == 0)
- return;
- if (dirloc + dp->d_reclen > DIRBLKSIZ) {
- ((struct direct *)(dirbuf + prev))->d_reclen =
- DIRBLKSIZ - prev;
- (*wrtfunc)(dirbuf, DIRBLKSIZ);
- dirloc = 0;
- }
- blkcpy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen);
- prev = dirloc;
- dirloc += dp->d_reclen;
-}
-
-/*
- * flush out a directory that is finished.
- */
-flushent(wrtfunc)
- int (*wrtfunc)();
-{
-
- ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev;
- (*wrtfunc)(dirbuf, dirloc);
- dirloc = 0;
-}
-
-dirwrite(buf, size)
- char *buf;
- int size;
-{
-
- fwrite(buf, 1, size, df);
- seekpt = ftell(df);
-}
-
-dcvt(odp, ndp)
- register struct odirect *odp;
- register struct direct *ndp;
-{
-
- blkclr((char *)ndp, (long)(sizeof *ndp));
- ndp->d_ino = odp->d_ino;
- strncpy(ndp->d_name, odp->d_name, ODIRSIZ);
- ndp->d_namlen = strlen(ndp->d_name);
- ndp->d_reclen = DIRSIZ(ndp);
- /*
- * this quickly calculates if this inode is a directory.
- * Currently not maintained.
- *
- for (itp = inotab[INOHASH(odp->d_ino)]; itp; itp = itp->t_next) {
- if (itp->t_ino != odp->d_ino)
- continue;
- ndp->d_fmt = IFDIR;
- break;
- }
- */
-}
-
-/*
- * Open a directory.
- * Modified to allow any random file to be a legal directory.
- */
-DIR *
-opendir(name)
- char *name;
-{
- register DIR *dirp;
-
- dirp = (DIR *)malloc(sizeof(DIR));
- dirp->dd_fd = open(name, 0);
- if (dirp->dd_fd == -1) {
- free((char *)dirp);
- return NULL;
- }
- dirp->dd_loc = 0;
- return dirp;
-}
-
-/*
- * Seek to an entry in a directory.
- * Only values returned by ``telldir'' should be passed to seekdir.
- * Modified to have many directories based in one file.
- */
-void
-seekdir(dirp, loc, base)
- register DIR *dirp;
- daddr_t loc, base;
-{
-
- if (loc == telldir(dirp))
- return;
- loc -= base;
- if (loc < 0)
- fprintf(stderr, "bad seek pointer to seekdir %d\n", loc);
- (void)lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0);
- dirp->dd_loc = loc & (DIRBLKSIZ - 1);
- if (dirp->dd_loc != 0)
- dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ);
-}
-
-/*
- * get next entry in a directory.
- */
-struct direct *
-readdir(dirp)
- register DIR *dirp;
-{
- register struct direct *dp;
-
- for (;;) {
- if (dirp->dd_loc == 0) {
- dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf,
- DIRBLKSIZ);
- if (dirp->dd_size <= 0)
- return NULL;
- }
- if (dirp->dd_loc >= dirp->dd_size) {
- 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)
- return NULL;
- dirp->dd_loc += dp->d_reclen;
- if (dp->d_ino == 0)
- continue;
- return (dp);
- }
-}
-
-allocinotab(ino, seekpt)
- ino_t ino;
- daddr_t seekpt;
-{
- register struct inotab *itp;
-
- itp = (struct inotab *)calloc(1, sizeof(struct inotab));
- itp->t_next = inotab[INOHASH(ino)];
- inotab[INOHASH(ino)] = itp;
- itp->t_ino = ino;
- itp->t_seekpt = seekpt;
-}
-
-allocxtr(ino, name, flags)
- ino_t ino;
- char *name;
- char flags;
-{
- register struct xtrlist *xp, *pxp;
-
- xp = (struct xtrlist *)calloc(1, sizeof(struct xtrlist) + strlen(name));
- xp->x_next = xtrlist[INOHASH(ino)];
- xtrlist[INOHASH(ino)] = xp;
- xp->x_ino = ino;
- strcpy(xp->x_name, name);
- xtrcnt++;
- xp->x_flags = flags;
- for (pxp = xp->x_next; pxp; pxp = pxp->x_next)
- if (pxp->x_ino == ino && (pxp->x_flags & XLINKED) == 0) {
- xp->x_flags |= XLINKED;
- xp->x_linkedto = pxp;
- xtrcnt--;
- break;
- }
- if (!vflag)
- return;
- if (xp->x_flags & XLINKED)
- fprintf(stdout, "%s: linked to %s\n", xp->x_name, pxp->x_name);
- else if (xp->x_flags & XISDIR)
- fprintf(stdout, "%s: directory inode %u\n", xp->x_name, ino);
- else
- fprintf(stdout, "%s: inode %u\n", xp->x_name, ino);
-}
-
-done(exitcode)
- int exitcode;
-{
-
- unlink(dirfile);
- exit(exitcode);