|
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 - metrics - download
Length: 8377 (0x20b9) Types: TextFile Notes: UNIX file Names: »bad.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─⟦this⟧ »cmd/bad.c«
/* * For manipulating bad blocks. */ #include <stdio.h> #include <canon.h> #include <filsys.h> #include <ino.h> #include <inode.h> /* * For the C compiler. */ int addlist(); long atol(); char *bread(); char *bclaim(); char *index(); char *realloc(); daddr_t balloc(); int dellist(); /* * Variables. */ struct filsys supb; /* Super block */ INODE inol; /* Bad block inode */ char bufl[1+NI][BSIZE]; /* Buffers for bread */ daddr_t bnol[1+NI]; /* Block numbers */ daddr_t *badl; /* Bad block list */ int badn; /* Number of bad blocks in list */ int badm; /* Maximum number of bad blocks */ int filf; /* Filesystem file descriptor */ main(argc, argv) char *argv[]; { register int i; if (argc < 3) usage(); if ((filf=open(argv[2], 2)) < 0) panic("Cannot open %s", argv[2]); badm = 64; if ((badl=malloc(badm*sizeof(*badl))) == NULL) panic("No memory"); switch (argv[1][0]) { case 'a': gather(); for (i=3; i<argc; i++) route(argv[i], addlist); update(); break; case 'c': update(); break; case 'd': gather(); for (i=3; i<argc; i++) route(argv[i], dellist); update(); break; case 'l': gather(); display(); break; default: usage(); } } /* * Print out usage. */ usage() { panic("Usage: bad [acdl] <filesystem> <bad block list>"); } /* * Given a string and a pointer to a function, extract a list of block * numbers from the string and call the function with them. */ route(cp1, f) register char *cp1; int (*f)(); { register char *cp2; register long b; register long l; if ((cp2=index(cp1, '-')) == NULL) (*f)(atol(cp1)); else { *cp2++ = '\0'; l = atol(cp2); for (b=atol(cp1); b<=l; b++) (*f)(b); } } /* * List the set of bad blocks. */ display() { register int i; for (i=0; i<badn; i++) printf("%ld\n", badl[i]); } /* * Read the list of bad blocks into the bad block list. */ gather() { register int n; register daddr_t b; copydm(); for (n=0; n<ND; n++) { if ((b=inol.i_a.i_addr[n]) != 0) addlist(b); } for (n=ND; n<ND+NI; n++) { if ((b=inol.i_a.i_addr[n]) != 0) indlist(b, 1+n-ND); } } /* * Given an indirect block, `b', with level of indirection, `l', add all * allocated blocks onto the bad block list. */ indlist(b, l) daddr_t b; register unsigned l; { register int i; register char *bp; daddr_t b1; if (b == 0) return; if (l-- > 0) { bp = bread(l, b); for (i=0; i<NBN; i++) { if ((b1=((daddr_t *)bp)[i]) == 0) continue; candaddr(b1); if (l == 0) addlist(b1); else indlist(b1, l); } } } /* * Add the given block onto the end of the bad block list. */ addlist(b) daddr_t b; { register int i; register int n; if (badn >= badm) { badm *= 2; if ((badl=realloc(badl, badm*sizeof(*badl))) == NULL) panic("Out of memory"); } for (i=0; i<badn; i++) { if (b == badl[i]) panic("Duplicate bad block %ld", b); if (b < badl[i]) break; } for (n=badn; n>i; --n) badl[n] = badl[n-1]; badl[i] = b; badn++; } /* * Delete the given bad block from the bad block list. */ dellist(b) daddr_t b; { register int n; for (n=0; n<badn; n++) { if (b == badl[n]) { for (--badn; n<badn; n++) badl[n] = badl[n+1]; return; } } panic("Cannot find block %ld", b); } /* * Update the bad block file. */ update() { register char *bp; register int i; bp = bread(0, (daddr_t)SUPERI); strcopy(bp, (char *)&supb, sizeof(struct filsys)); cansuper(&supb); for (i=0; i<ND+NI; i++) inol.i_a.i_addr[i] = 0; for (i=0; i<badn; i++) block(i, badl[i]); copymd(); bp = bread(0, (daddr_t)SUPERI); strcopy((char *)&supb, bp, sizeof(supb)); cansuper((struct filsys *)bp); bwrite(bp, (daddr_t)SUPERI); } /* * Canonize the super block. */ cansuper(sbp) register struct filsys *sbp; { register int i; canint(sbp->s_isize); candaddr(sbp->s_fsize); canshort(sbp->s_nfree); for (i=0; i<NICFREE; i++) candaddr(sbp->s_free[i]); canshort(sbp->s_ninode); for (i=0; i<NICINOD; i++) canino(sbp->s_inode[i]); cantime(sbp->s_time); candaddr(sbp->s_tfree); canino(sbp->s_tinode); canshort(sbp->s_m); canshort(sbp->s_n); canlong(sbp->s_unique); } /* * Copy the bad block inode to memory performing canonization. */ copydm() { register struct dinode *dip; register char *bp; bp = bread(0, (daddr_t)iblockn(BADFIN)); dip = (struct dinode *)bp+iblocko(BADFIN); inol.i_mode = dip->di_mode; canshort(inol.i_mode); inol.i_nlink = dip->di_nlink; canshort(inol.i_nlink); inol.i_uid = dip->di_uid; canshort(inol.i_uid); inol.i_gid = dip->di_gid; canshort(inol.i_gid); inol.i_size = dip->di_size; cansize(inol.i_size); l3tol(inol.i_a.i_addr, dip->di_addr, NADDR); inol.i_atime = dip->di_atime; cantime(inol.i_atime); inol.i_mtime = dip->di_mtime; cantime(inol.i_mtime); inol.i_ctime = dip->di_ctime; cantime(inol.i_ctime); return (1); } /* * Copy the bad block inode to disk performing canonization. */ copymd() { register struct dinode *dip; register char *bp; bp = bread(0, (daddr_t)iblockn(BADFIN)); dip = (struct dinode *)bp+iblocko(BADFIN); dip->di_mode = IFREG; canshort(dip->di_mode); dip->di_nlink = inol.i_nlink; canshort(dip->di_nlink); dip->di_uid = inol.i_uid; canshort(dip->di_uid); dip->di_gid = inol.i_gid; canshort(dip->di_gid); dip->di_size = badn*BSIZE; cansize(dip->di_size); ltol3(dip->di_addr, inol.i_a.i_addr, NADDR); dip->di_atime = inol.i_atime; cantime(dip->di_atime); dip->di_mtime = inol.i_mtime; cantime(dip->di_mtime); dip->di_ctime = inol.i_ctime; cantime(dip->di_ctime); bwrite(bp, (daddr_t)iblockn(BADFIN)); } /* * Make the physical block, `b', logical block, `n' of the bad block file. */ block(n, b) register int n; register daddr_t b; { register daddr_t pb; register char *bp; register daddr_t pbb; register char *bpp; if (n < ND) { inol.i_a.i_addr[n] = b; return; } n -= ND; if (n < NBN) { if ((pb=inol.i_a.i_addr[ND]) != 0) bp = bread(1, pb); else { inol.i_a.i_addr[ND] = pb = balloc(); bp = bclaim(1); } ((daddr_t *)bp)[n] = b; candaddr(((daddr_t *)bp)[n]); bwrite(bp, pb); return; } n -= NBN; if (n < NBN*NBN) { if ((pbb=inol.i_a.i_addr[ND+1]) != 0) bpp = bread(2, pbb); else { inol.i_a.i_addr[ND+1] = pbb = balloc(); bpp = bclaim(2); } pb = ((daddr_t *)bpp)[n/NBN]; candaddr(pb); if (pb != 0) bp = bread(1, pb); else { ((daddr_t *)bpp)[n/NBN] = pb = balloc(); candaddr(((daddr_t *)bpp)[n/NBN]); bwrite(bpp, pbb); bp = bclaim(1); } ((daddr_t *)bp)[n%NBN] = b; candaddr(((daddr_t *)bp)[n%NBN]); bwrite(bp, pb); return; } panic("Bad block file too large"); } /* * Allocate a block from our filesystem. */ daddr_t balloc() { register struct fblk *fbp; register daddr_t b; register int i; next: if (supb.s_tfree==0 || (b=supb.s_free[--supb.s_nfree])==0) panic("Out of space on filesystem"); if (supb.s_nfree == 0) { fbp = (struct fblk *)bread(0, b); supb.s_nfree = fbp->df_nfree; canshort(supb.s_nfree); for (i=0; i<sizeof(supb.s_free); i++) { supb.s_free[i] = fbp->df_free[i]; candaddr(supb.s_free[i]); } } --supb.s_tfree; if (b>=supb.s_fsize || b<supb.s_isize) panic("Bad block %u (alloc)", (unsigned)b); for (i=0; i<badn; i++) if (b == badl[i]) goto next; return (b); } /* * Given a buffer number, claim the buffer. */ char * bclaim(l) { register char *bp; register int n; n = BSIZE; bp = bufl[l]; do { *bp++ = 0; } while (--n); return (bufl[l]); } /* * Given a buffer number, read the given block into the given buffer and * return a pointer to the buffer. */ char * bread(l, b) daddr_t b; { register char *bp; bp = bufl[l]; if (b != bnol[l]) { lseek(filf, (long)b*BSIZE, 0); if (read(filf, bp, BSIZE) != BSIZE) panic("Read error on block %ld", b); bnol[l] = b; } return (bp); } /* * Given a pointer to a buffer, write it out as the given block. */ bwrite(bp, b) char *bp; daddr_t b; { lseek(filf, (long)b*BSIZE, 0); if (write(filf, bp, BSIZE) != BSIZE) panic("Write error on block %ld", b); } /* * Copy `n' bytes from `bp1' to `bp2'. */ strcopy(bp1, bp2, n) register char *bp1; register char *bp2; register unsigned n; { if (n == 0) return; do { *bp2++ = *bp1++; } while (--n); } /* * Print out an error message and exit. */ panic(a1) char *a1; { fprintf(stderr, "%r", &a1); fprintf(stderr, "\n"); exit(1); }