6 #define NBLOCK 40 /* maximum blocksize */
7 #define DBLOCK 20 /* default blocksize */
22 char linkname[NAMSIZ];
24 } dblock, tbuf[NBLOCK];
29 int rflag, xflag, vflag, tflag, mt, cflag, fflag, Tflag, Rflag;
31 int chksum, recno, first;
39 void putfile(char*, char *, char *);
40 void doxtract(char **);
44 int checkdir(char *, int, Qid*);
47 int checkupdate(char *);
48 int prefix(char *, char *);
53 void affix(int, char *);
56 main(int argc, char **argv)
64 Binit(&bout, 1, OWRITE);
68 for (cp = *argv++; *cp; cp++)
80 uflag = strtoul(ap, 0, 0);
86 gflag = strtoul(ap, 0, 0);
113 fprint(2, "tar: %c: unknown option\n", *cp);
117 fmtinstall('M', dirmodefmt);
122 fprint(2, "tar: can only create standard output archives\n");
128 else if ((mt = open(usefile, ORDWR)) < 0) {
129 if (cflag == 0 || (mt = create(usefile, OWRITE, 0666)) < 0) {
130 fprint(2, "tar: cannot open %s: %r\n", usefile);
141 else if ((mt = open(usefile, OREAD)) < 0) {
142 fprint(2, "tar: cannot open %s: %r\n", usefile);
152 else if ((mt = open(usefile, OREAD)) < 0) {
153 fprint(2, "tar: cannot open %s: %r\n", usefile);
166 fprint(2, "tar: usage tar {txrc}[Rvf] [tarfile] file1 file2...\n");
173 char cwdbuf[2048], *cwd, thisdir[2048];
177 if (getwd(cwdbuf, sizeof(cwdbuf)) == 0) {
178 fprint(2, "tar: can't find current directory: %r\n");
193 if (!strcmp(cp2, "-C") && argv[1]) {
195 if (chdir(*argv) < 0)
202 for (cp = *argv; *cp; cp++)
209 strncpy(thisdir, *argv, sizeof(thisdir));
211 snprint(thisdir, sizeof(thisdir), "%s/%s", cwd, *argv);
216 strncpy(thisdir, cwd, sizeof(thisdir));
217 putfile(thisdir, *argv++, cp2);
218 if(cd && chdir(cwd) < 0) {
219 fprint(2, "tar: can't cd back to %s: %r\n", cwd);
231 if (dblock.dbuf.name[0] == '\0') {
244 readtar((char*)&dblock);
245 if (dblock.dbuf.name[0] == '\0')
248 stbuf = malloc(sizeof(Dir));
250 fprint(2, "tar: can't malloc: %r\n");
255 sp->mode = strtol(dblock.dbuf.mode, 0, 8);
258 sp->length = strtol(dblock.dbuf.size, 0, 8);
259 sp->mtime = strtol(dblock.dbuf.mtime, 0, 8);
260 chksum = strtol(dblock.dbuf.chksum, 0, 8);
261 if (chksum != checksum()) {
262 fprint(2, "directory checksum error\n");
263 exits("checksum error");
266 /* the mode test is ugly but sometimes necessary */
267 if (dblock.dbuf.linkflag == '5' || (sp->mode&0170000) == 040000) {
268 sp->qid.type |= QTDIR;
279 if (dblock.dbuf.linkflag == '1' || dblock.dbuf.linkflag == 's')
281 blocks = stbuf->length;
290 putfile(char *dir, char *longname, char *sname)
296 char shortname[4096];
301 if(strlen(sname) > sizeof shortname - 3){
302 fprint(2, "tar: %s: name too long (max %d)\n", sname, sizeof shortname - 3);
306 snprint(shortname, sizeof shortname, "./%s", sname);
307 infile = open(shortname, OREAD);
309 fprint(2, "tar: %s: cannot open file - %r\n", longname);
315 stbuf = dirfstat(infile);
317 if (stbuf->qid.type & QTDIR) {
319 for (i = 0, cp = buf; *cp++ = longname[i++];);
322 if( (cp - buf) >= NAMSIZ) {
323 fprint(2, "tar: %s: file name too long\n", longname);
329 strcpy(dblock.dbuf.name,buf);
330 dblock.dbuf.linkflag = '5'; /* Directory */
331 sprint(dblock.dbuf.chksum, "%6o", checksum());
332 writetar( (char *) &dblock);
333 if (chdir(shortname) < 0) {
334 fprint(2, "tar: can't cd to %s: %r\n", shortname);
335 snprint(curdir, sizeof(curdir), "cd %s", shortname);
338 sprint(curdir, "%s/%s", dir, sname);
339 while ((n = dirread(infile, &db)) > 0) {
340 for(i = 0; i < n; i++){
341 strncpy(cp, db[i].name, sizeof buf - (cp-buf));
342 putfile(curdir, buf, db[i].name);
346 if (chdir(dir) < 0 && chdir("..") < 0) {
347 fprint(2, "tar: can't cd to ..(%s): %r\n", dir);
348 snprint(curdir, sizeof(curdir), "cd ..(%s)", dir);
358 for (cp = dblock.dbuf.name, i=0; (*cp++ = *cp2++) && i < NAMSIZ; i++);
360 fprint(2, "%s: file name too long\n", longname);
365 blocks = (stbuf->length + (TBLOCK-1)) / TBLOCK;
367 fprint(2, "a %s ", longname);
368 fprint(2, "%ld blocks\n", blocks);
370 dblock.dbuf.linkflag = 0; /* Regular file */
371 sprint(dblock.dbuf.chksum, "%6o", checksum());
372 writetar( (char *) &dblock);
374 while ((i = readn(infile, buf, TBLOCK)) > 0 && blocks > 0) {
379 if (blocks != 0 || i != 0)
380 fprint(2, "%s: file changed size\n", longname);
387 doxtract(char **argv)
391 char buf[TBLOCK], outname[NAMSIZ+4];
403 for (cp = argv; *cp; cp++)
404 if (prefix(*cp, dblock.dbuf.name))
410 if(checkdir(dblock.dbuf.name, stbuf->mode, &(stbuf->qid)))
413 if (dblock.dbuf.linkflag == '1') {
414 fprint(2, "tar: can't link %s %s\n",
415 dblock.dbuf.linkname, dblock.dbuf.name);
416 remove(dblock.dbuf.name);
419 if (dblock.dbuf.linkflag == 's') {
420 fprint(2, "tar: %s: cannot symlink\n", dblock.dbuf.name);
423 if(dblock.dbuf.name[0] != '/' || Rflag)
424 sprint(outname, "./%s", dblock.dbuf.name);
426 strcpy(outname, dblock.dbuf.name);
427 if ((ofile = create(outname, OWRITE, stbuf->mode & 0777)) < 0) {
428 fprint(2, "tar: %s - cannot create: %r\n", outname);
433 blocks = ((bytes = stbuf->length) + TBLOCK-1)/TBLOCK;
435 fprint(2, "x %s, %ld bytes\n",
436 dblock.dbuf.name, bytes);
437 while (blocks-- > 0) {
439 if (bytes > TBLOCK) {
440 if (write(ofile, buf, TBLOCK) < 0) {
441 fprint(2, "tar: %s: HELP - extract write error: %r\n", dblock.dbuf.name);
442 exits("extract write");
445 if (write(ofile, buf, bytes) < 0) {
446 fprint(2, "tar: %s: HELP - extract write error: %r\n", dblock.dbuf.name);
447 exits("extract write");
453 null.mtime = stbuf->mtime;
454 dirfwstat(ofile, &null);
469 Bprint(&bout, "%s", dblock.dbuf.name);
470 if (dblock.dbuf.linkflag == '1')
471 Bprint(&bout, " linked to %s", dblock.dbuf.linkname);
472 if (dblock.dbuf.linkflag == 's')
473 Bprint(&bout, " -> %s", dblock.dbuf.linkname);
484 memset(buf, 0, TBLOCK);
493 Bprint(&bout, "%M %4d/%1d ", st->mode, 0, 0); /* 0/0 uid/gid */
494 Bprint(&bout, "%8lld", st->length);
495 cp = ctime(st->mtime);
496 Bprint(&bout, " %-12.12s %-4.4s ", cp+4, cp+24);
500 checkdir(char *name, int mode, Qid *qid)
506 if(Rflag && *name == '/')
514 if (access(name, 0) < 0) {
515 f = create(name, OREAD, DMDIR + 0775L);
517 fprint(2, "tar: mkdir %s failed: %r\n", name);
524 /* if this is a directory, chmod it to the mode in the tar plus 700 */
525 if(cp[-1] == '/' || (qid->type&QTDIR)){
526 if((d=dirstat(name)) != 0){
528 null.mode = DMDIR | (mode & 0777) | 0700;
529 dirwstat(name, &null);
542 for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
544 sprint(dblock.dbuf.mode, "%6lo ", sp->mode & 0777);
545 sprint(dblock.dbuf.uid, "%6o ", uflag);
546 sprint(dblock.dbuf.gid, "%6o ", gflag);
547 sprint(dblock.dbuf.size, "%11llo ", sp->length);
548 sprint(dblock.dbuf.mtime, "%11lo ", sp->mtime);
557 for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++)
560 for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
566 prefix(char *s1, char *s2)
577 readtar(char *buffer)
581 if (recno >= nblock || first == 0) {
582 if ((i = readn(mt, tbuf, TBLOCK*nblock)) <= 0) {
583 fprint(2, "tar: archive read error: %r\n");
584 exits("archive read");
587 if ((i % TBLOCK) != 0) {
588 fprint(2, "tar: archive blocksize error: %r\n");
593 fprint(2, "tar: blocksize = %d\n", i);
600 memmove(buffer, &tbuf[recno++], TBLOCK);
605 writetar(char *buffer)
608 if (recno >= nblock) {
609 if (write(mt, tbuf, TBLOCK*nblock) != TBLOCK*nblock) {
610 fprint(2, "tar: archive write error: %r\n");
615 memmove(&tbuf[recno++], buffer, TBLOCK);
616 if (recno >= nblock) {
617 if (write(mt, tbuf, TBLOCK*nblock) != TBLOCK*nblock) {
618 fprint(2, "tar: archive write error: %r\n");
627 * backup over last tar block
632 seek(mt, -TBLOCK*nblock, 1);
639 write(mt, tbuf, TBLOCK*nblock);