BSD 4_1_snap release
[unix-history] / usr / src / cmd / tar.c
index e24f4fe..5012800 100644 (file)
@@ -1,7 +1,9 @@
+static char *sccsid = "@(#)tar.c       4.5 (Berkeley) 81/04/02";
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/dir.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/dir.h>
+#include <sys/mtio.h>
 #include <signal.h>
 
 char   *sprintf();
 #include <signal.h>
 
 char   *sprintf();
@@ -35,10 +37,10 @@ struct linkbuf {
 
 struct stat stbuf;
 
 
 struct stat stbuf;
 
-int    rflag, xflag, vflag, tflag, mt, cflag, mflag;
+int    rflag, xflag, vflag, tflag, mt, cflag, mflag, fflag, oflag, pflag;
 int    term, chksum, wflag, recno, first, linkerrok;
 int    freemem = 1;
 int    term, chksum, wflag, recno, first, linkerrok;
 int    freemem = 1;
-int    nblock = 1;
+int    nblock = NBLOCK;
 
 daddr_t        low;
 daddr_t        high;
 
 daddr_t        low;
 daddr_t        high;
@@ -48,7 +50,7 @@ char  tname[] = "/tmp/tarXXXXXX";
 
 
 char   *usefile;
 
 
 char   *usefile;
-char   magtape[]       = "/dev/mt1";
+char   magtape[]       = "/dev/rmt8";
 
 char   *malloc();
 
 
 char   *malloc();
 
@@ -70,11 +72,18 @@ char        *argv[];
                switch(*cp) {
                case 'f':
                        usefile = *argv++;
                switch(*cp) {
                case 'f':
                        usefile = *argv++;
+                       fflag++;
                        break;
                case 'c':
                        cflag++;
                        rflag++;
                        break;
                        break;
                case 'c':
                        cflag++;
                        rflag++;
                        break;
+               case 'o':
+                       oflag++;
+                       break;
+               case 'p':
+                       pflag++;
+                       break;
                case 'u':
                        mktemp(tname);
                        if ((tfile = fopen(tname, "w")) == NULL) {
                case 'u':
                        mktemp(tname);
                        if ((tfile = fopen(tname, "w")) == NULL) {
@@ -85,11 +94,6 @@ char *argv[];
                        /* FALL THROUGH */
                case 'r':
                        rflag++;
                        /* FALL THROUGH */
                case 'r':
                        rflag++;
-                       if (nblock != 1) {
-noupdate:
-                               fprintf(stderr, "Blocked tapes cannot be updated (yet)\n");
-                               done(1);
-                       }
                        break;
                case 'v':
                        vflag++;
                        break;
                case 'v':
                        vflag++;
@@ -110,7 +114,11 @@ noupdate:
                        break;
                case '0':
                case '1':
                        break;
                case '0':
                case '1':
-                       magtape[7] = *cp;
+               case '4':
+               case '5':
+               case '7':
+               case '8':
+                       magtape[8] = *cp;
                        usefile = magtape;
                        break;
                case 'b':
                        usefile = magtape;
                        break;
                case 'b':
@@ -119,8 +127,6 @@ noupdate:
                                fprintf(stderr, "Invalid blocksize. (Max %d)\n", NBLOCK);
                                done(1);
                        }
                                fprintf(stderr, "Invalid blocksize. (Max %d)\n", NBLOCK);
                                done(1);
                        }
-                       if (rflag && !cflag)
-                               goto noupdate;
                        break;
                case 'l':
                        linkerrok++;
                        break;
                case 'l':
                        linkerrok++;
@@ -135,7 +141,7 @@ noupdate:
                        usage();
                        done(1);
                }
                        usage();
                        done(1);
                }
-               if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
+               if (signal(SIGINT, SIG_IGN) != SIG_IGN)
                        signal(SIGINT, onintr);
                if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
                        signal(SIGHUP, onhup);
                        signal(SIGINT, onintr);
                if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
                        signal(SIGHUP, onhup);
@@ -151,6 +157,7 @@ noupdate:
                                done(1);
                        }
                        mt = dup(1);
                                done(1);
                        }
                        mt = dup(1);
