/*************************************************************** * * Lib.c * * Disk Library Documentation System * Main Program * * By Wilson Snyder (c) January 1988 * **************************************************************** * * NOTICE: * * This program was written as a service to the amiga * users. This program may be used by all parties, including * sale (see below) as long as the author's name and address * remains intact in the program and documentation. * Distribution of this program by parties selling it * as part of a commercial for-profit package of over $10 * must contact the address below before such a package is sold. * * I make no warranties over this program, performance, * etc. And any costs incurred by this program, or its * actions are placed on the user. * * PLEASE FORWARD INPROVEMENTS MADE TO THIS PROGRAM TO: * * Wilson Snyder, 15 Davis Parkway, South Burlington, VT 05403 * **************************************************************** * * AddName and base for Process taken from the TSIZE * utility written by the excellent work of the * Software Distillery. * ****************************************************************/ #include "libraries/dosextens.h" #include "ctype.h" #include "stdio.h" #define VERSION "AMIGA-LIB. Version 1.0.2. By Wilson Snyder" #define DESC "$$DES$$" #define PERSUB 8 /* Characters to indent per subdirectory */ #define INFOIND 8 /* Indent for description and filesize */ #define RM 75 /* Right margin */ #define LM 0 /* Left margin */ #define TM 1 /* Top margin */ #define HM 2 /* Header margin (lines after header) */ #define LINES 60 /* Lines per page */ BPTR Lock(); /* Define functions... */ BOOL Examine(); BOOL ExNext(); char path [256]; /* Current search path */ char header [80]; /* Header for top line */ BOOL prtsize = FALSE; /* Print the path size information */ BOOL prtheader = FALSE; /* Print the header and page breaks */ struct Sortem { /* Linked list for insertion sort of directory names */ char FileName[108]; /* Directory name */ struct Sortem *Next; /* Pointer to next */ }; /*************************************************************** * ADDNAME * * Add filename to the end of the current path. * * Routine taken from from TSIZE utility by the Software Distillery. ***************************************************************/ int AddName(name, len) register char *name; int len; { register char *p; /* current position in path */ register int i = 0; /* added length counter */ char ch; /* last character of current path */ p = path + len; /* add a slash between path and name if legal */ if (len != 0 && (ch = path[len-1]) != '/' && ch != ':') { *p++ = '/'; i++; } /* copy name to end of path (including null terminator) */ while (*p++ = *name++) i++; /* return new length of path */ return (len + i); } /*************************************************************** * FILECMP * Compare two filenames for sort routine (case insensitive.) ***************************************************************/ int filecmp(a,b) char *a,*b; { for (;toupper(*a)==toupper(*b);a++,b++) if (*a=='\0') return (0); return (toupper(*a)-toupper(*b)); } /*************************************************************** * INDENT * Indent a number of spaces. Outputted to stdout. ***************************************************************/ void Indent(num) int num; { while (num--) putchar (' '); } /*************************************************************** * HEADER * Print header every so many lines. ***************************************************************/ void Header(inc) int inc; { static int linecount; /* Number of lines down */ static int page; /* Current page number */ int t; /* Temp */ if (inc) linecount += inc; else { /* 0 increment resets information */ linecount = 0; page = 0; } if (linecount>LINES && prtheader) { /* Time to print the header */ putchar ('\f'); page++; for (t=TM;t;t--) putchar ('\n'); printf (header,page); for (t=HM;t;t--) putchar ('\n'); linecount = TM + HM + 1; } } /*************************************************************** * ROOT * Print information for the page header ***************************************************************/ BOOL Root() { struct FileInfoBlock *info; /* pointer to file info */ BPTR lock; /* pointer to file lock */ int t,loc; /* temp stuff */ /* allocate an info block (must be longword alligned) */ if (!(info = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock), 0))) { printf ("Out of memory.\n"); return (TRUE); } /* try to obtain lock on current file */ if (!(lock = Lock(path, ACCESS_READ))) { printf ("Invalid file or directory, '%s'.\n", path); FreeMem(info, sizeof(struct FileInfoBlock)); return (TRUE); } /* get information on file or directory associated with lock */ if (!Examine(lock, info)) { printf ("Error examining locked file or directory.\n"); UnLock(lock); FreeMem(info, sizeof(struct FileInfoBlock)); return (TRUE); } /* Make sure user specified a directory, not a file */ if (info->fib_DirEntryType <= 0) { printf ("Must specify a directory, not a file.\n"); UnLock(lock); FreeMem(info, sizeof(struct FileInfoBlock)); return (TRUE); } /* Build Header line (will be used with printf) */ loc = 0; for (t=LM;t;t--) header[loc++] = ' '; strcpy (&header[loc], "Page %-4d"); loc += 9; for (t=RM-loc-strlen(info->fib_FileName);t;t--) header[loc++] = ' '; strcpy (&header[loc],info->fib_FileName); loc += strlen(info->fib_FileName); header[loc++] = '\n'; header[loc] = '\0'; /* Initalize header printer, then force header printing */ Header (0); Header (LINES+2); UnLock(lock); FreeMem(info, sizeof(struct FileInfoBlock)); return (FALSE); } /*************************************************************** * BOTTOM * Display size information at bott om of directory. ***************************************************************/ void Bottom (depth,size,found) int depth; long size; BOOL found; { if (prtsize) { Indent (depth*PERSUB+INFOIND+LM); printf ("Total size %ld bytes.\n", size); if (found) printf ("\n"); Header (2); } } /*************************************************************** * DISPLAY * Display information from the DESC file in the directory. ***************************************************************/ BOOL Display (depth,dirname) int depth; char *dirname; { FILE *desc; /* DESCription file info */ BOOL found; /* Found a description file */ int lineloc; /* Location on the output line */ int wordlen; /* Length of word in the buffer */ char wordstore[RM+10]; /* Storage for current word */ BOOL Cont; /* & encountered, ignore return */ BOOL Long; /* Long line/word just printed */ char ch; /* Character from file */ int t,lm; /* temp */ /* Print directory name */ Header (2); Indent (depth*PERSUB+LM); printf ("%s\n", dirname); /* Add DESC filename to path, attempt to open the file */ t = strlen(path); AddName (DESC,t); found = ((desc=fopen(path,"r"))!=0); /* If found, justify the file on the way out */ if (found) { lm = depth*PERSUB+INFOIND+LM; lineloc = lm; Indent (lm); wordlen = 0; Cont = FALSE; Long = FALSE; /* Process one character at a time */ while ((ch=getc(desc))!=EOF) { /* Ignore return if proceded by a & */ if ((ch=='\n') && Cont) { Cont = FALSE; continue; } if (Cont) { /* & not proceded by a return */ wordstore[wordlen++] = '&'; Cont = FALSE; } /* Dump out the current word */ if (ch==' ' || ch=='\n') { wordstore[wordlen] = '\0'; printf ("%s ",wordstore); lineloc += wordlen + 1; wordlen = 0; if (Long || ch=='\n') { putchar ('\n'); Header(1); Indent (lm); lineloc = lm; Long = FALSE; } continue; } /* Force return if line goes over right margin */ if (((wordlen+lineloc)>RM) || (wordlen>(RM-lm))) { if (wordlen>(RM-lm)) { wordstore[wordlen] = '\0'; printf ("%s",wordstore); wordlen = 0; Long = TRUE; } putchar ('\n'); Header(1); Indent (lm); lineloc = lm; } /* Check for continuation character */ if (ch=='&') Cont = TRUE; else wordstore[wordlen++] = ch; } fclose (desc); /* Dump out any remaining word in the buffer */ if (wordlen) { wordstore[wordlen] = '\0'; puts (wordstore); putchar ('\n'); Header (1); lineloc=0; } if (lineloc>lm) putchar('\n'); putchar('\n'); } /* Restore path, return status if file was found */ path[t] = '\0'; return (found); } /************************************************************* * PROCESS * * Find the size of a directory tree by adding the sizes * of all files in the directory and all of its subdirectories. * * General directory searching concept taken from TSIZE * utility by the Software Distillery. ************************************************************/ long Process(len,depth) int len; /* Length of path name */ int depth; /* Number of directories down */ { struct FileInfoBlock *info = NULL; /* pointer to file info */ struct Sortem *sort_top = NULL; /* top of sort list */ struct Sortem *sort_cur = NULL; /* current sort list loc */ struct Sortem *sort_tmp = NULL; /* current sort temp loc */ struct Sortem *sort_last= NULL; /* last sort temp loc */ long size = 0; /* running total of file size */ BPTR lock; /* pointer to file lock */ BOOL found; /* found DESC file */ /* Try to obtain lock on current directory */ if (!(lock = Lock(path, ACCESS_READ))) { printf ("Invalid directory, '%s'.\n", path); goto EXIT; } /* Allocate an info block (must be longword alligned) */ if (!(info = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock), 0))) { printf ("Out of memory.\n"); goto EXIT; } /* Get information on file or directory associated with lock */ if (!Examine(lock, info)) { printf ("Error examining locked directory.\n"); goto EXIT; } /* This should not happen, but... */ if (info->fib_DirEntryType <= 0) { printf ("Locked a file, not directory.\n"); goto EXIT; } /* Display top of directory header */ found = Display (depth,info->fib_FileName); /* Read this directory */ while (ExNext(lock, info)) { /* This is a directory */ if (info->fib_DirEntryType > 0) { /* sub-directory, allocate sortem node */ if (!(sort_cur = (struct Sortem *) AllocMem(sizeof(struct Sortem), 0))) { printf ("Out of memory.\n"); break; } strcpy(sort_cur->FileName,info->fib_FileName); sort_cur->Next = NULL; /* Alphabetical insertion sort */ /* Find insertion location for new node */ for (sort_tmp = sort_top; sort_tmp; sort_tmp = sort_tmp->Next) { if (filecmp(sort_tmp->FileName,info->fib_FileName)>0) break; sort_last = sort_tmp; } /* Insert the node */ if (sort_tmp==sort_top) { sort_cur->Next = sort_top; sort_top = sort_cur; } else if (!sort_tmp) { sort_cur->Next = NULL; sort_last->Next = sort_cur; } else { sort_cur->Next = sort_last->Next; sort_last->Next = sort_cur; } sort_cur = NULL; } else /* found a file, just add size */ size += info->fib_Size; } /* Transverse sorted list, process then deallocate the node */ for (sort_tmp = sort_top; sort_tmp; sort_tmp = sort_last) { size += Process(AddName(sort_tmp->FileName, len),depth+1); sort_last = sort_tmp->Next; FreeMem(sort_tmp, sizeof(struct Sortem)); } /* Repair path */ path[len] = '\0'; /* Print bottom of directory information */ Bottom (depth, size, found); EXIT: if (info) FreeMem(info, sizeof(struct FileInfoBlock)); if (lock) UnLock(lock); return(size); } /*************************************************************** * MAIN ***************************************************************/ main(argc, argv) int argc; char *argv[]; { int len; /* Length of file name given on command line */ int t; /* Temp variable */ /* Help information */ if (argv[1][0]=='?') { printf ("%s\nUseage: %s [Read-Path] [-size]\n", VERSION, argv[0]); exit (0); } /* parse command line (len used as temp param counter) */ for (len=1;len1) len = AddName(argv[1], 0); else len = AddName(":", 0); /* Check root info, exit if invalid */ if (Root()) return(20); /* Process root directory */ (void)Process(len,0); EXIT: return(0); }