xdu/xdu.c
2026-03-23 12:38:40 -05:00

110 lines
2.3 KiB
C

#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/dirent.h>
#include <sys/stat.h>
#include <sys/syslimits.h>
/*
* Only a directory should be passed here currently as it's
* very naive.
*/
ssize_t sizeof_dir(const char *restrict path) {
DIR *dir = NULL;
char estr[LINE_MAX] = {'\0'};
struct dirent *de = NULL;
ssize_t sz = 0;
struct stat st;
int err = 0;
if ((dir = opendir(path)) == NULL) {
strerror_r(errno, estr, sizeof estr);
fprintf(stderr, "Error opening directory '%s': %s\n", path, estr);
return -1;
}
if (lstat(path, &st) != 0) {
strerror_r(errno, estr, sizeof estr);
fprintf(stderr, "Error callings stat on '%s': %s\n", path, estr);
closedir(dir);
return -1;
}
/* No tasks spawned yet, plain write is safe. */
sz += st.st_blocks * 512;
while ((de = readdir(dir)) != NULL) {
if ((strcmp(de->d_name, ".") == 0) || (strcmp(de->d_name, "..") == 0))
continue;
char fullpath[PATH_MAX];
snprintf(fullpath, sizeof fullpath, "%s/%s", path, de->d_name);
if (lstat(fullpath, &st) != 0) {
strerror_r(errno, estr, sizeof estr);
fprintf(stderr, "Error callings stat on '%s': %s\n", de->d_name, estr);
#pragma omp atomic write
err = 1;
break;
}
if (!S_ISDIR(st.st_mode)) {
#pragma omp atomic
sz += st.st_blocks * 512;
} else {
char *fp = strdup(fullpath);
if (!fp) {
fprintf(stderr, "strdup failed\n");
#pragma omp atomic write
err = 1;
break;
}
#pragma omp task firstprivate(fp) shared(sz, err)
{
ssize_t result = sizeof_dir(fp);
free(fp);
if (result == -1) {
#pragma omp atomic write
err = 1;
} else {
#pragma omp atomic
sz += result;
}
}
}
}
closedir(dir);
#pragma omp taskwait
return err ? -1 : sz;
}
/*
* Just a *possible* proof of concept.
*/
int main(int argc, char **argv) {
ssize_t sz = 0;
if (argc < 2) {
fprintf(stderr, "Insufficient arguments.\n");
exit(EXIT_FAILURE);
}
#pragma omp parallel
#pragma omp single
sz = sizeof_dir(argv[1]);
if (sz == -1)
fprintf(stderr, "Failed.\n");
printf("Size = %zd\n", sz);
return 0;
}