jad@dayton.UUCP (J. Deters) (02/08/91)
[ 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@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@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@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@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@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@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