Created
February 2, 2019 13:00
-
-
Save Cxarli/eaaaad7f540cd8ed6e050c0f52f95022 to your computer and use it in GitHub Desktop.
Make a single file with the filesize, name and modification time of all files in the given directory
This file contains 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 <stdio.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <dirent.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <stdlib.h> | |
void printdirent(struct dirent *entry, int parent_fd, char *parent_name); | |
void collect(char *dirname, int parent_fd, char *parent_name); | |
void printdirent(struct dirent *entry, int parent_fd, char *parent_name) | |
{ | |
// Get entryname | |
char *name = entry->d_name; | |
// Get some stats such as size and modification time | |
struct stat statbuf; | |
if (fstatat(parent_fd, name, &statbuf, AT_SYMLINK_NOFOLLOW) == -1) { | |
fprintf(stderr, "lstat failed for %s: %s\n", name, strerror(errno)); | |
return; | |
} | |
off_t size = statbuf.st_size; | |
struct timespec modiftime = statbuf.st_mtim; | |
unsigned mode = statbuf.st_mode; | |
char *type = S_ISREG(mode) ? "REG" : S_ISDIR(mode) ? "DIR" : S_ISLNK(mode) ? "LNK" : "UNK"; | |
// Print all stats | |
printf("size=%ld\1mtime=%lu\1type=%s\1path=%s\1name=%s\n", | |
size, modiftime.tv_sec, type, parent_name, name); | |
} | |
void collect(char *dirname, int parent_fd, char *parent_name) | |
{ | |
// Open FD for directory | |
int dir_fd = openat(parent_fd, dirname, O_DIRECTORY | O_RDONLY); | |
if (dir_fd == -1) { | |
fprintf(stderr, "open failed for %s%s: %s\n", parent_name, dirname, strerror(errno)); | |
return; | |
} | |
// Get DIR struct for directory | |
DIR *dir = fdopendir(dir_fd); | |
if (dir == NULL) { | |
fprintf(stderr, "opendir failed for %s%s: %s\n", parent_name, dirname, strerror(errno)); | |
return; | |
} | |
// Current directory string | |
char *dirstr = malloc(1024 * sizeof(*dirstr)); | |
strncpy(dirstr, parent_name, 1024); | |
strncat(dirstr, dirname, 1024); | |
strncat(dirstr, "/", 1024); | |
// Loop over all entries in directory | |
struct dirent *stats; | |
while ((stats = readdir(dir)) != NULL) { | |
// Ignore . and .. | |
if (strcmp(stats->d_name, ".") == 0 || strcmp(stats->d_name, "..") == 0) continue; | |
// Print stats for current entry | |
printdirent(stats, dir_fd, dirstr); | |
// If directory: recurse | |
if (stats->d_type == DT_DIR) { | |
collect(stats->d_name, dir_fd, dirstr); | |
} | |
} | |
// Clean up all resources | |
free(dirstr); | |
closedir(dir); | |
close(dir_fd); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
// Ignore program name | |
--argc; ++argv; | |
// Get directory name from first argument or default . | |
char *dirname = "."; | |
if (argc > 0) { | |
dirname = argv[0]; | |
} | |
collect(dirname, AT_FDCWD, ""); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment