From 02e2bb0b93a32c4684cb8e3181e6d107f6bfcdd6 Mon Sep 17 00:00:00 2001 From: mazze Date: Sat, 14 Jan 2017 13:38:54 +0000 Subject: [PATCH] POSIX functions scandir() and alphasort() implemented. git-svn-id: https://svn.aros.org/svn/aros/trunk/AROS@53210 fb15a70f-31f2-0310-bbcc-cdcc74a49acc --- compiler/posixc/alphasort.c | 43 +++++++++ compiler/posixc/include/aros/posixc/dirent.h | 8 +- compiler/posixc/mmakefile.src | 2 + compiler/posixc/posixc.conf | 6 +- compiler/posixc/scandir.c | 125 +++++++++++++++++++++++++++ test/clib/mmakefile.src | 1 + test/clib/scandir.c | 48 ++++++++++ 7 files changed, 225 insertions(+), 8 deletions(-) create mode 100644 compiler/posixc/alphasort.c create mode 100644 compiler/posixc/scandir.c create mode 100644 test/clib/scandir.c diff --git a/compiler/posixc/alphasort.c b/compiler/posixc/alphasort.c new file mode 100644 index 0000000000..f4a1cf76aa --- /dev/null +++ b/compiler/posixc/alphasort.c @@ -0,0 +1,43 @@ +/* + Copyright © 1995-2017, The AROS Development Team. All rights reserved. + $Id$ + + POSIX.1-2008 function alphasort(). +*/ + +#include + +/***************************************************************************** + + NAME */ +#include + + int alphasort ( + +/* SYNOPSIS */ + const struct dirent **a, + const struct dirent **b + ) + +/* FUNCTION + Support function for scandir(). + + INPUTS + + RESULT + + NOTES + + EXAMPLE + + BUGS + + SEE ALSO + scandir() + + INTERNALS + +******************************************************************************/ +{ + return strcoll((*a)->d_name, (*b)->d_name); +} diff --git a/compiler/posixc/include/aros/posixc/dirent.h b/compiler/posixc/include/aros/posixc/dirent.h index 15d8132c91..6212bb2d93 100644 --- a/compiler/posixc/include/aros/posixc/dirent.h +++ b/compiler/posixc/include/aros/posixc/dirent.h @@ -2,7 +2,7 @@ #define _POSIXC_DIRENT_H_ /* - Copyright © 1995-2012, The AROS Development Team. All rights reserved. + Copyright © 1995-2017, The AROS Development Team. All rights reserved. $Id$ Desc: POSIX.1-2008 header file dirent.h @@ -53,7 +53,7 @@ typedef struct __dirdesc DIR; __BEGIN_DECLS -/* NOTIMPL int alphasort(const struct dirent **a, const struct dirent **b); */ +int alphasort(const struct dirent **a, const struct dirent **b); int closedir(DIR *dir); int dirfd(DIR *dir); /* NOTIMPL DIR *fdopendir(int); */ @@ -61,9 +61,9 @@ DIR *opendir(const char *filename); struct dirent *readdir(DIR *dir); /* NOTIMPL int readdir_r(DIR *restrict, struct dirent *restrict, struct dirent **restrict); */ void rewinddir(DIR *dir); -/* NOTIMPL int scandir (const char *dir, struct dirent ***namelist, +int scandir (const char *dir, struct dirent ***namelist, int (*select)(const struct dirent *), - int (*compar)(const struct dirent **, const struct dirent **)); */ + int (*compar)(const struct dirent **, const struct dirent **)); void seekdir(DIR *dir, off_t loc); long telldir(DIR *dir); diff --git a/compiler/posixc/mmakefile.src b/compiler/posixc/mmakefile.src index 1d4ebc8d68..4f09f1d1d7 100644 --- a/compiler/posixc/mmakefile.src +++ b/compiler/posixc/mmakefile.src @@ -18,6 +18,7 @@ POSIXC := \ __upath \ __vfork \ access \ + alphasort \ basename \ cfgetispeed \ cfgetospeed \ @@ -138,6 +139,7 @@ POSIXC := \ rewind \ rewinddir \ rmdir \ + scandir \ scanf \ seed48 \ seekdir \ diff --git a/compiler/posixc/posixc.conf b/compiler/posixc/posixc.conf index b2db27a621..962bbc1c2f 100644 --- a/compiler/posixc/posixc.conf +++ b/compiler/posixc/posixc.conf @@ -108,8 +108,7 @@ void __posixc_assert (const char *, const char *, unsigned int) #int _tolower(int) # # * dirent.h -.skip 1 -#int alphasort(const struct dirent **a, const struct dirent **b) +int alphasort(const struct dirent **a, const struct dirent **b) int closedir(DIR *dir) int dirfd(DIR *dir) .skip 1 @@ -119,8 +118,7 @@ struct dirent *readdir(DIR *dir) .skip 1 #int readdir_r(DIR *restrict, struct dirent *restrict, struct dirent **restrict) void rewinddir(DIR *dir) -.skip 1 -#int scandir (const char *dir, struct dirent ***namelist, int (*select)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **)) +int scandir (const char *dir, struct dirent ***namelist, int (*select)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **)) void seekdir(DIR *dir, off_t loc) long telldir(DIR *dir) # diff --git a/compiler/posixc/scandir.c b/compiler/posixc/scandir.c new file mode 100644 index 0000000000..d814570ca0 --- /dev/null +++ b/compiler/posixc/scandir.c @@ -0,0 +1,125 @@ +/* + Copyright © 1995-2017, The AROS Development Team. All rights reserved. + $Id$ + + POSIX.1-2008 function scandir(). +*/ + +#include +#include +#include + +/***************************************************************************** + + NAME */ +#include + + int scandir ( + +/* SYNOPSIS */ + const char *dir, + struct dirent ***namelist, + int (*select)(const struct dirent *), + int (*compar)(const struct dirent **, const struct dirent **) + ) + +/* FUNCTION + Scan directory + + INPUTS + dir - Directory to be scanned + namelist - Array with the found entries. + select - Filter function which must return non-zero if entry shall be + added. If NULL all entries will be added. + compar - Function which will be used by qsort() for sorting of the + entries. The function alphasort() can be used for sorting + in alphabetical oder. If NULL sorting order isn't specified. + + RESULT + Number of entries + + NOTES + + EXAMPLE + + BUGS + + SEE ALSO + alphasort() + + INTERNALS + +******************************************************************************/ +{ + DIR *dirp = NULL; + struct dirent *dp; + struct dirent *newdp; + int cnt = 0; + struct dirent **darr = NULL; + struct dirent **newdarr; + int arrcnt = 0; + int selected; + int olderrno; + + errno = 0; + + if ((dirp = opendir(dir)) == NULL) + { + goto fail; + } + + do + { + if ((dp = readdir(dirp)) != NULL) + { + selected = 0; + if (select != NULL) + { + olderrno = errno; + selected = select(dp); + errno = olderrno; + } + if ((select == NULL) || selected) + { + if ((darr == NULL) || cnt >= arrcnt) + { + arrcnt += 50; + newdarr = realloc(darr, arrcnt * sizeof(*darr)); + if (newdarr == NULL) + { + goto fail; + } + darr = newdarr; + } + newdp = malloc(sizeof(*newdp)); + if (newdp == NULL) + { + goto fail; + } + memcpy(newdp, dp, sizeof(*newdp)); + darr[cnt] = newdp; + cnt++; + } + } + } while (dp != NULL); + + closedir(dirp); + + if (compar != NULL) + { + olderrno = errno; + qsort (darr, cnt, sizeof (*darr), (int (*) (const void *, const void *)) compar); + errno = olderrno; + } + *namelist = darr; + return cnt; + +fail: + while (cnt > 0) + { + free(darr[--cnt]); + } + free(darr); + closedir(dirp); + return -1; +} diff --git a/test/clib/mmakefile.src b/test/clib/mmakefile.src index b1d434a3bf..b121f40f88 100644 --- a/test/clib/mmakefile.src +++ b/test/clib/mmakefile.src @@ -29,6 +29,7 @@ FILES := \ raise \ random \ randtest \ + scandir \ setjmp \ snprintf \ sprintf \ diff --git a/test/clib/scandir.c b/test/clib/scandir.c new file mode 100644 index 0000000000..9f7fb6c7c7 --- /dev/null +++ b/test/clib/scandir.c @@ -0,0 +1,48 @@ +/* + Copyright © 1995-2017, The AROS Development Team. All rights reserved. + $Id$ +*/ + +#include +#include +#include +#include + +int filter(const struct dirent *de) +{ + return !strcmp(de->d_name, "T"); +} + +void testscandir(const char *dir, + int (*select)(const struct dirent *), + int (*compar)(const struct dirent **, const struct dirent **)) +{ + int i; + struct dirent **namelist; + + printf("\nscandir dir %s filter %p sort %p\n", dir, select, compar); + + int res = scandir(dir, &namelist, select, compar); + printf("result %d\n", res); + if (res < 0) + { + perror("scandir"); + } + else + { + for (i=0 ; i < res ; i++) + { + printf("%d %s\n", i, namelist[i]->d_name); + free(namelist[i]); + } + free(namelist); + } +} + +int main(void) +{ + testscandir("ram:", NULL, NULL); + testscandir("ram:", NULL, alphasort); + testscandir("ram:", filter, NULL); + return 0; +} -- 2.11.4.GIT