View Single Post
Old 12-03-2006, 08:56 PM   #4 (permalink)
albtross
Recruit
 
Join Date: Nov 2006
Posts: 9
albtross is on a distinguished road
nice programs there, however it differs from what real du command outputs, i made a modification which matches what du command output, however, it only includes one -k option. now it takes a file or a directory. also, it can take no argument which by default it will be current directory, and it takes -k option which only display half size. lastly, i includes a small feature which when the sub directories go beyond 4 it will stop and print message, because we don't want to print a very unacceptable long path directory info.
Code:
#define NONE 0 #define ALL 1 #define SUM 2 #define F 3 #define G 4 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <dirent.h> #include <getopt.h> #include <string.h> #include <errno.h> int optS( char* ); int noOpt( char*, int,char* ); int optK(char* , int,char*); int fopt( char* ); int main( int argc, char *argv[] ) { int c,type=NONE,lvl=0,blocksize=0; char ck[1000]; struct stat info; if (argc ==1) /* no argument */ {type = ALL;} if (argc ==2) { strcpy(ck, argv[1]); if(lstat(ck, &info) < 0) {printf( "Unable to stat: %s \n", ck); exit(1);} if(S_ISDIR(info.st_mode) == 0) /* it's a file */ { type = F; } } while( (c = getopt(argc, argv, "+k")) != -1 ) /*take option */ { switch( c ) { case 'k': /* option k */ strcpy(ck, argv[2]); if(lstat(ck, &info) < 0) {printf( "Unable to stat: %s \n", ck); exit(1);} if(S_ISDIR(info.st_mode) == 0) /* if it's a file */ {type = G;} else if( type == NONE ) type = SUM; else { return EXIT_FAILURE; } break; default: return EXIT_FAILURE; } } switch( type ) { case ALL: noOpt(".", lvl,NULL); /*no argument, so current dir is default setting*/ break; case SUM: while( optind < argc ) /*directory is taking option -k */ optK( argv[optind++], lvl, NULL ); break; case NONE: while( optind < argc ) /* normal one argument, directory*/ noOpt( argv[optind++], lvl,NULL ); break; case F: while( optind < argc ) /*argument is a file*/ { if( (blocksize=fopt(argv[optind])) != -1 ) printf( "%d%s%s\n", blocksize, "\t ", argv[optind++] ); } break; case G: while( optind < argc ) /*argument is a file and take -k option*/ { if( (blocksize=fopt(argv[optind])) != -1 ) printf( "%d%s%s\n", blocksize/2, "\t ", argv[optind++] ); } break; } return EXIT_SUCCESS; } /************************************************ Function optS calculate total blocksize and return value *************************************************/ int optS( char *dpath ) { DIR *pDir; struct dirent *dInfo; struct stat fInfo; char tempName[1000]; int blocksize = 0; if( (pDir = opendir(dpath)) == NULL) /*see if can stat or not*/ { perror("cannot open"); return 0; } while( (dInfo=readdir(pDir)) != NULL ) { if( strcmp(dInfo->d_name, ".") != 0 && strcmp(dInfo->d_name, "..") != 0 ) /*ignore .. and . */ { strcpy( tempName, dpath ); strcat( tempName, "/" ); strcat( tempName, dInfo->d_name ); if ((lstat(tempName,&fInfo)) == -1) printf( "Unable to lstat: %s\n", dInfo->d_name); else if( S_ISDIR(fInfo.st_mode) ) /*accumulate size and add directory size*/ {blocksize += fInfo.st_blocks; blocksize += optS (tempName);} else blocksize += fInfo.st_blocks; /*accumulate blocksize*/ } } closedir( pDir ); return blocksize; } /************************************************ function noOpt normal directory argument ************************************************/ int noOpt( char *dpath, int lvl,char *temp ) { DIR *pDir; struct dirent *dInfo; struct stat fInfo; char tempName[1000],tempchar[1000]; if( (pDir = opendir(dpath)) == NULL ) { perror("cannot open"); return 1; } while( (dInfo=readdir(pDir)) != NULL ) { if( strcmp(dInfo->d_name, ".") != 0 && strcmp(dInfo->d_name, "..") != 0 ) { strcpy( tempName, dpath ); strcat( tempName, "/" ); strcat( tempName, dInfo->d_name ); if( lstat(tempName, &fInfo) == -1 ) printf( "Unable to stat: %s \n", tempName ); else if( S_ISDIR(fInfo.st_mode) ) /*if it's a nested directory loop through*/ { strcpy(tempchar, dInfo->d_name); if ( lvl > 2) /*set up a counter to monitor how many directory go through*/ {printf("encounter a deep path unable to print : %s.\n",temp);/*print message*/ return 0; } noOpt( tempName, lvl+1,tempchar ); } } } printf("%d%s%s\n", 2+optS(dpath), "\t", dpath); /* print final outcome for every loop*/ return 0; } /************************************************** function optK take directory as argument and take -k option **************************************************/ int optK(char *dpath, int lvl,char *temp ) { DIR *pDir; struct dirent *dInfo; struct stat fInfo; char tempName[1000], tempchar[1000]; if( (pDir = opendir(dpath)) == NULL ) { perror("cannot open"); return 1; } while( (dInfo=readdir(pDir)) != NULL ) { if( strcmp(dInfo->d_name, ".") != 0 && strcmp(dInfo->d_name, "..") != 0 ) { strcpy( tempName, dpath ); strcat( tempName, "/" ); strcat( tempName, dInfo->d_name ); if( lstat(tempName, &fInfo) == -1 ) printf( "Unable to stat: %s \n", tempName ); else if( S_ISDIR(fInfo.st_mode) ) { strcpy(tempchar, dInfo->d_name); if ( lvl > 2) /*set up a counter to monitor how many directory go through*/ {printf("encounter a deep path unable to print : %s.\n",temp);/*print message*/ return 0; } /*loop through all directory inside */ optK( tempName, lvl+1,tempchar); } } } lvl = 0; /* clear it after loop*/ printf("%d%s%s\n", (2+optS(dpath))/2, "\t", dpath); /*the size is half of regular*/ return 0; } /************************************************ function fopt take argument as file *************************************************/ int fopt(char *dpath) { char tempName[1000]; int blocksize = 0; struct stat fInfo; strcpy( tempName, dpath ); if ((lstat(tempName,&fInfo)) == -1) printf( "Unable to lstat: %s\n", tempName); else blocksize = fInfo.st_blocks; return blocksize; }
__________________
albtross is offline   Reply With Quote