/* TREEDIR -- Tree directory for MSDOS V2.0 and above. This program combines TREE and DIR to produce a directory of all files in each directory along with date, time and file size. usage: TREEDIR [directory] [/s] [/knnn] If the directory is omitted, the tree starts with the root directory. Use TREEDIR . to start from the current directory. Totals are given for each directory, which includes the totals of any sub-directories. If the /s option is specified only the totals are displayed. This program was primarily written to display the actual space used on the hard disk for each directory, and the amount of space needed to copy to a diskette. This is due to the allocation cluster of MSDOS: files on diskette are allocated in increments of 1024 bytes while files on the hard disk (10 MB) are in 4096 byte chunks. To see the space that would be taken by some other allocation size, use the /k option. For example, to see how much hard disk space would be used by copying all the files from the diskette on drive a, type treedir a: /k4 The program as written requires Lattice c, version 2.1 or higher. No attempt was made to keep it portable, since the dos interface is non-portable by definition. The Lattice conio.h is used instead of stdio.h, resulting in direct console i/o and a smaller com file. The program also requires DOS 2.0 or higher, since it doesn't make any sense otherswise. Alan Losoff Milwaukee, Wisconsin revisions: 07-05-84 1.01 test for ^C hit (needed when bypassing standard i/o) 08-01-84 1.2 add summary /s option 09-13-84 1.3 add /k other allocation. clean up format */ #include /* Lattice direct console I/O */ #include /* time/date file from my cc.bat */ /* static char *__stamp[] = {"dd/dd/dd", "tt/tt/tt"}; */ /* BDOS CALLS */ #define GETFAT 0x3600 #define SETDTA 0x1A00 #define FFIRST 0x4E00 #define FNEXT 0x4F00 #define SUBDIR 0x0010 /* attribute for sub directory */ #define CTRL_C 3 struct XREG /* for lattice bdos call */ { short ax,bx,cx,dx,si,di; }; struct DIRS /* dos directory entry */ { char for_dos[21]; char attr; struct { unsigned hour : 5; unsigned minute : 6; unsigned twosec : 5; } time; struct { unsigned year : 7; unsigned month : 4; unsigned day : 5; } date; long size; char name[13]; char fill[85]; }; struct counts { int files; long blocks; long others; long bytes; }; int _stack = 10000; /* set stack size (lattice specific) */ static long blocksize = 0; /* cluster size for drive specified */ static long othersize = 1024; static int summary = 0; /* switch for summary only */ #define unit(n, u) (((n) + (u) - 1) / (u)) #define kbytes(n, u) unit((n)*(u), 1024) main(argc, argv) int argc; char *argv[]; { char *path; int n; for (n=1; n 1 && argv[1][0] != '/') ? argv[1] : ""; blocksize = cluster(path); printf("\nTREEDIR Tree Directory version 1.3 compiled%s\n\n", __stamp[0]); printf("%-36s %-18sBytes (%4ld) (%4ld)\n", "Filename", summary ? "" : "Date Time", blocksize, othersize); pdir (path, 0); } pdir (path, cp) /* print & total for given path */ char *path; struct counts *cp; { static margin = -2; char *indent(); char newpath[129]; struct DIRS buf; struct counts c; int r; long n, k; margin += 2; c.bytes = c.files = c.blocks = c.others = 0; for (r = first(path, &buf); !r; r = next(path, &buf)) { kbhit(); /* checks for ^C */ if (*buf.name == '.') continue; if (buf.attr & SUBDIR) { if (!summary) printf("\n\n%-36s", indent(margin, buf.name)); sprintf(newpath, "%s\\%s", path, buf.name); pdir(newpath, &c); } else { n = unit(buf.size, blocksize); k = unit(buf.size, othersize); if (!summary) printf("\n%-36s%2d/%02d/%02d %2d:%02d %9ld %5ldK %5ldK", indent(margin, buf.name) , buf.date.month, buf.date.day, buf.date.year+80, buf.time.hour, buf.time.minute, buf.size, kbytes(n, blocksize), kbytes(k, othersize)); c.files++; c.blocks += n; c.others += k; c.bytes += buf.size; } } margin -= 2; if (summary) printf("\n%-41s%4d files %9ld %5ldK %5ldK **", path, c.files, c.bytes, kbytes(c.blocks, blocksize), kbytes(c.others, othersize)); else printf("\n%-41s%4d files %9ld %5ldK %5ldK **", "", c.files, c.bytes, kbytes(c.blocks, blocksize), kbytes(c.others, othersize)); if (cp) { cp->blocks += c.blocks; cp->others += c.others; cp->files += c.files; cp->bytes += c.bytes; } return; } char * indent (margin, name) /* indent name to margin */ int margin; char *name; { int n; static char work[129]; for (n = 0; n< margin; n++) work[n] = ' '; strcpy(work + margin, name); return (work); } cluster(dir) /* return cluster size of disk */ char *dir; { struct XREG inregs, outregs; inregs.dx = dir[1] == ':' ? dir[0] & 0x1F : 0; inregs.ax = GETFAT; intdos(&inregs, &outregs); return (outregs.ax * outregs.cx); } first (dir, buf) /* find first directory entry */ char *dir, *buf; { struct XREG inregs, outregs; char arg[129]; inregs.ax = SETDTA; inregs.dx = (int) buf; intdos(&inregs, &outregs); sprintf(arg, "%s\\????????.???", dir); inregs.ax = FFIRST; inregs.cx = SUBDIR; inregs.dx = (int) (&arg); intdos(&inregs, &outregs); return (outregs.ax); } next (dir, buf) /* find next directory entry */ char *dir, *buf; { struct XREG inregs, outregs; char arg[129]; inregs.ax = SETDTA; inregs.dx = (int) buf; intdos(&inregs, &outregs); sprintf(arg, "%s\\*.*", dir); inregs.ax = FNEXT; inregs.cx = SUBDIR; inregs.dx = (int) (&arg); intdos(&inregs, &outregs); return (outregs.ax); } ; inregs.cx = SUBDIR; inregs.dx = (int) (&arg); intdos(&inregs, &outregs); return (outregs.ax); }