|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 8345 (0x2099) Types: TextFile Notes: UNIX file Names: »dumpdir.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─ ⟦this⟧ »cmd/dump/dumpdir.c«
/* * dumpdir [af [dumpfile]] * a Show all entries (include `.' and `..'). * f Use `dumpfile', not default. */ #include <stdio.h> #include <dumptape.h> #include <canon.h> #include <mdata.h> #include <signal.h> /* * Structure used to remember * things about all the directories * on the tape. */ struct dlist { struct dlist *dl_dlp; /* Link to next */ ino_t dl_ino; /* Inumber */ int dl_dejavu; /* Already seen flag */ long dl_seek; /* Tempfile base */ long dl_size; /* Size */ }; char *dtn = DTAPE; /* Tape name */ FILE *dtp; /* Tape file pointer */ char tfn[30] = "/tmp/ddXXXXXX"; /* Temp file name */ FILE *tfp; /* Temp file pointer */ int aflag; /* All flag */ size_t length = 1; /* Length in bytes of volume */ size_t nread; /* Number of bytes read from volume */ struct dlist *dlist; /* List of remembered directories */ struct dlist *droot; /* Pointer to first directory */ char dstr[1000]; /* Name string */ char *dstrp = &dstr[0]; /* Pointer into the above */ int reel = 1; /* Reel # */ char *ddbuf; /* Dump data buffer */ char *ddend; /* Ptr to end of dump data buffer */ int ddnbuf; /* Size of buffer (bytes) */ union dumpdata *ddptr; /* Ptr to current record in buffer */ char *map; /* Inode map */ union dumpdata *readdump(); struct dlist *findnode(); int cleanup(); char *calloc(); main(argc, argv) char *argv[]; { register char *p; register c, i; if (argc > 1) { i = 1; p = argv[1]; while ((c = *p++) != '\0') { switch (c) { case 'a': aflag = 1; break; case 'f': if (++i >= argc) usage(); dtn = argv[i]; break; default: usage(); } } } if ((dtp=fopen(dtn, "r")) == NULL) fatal("%s: cannot open dump file", dtn); if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, cleanup); mktemp(tfn); if ((tfp=fopen(tfn, "w")) == NULL || (tfp=freopen(tfn, "r+w", tfp)) == NULL) fatal("%s: cannot create temporary file", tfn); nextvol(); readdirs(); if (droot == NULL) fatal("no directories"); dumpdirs(droot); delexit(0); } /* * This routine has two jobs. * It reads in the dump file header and * checks it out, looking for strangenesses * in format. It also is responsible for * using information in the header to * allocate the necessary map and dump I/O * buffers. */ readhead() { static struct dumpheader dh; register char *p; register checksum; if (read(fileno(dtp), &dh, sizeof dh) != sizeof dh) fatal("header read error"); nread = sizeof dh; canint(dh.dh_magic); canino(dh.dh_nino); cantime(dh.dh_bdate); cantime(dh.dh_ddate); canint(dh.dh_level); canint(dh.dh_reel); canint(dh.dh_blocking); cansize(dh.dh_nbyte); canint(dh.dh_checksum); if (dh.dh_magic != DH_MAG) fatal("not a dump"); p = (char *) &dh; checksum = 0; while (p < (char *) &dh.dh_checksum) checksum += (*p++) & 0377; if (checksum != dh.dh_checksum) fatal("header checksum error"); if (dh.dh_reel != reel) fatal("wrong reel (is %d, not %d)", dh.dh_reel, reel); ++reel; if (map != NULL) free(map); if (ddbuf != NULL) free(ddbuf); if ((map = calloc(sizeof(char), (dh.dh_nino+NBCHAR-1)/NBCHAR)) == NULL) fatal("out of memory (map)"); ddnbuf = dh.dh_blocking * sizeof(union dumpdata); if ((ddbuf = malloc(ddnbuf)) == NULL) fatal("out of memory (buffer)"); ddend = &ddbuf[ddnbuf]; ddptr = (union dumpdata *) ddend; length = dh.dh_nbyte; } /* * Read in all the directories. * This routine assumes that the map entries * have been put out before the inodes and * that all the directories have been put out * before the files. */ readdirs() { register union dumpdata *ddp; register struct dlist *dlp; while ((ddp=readdump()) != NULL) { canint(ddp->dd_type); switch (ddp->dd_type) { case DD_EOT: return; case DD_DATA: canino(ddp->dd_ino); candaddr(ddp->dd_block); canint(ddp->dd_size); if (dlist==NULL || dlist->dl_ino!=ddp->dd_ino) fatal("out of sync"); fseek(tfp, dlist->dl_seek+(BUFSIZ*ddp->dd_block), 0); fwrite(ddp->dd_data, sizeof(char), BUFSIZ, tfp); if (ferror(tfp)) fatal("temporary file write error"); break; case DD_INO: canino(ddp->dd_ino); canshort(ddp->dd_dinode.di_mode); cansize(ddp->dd_dinode.di_size); if ((ddp->dd_dinode.di_mode&IFMT) != IFDIR) return; dlp = (struct dlist *) malloc(sizeof(struct dlist)); if (dlp == NULL) fatal("out of memory (directory)"); dlp->dl_dlp = dlist; dlist = dlp; if (droot == NULL) droot = dlp; dlp->dl_ino = ddp->dd_ino; dlp->dl_dejavu = 0; dlp->dl_seek = ftell(tfp); dlp->dl_size = ddp->dd_dinode.di_size; break; case DD_MAP: canino(ddp->dd_ino); canint(ddp->dd_nmap); setmap(ddp); break; default: fatal("bad type %d", ddp->dd_type); } } } /* * Process a map entry. * Set a bit in the map for every inode * whose dump map entry has the DD_DUMP flag * set. */ setmap(ddp) union dumpdata *ddp; { register char *mmapp, *dmapp; register mmask; register nmapb; mmapp = &map[--ddp->dd_ino/NBCHAR]; mmask = 01 << (ddp->dd_ino%NBCHAR); dmapp = &ddp->dd_map[0]; nmapb = ddp->dd_nmap; while (nmapb--) { if (((*dmapp++)&DD_DUMP) != 0) *mmapp |= mmask; if ((mmask <<= 1) == (01<<NBCHAR)) { ++mmapp; mmask = 01; } } } /* * Return a pointer to the * next dump file item. This routine * knows all about reading the * next tape in a multitape dump. */ union dumpdata * readdump() { register nb; while ((char *) ddptr == ddend) { if (length != 0 && (nread+ddnbuf) > length) { nextvol(); continue; } if ((nb = read(fileno(dtp), ddbuf, ddnbuf)) != ddnbuf) { if (nb != 0) fatal("dump read error"); nextvol(); continue; } nread += nb; ddptr = (union dumpdata *) ddbuf; break; } return (ddptr++); } /* * Read the next reel or volume. */ nextvol() { fclose(dtp); fprintf(stderr, "dumpdir: mount %s %d, type return key ...", length ? "volume" : "reel", reel); if (fgets(dstr, sizeof(dstr), stdin) == NULL) delexit(1); if ((dtp = fopen(dtn, "r")) == NULL) fatal("%s: cannot open dump tape", dtn); readhead(); } /* * Start at the root and * print all of the directories. * Don't print the names of things that * the map says are not on the tape. */ dumpdirs(dlp) register struct dlist *dlp; { char *sdstrp; struct direct dirbuf; register char *p1, *p2; register c; register struct dlist *sdlp; ino_t ino; dlp->dl_dejavu = 1; while (dlp->dl_size != 0) { fseek(tfp, dlp->dl_seek, 0); if (fread(&dirbuf, sizeof(dirbuf), 1, tfp) != 1) fatal("temporary file read error"); dlp->dl_seek += sizeof(struct direct); dlp->dl_size -= sizeof(struct direct); if (aflag == 0) { if (strncmp(dirbuf.d_name, ".", DIRSIZ) == 0) continue; if (strncmp(dirbuf.d_name, "..", DIRSIZ) == 0) continue; } canino(dirbuf.d_ino); if ((ino = dirbuf.d_ino)!=0 && getbit(ino)!=0) { p1 = sdstrp = dstrp; if (p1 != dstr) *p1++ = '/'; p2 = dirbuf.d_name; while (p2<&dirbuf.d_name[DIRSIZ] && (c=*p2++)) *p1++ = c; *p1 = '\0'; dstrp = p1; printf("%u\t%s\n", ino, dstr); if ((sdlp=findnode(ino))!=NULL && sdlp->dl_dejavu==0) dumpdirs(sdlp); dstrp = sdstrp; *dstrp = '\0'; } } dlp->dl_dejavu = 0; } /* * Get the dumped bit for * inode `ino' from the big bit map. */ getbit(ino) ino_t ino; { register mapent; mapent = map[--ino/NBCHAR]; return (mapent & (01<<ino%NBCHAR)); } /* * Return the dlist pointer * for directory inode `ino', or NULL * if it is not there. Not there means * not a directory. */ struct dlist * findnode(ino) register ino_t ino; { register struct dlist *dlp; dlp = dlist; while (dlp != NULL) { if (dlp->dl_ino == ino) break; dlp = dlp->dl_dlp; } return (dlp); } /* * Nasty nasty nasty. */ fatal(a) { fprintf(stderr, "dumpdir: %r", &a); fprintf(stderr, "\n"); delexit(1); } /* * This routine is called from the * interupt signal. It points off to dumpdir * who deletes the temp file and returns * the error status. */ cleanup() { delexit(1); } /* * A special version of `exit' that * cleans up by unlinking the temporary * file. */ delexit(s) { if (tfp != NULL) unlink(tfn); exit(s); } /* * Print the usage message and * exit. */ usage() { fprintf(stderr, "Usage: dumpdir [af [dumpfile]]\n"); exit(1); }