|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.