#include #include #include #include #include #include #include #include #include #include #include /* * 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; }