Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <ctype.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <dirent.h>
- #include <string.h>
- #include <stdbool.h>
- #define ARRLEN(a) (sizeof(a)/sizeof*(a))
- static char path[PATH_MAX];
- static char all_extensions[8192];
- #define KEY_COUNT 256
- static size_t key_counts[KEY_COUNT];
- struct key_entry {
- char key;
- size_t count;
- } key_entries[KEY_COUNT];
- static size_t total_bytes;
- static size_t total_files;
- static size_t total_directories;
- static size_t total_files_failed;
- static size_t total_directories_failed;
- bool has_extension(const char *ext)
- {
- if (all_extensions[0] == '\0')
- return true;
- for (const char *exts = all_extensions; *exts != '\0'; exts++) {
- size_t j = 0;
- for (; ext[j] != '\0'; exts++, j++)
- if (ext[j] != *exts)
- break;
- if (ext[j] == '\0' && *exts == '\0')
- return true;
- while (*exts != '\0')
- exts++;
- }
- return false;
- }
- void recursive_check_dir(void)
- {
- DIR *dir;
- int dfd;
- struct dirent *ent;
- int fd;
- char buf[1024];
- size_t nPath;
- ssize_t r;
- size_t bytes;
- size_t nName;
- const char *ext;
- dir = opendir(path);
- if (dir == NULL) {
- printf("could not open dir: %s\n", strerror(errno));
- total_directories_failed++;
- return;
- }
- dfd = dirfd(dir);
- total_directories++;
- printf("\tin: %s\n", path);
- nPath = strlen(path);
- while ((ent = readdir(dir)) != NULL) {
- if (ent->d_name[0] == '.')
- continue;
- if (ent->d_type == DT_REG && nName >= 2) {
- ext = strrchr(ent->d_name, '.');
- if (ext == NULL)
- continue;
- ext++; /* skip '.' */
- if (!has_extension(ext))
- continue;
- printf("\t\t%s ", ent->d_name);
- fd = openat(dfd, ent->d_name, O_RDONLY);
- if (fd < 0) {
- printf("fail: %s\n", strerror(errno));
- total_files_failed++;
- continue;
- }
- printf("success");
- bytes = 0;
- while ((r = read(fd, buf, sizeof(buf))) > 0) {
- bytes += r;
- for(unsigned char *b = (unsigned char*) buf;
- r; b++, r--)
- key_counts[*b]++;
- }
- total_bytes += bytes;
- total_files++;
- printf(" %zu bytes read", bytes);
- if (r < 0)
- printf(" but error occured: %s",
- strerror(errno));
- printf("\n");
- close(fd);
- } else if (ent->d_type == DT_DIR) {
- nName = strlen(ent->d_name);
- strcpy(path + nPath, ent->d_name);
- if (nPath + nName + 2 > sizeof(path)) {
- printf("failed entering '%s': path too long\n");
- continue;
- }
- strcpy(path + nPath + nName, "/");
- recursive_check_dir();
- }
- }
- }
- void get_extensions(void)
- {
- int c;
- size_t i = 0;
- bool sp = true;
- printf("Type the extensions you want to use (space separated, nothing means ALL):\n> ");
- while ((c = getchar()) != '\n') {
- if (isblank(c)) {
- if (!sp)
- all_extensions[i++] = 0;
- sp = true;
- continue;
- }
- all_extensions[i++] = c;
- sp = false;
- }
- /* make sure there are two null terminators at the end */
- if (!sp)
- all_extensions[i++] = 0;
- all_extensions[i] = 0;
- printf("Using these extensions now: ");
- for (const char *ext = all_extensions; *ext != '\0'; ext++) {
- if (ext != all_extensions)
- printf(", ");
- printf("%s", ext);
- ext += strlen(ext);
- }
- printf("\n");
- }
- int key_entry_cmp(const void *a, const void *b)
- {
- const struct key_entry *ka, *kb;
- ka = (struct key_entry*) a;
- kb = (struct key_entry*) b;
- return kb->count - ka->count;
- }
- int main(int argc, char **argv)
- {
- get_extensions();
- if (argc > 1) {
- strcpy(path, argv[1]);
- strcat(path, "/");
- printf("Checking in '%s':\n", path);
- } else {
- getcwd(path, sizeof(path));
- printf("Checking in '%s' (.):\n", path);
- path[0] = '.';
- path[1] = '/';
- path[2] = '\0';
- }
- printf("Press enter to confirm...");
- getchar();
- recursive_check_dir();
- printf("Reults:\n");
- for (int i = 0; i < KEY_COUNT; i++) {
- char key[3];
- if (i < 32) {
- key[0] = '^';
- key[1] = i + '@';
- key[2] = 0;
- } else {
- key[0] = i;
- key[1] = 0;
- }
- printf("\t%2s : %zu\n", key, key_counts[i]);
- key_entries[i].key = i;
- key_entries[i].count = key_counts[i];
- }
- printf("Sorted results:\n");
- qsort(key_entries, KEY_COUNT, sizeof(*key_entries), key_entry_cmp);
- for (int i = 0; i < KEY_COUNT; i++) {
- char key[3];
- const unsigned char ch = key_entries[i].key;
- if (ch < 32) {
- key[0] = '^';
- key[1] = ch + '@';
- key[2] = 0;
- } else {
- key[0] = ch;
- key[1] = 0;
- }
- printf("\t%3d. %2s : %zu\n", i + 1, key, key_entries[i].count);
- }
- printf("Checked %zu directories and "
- "read %zu files with a total of %zu bytes\n",
- total_directories, total_files, total_bytes);
- printf("Failed opening %zu directories and %zu files\n",
- total_directories_failed, total_files_failed);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement