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