+                       nblock = 1;
                }
                else if ((mt = open(usefile, 2)) < 0) {
                        if (cflag == 0 || (mt =  creat(usefile, 0666)) < 0) {
                }
                else if ((mt = open(usefile, 2)) < 0) {
                        if (cflag == 0 || (mt =  creat(usefile, 0666)) < 0) {
@@ -161,8 +168,10 @@ noupdate:
                dorep(argv);
        }
        else if (xflag)  {
                dorep(argv);
        }
        else if (xflag)  {
-               if (strcmp(usefile, "-") == 0)
+               if (strcmp(usefile, "-") == 0) {
                        mt = dup(0);
                        mt = dup(0);
+                       nblock = 1;
+               }
                else if ((mt = open(usefile, 0)) < 0) {
                        fprintf(stderr, "tar: cannot open %s\n", usefile);
                        done(1);
                else if ((mt = open(usefile, 0)) < 0) {
                        fprintf(stderr, "tar: cannot open %s\n", usefile);
                        done(1);
@@ -170,7 +179,11 @@ noupdate:
                doxtract(argv);
        }
        else if (tflag) {
                doxtract(argv);
        }
        else if (tflag) {
-               if ((mt = open(usefile, 0)) < 0) {
+               if (strcmp(usefile, "-") == 0) {
+                       mt = dup(0);
+                       nblock = 1;
+               }
+               else if ((mt = open(usefile, 0)) < 0) {
                        fprintf(stderr, "tar: cannot open %s\n", usefile);
                        done(1);
                }
                        fprintf(stderr, "tar: cannot open %s\n", usefile);
                        done(1);
                }
@@ -197,16 +210,14 @@ char      *argv[];
                getdir();
                do {
                        passtape();
                getdir();
                do {
                        passtape();
+                       if (term)
+                               done(0);
                        getdir();
                } while (!endtape());
                if (tfile != NULL) {
                        char buf[200];
 
                        getdir();
                } while (!endtape());
                if (tfile != NULL) {
                        char buf[200];
 
-                       strcat(buf, "sort +0 -1 +1nr ");
-                       strcat(buf, tname);
-                       strcat(buf, " -o ");
-                       strcat(buf, tname);
-                       sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX;mv %sX %s",
+                       sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX; mv %sX %s",
                                tname, tname, tname, tname, tname, tname);
                        fflush(tfile);
                        system(buf);
                                tname, tname, tname, tname, tname, tname);
                        fflush(tfile);
                        system(buf);
@@ -219,6 +230,15 @@ char       *argv[];
        getwdir(wdir);
        while (*argv && ! term) {
                cp2 = *argv;
        getwdir(wdir);
        while (*argv && ! term) {
                cp2 = *argv;
+               if (!strcmp(cp2, "-C") && argv[1]) {
+                       argv++;
+                       if (chdir(*argv) < 0)
+                               perror(*argv);
+                       else
+                               getwdir(wdir);
+                       argv++;
+                       continue;
+               }
                for (cp = *argv; *cp; cp++)
                        if (*cp == '/')
                                cp2 = cp;
                for (cp = *argv; *cp; cp++)
                        if (*cp == '/')
                                cp2 = cp;
@@ -314,7 +334,7 @@ char *shortname;
                close(infile);
                return;
        }
                close(infile);
                return;
        }
-       if (checkw('r', shortname) == 0) {
+       if (checkw('r', longname) == 0) {
                close(infile);
                return;
        }
                close(infile);
                return;
        }
@@ -322,8 +342,20 @@ char *shortname;
        if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
                for (i = 0, cp = buf; *cp++ = longname[i++];);
                *--cp = '/';
        if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
                for (i = 0, cp = buf; *cp++ = longname[i++];);
                *--cp = '/';
-               cp++;
+               *++cp = 0  ;
                i = 0;
                i = 0;
+               if (!oflag) {
+                   if( (cp - buf) >= NAMSIZ) {
+                       fprintf(stderr, "%s: file name too long\n", longname);
+                       close(infile);
+                       return;
+                   }
+                   stbuf.st_size = 0;
+                   tomodes(&stbuf);
+                   strcpy(dblock.dbuf.name,buf);
+                   sprintf(dblock.dbuf.chksum, "%6o", checksum());
+                   writetape( (char *) &dblock);
+               }
                chdir(shortname);
                while (read(infile, (char *)&dbuf, sizeof(dbuf)) > 0 && !term) {
                        if (dbuf.d_ino == 0) {
                chdir(shortname);
                while (read(infile, (char *)&dbuf, sizeof(dbuf)) > 0 && !term) {
                        if (dbuf.d_ino == 0) {
@@ -454,7 +486,8 @@ gotit:
                        continue;
                }
 
                        continue;
                }
 
-               checkdir(dblock.dbuf.name);
+               if(checkdir(dblock.dbuf.name))
+                       continue;
 
                if (dblock.dbuf.linkflag == '1') {
                        unlink(dblock.dbuf.name);
 
                if (dblock.dbuf.linkflag == '1') {
                        unlink(dblock.dbuf.name);
@@ -463,7 +496,8 @@ gotit:
                                continue;
                        }
                        if (vflag)
                                continue;
                        }
                        if (vflag)
-                               fprintf(stderr, "%s linked to %s\n", dblock.dbuf.name, dblock.dbuf.linkname);
+                               fprintf(stderr, "%s linked to %s\n",
+                                       dblock.dbuf.name, dblock.dbuf.linkname);
                        continue;
                }
                if ((ofile = creat(dblock.dbuf.name, stbuf.st_mode & 07777)) < 0) {
                        continue;
                }
                if ((ofile = creat(dblock.dbuf.name, stbuf.st_mode & 07777)) < 0) {
@@ -471,12 +505,12 @@ gotit:
                        passtape();
                        continue;
                }
                        passtape();
                        continue;
                }
-
                chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid);
 
                blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK;
                if (vflag)
                chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid);
 
                blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK;
                if (vflag)
-                       fprintf(stderr, "x %s, %ld bytes, %ld tape blocks\n", dblock.dbuf.name, bytes, blocks);
+                       fprintf(stderr, "x %s, %ld bytes, %ld tape blocks\n",
+                               dblock.dbuf.name, bytes, blocks);
                while (blocks-- > 0) {
                        readtape(buf);
                        if (bytes > TBLOCK) {
                while (blocks-- > 0) {
                        readtape(buf);
                        if (bytes > TBLOCK) {
@@ -499,6 +533,8 @@ gotit:
                        timep[1] = stbuf.st_mtime;
                        utime(dblock.dbuf.name, timep);
                }
                        timep[1] = stbuf.st_mtime;
                        utime(dblock.dbuf.name, timep);
                }
+               if (pflag)
+                   chmod(dblock.dbuf.name, stbuf.st_mode & 07777);
        }
 }
 
        }
 }
 
@@ -596,18 +632,25 @@ register char *name;
                if (*cp == '/') {
                        *cp = '\0';
                        if (access(name, 01) < 0) {
                if (*cp == '/') {
                        *cp = '\0';
                        if (access(name, 01) < 0) {
-                               if (fork() == 0) {
+                               register int pid, rp;
+
+                               if ((pid = fork()) == 0) {
                                        execl("/bin/mkdir", "mkdir", name, 0);
                                        execl("/usr/bin/mkdir", "mkdir", name, 0);
                                        fprintf(stderr, "tar: cannot find mkdir!\n");
                                        done(0);
                                }
                                        execl("/bin/mkdir", "mkdir", name, 0);
                                        execl("/usr/bin/mkdir", "mkdir", name, 0);
                                        fprintf(stderr, "tar: cannot find mkdir!\n");
                                        done(0);
                                }
-                               while (wait(&i) >= 0);
+                               while ((rp = wait(&i)) >= 0 && rp != pid)
+                                       ;
                                chown(name, stbuf.st_uid, stbuf.st_gid);
                                chown(name, stbuf.st_uid, stbuf.st_gid);
+                               if (pflag)
+                                       chmod(dblock.dbuf.name,
+                                           stbuf.st_mode & 0777);
                        }
                        *cp = '/';
                }
        }
                        }
                        *cp = '/';
                }
        }
