Last active
October 17, 2022 21:48
-
-
Save flatcap/f0ee75ee26b30a8cade75c37b55419b5 to your computer and use it in GitHub Desktop.
Directory Traversal
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* We want POSIX.1-2008 + XSI, i.e. SuSv4, features */ | |
#define _XOPEN_SOURCE 700 | |
/* Added on 2017-06-25: | |
If the C library can support 64-bit file sizes | |
and offsets, using the standard names, | |
these defines tell the C library to do so. */ | |
#define _LARGEFILE64_SOURCE | |
#define _FILE_OFFSET_BITS 64 | |
#include <errno.h> | |
#include <ftw.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <time.h> | |
#include <unistd.h> | |
/* POSIX.1 says each process has at least 20 file descriptors. | |
* Three of those belong to the standard streams. | |
* Here, we use a conservative estimate of 15 available; | |
* assuming we use at most two for other uses in this program, | |
* we should never run into any problems. | |
* Most trees are shallower than that, so it is efficient. | |
* Deeper trees are traversed fine, just a bit slower. | |
* (Linux allows typically hundreds to thousands of open files, | |
* so you'll probably never see any issues even if you used | |
* a much higher value, say a couple of hundred, but | |
* 15 is a safe, reasonable value.) | |
*/ | |
#ifndef USE_FDS | |
#define USE_FDS 15 | |
#endif | |
int print_entry(const char *filepath, const struct stat *info, | |
const int typeflag, struct FTW *pathinfo) | |
{ | |
/* const char *const filename = filepath + pathinfo->base; */ | |
const double bytes = (double) info->st_size; /* Not exact if large! */ | |
struct tm mtime; | |
localtime_r(&(info->st_mtime), &mtime); | |
printf("%04d-%02d-%02d %02d:%02d:%02d", mtime.tm_year + 1900, mtime.tm_mon + 1, | |
mtime.tm_mday, mtime.tm_hour, mtime.tm_min, mtime.tm_sec); | |
if (bytes >= 1099511627776.0) | |
printf(" %9.3f TiB", bytes / 1099511627776.0); | |
else if (bytes >= 1073741824.0) | |
printf(" %9.3f GiB", bytes / 1073741824.0); | |
else if (bytes >= 1048576.0) | |
printf(" %9.3f MiB", bytes / 1048576.0); | |
else if (bytes >= 1024.0) | |
printf(" %9.3f KiB", bytes / 1024.0); | |
else | |
printf(" %9.0f B ", bytes); | |
if (typeflag == FTW_SL) | |
{ | |
char *target; | |
size_t maxlen = 1023; | |
ssize_t len; | |
while (1) | |
{ | |
target = malloc(maxlen + 1); | |
if (target == NULL) | |
return ENOMEM; | |
len = readlink(filepath, target, maxlen); | |
if (len == (ssize_t) -1) | |
{ | |
const int saved_errno = errno; | |
free(target); | |
return saved_errno; | |
} | |
if (len >= (ssize_t) maxlen) | |
{ | |
free(target); | |
maxlen += 1024; | |
continue; | |
} | |
target[len] = '\0'; | |
break; | |
} | |
printf(" %s -> %s\n", filepath, target); | |
free(target); | |
} | |
else if (typeflag == FTW_SLN) | |
printf(" %s (dangling symlink)\n", filepath); | |
else if (typeflag == FTW_F) | |
printf(" %s\n", filepath); | |
else if (typeflag == FTW_D || typeflag == FTW_DP) | |
printf(" %s/\n", filepath); | |
else if (typeflag == FTW_DNR) | |
printf(" %s/ (unreadable)\n", filepath); | |
else | |
printf(" %s (unknown)\n", filepath); | |
return 0; | |
} | |
int print_directory_tree(const char *const dirpath) | |
{ | |
int result; | |
/* Invalid directory path? */ | |
if (dirpath == NULL || *dirpath == '\0') | |
return errno = EINVAL; | |
result = nftw(dirpath, print_entry, USE_FDS, FTW_PHYS); | |
if (result >= 0) | |
errno = result; | |
return errno; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
int arg; | |
if (argc < 2) | |
{ | |
if (print_directory_tree(".")) | |
{ | |
fprintf(stderr, "%s.\n", strerror(errno)); | |
return EXIT_FAILURE; | |
} | |
} | |
else | |
{ | |
for (arg = 1; arg < argc; arg++) | |
{ | |
if (print_directory_tree(argv[arg])) | |
{ | |
fprintf(stderr, "%s.\n", strerror(errno)); | |
return EXIT_FAILURE; | |
} | |
} | |
} | |
return EXIT_SUCCESS; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _XOPEN_SOURCE 500 | |
#include <ftw.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
static int display_info(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf) | |
{ | |
printf("%-3s %2d ", | |
(tflag == FTW_D) ? "d" : | |
(tflag == FTW_DNR) ? | |
"dnr" : | |
(tflag == FTW_DP) ? | |
"dp" : | |
(tflag == FTW_F) ? | |
"f" : | |
(tflag == FTW_NS) ? | |
"ns" : | |
(tflag == FTW_SL) ? "sl" : (tflag == FTW_SLN) ? "sln" : "???", | |
ftwbuf->level); | |
if (tflag == FTW_NS) | |
printf("-------"); | |
else | |
printf("%7jd", (intmax_t) sb->st_size); | |
printf(" %-40s %d %s\n", fpath, ftwbuf->base, fpath + ftwbuf->base); | |
return 0; /* To tell nftw() to continue */ | |
} | |
int main(int argc, char *argv[]) | |
{ | |
int flags = 0; | |
if (argc > 2 && strchr(argv[2], 'd') != NULL) | |
flags |= FTW_DEPTH; | |
if (argc > 2 && strchr(argv[2], 'p') != NULL) | |
flags |= FTW_PHYS; | |
if (nftw((argc < 2) ? "." : argv[1], display_info, 20, flags) == -1) | |
{ | |
perror("nftw"); | |
exit(EXIT_FAILURE); | |
} | |
exit(EXIT_SUCCESS); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <dirent.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
void listdir(const char *name, int indent) | |
{ | |
DIR *dir; | |
struct dirent *entry; | |
if (!(dir = opendir(name))) | |
return; | |
while ((entry = readdir(dir)) != NULL) | |
{ | |
if (entry->d_type == DT_DIR) | |
{ | |
char path[1024]; | |
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) | |
continue; | |
snprintf(path, sizeof(path), "%s/%s", name, entry->d_name); | |
printf("%*s[%s]\n", indent, "", entry->d_name); | |
listdir(path, indent + 2); | |
} | |
else | |
{ | |
printf("%*s- %s\n", indent, "", entry->d_name); | |
} | |
} | |
closedir(dir); | |
} | |
int main(void) | |
{ | |
listdir(".", 0); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment