From 80a21be075c570bb82bc3a2ed9d805daa35f926b Mon Sep 17 00:00:00 2001 From: Jeff Johnston Date: Fri, 26 Jul 2002 21:44:34 +0000 Subject: 2002-07-26 Jeff Johnston * libc/include/sys/param.h (MAX, MIN): Added macros. * libc/sys/linux/Makefile.am: Add new files. * libc/sys/linux/Makefile.in: Regenerated. * libc/sys/linux/sys/stat.h: Add *stat64 prototypes. * libc/sys/linux/inode.c (fchdir): Added syscall. * libc/sys/linux/ftw.c: New file. * libc/sys/linux/ftw64.c: Ditto. * libc/sys/linux/getwd.c: Ditto. * libc/sys/linux/scandir64.c: Ditto. * libc/sys/linux/strverscmp.c: Ditto. * libc/sys/linux/versionsort.c: Ditto. * libc/sys/linux/versionsort64.c: Ditto. --- newlib/libc/sys/linux/Makefile.am | 7 + newlib/libc/sys/linux/Makefile.in | 97 +++--- newlib/libc/sys/linux/ftw.c | 640 ++++++++++++++++++++++++++++++++++ newlib/libc/sys/linux/ftw64.c | 30 ++ newlib/libc/sys/linux/getwd.c | 20 ++ newlib/libc/sys/linux/inode.c | 1 + newlib/libc/sys/linux/scandir64.c | 176 ++++++++++ newlib/libc/sys/linux/strverscmp.c | 113 ++++++ newlib/libc/sys/linux/sys/stat.h | 6 +- newlib/libc/sys/linux/versionsort.c | 11 + newlib/libc/sys/linux/versionsort64.c | 11 + 11 files changed, 1066 insertions(+), 46 deletions(-) create mode 100644 newlib/libc/sys/linux/ftw.c create mode 100644 newlib/libc/sys/linux/ftw64.c create mode 100644 newlib/libc/sys/linux/getwd.c create mode 100644 newlib/libc/sys/linux/scandir64.c create mode 100644 newlib/libc/sys/linux/strverscmp.c create mode 100644 newlib/libc/sys/linux/versionsort.c create mode 100644 newlib/libc/sys/linux/versionsort64.c (limited to 'newlib/libc/sys') diff --git a/newlib/libc/sys/linux/Makefile.am b/newlib/libc/sys/linux/Makefile.am index d79536201..5d50b0b71 100644 --- a/newlib/libc/sys/linux/Makefile.am +++ b/newlib/libc/sys/linux/Makefile.am @@ -30,6 +30,8 @@ LIB_SOURCES = \ fstatvfs.c \ fstatvfs64.c \ ftok.c \ + ftw.c \ + ftw64.c \ funlockfile.c \ getdate.c \ getdate_err.c \ @@ -37,6 +39,7 @@ LIB_SOURCES = \ getoptlong.c \ getreent.c \ getrlimit64.c \ + getwd.c \ ids.c \ inode.c \ io.c \ @@ -81,6 +84,7 @@ LIB_SOURCES = \ realpath.c \ rename.c \ resource.c \ + scandir64.c \ sched.c \ select.c \ seteuid.c \ @@ -101,6 +105,7 @@ LIB_SOURCES = \ statvfs.c \ statvfs64.c \ strsignal.c \ + strverscmp.c \ sysconf.c \ sysctl.c \ systat.c \ @@ -113,6 +118,8 @@ LIB_SOURCES = \ usleep.c \ utimes.c \ vallocr.c \ + versionsort.c \ + versionsort64.c \ wait.c # This will handle both /usr/src/linux-2.4/include/asm/signal.h (in Red Hat Linux 7.1) diff --git a/newlib/libc/sys/linux/Makefile.in b/newlib/libc/sys/linux/Makefile.in index 71d7f6b97..3bb44e20c 100644 --- a/newlib/libc/sys/linux/Makefile.in +++ b/newlib/libc/sys/linux/Makefile.in @@ -127,6 +127,8 @@ LIB_SOURCES = \ fstatvfs.c \ fstatvfs64.c \ ftok.c \ + ftw.c \ + ftw64.c \ funlockfile.c \ getdate.c \ getdate_err.c \ @@ -134,6 +136,7 @@ LIB_SOURCES = \ getoptlong.c \ getreent.c \ getrlimit64.c \ + getwd.c \ ids.c \ inode.c \ io.c \ @@ -178,6 +181,7 @@ LIB_SOURCES = \ realpath.c \ rename.c \ resource.c \ + scandir64.c \ sched.c \ select.c \ seteuid.c \ @@ -198,6 +202,7 @@ LIB_SOURCES = \ statvfs.c \ statvfs64.c \ strsignal.c \ + strverscmp.c \ sysconf.c \ sysctl.c \ systat.c \ @@ -210,6 +215,8 @@ LIB_SOURCES = \ usleep.c \ utimes.c \ vallocr.c \ + versionsort.c \ + versionsort64.c \ wait.c @@ -258,42 +265,45 @@ LIBS = @LIBS@ @USE_LIBTOOL_FALSE@flockfile.$(OBJEXT) fpathconf.$(OBJEXT) \ @USE_LIBTOOL_FALSE@free.$(OBJEXT) freer.$(OBJEXT) fstab.$(OBJEXT) \ @USE_LIBTOOL_FALSE@fstatvfs.$(OBJEXT) fstatvfs64.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@ftok.$(OBJEXT) funlockfile.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@getdate.$(OBJEXT) getdate_err.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@gethostname.$(OBJEXT) getoptlong.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@getreent.$(OBJEXT) getrlimit64.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@ids.$(OBJEXT) inode.$(OBJEXT) io.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@io64.$(OBJEXT) ipc.$(OBJEXT) linux.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@malign.$(OBJEXT) malignr.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@mallinfor.$(OBJEXT) mallocr.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@malloptr.$(OBJEXT) mallstatsr.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@mmap.$(OBJEXT) mntent.$(OBJEXT) mntent_r.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@mq_close.$(OBJEXT) mq_getattr.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@mq_notify.$(OBJEXT) mq_open.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@mq_receive.$(OBJEXT) mq_send.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@mq_setattr.$(OBJEXT) mq_unlink.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@msize.$(OBJEXT) msizer.$(OBJEXT) mstats.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@mtrim.$(OBJEXT) mtrimr.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@ftok.$(OBJEXT) ftw.$(OBJEXT) ftw64.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@funlockfile.$(OBJEXT) getdate.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@getdate_err.$(OBJEXT) gethostname.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@getoptlong.$(OBJEXT) getreent.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@getrlimit64.$(OBJEXT) getwd.$(OBJEXT) ids.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@inode.$(OBJEXT) io.$(OBJEXT) io64.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@ipc.$(OBJEXT) linux.$(OBJEXT) malign.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@malignr.$(OBJEXT) mallinfor.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@mallocr.$(OBJEXT) malloptr.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@mallstatsr.$(OBJEXT) mmap.$(OBJEXT) mntent.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@mntent_r.$(OBJEXT) mq_close.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@mq_getattr.$(OBJEXT) mq_notify.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@mq_open.$(OBJEXT) mq_receive.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@mq_send.$(OBJEXT) mq_setattr.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@mq_unlink.$(OBJEXT) msize.$(OBJEXT) msizer.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@mstats.$(OBJEXT) mtrim.$(OBJEXT) mtrimr.$(OBJEXT) \ @USE_LIBTOOL_FALSE@ntp_gettime.$(OBJEXT) pathconf.$(OBJEXT) \ @USE_LIBTOOL_FALSE@pread.$(OBJEXT) pread64.$(OBJEXT) process.$(OBJEXT) \ @USE_LIBTOOL_FALSE@psignal.$(OBJEXT) pvallocr.$(OBJEXT) \ @USE_LIBTOOL_FALSE@pwrite.$(OBJEXT) pwrite64.$(OBJEXT) raise.$(OBJEXT) \ @USE_LIBTOOL_FALSE@readdir64.$(OBJEXT) realloc.$(OBJEXT) \ @USE_LIBTOOL_FALSE@reallocr.$(OBJEXT) realpath.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@rename.$(OBJEXT) resource.$(OBJEXT) sched.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@select.$(OBJEXT) seteuid.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@sethostname.$(OBJEXT) setrlimit64.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@shm_open.$(OBJEXT) shm_unlink.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@sig.$(OBJEXT) sigaction.$(OBJEXT) sigqueue.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@rename.$(OBJEXT) resource.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@scandir64.$(OBJEXT) sched.$(OBJEXT) select.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@seteuid.$(OBJEXT) sethostname.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@setrlimit64.$(OBJEXT) shm_open.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@shm_unlink.$(OBJEXT) sig.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@sigaction.$(OBJEXT) sigqueue.$(OBJEXT) \ @USE_LIBTOOL_FALSE@signal.$(OBJEXT) siglongjmp.$(OBJEXT) \ @USE_LIBTOOL_FALSE@sigset.$(OBJEXT) sigwait.$(OBJEXT) socket.$(OBJEXT) \ @USE_LIBTOOL_FALSE@sleep.$(OBJEXT) stack.$(OBJEXT) statvfs.$(OBJEXT) \ @USE_LIBTOOL_FALSE@statvfs64.$(OBJEXT) strsignal.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@sysconf.$(OBJEXT) sysctl.$(OBJEXT) systat.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@system.$(OBJEXT) tcdrain.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@tcsendbrk.$(OBJEXT) termios.$(OBJEXT) time.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@ttyname_r.$(OBJEXT) usleep.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@utimes.$(OBJEXT) vallocr.$(OBJEXT) wait.$(OBJEXT) +@USE_LIBTOOL_FALSE@strverscmp.$(OBJEXT) sysconf.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@sysctl.$(OBJEXT) systat.$(OBJEXT) system.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@tcdrain.$(OBJEXT) tcsendbrk.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@termios.$(OBJEXT) time.$(OBJEXT) ttyname_r.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@usleep.$(OBJEXT) utimes.$(OBJEXT) vallocr.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@versionsort.$(OBJEXT) versionsort64.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@wait.$(OBJEXT) LTLIBRARIES = $(noinst_LTLIBRARIES) @USE_LIBTOOL_TRUE@liblinux_la_OBJECTS = aio.lo brk.lo calloc.lo \ @@ -301,26 +311,27 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) @USE_LIBTOOL_TRUE@clock_gettime.lo clock_settime.lo confstr.lo \ @USE_LIBTOOL_TRUE@ctermid.lo fclean.lo flockfile.lo fpathconf.lo \ @USE_LIBTOOL_TRUE@free.lo freer.lo fstab.lo fstatvfs.lo fstatvfs64.lo \ -@USE_LIBTOOL_TRUE@ftok.lo funlockfile.lo getdate.lo getdate_err.lo \ -@USE_LIBTOOL_TRUE@gethostname.lo getoptlong.lo getreent.lo \ -@USE_LIBTOOL_TRUE@getrlimit64.lo ids.lo inode.lo io.lo io64.lo ipc.lo \ -@USE_LIBTOOL_TRUE@linux.lo malign.lo malignr.lo mallinfor.lo mallocr.lo \ -@USE_LIBTOOL_TRUE@malloptr.lo mallstatsr.lo mmap.lo mntent.lo \ -@USE_LIBTOOL_TRUE@mntent_r.lo mq_close.lo mq_getattr.lo mq_notify.lo \ -@USE_LIBTOOL_TRUE@mq_open.lo mq_receive.lo mq_send.lo mq_setattr.lo \ -@USE_LIBTOOL_TRUE@mq_unlink.lo msize.lo msizer.lo mstats.lo mtrim.lo \ -@USE_LIBTOOL_TRUE@mtrimr.lo ntp_gettime.lo pathconf.lo pread.lo \ -@USE_LIBTOOL_TRUE@pread64.lo process.lo psignal.lo pvallocr.lo \ -@USE_LIBTOOL_TRUE@pwrite.lo pwrite64.lo raise.lo readdir64.lo \ -@USE_LIBTOOL_TRUE@realloc.lo reallocr.lo realpath.lo rename.lo \ -@USE_LIBTOOL_TRUE@resource.lo sched.lo select.lo seteuid.lo \ -@USE_LIBTOOL_TRUE@sethostname.lo setrlimit64.lo shm_open.lo \ +@USE_LIBTOOL_TRUE@ftok.lo ftw.lo ftw64.lo funlockfile.lo getdate.lo \ +@USE_LIBTOOL_TRUE@getdate_err.lo gethostname.lo getoptlong.lo \ +@USE_LIBTOOL_TRUE@getreent.lo getrlimit64.lo getwd.lo ids.lo inode.lo \ +@USE_LIBTOOL_TRUE@io.lo io64.lo ipc.lo linux.lo malign.lo malignr.lo \ +@USE_LIBTOOL_TRUE@mallinfor.lo mallocr.lo malloptr.lo mallstatsr.lo \ +@USE_LIBTOOL_TRUE@mmap.lo mntent.lo mntent_r.lo mq_close.lo \ +@USE_LIBTOOL_TRUE@mq_getattr.lo mq_notify.lo mq_open.lo mq_receive.lo \ +@USE_LIBTOOL_TRUE@mq_send.lo mq_setattr.lo mq_unlink.lo msize.lo \ +@USE_LIBTOOL_TRUE@msizer.lo mstats.lo mtrim.lo mtrimr.lo ntp_gettime.lo \ +@USE_LIBTOOL_TRUE@pathconf.lo pread.lo pread64.lo process.lo psignal.lo \ +@USE_LIBTOOL_TRUE@pvallocr.lo pwrite.lo pwrite64.lo raise.lo \ +@USE_LIBTOOL_TRUE@readdir64.lo realloc.lo reallocr.lo realpath.lo \ +@USE_LIBTOOL_TRUE@rename.lo resource.lo scandir64.lo sched.lo select.lo \ +@USE_LIBTOOL_TRUE@seteuid.lo sethostname.lo setrlimit64.lo shm_open.lo \ @USE_LIBTOOL_TRUE@shm_unlink.lo sig.lo sigaction.lo sigqueue.lo \ @USE_LIBTOOL_TRUE@signal.lo siglongjmp.lo sigset.lo sigwait.lo \ @USE_LIBTOOL_TRUE@socket.lo sleep.lo stack.lo statvfs.lo statvfs64.lo \ -@USE_LIBTOOL_TRUE@strsignal.lo sysconf.lo sysctl.lo systat.lo system.lo \ -@USE_LIBTOOL_TRUE@tcdrain.lo tcsendbrk.lo termios.lo time.lo \ -@USE_LIBTOOL_TRUE@ttyname_r.lo usleep.lo utimes.lo vallocr.lo wait.lo +@USE_LIBTOOL_TRUE@strsignal.lo strverscmp.lo sysconf.lo sysctl.lo \ +@USE_LIBTOOL_TRUE@systat.lo system.lo tcdrain.lo tcsendbrk.lo \ +@USE_LIBTOOL_TRUE@termios.lo time.lo ttyname_r.lo usleep.lo utimes.lo \ +@USE_LIBTOOL_TRUE@vallocr.lo versionsort.lo versionsort64.lo wait.lo CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) diff --git a/newlib/libc/sys/linux/ftw.c b/newlib/libc/sys/linux/ftw.c new file mode 100644 index 000000000..a7f7259bc --- /dev/null +++ b/newlib/libc/sys/linux/ftw.c @@ -0,0 +1,640 @@ +/* File tree walker functions. + Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Modified for newlib by Jeff Johnston, July 26, 2002 */ + +#define _GNU_SOURCE 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct dirent64 *__readdir64 (DIR *); + +/* #define NDEBUG 1 */ +#include + +/* Support for the LFS API version. */ +#ifndef FTW_NAME +# define FTW_NAME ftw +# define NFTW_NAME nftw +# define INO_T ino_t +# define STAT stat +# define LXSTAT lstat +# define XSTAT stat +# define FTW_FUNC_T __ftw_func_t +# define NFTW_FUNC_T __nftw_func_t +#endif + +#define dirfd(x) ((x)->dd_fd) + +struct dir_data +{ + DIR *stream; + char *content; +}; + +struct known_object +{ + dev_t dev; + INO_T ino; +}; + +struct ftw_data +{ + /* Array with pointers to open directory streams. */ + struct dir_data **dirstreams; + size_t actdir; + size_t maxdir; + + /* Buffer containing name of currently processed object. */ + char *dirbuf; + size_t dirbufsize; + + /* Passed as fourth argument to `nftw' callback. The `base' member + tracks the content of the `dirbuf'. */ + struct FTW ftw; + + /* Flags passed to `nftw' function. 0 for `ftw'. */ + int flags; + + /* Conversion array for flag values. It is the identity mapping for + `nftw' calls, otherwise it maps the values to those know by + `ftw'. */ + const int *cvt_arr; + + /* Callback function. We always use the `nftw' form. */ + NFTW_FUNC_T func; + + /* Device of starting point. Needed for FTW_MOUNT. */ + dev_t dev; + + /* Data structure for keeping fingerprints of already processed + object. This is needed when not using FTW_PHYS. */ + void *known_objects; +}; + + +/* Internally we use the FTW_* constants used for `nftw'. When the + process called `ftw' we must reduce the flag to the known flags + for `ftw'. */ +static const int nftw_arr[] = +{ + FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_SL, FTW_DP, FTW_SLN +}; + +static const int ftw_arr[] = +{ + FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_F, FTW_D, FTW_NS +}; + + +/* Forward declarations of local functions. */ +static int ftw_dir (struct ftw_data *data, struct STAT *st); + + +static int +object_compare (const void *p1, const void *p2) +{ + /* We don't need a sophisticated and useful comparison. We are only + interested in equality. However, we must be careful not to + accidentally compare `holes' in the structure. */ + const struct known_object *kp1 = p1, *kp2 = p2; + int cmp1; + cmp1 = (kp1->dev > kp2->dev) - (kp1->dev < kp2->dev); + if (cmp1 != 0) + return cmp1; + return (kp1->ino > kp2->ino) - (kp1->ino < kp2->ino); +} + + +static inline int +add_object (struct ftw_data *data, struct STAT *st) +{ + struct known_object *newp = malloc (sizeof (struct known_object)); + if (newp == NULL) + return -1; + newp->dev = st->st_dev; + newp->ino = st->st_ino; + return tsearch (newp, &data->known_objects, object_compare) ? 0 : -1; +} + + +static inline int +find_object (struct ftw_data *data, struct STAT *st) +{ + struct known_object obj = { dev: st->st_dev, ino: st->st_ino }; + return tfind (&obj, &data->known_objects, object_compare) != NULL; +} + + +static inline int +open_dir_stream (struct ftw_data *data, struct dir_data *dirp) +{ + int result = 0; + + if (data->dirstreams[data->actdir] != NULL) + { + /* Oh, oh. We must close this stream. Get all remaining + entries and store them as a list in the `content' member of + the `struct dir_data' variable. */ + size_t bufsize = 1024; + char *buf = malloc (bufsize); + + if (buf == NULL) + result = -1; + else + { + DIR *st = data->dirstreams[data->actdir]->stream; + struct dirent64 *d; + size_t actsize = 0; + + while ((d = __readdir64 (st)) != NULL) + { + size_t this_len = strlen (d->d_name); + if (actsize + this_len + 2 >= bufsize) + { + char *newp; + bufsize += MAX (1024, 2 * this_len); + newp = realloc (buf, bufsize); + if (newp == NULL) + { + /* No more memory. */ + int save_err = errno; + free (buf); + __set_errno (save_err); + result = -1; + break; + } + buf = newp; + } + + *((char *) mempcpy (buf + actsize, d->d_name, this_len)) + = '\0'; + actsize += this_len + 1; + } + + /* Terminate the list with an additional NUL byte. */ + buf[actsize++] = '\0'; + + /* Shrink the buffer to what we actually need. */ + data->dirstreams[data->actdir]->content = realloc (buf, actsize); + if (data->dirstreams[data->actdir]->content == NULL) + { + int save_err = errno; + free (buf); + __set_errno (save_err); + result = -1; + } + else + { + closedir (st); + data->dirstreams[data->actdir]->stream = NULL; + data->dirstreams[data->actdir] = NULL; + } + } + } + + /* Open the new stream. */ + if (result == 0) + { + assert (data->dirstreams[data->actdir] == NULL); + + dirp->stream = opendir (data->dirbuf); + if (dirp->stream == NULL) + result = -1; + else + { + dirp->content = NULL; + data->dirstreams[data->actdir] = dirp; + + if (++data->actdir == data->maxdir) + data->actdir = 0; + } + } + + return result; +} + + +static inline int +process_entry (struct ftw_data *data, struct dir_data *dir, const char *name, + size_t namlen) +{ + struct STAT st; + int result = 0; + int flag = 0; + + if (name[0] == '.' && (name[1] == '\0' + || (name[1] == '.' && name[2] == '\0'))) + /* Don't process the "." and ".." entries. */ + return 0; + + if (data->dirbufsize < data->ftw.base + namlen + 2) + { + /* Enlarge the buffer. */ + char *newp; + + data->dirbufsize *= 2; + newp = realloc (data->dirbuf, data->dirbufsize); + if (newp == NULL) + return -1; + data->dirbuf = newp; + } + + *((char *) mempcpy (data->dirbuf + data->ftw.base, name, namlen)) = '\0'; + + if (((data->flags & FTW_PHYS) + ? LXSTAT (data->dirbuf, &st) + : XSTAT (data->dirbuf, &st)) < 0) + { + if (errno != EACCES && errno != ENOENT) + result = -1; + else if (!(data->flags & FTW_PHYS) + && LXSTAT (data->dirbuf, &st) == 0 + && S_ISLNK (st.st_mode)) + flag = FTW_SLN; + else + flag = FTW_NS; + } + else + { + if (S_ISDIR (st.st_mode)) + flag = FTW_D; + else if (S_ISLNK (st.st_mode)) + flag = FTW_SL; + else + flag = FTW_F; + } + + if (result == 0 + && (flag == FTW_NS + || !(data->flags & FTW_MOUNT) || st.st_dev == data->dev)) + { + if (flag == FTW_D) + { + if ((data->flags & FTW_PHYS) + || (!find_object (data, &st) + /* Remember the object. */ + && (result = add_object (data, &st)) == 0)) + { + result = ftw_dir (data, &st); + + if (result == 0 && (data->flags & FTW_CHDIR)) + { + /* Change back to current directory. */ + int done = 0; + if (dir->stream != NULL) + if (fchdir (dirfd (dir->stream)) == 0) + done = 1; + + if (!done) + { + if (data->ftw.base == 1) + { + if (chdir ("/") < 0) + result = -1; + } + else + { + /* Please note that we overwrite a slash. */ + data->dirbuf[data->ftw.base - 1] = '\0'; + + if (chdir (data->dirbuf) < 0) + result = -1; + + data->dirbuf[data->ftw.base - 1] = '/'; + } + } + } + } + } + else + result = (*data->func) (data->dirbuf, &st, data->cvt_arr[flag], + &data->ftw); + } + + return result; +} + + +static int +ftw_dir (struct ftw_data *data, struct STAT *st) +{ + struct dir_data dir; + struct dirent64 *d; + int previous_base = data->ftw.base; + int result; + char *startp; + + /* Open the stream for this directory. This might require that + another stream has to be closed. */ + result = open_dir_stream (data, &dir); + if (result != 0) + { + if (errno == EACCES) + /* We cannot read the directory. Signal this with a special flag. */ + result = (*data->func) (data->dirbuf, st, FTW_DNR, &data->ftw); + + return result; + } + + /* First, report the directory (if not depth-first). */ + if (!(data->flags & FTW_DEPTH)) + { + result = (*data->func) (data->dirbuf, st, FTW_D, &data->ftw); + if (result != 0) + return result; + } + + /* If necessary, change to this directory. */ + if (data->flags & FTW_CHDIR) + { + if (fchdir (dirfd (dir.stream)) < 0) + { + if (errno == ENOSYS) + { + if (chdir (data->dirbuf) < 0) + result = -1; + } + else + result = -1; + } + + if (result != 0) + { + int save_err = errno; + closedir (dir.stream); + __set_errno (save_err); + + if (data->actdir-- == 0) + data->actdir = data->maxdir - 1; + data->dirstreams[data->actdir] = NULL; + + return result; + } + } + + /* Next, update the `struct FTW' information. */ + ++data->ftw.level; + startp = strchr (data->dirbuf, '\0'); + /* There always must be a directory name. */ + assert (startp != data->dirbuf); + if (startp[-1] != '/') + *startp++ = '/'; + data->ftw.base = startp - data->dirbuf; + + while (dir.stream != NULL && (d = __readdir64 (dir.stream)) != NULL) + { + result = process_entry (data, &dir, d->d_name, strlen (d->d_name)); + if (result != 0) + break; + } + + if (dir.stream != NULL) + { + /* The stream is still open. I.e., we did not need more + descriptors. Simply close the stream now. */ + int save_err = errno; + + assert (dir.content == NULL); + + closedir (dir.stream); + __set_errno (save_err); + + if (data->actdir-- == 0) + data->actdir = data->maxdir - 1; + data->dirstreams[data->actdir] = NULL; + } + else + { + int save_err; + char *runp = dir.content; + + while (result == 0 && *runp != '\0') + { + char *endp = strchr (runp, '\0'); + + result = process_entry (data, &dir, runp, endp - runp); + + runp = endp + 1; + } + + save_err = errno; + free (dir.content); + __set_errno (save_err); + } + + /* Prepare the return, revert the `struct FTW' information. */ + data->dirbuf[data->ftw.base - 1] = '\0'; + --data->ftw.level; + data->ftw.base = previous_base; + + /* Finally, if we process depth-first report the directory. */ + if (result == 0 && (data->flags & FTW_DEPTH)) + result = (*data->func) (data->dirbuf, st, FTW_DP, &data->ftw); + + return result; +} + + +static int +ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, + int flags) +{ + struct ftw_data data; + struct STAT st; + int result = 0; + int save_err; + int len; + char *cwd = NULL; + char *cp; + + /* First make sure the parameters are reasonable. */ + if (dir[0] == '\0') + { + __set_errno (ENOENT); + return -1; + } + + if (access (dir, R_OK) != 0) + return -1; + + data.maxdir = descriptors < 1 ? 1 : descriptors; + data.actdir = 0; + data.dirstreams = (struct dir_data **) alloca (data.maxdir + * sizeof (struct dir_data *)); + memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *)); + +#ifdef PATH_MAX + data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX); +#else + data.dirbufsize = 2 * strlen (dir); +#endif + data.dirbuf = (char *) malloc (data.dirbufsize); + if (data.dirbuf == NULL) + return -1; + len = strlen (dir); + cp = mempcpy (data.dirbuf, dir, len); + /* Strip trailing slashes. */ + while (cp > data.dirbuf + 1 && cp[-1] == '/') + --cp; + *cp = '\0'; + + data.ftw.level = 0; + + /* Find basename. */ + while (cp > data.dirbuf && cp[-1] != '/') + --cp; + data.ftw.base = cp - data.dirbuf; + + data.flags = flags; + + /* This assignment might seem to be strange but it is what we want. + The trick is that the first three arguments to the `ftw' and + `nftw' callback functions are equal. Therefore we can call in + every case the callback using the format of the `nftw' version + and get the correct result since the stack layout for a function + call in C allows this. */ + data.func = (NFTW_FUNC_T) func; + + /* Since we internally use the complete set of FTW_* values we need + to reduce the value range before calling a `ftw' callback. */ + data.cvt_arr = is_nftw ? nftw_arr : ftw_arr; + + /* No object known so far. */ + data.known_objects = NULL; + + /* Now go to the directory containing the initial file/directory. */ + if ((flags & FTW_CHDIR) && data.ftw.base > 0) + { + /* GNU extension ahead. */ + cwd = getcwd (NULL, 0); + if (cwd == NULL) + result = -1; + else + { + /* Change to the directory the file is in. In data.dirbuf + we have a writable copy of the file name. Just NUL + terminate it for now and change the directory. */ + if (data.ftw.base == 1) + /* I.e., the file is in the root directory. */ + result = chdir ("/"); + else + { + char ch = data.dirbuf[data.ftw.base - 1]; + data.dirbuf[data.ftw.base - 1] = '\0'; + result = chdir (data.dirbuf); + data.dirbuf[data.ftw.base - 1] = ch; + } + } + } + + /* Get stat info for start directory. */ + if (result == 0) + { + if (((flags & FTW_PHYS) + ? LXSTAT (data.dirbuf, &st) + : XSTAT (data.dirbuf, &st)) < 0) + { + if (errno == EACCES) + result = (*data.func) (data.dirbuf, &st, FTW_NS, &data.ftw); + else if (!(flags & FTW_PHYS) + && errno == ENOENT + && LXSTAT (dir, &st) == 0 + && S_ISLNK (st.st_mode)) + result = (*data.func) (data.dirbuf, &st, data.cvt_arr[FTW_SLN], + &data.ftw); + else + /* No need to call the callback since we cannot say anything + about the object. */ + result = -1; + } + else + { + if (S_ISDIR (st.st_mode)) + { + /* Remember the device of the initial directory in case + FTW_MOUNT is given. */ + data.dev = st.st_dev; + + /* We know this directory now. */ + if (!(flags & FTW_PHYS)) + result = add_object (&data, &st); + + if (result == 0) + result = ftw_dir (&data, &st); + } + else + { + int flag = S_ISLNK (st.st_mode) ? FTW_SL : FTW_F; + + result = (*data.func) (data.dirbuf, &st, data.cvt_arr[flag], + &data.ftw); + } + } + } + + /* Return to the start directory (if necessary). */ + if (cwd != NULL) + { + int save_err = errno; + chdir (cwd); + free (cwd); + __set_errno (save_err); + } + + /* Free all memory. */ + save_err = errno; + tdestroy (data.known_objects, free); + free (data.dirbuf); + __set_errno (save_err); + + return result; +} + + + +/* Entry points. */ + +int +FTW_NAME (path, func, descriptors) + const char *path; + FTW_FUNC_T func; + int descriptors; +{ + return ftw_startup (path, 0, func, descriptors, 0); +} + +int +NFTW_NAME (path, func, descriptors, flags) + const char *path; + NFTW_FUNC_T func; + int descriptors; + int flags; +{ + return ftw_startup (path, 1, func, descriptors, flags); +} diff --git a/newlib/libc/sys/linux/ftw64.c b/newlib/libc/sys/linux/ftw64.c new file mode 100644 index 000000000..216549ac3 --- /dev/null +++ b/newlib/libc/sys/linux/ftw64.c @@ -0,0 +1,30 @@ +/* File tree walker functions. LFS version. + Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FTW_NAME ftw64 +#define NFTW_NAME nftw64 +#define INO_T ino64_t +#define STAT stat64 +#define LXSTAT lstat64 +#define XSTAT stat64 +#define FTW_FUNC_T __ftw64_func_t +#define NFTW_FUNC_T __nftw64_func_t + +#include "ftw.c" diff --git a/newlib/libc/sys/linux/getwd.c b/newlib/libc/sys/linux/getwd.c new file mode 100644 index 000000000..72db33830 --- /dev/null +++ b/newlib/libc/sys/linux/getwd.c @@ -0,0 +1,20 @@ +#include +#include +#include + +char * +getwd (char *buf) +{ + char tmp[MAXPATHLEN]; + + if (buf == NULL) + { + errno = EINVAL; + return NULL; + } + + if (getcwd (tmp, MAXPATHLEN) == NULL) + return NULL; + + return strncpy (buf, tmp, MAXPATHLEN); +} diff --git a/newlib/libc/sys/linux/inode.c b/newlib/libc/sys/linux/inode.c index 6b2a2571f..280d55876 100644 --- a/newlib/libc/sys/linux/inode.c +++ b/newlib/libc/sys/linux/inode.c @@ -21,6 +21,7 @@ __LOCK_INIT(static, umask_lock); _syscall2(int,link,const char *,oldpath,const char *,newpath) _syscall1(int,unlink,const char *,pathname) _syscall1(int,chdir,const char *,path) +_syscall1(int,fchdir,int,fd) _syscall3(int,mknod,const char *,pathname,mode_t,mode,dev_t,dev) _syscall2(int,chmod,const char *,path,mode_t,mode) _syscall2(int,fchmod,int,filedes,mode_t,mode) diff --git a/newlib/libc/sys/linux/scandir64.c b/newlib/libc/sys/linux/scandir64.c new file mode 100644 index 000000000..b21b42342 --- /dev/null +++ b/newlib/libc/sys/linux/scandir64.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)scandir.c 5.10 (Berkeley) 2/23/91"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Scan the directory dirname calling select to make a list of selected + * directory entries then sort using qsort and compare routine dcomp. + * Returns the number of entries and a pointer to a list of pointers to + * struct dirent64 (through namelist). Returns -1 if there were any errors. + */ + +#include +#include +#include +#include +#include +#include + +extern struct dirent64 *__readdir64 (DIR *); + +/* + * The DIRSIZ macro gives the minimum record length which will hold + * the directory entry. This requires the amount of space in struct dirent64 + * without the d_name field, plus enough space for the name with a terminating + * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. + */ +#undef DIRSIZ +#ifdef _DIRENT_HAVE_D_NAMLEN +#define DIRSIZ(dp) \ + ((sizeof (struct dirent64) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) +#else +#define DIRSIZ(dp) \ + ((sizeof (struct dirent64) - (MAXNAMLEN+1)) + ((strlen((dp)->d_name)+1 + 3) &~ 3)) +#endif + +#ifndef __P +#define __P(args) () +#endif + +int +scandir64(dirname, namelist, select, dcomp) + const char *dirname; + struct dirent64 ***namelist; + int (*select) __P((struct dirent64 *)); + int (*dcomp) __P((const void *, const void *)); +{ + register struct dirent64 *d, *p, **names; + register size_t nitems; + struct stat64 stb; + long arraysz; + DIR *dirp; + + if ((dirp = opendir(dirname)) == NULL) + return(-1); +#ifdef HAVE_DD_LOCK + __lock_acquire_recursive(dirp->dd_lock); +#endif + if (fstat64(dirp->dd_fd, &stb) < 0) { +#ifdef HAVE_DD_LOCK + __lock_release_recursive(dirp->dd_lock); +#endif + return(-1); + } + + /* + * estimate the array size by taking the size of the directory file + * and dividing it by a multiple of the minimum size entry. + */ + arraysz = (stb.st_size / 24); + names = (struct dirent64 **)malloc(arraysz * sizeof(struct dirent64 *)); + if (names == NULL) { +#ifdef HAVE_DD_LOCK + __lock_release_recursive(dirp->dd_lock); +#endif + return(-1); + } + + nitems = 0; + while ((d = __readdir64(dirp)) != NULL) { + if (select != NULL && !(*select)(d)) + continue; /* just selected names */ + /* + * Make a minimum size copy of the data + */ + p = (struct dirent64 *)malloc(DIRSIZ(d)); + if (p == NULL) { +#ifdef HAVE_DD_LOCK + __lock_release_recursive(dirp->dd_lock); +#endif + return(-1); + } + p->d_ino = d->d_ino; + p->d_reclen = d->d_reclen; +#ifdef _DIRENT_HAVE_D_NAMLEN + p->d_namlen = d->d_namlen; + bcopy(d->d_name, p->d_name, p->d_namlen + 1); +#else + strcpy(p->d_name, d->d_name); +#endif + /* + * Check to make sure the array has space left and + * realloc the maximum size. + */ + if (++nitems >= arraysz) { + if (fstat64(dirp->dd_fd, &stb) < 0) { +#ifdef HAVE_DD_LOCK + __lock_release_recursive(dirp->dd_lock); +#endif + return(-1); /* just might have grown */ + } + arraysz = stb.st_size / 12; + names = (struct dirent64 **)realloc((char *)names, + arraysz * sizeof(struct dirent64 *)); + if (names == NULL) { +#ifdef HAVE_DD_LOCK + __lock_release_recursive(dirp->dd_lock); +#endif + return(-1); + } + } + names[nitems-1] = p; + } + closedir(dirp); + if (nitems && dcomp != NULL) + qsort(names, nitems, sizeof(struct dirent64 *), dcomp); + *namelist = names; +#ifdef HAVE_DD_LOCK + __lock_release_recursive(dirp->dd_lock); +#endif + return(nitems); +} + +/* + * Alphabetic order comparison routine for those who want it. + */ +int +alphasort64(d1, d2) + const struct dirent64 **d1; + const struct dirent64 **d2; +{ + return(strcmp((*d1)->d_name, (*d2)->d_name)); +} + diff --git a/newlib/libc/sys/linux/strverscmp.c b/newlib/libc/sys/linux/strverscmp.c new file mode 100644 index 000000000..2a9cbf48a --- /dev/null +++ b/newlib/libc/sys/linux/strverscmp.c @@ -0,0 +1,113 @@ +/* Compare strings while treating digits characters numerically. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jean-François Bignolles , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* states: S_N: normal, S_I: comparing integral part, S_F: comparing + fractionnal parts, S_Z: idem but with leading Zeroes only */ +#define S_N 0x0 +#define S_I 0x4 +#define S_F 0x8 +#define S_Z 0xC + +/* result_type: CMP: return diff; LEN: compare using len_diff/diff */ +#define CMP 2 +#define LEN 3 + + +/* Compare S1 and S2 as strings holding indices/version numbers, + returning less than, equal to or greater than zero if S1 is less than, + equal to or greater than S2 (for more info, see the texinfo doc). +*/ + +int +__strverscmp (s1, s2) + const char *s1; + const char *s2; +{ + const unsigned char *p1 = (const unsigned char *) s1; + const unsigned char *p2 = (const unsigned char *) s2; + unsigned char c1, c2; + int state; + int diff; + + /* Symbol(s) 0 [1-9] others (padding) + Transition (10) 0 (01) d (00) x (11) - */ + static const unsigned int next_state[] = + { + /* state x d 0 - */ + /* S_N */ S_N, S_I, S_Z, S_N, + /* S_I */ S_N, S_I, S_I, S_I, + /* S_F */ S_N, S_F, S_F, S_F, + /* S_Z */ S_N, S_F, S_Z, S_Z + }; + + static const int result_type[] = + { + /* state x/x x/d x/0 x/- d/x d/d d/0 d/- + 0/x 0/d 0/0 0/- -/x -/d -/0 -/- */ + + /* S_N */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP, + CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, + /* S_I */ CMP, -1, -1, CMP, +1, LEN, LEN, CMP, + +1, LEN, LEN, CMP, CMP, CMP, CMP, CMP, + /* S_F */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP, + CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, + /* S_Z */ CMP, +1, +1, CMP, -1, CMP, CMP, CMP, + -1, CMP, CMP, CMP + }; + + if (p1 == p2) + return 0; + + c1 = *p1++; + c2 = *p2++; + /* Hint: '0' is a digit too. */ + state = S_N | ((c1 == '0') + (isdigit (c1) != 0)); + + while ((diff = c1 - c2) == 0 && c1 != '\0') + { + state = next_state[state]; + c1 = *p1++; + c2 = *p2++; + state |= (c1 == '0') + (isdigit (c1) != 0); + } + + state = result_type[state << 2 | (((c2 == '0') + (isdigit (c2) != 0)))]; + + switch (state) + { + case CMP: + return diff; + + case LEN: + while (isdigit (*p1++)) + if (!isdigit (*p2++)) + return 1; + + return isdigit (*p2) ? -1 : diff; + + default: + return state; + } +} +weak_alias (__strverscmp, strverscmp) diff --git a/newlib/libc/sys/linux/sys/stat.h b/newlib/libc/sys/linux/sys/stat.h index ce20cb684..7bc06f7ae 100644 --- a/newlib/libc/sys/linux/sys/stat.h +++ b/newlib/libc/sys/linux/sys/stat.h @@ -17,16 +17,16 @@ #include int _EXFUN(fstat,( int __fd, struct stat *__sbuf )); -int _EXFUN(fstat64,( int __fd, struct stat64 *__sbuf )); int _EXFUN(mkdir,( const char *_path, mode_t __mode )); int _EXFUN(mkfifo,( const char *__path, mode_t __mode )); int _EXFUN(stat,( const char *__path, struct stat *__sbuf )); -int _EXFUN(stat64,( const char *__path, struct stat64 *__sbuf )); mode_t _EXFUN(umask,( mode_t __mask )); #ifndef _POSIX_SOURCE +int _EXFUN(fstat64,( int __fd, struct stat *__sbuf )); int _EXFUN(lstat,( const char *file_name, struct stat *buf)); -int _EXFUN(lstat64,( const char *file_name, struct stat64 *buf)); +int _EXFUN(lstat64,( const char *file_name, struct stat *buf)); +int _EXFUN(stat64,( const char *__path, struct stat *__sbuf )); #endif /* _POSIX_SOURCE */ #endif /* _SYS_STAT_H */ diff --git a/newlib/libc/sys/linux/versionsort.c b/newlib/libc/sys/linux/versionsort.c new file mode 100644 index 000000000..13cbdccfc --- /dev/null +++ b/newlib/libc/sys/linux/versionsort.c @@ -0,0 +1,11 @@ +#include +#include + +extern int __strverscmp (char *, char *); + +int +versionsort (const void *a, const void *b) +{ + return __strverscmp ((*(const struct dirent **)a)->d_name, + (*(const struct dirent **)b)->d_name); +} diff --git a/newlib/libc/sys/linux/versionsort64.c b/newlib/libc/sys/linux/versionsort64.c new file mode 100644 index 000000000..45147b00d --- /dev/null +++ b/newlib/libc/sys/linux/versionsort64.c @@ -0,0 +1,11 @@ +#include +#include + +extern int __strverscmp (char *, char *); + +int +versionsort64 (const void *a, const void *b) +{ + return __strverscmp ((*(const struct dirent64 **)a)->d_name, + (*(const struct dirent64 **)b)->d_name); +} -- cgit v1.2.3