|
|
1.1 ! root 1: /* ! 2: * dumpdir [af [dumpfile]] ! 3: * a Show all entries (include `.' and `..'). ! 4: * f Use `dumpfile', not default. ! 5: */ ! 6: #include <stdio.h> ! 7: #include <dumptape.h> ! 8: #include <canon.h> ! 9: #include <mdata.h> ! 10: #include <signal.h> ! 11: ! 12: /* ! 13: * Structure used to remember ! 14: * things about all the directories ! 15: * on the tape. ! 16: */ ! 17: struct dlist ! 18: { ! 19: struct dlist *dl_dlp; /* Link to next */ ! 20: ino_t dl_ino; /* Inumber */ ! 21: int dl_dejavu; /* Already seen flag */ ! 22: long dl_seek; /* Tempfile base */ ! 23: long dl_size; /* Size */ ! 24: }; ! 25: ! 26: char *dtn = DTAPE; /* Tape name */ ! 27: FILE *dtp; /* Tape file pointer */ ! 28: char tfn[30] = "/tmp/ddXXXXXX"; /* Temp file name */ ! 29: FILE *tfp; /* Temp file pointer */ ! 30: int aflag; /* All flag */ ! 31: fsize_t length = 1; /* Length in bytes of volume */ ! 32: fsize_t nread; /* Number of bytes read from volume */ ! 33: struct dlist *dlist; /* List of remembered directories */ ! 34: struct dlist *droot; /* Pointer to first directory */ ! 35: char dstr[1000]; /* Name string */ ! 36: char *dstrp = &dstr[0]; /* Pointer into the above */ ! 37: int reel = 1; /* Reel # */ ! 38: char *ddbuf; /* Dump data buffer */ ! 39: char *ddend; /* Ptr to end of dump data buffer */ ! 40: int ddnbuf; /* Size of buffer (bytes) */ ! 41: union dumpdata *ddptr; /* Ptr to current record in buffer */ ! 42: char *map; /* Inode map */ ! 43: ! 44: union dumpdata *readdump(); ! 45: struct dlist *findnode(); ! 46: int cleanup(); ! 47: char *calloc(); ! 48: ! 49: main(argc, argv) ! 50: char *argv[]; ! 51: { ! 52: register char *p; ! 53: register c, i; ! 54: ! 55: if (argc > 1) { ! 56: i = 1; ! 57: p = argv[1]; ! 58: while ((c = *p++) != '\0') { ! 59: switch (c) { ! 60: ! 61: case 'a': ! 62: aflag = 1; ! 63: break; ! 64: ! 65: case 'f': ! 66: if (++i >= argc) ! 67: usage(); ! 68: dtn = argv[i]; ! 69: break; ! 70: ! 71: default: ! 72: usage(); ! 73: } ! 74: } ! 75: } ! 76: if ((dtp=fopen(dtn, "r")) == NULL) ! 77: fatal("%s: cannot open dump file", dtn); ! 78: if (signal(SIGINT, SIG_IGN) != SIG_IGN) ! 79: signal(SIGINT, cleanup); ! 80: mktemp(tfn); ! 81: if ((tfp=fopen(tfn, "w")) == NULL ! 82: || (tfp=freopen(tfn, "r+w", tfp)) == NULL) ! 83: fatal("%s: cannot create temporary file", tfn); ! 84: nextvol(); ! 85: readdirs(); ! 86: if (droot == NULL) ! 87: fatal("no directories"); ! 88: dumpdirs(droot); ! 89: delexit(0); ! 90: } ! 91: ! 92: /* ! 93: * This routine has two jobs. ! 94: * It reads in the dump file header and ! 95: * checks it out, looking for strangenesses ! 96: * in format. It also is responsible for ! 97: * using information in the header to ! 98: * allocate the necessary map and dump I/O ! 99: * buffers. ! 100: */ ! 101: readhead() ! 102: { ! 103: static struct dumpheader dh; ! 104: register char *p; ! 105: register checksum; ! 106: ! 107: if (read(fileno(dtp), &dh, sizeof dh) != sizeof dh) ! 108: fatal("header read error"); ! 109: nread = sizeof dh; ! 110: canint(dh.dh_magic); ! 111: canino(dh.dh_nino); ! 112: cantime(dh.dh_bdate); ! 113: cantime(dh.dh_ddate); ! 114: canint(dh.dh_level); ! 115: canint(dh.dh_reel); ! 116: canint(dh.dh_blocking); ! 117: cansize(dh.dh_nbyte); ! 118: canint(dh.dh_checksum); ! 119: if (dh.dh_magic != DH_MAG) ! 120: fatal("not a dump"); ! 121: p = (char *) &dh; ! 122: checksum = 0; ! 123: while (p < (char *) &dh.dh_checksum) ! 124: checksum += (*p++) & 0377; ! 125: if (checksum != dh.dh_checksum) ! 126: fatal("header checksum error"); ! 127: if (dh.dh_reel != reel) ! 128: fatal("wrong reel (is %d, not %d)", dh.dh_reel, reel); ! 129: ++reel; ! 130: if (map != NULL) ! 131: free(map); ! 132: if (ddbuf != NULL) ! 133: free(ddbuf); ! 134: if ((map = calloc(sizeof(char), (dh.dh_nino+NBCHAR-1)/NBCHAR)) == NULL) ! 135: fatal("out of memory (map)"); ! 136: ddnbuf = dh.dh_blocking * sizeof(union dumpdata); ! 137: if ((ddbuf = malloc(ddnbuf)) == NULL) ! 138: fatal("out of memory (buffer)"); ! 139: ddend = &ddbuf[ddnbuf]; ! 140: ddptr = (union dumpdata *) ddend; ! 141: length = dh.dh_nbyte; ! 142: } ! 143: ! 144: /* ! 145: * Read in all the directories. ! 146: * This routine assumes that the map entries ! 147: * have been put out before the inodes and ! 148: * that all the directories have been put out ! 149: * before the files. ! 150: */ ! 151: readdirs() ! 152: { ! 153: register union dumpdata *ddp; ! 154: register struct dlist *dlp; ! 155: ! 156: while ((ddp=readdump()) != NULL) { ! 157: canint(ddp->dd_type); ! 158: switch (ddp->dd_type) { ! 159: ! 160: case DD_EOT: ! 161: return; ! 162: ! 163: case DD_DATA: ! 164: canino(ddp->dd_ino); ! 165: candaddr(ddp->dd_block); ! 166: canint(ddp->dd_size); ! 167: if (dlist==NULL || dlist->dl_ino!=ddp->dd_ino) ! 168: fatal("out of sync"); ! 169: fseek(tfp, dlist->dl_seek+(BUFSIZ*ddp->dd_block), 0); ! 170: fwrite(ddp->dd_data, sizeof(char), BUFSIZ, tfp); ! 171: if (ferror(tfp)) ! 172: fatal("temporary file write error"); ! 173: break; ! 174: ! 175: case DD_INO: ! 176: canino(ddp->dd_ino); ! 177: canshort(ddp->dd_dinode.di_mode); ! 178: cansize(ddp->dd_dinode.di_size); ! 179: if ((ddp->dd_dinode.di_mode&IFMT) != IFDIR) ! 180: return; ! 181: dlp = (struct dlist *) malloc(sizeof(struct dlist)); ! 182: if (dlp == NULL) ! 183: fatal("out of memory (directory)"); ! 184: dlp->dl_dlp = dlist; ! 185: dlist = dlp; ! 186: if (droot == NULL) ! 187: droot = dlp; ! 188: dlp->dl_ino = ddp->dd_ino; ! 189: dlp->dl_dejavu = 0; ! 190: dlp->dl_seek = ftell(tfp); ! 191: dlp->dl_size = ddp->dd_dinode.di_size; ! 192: break; ! 193: ! 194: case DD_MAP: ! 195: canino(ddp->dd_ino); ! 196: canint(ddp->dd_nmap); ! 197: setmap(ddp); ! 198: break; ! 199: ! 200: default: ! 201: fatal("bad type %d", ddp->dd_type); ! 202: } ! 203: } ! 204: } ! 205: ! 206: /* ! 207: * Process a map entry. ! 208: * Set a bit in the map for every inode ! 209: * whose dump map entry has the DD_DUMP flag ! 210: * set. ! 211: */ ! 212: setmap(ddp) ! 213: union dumpdata *ddp; ! 214: { ! 215: register char *mmapp, *dmapp; ! 216: register mmask; ! 217: register nmapb; ! 218: ! 219: mmapp = &map[--ddp->dd_ino/NBCHAR]; ! 220: mmask = 01 << (ddp->dd_ino%NBCHAR); ! 221: dmapp = &ddp->dd_map[0]; ! 222: nmapb = ddp->dd_nmap; ! 223: while (nmapb--) { ! 224: if (((*dmapp++)&DD_DUMP) != 0) ! 225: *mmapp |= mmask; ! 226: if ((mmask <<= 1) == (01<<NBCHAR)) { ! 227: ++mmapp; ! 228: mmask = 01; ! 229: } ! 230: } ! 231: } ! 232: ! 233: /* ! 234: * Return a pointer to the ! 235: * next dump file item. This routine ! 236: * knows all about reading the ! 237: * next tape in a multitape dump. ! 238: */ ! 239: union dumpdata * ! 240: readdump() ! 241: { ! 242: register nb; ! 243: ! 244: while ((char *) ddptr == ddend) { ! 245: if (length != 0 && (nread+ddnbuf) > length) { ! 246: nextvol(); ! 247: continue; ! 248: } ! 249: if ((nb = read(fileno(dtp), ddbuf, ddnbuf)) != ddnbuf) { ! 250: if (nb != 0) ! 251: fatal("dump read error"); ! 252: nextvol(); ! 253: continue; ! 254: } ! 255: nread += nb; ! 256: ddptr = (union dumpdata *) ddbuf; ! 257: break; ! 258: } ! 259: return (ddptr++); ! 260: } ! 261: ! 262: /* ! 263: * Read the next reel or volume. ! 264: */ ! 265: nextvol() ! 266: { ! 267: fclose(dtp); ! 268: fprintf(stderr, "dumpdir: mount %s %d, type return key ...", ! 269: length ? "volume" : "reel", reel); ! 270: if (fgets(dstr, sizeof(dstr), stdin) == NULL) ! 271: delexit(1); ! 272: if ((dtp = fopen(dtn, "r")) == NULL) ! 273: fatal("%s: cannot open dump tape", dtn); ! 274: readhead(); ! 275: } ! 276: ! 277: /* ! 278: * Start at the root and ! 279: * print all of the directories. ! 280: * Don't print the names of things that ! 281: * the map says are not on the tape. ! 282: */ ! 283: dumpdirs(dlp) ! 284: register struct dlist *dlp; ! 285: { ! 286: char *sdstrp; ! 287: struct direct dirbuf; ! 288: register char *p1, *p2; ! 289: register c; ! 290: register struct dlist *sdlp; ! 291: ino_t ino; ! 292: ! 293: dlp->dl_dejavu = 1; ! 294: while (dlp->dl_size != 0) { ! 295: fseek(tfp, dlp->dl_seek, 0); ! 296: if (fread(&dirbuf, sizeof(dirbuf), 1, tfp) != 1) ! 297: fatal("temporary file read error"); ! 298: dlp->dl_seek += sizeof(struct direct); ! 299: dlp->dl_size -= sizeof(struct direct); ! 300: if (aflag == 0) { ! 301: if (strncmp(dirbuf.d_name, ".", DIRSIZ) == 0) ! 302: continue; ! 303: if (strncmp(dirbuf.d_name, "..", DIRSIZ) == 0) ! 304: continue; ! 305: } ! 306: canino(dirbuf.d_ino); ! 307: if ((ino = dirbuf.d_ino)!=0 && getbit(ino)!=0) { ! 308: p1 = sdstrp = dstrp; ! 309: if (p1 != dstr) ! 310: *p1++ = '/'; ! 311: p2 = dirbuf.d_name; ! 312: while (p2<&dirbuf.d_name[DIRSIZ] && (c=*p2++)) ! 313: *p1++ = c; ! 314: *p1 = '\0'; ! 315: dstrp = p1; ! 316: printf("%u\t%s\n", ino, dstr); ! 317: if ((sdlp=findnode(ino))!=NULL && sdlp->dl_dejavu==0) ! 318: dumpdirs(sdlp); ! 319: dstrp = sdstrp; ! 320: *dstrp = '\0'; ! 321: } ! 322: } ! 323: dlp->dl_dejavu = 0; ! 324: } ! 325: ! 326: /* ! 327: * Get the dumped bit for ! 328: * inode `ino' from the big bit map. ! 329: */ ! 330: getbit(ino) ! 331: ino_t ino; ! 332: { ! 333: register mapent; ! 334: ! 335: mapent = map[--ino/NBCHAR]; ! 336: return (mapent & (01<<ino%NBCHAR)); ! 337: } ! 338: ! 339: /* ! 340: * Return the dlist pointer ! 341: * for directory inode `ino', or NULL ! 342: * if it is not there. Not there means ! 343: * not a directory. ! 344: */ ! 345: struct dlist * ! 346: findnode(ino) ! 347: register ino_t ino; ! 348: { ! 349: register struct dlist *dlp; ! 350: ! 351: dlp = dlist; ! 352: while (dlp != NULL) { ! 353: if (dlp->dl_ino == ino) ! 354: break; ! 355: dlp = dlp->dl_dlp; ! 356: } ! 357: return (dlp); ! 358: } ! 359: ! 360: /* ! 361: * Nasty nasty nasty. ! 362: */ ! 363: fatal(a) ! 364: { ! 365: fprintf(stderr, "dumpdir: %r", &a); ! 366: fprintf(stderr, "\n"); ! 367: delexit(1); ! 368: } ! 369: ! 370: /* ! 371: * This routine is called from the ! 372: * interupt signal. It points off to dumpdir ! 373: * who deletes the temp file and returns ! 374: * the error status. ! 375: */ ! 376: cleanup() ! 377: { ! 378: delexit(1); ! 379: } ! 380: ! 381: /* ! 382: * A special version of `exit' that ! 383: * cleans up by unlinking the temporary ! 384: * file. ! 385: */ ! 386: delexit(s) ! 387: { ! 388: if (tfp != NULL) ! 389: unlink(tfn); ! 390: exit(s); ! 391: } ! 392: ! 393: /* ! 394: * Print the usage message and ! 395: * exit. ! 396: */ ! 397: usage() ! 398: { ! 399: fprintf(stderr, "Usage: dumpdir [af [dumpfile]]\n"); ! 400: exit(1); ! 401: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.