disklist - find-like directory tree dumper

J. Deters jad at dayton.UUCP
Fri Feb 8 04:03:38 AEST 1991


[ I am posting this for a friend who does not have net access.  Please
  make sure that any replies, flames, kudos or $$$ are mailed to:
  joel at crystal.mn.org.  Thank you, -j ]

------

This is "disklist", a find-like program to dump directory trees.  Unlike find,
it knows where disk boundaries sit.  This is nice when you have a bunch of
disks on your machine, but you're currently only interested in one.  It has
some other small features, as well.  (See the -h option.)

It doesn't incorporate very many of the features in find yet.  It will,
eventually.  If you should add any, send the code my way, please.

-Joe

---Cut here---8<---Valuable Coupon---8<---Clip'n'save---8<---Scratch'n'sniff---
#!/bin/sh
# This is a shell archive (shar 3.47)
# made 02/07/1991 16:03 UTC by joel at crystal
# Source directory /users/mpls/mis/joel/work/newos/xx
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   6159 -rw-r--r-- disklist.c
#   1552 -rw-r--r-- readme
#
# ============= disklist.c ==============
if test -f 'disklist.c' -a X"$1" != X"-c"; then
	echo 'x - skipping disklist.c (File already exists)'
else
echo 'x - extracting disklist.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'disklist.c' &&
/*
X * disklist: list contents of a disk without stepping into children disks.
X *           see the "-h" option for more help.
X *
X * Author:
X *
X *      Joseph P. Larson
X *      Crystal Farms
X *      6465 Wayzata Blvd, Suite 200
X *      St. Louis Park, Minnesota 55426
X *      612-542-1245
X *      joel at crystal.mn.org
X *
X * Copyright 1991 by Crystal Farms.  Permission is hearby granted to
X *      distribute this software provided this comment remains intact
X *      and fees are limited to reasonable media costs only.  Furthermore,
X *      if you make changes, please comment your changes and inform the
X *      author.
X *
X * Revision History:
X *
X *      1-8-91      jpl.        Created.
X *      2-7-91      jpl.        Added -d option.
X */
X
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <time.h>
X
#define DIRECT struct direct
#define STAT struct stat
#define TM struct tm
X
short   disk_cnt, skip_cnt;
char    disk_names[12][32],
X        *skip_names[100];
char    dolong, showdsize;
X
main(argc,argv)
int argc;
char **argv;
{
X    short   i;
X    char    c;
X    extern int optind;
X    extern char *optarg;
X
X    skip_cnt = 0;
X    dolong = 0;
X    showdsize = 0;
X    while ((c = getopt(argc, argv, "dls:hH")) != EOF)
X        switch (c)
X        {
X            case 'd':   showdsize = 1; break;
X            case 'l':   dolong = 1; break;
X            case 's':   skip_names[skip_cnt++] = optarg; break;
X            case 'H':
X            case 'h':
X            default:    usage(argv[0]);
X        }
X
X    getdlist();
X    for (i = optind; i < argc; i++)
X    {
/*      if (argv[i][0] != '/')
X        {
X            fprintf(stderr, "%s: Must use absolute pathnames:%s.\n",
X                    argv[0], argv[i]);
X            continue;
X        }
*/      procdir(argv[i]);
X    }
}
X
getdlist()
/*
X * Read the /etc/fstab file, getting the list of disk mount points.
X *      This provides us with a list of directories that aren't expanded.
X */
{
X    char    line[132], *cptr;
X    FILE    *file;
X    short   i;
X
X    disk_cnt = 0;
X    if (!(file = fopen("/etc/fstab", "r")))
X        xerror("/etc/mntnodes");
X    while (fgets(line, 132, file))
X    {
X        for (cptr = line; *cptr && isspace(*cptr); cptr++);
X        if (!(*cptr) || (*cptr == '#')) continue;
X        for ( ; *cptr && !isspace(*cptr); cptr++);
X        for ( ; isspace(*cptr); cptr++);
X        for (i = 0; *cptr && !isspace(*cptr); i++, cptr++)
X            disk_names[disk_cnt][i] = *cptr;
X        disk_names[disk_cnt][i] = 0;
X        disk_cnt++;
X    }
X    fclose(file);
}
X
procdir(dname)
char *dname;
/*
X * Do this directory.
X */
{
X    DIRECT  *dbuf;              /* Current directory entry      */
X    STAT    sbuf;               /* For doing stat() calls       */
X    FILE    *file;              /* The directory file           */
X    TM      *tmptr;             /* Return from localtime()      */
X    long    dtotalsize;         /* Used with -d option.         */
X    short   i, j, ncnt;         /* Various counters             */
X    int     cmpdir();           /* For sorting dnames.          */
X    char    fname[256],         /* New file name                */
X            *fptr,              /* Offset into fname            */
X            *dirind;            /* Either "dir" or "   "        */
X    char    gonofurther;        /* Do not expand subdirs?       */
X
X    gonofurther = 0;
X    for (i = 0; i < skip_cnt; i++)
X        if (!strcmp(skip_names[i], dname))
X        {
X            gonofurther = 1;
X            break;
X        }
X    if (stat(dname, &sbuf) < 0)
X    {
X        perror(dname);
X        return;
X    }
X    dbuf = (DIRECT *)malloc(sbuf.st_size);
X    if (!(file = fopen(dname, "r")))
X    {
X        perror(dname);
X        free(dbuf);
X        return;
X    }
X    dtotalsize = sbuf.st_size;
X    ncnt = sbuf.st_size / sizeof(DIRECT);
X    fread(dbuf, sizeof(DIRECT), ncnt, file);
X    fclose(file);
X    qsort(dbuf, ncnt, sizeof(DIRECT), cmpdir);
X
X    strcpy(fname, dname);
X    if (strcmp(dname, "/")) strcat(fname, "/");
X    fptr = fname + strlen(fname);
X                                    /* Go dump ALL the files. */
X    for (i = 0; i < ncnt; i++)
X    {
X        if (!dbuf[i].d_ino) continue;
X        if (!strcmp(dbuf[i].d_name, ".") || !strcmp(dbuf[i].d_name, ".."))
X        {
X            dbuf[i].d_ino = 0;
X            continue;
X        }
X        strncpy(fptr, dbuf[i].d_name, 14);
X        fptr[14] = 0;
X        if (stat(fname, &sbuf) < 0)
X        {
X            perror(fname);
X            dbuf[i].d_ino = 0;
X            continue;
X        }
X        dirind = "dir";
X        if (gonofurther || ((sbuf.st_mode & 0170000) != 040000))
X        {
X            dbuf[i].d_ino = 0;
X            dirind = "   ";
X        }
X        if (dolong)
X        {
X            tmptr = localtime(&sbuf.st_mtime);
X            printf("%9d  %2d-%2d-%2d  %s  %s\n", sbuf.st_size,
X                tmptr->tm_mon+1, tmptr->tm_mday, tmptr->tm_year,
X                dirind, fname);
X        }
X        else
X            puts(fname);
X        dtotalsize += sbuf.st_size;
X    }
X    if (showdsize)
X        printf("%9d            Tot  Directory Total (bytes)\n", dtotalsize);
X
X                                    /* Now go back and get the subdirectories */
X    for (i = 0; i < ncnt; i++)
X    {
X        if (!dbuf[i].d_ino) continue;
X        strncpy(fptr, dbuf[i].d_name, 14);
X        fptr[14] = 0;
X        for (j = 0; j < disk_cnt; j++)
X            if (!strcmp(fname, disk_names[j])) break;
X        if (j >= disk_cnt) procdir(fname);
X    }
X
X    free(dbuf);
}
X
cmpdir(d1,d2)
DIRECT *d1, *d2;
/*
X * Compare two directory names.
X */
{
X    char    n1[16], n2[16];
X
X    if (!d1->d_ino && !d2->d_ino) return(0);
X    if (!d1->d_ino) return(-1);
X    if (!d2->d_ino) return(1);
X    strncpy(n1, d1->d_name, 14);
X    n1[14] = 0;
X    strncpy(n2, d2->d_name, 14);
X    n2[14] = 0;
X    return(strcmp(n1, n2));
}
X
usage(arg)
char *arg;
{
X    fprintf(stderr, "\
Usage: %s [-d] [-l] [-s skipdir] fulldiskpathname\n\
Where:\n\
X       -d    show directory size totals\n\
X       -l    long listing (show date, size, etc)\n\
X       -s    do not expand subdirectories of skipdir\n", arg);
X    exit(-1);
}
SHAR_EOF
chmod 0644 disklist.c ||
echo 'restore of disklist.c failed'
Wc_c="`wc -c < 'disklist.c'`"
test 6159 -eq "$Wc_c" ||
	echo 'disklist.c: original size 6159, current size' "$Wc_c"
fi
# ============= readme ==============
if test -f 'readme' -a X"$1" != X"-c"; then
	echo 'x - skipping readme (File already exists)'
else
echo 'x - extracting readme (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'readme' &&
Ever wish the find program could stop at disk boundaries or perhaps exclude
certain directories?  Or maybe you just wish it would sort the file names
for you.
X
When I need to shuffle stuff off one disk onto another, I like to see what
is on the disk first.  Find doesn't really let you do that, so I wrote
"disklist".  It's not as full-featured as find (yet), but it does know where
disk boundaries are, and it sorts the file names for me.  Also, it doesn't
expand subdirectories until it lists the entire top directory first.
X
X
BUGS:
X
Disklist does assume SysV directory types.  That is, "struct direct"
exists, a directory is readable, and everything you need to know about
file names in the directory is in there.  Thus, it probably won't work
on an RS-6000, for instance.
X
It does work just fine on my NCR Tower 32/850 running SysVR3.  It did work
under SysVR2, but you may need to change the section that reads /etc/fstab
to get it to run on your machine.  (That's how it knows where disk boundaries
are.)
X
I commented-out the code that forces full path names.  However, if you do
not specify the full path name of the directory you are dumping, disklist
won't know to where to stop if any disks are mounted below the disk being
listed.  That's life.  (Someone with time on their hands could always
fix this, but I didn't think it was worth bothering with.)
X
X
If you should make changes (other than those associated with reading your
fstab, mntnodes, or whatever file), please drop me a line.  Thanks.
X
Joe Larson
joel at crystal.mn.org
612-542-1683
SHAR_EOF
chmod 0644 readme ||
echo 'restore of readme failed'
Wc_c="`wc -c < 'readme'`"
test 1552 -eq "$Wc_c" ||
	echo 'readme: original size 1552, current size' "$Wc_c"
fi
exit 0
----
Joe Larson               joel at crystal.mn.org       612-542-1245(w)
Crystal Foods                                      612-591-1037(h)
6465 Wayzata Blvd
St. Louis Park, Mn 55426
-- 
J. Deters
INTERNET:  jad at dayton.DHDSC.MN.ORG  ATT:   612-375-3116
UUCP:  ...!bungia!dayton!jad        USPS:  700 Nicollet Mall/MIS 1060
ICBM:  44^58'36"N by 93^16'14"W            Minneapolis, MN  55402



More information about the Alt.sources mailing list