libroot: Replace scandir, alphasort implementations with musl's.

Notably alphasort actually uses strcoll not strcmp, so this does
affect behavior. scandir should be the same.
This commit is contained in:
Augustin Cavalier
2022-09-27 17:28:46 -04:00
parent d2d46658d7
commit 1b72036bef
5 changed files with 72 additions and 82 deletions
-82
View File
@@ -308,85 +308,3 @@ dirfd(DIR* dir)
{
return dir->fd;
}
int
alphasort(const struct dirent** entry1, const struct dirent** entry2)
{
return strcmp((*entry1)->d_name, (*entry2)->d_name);
}
int
scandir(const char* path, struct dirent*** _entryArray,
int (*selectFunc)(const struct dirent*),
int (*compareFunc)(const struct dirent** entry1,
const struct dirent** entry2))
{
struct dirent** array = NULL;
size_t arrayCapacity = 0;
size_t arrayCount = 0;
DIR* dir = opendir(path);
if (dir == NULL)
return -1;
while (true) {
struct dirent* copiedEntry;
struct dirent* entry = readdir(dir);
if (entry == NULL)
break;
// Check whether or not we should include this entry
if (selectFunc != NULL && !selectFunc(entry))
continue;
copiedEntry = malloc(entry->d_reclen);
if (copiedEntry == NULL)
goto error;
memcpy(copiedEntry, entry, entry->d_reclen);
// Put it into the array
if (arrayCount == arrayCapacity) {
struct dirent** newArray;
// Enlarge array
if (arrayCapacity == 0)
arrayCapacity = 64;
else
arrayCapacity *= 2;
newArray = realloc(array, arrayCapacity * sizeof(void*));
if (newArray == NULL) {
free(copiedEntry);
goto error;
}
array = newArray;
}
array[arrayCount++] = copiedEntry;
}
closedir(dir);
if (arrayCount > 0 && compareFunc != NULL) {
qsort(array, arrayCount, sizeof(void*),
(int (*)(const void*, const void*))compareFunc);
}
*_entryArray = array;
return arrayCount;
error:
closedir(dir);
while (arrayCount-- > 0)
free(array[arrayCount]);
free(array);
return -1;
}
+2
View File
@@ -7,6 +7,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
MergeObjectFromObjects <$(architecture)>posix_musl.o :
:
<$(architecture)>posix_musl_dirent.o
<$(architecture)>posix_musl_math.o
<$(architecture)>posix_musl_misc.o
<$(architecture)>posix_musl_regex.o
@@ -22,6 +23,7 @@ for arch in $(TARGET_ARCHS) {
HaikuSubInclude math $(arch) ;
}
HaikuSubInclude dirent ;
HaikuSubInclude misc ;
HaikuSubInclude regex ;
HaikuSubInclude search ;
@@ -0,0 +1,17 @@
SubDir HAIKU_TOP src system libroot posix musl dirent ;
SubDirSysHdrs [ FDirName $(SUBDIR) .. include ] ;
UseHeaders [ FDirName $(SUBDIR) .. internal ] ;
UseHeaders [ FDirName $(SUBDIR) .. arch $(TARGET_ARCH) ] ;
local architectureObject ;
for architectureObject in [ MultiArchSubDirSetup ] {
on $(architectureObject) {
local architecture = $(TARGET_PACKAGING_ARCH) ;
MergeObject <$(architecture)>posix_musl_dirent.o :
alphasort.c
scandir.c
;
}
}
@@ -0,0 +1,7 @@
#include <string.h>
#include <dirent.h>
int alphasort(const struct dirent **a, const struct dirent **b)
{
return strcoll((*a)->d_name, (*b)->d_name);
}
@@ -0,0 +1,46 @@
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#include <stddef.h>
int scandir(const char *path, struct dirent ***res,
int (*sel)(const struct dirent *),
int (*cmp)(const struct dirent **, const struct dirent **))
{
DIR *d;
struct dirent *de, **names=0, **tmp;
size_t cnt=0, len=0;
int old_errno = errno;
d = opendir(path);
if (!d) return -1;
while ((errno=0), (de = readdir(d))) {
if (sel && !sel(de)) continue;
if (cnt >= len) {
len = 2*len+1;
if (len > SIZE_MAX/sizeof *names) break;
tmp = realloc(names, len * sizeof *names);
if (!tmp) break;
names = tmp;
}
names[cnt] = malloc(de->d_reclen);
if (!names[cnt]) break;
memcpy(names[cnt++], de, de->d_reclen);
}
closedir(d);
if (errno) {
if (names) while (cnt-->0) free(names[cnt]);
free(names);
return -1;
}
errno = old_errno;
if (cmp) qsort(names, cnt, sizeof *names, (int (*)(const void *, const void *))cmp);
*res = names;
return cnt;
}