/* Created using Turbo C - Copyright (C) Borland 1987,1988 */ /*------------------------------------------------------------------------- DS - Directory Size. Written by Aaron Bredon. Version 4.5 This program reports the amount of space taken up by a directory's files (including subdirectories). It will not include the space taken up by the directory itself. It could be off by a couple of clusters from what CHKDSK reports (total of hidden,directories, & files). I think this is caused by unused blocks being marked used in the FAT. Usage: ds [-abcdfhinoprsxz | q[nn] | l[nnnn] ... ] [pathname ] where: -a : Show files in directory (Toggle - default:OFF) -b : Show attribute instead of time (Toggle - default:OFF) -c : Show sizes in clusters (Toggle - default:OFF) -d : Split screen (Toggle - default:OFF) -f : Base on file size, not disk space (Toggle - default:OFF) -h : Count Hidden and System files (Toggle - default:ON) -i : Include space occupied by subdirectories (Toggle - default:ON) -lnnnn : Force cluster size to be nnnn bytes. nnnn = 0 uses actual cluster size. -n : Show full pathname (Toggle - default:OFF) -o : Show path & size only (Toggle - default:OFF) -p : Paged listing (Toggle - default:OFF) -qnn : use nn lines per page before pausing. (default:25) -r : Recursive calls for subdirectory size (Toggle - default:ON) -s : Summary information only (Toggle - default:ON) -x : Show info on current directory (Toggle - default:OFF) -z : Show total statistics (Toggle - default:ON) The default pathname is the current directory on the current drive. --------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #define MAXDIRS 10 void parspath(char * path); /* takes a pathname and changes it to a full pathname */ int EGA; int maxlines_printed; int xx; /* debugging var*/ char copmes[] = "Created using Turbo C - Copyright (C) Borland 1987,1988"; char drive[MAXDRIVE], dir[MAXDIR], filename[MAXFILE], ext[MAXEXT]; char mask[(MAXFILE+MAXEXT)]; unsigned char udrive = 0; int dir_specified = 0, show_sub = 0, /* flags for options */ show_files = 0, traverse_sub = 1, total_stats = 1, show_cluster = 0, show_hidden = 1, force_cluster = 0, file_size = 0, curr_dir = 0, split_screen = 0, paged_list = 0, dir_space = 1, show_attrib = 0, show_path = 0, path_only = 0; int cluster_size = 0; int first_column = 1; /* toggle for split-screen */ int lines_printed = 0; /* count for paged listing */ struct dfree dinfo; /* used by getdfree */ char searchdir[81], buf[81]; /* used by main & process_dir */ char temparg[MAXDIRS][81]; union fdte{ struct { unsigned dy:5; unsigned mn:4; unsigned yr:7; }fd; unsigned us; }; union ftme{ struct { unsigned :5; unsigned mn:6; unsigned hr:5; }ft; unsigned us; }; void usage(void) /* produces usage output */ { printf("DS - Directory Size - Version 4.5\n"); printf("Usage: ds [-abcdfhinoprsxz | q[nn] | l[nnnn] ... ] [pathname ]\n"); printf(" where:\n"); printf(" -a : Show files in directory (Toggle - default:OFF)\n"); printf(" -b : Show attribute instead of time (Toggle - default:OFF)\n"); printf(" -c : Show sizes in clusters (Toggle - default:OFF)\n"); printf(" -d : Split screen (Toggle - default:OFF)\n"); printf(" -f : Base on file size, not disk space (Toggle - default:OFF)\n"); printf(" -h : Count Hidden and System files (Toggle - default:ON)\n"); printf(" -i : Include space occupied by subdirectories (Toggle - default:ON)\n"); printf(" -lnnnn : Force cluster size to be nnnn bytes.\n"); printf(" nnnn = 0 uses actual cluster size.\n"); printf(" -n : Show full pathname (Toggle - default:OFF)\n"); printf(" -o : Show path & size only (Toggle - default:OFF)\n"); printf(" -p : Paged listing (Toggle - default:OFF)\n"); printf(" -qnn : use nn lines per page before pausing. (default:25)\n"); printf(" -r : Recursive calls for subdirectory size (Toggle - default:ON)\n"); printf(" -s : Summary information only (Toggle - default:ON)\n"); printf(" -x : Show info on current directory (Toggle - default:OFF)\n"); printf(" -z : Show total statistics (Toggle - default:ON)\n"); printf("The default pathname is the current directory on the current drive.\n"); printf(" NOTE: This program is very occasionally not quite 100% accurate.\n"); } void path_only_output(struct ffblk * data1,long int number,char * path1) { char num[20]=""; char oldnum[20]=""; register int x; char dc; char tempstr[81]; dc=((data1->ff_attrib)&FA_DIREC)?'\\':' '; ltoa( number, oldnum, 10 ); /* get number as a string */ x = ( strlen(oldnum) % 3 ); /* find # of digits in first group */ if (x == 0) x = 3; strncpy(num, oldnum, x); /* move first group */ while ( x < strlen(oldnum) ) /* move rest of number */ { strcat(num,","); /* add comma */ strncat(num, oldnum+x, 3); /* move next group */ x+=3; /* update x */ } strcpy(tempstr,path1); strcat(tempstr,data1->ff_name); printf("%15s %-21s%c",num,tempstr,dc); if ( split_screen && first_column ) /* handle split-screen output */ { printf("³"); first_column = 0; } else { printf("\n"); lines_printed++; if ( paged_list && ( lines_printed > (maxlines_printed-3) ) ) { /* handle paged listing */ register int i; printf("%62s","========== hit any key to continue =========="); getch(); /* wait for key */ for(i=0;i<62;i++) printf("\b \b"); lines_printed = 0; /* reset counter */ } first_column = 1; } } void normal_output(struct ffblk * data1,long int number) /* xchar is used to identify dir's */ { /* outputs info with commas */ char * extbeg; char num[20]=""; /* number with commas */ char oldnum[20]=""; /* number without commas */ register int x; /* # digits written */ int namelen; char dc; char tc; union ftme ft; union fdte fd; int day,mon,yr,hour,min; fd.us=data1->ff_fdate; ft.us=data1->ff_ftime; day=fd.fd.dy; mon=fd.fd.mn; yr=fd.fd.yr+80; while (yr>99) yr-=100; hour=(ft.ft.hr)%12; if (hour==0) hour=12; tc=((ft.ft.hr)/12)?'p':'a'; min=ft.ft.mn; extbeg=strchr(data1->ff_name,'.')+1; namelen=(extbeg-data1->ff_name)-1; if (namelen>9) { extbeg=data1->ff_name+strlen(data1->ff_name); namelen=(extbeg-data1->ff_name); } dc=((data1->ff_attrib)&FA_DIREC)?'\\':' '; ltoa( number, oldnum, 10 ); /* get number as a string */ x = ( strlen(oldnum) % 3 ); /* find # of digits in first group */ if (x == 0) x = 3; strncpy(num, oldnum, x); /* move first group */ while ( x < strlen(oldnum) ) /* move rest of number */ { strcat(num,","); /* add comma */ strncat(num, oldnum+x, 3); /* move next group */ x+=3; /* update x */ } printf("%-8.*s.%-3.3s%c",namelen,data1->ff_name,extbeg,dc); printf("%10s",num); printf(" %2d-%02d-%02d",mon,day,yr); if (show_attrib) { printf(" %c%c%c%c%c%c", data1->ff_attrib&FA_RDONLY?'R':'-', data1->ff_attrib&FA_HIDDEN?'H':'-', data1->ff_attrib&FA_SYSTEM?'S':'-', data1->ff_attrib&FA_LABEL?'L':'-', data1->ff_attrib&FA_DIREC?'D':'-', data1->ff_attrib&FA_ARCH?'A':'-'); } else { printf(" %2d:%02d%c",hour,min,tc); } if ( split_screen && first_column ) /* handle split-screen output */ { printf("³"); first_column = 0; } else { printf("\n"); lines_printed++; if ( paged_list && ( lines_printed > (maxlines_printed-3) ) ) { /* handle paged listing */ register int i; printf("%62s","========== hit any key to continue =========="); getch(); /* wait for key */ for(i=0;i<62;i++) printf("\b \b"); lines_printed = 0; /* reset counter */ } first_column = 1; } } void totals_output(char * name,long int number) { /* outputs info with commas */ char num[20]=""; /* number with commas */ char oldnum[20]=""; /* number without commas */ register int x; /* # digits written */ if ( paged_list && ( (maxlines_printed-lines_printed)<2) ) { /* handle paged listing */ register int i; printf("%62s","========== hit any key to continue =========="); getch(); /* wait for key */ for(i=0;i<62;i++) printf("\b \b"); lines_printed = 0; /* reset counter */ } ltoa( number, oldnum, 10 ); /* get number as a string */ x = ( strlen(oldnum) % 3 ); /* find # of digits in first group */ if (x == 0) x = 3; strncpy(num, oldnum, x); /* move first group */ while ( x < strlen(oldnum) ) /* move rest of number */ { strcat(num,","); /* add comma */ strncat(num, oldnum+x, 3); /* move next group */ x+=3; /* update x */ } printf("%s %11s\n",name,num); } long int size(long int bytes) { /* computes output size of file */ long int i; long int j; /* used in calculations */ if ( !show_cluster && file_size ) /* show file size, not disk space */ return(bytes); i = bytes / cluster_size; /* # of full clusters */ j = bytes % cluster_size; /* possible partial cluster */ if ( j ) i++; /* partial cluster */ if( !show_cluster ) /* output disk space in bytes */ return(i * cluster_size); return(i); /* output # of clusters */ } long int get_directory_size(char * s_dir,char * mask,int show_curr,int level) { /* gets space occupied by dir. */ long int result = 0; /* disk space */ long int temp = 0; /* used to calculate space */ register int files = 0; /* # of files in directory */ /* used to calculate dir. size */ struct ffblk fileinfo; /* used by findfirst/findnext */ char searchpath[80]; /* used in recursion */ char searchkey[80]; /* used in findfirst */ strcpy(searchkey, s_dir); /* set up search key */ strcat(searchkey, mask); if ( findfirst(searchkey, &fileinfo, 0x3f) != -1 ) { /* find first file matching key */ do { /* calculations until no match */ temp=0; /* file found - size not yet known */ if ( ( fileinfo.ff_attrib & 0x06 ) != 0 ) { /* hidden/system file */ if ( !show_hidden ) { /* hidden/system file. do nothing */ } else { /* process hidden/system files */ temp = size(fileinfo.ff_fsize); if ( show_files && ( show_curr || !curr_dir ) ) { /* show file */ if (show_path) { printf("%-39s³",s_dir); first_column=0; } if (path_only) path_only_output(&fileinfo,temp,s_dir); else normal_output(&fileinfo, temp); } result += temp; /* update size of dir. */ } } else /* normal file/directory */ if ( ( fileinfo.ff_attrib & 0x10 ) == 0 ) { /* file */ temp=size(fileinfo.ff_fsize); if ( show_files && (show_curr || !curr_dir ) ) { if (show_path) { printf("%-39s³",s_dir); first_column=0; } if (path_only) path_only_output(&fileinfo,temp,s_dir); else normal_output(&fileinfo,temp); } else { /* do nothing */ } result+=temp; } else { /* directories are handled further down */ } } while ( findnext(&fileinfo) != -1 ); } /* process directories */ { strcpy(searchkey,s_dir); /* set up search key */ strcat(searchkey,"*.*"); /* match all files to find */ /* directories with matches */ if ( findfirst(searchkey, &fileinfo, 0x3f) != -1 ) { do { /* process until no match */ files++; /* file found */ if ( ( fileinfo.ff_attrib & 0x06 ) != 0 ) { /* hidden/system file. do nothing */ } else if ( ( fileinfo.ff_attrib & 0x08 ) != 0 ) { /* Volume Label - do nothing */ } else if ( ( fileinfo.ff_attrib & 0x10) == 0 ) { /* file - do nothing */ } else /* directory */ if ( strcmp(fileinfo.ff_name, ".") && strcmp(fileinfo.ff_name, "..") ) { /* File is a Directory - compute and add size */ /* Yes, Directories are handled here! */ if ( traverse_sub ) { int flag = show_sub; /* flag becomes show_curr */ strcpy(searchpath, s_dir); /* in recursion */ strcat(searchpath, fileinfo.ff_name); strcat(searchpath, "\\"); temp = get_directory_size(searchpath,mask,flag,2); result += temp; /* update size */ if ( show_sub || show_curr ) { /* print directory */ if (show_path) { printf("%-39s³",s_dir); first_column=0; } if (path_only) path_only_output(&fileinfo,temp,s_dir); else normal_output(&fileinfo,temp); } } } } while ( findnext(&fileinfo) != -1 ); if (dir_space && (level == 2)) { /* calc. size of dir. files */ temp = size(files*32); /* each dir. entry takes 32 bytes */ result += temp; } } return(result); } } void process_option(char * option) { switch ( *option ) { case 'a': /* toggle output of files */ case 'A': /* default - off */ show_files = !show_files; break; case 'b': /* show file attributes instead of */ case 'B': /* file modification time */ show_attrib = !show_attrib; break; case 'c': /* toggle display by */ case 'C': /* # of clusters */ show_cluster = !show_cluster; /* default - off */ break; case 'd': /* toggle split-screen display */ case 'D': /* default - off */ split_screen = !split_screen; break; case 'f': /* toggle use of */ case 'F': /* file size, not disk space */ file_size = !file_size; break; case 'h': /* toggle counting of */ case 'H': /* default - on */ show_hidden = !show_hidden; break; case 'i': /* toggle counting of space */ case 'I': /* taken up by directory file */ dir_space = !dir_space; /* default - on */ break; case 'l': /* force cluster size to */ case 'L': /* specific # of bytes */ force_cluster = 1; cluster_size = atoi(option+1); if ( cluster_size == 0 ) { force_cluster = 0; } break; case 'n': /* show path as well as */ case 'N': /* file information */ show_path = !show_path; break; case 'o': /* show only path, filename */ case 'O': /* and size */ path_only = !path_only; break; case 'p': /* toggle paging of output */ case 'P': /* default - off */ paged_list = !paged_list; break; case 'q': /* set maximum lines per page */ case 'Q': maxlines_printed = atoi(option+1); break; case 'r': /* toggle recursive calls */ case 'R': /* default - on */ traverse_sub = !traverse_sub; break; case 's': /* toggle output of */ case 'S': /* subdirectories */ show_sub = !show_sub; /* default - off */ break; case 'x': /* toggle extended directory */ case 'X': /* default - off */ curr_dir = !curr_dir; /* note: -a -s changed */ show_files = curr_dir; break; case 'z': /* toggle total statistics */ case 'Z': /* default - on */ total_stats = !total_stats; break; default: printf("I don't know option '%c'\n", *option); usage(); exit(1); /* unknown option: Usage & exit */ } } void split_path(char *path) /* splits full path to */ { /* path & mask(file.ext) */ char drive[MAXDRIVE]; char dir[MAXDIR]; char name[MAXFILE]; char ext[MAXEXT]; fnsplit(path,drive,dir,name,ext); udrive=((drive[0]-'A')+1); strcpy(mask,name); strcat(mask,ext); strcpy(path,drive); strcat(path,dir); } void process_dir(char *path) { /* converts path to full path */ register char * cp; strcpy(searchdir, path); while((cp = strchr(searchdir,'/'))!=NULL) *cp = '\\'; /* convert / to \ */ parspath(searchdir); split_path(searchdir); /* get mask */ } void main(int argc, char *argv[]) { long int size; /* directory size */ register int i; register int x=0; /* # directories specified */ _BL=0x10; /* call INT 10, Function 12, */ _AH=0x12; /* subfunction 10 ( Get EGA config info) */ geninterrupt(0x10); EGA=_BL; if (EGA!=0x10) /* EGA/VGA BIOS changes BL */ maxlines_printed = (*(char far *)MK_FP(0x0040,0x0084))+1; else /* other BIOSes don't have this function */ maxlines_printed = 25; for ( i = 1 ; i < argc ; i++ ) { /* process command line */ switch ( *argv[i] ) { case '-': /* option */ process_option(argv[i]+1); break; case '?': /* request Usage report */ usage(); exit(0); default: /* assume pathname */ if ( x == MAXDIRS ) { /* currently 10 paths allowed */ printf("too many arguments!\7\n"); exit(1); } else { strcpy(temparg[x++],argv[i]); dir_specified = 1; } } } if ( !dir_specified ) { /* no path - use current directory */ getcwd(buf, 80); strcpy(temparg[x++],buf); printf("no directory specified. Using \"%s\"\n",buf); } for ( i = 0 ; i < x ; i++ ) { process_dir(temparg[i]); if ( show_cluster || !file_size ) { /* compute cluster size */ if ( !force_cluster ) { /* get cluster size */ getdfree(udrive, &dinfo); cluster_size = dinfo.df_bsec * dinfo.df_sclus; } printf("directory : %s\n",searchdir); printf("bytes per cluster = %d\n", cluster_size); } lines_printed=2; size = get_directory_size(searchdir,mask,curr_dir,1); /* get directory size */ if ( !first_column ) printf("\n"); printf("\n"); if (paged_list&&((maxlines_printed-lines_printed)<2)) { register int i; printf("%62s","========== hit any key to continue =========="); getch(); /* wait for key */ for(i=0;i<62;i++) printf("\b \b"); lines_printed = 0; } if ( total_stats ) { /* print size */ totals_output(searchdir, size); } } }