Advertisement
cutecoder

Counts the bytes of all files and the individual bytes and prints a ranking

Sep 6th, 2023 (edited)
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.72 KB | Source Code | 0 0
  1. #include <ctype.h>
  2. #include <errno.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <unistd.h>
  6. #include <fcntl.h>
  7. #include <dirent.h>
  8. #include <string.h>
  9. #include <stdbool.h>
  10.  
  11. #define ARRLEN(a) (sizeof(a)/sizeof*(a))
  12.  
  13. static char path[PATH_MAX];
  14. static char all_extensions[8192];
  15.  
  16. #define KEY_COUNT 256
  17.  
  18. static size_t key_counts[KEY_COUNT];
  19. struct key_entry {
  20.     char key;
  21.     size_t count;
  22. } key_entries[KEY_COUNT];
  23.  
  24. static size_t total_bytes;
  25. static size_t total_files;
  26. static size_t total_directories;
  27. static size_t total_files_failed;
  28. static size_t total_directories_failed;
  29.  
  30. bool has_extension(const char *ext)
  31. {
  32.     if (all_extensions[0] == '\0')
  33.         return true;
  34.     for (const char *exts = all_extensions; *exts != '\0'; exts++) {
  35.         size_t j = 0;
  36.  
  37.         for (; ext[j] != '\0'; exts++, j++)
  38.             if (ext[j] != *exts)
  39.                 break;
  40.         if (ext[j] == '\0' && *exts == '\0')
  41.             return true;
  42.         while (*exts != '\0')
  43.             exts++;
  44.     }
  45.     return false;
  46. }
  47.  
  48. void recursive_check_dir(void)
  49. {
  50.     DIR *dir;
  51.     int dfd;
  52.     struct dirent *ent;
  53.     int fd;
  54.     char buf[1024];
  55.     size_t nPath;
  56.     ssize_t r;
  57.     size_t bytes;
  58.     size_t nName;
  59.     const char *ext;
  60.  
  61.     dir = opendir(path);
  62.     if (dir == NULL) {
  63.         printf("could not open dir: %s\n", strerror(errno));
  64.         total_directories_failed++;
  65.         return;
  66.     }
  67.     dfd = dirfd(dir);
  68.     total_directories++;
  69.     printf("\tin: %s\n", path);
  70.     nPath = strlen(path);
  71.     while ((ent = readdir(dir)) != NULL) {
  72.         if (ent->d_name[0] == '.')
  73.             continue;
  74.         if (ent->d_type == DT_REG && nName >= 2) {
  75.             ext = strrchr(ent->d_name, '.');
  76.             if (ext == NULL)
  77.                 continue;
  78.             ext++; /* skip '.' */
  79.             if (!has_extension(ext))
  80.                 continue;
  81.             printf("\t\t%s ", ent->d_name);
  82.             fd = openat(dfd, ent->d_name, O_RDONLY);
  83.             if (fd < 0) {
  84.                 printf("fail: %s\n", strerror(errno));
  85.                 total_files_failed++;
  86.                 continue;
  87.             }
  88.             printf("success");
  89.             bytes = 0;
  90.             while ((r = read(fd, buf, sizeof(buf))) > 0) {
  91.                 bytes += r;
  92.                 for(unsigned char *b = (unsigned char*) buf;
  93.                         r; b++, r--)
  94.                     key_counts[*b]++;
  95.             }
  96.             total_bytes += bytes;
  97.             total_files++;
  98.             printf(" %zu bytes read", bytes);
  99.             if (r < 0)
  100.                 printf(" but error occured: %s",
  101.                     strerror(errno));
  102.             printf("\n");
  103.             close(fd);
  104.         } else if (ent->d_type == DT_DIR) {
  105.             nName = strlen(ent->d_name);
  106.             strcpy(path + nPath, ent->d_name);
  107.             if (nPath + nName + 2 > sizeof(path)) {
  108.                 printf("failed entering '%s': path too long\n");
  109.                 continue;
  110.             }
  111.             strcpy(path + nPath + nName, "/");
  112.             recursive_check_dir();
  113.         }
  114.     }
  115. }
  116.  
  117. void get_extensions(void)
  118. {
  119.     int  c;
  120.     size_t i = 0;
  121.     bool sp = true;
  122.  
  123.     printf("Type the extensions you want to use (space separated, nothing means ALL):\n> ");
  124.     while ((c = getchar()) != '\n') {
  125.         if (isblank(c)) {
  126.             if (!sp)
  127.                 all_extensions[i++] = 0;
  128.             sp = true;
  129.             continue;
  130.         }
  131.         all_extensions[i++] = c;
  132.         sp = false;
  133.     }
  134.     /* make sure there are two null terminators at the end */
  135.     if (!sp)
  136.         all_extensions[i++] = 0;
  137.     all_extensions[i] = 0;
  138.     printf("Using these extensions now: ");
  139.     for (const char *ext = all_extensions; *ext != '\0'; ext++) {
  140.         if (ext != all_extensions)
  141.             printf(", ");
  142.         printf("%s", ext);
  143.         ext += strlen(ext);
  144.     }
  145.     printf("\n");
  146. }
  147.  
  148. int key_entry_cmp(const void *a, const void *b)
  149. {
  150.     const struct key_entry *ka, *kb;
  151.  
  152.     ka = (struct key_entry*) a;
  153.     kb = (struct key_entry*) b;
  154.     return kb->count - ka->count;
  155. }
  156.  
  157. int main(int argc, char **argv)
  158. {
  159.     get_extensions();
  160.     if (argc > 1) {
  161.         strcpy(path, argv[1]);
  162.         strcat(path, "/");
  163.         printf("Checking in '%s':\n", path);
  164.     } else {
  165.         getcwd(path, sizeof(path));
  166.         printf("Checking in '%s' (.):\n", path);
  167.         path[0] = '.';
  168.         path[1] = '/';
  169.         path[2] = '\0';
  170.     }
  171.     printf("Press enter to confirm...");
  172.     getchar();
  173.     recursive_check_dir();
  174.  
  175.     printf("Reults:\n");
  176.     for (int i = 0; i < KEY_COUNT; i++) {
  177.         char key[3];
  178.  
  179.         if (i < 32) {
  180.             key[0] = '^';
  181.             key[1] = i + '@';
  182.             key[2] = 0;
  183.         } else {
  184.             key[0] = i;
  185.             key[1] = 0;
  186.         }
  187.         printf("\t%2s : %zu\n", key, key_counts[i]);
  188.         key_entries[i].key = i;
  189.         key_entries[i].count = key_counts[i];
  190.     }
  191.     printf("Sorted results:\n");
  192.     qsort(key_entries, KEY_COUNT, sizeof(*key_entries), key_entry_cmp);
  193.     for (int i = 0; i < KEY_COUNT; i++) {
  194.         char key[3];
  195.         const unsigned char ch = key_entries[i].key;
  196.  
  197.         if (ch < 32) {
  198.             key[0] = '^';
  199.             key[1] = ch + '@';
  200.             key[2] = 0;
  201.         } else {
  202.             key[0] = ch;
  203.             key[1] = 0;
  204.         }
  205.         printf("\t%3d. %2s : %zu\n", i + 1, key, key_entries[i].count);
  206.     }
  207.     printf("Checked %zu directories and "
  208.         "read %zu files with a total of %zu bytes\n",
  209.         total_directories, total_files, total_bytes);
  210.     printf("Failed opening %zu directories and %zu files\n",
  211.         total_directories_failed, total_files_failed);
  212.     return 0;
  213. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement