Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <getopt.h>
- #include <libgen.h>
- #include <string.h>
- #include <dirent.h>
- #include <sys/stat.h>
- #define TERABYTE (1024.0 * 1024.0 * 1024.0)
- #define GIGABYTE (1024.0 * 1024.0)
- #define MEGABYTE (1024.0)
- #define KILABYTE (1.0)
- struct option long_options[] = {
- {"all", no_argument, 0, 'a'},
- {"bytes", no_argument, 0, 'b'},
- {"human-readable", no_argument, 0, 'h'},
- {"threshold", required_argument, 0, 't'},
- {"help", no_argument, 0, 0},
- {"version", no_argument, 0, 0}
- };
- char opt_bytes = 0;
- char opt_all = 0;
- char opt_human = 0;
- int opt_threshold = 0;
- double special_round(double value) {
- double delta = value - (int)(value * 10) / 10.0;
- if (delta > 1e-9) value = (int)(value * 10 + 1) / 10.0;
- return value;
- }
- void print_size(unsigned int bytes) {
- if (opt_human) {
- if (bytes >= TERABYTE) {
- printf("%.1f%c\t", special_round(bytes * 1.0 / TERABYTE), 'T');
- } else if (bytes >= GIGABYTE) {
- printf("%.1f%c\t", special_round(bytes * 1.0 / TERABYTE), 'G');
- } else if (bytes >= MEGABYTE) {
- printf("%-.1f%c\t", special_round(bytes * 1.0 / MEGABYTE), 'M');
- } else if (bytes >= KILABYTE) {
- printf("%.1f%c\t", special_round(bytes * 1.0 / KILABYTE), 'K');
- } else {
- printf("%.1f%c\t", special_round(bytes * 1.0), 'B');
- }
- } else {
- printf("%u\t", bytes);
- }
- }
- long long parse_SIZE(char *strsize, int *error_state) {
- *error_state = 0;
- char dig = 1;
- unsigned long long num = 0;
- long long multiply = 1;
- int index = 0;
- if (strsize[index] == '-') {
- dig = -1;
- index++;
- }
- char *endptr;
- num = strtol(strsize + index, &endptr, 10);
- if (num == 0) {
- *error_state = 1;
- return 0;
- }
- if (*endptr != 0) {
- if (strcmp(endptr, "k") == 0) {
- multiply = 1000;
- } else if (strcmp(endptr, "K") == 0) {
- multiply = 1024;
- } else if (strcmp(endptr, "m") == 0) {
- multiply = 1000 * 1000;
- } else if (strcmp(endptr, "M") == 0) {
- multiply = 1024 * 1024;
- } else if (strcmp(endptr, "G") == 0) {
- multiply = 1024 * 1024 * 1024;
- } else if (strcmp(endptr, "T") == 0) {
- multiply = 1024ULL * 1024ULL * 1024ULL * 1024ULL;
- } else {
- *error_state = 2;
- return 0;
- }
- }
- return dig * num * multiply;
- }
- char *create_path(char *path, char *d_name) {
- unsigned int length_path = strlen(path);
- unsigned int length_d_name = strlen(d_name);
- unsigned int length = length_path + length_d_name + 1;
- char *npath = malloc(length + 1);
- npath[length] = 0;
- memcpy(npath, path, length_path);
- npath[length_path] = '/';
- memcpy(npath + length_path + 1, d_name, length_d_name);
- return npath;
- }
- unsigned int dfs(char *path) {
- DIR *dir = opendir(path);
- if (!dir) {
- return 0;
- }
- struct dirent *dir_entry;
- unsigned int total_size = 0;
- while ((dir_entry = readdir(dir)) != NULL) {
- if (dir_entry->d_type == DT_DIR) {
- char *next_dir = dir_entry->d_name;
- if (strcmp(next_dir, ".") != 0) {
- if (strcmp(next_dir, "..") != 0) {
- total_size += dfs(create_path(path, next_dir));
- } else {
- struct stat st;
- if(stat(create_path(path, dir_entry->d_name), &st) == 0) {
- if (!opt_bytes) {
- int value = (st.st_size + 1023) / 1024;
- if (value % 4 != 0) value += 4 - value % 4;
- total_size += value;
- } else {
- total_size += st.st_size;
- }
- }
- }
- }
- } else {
- struct stat st;
- char *npath = create_path(path, dir_entry->d_name);
- if(stat(npath, &st) == 0) {
- if (opt_all) {
- if (!opt_bytes) {
- int value = (st.st_size + 1023) / 1024;
- if (value % 4 != 0) value += 4 - value % 4;
- print_size(value);
- } else {
- print_size(st.st_size);
- }
- printf("%s\n", npath);
- }
- if (!opt_bytes) {
- int value = (st.st_size + 1023) / 1024;
- if (value % 4 != 0) value += 4 - value % 4;
- total_size += value;
- } else {
- total_size += st.st_size;
- }
- }
- }
- }
- if (!((opt_threshold > 0 && total_size < opt_threshold) || (opt_threshold < 0 && total_size > -opt_threshold))) {
- print_size(total_size);
- printf("%s\n", path);
- }
- free(path);
- closedir(dir);
- return total_size;
- }
- int main(int argc, char **argv) {
- int option_index = -1;
- int opt = getopt_long(argc, argv, "abht:", long_options, &option_index);
- while (opt != -1) {
- if (opt != 0) {
- if (opt == 't') {
- int error_state;
- opt_threshold = parse_SIZE(optarg, &error_state);
- if (error_state == 1) {
- if (option_index != -1 && long_options[option_index].val == 't') {
- printf("du: invalid --threshold argument '%s'\n", optarg);
- } else {
- printf("du: invalid -t argument '%s'\n", optarg);
- }
- return 1;
- } else if (error_state == 2) {
- if (option_index != -1 && long_options[option_index].val == 't') {
- printf("du: invalid suffix in --threshold argument '%s'\n", optarg);
- } else {
- printf("du: invalid suffix in -t argument '%s'\n", optarg);
- }
- return 1;
- }
- } else if (opt == 'a') {
- opt_all = 1;
- } else if (opt == 'h') {
- opt_human = 1;
- } else if (opt == 'b') {
- opt_bytes = 1;
- opt_human = 0;
- }
- } else {
- if (option_index == 4) {
- printf(
- "Summarize disk usage of the set of FILEs, recursively for\n"
- "directories.\n"
- "\n"
- "Mandatory arguments to long options are mandatory for short options\n"
- "too.\n"
- "\n"
- "-b, --bytes\n"
- " equivalent to '--apparent-size --block-size=1'\n"
- "\n"
- "-a, --all\n"
- " write counts for all files, not just directories\n"
- "\n"
- "-h, --human-readable\n"
- " print sizes in human readable format (e.g., 1K 234M 2G)\n"
- "\n"
- "-t, --threshold=SIZE\n"
- " exclude entries smaller than SIZE if positive, or entries\n"
- " greater than SIZE if negative\n"
- "\n"
- "--help display this help and exit\n"
- "\n"
- "--version\n"
- " output version information and exit\n"
- "\n"
- );
- return 0;
- } else if (option_index == 5) {
- printf(
- "utility du\n"
- "Written by Alexander Katkov.\n"
- );
- return 0;
- }
- }
- option_index = -1;
- opt = getopt_long(argc, argv, "abht:", long_options, &option_index);
- }
- if (optind < argc) {
- for (int i = optind; i < argc; i++) {
- char *filepath = strdup(argv[i]);
- struct stat st;
- if(stat(filepath, &st) == 0) {
- if (!opt_bytes) {
- int value = (st.st_size + 1023) / 1024;
- if (value % 4 != 0) value += 4 - value % 4;
- print_size(value);
- } else {
- print_size(st.st_size);
- }
- printf("%s\n", filepath);
- } else {
- DIR *dir = opendir(filepath);
- if (!dir) {
- printf("du: cannot access '%s': No such file or directory\n", filepath);
- return 1;
- }
- closedir(dir);
- }
- dfs(filepath);
- }
- } else {
- char *filepath = strdup(argv[0]);
- char *path = dirname(filepath);
- dfs(path);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement