#define _GNU_SOURCE #include "search.h" #include "ll.h" // Scan a directory // Sort inputs into files and folders // Store the full path for each file/folder // Search new folders #include #include #include #include #include #include #include #include #include #include int nodesort(const struct dirent *node, int (*S_IS_CALLBACK)(mode_t)) { // Ignore . and .. folders if(strcmp(node->d_name, ".") == 0 || strcmp(node->d_name, "..") == 0 || strcmp(node->d_name, ".config") == 0) return 0; // Stat the file struct stat sb; if(stat(node->d_name, &sb) < 0) { error(0, errno, "Couldn't stat file \"%s\"", node->d_name); return 0; } // Check if the mode is correct if((*S_IS_CALLBACK)(sb.st_mode)) return 1; // God I love function pointers // Not what is being checked for, exclude it return 0; } int S_ISDIR_WRAPPER(mode_t mode) { return S_ISDIR(mode); } int S_ISREG_WRAPPER(mode_t mode) { return (S_ISREG(mode) && !S_ISDIR(mode)); } int foldersort(const struct dirent *node) { return nodesort(node, S_ISDIR_WRAPPER); } int filesort(const struct dirent *node) { return nodesort(node, S_ISREG_WRAPPER); } struct nodelist* scanfolders(const char *STARTPATH, int (*cmp)(const struct dirent **, const struct dirent **)) { struct dirent **nodes = NULL; char *restoredir = NULL; restoredir = get_current_dir_name(); if(restoredir == NULL) { error(0, errno, "Couldn't get the current working dir to restore from later"); return NULL; } struct nodelist *scanner = nodelist_init(NULL), *holder = NULL, *start = scanner; scanner->fullpath = realpath(STARTPATH, NULL); for(; scanner != NULL; scanner = scanner->next) { if(chdir(scanner->fullpath) < 0) { error(0, errno, "Couldn't change to dir \"%s\". Skipping scan of that folder", scanner->fullpath); continue; } int n = scandir(scanner->fullpath, &nodes, foldersort, cmp); if(n >= 0) { for(int i = 0; i < n; i++) { holder = nodelist_init(NULL); holder->fullpath = realpath(nodes[i]->d_name, NULL); nodelist_append(scanner, holder); // Yeah this is slow but idk rn } } else { error(0, errno, "Couldn't open dir \"%s\"", scanner->fullpath); return NULL; } } if(chdir(restoredir) < 0) { error(0, errno, "Couldn't restore to proper working dir"); return NULL; } return start; } struct nodelist* scanfiles(const char *STARTPATH, int (*cmp)(const struct dirent **, const struct dirent **)) { struct nodelist *folders = NULL, *files = NULL, *start = files; folders = scanfolders(STARTPATH, cmp); struct dirent **nodes; int n = 0; char *restoredir = NULL; restoredir = get_current_dir_name(); if(restoredir == NULL) { error(0, errno, "Could not get path to current working dir"); nodelist_delete(folders); return NULL; } for(struct nodelist *p = folders; p != NULL; p = p->next) { if(chdir(p->fullpath) < 0) { error(0, errno, "Couldn't enter dir \"%s\", skipping...", p->fullpath); continue; } n = scandir(p->fullpath, &nodes, filesort, cmp); if(n >= 0) { for(int i = 0; i < n; i++) { if(files == NULL) { files = nodelist_init(NULL); start = files; } files->fullpath = realpath(nodes[i]->d_name, NULL); printf("%s\n", files->fullpath); files->next = nodelist_init(NULL); files = files->next; } } else { error(0, errno, "Could not scan dir \"%s\", skipping...", p->fullpath); continue; } } return start; } /* int main(void) { struct nodelist *files = scanfiles("./", alphasort); printf("\nafter scan\n"); for(struct nodelist *p = files; p != NULL; p = p->next) { if(p->fullpath != NULL) // Annoying extra "null" entry at the end of the list printf("%s\n", p->fullpath); } return 0; } */