Skip to content

Instantly share code, notes, and snippets.

@Cxarli
Created February 2, 2019 13:00
Show Gist options
  • Save Cxarli/eaaaad7f540cd8ed6e050c0f52f95022 to your computer and use it in GitHub Desktop.
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
#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