[comp.sources.misc] v07i112: My reworking of "vol"

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (07/31/89)

Posting-number: Volume 7, Issue 112
Submitted-by: allbery@uunet.UU.NET (Your friendly neighborhood c.s.m moderator)
Archive-name: vol_bsa

The recently submitted "vol" program will not work on any System V or Xenix
5.x that I have access to; and from the looks of it, it would not work on any
standard Unix system.  Since (as per my comment in the original) it is
potentially useful for sites which run C news and don't have "smart" "df"
commands, I've rewritten it.

Usage:  vol [-qd] [file/directory ...]

-q suppresses the "file: " label on output, so the result can be passed to
another program.  -d outputs the device instead of the filesystem root.

++Brandon
#------------------------------- cut here -------------------------------------
#! /bin/sh
# This file was wrapped with "dummyshar".  "sh" this file to extract.
# Contents:  vol.c
echo extracting 'vol.c'
if test -f 'vol.c' -a -z "$1"; then echo Not overwriting 'vol.c'; else
sed 's/^X//' << \EOF > 'vol.c'
X/*
X * The "vol" program I was passed was just plain unusable.  I'm surprised
X * that it ever worked on *any* system -- certainly it is guaranteed to fail
X * on all of the System V's I've ever used.  So here's my own.
X * (To the original author:  watch and learn, grasshopper!  ;-)
X *
X * usage: vol [-q] [-d] [file ...]
X *	-q: quiet, no "(file) is on " label
X *	-d: report device instead of filesystem root
X *	default file is current directory
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <string.h>
X#include <mnttab.h>
X
X#define MAXPATH		64
X#define MAXFS		32
X
Xstatic struct fs
X{
X    char fs_name[MAXPATH];
X    dev_t fs_devno;
X};
X
Xstatic struct fs filesys[MAXFS];
Xstatic int numfs = 0;
X
X#ifdef __STDC__
X# define PROTO(x) x
X# define generic void
X#else
X# define PROTO(x) ()
X# define generic char
X# define const
X#endif
X
Xextern int getopt PROTO((int, const char **, const char *));
Xextern void exit PROTO((int));
Xextern int stat PROTO((const char *, struct stat *));
Xextern void perror PROTO((const char *));
Xextern int printf PROTO((const char *, ...));
Xextern int strcmp PROTO((const char *, const char *));
Xextern FILE *fopen PROTO((const char *, const char *));
Xextern int fread PROTO((char *, unsigned, unsigned, FILE *));
Xextern char *strcpy PROTO((char *, const char *));
Xextern int strlen PROTO((const char *));
Xextern char *strncat PROTO((char *, const char *, int));
Xextern int fprintf PROTO((FILE *, const char *, ...));
Xextern char *strncpy PROTO((char *, const char *, int));
Xextern int fclose PROTO((FILE *));
Xextern void qsort PROTO((void *, int, unsigned, int (*)()));
X
Xint main PROTO((int, const char **));
Xint process PROTO((const char *, int));
Xint revsort PROTO((const generic *, const generic *));
Xint build_mount_table PROTO((int));
Xchar *match PROTO((dev_t));
X
Xint
Xmain(argc, argv)
X    char *argv[];
X{
X    int opt, verbose, devonly, nerr;
X    extern int optind;
X    extern char *optarg;
X
X    verbose = 1;
X    devonly = 0;
X    nerr = 0;
X    while ((opt = getopt(argc, argv, "qd")) != EOF)
X	switch (opt)
X	{
X	case 'q':
X	    verbose = !verbose;
X	    break;
X	case 'd':
X	    devonly = !devonly;
X	    break;
X	default:
X	    nerr = 1;
X	}
X    if (nerr != 0)
X    {
X	(void) fprintf(stderr, "usage: %s [-qd] [file ...]\n",
X		       (argc == 0? "vol": argv[0]));
X	exit(1);
X    }
X    if (!build_mount_table(devonly))
X	exit(1);
X    nerr = 0;
X    if (optind == argc)
X	nerr += process(".", verbose);
X    else
X	while (optind != argc)
X	    nerr += process(argv[optind++], verbose);
X    exit(nerr);
X}
X
Xint
Xprocess(name, verbose)
X    const char *name;
X    int verbose;
X{
X    struct stat buf;
X    char *path;
X
X    if (stat(name, &buf) == -1)
X    {
X	perror(name);
X	return 1;
X    }
X    else if ((path = match(buf.st_dev)) == (char *) 0)
X    {
X	(void) fprintf(stderr, "%s: Filesystem unknown\n", name);
X	return 1;
X    }
X    else
X    {
X	if (verbose)
X	    (void) printf("%s: ", name);
X	(void) puts(path);
X	return 0;
X    }
X}
X
Xint
Xrevsort(p1, p2)
X    const generic *p1, *p2;
X{
X    return - strcmp(((struct fs *) p1)->fs_name, ((struct fs *) p2)->fs_name);
X}
X
Xint
Xbuild_mount_table(use_dev)
X    int use_dev;
X{
X    struct mnttab disk;
X    struct stat buf;
X    FILE *mount;
X    char dev[1024];
X    int start;
X
X    if ((mount = fopen("/etc/mnttab", "r")) == (FILE *) 0)
X    {
X	perror("/etc/mnttab");
X	return 0;
X    }
X    while (fread((generic *) &disk, sizeof disk, 1, mount) == 1)
X    {
X	if (disk.mt_dev[0] == '\0' || disk.mt_filsys[0] == '\0')
X	    continue;		/* null entry -- unmounted fs */
X	if (disk.mt_dev[0] != '/')
X	    (void) strcpy(dev, "/dev/");
X	else
X	    dev[0] = '\0';
X	start = strlen(dev);
X	(void) strncat(dev, disk.mt_dev, sizeof disk.mt_dev);
X	dev[start + sizeof disk.mt_dev] = '\0';
X	if (stat(dev, &buf) == -1)
X	{
X	    perror(dev);
X	    continue;
X	}
X	if ((buf.st_mode & S_IFMT) != S_IFBLK)
X	{
X	    fprintf(stderr, "dev: Not block special\n", dev);
X	    continue;
X	}
X	if (use_dev)
X	    (void) strcpy(filesys[numfs].fs_name, dev);
X	else
X	{
X	    (void) strncpy(filesys[numfs].fs_name, disk.mt_filsys,
X			   sizeof disk.mt_filsys);
X	    filesys[numfs].fs_name[sizeof disk.mt_filsys] = '\0';
X	}
X	filesys[numfs++].fs_devno = buf.st_rdev;
X    }
X    (void) fclose(mount);
X    qsort((generic *) filesys, numfs, sizeof *filesys, revsort);
X    return 1;
X}
X
Xchar *
Xmatch(id)
X    dev_t id;
X{
X    int fs;
X
X    for (fs = 0 ; fs < numfs; fs++)
X	if (filesys[fs].fs_devno == id)
X	    return filesys[fs].fs_name;
X    return (char *) 0;
X}
EOF
chars=`wc -c < 'vol.c'`
if test $chars !=     4453; then echo 'vol.c' is $chars characters, should be     4453 characters!; fi
fi
exit 0
--
Brandon S. Allbery, moderator of comp.sources.misc	allbery@uunet.uu.net
Please send comp.sources.misc submissions to comp-sources-misc@<backbone>,
related mail to comp-sources-misc-request@<backbone>, and personal mail ONLY
to allbery@NCoast.ORG.  You have only yourself to blame if you don't.