|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include <string.h> ! 3: #include <time.h> ! 4: #include <sys/types.h> ! 5: #include <sys/stat.h> ! 6: #include <fcntl.h> ! 7: #include <unistd.h> ! 8: #include <utime.h> ! 9: #include <libv.h> ! 10: #include "tar.h" ! 11: #include "misc.h" ! 12: ! 13: #ifndef S_ISDIR ! 14: #define S_ISDIR(M) (((M) & S_IFMT) == S_IFDIR) ! 15: #endif ! 16: ! 17: #define MIN(A, B) ((A) < (B) ? (A) : (B)) ! 18: ! 19: int fflag; ! 20: int tflag; ! 21: int vflag; ! 22: ! 23: int nerr; ! 24: ! 25: struct chtmug { ! 26: char *path; ! 27: time_t mtime; ! 28: int mode; ! 29: int uid; ! 30: int gid; ! 31: struct chtmug *next; ! 32: }; ! 33: ! 34: struct chtmug *chtmuglist; ! 35: ! 36: void ! 37: chtmug(char *path, time_t mtime, int mode, int uid, int gid) ! 38: { ! 39: struct utimbuf ut; ! 40: ! 41: time(&ut.actime); ! 42: ut.modtime = mtime; ! 43: utime(path, &ut); ! 44: chmod(path, mode); ! 45: chown(path, uid, gid); ! 46: chmod(path, mode); /* fix possibly cleared s[ug]id bits */ ! 47: } ! 48: ! 49: void ! 50: chtmugs(void) ! 51: { ! 52: struct chtmug *ch; ! 53: ! 54: /* we handle the chtmug list in the reverse order of which it ! 55: was built, which is just right for nested directories created ! 56: from tar files */ ! 57: for (ch = chtmuglist; ch; ch = ch->next) ! 58: chtmug(ch->path, ch->mtime, ch->mode, ch->uid, ch->gid); ! 59: } ! 60: ! 61: void ! 62: mkchtmug(char *path, time_t mtime, int mode, int uid, int gid) ! 63: { ! 64: struct chtmug *ch; ! 65: ! 66: ch = xmalloc(sizeof (struct chtmug)); ! 67: ch->path = xstrdup(path); ! 68: ch->mtime = mtime; ! 69: ch->mode = mode; ! 70: ch->uid = uid; ! 71: ch->gid = gid; ! 72: ch->next = chtmuglist; ! 73: chtmuglist= ch; ! 74: } ! 75: ! 76: void ! 77: mkdirs(char *path) ! 78: { ! 79: char *slash; ! 80: ! 81: slash = strrchr(path, '/'); ! 82: if (slash == path) ! 83: return; ! 84: if (slash) { ! 85: *slash = '\0'; ! 86: if (access(path, F_OK) != 0) { ! 87: mkdirs(path); ! 88: mkdir(path, 0777); ! 89: } ! 90: *slash = '/'; ! 91: } ! 92: } ! 93: ! 94: int ! 95: isdir(char *path) ! 96: { ! 97: struct stat st; ! 98: ! 99: if (stat(path, &st) == 0) ! 100: return S_ISDIR(st.st_mode); ! 101: return 0; ! 102: } ! 103: ! 104: int ! 105: extract(FILE *ifp) ! 106: { ! 107: struct tarbuf buf; ! 108: struct tarhdr hdr; ! 109: int fd, blocks; ! 110: FILE *ofp; ! 111: static char zeroes[TSIZE]; ! 112: ! 113: if (fread(&buf, sizeof buf, 1, ifp) != 1) ! 114: return 0; ! 115: if (memcmp(&buf, zeroes, sizeof zeroes) == 0) ! 116: return 0; ! 117: if (thdrget(&hdr, &buf) != 0) { ! 118: ++nerr; ! 119: fprintf(stderr, "tarx: bad input header\n"); ! 120: return 0; ! 121: } ! 122: if (tflag) ! 123: printf("%s\n", hdr.name); ! 124: if (vflag) ! 125: fprintf(stderr, "%s\n", hdr.name); ! 126: mkdirs(hdr.name); ! 127: switch (hdr.typeflag) { ! 128: case REGTYPE: ! 129: blocks = (hdr.size + TSIZE - 1) / TSIZE; ! 130: fd = creat(hdr.name, hdr.mode); ! 131: if (fd < 0) { ! 132: remove(hdr.name); ! 133: fd = creat(hdr.name, hdr.mode); ! 134: if (fd < 0) { ! 135: ++nerr; ! 136: fprintf(stderr, "tarx: can't create '%s'\n", ! 137: hdr.name); ! 138: discard(ifp, blocks * TSIZE); ! 139: return 1; ! 140: } ! 141: } ! 142: ofp = fdopen(fd, "w"); ! 143: fpcopy(ofp, ifp, hdr.size); ! 144: fclose(ofp); ! 145: close(fd); /* paranoia */ ! 146: discard(ifp, blocks * TSIZE - hdr.size); ! 147: chtmug(hdr.name, hdr.mtime, hdr.mode, hdr.uid, hdr.gid); ! 148: break; ! 149: ! 150: case DIRTYPE: ! 151: mkchtmug(hdr.name, hdr.mtime, hdr.mode, hdr.uid, hdr.gid); ! 152: if (!isdir(hdr.name)) { ! 153: remove(hdr.name); ! 154: if (mkdir(hdr.name, hdr.mode) < 0) { ! 155: ++nerr; ! 156: fprintf(stderr, "tarx: can't mkdir '%s'\n", ! 157: hdr.name); ! 158: return 1; ! 159: } ! 160: } ! 161: break; ! 162: ! 163: case LNKTYPE: ! 164: remove(hdr.name); ! 165: if (link(hdr.linkname, hdr.name) < 0) { ! 166: ++nerr; ! 167: fprintf(stderr, "tarx: can't link '%s' to '%s'\n", ! 168: hdr.linkname, hdr.name); ! 169: return 1; ! 170: } ! 171: break; ! 172: ! 173: case SYMTYPE: ! 174: remove(hdr.name); ! 175: if (symlink(hdr.linkname, hdr.name) < 0) { ! 176: ++nerr; ! 177: fprintf(stderr, "tarx: can't symlink '%s' to '%s'\n", ! 178: hdr.linkname, hdr.name); ! 179: return 1; ! 180: } ! 181: break; ! 182: ! 183: default: ! 184: fprintf(stderr, "tarx: unknown typeflag '%c'\n", hdr.typeflag); ! 185: return 1; ! 186: } ! 187: return 1; ! 188: } ! 189: ! 190: void ! 191: usage(void) ! 192: { ! 193: fprintf(stderr, "usage: tarx [-ftv]\n"); ! 194: exit(1); ! 195: } ! 196: ! 197: int ! 198: main(int argc, char *argv[]) ! 199: { ! 200: int c, i; ! 201: prog = argv[0]; ! 202: ! 203: while ((c = getopt(argc, argv, "ftv")) != EOF) ! 204: switch (c) { ! 205: case 'f': ! 206: ++fflag; ! 207: break; ! 208: case 't': ! 209: ++tflag; ! 210: break; ! 211: case 'v': ! 212: ++vflag; ! 213: break; ! 214: default: ! 215: usage(); ! 216: break; ! 217: } ! 218: if (optind != argc) ! 219: usage(); ! 220: if (fflag) { ! 221: setbuf(stdin, NULL); ! 222: extract(stdin); ! 223: } else ! 224: while (extract(stdin)) ! 225: ; ! 226: chtmugs(); ! 227: if (ferror(stdin)) ! 228: return 1; ! 229: return nerr ? 1 : 0; ! 230: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.