|
|
1.1 ! root 1: #include <stddef.h> ! 2: #include <stdio.h> ! 3: #include <sys/types.h> ! 4: #include <sys/stat.h> ! 5: #include <libv.h> ! 6: #include "ftwlk.h" ! 7: #include "tar.h" ! 8: #include "misc.h" ! 9: ! 10: #define MIN(A, B) ((A) < (B) ? (A) : (B)) ! 11: ! 12: int vflag; ! 13: ! 14: int nerr; ! 15: ! 16: struct hardlink { ! 17: char *name; ! 18: int ino; ! 19: int dev; ! 20: struct hardlink *next; ! 21: }; ! 22: ! 23: struct hardlink *links; ! 24: ! 25: struct hardlink * ! 26: findlink(char *name, int ino, int dev) ! 27: { ! 28: struct hardlink *h; ! 29: ! 30: for (h = links; h; h = h->next) ! 31: if (ino == h->ino && dev == h->dev) ! 32: return h; ! 33: h = xmalloc(sizeof (struct hardlink)); ! 34: h->name = xstrdup(name); ! 35: h->ino = ino; ! 36: h->dev = dev; ! 37: h->next = links; ! 38: links = h; ! 39: return 0; /* make a new entry, but say we didn't find it */ ! 40: } ! 41: ! 42: #ifndef S_ISREG ! 43: #define S_ISREG(M) (((M) & S_IFMT) == S_IFREG) ! 44: #endif ! 45: ! 46: void ! 47: zeropad(long from, long to) ! 48: { ! 49: static char zero[512]; ! 50: static int n; ! 51: ! 52: while (from < to) { ! 53: n = MIN(to - from, sizeof zero); ! 54: if (fwrite(zero, 1, n, stdout) != n) { ! 55: fprintf(stderr, "tarc: zero padding failed\n"); ! 56: exit(1); ! 57: } ! 58: from += n; ! 59: } ! 60: } ! 61: ! 62: int ! 63: dofile(char *name, struct stat *st, int code, struct FTWLK *f) ! 64: { ! 65: struct tarhdr hdr; ! 66: struct tarbuf buf; ! 67: struct hardlink *hl; ! 68: FILE *fp; ! 69: long cc; ! 70: ! 71: if (code == FTWLK_NSL || code == FTWLK_SL) ! 72: lstat(name, st); /* fix ftwlk braindamage */ ! 73: ! 74: memset(&hdr, 0, sizeof hdr); ! 75: if (strlen(name) > TNAMEMAX) { ! 76: fprintf(stderr, "tarc: file name too long '%s'\n", name); ! 77: exit(1); ! 78: } ! 79: ! 80: strcpy(hdr.name, name); ! 81: hdr.mode = st->st_mode & TMASK; ! 82: hdr.uid = st->st_uid; ! 83: hdr.gid = st->st_gid; ! 84: hdr.size = st->st_size; ! 85: hdr.mtime = st->st_mtime; ! 86: ! 87: switch (code) { ! 88: case FTWLK_D: ! 89: if (strlen(name) <= TNAMEMAX - 1) ! 90: strcat(hdr.name, "/"); ! 91: hdr.typeflag = DIRTYPE; ! 92: break; ! 93: ! 94: case FTWLK_F: ! 95: if (st->st_nlink > 1 ! 96: && (hl = findlink(name, st->st_ino, st->st_dev)) ! 97: && strlen(hl->name) <= TLINKMAX) { ! 98: hdr.typeflag = LNKTYPE; ! 99: strcpy(hdr.linkname, hl->name); ! 100: } else if (S_ISREG(st->st_mode)) ! 101: hdr.typeflag = REGTYPE; ! 102: else { ! 103: fprintf(stderr, "tarc: not a regular file '%s'\n", ! 104: name); ! 105: ++nerr; ! 106: return 0; ! 107: } ! 108: break; ! 109: ! 110: case FTWLK_SL: ! 111: if (f->level == 0) { ! 112: f->quit = FTWLK_FOLLOW; ! 113: return 0; ! 114: } ! 115: hdr.typeflag = SYMTYPE; ! 116: cc = readlink(name, hdr.linkname, sizeof hdr.linkname); ! 117: if (cc < 0) { ! 118: fprintf(stderr, "tarc: can't read symlink '%s'\n", ! 119: name); ! 120: ++nerr; ! 121: return 0; ! 122: } ! 123: break; ! 124: ! 125: default: ! 126: return 0; ! 127: } ! 128: ! 129: if (hdr.typeflag != REGTYPE) ! 130: hdr.size = 0; ! 131: if (vflag) ! 132: fprintf(stderr, "%s\n", hdr.name); ! 133: if (thdrput(&buf, &hdr) != 0) { ! 134: fprintf(stderr, "tarc: failed making header for '%s'\n", name); ! 135: ++nerr; ! 136: return 0; ! 137: } ! 138: if (hdr.typeflag == REGTYPE && !(fp = fopen(name, "r"))) ! 139: return 0; ! 140: if (fwrite(&buf, sizeof buf, 1, stdout) != 1) { ! 141: fprintf(stderr, "tarc: write failed\n"); ! 142: exit(1); ! 143: } ! 144: if (hdr.typeflag == REGTYPE) { ! 145: cc = fpcopy(stdout, fp, st->st_size); ! 146: if (cc < 0) { ! 147: fprintf(stderr, "tarc: file copy failed '%s'\n", name); ! 148: exit(1); ! 149: } ! 150: if (cc != st->st_size) ! 151: fprintf(stderr, "tarc: warning: size change '%s'\n", ! 152: name); ! 153: zeropad(cc, (st->st_size + TSIZE - 1) / TSIZE * TSIZE); ! 154: fclose(fp); ! 155: } ! 156: return 0; ! 157: } ! 158: ! 159: void ! 160: usage(void) ! 161: { ! 162: fprintf(stderr, "usage: tarc [-v] files...\n"); ! 163: exit(1); ! 164: } ! 165: ! 166: int ! 167: main(int argc, char *argv[]) ! 168: { ! 169: int i, c; ! 170: ! 171: prog = argv[0]; ! 172: while ((c = getopt(argc, argv, "v")) != EOF) ! 173: switch (c) { ! 174: case 'v': ! 175: ++vflag; ! 176: break; ! 177: default: ! 178: usage(); ! 179: break; ! 180: } ! 181: for (i = optind; i < argc; ++i) ! 182: ftwlk(argv[i], dofile, 10); ! 183: zeropad(0, 2 * TSIZE); ! 184: return nerr ? 1 : 0; ! 185: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.