📄 tar.c
字号:
#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/dir.h>#include <signal.h>char *sprintf();char *strcat();daddr_t bsrch();#define TBLOCK 512#define NBLOCK 20#define NAMSIZ 100union hblock { char dummy[TBLOCK]; struct header { char name[NAMSIZ]; char mode[8]; char uid[8]; char gid[8]; char size[12]; char mtime[12]; char chksum[8]; char linkflag; char linkname[NAMSIZ]; } dbuf;} dblock, tbuf[NBLOCK];struct linkbuf { ino_t inum; dev_t devnum; int count; char pathname[NAMSIZ]; struct linkbuf *nextp;} *ihead;struct stat stbuf;int rflag, xflag, vflag, tflag, mt, cflag, mflag;int term, chksum, wflag, recno, first, linkerrok;int freemem = 1;int nblock = 1;daddr_t low;daddr_t high;FILE *tfile;char tname[] = "/tmp/tarXXXXXX";char *usefile;char magtape[] = "/dev/mt1";char *malloc();main(argc, argv)int argc;char *argv[];{ char *cp; int onintr(), onquit(), onhup(), onterm(); if (argc < 2) usage(); tfile = NULL; usefile = magtape; argv[argc] = 0; argv++; for (cp = *argv++; *cp; cp++) switch(*cp) { case 'f': usefile = *argv++; if (nblock == 1) nblock = 0; break; case 'c': cflag++; rflag++; break; case 'u': mktemp(tname); if ((tfile = fopen(tname, "w")) == NULL) { fprintf(stderr, "Tar: cannot create temporary file (%s)\n", tname); done(1); } fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n"); /* FALL THROUGH */ case 'r': rflag++; if (nblock != 1 && cflag == 0) {noupdate: fprintf(stderr, "Tar: Blocked tapes cannot be updated (yet)\n"); done(1); } break; case 'v': vflag++; break; case 'w': wflag++; break; case 'x': xflag++; break; case 't': tflag++; break; case 'm': mflag++; break; case '-': break; case '0': case '1': magtape[7] = *cp; usefile = magtape; break; case 'b': nblock = atoi(*argv++); if (nblock > NBLOCK || nblock <= 0) { fprintf(stderr, "Invalid blocksize. (Max %d)\n", NBLOCK); done(1); } if (rflag && !cflag) goto noupdate; break; case 'l': linkerrok++; break; default: fprintf(stderr, "tar: %c: unknown option\n", *cp); usage(); } if (rflag) { if (cflag && tfile != NULL) { usage(); done(1); } if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, onintr); if (signal(SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, onhup); if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) signal(SIGQUIT, onquit);/* if (signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, onterm);*/ if (strcmp(usefile, "-") == 0) { if (cflag == 0) { fprintf(stderr, "Can only create standard output archives\n"); done(1); } mt = dup(1); nblock = 1; } else if ((mt = open(usefile, 2)) < 0) { if (cflag == 0 || (mt = creat(usefile, 0666)) < 0) { fprintf(stderr, "tar: cannot open %s\n", usefile); done(1); } } if (cflag == 0 && nblock == 0) nblock = 1; dorep(argv); } else if (xflag) { 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); } doxtract(argv); } else if (tflag) { 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); } dotable(); } else usage(); done(0);}usage(){ fprintf(stderr, "tar: usage tar -{txru}[cvfblm] [tapefile] [blocksize] file1 file2...\n"); done(1);}dorep(argv)char *argv[];{ register char *cp, *cp2; char wdir[60]; if (!cflag) { getdir(); do { passtape(); if (term) done(0); 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", tname, tname, tname, tname, tname, tname); fflush(tfile); system(buf); freopen(tname, "r", tfile); fstat(fileno(tfile), &stbuf); high = stbuf.st_size; } } getwdir(wdir); while (*argv && ! term) { cp2 = *argv; for (cp = *argv; *cp; cp++) if (*cp == '/') cp2 = cp; if (cp2 != *argv) { *cp2 = '\0'; chdir(*argv); *cp2 = '/'; cp2++; } putfile(*argv++, cp2); chdir(wdir); } putempty(); putempty(); flushtape(); if (linkerrok == 1) for (; ihead != NULL; ihead = ihead->nextp) if (ihead->count != 0) fprintf(stderr, "Missing links to %s\n", ihead->pathname);}endtape(){ if (dblock.dbuf.name[0] == '\0') { backtape(); return(1); } else return(0);}getdir(){ register struct stat *sp; int i; readtape( (char *) &dblock); if (dblock.dbuf.name[0] == '\0') return; sp = &stbuf; sscanf(dblock.dbuf.mode, "%o", &i); sp->st_mode = i; sscanf(dblock.dbuf.uid, "%o", &i); sp->st_uid = i; sscanf(dblock.dbuf.gid, "%o", &i); sp->st_gid = i; sscanf(dblock.dbuf.size, "%lo", &sp->st_size); sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime); sscanf(dblock.dbuf.chksum, "%o", &chksum); if (chksum != checksum()) { fprintf(stderr, "directory checksum error\n"); done(2); } if (tfile != NULL) fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime);}passtape(){ long blocks; char buf[TBLOCK]; if (dblock.dbuf.linkflag == '1') return; blocks = stbuf.st_size; blocks += TBLOCK-1; blocks /= TBLOCK; while (blocks-- > 0) readtape(buf);}putfile(longname, shortname)char *longname;char *shortname;{ int infile; long blocks; char buf[TBLOCK]; register char *cp, *cp2; struct direct dbuf; int i, j; infile = open(shortname, 0); if (infile < 0) { fprintf(stderr, "tar: %s: cannot open file\n", longname); return; } fstat(infile, &stbuf); if (tfile != NULL && checkupdate(longname) == 0) { close(infile); return; } if (checkw('r', longname) == 0) { close(infile); return; } if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { for (i = 0, cp = buf; *cp++ = longname[i++];); *--cp = '/'; cp++; i = 0; chdir(shortname); while (read(infile, (char *)&dbuf, sizeof(dbuf)) > 0 && !term) { if (dbuf.d_ino == 0) { i++; continue; } if (strcmp(".", dbuf.d_name) == 0 || strcmp("..", dbuf.d_name) == 0) { i++; continue; } cp2 = cp; for (j=0; j < DIRSIZ; j++) *cp2++ = dbuf.d_name[j]; *cp2 = '\0'; close(infile); putfile(buf, cp); infile = open(".", 0); i++; lseek(infile, (long) (sizeof(dbuf) * i), 0); } close(infile); chdir(".."); return; } if ((stbuf.st_mode & S_IFMT) != S_IFREG) { fprintf(stderr, "tar: %s is not a file. Not dumped\n", longname); return; } tomodes(&stbuf); cp2 = longname; for (cp = dblock.dbuf.name, i=0; (*cp++ = *cp2++) && i < NAMSIZ; i++); if (i >= NAMSIZ) { fprintf(stderr, "%s: file name too long\n", longname); close(infile); return; } if (stbuf.st_nlink > 1) { struct linkbuf *lp; int found = 0; for (lp = ihead; lp != NULL; lp = lp->nextp) { if (lp->inum == stbuf.st_ino && lp->devnum == stbuf.st_dev) { found++; break; } } if (found) { strcpy(dblock.dbuf.linkname, lp->pathname); dblock.dbuf.linkflag = '1'; sprintf(dblock.dbuf.chksum, "%6o", checksum()); writetape( (char *) &dblock); if (vflag) { fprintf(stderr, "a %s ", longname); fprintf(stderr, "link to %s\n", lp->pathname); } lp->count--; close(infile); return; } else { lp = (struct linkbuf *) malloc(sizeof(*lp)); if (lp == NULL) { if (freemem) { fprintf(stderr, "Out of memory. Link information lost\n"); freemem = 0; } } else { lp->nextp = ihead; ihead = lp; lp->inum = stbuf.st_ino; lp->devnum = stbuf.st_dev; lp->count = stbuf.st_nlink - 1; strcpy(lp->pathname, longname); } } } blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK; if (vflag) { fprintf(stderr, "a %s ", longname); fprintf(stderr, "%ld blocks\n", blocks); } sprintf(dblock.dbuf.chksum, "%6o", checksum()); writetape( (char *) &dblock); while ((i = read(infile, buf, TBLOCK)) > 0 && blocks > 0) { writetape(buf); blocks--; } close(infile); if (blocks != 0 || i != 0) fprintf(stderr, "%s: file changed size\n", longname); while (blocks-- > 0) putempty();}doxtract(argv)char *argv[];{ long blocks, bytes; char buf[TBLOCK]; char **cp; int ofile; for (;;) { getdir(); if (endtape()) break; if (*argv == 0) goto gotit; for (cp = argv; *cp; cp++) if (prefix(*cp, dblock.dbuf.name)) goto gotit; passtape(); continue;gotit: if (checkw('x', dblock.dbuf.name) == 0) { passtape(); continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -