/*************************************************************************/ /* Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 */ /*************************************************************************/ /* */ /* depthFirstTraversal */ /* */ /* A non recursive depth first traversal of a directory tree useful in */ /* the event that the stack size is limited relative to the heap size. */ /* */ /*************************************************************************/ #include #include #include #include #include #include #include #include "stringQueue.h" #ifndef S_ISDIR #define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR) #endif /*************************************************************************/ /* Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 */ /*************************************************************************/ /* Concatenates two filesystem paths a and b together. */ /*************************************************************************/ char *pathCombine(char *a, char *b) { size_t sa = strlen(a); size_t sb = strlen(b); char *rt = (char*)calloc(sa + sb + 1, sizeof(char *)); memcpy(rt, a, sa); switch (a[sa - 1]) { case '/': break; default: rt = (char*)realloc(rt, (strlen(rt) + 1) * sizeof(char *)); rt[sa] = '/'; break; } memcpy(rt + strlen(rt), b, sb + 1); return rt; } int main(int argc, char **argv) { DIR *dir; struct dirent *de; struct stat st; stringQueue *dirQueue = stringQueueCreate(1); char *path; char *file; if (argc != 2) { printf("Syntax: %s [DIRECTORY]\n", argv[0]); return 1; } /* Enqueue the current working directory path. */ stringQueueEnqueue(dirQueue, strdup(argv[1])); /* While there are still directories to be processed. */ while ((path = stringQueueDequeue(dirQueue)) != NULL) { /* If we cannot open a directory, warn and continue. */ if ((dir = opendir(path)) == NULL) { printf("Unable to open directory: %s\n", path); continue; } /* Read the contents of the current directory. */ while ((de = readdir(dir))) { /* Combine path with file. */ file = pathCombine(path, de->d_name); /* If we fail to get the stats for the file, skip it. */ if(stat(file, &st) != 0) { free(file); continue; } /* If the file is not a directory, skip it. */ if(!S_ISDIR(st.st_mode)) { free(file); continue; } /* If the directory starts with "." or "..", then skip it. */ if(strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) { free(file); continue; } /* Print the directory. */ printf("Directory: %s\n", file); /* Enqueue the directory. */ stringQueueEnqueue(dirQueue, file); /* And release the file. */ free(file); } /* And close the directory. */ closedir(dir); } return 0; }