Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <dirent.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <string.h>
- #include <pwd.h>
- #include <limits.h>
- #define L_NONE 0
- #define L_RECURSIVE 1
- #define ST_INIT 0
- #define ST_PROCESS 1
- #define ST_FIN 2
- #define ST_CLEAR 4
- struct fileStat {
- char* name;
- char* dir;
- struct stat stat;
- };
- void fileStatPrint(struct fileStat* stat);
- void fileStatClear(struct fileStat* stat);
- int fileStatCmp(struct fileStat* dest,const struct fileStat* src);
- void fileStatRewrite(struct fileStat* dest,const struct fileStat* src);
- void* largest(int state,const struct fileStat* p);
- void* largest_three(int state,const struct fileStat* p);
- void* largest_three_bydate(int state,const struct fileStat* p);
- void* largest_each_subdir(int state,const struct fileStat* p);
- void* find_largest(void* (*process)(int,const struct fileStat*),const char* rootdir,const int flags);
- void print_help();
- int main(int argc,char** argv) {
- if (argc != 2) {
- print_help();
- return 1;
- }
- //char* MY_ROOT = getenv("HOME");
- //char* MY_ROOT = ".";
- if (!strcmp(argv[1],"1")) {
- struct fileStat* max = (struct fileStat*)find_largest(largest,".",L_NONE);
- fileStatPrint(max);
- largest(ST_CLEAR,NULL);
- } else if (!strcmp(argv[1],"2")) {
- find_largest(largest_each_subdir,".",L_RECURSIVE);
- largest_each_subdir(ST_CLEAR,NULL);
- } else if (!strcmp(argv[1],"3")) {
- struct fileStat** max = (struct fileStat**)find_largest(largest_three,".",L_RECURSIVE);
- fileStatPrint(max[0]);
- fileStatPrint(max[1]);
- fileStatPrint(max[2]);
- largest_three(ST_CLEAR,NULL);
- } else if (!strcmp(argv[1],"4")) {
- struct fileStat** max = (struct fileStat**)find_largest(largest_three_bydate,".",L_RECURSIVE);
- fileStatPrint(max[0]);
- fileStatPrint(max[1]);
- fileStatPrint(max[2]);
- largest_three_bydate(ST_CLEAR,NULL);
- } else {
- print_help();
- return 1;
- }
- return 0;
- }
- void fileStatPrint(struct fileStat* stat) {
- if (stat == NULL || stat->dir == NULL) {
- printf("no files found\n");
- } else {
- printf("%s: %lld bytes\n",stat->name,(long long)stat->stat.st_size);
- //printf("%s: %lld bytes",stat->name,(long long)stat->stat.st_size,);
- }
- }
- void fileStatClear(struct fileStat* stat) {
- if (stat) {
- if (stat->name) { free(stat->name); }
- if (stat->dir) { free(stat->dir); }
- free(stat);
- }
- }
- int fileStatCmp(struct fileStat* dest,const struct fileStat* src) {
- if (src->stat.st_size > dest->stat.st_size) {
- return 1;
- } else if (src->stat.st_size == dest->stat.st_size) {
- return 0;
- } else {
- return -1;
- }
- }
- void fileStatRewrite(struct fileStat* dest,const struct fileStat* src) {
- if (!dest) { return; }
- if (!src) { return; }
- if (dest->name) { free(dest->name); }
- if (dest->dir) { free(dest->dir); }
- if (src->name) {
- dest->name = strdup(src->name);
- }
- if (dest->name) {
- dest->dir = strdup(src->dir);
- }
- dest->stat = src->stat;
- }
- struct fileStat* fileStatInit() {
- struct fileStat* max = malloc(sizeof(struct fileStat));
- max->dir = 0; max->name = 0; max->stat.st_size = -1;
- return max;
- }
- void* largest_each_subdir(int state,const struct fileStat* p) {
- static char* last_dir; // it's automatically init to 0 when the program starts
- switch (state) {
- case ST_INIT:
- break;
- case ST_FIN:
- printf("in %s: ",last_dir);
- fileStatPrint(largest(ST_FIN,NULL));
- if (last_dir) { free(last_dir); }
- largest(ST_FIN,NULL);
- largest(ST_CLEAR,NULL);
- break;
- case ST_CLEAR:
- break;
- default:
- if (!last_dir) { // first run
- last_dir = strdup(p->dir);
- largest(ST_INIT,NULL);
- }
- if (!strcmp(p->dir,last_dir)) {
- largest(state,p);
- } else {
- printf("in %s: ",last_dir);
- free(last_dir);
- fileStatPrint(largest(ST_FIN,NULL));
- largest(ST_CLEAR,NULL);
- largest(ST_INIT,NULL);
- largest(state,p);
- last_dir = strdup(p->dir);
- }
- }
- return NULL;
- }
- void* largest(int state,const struct fileStat* p) {
- static struct fileStat* max = NULL;
- switch (state) {
- case ST_INIT:
- max = fileStatInit();
- break;
- case ST_FIN:
- return max;
- break;
- case ST_CLEAR:
- fileStatClear(max);
- break;
- default:
- if (fileStatCmp(max,p) == 1) {
- fileStatRewrite(max,p);
- }
- }
- return NULL;
- }
- void* largest_three(int state,const struct fileStat* p) {
- static struct fileStat* max = NULL;
- static struct fileStat* sn_max = NULL;
- static struct fileStat* rd_max = NULL;
- static struct fileStat** ret = NULL;
- switch (state) {
- case ST_INIT:
- max = fileStatInit();
- sn_max = fileStatInit();
- rd_max = fileStatInit();
- break;
- case ST_FIN:
- ret = malloc(sizeof(struct fileStat*)*3);
- ret[0]=max;
- ret[1]=sn_max;
- ret[2]=rd_max;
- return ret;
- break;
- case ST_CLEAR:
- if (ret) { free(ret); }
- fileStatClear(max);
- fileStatClear(sn_max);
- fileStatClear(rd_max);
- break;
- default:
- if (fileStatCmp(rd_max,p) == 1 ) {
- if (fileStatCmp(sn_max,p) == 1) {
- if (fileStatCmp(max,p) == 1) {
- fileStatRewrite(rd_max,sn_max);
- fileStatRewrite(sn_max,max);
- fileStatRewrite(max,p);
- } else { //bigger than sn but same size or smaller than max
- fileStatRewrite(rd_max,sn_max);
- fileStatRewrite(sn_max,p);
- }
- } else { // bigger than rd but same size or smaller than sn
- fileStatRewrite(rd_max,p);
- }
- }
- }
- return NULL;
- }
- int cmpDates(const void* a,const void* b) {
- if (!a) { return 1; }
- if (!b) { return -1; }
- const struct fileStat* pa = *((const struct fileStat**)a);
- const struct fileStat* pb = *((const struct fileStat**)b);
- if (!pa) { return 1; }
- if (!pb) { return -1; }
- if (pa->stat.st_size<0) { return 1;}
- if (pb->stat.st_size<0) { return -1;}
- const time_t da = pa->stat.st_mtime;
- const time_t db = pb->stat.st_mtime;
- if (da>db) {
- return 1;
- } else if (da==db) {
- return 0;
- } else {
- return -1;
- }
- return 1;
- }
- void* largest_three_bydate(int state,const struct fileStat* p) {
- switch (state) {
- case ST_FIN: ;
- struct fileStat** ret = largest_three(state,p);
- qsort(ret,3,sizeof(struct fileStat*),cmpDates);
- return ret;
- default:
- largest_three(state,p);
- break;
- }
- return NULL;
- }
- // directory list
- struct dl {
- char* name;
- struct dl* next;
- };
- struct dl* dl_init(char* name) {
- struct dl* new_dl = malloc(sizeof(struct dl));
- new_dl->name = strdup(name);
- new_dl->next = 0;
- return new_dl;
- }
- void dl_add(struct dl* dl,char* name) {
- if (!dl) { return; }
- while (dl) {
- if (!dl->next) {
- dl->next = dl_init(name);
- break;
- }
- dl=dl->next;
- }
- }
- void dl_clear(struct dl* dl) {
- struct dl* t;
- while (dl) {
- free(dl->name);
- t=dl->next;
- free(dl);
- dl = t;
- }
- }
- void* find_largest_real(void* (*process)(int,const struct fileStat*),const char* rootdir,const int flags,const int inner) {
- if (!inner) {
- process(ST_INIT,NULL);
- }
- struct dl* subdirs = NULL;
- char root_abs[PATH_MAX];
- realpath(rootdir,root_abs);
- DIR* d = opendir(root_abs);
- if (d==NULL) { return NULL; }
- struct dirent* de;
- while ( (de = readdir(d)) != NULL ) {
- if (!strcmp(de->d_name,".") || !strcmp(de->d_name,"..")) { continue; }
- struct fileStat s;
- struct stat s_stat;
- s.name = de->d_name;
- s.dir = root_abs;
- char* fullpath = malloc(strlen(s.dir)+1+strlen(s.name)+1);
- sprintf(fullpath,"%s/%s",s.dir,s.name);
- if (lstat(fullpath,&s_stat) != 0 ) {
- fprintf(stderr,"problem accessing %s - skipping...\n",fullpath);
- free(fullpath);
- continue;
- }
- s.stat = s_stat;
- if (!S_ISDIR(s_stat.st_mode)) {
- process(ST_PROCESS,&s);
- }
- if (flags == L_RECURSIVE) {
- if (S_ISDIR(s_stat.st_mode) && ! S_ISLNK(s_stat.st_mode) ) {
- if (!subdirs) {
- subdirs = dl_init(fullpath);
- } else {
- dl_add(subdirs,fullpath);
- }
- }
- }
- free(fullpath);
- }
- closedir(d);
- struct dl* subdir = subdirs;
- while (subdir) {
- find_largest_real(process,subdir->name,flags,1);
- subdir=subdir->next;
- }
- dl_clear(subdirs);
- if (!inner) {
- return process(ST_FIN,NULL);
- } else {
- return NULL;
- }
- }
- // hide the magic value inner from users
- void* find_largest(void* (*process)(int,const struct fileStat*),const char* rootdir,const int flags) {
- return find_largest_real(process,rootdir,flags,0);
- }
- void print_help() {
- printf(
- "usage: the program takes one argument: 1,2,3 or 4\n\n"
- "(1) List the name of"
- "the largest file in your current directory\n"
- "(2) List the name of the largest"
- "file in your each sub dir\n"
- "(3) List the names of the largest three files"
- "on the system.\n"
- "(4) Three largest file on the system ordered by age\n"
- );
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement