home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / unix / bsd / 8976 < prev    next >
Encoding:
Internet Message Format  |  1992-11-17  |  19.9 KB

  1. Path: sparky!uunet!usc!cs.utexas.edu!uwm.edu!zaphod.mps.ohio-state.edu!saimiri.primate.wisc.edu!ames!agate!doc.ic.ac.uk!uknet!mcsun!fuug!kiae!rdrel!guam.relcom.msk.su!vak
  2. From: vak@guam.relcom.msk.su (Serge V.Vakulenko)
  3. Newsgroups: comp.unix.bsd
  4. Subject: [386BSD] fs - print info about opened files
  5. Message-ID: <1992Nov16.210249.1609@rdrel.relcom.msk.su>
  6. Date: 16 Nov 92 21:02:49 GMT
  7. Sender: usenet@rdrel.relcom.msk.su (Usenet News Administrator)
  8. Organization: Relcom R&D
  9. Lines: 859
  10. X-Newsreader: TIN [version 1.1 PL6]
  11.  
  12. Here is simple utility, called `fs', which reads from the kernel
  13. and prints the information about files, opened by running
  14. processes.  It also tries to convert dev/inode pairs to
  15. absolute file names.
  16.  
  17. Share and enjoy!
  18.  
  19. # This is a shell archive.  Save it in a file, remove anything before
  20. # this line, and then unpack it by entering "sh file".  Note, it may
  21. # create directories; files and directories will be owned by you and
  22. # have default permissions.
  23. #
  24. # This archive contains:
  25. #
  26. #    Makefile
  27. #    fs.1
  28. #    fs.c
  29. #    fs.h
  30. #    fsdumpdb.c
  31. #    fsmakedb.1
  32. #    fsmakedb.c
  33. #
  34. echo x - Makefile
  35. sed 's/^X//' >Makefile << 'END-of-Makefile'
  36. X# Copyright (C) 1992 Sergey Vakulenko, <vak@kiae.su>.
  37. X# Permission to use and distribute this software is permitted
  38. X# without fee, provided that this copyright notice is not changed.
  39. X
  40. XSHELL   = /bin/sh
  41. XCFLAGS  = -pipe -O
  42. XLDFLAGS = -pipe -O
  43. X
  44. XSRCS    = fs.c fsdumpdb.c fsmakedb.c
  45. X
  46. Xall:    fs fsmakedb fs.0 fsmakedb.0
  47. X
  48. Xfs:     fs.o
  49. X    $(CC) $(LDFLAGS) fs.o -o fs -lutil
  50. X
  51. Xfsmakedb: fsmakedb.o
  52. X    $(CC) $(LDFLAGS) fsmakedb.o -o fsmakedb
  53. X
  54. Xfsdumpdb: fsdumpdb.o
  55. X    $(CC) $(LDFLAGS) fsdumpdb.o -o fsdumpdb
  56. X
  57. Xinstall: fs fsmakedb fs.0 fsmakedb.0
  58. X    install -c -s -o root -m 4755 fs /usr/bin/fs
  59. X    install -c -s -o root -m 4755 fsmakedb /usr/sbin/fsmakedb
  60. X    install -c fs.0 /usr/share/man/cat1/fs.0
  61. X    install -c fsmakedb.0 /usr/share/man/cat8/fsmakedb.0
  62. X
  63. Xdepend:
  64. X    mkdep $(SRCS) &&\
  65. X    sed '/^###$$/,$$d' Makefile > Makefile~ &&\
  66. X    echo '###' >> Makefile~ &&\
  67. X    cat .depend >> Makefile~ &&\
  68. X    rm .depend &&\
  69. X    mv Makefile~ Makefile
  70. X
  71. Xclean:
  72. X    rm -f core.* .,* *.b *.o fs fsmakedb fsdumpdb .depend *.0
  73. X
  74. X.SUFFIXES: .1 .0
  75. X
  76. X.1.0:
  77. X    nroff -man $< > $@
  78. X
  79. X###
  80. Xfs.o : fs.c /usr/include/stdio.h /usr/include/sys/cdefs.h \
  81. X  /usr/include/machine/ansi.h /usr/include/nlist.h /usr/include/sys/types.h \
  82. X  /usr/include/machine/types.h /usr/include/db.h /usr/include/dirent.h \
  83. X  /usr/include/fcntl.h /usr/include/sys/param.h /usr/include/sys/syslimits.h \
  84. X  /usr/include/sys/errno.h /usr/include/sys/time.h \
  85. X  /usr/include/sys/resource.h /usr/include/sys/ucred.h /usr/include/sys/uio.h \
  86. X  /usr/include/sys/signal.h /usr/include/machine/trap.h \
  87. X  /usr/include/machine/param.h /usr/include/machine/endian.h \
  88. X  /usr/include/machine/limits.h /usr/include/sys/stat.h \
  89. X  /usr/include/ufs/quota.h /usr/include/sys/namei.h /usr/include/sys/file.h \
  90. X  /usr/include/sys/fcntl.h /usr/include/sys/unistd.h /usr/include/sys/vnode.h \
  91. X  /usr/include/ufs/inode.h /usr/include/ufs/../ufs/dinode.h \
  92. X  /usr/include/sys/proc.h /usr/include/machine/proc.h fs.h 
  93. Xfsdumpdb.o : fsdumpdb.c /usr/include/stdio.h /usr/include/sys/cdefs.h \
  94. X  /usr/include/machine/ansi.h /usr/include/sys/types.h \
  95. X  /usr/include/machine/types.h /usr/include/db.h /usr/include/fcntl.h fs.h 
  96. Xfsmakedb.o : fsmakedb.c /usr/include/stdio.h /usr/include/sys/cdefs.h \
  97. X  /usr/include/machine/ansi.h /usr/include/sys/types.h \
  98. X  /usr/include/machine/types.h /usr/include/db.h /usr/include/dirent.h \
  99. X  /usr/include/sys/stat.h /usr/include/fcntl.h fs.h 
  100. END-of-Makefile
  101. echo x - fs.1
  102. sed 's/^X//' >fs.1 << 'END-of-fs.1'
  103. X.\" Copyright (C) 1992 Sergey Vakulenko, <vak@kiae.su>.
  104. X.\" Permission to use and distribute this software is permitted
  105. X.\" without fee, provided that this copyright notice is not changed.
  106. X.Dd November 16, 1992
  107. X.Dt FS 1
  108. X.Os BSD 3
  109. X.Sh NAME
  110. X.Nm fs
  111. X.Nd print opened files
  112. X.Sh SYNOPSIS
  113. X.Nm fs
  114. X.Op Fl s
  115. X.Op Fl f Ar dbfile
  116. X.Sh DESCRIPTION
  117. XThe
  118. X.Nm fs
  119. Xutility prints information about files, which are currently opened by
  120. Xrunning processes.
  121. X.Pp
  122. XGiven the device and inode numbers of file,
  123. X.Nm fs
  124. Xtries to compute the full file name, using the database of
  125. Xall files in the filesystem.  This database should be create by
  126. X.Xr fsmakedb 1 ,
  127. Xand placed in
  128. X.Ql /var/db/fs.db .
  129. X.Pp
  130. XThe options are as follows:
  131. X.Bl -tag -width Ds
  132. X.It Fl s
  133. XShow opened sockets in addition to files.
  134. X.It Fl f
  135. XRead the file name info from the specified file.
  136. X.El
  137. X.Pp
  138. XIn order to have read access to /dev/kmem and other system files, the
  139. X.Nm fs
  140. Xutility should run setuid root.
  141. X.Sh SEE ALSO
  142. X.Xr fsmakedb 1 .
  143. END-of-fs.1
  144. echo x - fs.c
  145. sed 's/^X//' >fs.c << 'END-of-fs.c'
  146. X/*
  147. X * fs.c - print files, opened by running processes.
  148. X *
  149. X * Version 1.0, Tue Nov 17 00:03:11 MSK 1992
  150. X *
  151. X * Copyright (C) 1992 Sergey Vakulenko, <vak@kiae.su>.
  152. X * Permission to use and distribute this software is permitted
  153. X * without fee, provided that this copyright notice is not changed.
  154. X */
  155. X#include <stdio.h>
  156. X#include <nlist.h>
  157. X#include <sys/types.h>
  158. X#include <db.h>
  159. X#include <dirent.h>
  160. X#define KERNEL
  161. X#include <fcntl.h>
  162. X#include <sys/param.h>
  163. X#include <sys/time.h>
  164. X#include <sys/stat.h>
  165. X#include <ufs/quota.h>
  166. X#include <sys/namei.h>
  167. X#include <sys/uio.h>
  168. X#include <sys/file.h>
  169. X#include <sys/vnode.h>
  170. X#include <ufs/inode.h>
  171. X#include <sys/ucred.h>
  172. X#include <sys/proc.h>
  173. X#include "fs.h"
  174. X
  175. Xstruct devtab {
  176. X    char *name;
  177. X    int dev;
  178. X};
  179. X
  180. Xstruct nlist symtab [] = {
  181. X    { "_filehead", },               /* struct file * */
  182. X#define FILEHEAD symtab[0]
  183. X    { "_nfiles", },                 /* int */
  184. X#define NFILES symtab[1]
  185. X    { 0, },
  186. X};
  187. X
  188. Xint nfiles;
  189. Xstruct file *filetab;
  190. Xstruct vnode *vnodetab;
  191. Xstruct devtab *cdev, *bdev;
  192. Xint cdevlen, bdevlen;
  193. Xint cdevcnt, bdevcnt;
  194. Xint initdevtab = 0;
  195. XDB *db;
  196. Xint sflag = 0;
  197. X
  198. Xchar *progname;
  199. X
  200. Xextern char *strrchr (), *strdup (), *malloc (), *calloc ();
  201. X
  202. X/* VARARGS1 */
  203. Xvoid fatal (msg, a, b, c, d)
  204. Xchar *msg;
  205. Xlong a, b, c, d;
  206. X{
  207. X    fprintf (stderr, "%s: ", progname);
  208. X    fprintf (stderr, msg, a, b, c, d);
  209. X    fprintf (stderr, "\n");
  210. X    exit (-1);
  211. X}
  212. X
  213. Xvoid kread (off, addr, sz)
  214. Xlong off;
  215. Xvoid *addr;
  216. X{
  217. X    if (kvm_read (off, addr, sz) != sz)
  218. X        fatal ("cannot read kernel memory");
  219. X}
  220. X
  221. Xvoid readproc ()
  222. X{
  223. X    struct file *f, *ptr;
  224. X    struct vnode v;
  225. X
  226. X    if (kvm_openfiles (0, 0, 0) < 0)
  227. X        fatal ("cannot open kernel files");
  228. X    if (kvm_nlist (symtab) != 0)
  229. X        fatal ("cannot read kernel symbols");
  230. X    kread (NFILES.n_value, &nfiles, sizeof (nfiles));
  231. X
  232. X    filetab = (struct file *) calloc (nfiles, sizeof (struct file));
  233. X    vnodetab = (struct vnode *) calloc (nfiles, sizeof (struct vnode));
  234. X    if (!filetab || !vnodetab)
  235. X        fatal ("out of memory");
  236. X
  237. X    kread (FILEHEAD.n_value, &ptr, sizeof (ptr));
  238. X    for (f=filetab; ptr && f<filetab+nfiles; ++f) {
  239. X        int i = f - filetab;
  240. X        kread (ptr, f, sizeof (struct file));
  241. X
  242. X        if (f->f_type == DTYPE_VNODE)
  243. X            kvm_read (f->f_data, vnodetab+i, sizeof (struct vnode));
  244. X
  245. X        ptr = f->f_filef;
  246. X    }
  247. X}
  248. X
  249. Xchar *fileflag (int fl)
  250. X{
  251. X    static char buf [8];
  252. X    char *p;
  253. X
  254. X    if (fl & ~(FREAD | FWRITE | O_APPEND | O_NONBLOCK | FHASLOCK)) {
  255. X        sprintf (buf, "%o", fl);
  256. X        return (buf);
  257. X    }
  258. X    p = buf + sizeof(buf);
  259. X    *--p = 0;
  260. X    *--p = (fl & FREAD)      ? 'r' : '-';
  261. X    *--p = (fl & FWRITE)     ? 'w' : '-';
  262. X    *--p = (fl & O_APPEND)   ? 'a' : '-';
  263. X    *--p = (fl & O_NONBLOCK) ? 'n' : '-';
  264. X    *--p = (fl & FHASLOCK)   ? 'l' : '-';
  265. X    return (p);
  266. X}
  267. X
  268. Xchar *filecount (cnt)
  269. X{
  270. X    static char buf [16];
  271. X
  272. X    if (cnt == 1)
  273. X        return ("");
  274. X    sprintf (buf, "(%d)", cnt);
  275. X    return (buf);
  276. X}
  277. X
  278. Xchar *fileoffset (off)
  279. Xlong off;
  280. X{
  281. X    static char buf [24];
  282. X
  283. X    if (off == 0)
  284. X        return ("");
  285. X    sprintf (buf, "%x", off);
  286. X    return (buf);
  287. X}
  288. X
  289. Xchar *vnodetype (typ)
  290. X{
  291. X    switch (typ) {
  292. X    case VNON:      return ("non");
  293. X    case VBAD:      return ("bad");
  294. X    case VSOCK:     return ("sock");
  295. X    case VFIFO:     return ("fifo");
  296. X    case VLNK:      return ("lnk");
  297. X    case VBLK:      return ("blk");
  298. X    case VCHR:      return ("chr");
  299. X    case VDIR:      return ("dir");
  300. X    case VREG:      return ("file");
  301. X    }
  302. X    return ("?");
  303. X}
  304. X
  305. Xvoid makedevtab ()
  306. X{
  307. X    DIR *dird;
  308. X    struct dirent *d;
  309. X    struct stat st;
  310. X    char afname [128];
  311. X
  312. X    cdevcnt = bdevcnt = 0;
  313. X    cdevlen = bdevlen = 64;
  314. X    bdev = (struct devtab *) malloc (bdevlen * sizeof (struct devtab));
  315. X    cdev = (struct devtab *) malloc (cdevlen * sizeof (struct devtab));
  316. X    if (! bdev || ! cdev)
  317. X        fatal ("out of memory");
  318. X    strcpy (afname, "/dev/");
  319. X    dird = opendir (afname);
  320. X    if (! dird)
  321. X        fatal ("cannot read /dev directory");
  322. X    for (d=readdir(dird); d; d=readdir(dird)) {
  323. X        strcpy (afname+5, d->d_name);
  324. X        if (stat (afname, &st) < 0)
  325. X            continue;
  326. X        if ((st.st_mode & S_IFMT) == S_IFBLK) {
  327. X            if (bdevcnt >= bdevlen) {
  328. X                bdevlen += 64;
  329. X                bdev = (struct devtab *) realloc ((char *) bdev,
  330. X                    bdevlen * sizeof (struct devtab));
  331. X                if (! bdev)
  332. X                    fatal ("out of memory");
  333. X            }
  334. X            bdev[bdevcnt].dev = st.st_rdev;
  335. X            bdev[bdevcnt].name = strdup (afname);
  336. X            ++bdevcnt;
  337. X        } else if ((st.st_mode & S_IFMT) == S_IFCHR) {
  338. X            if (cdevcnt >= cdevlen) {
  339. X                cdevlen += 64;
  340. X                cdev = (struct devtab *) realloc ((char *) cdev,
  341. X                    cdevlen * sizeof (struct devtab));
  342. X                if (! cdev)
  343. X                    fatal ("out of memory");
  344. X            }
  345. X            cdev[cdevcnt].dev = st.st_rdev;
  346. X            cdev[cdevcnt].name = strdup (afname);
  347. X            ++cdevcnt;
  348. X        }
  349. X    }
  350. X    closedir (dird);
  351. X}
  352. X
  353. Xchar *devname (typ, dev)
  354. X{
  355. X    struct devtab *p;
  356. X    int cnt, i;
  357. X    static char buf [16];
  358. X
  359. X    if (! initdevtab) {
  360. X        makedevtab ();
  361. X        initdevtab = 1;
  362. X    }
  363. X    p = typ=='b' ? bdev : cdev;
  364. X    cnt = typ=='b' ? bdevcnt : cdevcnt;
  365. X    for (; --cnt>=0; ++p)
  366. X        if (p->dev == dev)
  367. X            return (p->name);
  368. X    sprintf (buf, "%c %d/%d", typ, major (dev), minor (dev));
  369. X    return (buf);
  370. X}
  371. X
  372. Xchar *fetch (dev, inode, pdev, pinode)
  373. Xlong dev, inode, *pdev, *pinode;
  374. X{
  375. X    DBT key, val;
  376. X    struct fskey keyrec;
  377. X    struct fsrec *v;
  378. X
  379. X    keyrec.dev = dev;
  380. X    keyrec.inode = inode;
  381. X    key.data = (char *) &keyrec;
  382. X    key.size = sizeof (keyrec);
  383. X    if ((*db->get) (db, &key, &val, 0) != 0)
  384. X        return (0);
  385. X    v = (struct fsrec *) val.data;
  386. X    *pdev = v->pdev;
  387. X    *pinode = v->pinode;
  388. X    return (v->filename);
  389. X}
  390. X
  391. Xchar *strrcpy (to, from)
  392. Xchar *to, *from;
  393. X{
  394. X    int len = strlen (from);
  395. X
  396. X    strncpy (to -= len, from, len);
  397. X    return (to);
  398. X}
  399. X
  400. Xchar *filename (dev, inode)
  401. Xlong dev, inode;
  402. X{
  403. X    long pdev, pinode;
  404. X    static char fullname [512];
  405. X    char *p, *name;
  406. X
  407. X    if (! db)
  408. X        return (0);
  409. X    name = fetch (dev, inode, &pdev, &pinode);
  410. X    if (! name)
  411. X        return (0);
  412. X    p = fullname + sizeof (fullname);
  413. X    *--p = 0;
  414. X    for (;;) {
  415. X        p = strrcpy (p, name);
  416. X        if (dev==pdev && inode==pinode)
  417. X            break;
  418. X        *--p = '/';
  419. X        name = fetch (dev = pdev, inode = pinode, &pdev, &pinode);
  420. X        if (! name)
  421. X            return (0);
  422. X    }
  423. X    return (p);
  424. X}
  425. X
  426. Xvoid printvnode (v)
  427. Xstruct vnode *v;
  428. X{
  429. X    struct inode *i;
  430. X    char *name;
  431. X
  432. X    switch (v->v_type) {
  433. X    case VNON: case VBAD: case VSOCK: case VFIFO: case VLNK:
  434. X    default:
  435. X        printf (vnodetype (v->v_type));
  436. X        return;
  437. X    case VBLK: case VCHR: case VDIR: case VREG:
  438. X        break;
  439. X    }
  440. X    switch (v->v_tag) {
  441. X    default:
  442. X        printf ("%s on %d fs", vnodetype (v->v_type), v->v_tag);
  443. X        return;
  444. X    case VT_NON:
  445. X        printf ("%s nowhere", vnodetype (v->v_type));
  446. X        return;
  447. X    case VT_NFS:
  448. X        printf ("%s on nfs", vnodetype (v->v_type));
  449. X        return;
  450. X    case VT_MFS:
  451. X        printf ("%s on mfs", vnodetype (v->v_type));
  452. X        return;
  453. X    case VT_UFS:
  454. X        break;
  455. X    }
  456. X    i = VTOI (v);
  457. X    switch (v->v_type) {
  458. X    case VBLK:
  459. X        printf ("%s", devname ('b', i->i_rdev));
  460. X        return;
  461. X    case VCHR:
  462. X        printf ("%s", devname ('c', i->i_rdev));
  463. X        return;
  464. X    }
  465. X    name = filename (i->i_dev, i->i_number);
  466. X    switch (v->v_type) {
  467. X    case VDIR:
  468. X        if (name)
  469. X            printf ("%s/", name);
  470. X        else
  471. X            printf ("%s dir %d", devname ('b', i->i_dev), i->i_number);
  472. X        break;
  473. X    case VREG:
  474. X        if (name)
  475. X            printf ("%s", name);
  476. X        else
  477. X            printf ("%s file %d", devname ('b', i->i_dev), i->i_number);
  478. X        break;
  479. X    }
  480. X}
  481. X
  482. Xvoid printproc (f)
  483. Xstruct file *f;
  484. X{
  485. X    printf ("%6s %5s %8s ",
  486. X        fileflag (f->f_flag),   /* read/write etc. */
  487. X        filecount (f->f_count), /* reference count */
  488. X        fileoffset (f->f_offset) /* seek offset in file */
  489. X    );
  490. X    if (f->f_type == DTYPE_VNODE)
  491. X        printvnode (vnodetab + (f - filetab));
  492. X    else if (f->f_type == DTYPE_SOCKET)
  493. X        printf ("<socket>");
  494. X    printf ("\n");
  495. X}
  496. X
  497. Xusage ()
  498. X{
  499. X    fprintf (stderr, "Usage: %s [-s] [-f dbfile]\n", progname);
  500. X    exit (-1);
  501. X}
  502. X
  503. Xint fsrechash (a, sz)
  504. Xstruct fskey *a;
  505. X{
  506. X    return (a->inode);
  507. X}
  508. X
  509. Xint main (argc, argv)
  510. Xchar **argv;
  511. X{
  512. X    struct file *f;
  513. X    char *dbfile = FSDBFILE;
  514. X    HASHINFO hi;
  515. X
  516. X    /* Store the program name for message printing. */
  517. X    progname = strrchr (*argv, '/');
  518. X    if (! progname)
  519. X        progname = *argv;
  520. X
  521. X    /* Parse options. */
  522. X    for (++argv, --argc; *argv && **argv=='-'; ++argv, --argc) {
  523. X        char *p;
  524. X
  525. X        for (p=1+*argv; *p; ++p) {
  526. X            switch (*p) {
  527. X            case 's':
  528. X                ++sflag;
  529. X                continue;
  530. X            case 'f':
  531. X                dbfile = *++argv;
  532. X                --argc;
  533. X                if (! dbfile)
  534. X                    usage ();
  535. X                break;
  536. X            default:
  537. X                fprintf (stderr, "%s: no such option: %c\n",
  538. X                    progname, *p);
  539. X                usage ();
  540. X            }
  541. X            break;
  542. X        }
  543. X    }
  544. X    if (*argv)
  545. X        usage ();
  546. X
  547. X    /* Read kernel info. */
  548. X    readproc ();
  549. X    kvm_close ();
  550. X
  551. X    /* Open dev/inode to file name conversion database */
  552. X    hi.bsize = 512;                 /* page size */
  553. X    hi.cachesize = 200*512;         /* cache size */
  554. X    hi.hash = fsrechash;            /* hash function */
  555. X    hi.lorder = 0;                  /* byte order */
  556. X    hi.ffactor = 64;                /* fill factor */
  557. X    db = hash_open (dbfile, O_RDONLY, 0, &hi);
  558. X
  559. X    /* Print processes information. */
  560. X    printf (" FLAGS REFCNT  OFFSET FILENAME\n");
  561. X
  562. X    for (f=filetab; f->f_filef && f<filetab+nfiles; ++f)
  563. X        if (sflag || f->f_type==DTYPE_VNODE)
  564. X            printproc (f);
  565. X
  566. X    return (0);
  567. X}
  568. END-of-fs.c
  569. echo x - fs.h
  570. sed 's/^X//' >fs.h << 'END-of-fs.h'
  571. X/*
  572. X * Copyright (C) 1992 Sergey Vakulenko, <vak@kiae.su>.
  573. X * Permission to use and distribute this software is permitted
  574. X * without fee, provided that this copyright notice is not changed.
  575. X */
  576. X#define FSDBFILE "/var/db/fs.db"
  577. X
  578. Xstruct fskey {
  579. X    long dev;
  580. X    long inode;
  581. X};
  582. X
  583. Xstruct fsrec {
  584. X    long pdev;
  585. X    long pinode;
  586. X    char filename [256];
  587. X};
  588. END-of-fs.h
  589. echo x - fsdumpdb.c
  590. sed 's/^X//' >fsdumpdb.c << 'END-of-fsdumpdb.c'
  591. X/*
  592. X * Dump the file info database.  Used for debugging.
  593. X *
  594. X * Copyright (C) 1992 Sergey Vakulenko, <vak@kiae.su>.
  595. X * Permission to use and distribute this software is permitted
  596. X * without fee, provided that this copyright notice is not changed.
  597. X */
  598. X#include <stdio.h>
  599. X#include <sys/types.h>
  600. X#include <db.h>
  601. X#include <fcntl.h>
  602. X#include "fs.h"
  603. X
  604. XDB *db;
  605. Xchar *progname;
  606. Xint vflag = 0;
  607. X
  608. Xextern char *strrchr ();
  609. X
  610. Xvoid dump ()
  611. X{
  612. X    DBT key, val;
  613. X    struct fskey *k;
  614. X    struct fsrec *v;
  615. X
  616. X    for (;;) {
  617. X        if ((*db->seq) (db, &key, &val, 0) != 0) {
  618. X            perror ("seq");
  619. X            return;
  620. X        }
  621. X        k = (struct fskey *) key.data;
  622. X        v = (struct fsrec *) val.data;
  623. X        printf ("%d/%d -> %s\n", k->dev, k->inode, v->filename);
  624. X    }
  625. X}
  626. X
  627. Xint fsrechash (a, sz)
  628. Xstruct fskey *a;
  629. X{
  630. X    return (a->inode);
  631. X}
  632. X
  633. Xusage ()
  634. X{
  635. X    fprintf (stderr, "Usage: %s [dbfile]\n", progname);
  636. X    exit (-1);
  637. X}
  638. X
  639. Xint main (argc, argv)
  640. Xchar **argv;
  641. X{
  642. X    char *dbname = FSDBFILE;
  643. X    HASHINFO hi;
  644. X
  645. X    /* Store the program name for message printing. */
  646. X    progname = strrchr (*argv, '/');
  647. X    if (! progname)
  648. X        progname = *argv;
  649. X
  650. X    /* Parse options. */
  651. X    for (++argv, --argc; *argv && **argv=='-'; ++argv, --argc) {
  652. X        char *p;
  653. X
  654. X        for (p=1+*argv; *p; ++p) {
  655. X            switch (*p) {
  656. X            case 'v':
  657. X                ++vflag;
  658. X                continue;
  659. X            default:
  660. X                fprintf (stderr, "%s: no such option: %c",
  661. X                    progname, *p);
  662. X                usage ();
  663. X            }
  664. X        }
  665. X    }
  666. X    if (*argv)
  667. X        dbname = *argv++;
  668. X    if (*argv)
  669. X        usage ();
  670. X
  671. X    /* Open dev/inode to file name conversion database */
  672. X    hi.bsize = 512;                 /* page size */
  673. X    hi.cachesize = 200*512;         /* cache size */
  674. X    hi.hash = fsrechash;            /* hash function */
  675. X    hi.lorder = 0;                  /* byte order */
  676. X    hi.ffactor = 64;                /* fill factor */
  677. X    db = hash_open (dbname, O_RDONLY, 0, &hi);
  678. X    if (! db) {
  679. X        fprintf (stderr, "%s: cannot read %s", progname, dbname);
  680. X        exit (-1);
  681. X    }
  682. X    dump ();
  683. X
  684. X    return (0);
  685. X}
  686. END-of-fsdumpdb.c
  687. echo x - fsmakedb.1
  688. sed 's/^X//' >fsmakedb.1 << 'END-of-fsmakedb.1'
  689. X.\" Copyright (C) 1992 Sergey Vakulenko, <vak@kiae.su>.
  690. X.\" Permission to use and distribute this software is permitted
  691. X.\" without fee, provided that this copyright notice is not changed.
  692. X.Dd November 16, 1992
  693. X.Dt FSMAKEDB 8
  694. X.Os BSD 3
  695. X.Sh NAME
  696. X.Nm fsmakedb
  697. X.Nd create file name database for fs(1) utility
  698. X.Sh SYNOPSIS
  699. X.Nm fsmakedb
  700. X.Op Ar dbfile
  701. X.Sh DESCRIPTION
  702. XThe
  703. X.Nm fsmakedb
  704. Xutility creates the database of all files in the filesystem.
  705. X.Pp
  706. XThe
  707. X.Ar dbfile
  708. Xis the database name to create, default
  709. X.Ql /var/db/fs.db .
  710. X.Pp
  711. XIn order to have read/chdir access to all directories, the
  712. X.Nm fsmakedb
  713. Xutility should run setuid root.
  714. X.Sh SEE ALSO
  715. X.Xr fs 1 .
  716. END-of-fsmakedb.1
  717. echo x - fsmakedb.c
  718. sed 's/^X//' >fsmakedb.c << 'END-of-fsmakedb.c'
  719. X/*
  720. X * Create the file info database for the fs(1) utility.
  721. X *
  722. X * Copyright (C) 1992 Sergey Vakulenko, <vak@kiae.su>.
  723. X * Permission to use and distribute this software is permitted
  724. X * without fee, provided that this copyright notice is not changed.
  725. X */
  726. X#include <stdio.h>
  727. X#include <sys/types.h>
  728. X#include <db.h>
  729. X#include <dirent.h>
  730. X#include <sys/stat.h>
  731. X#include <fcntl.h>
  732. X#include "fs.h"
  733. X
  734. XDB *db;
  735. Xchar *progname;
  736. Xint vflag = 0;
  737. X
  738. Xextern char *strrchr ();
  739. X
  740. X/* VARARGS1 */
  741. Xvoid fatal (msg, a, b, c, d)
  742. Xchar *msg;
  743. Xlong a, b, c, d;
  744. X{
  745. X    fprintf (stderr, "%s: ", progname);
  746. X    fprintf (stderr, msg, a, b, c, d);
  747. X    fprintf (stderr, "\n");
  748. X    exit (-1);
  749. X}
  750. X
  751. Xvoid store (dev, inode, name, pdev, pinode)
  752. Xchar *name;
  753. X{
  754. X    DBT key, val;
  755. X    struct fskey keyrec;
  756. X    struct fsrec valrec;
  757. X
  758. X    keyrec.dev = dev;
  759. X    keyrec.inode = inode;
  760. X    key.data = (char *) &keyrec;
  761. X    key.size = sizeof (keyrec);
  762. X
  763. X    valrec.pdev = pdev;
  764. X    valrec.pinode = pinode;
  765. X    strcpy (valrec.filename, name);
  766. X    val.data = (char *) &valrec;
  767. X    val.size = (char *) &valrec.filename - (char *) &valrec +
  768. X        strlen (name) + 1;
  769. X
  770. X    if (vflag)
  771. X        printf ("%d/%d -> %s\n", dev, inode, name);
  772. X    if ((*db->put) (db, &key, &val, R_PUT) != 0)
  773. X        fprintf (stderr, "error storing new record\n");
  774. X}
  775. X
  776. Xvoid scan (dir, pst)
  777. Xchar *dir;
  778. Xstruct stat *pst;
  779. X{
  780. X    DIR *dird;
  781. X    struct dirent *d;
  782. X    struct stat st;
  783. X
  784. X    if (chdir (dir) < 0) {
  785. X        perror (dir);
  786. X        return;
  787. X    }
  788. X    dird = opendir (".");
  789. X    if (! dird) {
  790. X        perror (dir);
  791. X        chdir ("..");
  792. X        return;
  793. X    }
  794. X    for (d=readdir(dird); d; d=readdir(dird)) {
  795. X        if (d->d_name[0] == '.' && (d->d_name[1] == 0 ||
  796. X            d->d_name[1] == '.' && d->d_name[2] == 0))
  797. X            continue;
  798. X        if (lstat (d->d_name, &st) < 0) {
  799. X            perror (d->d_name);
  800. X            continue;
  801. X        }
  802. X        store (st.st_dev, st.st_ino, d->d_name, pst->st_dev, pst->st_ino);
  803. X        if ((st.st_mode & S_IFMT) == S_IFDIR)
  804. X            scan (d->d_name, &st);
  805. X    }
  806. X    closedir (dird);
  807. X    chdir ("..");
  808. X}
  809. X
  810. Xint fsrechash (a, sz)
  811. Xstruct fskey *a;
  812. X{
  813. X    return (a->inode);
  814. X}
  815. X
  816. Xint main (argc, argv)
  817. Xchar **argv;
  818. X{
  819. X    char *dbname = FSDBFILE;
  820. X    struct stat st;
  821. X    HASHINFO hi;
  822. X
  823. X    /* Store the program name for message printing. */
  824. X    progname = strrchr (*argv, '/');
  825. X    if (! progname)
  826. X        progname = *argv;
  827. X
  828. X    /* Parse options. */
  829. X    for (++argv, --argc; *argv && **argv=='-'; ++argv, --argc) {
  830. X        char *p;
  831. X
  832. X        for (p=1+*argv; *p; ++p) {
  833. X            switch (*p) {
  834. X            case 'v':
  835. X                ++vflag;
  836. X                break;
  837. X            default:
  838. X                fatal ("no such option: %c", *p);
  839. X            }
  840. X        }
  841. X    }
  842. X    if (*argv)
  843. X        dbname = *argv++;
  844. X    if (*argv)
  845. X        fatal ("usage: %s [dbfile]", progname);
  846. X
  847. X    /* Open dev/inode to file name conversion database */
  848. X    hi.bsize = 512;                 /* page size */
  849. X    hi.cachesize = 200*512;         /* cache size */
  850. X    hi.hash = fsrechash;            /* hash function */
  851. X    hi.lorder = 0;                  /* byte order */
  852. X    hi.ffactor = 64;                /* fill factor */
  853. X    db = hash_open (dbname, O_RDWR|O_CREAT|O_TRUNC, 0644, &hi);
  854. X    if (! db)
  855. X        fatal ("cannot create %s", dbname);
  856. X
  857. X    if (lstat ("/", &st) < 0) {
  858. X        perror ("/");
  859. X        return (-1);
  860. X    }
  861. X
  862. X    /* Scan all files recursively beginning from the root. */
  863. X    store (st.st_dev, st.st_ino, "", st.st_dev, st.st_ino);
  864. X    scan ("/", &st);
  865. X
  866. X    dbm_close (db);
  867. X    return (0);
  868. X}
  869. END-of-fsmakedb.c
  870. exit
  871.