home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / diskutil / du.c < prev    next >
C/C++ Source or Header  |  1994-03-04  |  7KB  |  394 lines

  1. /*
  2.  * du.c:
  3.  *
  4.  * `Du' is a disk usage utility which computes the diskusage of
  5.  * all the files in a directory and it's subdirectories.
  6.  *
  7.  * This utility is comparable with the UNIX du program.
  8.  *
  9.  * Usage: du [-s] [-a] [d:path ...]
  10.  *
  11.  * Option -s (/s) does not show subdirectories (short listing).
  12.  * Option -a (/a) shows size of all the files.
  13.  *
  14.  * Copyright: Tom Vijlbrief, Baarn, The Netherlands
  15.  * Date:      Fri May  8 13:53:29 GMT+1:00 1987
  16.  *
  17.  * This program may be distributed freely for non commercial purposes
  18.  * and with this Copyright notice unchanged.
  19.  */
  20.  
  21. /*
  22.  * Compilation must be performed with structure packing and larger stack:
  23.  * Microsoft C 4.00: -Zp -F2000
  24.  */
  25.  
  26. #include    <stdio.h>
  27. #include    <string.h>
  28. #include    <dos.h>
  29. #include    <io.h>
  30. #include    <direct.h>
  31. #include    <sys/types.h>
  32. #include    <sys/stat.h>
  33. #include    <ctype.h>
  34.  
  35. #define        BLOCK_SIZE    512
  36. #define        ALL_FILES    (0x1 | 0x2 | 0x4 | 0x10 |0x20)
  37. #define        DIRECTORIES    (0x10)
  38.  
  39. #define        NAME_LEN    8
  40. #define        EXT_LEN        3
  41.  
  42. #define        MAX_CWD        256
  43.  
  44. typedef unsigned char    byte;
  45.  
  46. typedef struct {
  47.     byte        FF;
  48.     byte        zero_5[5];
  49.     byte        attribute;
  50.     byte        drive;
  51.     char        name[NAME_LEN];
  52.     char        extension[EXT_LEN];
  53.     unsigned    cur_block;
  54.     unsigned    rec_size;
  55.     unsigned    fs_low;
  56.     unsigned    fs_high;
  57.     unsigned    date;
  58.     byte        unused2[10];
  59.     byte        cur_record;
  60.     unsigned    ran_low;
  61.     unsigned    ran_high;
  62. } ext_fcb;
  63.  
  64. char    *get_first(char *, int, ext_fcb *);
  65. char    *get_next(ext_fcb *);
  66. long    scan();
  67.  
  68.  
  69. byte    sector[BLOCK_SIZE];
  70.  
  71. int    cluster_size;
  72.  
  73. int    a_flag;
  74. int    s_flag;
  75. int    in_tree;
  76.  
  77. ext_fcb    return_fcb;
  78.  
  79. main(argc, argv)
  80.  
  81. int    argc;
  82. char    *argv[];
  83. {
  84.   char        *option_p;
  85.   static char    cur_cwd[MAX_CWD];
  86.   int        drive_nr;
  87.   int        cur_drive;
  88.  
  89.   while (argc > 1) {
  90.     option_p= *++argv;
  91.  
  92.     if (*option_p == '-' || *option_p == '/') {
  93.         for (option_p++; *option_p; option_p++) {
  94.             switch (*option_p) {
  95.             case 'a':
  96.                 a_flag++;
  97.                 break;
  98.             case 's':
  99.                 s_flag++;
  100.                 break;
  101.             default:
  102.                 fprintf(stderr,
  103.                     "Unknown option: %c\n", *option_p);
  104.                 fprintf(stderr,
  105.                     "Usage: du [-s] [-a] [d:path ...]\n");
  106.                 exit(1);
  107.             }
  108.         }
  109.         argc--;
  110.     } else
  111.         break;
  112.   }
  113.  
  114.   if (argc == 1) {
  115.     cluster_size= comp_cluster(get_drive());
  116.     scan();
  117.   } else {
  118.     for (; argc > 1; argc--, argv++) {
  119.         cur_drive= get_drive();
  120.         getcwd(cur_cwd, MAX_CWD - 1);
  121.         if ((*argv)[1] == ':')
  122.             set_drive(tolower((*argv)[0]) - 'a');
  123.         if (chdir(*argv) != 0) {
  124.             perror(*argv);
  125.             set_drive(cur_drive);
  126.             continue;
  127.         }
  128.         cluster_size= comp_cluster(get_drive());
  129.         scan();
  130.         set_drive(cur_drive);
  131.         if (chdir(cur_cwd) != 0) {
  132.             perror(cur_cwd);
  133.             exit(1);
  134.         }
  135.  
  136.         in_tree= 0;
  137.     }
  138.   }
  139. }
  140.  
  141.  
  142. static struct stat    the_stat;
  143. static char        cwd[MAX_CWD];
  144.  
  145. long scan()
  146. {
  147.   char        *p;
  148.   long        file_size;
  149.   long        disk_use;
  150.   int        tree_flag;
  151.   ext_fcb    the_fcb;
  152.   char        pattern[NAME_LEN + EXT_LEN + 2];
  153.  
  154.   tree_flag= in_tree;
  155.   disk_use= 0;
  156.  
  157.   strcpy(pattern, "????????.???");
  158.  
  159.   p= get_first(pattern, ALL_FILES, &the_fcb);
  160.   for (; p != NULL; p= get_next(&the_fcb)) {
  161.     if (strcmp(p, "..      .   ") == 0
  162.        || strcmp(p, ".       .   ") == 0)
  163.         continue;
  164.  
  165.     if (stat(p, &the_stat) != 0) {
  166.         perror(p);
  167.         exit(1);
  168.     }
  169.  
  170.     if (the_stat.st_mode & S_IFDIR) {
  171.         if (a_flag) {
  172.             printf("%s\n", p);
  173.             printf("========================\n");
  174.         }
  175.         chdir(p);
  176.         in_tree= 1;
  177.         disk_use+= scan();
  178.         chdir("..");
  179.     } else {
  180.         disk_use+= ((file_size= the_stat.st_size) + (cluster_size - 1))
  181.             / cluster_size * cluster_size;
  182.         if (a_flag) {
  183.             printf("%s: %10ld\n", p, file_size);
  184.         }
  185.     }
  186.   }
  187.  
  188.   if (a_flag)
  189.       printf("========================\n");
  190.   if (!s_flag || !tree_flag)
  191.       printf("Disk Usage  : %10ld (%s)\n", disk_use,
  192.         getcwd(cwd, MAX_CWD - 1));
  193.   if (a_flag)
  194.       printf("\n");
  195.  
  196.   return(disk_use);
  197. }
  198.  
  199.  
  200. /*
  201.  * get_first returns the first_name in a directory matching the
  202.  * pattern (e.g. ????????.OBJ) and attribute
  203.  */
  204.  
  205. char *get_first (pattern, attribute, fcb_p)
  206.  
  207. char    *pattern;
  208. int    attribute;
  209. ext_fcb    *fcb_p;
  210. {
  211.   set_dta(&return_fcb);
  212.  
  213.   strncpy(fcb_p->name, pattern, NAME_LEN);
  214.   strncpy(fcb_p->extension, pattern + NAME_LEN + 1, EXT_LEN);
  215.   fcb_p->attribute= attribute;
  216.   fcb_p->FF= 0xFF;
  217.   fcb_p->drive= get_drive() + 1;
  218.  
  219.   if ((bdos(0x11, (int) fcb_p, 0) & 0xFF) == 0) {
  220.     strncpy(pattern, return_fcb.name, NAME_LEN);
  221.     strncpy(pattern + NAME_LEN + 1, return_fcb.extension, EXT_LEN);
  222.     return(pattern);
  223.   } else
  224.     return(NULL);
  225. }
  226.  
  227.  
  228. char *get_next(fcb_p)
  229.  
  230. ext_fcb    *fcb_p;
  231. {
  232.   static char    pattern[]= "12345678.123";
  233.  
  234.   set_dta(&return_fcb);
  235.  
  236.   if ((bdos(0x12,  (int) fcb_p, 0) & 0xFF) == 0) {
  237.     strncpy(pattern, return_fcb.name, NAME_LEN);
  238.     strncpy(pattern + NAME_LEN + 1, return_fcb.extension, EXT_LEN);
  239.     pattern[NAME_LEN + EXT_LEN + 1]= '\0';
  240.     return(pattern);
  241.   } else {
  242.     return(NULL);
  243.   }
  244. }
  245.  
  246.  
  247. /*
  248.  * `set_drive' changes the current drive. (A = 0, etc).
  249.  */
  250. int set_drive(drive_nr)
  251.  
  252. int    drive_nr;
  253. {
  254.   return(bdos(0xE, drive_nr, 0) & 0xFF);
  255. }
  256.  
  257. /*
  258.  * `get_drive' returns the number of the current drive. (A = 0, etc).
  259.  */
  260. int get_drive()
  261.  
  262. {
  263.   return(bdos(0x19, 0, 0) & 0xFF);
  264. }
  265.  
  266.  
  267.  
  268. set_dta(p)
  269.  
  270. ext_fcb    *p;
  271. {
  272.   return(bdos(0x1A, (int) p, 0) & 0xFF);
  273. }
  274.  
  275.  
  276.  
  277. #define        DISK        0x13
  278. #define        READ_SECT    0x2
  279. #define        RESET_DISK    0x0
  280.  
  281. #define        FLOP_RETRIES    3
  282.  
  283. int readsect(buffer, drive, head, cyl, sector, n_sectors)
  284.  
  285. char        *buffer;
  286. unsigned int    drive;
  287. unsigned int    head;
  288. unsigned int    cyl;
  289. unsigned int    sector;
  290. unsigned int    n_sectors;
  291. {
  292.   int        result;
  293.   int        retries;
  294.   int        max_retries;
  295.   union REGS    inregs,
  296.         outregs;
  297.   struct SREGS    segregs;
  298.  
  299.   segread(&segregs);
  300.   segregs.es= segregs.ds;
  301.  
  302.   if (drive < 0x80)
  303.     max_retries= FLOP_RETRIES;
  304.   else
  305.     max_retries= 1;
  306.  
  307.   for (retries= 0; retries < max_retries; retries++) {
  308.     if (drive < 0x80) {
  309.         inregs.h.ah= RESET_DISK;
  310.         inregs.h.dl= drive;
  311.         int86(DISK, &inregs, &outregs);
  312.     }
  313.  
  314.     inregs.h.ah= READ_SECT;
  315.     inregs.x.bx= (unsigned) buffer;
  316.     inregs.h.dl= drive;
  317.     inregs.h.dh= head;
  318.     inregs.h.ch= cyl;
  319.     inregs.h.cl= sector | ((cyl & ~0xFF) >> 2);
  320.     inregs.h.al= n_sectors;
  321.  
  322.     result= (unsigned) int86x(DISK, &inregs, &outregs, &segregs) >> 8;
  323.  
  324.     if (outregs.x.cflag)
  325.         continue;
  326.     else
  327.         break;
  328.   }
  329.   if (retries == max_retries)
  330.     return(-result);
  331.   else
  332.     return(0);
  333. }
  334.  
  335.  
  336.  
  337. int comp_cluster(drive_nr)
  338.  
  339. int    drive_nr;
  340. {
  341.   int    nr_sectors;
  342.   int    head_nr;
  343.   int    high_head;
  344.   int    sector_nr;
  345.  
  346.   if (drive_nr > 1)
  347.     drive_nr+= 0x80 - 2;
  348.  
  349.   high_head= max_head(drive_nr);
  350.  
  351.   for (head_nr= 0; head_nr <= high_head; head_nr++) {
  352.     for (sector_nr= 1; sector_nr <= 8; sector_nr++) {
  353.     if (readsect(sector, drive_nr, head_nr, 0, sector_nr, 1) != 0) {
  354.         fprintf(stderr, "Cannot read bootblock from disk\n");
  355.         exit(1);
  356.     }
  357.     if (sector[0] == 0xEB)
  358.         break;
  359.     }
  360.     if (sector[0] == 0xEB)
  361.     break;
  362.   }
  363.   if (sector_nr > 8 || (nr_sectors= sector[13]) > 16) {
  364.     nr_sectors= 4;
  365.     fprintf(stderr,
  366.         "Unknown bootblock, clustersize of 4 sectors assumed\n");
  367.   }
  368.   if (nr_sectors == 0)
  369.     nr_sectors= 2;
  370.   return(nr_sectors * BLOCK_SIZE);
  371. }
  372.  
  373.  
  374.  
  375. #define        GET_PARAM    0x8
  376.  
  377. int max_head(drive)
  378.  
  379. unsigned int    drive;
  380. {
  381.   union REGS    inregs,
  382.         outregs;
  383.  
  384.   inregs.h.ah= GET_PARAM;
  385.   inregs.h.dl= drive;
  386.  
  387.   int86(DISK, &inregs, &outregs);
  388.  
  389.   if (outregs.x.cflag)
  390.     return(0);
  391.   else
  392.     return(outregs.h.dh);
  393. }
  394.