Annotation of researchv10no/cmd/odist/tar/tarx.c, revision 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.