-
Notifications
You must be signed in to change notification settings - Fork 7.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feature/scandir' into 'master'
feat(newlib): implement scandir and alphasort Closes IDF-2649 See merge request espressif/esp-idf!28068
- Loading branch information
Showing
4 changed files
with
176 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <dirent.h> | ||
#include "esp_check.h" | ||
#include "esp_log.h" | ||
|
||
static const char *TAG = "scandir"; | ||
|
||
int alphasort(const struct dirent **lhs, const struct dirent **rhs) | ||
{ | ||
return strcoll((*lhs)->d_name, (*rhs)->d_name); | ||
} | ||
|
||
int scandir(const char *dirname, struct dirent ***out_dirlist, | ||
int (*select_func)(const struct dirent *), | ||
int (*cmp_func)(const struct dirent **, const struct dirent **)) | ||
{ | ||
DIR *dir_ptr = NULL; | ||
struct dirent *entry; | ||
size_t num_entries = 0; | ||
size_t array_size = 8; /* initial estimate */ | ||
struct dirent **entries = NULL; | ||
int ret = -1; | ||
|
||
entries = malloc(array_size * sizeof(struct dirent *)); | ||
ESP_RETURN_ON_FALSE(entries, -1, TAG, "Malloc failed for entries"); | ||
|
||
dir_ptr = opendir(dirname); | ||
ESP_GOTO_ON_FALSE(dir_ptr, -1, out, TAG, "Failed to open directory: %s", dirname); | ||
|
||
while ((entry = readdir(dir_ptr)) != NULL) { | ||
/* skip entries that don't match the filter function */ | ||
if (select_func != NULL && !select_func(entry)) { | ||
continue; | ||
} | ||
|
||
struct dirent *entry_copy = malloc(sizeof(struct dirent)); | ||
ESP_GOTO_ON_FALSE(entry_copy, -1, out, TAG, "Malloc failed for entry_copy"); | ||
|
||
*entry_copy = *entry; | ||
entries[num_entries++] = entry_copy; | ||
|
||
/* grow the array size if it's full */ | ||
if (num_entries >= array_size) { | ||
array_size *= 2; | ||
struct dirent **new_entries = realloc(entries, array_size * sizeof(struct dirent *)); | ||
ESP_GOTO_ON_FALSE(new_entries, -1, out, TAG, "Realloc failed for entries"); | ||
entries = new_entries; | ||
} | ||
} | ||
|
||
/* sort the entries if a comparison function is provided */ | ||
if (num_entries && cmp_func) { | ||
qsort(entries, num_entries, sizeof(struct dirent *), | ||
(int (*)(const void *, const void *))cmp_func); | ||
} | ||
|
||
*out_dirlist = entries; | ||
ret = num_entries; | ||
|
||
out: | ||
if (ret < 0) { | ||
while (num_entries > 0) { | ||
free(entries[--num_entries]); | ||
} | ||
free(entries); | ||
} | ||
if (dir_ptr) { | ||
closedir(dir_ptr); | ||
} | ||
return ret; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters