Advertisement
Guest User

Untitled

a guest
Jun 25th, 2019
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.31 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <getopt.h>
  4. #include <libgen.h>
  5. #include <string.h>
  6. #include <dirent.h>
  7.  
  8. #include <sys/stat.h>
  9.  
  10. #define TERABYTE (1024.0 * 1024.0 * 1024.0)
  11. #define GIGABYTE (1024.0 * 1024.0)
  12. #define MEGABYTE (1024.0)
  13. #define KILABYTE (1.0)
  14.  
  15. struct option long_options[] = {
  16.         {"all",              no_argument,       0, 'a'},
  17.         {"bytes",            no_argument,       0, 'b'},
  18.         {"human-readable",   no_argument,       0, 'h'},
  19.         {"threshold",        required_argument, 0, 't'},
  20.         {"help",             no_argument,       0, 0},
  21.         {"version",          no_argument,       0, 0}
  22. };
  23.  
  24. char opt_bytes = 0;
  25. char opt_all = 0;
  26. char opt_human = 0;
  27. int opt_threshold = 0;
  28.  
  29. double special_round(double value) {
  30.     double delta = value - (int)(value * 10) / 10.0;
  31.  
  32.     if (delta > 1e-9) value = (int)(value * 10 + 1) / 10.0;
  33.  
  34.     return value;
  35. }
  36.  
  37. void print_size(unsigned int bytes) {
  38.     if (opt_human) {
  39.         if (bytes >= TERABYTE) {
  40.             printf("%.1f%c\t", special_round(bytes * 1.0 / TERABYTE), 'T');
  41.         } else if (bytes >= GIGABYTE) {
  42.             printf("%.1f%c\t", special_round(bytes * 1.0 / TERABYTE), 'G');
  43.         } else if (bytes >= MEGABYTE) {
  44.             printf("%-.1f%c\t", special_round(bytes * 1.0 / MEGABYTE), 'M');
  45.         } else if (bytes >= KILABYTE) {
  46.             printf("%.1f%c\t", special_round(bytes * 1.0 / KILABYTE), 'K');
  47.         } else {
  48.             printf("%.1f%c\t", special_round(bytes * 1.0), 'B');
  49.         }
  50.     } else {
  51.         printf("%u\t", bytes);
  52.     }
  53. }
  54.  
  55. long long parse_SIZE(char *strsize, int *error_state) {
  56.     *error_state = 0;
  57.  
  58.     char dig = 1;
  59.     unsigned long long num = 0;
  60.     long long multiply = 1;
  61.  
  62.     int index = 0;
  63.     if (strsize[index] == '-') {
  64.         dig = -1;
  65.         index++;
  66.     }
  67.  
  68.     char *endptr;
  69.  
  70.     num = strtol(strsize + index, &endptr, 10);
  71.  
  72.     if (num == 0) {
  73.         *error_state = 1;
  74.         return 0;
  75.     }
  76.  
  77.     if (*endptr != 0) {
  78.         if (strcmp(endptr, "k") == 0) {
  79.             multiply = 1000;
  80.         } else if (strcmp(endptr, "K") == 0) {
  81.             multiply = 1024;
  82.         } else if (strcmp(endptr, "m") == 0) {
  83.             multiply = 1000 * 1000;
  84.         } else if (strcmp(endptr, "M") == 0) {
  85.             multiply = 1024 * 1024;
  86.         } else if (strcmp(endptr, "G") == 0) {
  87.             multiply = 1024 * 1024 * 1024;
  88.         } else if (strcmp(endptr, "T") == 0) {
  89.             multiply = 1024ULL * 1024ULL * 1024ULL * 1024ULL;
  90.         } else {
  91.             *error_state = 2;
  92.             return 0;
  93.         }
  94.     }
  95.  
  96.     return dig * num * multiply;
  97. }
  98.  
  99. char *create_path(char *path, char *d_name) {
  100.     unsigned int length_path = strlen(path);
  101.     unsigned int length_d_name = strlen(d_name);
  102.  
  103.     unsigned int length = length_path + length_d_name + 1;
  104.     char *npath = malloc(length + 1);
  105.     npath[length] = 0;
  106.  
  107.  
  108.     memcpy(npath, path, length_path);
  109.     npath[length_path] = '/';
  110.     memcpy(npath + length_path + 1, d_name, length_d_name);
  111.  
  112.     return npath;
  113. }
  114.  
  115. unsigned int dfs(char *path) {
  116.     DIR *dir = opendir(path);
  117.  
  118.     if (!dir) {
  119.         return 0;
  120.     }
  121.  
  122.     struct dirent *dir_entry;
  123.  
  124.     unsigned int total_size = 0;
  125.  
  126.     while ((dir_entry = readdir(dir)) != NULL) {
  127.         if (dir_entry->d_type == DT_DIR) {
  128.             char *next_dir = dir_entry->d_name;
  129.  
  130.             if (strcmp(next_dir, ".") != 0) {
  131.                 if (strcmp(next_dir, "..") != 0) {
  132.                     total_size += dfs(create_path(path, next_dir));
  133.                 } else {
  134.                     struct stat st;
  135.                     if(stat(create_path(path, dir_entry->d_name), &st) == 0) {
  136.  
  137.                         if (!opt_bytes) {
  138.                             int value = (st.st_size + 1023) / 1024;
  139.                             if (value % 4 != 0) value += 4 - value % 4;
  140.  
  141.                             total_size += value;
  142.                         } else {
  143.                             total_size += st.st_size;
  144.                         }
  145.  
  146.                     }
  147.                 }
  148.             }
  149.         } else {
  150.             struct stat st;
  151.             char *npath = create_path(path, dir_entry->d_name);
  152.             if(stat(npath, &st) == 0) {
  153.                 if (opt_all) {
  154.                     if (!opt_bytes) {
  155.                         int value = (st.st_size + 1023) / 1024;
  156.                         if (value % 4 != 0) value += 4 - value % 4;
  157.  
  158.                         print_size(value);
  159.                     } else {
  160.                         print_size(st.st_size);
  161.                     }
  162.  
  163.                     printf("%s\n", npath);
  164.                 }
  165.  
  166.                 if (!opt_bytes) {
  167.                     int value = (st.st_size + 1023) / 1024;
  168.                     if (value % 4 != 0) value += 4 - value % 4;
  169.  
  170.                     total_size += value;
  171.                 } else {
  172.                     total_size += st.st_size;
  173.                 }
  174.             }
  175.         }
  176.     }
  177.  
  178.     if (!((opt_threshold > 0 && total_size < opt_threshold) || (opt_threshold < 0 && total_size > -opt_threshold))) {
  179.         print_size(total_size);
  180.         printf("%s\n", path);
  181.     }
  182.  
  183.     free(path);
  184.  
  185.     closedir(dir);
  186.  
  187.     return total_size;
  188. }
  189.  
  190. int main(int argc, char **argv) {
  191.     int option_index = -1;
  192.     int opt = getopt_long(argc, argv, "abht:", long_options, &option_index);
  193.  
  194.     while (opt != -1) {
  195.         if (opt != 0) {
  196.             if (opt == 't') {
  197.                 int error_state;
  198.  
  199.                 opt_threshold = parse_SIZE(optarg, &error_state);
  200.  
  201.                 if (error_state == 1) {
  202.                     if (option_index != -1 && long_options[option_index].val == 't') {
  203.                         printf("du: invalid --threshold argument '%s'\n", optarg);
  204.                     } else {
  205.                         printf("du: invalid -t argument '%s'\n", optarg);
  206.                     }
  207.  
  208.                     return 1;
  209.                 } else if (error_state == 2) {
  210.                     if (option_index != -1 && long_options[option_index].val == 't') {
  211.                         printf("du: invalid suffix in --threshold argument '%s'\n", optarg);
  212.                     } else {
  213.                         printf("du: invalid suffix in -t argument '%s'\n", optarg);
  214.                     }
  215.  
  216.                     return 1;
  217.                 }
  218.  
  219.             } else if (opt == 'a') {
  220.                 opt_all = 1;
  221.             } else if (opt == 'h') {
  222.                 opt_human = 1;
  223.             } else if (opt == 'b') {
  224.                 opt_bytes = 1;
  225.                 opt_human = 0;
  226.             }
  227.         } else {
  228.             if (option_index == 4) {
  229.                 printf(
  230.                         "Summarize disk usage of the set of FILEs, recursively for\n"
  231.                         "directories.\n"
  232.                         "\n"
  233.                         "Mandatory arguments to long options are mandatory for short options\n"
  234.                         "too.\n"
  235.                         "\n"
  236.                         "-b, --bytes\n"
  237.                         "              equivalent to '--apparent-size --block-size=1'\n"
  238.                         "\n"
  239.                         "-a, --all\n"
  240.                         "              write counts for all files, not just directories\n"
  241.                         "\n"
  242.                         "-h, --human-readable\n"
  243.                         "              print sizes in human readable format (e.g., 1K 234M 2G)\n"
  244.                         "\n"
  245.                         "-t, --threshold=SIZE\n"
  246.                         "              exclude entries smaller than SIZE if positive, or entries\n"
  247.                         "              greater than SIZE if negative\n"
  248.                         "\n"
  249.                         "--help display this help and exit\n"
  250.                         "\n"
  251.                         "--version\n"
  252.                         "      output version information and exit\n"
  253.                         "\n"
  254.                 );
  255.                 return 0;
  256.             } else if (option_index == 5) {
  257.                 printf(
  258.                         "utility du\n"
  259.                         "Written by Alexander Katkov.\n"
  260.                 );
  261.                 return 0;
  262.             }
  263.         }
  264.  
  265.         option_index = -1;
  266.         opt = getopt_long(argc, argv, "abht:", long_options, &option_index);
  267.     }
  268.  
  269.     if (optind < argc) {
  270.         for (int i = optind; i < argc; i++) {
  271.             char *filepath = strdup(argv[i]);
  272.  
  273.             struct stat st;
  274.             if(stat(filepath, &st) == 0) {
  275.                 if (!opt_bytes) {
  276.                     int value = (st.st_size + 1023) / 1024;
  277.                     if (value % 4 != 0) value += 4 - value % 4;
  278.  
  279.                     print_size(value);
  280.                 } else {
  281.                     print_size(st.st_size);
  282.                 }
  283.  
  284.                 printf("%s\n", filepath);
  285.             } else {
  286.                 DIR *dir = opendir(filepath);
  287.  
  288.                 if (!dir) {
  289.                     printf("du: cannot access '%s': No such file or directory\n", filepath);
  290.                     return 1;
  291.                 }
  292.                 closedir(dir);
  293.             }
  294.  
  295.             dfs(filepath);
  296.         }
  297.     } else {
  298.         char *filepath = strdup(argv[0]);
  299.         char *path = dirname(filepath);
  300.  
  301.         dfs(path);
  302.     }
  303.  
  304.     return 0;
  305. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement