home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d0xx / d035 / tsize.lha / Tsize / tsize.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-09-09  |  8.4 KB  |  252 lines

  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  2. /* |_o_o|\\ Copyright (c) 1986 The Software Distillery.  All Rights Reserved */
  3. /* |. o.| || This program may not be distributed without the permission of   */
  4. /* | .  | || the authors.                                                    */
  5. /* | o  | ||    Dave Baker     Ed Burnette  Stan Chow    Jay Denebeim        */
  6. /* |  . |//     Gordon Keener  Jack Rouse   John Toebes  Doug Walker         */
  7. /* ======          BBS:(919)-471-6436      VOICE:(919)-469-4210              */ 
  8. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  9.  
  10. /*--------------------------------------------------------------------------+
  11.  | program:   tsize
  12.  | purpose:   Find the size of a directory tree by adding the sizes
  13.  |            of all files in the directory and all of its
  14.  |            subdirectories.
  15.  | author:    Edmund Burnette
  16.  | usage:     tsize              -- find size of current directory
  17.  |            tsize <name>       -- find size of named file or directory
  18.  | history:   16apr86/ebb - version 1.0 created
  19.  |            10jul86/ebb - added break handler, tsize of single file
  20.  |            12jul86/ebb - changed break handling
  21.  | notes:     1. When given a file, this program just returns the size of
  22.  |               that file.
  23.  +-------------------------------------------------------------------------*/
  24.  
  25. #include <libraries/dosextens.h>
  26.  
  27. char copyright[] =
  28. "TSIZE v1.2 by Edmund Burnette - Copyright © 1986 The Software Distillery";
  29.  
  30. #define ERREXITRC(arcee) { rc = arcee; goto EXIT; }
  31. #define ERREXIT goto EXIT;
  32. #define ERRORRC(arcee, errmsg) { rc = arcee; printf errmsg; goto EXIT; }
  33. #define ERROR(errmsg) { printf errmsg; goto EXIT; }
  34.  
  35. #define CTOB(cptr) ((BPTR)((unsigned long)(cptr) >> 2))
  36. #define BTOC(bptr) ((char *)((unsigned long)(bptr) << 2))
  37.  
  38. /* exit codes */
  39. #define TOO_MANY_NAMES 50    /* more than one file or directory specified  */
  40.  
  41. BPTR stdout;
  42. char path[256];
  43. char empty[]    = "";
  44.  
  45. BPTR Output();
  46. int checkbreak();
  47. long tsize(int, int);
  48. int addname(char *, int);
  49. int parse(int, char *[], int *);
  50.  
  51. main(argc, argv)
  52. int argc;
  53. char *argv[];
  54.    {
  55.    int rc = 0;               /* return code                                */
  56.    int len;                  /* length of file name given on command line  */
  57.  
  58.    /* initialize standard out */
  59.    stdout = Output();
  60.  
  61.    /* parse command line */
  62.    if (rc = parse(argc, argv, &len)) ERREXIT
  63.  
  64.    /* print tree size information */
  65.    (void)tsize(len, TRUE);
  66.  
  67. EXIT:
  68.    return(rc);
  69.    }
  70.  
  71. /*--------------------------------------------------------------------------+
  72.  | name:      checkbreak
  73.  | purpose:   Check for CTRL-C / CTRL-D brek
  74.  | history:   12jul86/ebb - created
  75.  | usage:     rc = checkbreak();
  76.  |            int rc;                   flag="break detected"
  77.  | notes:     1. Sets global abort flag.
  78.  *-------------------------------------------------------------------------*/
  79.  
  80. #define SIGS (SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D)
  81.  
  82. int checkbreak()
  83.    {
  84.    static int abort = FALSE;
  85.  
  86.    /* print message and set abort flag if break occurred */
  87.    if (!abort && (SetSignal(0,SIGS) & SIGS))
  88.       {
  89.       printf("**BREAK\n");
  90.       abort = TRUE;
  91.       }
  92.  
  93.    /* return break detected flag */
  94.    return abort;
  95.    }
  96.  
  97. /*--------------------------------------------------------------------------+
  98.  | name:      tsize
  99.  | purpose:   Find the size of a directory tree by adding the sizes
  100.  |            of all files in the directory and all of its
  101.  |            subdirectories.
  102.  | usage:     size = tsize(len, prtsize)
  103.  |            long size;         returned size of tree
  104.  |            int len;           length of path name
  105.  |            int prtsize;       flag to print size of tree even if file
  106.  | history:   16apr86/ebb - created
  107.  |            10jul86/ebb - handle printing size of single file
  108.  |            12jul86/ebb - changed break handling
  109.  | notes:     1. Uses the path name stored in an external variable to
  110.  |               save stack space.
  111.  |            2. 
  112.  | future:    
  113.  +-------------------------------------------------------------------------*/
  114.  
  115. long tsize(len, prtsize)
  116. int len;
  117. int prtsize;
  118.    {
  119.    struct FileInfoBlock *info = NULL;  /* pointer to file info             */
  120.    long size = 0;                      /* running total of file size       */
  121.    BPTR lock;                          /* pointer to file lock             */
  122.  
  123.    BPTR Lock();
  124.    BOOL Examine();
  125.    BOOL ExNext();
  126.  
  127.    /* try to obtain lock on current file */
  128.    if ((lock = Lock(path, ACCESS_READ)) == NULL)
  129.       ERROR(("Invalid file or directory, '%s'.\n", path))
  130.  
  131.    /* allocate an info block (must be longword alligned) */
  132.    if ((info = (struct FileInfoBlock *)
  133.                AllocMem(sizeof(struct FileInfoBlock), 0)) == NULL)
  134.       ERROR(("Out of memory.\n"))
  135.  
  136.    /* get information on file or directory associated with lock */
  137.    if (!Examine(lock, info))
  138.       ERROR(("Error examining locked file or directory.\n"))
  139.  
  140.    /* what have we here... */
  141.    if (info->fib_DirEntryType > 0)
  142.       {
  143.       /* lock is for a directory */
  144.       while (ExNext(lock, info) && !checkbreak())
  145.          size += tsize(addname(info->fib_FileName, len), FALSE);
  146.       prtsize = TRUE;
  147.       }
  148.    else if (info->fib_DirEntryType < 0)
  149.       /* lock is for a file */
  150.       size = info->fib_Size;
  151.    else
  152.       /* invalid entry type */
  153.       ERROR(("Invalid directory entry type of 0 for '%s'.\n", path))
  154.  
  155.    /* repair path and print statistics */
  156.    if (prtsize && !checkbreak())
  157.       {
  158.       path[len] = '\0';
  159.       printf("%s %ld\n", path, size);
  160.       }
  161.    
  162. EXIT:
  163.    if (info) FreeMem(info, sizeof(struct FileInfoBlock));
  164.    if (lock) UnLock(lock);
  165.    return(size);
  166.    }
  167.  
  168. /*--------------------------------------------------------------------------+
  169.  | name:      parse
  170.  | purpose:   Recognize a file name or directory in the argument list.
  171.  | usage:     rc = parse(argc, argv, len);
  172.  |            int rc;            return code (0: ok, non-0: failed)
  173.  |            int argc;          number of arguments
  174.  |            char *argv[];      argument vector
  175.  |            int len;           length of file or directory name
  176.  | history:   16apr86/ebb - created
  177.  | notes:     1. Stores the file or directory name in the external
  178.  |               variable 'path' (null terminated).
  179.  |            2. 
  180.  | future:    
  181.  +-------------------------------------------------------------------------*/
  182.  
  183. int parse(argc, argv, len)
  184. int argc;
  185. char *argv[];
  186. int *len;
  187.    {
  188.    int rc = 0;               /* return code                                */
  189.    int i;                    /* argument index                             */
  190.    int found = 0;            /* flag="name found on argument list"         */
  191.    register char *arg;       /* pointer to current argument                */
  192.  
  193.    /* process all arguments */
  194.    for (i = 1; i < argc; i++)
  195.       {
  196.       arg = argv[i];
  197.       /* check for name already specified */
  198.       if (found)
  199.          /* attempt to give more than one directory */
  200.          ERRORRC(TOO_MANY_NAMES,
  201.                  ("More than one file or directory specified.\n"))
  202.       else
  203.          {
  204.          /* set name */
  205.          found = 1;
  206.          *len = addname(arg, 0);
  207.          }
  208.       } /* for */
  209.  
  210.    /* use current directory if no file or directory specified */
  211.    if (!found)
  212.       *len = addname(empty, 0);
  213.  
  214. EXIT:
  215.    return rc;
  216.    }
  217.  
  218. /*--------------------------------------------------------------------------+
  219.  | name:      addname
  220.  | purpose:   Add a name to the end of the current path.
  221.  | usage:     newlen = addname(name, len);
  222.  |            int newlen;        returned new length of resulting path
  223.  |            char *name;        null terminated name to add
  224.  |            int len;           length of current path
  225.  | history:   16apr86/ebb - created
  226.  | notes:     1. Modifies the external variable 'path'.
  227.  |            2. 
  228.  | future:    
  229.  +-------------------------------------------------------------------------*/
  230.  
  231. int addname(name, len)
  232. register char *name;
  233. int len;
  234.    {
  235.    register char *p = path + len;  /* current position in path             */
  236.    register int i = 0;             /* added length counter                 */
  237.    char ch;                        /* last character of current path       */
  238.  
  239.    /* add a slash between path and name if legal */
  240.    if (len != 0 && (ch = path[len-1]) != '/' && ch != ':')
  241.       {
  242.       *p++ = '/';
  243.       ++i;
  244.       }
  245.  
  246.    /* copy name to end of path (including null terminator) */
  247.    for (;*p++ = *name++; ++i) /* nothing */ ;
  248.  
  249.    /* return new length of path */
  250.    return len + i;
  251.    }
  252.