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

unix.superglobalmegacorp.com

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