#include "stderr.h" #include #include #include #include #include #include #include int main(int argc, char **argv) { err_setarg0(argv[0]); if (argc != 2) err_usage("directory"); struct stat sb; char *name = argv[1]; if (stat(name, &sb) != 0) err_syserr("Unable to stat directory '%s': ", name); if (!S_ISDIR(sb.st_mode)) err_error("File '%s' is not a directory (mode = %o)\n", name, sb.st_mode); size_t bufmax = 4096; char *buffer = malloc(bufmax); if (buffer == 0) err_syserr("Failed to malloc %zu bytes: ", bufmax); strcpy(buffer, name); size_t buflen = strlen(buffer); assert(buflen < bufmax); size_t levels = 0; while (buflen < bufmax) { if (chdir(name) != 0) { err_sysrem("Failed to chdir into '%s'\n", name); err_remark("%3zu (%4zu): %s\n", ++levels, buflen, buffer); err_error("Mode = %o\n", sb.st_mode); } printf("%3zu (%4zu): %s\n", ++levels, buflen, buffer); DIR *dp = opendir("."); struct dirent *nm; while ((nm = readdir(dp)) != 0) { if (strcmp(nm->d_name, ".") == 0 || strcmp(nm->d_name, "..") == 0) continue; if (stat(nm->d_name, &sb) != 0) err_syserr("Unable to stat name '%s': ", nm->d_name); if (!S_ISDIR(sb.st_mode)) { err_sysrem("Name '%s' is not a directory (mode = %o)\n", nm->d_name, sb.st_mode); if (unlink(nm->d_name) != 0) err_syserr("Failed to remove non-directory '%s': ", nm->d_name); err_remark("Removed '%s' from '%s'\n", nm->d_name, buffer); continue; } size_t namlen = strlen(nm->d_name); if (buflen + namlen + 1 >= bufmax) { err_remark("Allocate space - name is too long: additional name '%s' - (%zu levels) %zu '%s'\n", nm->d_name, levels, buflen, buffer); size_t newmax = 2 * bufmax; char *newbuf = realloc(buffer, newmax); if (newbuf == 0) err_syserr("Failed to reallocate %zu bytes memory: ", newmax); bufmax = newmax; buffer = newbuf; } buffer[buflen++] = '/'; strcpy(&buffer[buflen], nm->d_name); name = &buffer[buflen]; buflen += namlen; break; } closedir(dp); } return 0; }