Annotation of researchv10no/cmd/odist/tar/tarx.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.