Annotation of mstools/posix/samples/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 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.