Advertisement
Guest User

Untitled

a guest
Jul 27th, 2017
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.66 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <dirent.h>
  5. #include <sys/stat.h>
  6. #include <sys/types.h>
  7. #include <string.h>
  8. #include <pwd.h>
  9. #include <limits.h>
  10.  
  11. #define L_NONE 0
  12. #define L_RECURSIVE 1
  13.  
  14. #define ST_INIT 0
  15. #define ST_PROCESS 1
  16. #define ST_FIN 2
  17. #define ST_CLEAR 4
  18.  
  19. struct fileStat {
  20.     char* name;
  21.     char* dir;
  22.     struct stat stat;  
  23. };
  24.  
  25.  
  26. void fileStatPrint(struct fileStat* stat);
  27. void fileStatClear(struct fileStat* stat);
  28. int fileStatCmp(struct fileStat* dest,const struct fileStat* src);
  29. void fileStatRewrite(struct fileStat* dest,const struct fileStat* src);
  30.  
  31. void* largest(int state,const struct fileStat* p);
  32. void* largest_three(int state,const struct fileStat* p);
  33. void* largest_three_bydate(int state,const struct fileStat* p);
  34. void* largest_each_subdir(int state,const struct fileStat* p);
  35. void* find_largest(void* (*process)(int,const struct fileStat*),const char* rootdir,const int flags);
  36.  
  37. void print_help();
  38.  
  39. int main(int argc,char** argv) {
  40.     if (argc != 2) {
  41.         print_help();
  42.         return 1;
  43.     }
  44.    
  45.     //char* MY_ROOT = getenv("HOME");
  46.     //char* MY_ROOT = ".";
  47.  
  48.     if (!strcmp(argv[1],"1")) {
  49.         struct fileStat* max = (struct fileStat*)find_largest(largest,".",L_NONE);
  50.         fileStatPrint(max);
  51.         largest(ST_CLEAR,NULL);
  52.     } else if (!strcmp(argv[1],"2")) {
  53.         find_largest(largest_each_subdir,".",L_RECURSIVE);
  54.         largest_each_subdir(ST_CLEAR,NULL);
  55.     } else if (!strcmp(argv[1],"3")) {
  56.         struct fileStat** max = (struct fileStat**)find_largest(largest_three,".",L_RECURSIVE);
  57.         fileStatPrint(max[0]);
  58.         fileStatPrint(max[1]);
  59.         fileStatPrint(max[2]);
  60.         largest_three(ST_CLEAR,NULL);
  61.     } else if (!strcmp(argv[1],"4")) {
  62.         struct fileStat** max = (struct fileStat**)find_largest(largest_three_bydate,".",L_RECURSIVE);
  63.         fileStatPrint(max[0]);
  64.         fileStatPrint(max[1]);
  65.         fileStatPrint(max[2]);
  66.         largest_three_bydate(ST_CLEAR,NULL);
  67.     } else {
  68.         print_help();
  69.         return 1;
  70.     }
  71.     return 0;
  72. }
  73.  
  74. void fileStatPrint(struct fileStat* stat) {
  75.     if (stat == NULL || stat->dir == NULL) {
  76.         printf("no files found\n");
  77.     } else {
  78.         printf("%s: %lld bytes\n",stat->name,(long long)stat->stat.st_size);
  79.         //printf("%s: %lld bytes",stat->name,(long long)stat->stat.st_size,);
  80.     }
  81. }
  82.  
  83. void fileStatClear(struct fileStat* stat) {
  84.     if (stat) {
  85.         if (stat->name) { free(stat->name); }
  86.         if (stat->dir) { free(stat->dir); }
  87.         free(stat);
  88.     }
  89. }
  90.  
  91. int fileStatCmp(struct fileStat* dest,const struct fileStat* src) {
  92.     if (src->stat.st_size > dest->stat.st_size) {
  93.         return 1;
  94.     } else if (src->stat.st_size == dest->stat.st_size) {
  95.         return 0;
  96.     } else {
  97.         return -1;
  98.     }
  99. }
  100.  
  101. void fileStatRewrite(struct fileStat* dest,const struct fileStat* src) {
  102.     if (!dest) { return; }
  103.     if (!src) { return; }
  104.     if (dest->name) { free(dest->name); }
  105.     if (dest->dir) { free(dest->dir); }
  106.     if (src->name) {
  107.         dest->name = strdup(src->name);
  108.     }
  109.     if (dest->name) {
  110.         dest->dir = strdup(src->dir);
  111.     }
  112.     dest->stat = src->stat;
  113. }
  114.  
  115. struct fileStat* fileStatInit() {
  116.     struct fileStat* max = malloc(sizeof(struct fileStat));
  117.     max->dir = 0; max->name = 0; max->stat.st_size = -1;
  118.     return max;
  119. }
  120.  
  121. void* largest_each_subdir(int state,const struct fileStat* p) {
  122.     static char* last_dir; // it's automatically init to 0 when the program starts
  123.     switch (state) {
  124.         case ST_INIT:
  125.             break;
  126.         case ST_FIN:
  127.             printf("in %s: ",last_dir);
  128.             fileStatPrint(largest(ST_FIN,NULL));
  129.             if (last_dir) { free(last_dir); }
  130.             largest(ST_FIN,NULL);
  131.             largest(ST_CLEAR,NULL);
  132.             break;
  133.         case ST_CLEAR:
  134.             break;
  135.         default:
  136.             if (!last_dir) { // first run
  137.                 last_dir = strdup(p->dir);
  138.                 largest(ST_INIT,NULL);
  139.             }
  140.             if (!strcmp(p->dir,last_dir)) {
  141.                 largest(state,p);
  142.             } else {
  143.                 printf("in %s: ",last_dir);
  144.                 free(last_dir);
  145.                 fileStatPrint(largest(ST_FIN,NULL));
  146.                 largest(ST_CLEAR,NULL);
  147.                 largest(ST_INIT,NULL);
  148.                 largest(state,p);
  149.                 last_dir = strdup(p->dir);
  150.             }
  151.     }
  152.     return NULL;
  153. }
  154.  
  155. void* largest(int state,const struct fileStat* p) {
  156.     static struct fileStat* max = NULL;
  157.     switch (state) {
  158.         case ST_INIT:
  159.             max = fileStatInit();
  160.             break;
  161.         case ST_FIN:
  162.             return max;
  163.             break;
  164.         case ST_CLEAR:
  165.             fileStatClear(max);
  166.             break;
  167.         default:
  168.             if (fileStatCmp(max,p) == 1) {
  169.                 fileStatRewrite(max,p);
  170.             }
  171.     }
  172.     return NULL;
  173. }
  174.  
  175. void* largest_three(int state,const struct fileStat* p) {
  176.     static struct fileStat* max = NULL;
  177.     static struct fileStat* sn_max = NULL;
  178.     static struct fileStat* rd_max = NULL;
  179.     static struct fileStat** ret = NULL;
  180.     switch (state) {
  181.         case ST_INIT:
  182.             max = fileStatInit();
  183.             sn_max = fileStatInit();
  184.             rd_max = fileStatInit();
  185.             break;
  186.         case ST_FIN:
  187.             ret = malloc(sizeof(struct fileStat*)*3);
  188.             ret[0]=max;
  189.             ret[1]=sn_max;
  190.             ret[2]=rd_max;
  191.             return ret;
  192.             break;
  193.         case ST_CLEAR:
  194.             if (ret) { free(ret); }
  195.             fileStatClear(max);
  196.             fileStatClear(sn_max);
  197.             fileStatClear(rd_max);
  198.             break;
  199.         default:
  200.             if (fileStatCmp(rd_max,p) == 1 ) {
  201.                 if (fileStatCmp(sn_max,p) == 1) {
  202.                     if (fileStatCmp(max,p) == 1) {
  203.                         fileStatRewrite(rd_max,sn_max);
  204.                         fileStatRewrite(sn_max,max);
  205.                         fileStatRewrite(max,p);
  206.                     } else { //bigger than sn but same size or smaller than max
  207.                         fileStatRewrite(rd_max,sn_max);
  208.                         fileStatRewrite(sn_max,p);
  209.                     }
  210.                 } else { // bigger than rd but same size or smaller than sn
  211.                     fileStatRewrite(rd_max,p);
  212.                 }
  213.             }
  214.     }
  215.     return NULL;
  216. }
  217.  
  218. int cmpDates(const void* a,const void* b) {
  219.     if (!a) { return 1; }
  220.     if (!b) { return -1; }
  221.  
  222.     const struct fileStat* pa =  *((const struct fileStat**)a);
  223.     const struct fileStat* pb =  *((const struct fileStat**)b);
  224.  
  225.     if (!pa) { return 1; }
  226.     if (!pb) { return -1; }
  227.    
  228.     if (pa->stat.st_size<0) { return 1;}
  229.     if (pb->stat.st_size<0) { return -1;}
  230.  
  231.     const time_t da = pa->stat.st_mtime;
  232.     const time_t db = pb->stat.st_mtime;
  233.        
  234.     if (da>db) {
  235.         return 1;
  236.     } else if (da==db) {
  237.         return 0;
  238.     } else {
  239.         return -1;
  240.     }
  241.    
  242.     return 1;
  243. }
  244.  
  245. void* largest_three_bydate(int state,const struct fileStat* p) {
  246.     switch (state) {
  247.         case ST_FIN: ;
  248.             struct fileStat** ret = largest_three(state,p);
  249.             qsort(ret,3,sizeof(struct fileStat*),cmpDates);
  250.             return ret;
  251.         default:
  252.             largest_three(state,p);
  253.             break;
  254.     }
  255.     return NULL;
  256. }
  257.  
  258.  
  259. // directory list
  260. struct dl {
  261.     char* name;
  262.     struct dl* next;
  263. };
  264.  
  265. struct dl* dl_init(char* name) {
  266.     struct dl* new_dl = malloc(sizeof(struct dl));
  267.     new_dl->name = strdup(name);
  268.     new_dl->next = 0;
  269.     return new_dl;
  270. }
  271.  
  272. void dl_add(struct dl* dl,char* name) {
  273.     if (!dl) { return; }
  274.     while (dl) {
  275.         if (!dl->next) {
  276.             dl->next = dl_init(name);
  277.             break;
  278.         }
  279.         dl=dl->next;
  280.     }
  281. }
  282.  
  283. void dl_clear(struct dl* dl) {
  284.     struct dl* t;
  285.     while (dl) {
  286.         free(dl->name);
  287.         t=dl->next;
  288.         free(dl);
  289.         dl = t;
  290.     }
  291. }
  292.  
  293.  
  294. void* find_largest_real(void* (*process)(int,const struct fileStat*),const char* rootdir,const int flags,const int inner) {
  295.     if (!inner) {
  296.         process(ST_INIT,NULL);
  297.     }
  298.    
  299.     struct dl* subdirs = NULL;
  300.  
  301.     char root_abs[PATH_MAX];
  302.     realpath(rootdir,root_abs);
  303.  
  304.     DIR* d = opendir(root_abs);
  305.     if (d==NULL) { return NULL; }
  306.  
  307.     struct dirent* de;
  308.     while ( (de = readdir(d)) != NULL ) {
  309.         if (!strcmp(de->d_name,".") || !strcmp(de->d_name,"..")) { continue; }
  310.         struct fileStat s;
  311.         struct stat s_stat;
  312.         s.name = de->d_name;
  313.         s.dir = root_abs;
  314.         char* fullpath = malloc(strlen(s.dir)+1+strlen(s.name)+1);
  315.         sprintf(fullpath,"%s/%s",s.dir,s.name);
  316.         if (lstat(fullpath,&s_stat) != 0 ) {
  317.             fprintf(stderr,"problem accessing %s - skipping...\n",fullpath);
  318.             free(fullpath);
  319.             continue;
  320.         }
  321.         s.stat = s_stat;
  322.         if (!S_ISDIR(s_stat.st_mode)) {
  323.             process(ST_PROCESS,&s);
  324.         }
  325.         if (flags == L_RECURSIVE) {
  326.             if (S_ISDIR(s_stat.st_mode) && ! S_ISLNK(s_stat.st_mode) ) {
  327.                 if (!subdirs) {
  328.                     subdirs = dl_init(fullpath);
  329.                 } else {
  330.                     dl_add(subdirs,fullpath);
  331.                 }
  332.             }
  333.         }
  334.         free(fullpath);
  335.     }
  336.     closedir(d);
  337.  
  338.     struct dl* subdir = subdirs;
  339.     while (subdir) {
  340.         find_largest_real(process,subdir->name,flags,1);
  341.         subdir=subdir->next;
  342.     }
  343.     dl_clear(subdirs);
  344.    
  345.     if (!inner) {
  346.         return process(ST_FIN,NULL);
  347.     } else {
  348.         return NULL;
  349.     }
  350. }
  351.  
  352. // hide the magic value inner from users
  353. void* find_largest(void* (*process)(int,const struct fileStat*),const char* rootdir,const int flags) {
  354.     return find_largest_real(process,rootdir,flags,0);
  355. }
  356.  
  357.  
  358. void print_help() {
  359.     printf(
  360.     "usage: the program takes one argument: 1,2,3 or 4\n\n"
  361.     "(1) List the name of"
  362.     "the largest file in your current directory\n"
  363.     "(2) List the name of the largest"
  364.     "file in your each sub dir\n"
  365.     "(3) List the names of the largest three files"
  366.     "on the system.\n"
  367.     "(4) Three largest file on the system ordered by age\n"
  368.     );
  369. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement