|
|
@@ -1455,7 +1455,18 @@ _dir_list_cstr(const char *path, struct __dir_list_args args,
|
|
|
struct dirs empty = {0};
|
|
|
struct dirs dirs = {0};
|
|
|
|
|
|
- DIR *d = NULL;
|
|
|
+ struct ddata {
|
|
|
+ DIR *d;
|
|
|
+ const char *path;
|
|
|
+ };
|
|
|
+
|
|
|
+ struct {
|
|
|
+ struct ddata *data;
|
|
|
+ u64 size;
|
|
|
+ u64 cap;
|
|
|
+ } ds = {0};
|
|
|
+ u64 ds_i = 0;
|
|
|
+
|
|
|
struct dirent *de = NULL;
|
|
|
|
|
|
LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
|
|
|
@@ -1463,14 +1474,24 @@ _dir_list_cstr(const char *path, struct __dir_list_args args,
|
|
|
|
|
|
if ( out_err != NULL ) perr = out_err;
|
|
|
|
|
|
- d = opendir(path);
|
|
|
- if ( d == NULL ) {
|
|
|
- *perr = ERR_FAILED_OPENDIR;
|
|
|
- goto exit_err;
|
|
|
+ {
|
|
|
+ DIR *d = NULL;
|
|
|
+ d = opendir(path);
|
|
|
+ if ( d == NULL ) {
|
|
|
+ *perr = ERR_FAILED_OPENDIR;
|
|
|
+ goto exit_err;
|
|
|
+ }
|
|
|
+ DA_APPEND(ds, ((struct ddata) {.d=d, .path=path}), perr);
|
|
|
+ if ( *perr != ERR_OK ) goto exit_err;
|
|
|
}
|
|
|
|
|
|
errno = 0;
|
|
|
- de = readdir(d);
|
|
|
+
|
|
|
+_loop_ds:
|
|
|
+ if ( ds_i >= ds.size ) goto _end_loop_ds;
|
|
|
+ struct ddata dd = ds.data[ds_i++];
|
|
|
+
|
|
|
+ de = readdir(dd.d);
|
|
|
while ( de != NULL ) {
|
|
|
struct dir dir = {0};
|
|
|
|
|
|
@@ -1486,11 +1507,8 @@ _dir_list_cstr(const char *path, struct __dir_list_args args,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if ( args.recurse == true ) {
|
|
|
- }
|
|
|
-
|
|
|
dir.path = cstr_dup(
|
|
|
- temp_sprintf("%s/%s", path, de->d_name),
|
|
|
+ temp_sprintf("%s/%s", dd.path, de->d_name),
|
|
|
perr
|
|
|
);
|
|
|
if ( *perr != ERR_OK ) goto exit_err;
|
|
|
@@ -1503,24 +1521,49 @@ _dir_list_cstr(const char *path, struct __dir_list_args args,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if ( args.recurse == true ) {
|
|
|
+ if ( S_ISDIR(dir.stat.st_mode) ) {
|
|
|
+ DIR *d = opendir(dir.path);
|
|
|
+ if ( d == NULL ) {
|
|
|
+ *perr = ERR_FAILED_OPENDIR;
|
|
|
+ goto exit_err;
|
|
|
+ }
|
|
|
+
|
|
|
+ DA_APPEND(ds, ((struct ddata) {.d=d, .path=dir.path}), perr);
|
|
|
+ if ( *perr != ERR_OK ) goto exit_err;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
DA_APPEND(dirs, dir, perr);
|
|
|
if ( *perr != ERR_OK ) goto exit_err;
|
|
|
|
|
|
_continue:
|
|
|
- de = readdir(d);
|
|
|
+ de = readdir(dd.d);
|
|
|
}
|
|
|
-
|
|
|
if ( errno != 0 ) {
|
|
|
*perr = ERR_FAILED_READDIR;
|
|
|
goto exit_err;
|
|
|
}
|
|
|
|
|
|
- closedir(d);
|
|
|
+ if ( ds_i < ds.size ) goto _loop_ds;
|
|
|
+
|
|
|
+_end_loop_ds:
|
|
|
+
|
|
|
+ DA_FOREACH(ds, it) {
|
|
|
+ closedir(it->d);
|
|
|
+ }
|
|
|
+ LIB_FREE(ds.data);
|
|
|
|
|
|
*perr = ERR_OK;
|
|
|
return dirs;
|
|
|
exit_err:
|
|
|
- if ( d != NULL ) closedir(d);
|
|
|
+ if ( ds.data != NULL ) {
|
|
|
+ DA_FOREACH(ds, it) {
|
|
|
+ closedir(it->d);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ LIB_FREE(ds.data);
|
|
|
+
|
|
|
dir_list_destroy(&dirs, NULL);
|
|
|
return empty;
|
|
|
}
|