+       return(cp[-1]=='/');
 }
 
 onintr()
 }
 
 onintr()
@@ -833,14 +876,10 @@ char *b, *s;
 readtape(buffer)
 char *buffer;
 {
 readtape(buffer)
 char *buffer;
 {
-       int i, j;
+       register int i;
 
        if (recno >= nblock || first == 0) {
 
        if (recno >= nblock || first == 0) {
-               if (first == 0 && nblock == 1)
-                       j = NBLOCK;
-               else
-                       j = nblock;
-               if ((i = read(mt, tbuf, TBLOCK*j)) < 0) {
+               if ((i = read(mt, tbuf, TBLOCK*nblock)) < 0) {
                        fprintf(stderr, "Tar: tape read error\n");
                        done(3);
                }
                        fprintf(stderr, "Tar: tape read error\n");
                        done(3);
                }
@@ -850,11 +889,7 @@ char *buffer;
                                done(3);
                        }
                        i /= TBLOCK;
                                done(3);
                        }
                        i /= TBLOCK;
-                       if (rflag && i != 1) {
-                               fprintf(stderr, "Tar: Cannot update blocked tapes (yet)\n");
-                               done(4);
-                       }
-                       if (i != nblock && i != 1) {
+                       if (i != nblock) {
                                fprintf(stderr, "Tar: blocksize = %d\n", i);
                                nblock = i;
                        }
                                fprintf(stderr, "Tar: blocksize = %d\n", i);
                                nblock = i;
                        }
@@ -890,15 +925,20 @@ char *buffer;
 
 backtape()
 {
 
 backtape()
 {
-       lseek(mt, (long) -TBLOCK, 1);
-       if (recno >= nblock) {
-               recno = nblock - 1;
-               if (read(mt, tbuf, TBLOCK*nblock) < 0) {
-                       fprintf(stderr, "Tar: tape read error after seek\n");
+       static int mtdev = 1;
+       static struct mtop mtop = {MTBSR, 1};
+       struct mtget mtget;
+
+       if (mtdev == 1)
+               mtdev = ioctl(mt, MTIOCGET, &mtget);
+       if (mtdev == 0) {
+               if (ioctl(mt, MTIOCTOP, &mtop) < 0) {
+                       fprintf(stderr, "Tar: tape backspace error\n");
                        done(4);
                }
                        done(4);
                }
-               lseek(mt, (long) -TBLOCK, 1);
-       }
+       } else
+               lseek(mt, (long) -TBLOCK*nblock, 1);
+       recno--;
 }
 
 flushtape()
 }
 
 flushtape()