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