110 lines
2.3 KiB
C
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;
|
|
}
|