Annotation of mstools/posix/samples/psxarc/cpio.c, revision 1.1

1.1     ! root        1: //
        !             2: // Stuff to deal with cpio-format files
        !             3: //
        !             4: 
        !             5: #include <stdio.h>
        !             6: #include <unistd.h>
        !             7: #include <stdlib.h>
        !             8: #include <fcntl.h>
        !             9: #include <dirent.h>
        !            10: #include <limits.h>
        !            11: #include <sys/stat.h>
        !            12: #include <string.h>
        !            13: 
        !            14: #include "cpio.h"
        !            15: #include "buf.h"
        !            16: #include "psxarc.h"
        !            17: #include "links.h"
        !            18: 
        !            19: extern int errno;
        !            20: extern int fVerbose;
        !            21: 
        !            22: static void cpio_dodir(PBUF pb, char *pchfile, struct stat *psb);
        !            23: 
        !            24: //
        !            25: // Convert string pch of length len from octal and return the value.
        !            26: //
        !            27: static int
        !            28: cpio_atoi(char *pch, int len)
        !            29: {
        !            30:        int num = 0, i;
        !            31: 
        !            32:        for (i = 0; i < len; ++i) {
        !            33:                num = num * 8 + (pch[i] - '0');
        !            34:        }
        !            35:        return num;
        !            36: }
        !            37: 
        !            38: void
        !            39: CpioList(PBUF pb)
        !            40: {
        !            41:        int nbytes;
        !            42:        int namesize, filesize;
        !            43:        int i;
        !            44:        static char pathname[PATH_MAX + NAME_MAX + 2];
        !            45:        CPIO_HEAD x;
        !            46: 
        !            47:        for (;;) {
        !            48:                //
        !            49:                // read the cpio header
        !            50:                //
        !            51: 
        !            52:                for (i = 0; i < sizeof(x); ++i) {
        !            53:                        ((char *)&x)[i] = bgetc(pb);
        !            54:                }
        !            55:                if (0 != strncmp(x.c_magic, MAGIC, strlen(MAGIC))) {
        !            56:                        fprintf(stderr,
        !            57:                                "%s: this doesn't look like a cpio archive\n",
        !            58:                                progname);
        !            59:                        exit(1);
        !            60:                }
        !            61:                
        !            62:                namesize = cpio_atoi(x.c_namesize, sizeof(x.c_namesize));
        !            63:                filesize = cpio_atoi(x.c_filesize, sizeof(x.c_filesize));
        !            64: 
        !            65:                for (i = 0; i < namesize; ++i) {
        !            66:                        // nb:  namesize includes the null
        !            67:                        pathname[i] = bgetc(pb);
        !            68:                }
        !            69:                if (0 == strcmp(pathname, LASTFILENAME)) {
        !            70:                        break;
        !            71:                }
        !            72: 
        !            73:                printf("%s\n", pathname);
        !            74:        
        !            75:                // skip the file data
        !            76:                for (i = 0; i < filesize; ++i) {
        !            77:                        (void)bgetc(pb);
        !            78:                }
        !            79:        }
        !            80: }
        !            81: 
        !            82: void
        !            83: CpioRead(PBUF pb)
        !            84: {
        !            85:        int fdout;
        !            86:        int mode;
        !            87:        int i;
        !            88:        int namesize, filesize;
        !            89:        static CPIO_HEAD x;
        !            90:        static char pathname[PATH_MAX + NAME_MAX + 2];
        !            91: 
        !            92:        for (;;) {
        !            93:                //
        !            94:                // read the cpio header
        !            95:                //
        !            96: 
        !            97:                for (i = 0; i < sizeof(x); ++i) {
        !            98:                        ((char *)&x)[i] = bgetc(pb);
        !            99:                }
        !           100: 
        !           101:                if (0 != strncmp(x.c_magic, MAGIC, strlen(MAGIC))) {
        !           102:                        fprintf(stderr,
        !           103:                                "%s: this doesn't look like a cpio archive\n",
        !           104:                                progname);
        !           105:                        exit(1);
        !           106:                }
        !           107:                
        !           108:                namesize = cpio_atoi(x.c_namesize, sizeof(x.c_namesize));
        !           109:                filesize = cpio_atoi(x.c_filesize, sizeof(x.c_filesize));
        !           110: 
        !           111:                for (i = 0; i < namesize; ++i) {
        !           112:                        // nb:  namesize includes the null
        !           113:                        pathname[i] = bgetc(pb);
        !           114:                }
        !           115:                if (0 == strcmp(pathname, LASTFILENAME)) {
        !           116:                        break;
        !           117:                }
        !           118:                
        !           119:                if (fVerbose) {
        !           120:                        printf("%s\n", pathname);
        !           121:                }
        !           122: 
        !           123:                mode = cpio_atoi(x.c_mode, sizeof(x.c_mode));
        !           124: 
        !           125:                if (mode & C_ISDIR) {
        !           126:                        mkdir(pathname, 0777);
        !           127:                } else if (mode & C_ISFIFO) {
        !           128:                        mkfifo(pathname, 0666);
        !           129:                } else if (mode & C_ISREG) {
        !           130:                        fdout = open(pathname, O_WRONLY | O_CREAT, 0666);
        !           131:                        if (-1 == fdout) {
        !           132:                                fprintf(stderr, "%s: open: ", progname);
        !           133:                                perror(pathname);
        !           134: 
        !           135:                                // we could continue, but we'd have to be sure
        !           136:                                // to skip this file's data.
        !           137: 
        !           138:                                exit(1);
        !           139:                        }
        !           140:                        for (i = 0; i < filesize; ++i) {
        !           141:                                char c;
        !           142:                                c = (char)bgetc(pb);
        !           143:                                (void)write(fdout, &c, 1);
        !           144:                                --filesize;
        !           145:                        }
        !           146:                        (void)close(fdout);
        !           147:                } else if (mode & C_ISLNK) {
        !           148:                        // XXX.mjb: symbolic link
        !           149:                } else {
        !           150:                        fprintf(stderr, "%s: unknown mode 0%o\n", progname, mode);
        !           151:                        exit(4);
        !           152:                }
        !           153:        }
        !           154: }
        !           155: 
        !           156: void
        !           157: cpio_itoa(int i, char *pch, int len)
        !           158: {
        !           159:        int j;
        !           160:        char buf[20];
        !           161: 
        !           162:        sprintf(buf, "%o", i);
        !           163: 
        !           164:        j = strlen(buf);
        !           165:        if (j > len) {
        !           166:                printf("itoa: not enough room in buf: need %d, have %d\n",
        !           167:                        j, len);
        !           168:                exit(3);
        !           169:        }
        !           170: 
        !           171:        memset(pch, '0', len);
        !           172:        strncpy(&pch[len - j], buf, strlen(buf));
        !           173: }
        !           174: 
        !           175: void
        !           176: CpioWrite(PBUF pb, char **files, int count)
        !           177: {
        !           178:        CPIO_HEAD h;
        !           179:        struct stat statbuf;
        !           180:        int i, len;
        !           181:        int fdin;
        !           182: 
        !           183:        (void)strncpy(h.c_magic, MAGIC, strlen(MAGIC));
        !           184:        
        !           185:        while (count > 0) {
        !           186:                if (fVerbose) {
        !           187:                        printf("%s\n", *files);
        !           188:                }
        !           189:                if (-1 == (fdin = open(*files, O_RDONLY))) {
        !           190:                        fprintf(stderr, "%s: open: ");
        !           191:                        perror(*files);
        !           192:                        exit(1);
        !           193:                }       
        !           194:                if (-1 == fstat(fdin, &statbuf)) {
        !           195:                        perror("fstat");
        !           196:                        exit(1);
        !           197:                }
        !           198: 
        !           199:                cpio_itoa(strlen(*files) + 1, h.c_namesize, sizeof(h.c_namesize));
        !           200:                cpio_itoa(statbuf.st_dev, h.c_dev, sizeof(h.c_dev));
        !           201:                cpio_itoa(statbuf.st_ino, h.c_ino, sizeof(h.c_ino));
        !           202:                cpio_itoa(statbuf.st_uid, h.c_uid, sizeof(h.c_uid));
        !           203:                cpio_itoa(statbuf.st_gid, h.c_gid, sizeof(h.c_gid));
        !           204:                cpio_itoa(statbuf.st_nlink, h.c_nlink, sizeof(h.c_nlink));
        !           205:                cpio_itoa(statbuf.st_mtime, h.c_mtime, sizeof(h.c_mtime));
        !           206: 
        !           207:                if (S_ISDIR(statbuf.st_mode)) {
        !           208:                        cpio_itoa(C_ISDIR, h.c_mode, sizeof(h.c_mode));
        !           209:                        cpio_itoa(0, h.c_filesize, sizeof(h.c_filesize));
        !           210: 
        !           211:                        // write the header
        !           212: 
        !           213:                        for (i = 0; i < sizeof(h); ++i) {
        !           214:                                bputc(pb, ((char *)&h)[i]);
        !           215:                        }
        !           216: 
        !           217:                        // write the directory name
        !           218: 
        !           219:                        len = strlen(*files) + 1;       // the nul, too
        !           220:                        for (i = 0; i < len; ++i) {
        !           221:                                bputc(pb, (*files)[i]);
        !           222:                        }
        !           223: 
        !           224:                        // write the directory contents
        !           225:                        cpio_dodir(pb, *files, &statbuf);
        !           226: 
        !           227:                        count--;
        !           228:                        files++;
        !           229:                        continue;
        !           230:                }
        !           231:                if (S_ISFIFO(statbuf.st_mode)) {
        !           232:                        cpio_itoa(C_ISFIFO, h.c_mode, sizeof(h.c_mode));
        !           233:                        cpio_itoa(0, h.c_filesize, sizeof(h.c_filesize));
        !           234:                } else if (S_ISREG(statbuf.st_mode)) {
        !           235:                        cpio_itoa(C_ISREG, h.c_mode, sizeof(h.c_mode));
        !           236:                        cpio_itoa(statbuf.st_size, h.c_filesize, sizeof(h.c_filesize));
        !           237:                } else {
        !           238:                        printf("I'm not prepared to deal with the file type "
        !           239:                                "of %s\n", *files);
        !           240:                        exit(2);
        !           241:                }
        !           242: 
        !           243:                // write the cpio header
        !           244:                for (i = 0; i < sizeof(h); ++i) {
        !           245:                        bputc(pb, ((char *)&h)[i]);
        !           246:                }
        !           247: 
        !           248:                // write the filename
        !           249: 
        !           250:                len = strlen(*files) + 1;               // the nul, too
        !           251:                for (i = 0; i < len; ++i) {
        !           252:                        bputc(pb, (*files)[i]);
        !           253:                }
        !           254: 
        !           255:                while (statbuf.st_size > 0) {
        !           256:                        char b;
        !           257:                        (void)read(fdin, &b, 1);
        !           258:                        bputc(pb, b);
        !           259:                        --statbuf.st_size;
        !           260:                }
        !           261: 
        !           262:                close(fdin);
        !           263:                count--;
        !           264:                files++;
        !           265:        }
        !           266: 
        !           267: #if 0
        !           268:        printf("", count);              // null function call to work around    
        !           269:                                        // mips code generator problem
        !           270: #endif
        !           271: }
        !           272: 
        !           273: static void
        !           274: cpio_dodir(PBUF pb, char *pchfile, struct stat *psb)
        !           275: {
        !           276:        DIR *dp;
        !           277:        struct dirent *dirent;
        !           278:        char *pch;
        !           279: 
        !           280:        dp = opendir(pchfile);
        !           281:        if (NULL == dp) {
        !           282:                fprintf(stderr, "%s: opendir: ", progname);
        !           283:                perror(pchfile);
        !           284:                return;
        !           285:        }
        !           286:        while (NULL != (dirent = readdir(dp))) {
        !           287:                if ('.' == dirent->d_name[0] &&
        !           288:                   ('\0' == dirent->d_name[1] ||
        !           289:                    0 == strcmp(dirent->d_name, ".."))) {
        !           290:                        continue;
        !           291:                }
        !           292: 
        !           293:                //
        !           294:                // Recurse.  We append the file name read from the directory
        !           295:                // to the directory name we were given and call CpioWrite to
        !           296:                // put it on the tape.  It could be a directory, so we could
        !           297:                // end up back here.  This means that we must allocate the
        !           298:                // space for the pathname dynamically.  This seems like it
        !           299:                // will be a big time-waster.
        !           300:                //
        !           301:        
        !           302:                // strlen + 2:  one extra for '/', one extra for nul.
        !           303:                pch = malloc(strlen(pchfile) + strlen(dirent->d_name) + 2);
        !           304:                if (NULL == pch) {
        !           305:                        fprintf(stderr, "%s: virtual memory exhausted\n",
        !           306:                            progname);
        !           307:                        exit(4);
        !           308:                }
        !           309:                strcpy(pch, pchfile);
        !           310:                strcat(pch, "/");
        !           311:                strcat(pch, dirent->d_name);
        !           312:        
        !           313:                CpioWrite(pb, &pch, 1);
        !           314:        
        !           315:                free(pch);
        !           316:        }
        !           317:        (void)closedir(dp);
        !           318: }

unix.superglobalmegacorp.com

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