diff --git a/src/task_find.c b/src/task_find.c index 883e0644ba0cb65375aded01d77b7106923ed43b..c553a87b74f76f1542f6e184d53bd6439babd546 100644 --- a/src/task_find.c +++ b/src/task_find.c @@ -234,9 +234,15 @@ struct linux_dirent64 { /* Same as in GNU find. */ #define BUF_SIZE (32*1024) +enum action { + SUMMARIZE_DISK_USAGE = 1, + PRINT_LIBC = 1 << 1, + PRINT_MATCHES = 1 << 2, +}; + static int do_user_find(unsigned char d_type, int parent_dfd, const char *name, const char *search_name, int search_type, bool debug, - bool print_libc) { + int flags, size_t *disk_usage_total) { int err = 0; size_t namelen = strlen(name); @@ -247,11 +253,24 @@ static int do_user_find(unsigned char d_type, int parent_dfd, const char *name, bool match = (search_type != -1 && d_type == search_type) || (search_name != NULL && strcmp(search_name, name) == 0); if (match) { - if (print_libc) { - printf("%s\n", name); - } else { - write(STDOUT_FILENO, name, namelen); - write(STDOUT_FILENO, "\n", 1); + if (flags & PRINT_MATCHES) { + if (flags & PRINT_LIBC) { + printf("%s\n", name); + } else { + write(STDOUT_FILENO, name, namelen); + write(STDOUT_FILENO, "\n", 1); + } + } + + if (d_type == DT_REG && + flags & SUMMARIZE_DISK_USAGE) { + struct stat statbuf; + err = fstatat(parent_dfd, name, &statbuf, 0); + if (err) { + perror("fstatat"); + exit(EXIT_FAILURE); + } + *disk_usage_total += statbuf.st_size; } } @@ -265,11 +284,13 @@ static int do_user_find(unsigned char d_type, int parent_dfd, const char *name, return 0; } - if (print_libc) { - printf("%s/\n", name); - } else { - write(STDOUT_FILENO, name, namelen); - write(STDOUT_FILENO, "/\n", 2); + if (flags & PRINT_MATCHES) { + if (flags & PRINT_LIBC) { + printf("%s/\n", name); + } else { + write(STDOUT_FILENO, name, namelen); + write(STDOUT_FILENO, "/\n", 2); + } } while (true) { @@ -286,7 +307,7 @@ static int do_user_find(unsigned char d_type, int parent_dfd, const char *name, for (int bpos = 0; bpos < nread;) { struct linux_dirent64 *d = (struct linux_dirent64 *) (buf + bpos); err = do_user_find(d->d_type, dfd, d->d_name, search_name, search_type, - debug, print_libc); + debug, flags, disk_usage_total); if (err) { goto close; } @@ -295,25 +316,33 @@ static int do_user_find(unsigned char d_type, int parent_dfd, const char *name, } close: - if (print_libc) { - printf("..\n"); - } else { - write(STDOUT_FILENO, "..\n", 3); + if (flags & PRINT_MATCHES) { + if (flags & PRINT_LIBC) { + printf("..\n"); + } else { + write(STDOUT_FILENO, "..\n", 3); + } } close(dfd); return err; } static int user_find(const char *path, const char *search_name, - bool debug, int search_type, bool print_libc) { - return do_user_find(DT_DIR, AT_FDCWD, path, search_name, search_type, debug, print_libc); + bool debug, int search_type, int flags) { + size_t disk_usage_total = 0; + int err = do_user_find(DT_DIR, AT_FDCWD, path, search_name, search_type, + debug, flags, &disk_usage_total); + if (!err) { + printf("%zu %s\n", disk_usage_total, path); + } + return err; } int main(int argc, char **argv) { bool debug = false; bool variant_bpf = true; - bool print_libc = true; + int flags = 0; const char *path; const char *name = NULL; @@ -322,7 +351,7 @@ int main(int argc, char **argv) int optc; opterr = 0; - while ((optc = getopt(argc, argv, "D" "v:" "n:" "t:" "p:")) != -1) { + while ((optc = getopt(argc, argv, "D" "v:" "n:" "t:" "b" "s" "m")) != -1) { switch (optc) { case 'D': debug = true; @@ -336,8 +365,14 @@ int main(int argc, char **argv) case 't': type_str = optarg; break; - case 'p': - print_libc = strcmp("libc", optarg) == 0; + case 'b': + flags |= PRINT_LIBC; + break; + case 's': + flags |= SUMMARIZE_DISK_USAGE; + break; + case 'm': + flags |= PRINT_MATCHES; break; default: fprintf(stderr, "error: invalid option %c\n", optc); @@ -398,7 +433,7 @@ int main(int argc, char **argv) if (variant_bpf) { ret = bpf_find(path, name, debug, type); } else { - ret = user_find(path, name, debug, type, print_libc); + ret = user_find(path, name, debug, type, flags); } return ret;