Return to BSD News archive
Path: sserve!manuel.anu.edu.au!munnari.oz.au!spool.mu.edu!agate!ames!pacbell.com!hoptoad!curt From: curt@hoptoad.uucp (Curt Mayer) Newsgroups: comp.unix.bsd Subject: Almost Free Symbolic Links (source code) Message-ID: <39777@hoptoad.uucp> Date: 13 Dec 92 02:45:58 GMT Distribution: world Organization: kernel hackers R us Lines: 828 Keywords: symlink data in inode block list Summary: cute hack ---------cut anywhere near here---------- : To unbundle, sh this file #!/bin/sh mkdir . echo ./README cat >./README <<'@@@ Fin de ./README' this cruddy but complete hack answers one of the objections to symlinks: that they are slow, and cost an entire frag. symlinks of less than length 60 are stored in the inode itself. symlinks longer than this are still in the inode. to make the illusion of normality complete, dump and fsck are hacked. additionally, I made dumpfs verbose to excess. stability is perfect, having been in since 0.1 came out. to create fast symlinks, just put FASTLINKS in your kernel options, reconfig and rebuild. if you try to read a filesystem containing fast links with a kernel not built for them, you just get an einval when you reference any fast link. I call that a soft failure. a floppy boot disk needn't contain any symlinks anyway. share and enjoy. legalese: hack, slash, and redistribute all you want, just don't claim you wrote it. @@@ Fin de ./README echo ./dump.diffs cat >./dump.diffs <<'@@@ Fin de ./dump.diffs' diff -c /usr/src/sbin/dump/dumptraverse.c /usr/src/sbin/dump.new/dumptraverse.c *** /usr/src/sbin/dump/dumptraverse.c Wed Apr 24 17:55:03 1991 --- /usr/src/sbin/dump.new/dumptraverse.c Mon Nov 2 21:50:31 1992 *************** *** 308,313 **** --- 308,320 ---- writeheader(ino); return; } + if (DFASTLINK(*dp)) { + spcl.c_addr[0] = 1; + spcl.c_count = 1; + writeheader(ino); + writerec(dp->di_symlink); + return; + } if (dp->di_size > NDADDR * sblock->fs_bsize) cnt = NDADDR * sblock->fs_frag; else @@@ Fin de ./dump.diffs echo ./fsck.diffs cat >./fsck.diffs <<'@@@ Fin de ./fsck.diffs' diff -c /usr/src/sbin/fsck/inode.c /usr/src/sbin/fsck.new/inode.c *** /usr/src/sbin/fsck/inode.c Sat Apr 20 14:39:03 1991 --- /usr/src/sbin/fsck.new/inode.c Thu Oct 29 23:43:25 1992 *************** *** 58,64 **** idesc->id_fix = DONTKNOW; idesc->id_entryno = 0; idesc->id_filesize = dp->di_size; ! if ((dp->di_mode & IFMT) == IFBLK || (dp->di_mode & IFMT) == IFCHR) return (KEEPON); dino = *dp; ndb = howmany(dino.di_size, sblock.fs_bsize); --- 58,65 ---- idesc->id_fix = DONTKNOW; idesc->id_entryno = 0; idesc->id_filesize = dp->di_size; ! if ((dp->di_mode & IFMT) == IFBLK || (dp->di_mode & IFMT) == IFCHR || ! DFASTLINK(*dp)) return (KEEPON); dino = *dp; ndb = howmany(dino.di_size, sblock.fs_bsize); diff -c /usr/src/sbin/fsck/pass1.c /usr/src/sbin/fsck.new/pass1.c *** /usr/src/sbin/fsck/pass1.c Sat Apr 20 14:39:04 1991 --- /usr/src/sbin/fsck.new/pass1.c Tue Nov 3 02:24:23 1992 *************** *** 101,106 **** --- 101,113 ---- continue; } lastino = inumber; + /* is fast symlink? */ + if (DFASTLINK(*dp)) { + lncntp[inumber] = dp->di_nlink; + statemap[inumber] = FSTATE; + n_files++; + continue; + } if (/* dp->di_size < 0 || */ dp->di_size + sblock.fs_bsize - 1 < dp->di_size) { if (debug) diff -c /usr/src/sbin/fsck/pass5.c /usr/src/sbin/fsck.new/pass5.c *** /usr/src/sbin/fsck/pass5.c Sat Apr 20 14:39:05 1991 --- /usr/src/sbin/fsck.new/pass5.c Fri Oct 30 02:20:20 1992 *************** *** 109,118 **** --- 109,122 ---- dmax = dbase + fs->fs_fpg; if (dmax > fs->fs_size) dmax = fs->fs_size; + #ifdef notdef if (now > cg->cg_time) newcg->cg_time = cg->cg_time; else newcg->cg_time = now; + #else + newcg->cg_time = cg->cg_time; + #endif newcg->cg_cgx = c; if (c == fs->fs_ncg - 1) newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg; @@@ Fin de ./fsck.diffs echo ./ufs.diffs cat >./ufs.diffs <<'@@@ Fin de ./ufs.diffs' diff -c /usr/src/sys.386bsd/ufs/dinode.h /usr/src/sys.386bsd/ufs.new/dinode.h *** /usr/src/sys.386bsd/ufs/dinode.h Tue Dec 24 14:24:20 1991 --- /usr/src/sys.386bsd/ufs.new/dinode.h Thu Oct 29 21:17:53 1992 *************** *** 41,46 **** --- 41,48 ---- #define NDADDR 12 /* direct addresses in inode */ #define NIADDR 3 /* indirect addresses in inode */ + #define MAXFASTLINK (((NDADDR+NIADDR) * sizeof(daddr_t)) - 1) + struct dinode { u_short di_mode; /* 0: mode and type of file */ short di_nlink; /* 2: number of links to file */ *************** *** 53,60 **** long di_mtspare; time_t di_ctime; /* 32: last time inode changed */ long di_ctspare; ! daddr_t di_db[NDADDR]; /* 40: disk block addresses */ ! daddr_t di_ib[NIADDR]; /* 88: indirect blocks */ long di_flags; /* 100: status, currently unused */ long di_blocks; /* 104: blocks actually held */ long di_gen; /* 108: generation number */ --- 55,67 ---- long di_mtspare; time_t di_ctime; /* 32: last time inode changed */ long di_ctspare; ! union { ! struct { ! daddr_t di_udb[NDADDR]; /* 40: disk block addresses */ ! daddr_t di_uib[NIADDR]; /* 88: indirect blocks */ ! } di_addr; ! char di_usymlink[MAXFASTLINK]; ! } di_un; long di_flags; /* 100: status, currently unused */ long di_blocks; /* 104: blocks actually held */ long di_gen; /* 108: generation number */ *************** *** 61,66 **** --- 68,77 ---- long di_spare[4]; /* 112: reserved, currently unused */ }; + #define di_db di_un.di_addr.di_udb + #define di_ib di_un.di_addr.di_uib + #define di_symlink di_un.di_usymlink + #if BYTE_ORDER == LITTLE_ENDIAN || defined(tahoe) /* ugh! -- must be fixed */ #define di_size di_qsize.val[0] #else /* BYTE_ORDER == BIG_ENDIAN */ *************** *** 84,86 **** --- 95,103 ---- #define IREAD 0400 /* read permission */ #define IWRITE 0200 /* write permission */ #define IEXEC 0100 /* execute permission */ + + #define DFASTLINK(di) \ + ((((di).di_mode & IFMT) == IFLNK) && \ + ((di).di_size <= MAXFASTLINK) && \ + ((di).di_size == (di).di_spare[0])) + diff -c /usr/src/sys.386bsd/ufs/inode.h /usr/src/sys.386bsd/ufs.new/inode.h *** /usr/src/sys.386bsd/ufs/inode.h Tue Dec 24 14:24:20 1991 --- /usr/src/sys.386bsd/ufs.new/inode.h Thu Oct 29 21:17:15 1992 *************** *** 67,72 **** --- 67,74 ---- struct dinode i_din; /* the on-disk dinode */ }; + #define FASTLINK(ip) (DFASTLINK((ip)->i_din)) + #define i_symlink i_din.di_symlink #define i_mode i_din.di_mode #define i_nlink i_din.di_nlink #define i_uid i_din.di_uid diff -c /usr/src/sys.386bsd/ufs/ufs_inode.c /usr/src/sys.386bsd/ufs.new/ufs_inode.c *** /usr/src/sys.386bsd/ufs/ufs_inode.c Tue Dec 24 14:24:20 1991 --- /usr/src/sys.386bsd/ufs.new/ufs_inode.c Thu Oct 29 21:16:02 1992 *************** *** 406,411 **** --- 406,418 ---- struct inode tip; vnode_pager_setsize(ITOV(oip), length); + if (FASTLINK(oip)) { + if (length != 0) + panic("itrunc fastlink to non-zero"); + bzero(oip->i_symlink, MAXFASTLINK); + oip->i_size = 0; + oip->i_din.di_spare[0] = 0; + } if (oip->i_size <= length) { oip->i_flag |= ICHG|IUPD; error = iupdat(oip, &time, &time, 1); diff -c /usr/src/sys.386bsd/ufs/ufs_vnops.c /usr/src/sys.386bsd/ufs.new/ufs_vnops.c *** /usr/src/sys.386bsd/ufs/ufs_vnops.c Tue Dec 24 14:24:21 1991 --- /usr/src/sys.386bsd/ufs.new/ufs_vnops.c Thu Oct 29 21:28:34 1992 *************** *** 31,36 **** --- 31,44 ---- * SUCH DAMAGE. * * @(#)ufs_vnops.c 7.64 (Berkeley) 5/16/91 + * + * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE + * -------------------- ----- ---------------------- + * CURRENT PATCH LEVEL: 1 00007 + * -------------------- ----- ---------------------- + * + * 20 Aug 92 David Greenman Fixed incorrect setting of B_AGE after + * each read to improve cache performance */ #include "param.h" *************** *** 497,504 **** --- 505,514 ---- return (error); } error = uiomove(bp->b_un.b_addr + on, (int)n, uio); + #if OMIT /* 20 Aug 92*/ if (n + on == fs->fs_bsize || uio->uio_offset == ip->i_size) bp->b_flags |= B_AGE; + #endif /* OMIT*/ brelse(bp); } while (error == 0 && uio->uio_resid > 0 && n != 0); return (error); *************** *** 1267,1278 **** struct proc *p; { struct inode *ip; int error; error = maknode(IFLNK | vap->va_mode, ndp, &ip); if (error) return (error); ! error = vn_rdwr(UIO_WRITE, ITOV(ip), target, strlen(target), (off_t)0, UIO_SYSSPACE, IO_NODELOCKED, ndp->ni_cred, (int *)0, (struct proc *)0); iput(ip); --- 1277,1298 ---- struct proc *p; { struct inode *ip; + int len = strlen(target); int error; error = maknode(IFLNK | vap->va_mode, ndp, &ip); if (error) return (error); ! #ifdef FASTLINKS ! if (len <= MAXFASTLINK) { ! ip->i_din.di_spare[0] = len; ! ip->i_size = len; ! bcopy(target, ip->i_symlink, len); ! ip->i_flag |= ICHG; ! error = iupdat(ip, &time, &time, 1); ! } else ! #endif ! error = vn_rdwr(UIO_WRITE, ITOV(ip), target, len, (off_t)0, UIO_SYSSPACE, IO_NODELOCKED, ndp->ni_cred, (int *)0, (struct proc *)0); iput(ip); *************** *** 1314,1321 **** struct uio *uiop; struct ucred *cred; { ! ! return (ufs_read(vp, uiop, 0, cred)); } /* --- 1334,1344 ---- struct uio *uiop; struct ucred *cred; { ! struct inode *ip = VTOI(vp); ! if (FASTLINK(ip)) ! return (uiomove(ip->i_symlink, ip->i_size, uiop)); ! else ! return (ufs_read(vp, uiop, 0, cred)); } /* @@@ Fin de ./ufs.diffs mkdir ./usr mkdir ./usr/src mkdir ./usr/src/sbin mkdir ./usr/src/sbin/dumpfs echo ./usr/src/sbin/dumpfs/dumpfs.c cat >./usr/src/sbin/dumpfs/dumpfs.c <<'@@@ Fin de ./usr/src/sbin/dumpfs/dumpfs.c' #define EXTREME /* * Copyright (c) 1983 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * added much verbose hackery in conjunction with fast symlinks. * curt mayer, 11 Dec 1992 */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)dumpfs.c 5.10 (Berkeley) 6/1/90"; #endif /* not lint */ #include <sys/param.h> #include <ufs/dinode.h> #include <ufs/dir.h> #include <ufs/fs.h> #include <stdio.h> #include <fstab.h> /* * dumpfs */ union { struct fs fs; char pad[MAXBSIZE]; } fsun; #define afs fsun.fs union { struct cg cg; char pad[MAXBSIZE]; } cgun; #define acg cgun.cg struct dinode *din; extern char *malloc(); long dev_bsize = 1; main(argc, argv) char **argv; { register struct fstab *fs; argc--, argv++; if (argc < 1) { fprintf(stderr, "usage: dumpfs fs ...\n"); exit(1); } for (; argc > 0; argv++, argc--) { fs = getfsfile(*argv); if (fs == 0) dumpfs(*argv); else dumpfs(fs->fs_spec); } } dumpfs(name) char *name; { int c, i, j, k, size; close(0); if (open(name, 0) != 0) { perror(name); return; } lseek(0, SBOFF, 0); if (read(0, &afs, SBSIZE) != SBSIZE) { perror(name); return; } if (afs.fs_postblformat == FS_42POSTBLFMT) afs.fs_nrpos = 8; dev_bsize = afs.fs_fsize / fsbtodb(&afs, 1); if (afs.fs_inopb > 0 && afs.fs_inopb <= 1024) { din = (struct dinode *) malloc(afs.fs_inopb * sizeof(struct dinode)); } printf("magic\t%x\tformat\t%s\ttime\t%s", afs.fs_magic, afs.fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic", ctime(&afs.fs_time)); printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n", afs.fs_cstotal.cs_nbfree, afs.fs_cstotal.cs_ndir, afs.fs_cstotal.cs_nifree, afs.fs_cstotal.cs_nffree); printf("ncg\t%d\tncyl\t%d\tsize\t%d\tblocks\t%d\n", afs.fs_ncg, afs.fs_ncyl, afs.fs_size, afs.fs_dsize); printf("bsize\t%d\tshift\t%d\tmask\t0x%08x\n", afs.fs_bsize, afs.fs_bshift, afs.fs_bmask); printf("fsize\t%d\tshift\t%d\tmask\t0x%08x\n", afs.fs_fsize, afs.fs_fshift, afs.fs_fmask); printf("frag\t%d\tshift\t%d\tfsbtodb\t%d\n", afs.fs_frag, afs.fs_fragshift, afs.fs_fsbtodb); printf("cpg\t%d\tbpg\t%d\tfpg\t%d\tipg\t%d\n", afs.fs_cpg, afs.fs_fpg / afs.fs_frag, afs.fs_fpg, afs.fs_ipg); printf("minfree\t%d%%\toptim\t%s\tmaxcontig %d\tmaxbpg\t%d\n", afs.fs_minfree, afs.fs_optim == FS_OPTSPACE ? "space" : "time", afs.fs_maxcontig, afs.fs_maxbpg); printf("rotdelay %dms\theadswitch %dus\ttrackseek %dus\trps\t%d\n", afs.fs_rotdelay, afs.fs_headswitch, afs.fs_trkseek, afs.fs_rps); printf("ntrak\t%d\tnsect\t%d\tnpsect\t%d\tspc\t%d\n", afs.fs_ntrak, afs.fs_nsect, afs.fs_npsect, afs.fs_spc); printf("trackskew %d\tinterleave %d\n", afs.fs_trackskew, afs.fs_interleave); printf("nindir\t%d\tinopb\t%d\tnspf\t%d\n", afs.fs_nindir, afs.fs_inopb, afs.fs_nspf); printf("sblkno\t%d\tcblkno\t%d\tiblkno\t%d\tdblkno\t%d\n", afs.fs_sblkno, afs.fs_cblkno, afs.fs_iblkno, afs.fs_dblkno); printf("sbsize\t%d\tcgsize\t%d\tcgoffset %d\tcgmask\t0x%08x\n", afs.fs_sbsize, afs.fs_cgsize, afs.fs_cgoffset, afs.fs_cgmask); printf("csaddr\t%d\tcssize\t%d\tshift\t%d\tmask\t0x%08x\n", afs.fs_csaddr, afs.fs_cssize, afs.fs_csshift, afs.fs_csmask); printf("cgrotor\t%d\tfmod\t%d\tronly\t%d\n", afs.fs_cgrotor, afs.fs_fmod, afs.fs_ronly); if (afs.fs_cpc != 0) printf("blocks available in each of %d rotational positions", afs.fs_nrpos); else printf("insufficient space to maintain rotational tables\n"); for (c = 0; c < afs.fs_cpc; c++) { printf("\ncylinder number %d:", c); for (i = 0; i < afs.fs_nrpos; i++) { if (fs_postbl(&afs, c)[i] == -1) continue; printf("\n position %d:\t", i); for (j = fs_postbl(&afs, c)[i], k = 1; ; j += fs_rotbl(&afs)[j], k++) { printf("%5d", j); if (k % 12 == 0) printf("\n\t\t"); if (fs_rotbl(&afs)[j] == 0) break; } } } printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t"); for (i = 0, j = 0; i < afs.fs_cssize; i += afs.fs_bsize, j++) { size = afs.fs_cssize - i < afs.fs_bsize ? afs.fs_cssize - i : afs.fs_bsize; afs.fs_csp[j] = (struct csum *)calloc(1, size); lseek(0, fsbtodb(&afs, (afs.fs_csaddr + j * afs.fs_frag)) * dev_bsize, 0); if (read(0, afs.fs_csp[j], size) != size) { perror(name); return; } } for (i = 0; i < afs.fs_ncg; i++) { struct csum *cs = &afs.fs_cs(&afs, i); if (i && i % 4 == 0) printf("\n\t"); printf("(%d,%d,%d,%d) ", cs->cs_nbfree, cs->cs_ndir, cs->cs_nifree, cs->cs_nffree); } printf("\n"); if (afs.fs_ncyl % afs.fs_cpg) { printf("cylinders in last group %d\n", i = afs.fs_ncyl % afs.fs_cpg); printf("blocks in last group %d\n", i * afs.fs_spc / NSPB(&afs)); } printf("\n"); for (i = 0; i < afs.fs_ncg; i++) dumpcg(name, i); close(0); }; static char xxbuf[11]; char * modestr(k) unsigned short k; { int type, i, mode; type = ((k & IFMT) >> 12) & 0xf; xxbuf[0] = ".=c.d.b.-.l.s..."[type]; for (i = 0; i < 3; i++) { mode = (k << (i * 3)) & (IREAD | IWRITE | IEXEC); xxbuf[1 + (i * 3) + 0] = (mode & IREAD) ? 'r' : '-'; xxbuf[1 + (i * 3) + 1] = (mode & IWRITE) ? 'w' : '-'; xxbuf[1 + (i * 3) + 2] = (mode & IEXEC) ? 'x' : '-'; } if (k & ISUID) xxbuf[1 + (0 * 3) + 2] = 's'; if (k & ISGID) xxbuf[1 + (1 * 3) + 2] = 's'; if (k & ISVTX) xxbuf[1 + (2 * 3) + 2] = 's'; xxbuf[10] = '\0'; return (xxbuf); } dumpcg(name, c) char *name; int c; { int i, j; printf("\ncg %d:\n", c); lseek(0, fsbtodb(&afs, cgtod(&afs, c)) * dev_bsize, 0); i = lseek(0, 0, 1); if (read(0, (char *)&acg, afs.fs_bsize) != afs.fs_bsize) { printf("dumpfs: %s: error reading cg\n", name); return; } printf("magic\t%x\ttell\t%x\ttime\t%s", afs.fs_postblformat == FS_42POSTBLFMT ? ((struct ocg *)&acg)->cg_magic : acg.cg_magic, i, ctime(&acg.cg_time)); printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n", acg.cg_cgx, acg.cg_ncyl, acg.cg_niblk, acg.cg_ndblk); printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n", acg.cg_cs.cs_nbfree, acg.cg_cs.cs_ndir, acg.cg_cs.cs_nifree, acg.cg_cs.cs_nffree); printf("rotor\t%d\tirotor\t%d\tfrotor\t%d\nfrsum", acg.cg_rotor, acg.cg_irotor, acg.cg_frotor); for (i = 1, j = 0; i < afs.fs_frag; i++) { printf("\t%d", acg.cg_frsum[i]); j += i * acg.cg_frsum[i]; } printf("\nsum of frsum: %d\niused:\t", j); pbits(c * afs.fs_ipg, cg_inosused(&acg), afs.fs_ipg); printf("free:\t"); pbits(c * afs.fs_fpg, cg_blksfree(&acg), afs.fs_fpg); printf("b:\n"); for (i = 0; i < afs.fs_cpg; i++) { if (cg_blktot(&acg)[i] == 0) continue; printf(" c%d:\t(%d)\t", i, cg_blktot(&acg)[i]); for (j = 0; j < afs.fs_nrpos; j++) { if (afs.fs_cpc > 0 && fs_postbl(&afs, i % afs.fs_cpc)[j] == -1) continue; printf(" %d", cg_blks(&afs, &acg, i)[j]); } printf("\n"); } if (din) dumpinodes(c, name); }; dumpinodes(c, name) int c; char *name; { int i, j, k, l, m; printf("inum\tmode\t\tlinks\tuid\tgid\tblocks\tsize\n"); for (i = 0; i < acg.cg_niblk; i += INOPB(&afs)) { j = (afs.fs_ipg * c) + i; lseek(0, (fsbtodb(&afs, itod(&afs, j)) * dev_bsize), 0); if (read(0, (char *)din, INOPB(&afs) * sizeof(struct dinode)) != INOPB(&afs) * sizeof(struct dinode)) { printf("dumpfs: %s: error reading inode\n", name); return; } for (k = 0; k < INOPB(&afs); k++) { #ifdef EXTREME int l, m; char *p; char c; #endif if (!din[k].di_mode) continue; #ifdef EXTREME p = (char *)&din[k]; for (l = 0; l < sizeof(din[k]); l += 16) { for (m = 0; m < 16; m++) { printf("%02x ", p[l+m] & 0xff); } printf(" "); for (m = 0; m < 16; m++) { c = p[l+m]; if (c < 0x20 || c > 0x7e) c = '.'; printf("%c", c); } printf("\n"); } printf("\n"); #endif printf("%d\t%s\t%d\t%d\t%d\t%d\t%d\n\t", j + k, modestr(din[k].di_mode), din[k].di_nlink, din[k].di_uid, din[k].di_gid, din[k].di_blocks, din[k].di_size); /* dump fast symlink */ if (((din[k].di_mode & IFMT) == IFLNK) && (din[k].di_size <= MAXFASTLINK) && (din[k].di_size == din[k].di_spare[0])) { printf("%s\n\n", din[k].di_symlink); continue; } /* dump cdev/bdev */ if (((din[k].di_mode & IFMT) == IFCHR) || ((din[k].di_mode & IFMT) == IFBLK)) { printf("major %d minor %d (0x%x)\n\n", major(din[k].di_rdev), minor(din[k].di_rdev), minor(din[k].di_rdev)); continue; } /* dump normal symlink */ if (((din[k].di_mode & IFMT) == IFLNK) && ((din[k].di_size > MAXFASTLINK) || (din[k].di_size != din[k].di_spare[0]))) { dumpsymlink(din[k].di_db[0], din[k].di_size, name); } /* dump directory */ if (((din[k].di_mode & IFMT) == IFDIR)) { printf("ino\tname\n\t"); for (l = 0; l < NDADDR; l++) { dumpdirblk(din[k].di_db[l], dblksize(&afs,&din[k], l), name); } if (din[k].di_ib[0]) { printf("huge directory\n"); } printf("\n\t"); } /* dump direct blocks */ for (m = NDADDR - 1; m >= 0; m--) { if (din[k].di_db[m] != 0) break; } for (l = 0 ; l <= m; l++) { printf("%d\t", din[k].di_db[l]); if (((l + 1) % 8) == 0) printf("\n\t"); } if ((l % 8) != 0) printf("\n"); printf("\n"); /* dump indirect blocks */ for (m = NIADDR - 1; m >= 0; m--) { if (din[k].di_ib[m] != 0) break; } for (l = 0 ; l <= m; l++) { dumpindir(l, din[k].di_ib[l], name); } } } } dumpdirblk(b, bs, name) int b; int bs; char *name; { char *s, *p; struct direct *d; if (!b) return; lseek(0, fsbtodb(&afs, b) * dev_bsize, 0); s = malloc(bs); if (!s) { printf("malloc failed\n"); return; } if (read(0, s, bs) != bs) { printf("dumpfs: %s: error reading directory block\n", name); } for (p = s; p < &s[bs]; p += d->d_reclen) { d = (struct direct *)p; if (d->d_reclen > DIRSIZ(d)) continue; printf("%d\t%s\n\t", d->d_ino, d->d_name); } } dumpsymlink(b, len, name) int b; int len; char *name; { int i; int m; char *s; lseek(0, fsbtodb(&afs, b) * dev_bsize, 0); s = malloc(afs.fs_bsize); if (!s) { printf("malloc failed\n"); return; } if (read(0, s, afs.fs_bsize) != afs.fs_bsize) { printf("dumpfs: %s: error reading symlink block\n", name); } s[len] = '\0'; printf("%s\n\t", s); free(s); } dumpindir(d, b, name) int d; int b; char *name; { daddr_t *indirs; int i; int m; printf("\tI%d %d:\n", d, b); if (b == 0) return; indirs = (daddr_t *)malloc(afs.fs_nindir * sizeof(daddr_t)); lseek(0, fsbtodb(&afs, b) * dev_bsize, 0); if (read(0, (char *)indirs, afs.fs_nindir * sizeof(daddr_t)) != afs.fs_nindir * sizeof(daddr_t)) { printf("dumpfs: %s: error reading indirect block\n", name); } if (d == 0) { printf("\t"); for (m = afs.fs_nindir - 1; m >= 0; m--) { if (indirs[m] != 0) break; } for (i = 0; i <= m; i++) { printf("%d\t", indirs[i]); if (((i + 1) % 8) == 0) printf("\n\t"); } if ((i % 8) != 0) printf("\n"); printf("\n"); } else { for (m = afs.fs_nindir - 1; m >= 0; m--) { if (indirs[m] != 0) break; } for (i = 0; i <= m; i++) { dumpindir(d - 1, indirs[i], name); } } free((char *)indirs); } pbits(base, cp, max) int base; register char *cp; int max; { register int i; int count = 0, j; int width = 0; for (i = 0; i < max; i++) if (isset(cp, i)) { if (count) { width += printf(","); if (width > 55) { printf("\n\t"); width = 0; } } count++; width += printf("%d", i+base); j = i; while ((i+1)<max && isset(cp, i+1)) i++; if (i != j) width += printf("-%d", i+base); } printf("\n"); } @@@ Fin de ./usr/src/sbin/dumpfs/dumpfs.c exit 0 ---------cut anywhere near here---------- -- curt mayer curt@toad.com 415-387-0217 home