* include/dirent.h: New file. Import from glibc-2.2.5.
* include/dirstream.h: Likewise.
* lib/dirent/__getdirentries.c: Likewise.
* lib/dirent/closedir.c: Likewise.
* lib/dirent/readdir.c (readdir): Likewise.
* lib/libc+gnu.c: Include them.
* include/linux/x86/syscall.h (SYS_getdents): New macro.
* include/linux/x86_64/syscall.h (SYS_getdents): Likewise.
* lib/linux/gnu.c (getdents): New function.
* include/limits.h (NAME_MAX): New macro.
* include/fcntl.h (O_DIRECTORY): New macro.
* scaffold/tests/readdir.dir: New directory.
* scaffold/tests/99-readdir.c: New file, use it.
* build-aux/check-mescc.sh (tests): Run it.
96-strto
97-fopen
98-fopen
+99-readdir
"
# 90: needs GNU, fails for mescc, passes for tcc
--- /dev/null
+/* -*-comment-start: "//";comment-end:""-*-
+ * GNU Mes --- Maxwell Equations of Software
+ * Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+ * Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
+ *
+ * This file is part of GNU Mes.
+ *
+ * GNU Mes is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * GNU Mes 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MES_DIRENT_H
+#define __MES_DIRENT_H 1
+
+#if WITH_GLIBC
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#undef __MES_DIRENT_H
+#include_next <dirent.h>
+
+#else // ! WITH_GLIBC
+
+#include <dirstream.h>
+
+// Taken from GNU C Library 1.06.4, 2.2.5
+
+/*
+ * POSIX Standard: 5.1.2 Directory Operations <dirent.h>
+ */
+
+#include <stddef.h>
+
+int __getdirentries (int filedes, char *buffer, size_t nbytes, off_t *basep);
+
+struct dirent
+ {
+ ino_t d_ino;
+ off_t d_off;
+ unsigned short int d_reclen;
+#if 0
+ unsigned char d_type;
+#endif
+ char d_name[256]; /* We must not include limits.h! */
+ };
+
+/* Open a directory stream on NAME.
+ Return a DIR stream on the directory, or NULL if it could not be opened. */
+DIR *opendir (char const *name);
+
+/* Close the directory stream DIRP.
+ Return 0 if successful, -1 if not. */
+int closedir (DIR *dirp);
+
+/* Read a directory entry from DIRP.
+ Return a pointer to a `struct dirent' describing the entry,
+ or NULL for EOF or error. The storage returned may be overwritten
+ by a later readdir call on the same DIR stream. */
+struct dirent *readdir (DIR *dirp);
+
+/* Rewind DIRP to the beginning of the directory. */
+extern void rewinddir (DIR *dirp);
+
+#endif // ! WITH_GLIBC
+
+#endif // __MES_DIRENT_H
--- /dev/null
+/* -*-comment-start: "//";comment-end:""-*-
+ * GNU Mes --- Maxwell Equations of Software
+ *Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+ * Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
+ *
+ * This file is part of GNU Mes.
+ *
+ * GNU Mes is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * GNU Mes 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MES_DIRSTREAM_H
+#define __MES_DIRSTREAM_H 1
+
+#if WITH_GLIBC
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#undef __MES_DIRSTREAM_H
+#include_next <dirstream.h>
+
+#else // ! WITH_GLIBC
+
+#include <sys/types.h>
+
+// Taken from GNU C Library 2.2.5
+
+/* Directory stream type. */
+struct __dirstream
+ {
+ int fd; /* File descriptor. */
+
+ char *data; /* Directory block. */
+ size_t allocation; /* Space allocated for the block. */
+ size_t size; /* Total valid data in the block. */
+ size_t offset; /* Current offset into the block. */
+
+ off_t filepos; /* Position of next entry to read. */
+ };
+
+typedef struct __dirstream DIR;
+
+#endif // ! WITH_GLIBC
+
+#endif // __MES_DIRSTREAM_H
#else // ! WITH_GLIBC
-#define O_RDONLY 0
-#define O_WRONLY 1
-#define O_RDWR 2
-#define O_CREAT 64
-#define O_EXCL 128
-#define O_TRUNC 512
-#define O_APPEND 1024
+#define O_RDONLY 0
+#define O_WRONLY 1
+#define O_RDWR 2
+#define O_CREAT 0x40
+#define O_EXCL 0x80
+#define O_TRUNC 0x200
+#define O_APPEND 0x400
+#define O_DIRECTORY 0x10000
#define FD_CLOEXEC 1
#define LONG_MIN -2147483648
#define LONG_MAX 2147483647
#define _POSIX_OPEN_MAX 16
+#define PATH_MAX 512
+#define NAME_MAX 255
#endif // ! WITH_GLIBC
#define SYS_setitimer 0x68
#define SYS_fstat 0x6c
#define SYS_nanosleep 0xa2
+#define SYS_getdents 0x8d
#endif // __MES_LINUX_X86_SYSCALL_H
#define SYS_setitimer 0x26
#define SYS_fstat 0x05
#define SYS_nanosleep 0x33
+#define SYS_getdents 0x4e
#endif // __MES_LINUX_X86_64_SYSCALL_H
typedef unsigned ino_t;
#endif
+#ifndef __MES_INO64_T
+#define __MES_INO64_T
+#undef ino64_t
+typedef unsigned long long ino64_t;
+#endif
+
#ifndef __MES_INTPTR_T
#define __MES_INTPTR_T
#undef intptr_t
typedef unsigned long off_t;
#endif
+#ifndef __MES_OFF64_T
+#define __MES_OFF64_T
+#undef off64_t
+typedef unsigned long long off64_t;
+#endif
+
#ifndef __MES_PID_T
#define __MES_PID_T
#undef pid_t
--- /dev/null
+/* -*-comment-start: "//";comment-end:""-*-
+ * GNU Mes --- Maxwell Equations of Software
+ * Copyright (C) 1993 Free Software Foundation, Inc.
+ * Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
+ *
+ * This file is part of GNU Mes.
+ *
+ * GNU Mes is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * GNU Mes 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Taken from GNU C Library 1.06.4
+
+#include <dirent.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int
+__getdirentries (int filedes, char *buffer, size_t nbytes, off_t *basep)
+{
+ if (basep)
+ *basep = lseek (filedes, (off_t) 0, SEEK_CUR);
+
+ return read (filedes, buf, nbytes);
+}
--- /dev/null
+/* -*-comment-start: "//";comment-end:""-*-
+ * GNU Mes --- Maxwell Equations of Software
+ * Copyright (C) 1991, 1993, 1995, 1996, 1998 Free Software Foundation, Inc.
+ * Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
+ *
+ * This file is part of GNU Mes.
+ *
+ * GNU Mes is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * GNU Mes 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Taken from GNU C Library 2.2.5
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <dirstream.h>
+
+/* Close the directory stream DIRP.
+ Return 0 if successful, -1 if not. */
+int
+closedir (DIR *dirp)
+{
+ int filedes;
+
+ if (dirp == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ filedes = dirp->fd;
+ free (dirp);
+
+ return close (filedes);
+}
--- /dev/null
+/* -*-comment-start: "//";comment-end:""-*-
+ * GNU Mes --- Maxwell Equations of Software
+ * Copyright (C) 1991-1996,98,2000,2001 Free Software Foundation, Inc.
+ * Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
+ *
+ * This file is part of GNU Mes.
+ *
+ * GNU Mes is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * GNU Mes 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Taken from GNU C Library 2.2.5
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include <dirstream.h>
+
+/* Open a directory stream on NAME. */
+DIR *
+opendir (char const *name)
+{
+ DIR *dirp;
+ struct stat statbuf;
+ int fd;
+ size_t allocation;
+ int save_errno;
+
+ if (name[0] == '\0')
+ {
+ /* POSIX.1-1990 says an empty name gets ENOENT;
+ but `open' might like it fine. */
+ errno = ENOENT;
+ return 0;
+ }
+
+ fd = open (name, O_RDONLY|O_DIRECTORY);
+ if (fd < 0)
+ return 0;
+
+ if (fstat (fd, &statbuf) < 0)
+ goto lose;
+
+ if (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0)
+ goto lose;
+
+ allocation = statbuf.st_blksize;
+
+ dirp = (DIR *) calloc (1, sizeof (DIR) + allocation);
+ if (!dirp)
+ lose:
+ {
+ save_errno = errno;
+ close (fd);
+ errno = save_errno;
+ return 0;
+ }
+ dirp->data = (char *) (dirp + 1);
+ dirp->allocation = allocation;
+ dirp->fd = fd;
+
+ return dirp;
+}
--- /dev/null
+/* -*-comment-start: "//";comment-end:""-*-
+ * GNU Mes --- Maxwell Equations of Software
+ * Copyright (C) 1991,92,93,94,95,96,97,99,2000 Free Software Foundation, Inc.
+ * Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
+ *
+ * This file is part of GNU Mes.
+ *
+ * GNU Mes is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * GNU Mes 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Taken from GNU C Library 2.2.5
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <assert.h>
+
+#include <dirstream.h>
+
+/* Read a directory entry from DIRP. */
+struct dirent *
+readdir (DIR *dirp)
+{
+ struct dirent *dp;
+ int saved_errno = errno;
+
+ do
+ {
+ size_t reclen;
+
+ if (dirp->offset >= dirp->size)
+ {
+ /* We've emptied out our buffer. Refill it. */
+
+ size_t maxread;
+ ssize_t bytes;
+
+ maxread = dirp->allocation;
+
+#if 0
+ off_t base;
+ bytes = __getdirentries (dirp->fd, dirp->data, maxread, &base);
+#else
+ bytes = getdents (dirp->fd, dirp->data, maxread);
+#endif
+ if (bytes <= 0)
+ {
+ /* Don't modifiy errno when reaching EOF. */
+ if (bytes == 0)
+ errno = saved_errno;
+ dp = 0;
+ break;
+ }
+ dirp->size = (size_t) bytes;
+
+ /* Reset the offset into the buffer. */
+ dirp->offset = 0;
+ }
+
+ dp = (struct dirent *) &dirp->data[dirp->offset];
+
+ reclen = dp->d_reclen;
+ dirp->offset += reclen;
+ dirp->filepos = dp->d_off;
+
+ /* Skip deleted files. */
+ } while (dp->d_ino == 0);
+
+ return dp;
+}
#include <stdlib/__exit.c>
#include <stub/__cleanup.c>
+
+#include <dirent/__getdirentries.c>
+#include <dirent/closedir.c>
+#include <dirent/opendir.c>
+#include <dirent/readdir.c>
{
return _sys_call2 (SYS_fstat, (long)fd, (long)statbuf);
}
+
+int
+getdents (long filedes, char *buffer, size_t nbytes)
+{
+ return _sys_call3 (SYS_getdents, (long)filedes, (long)buffer, (long)nbytes);
+}
--- /dev/null
+/* -*-comment-start: "//";comment-end:""-*-
+ * GNU Mes --- Maxwell Equations of Software
+ * Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
+ *
+ * This file is part of GNU Mes.
+ *
+ * GNU Mes is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * GNU Mes 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libmes.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+
+int
+qsort_strcmp (void const* a, void const* b)
+{
+ return strcmp (*((char**) a), *((char**) b));
+}
+
+int
+main ()
+{
+ DIR *d = opendir ("scaffold/tests/readdir-fu");
+ if (d)
+ return 1;
+ if (errno != ENOENT)
+ return 2;
+
+ d = opendir ("scaffold/tests/99-readdir.c");
+ if (d)
+ return 3;
+ if (errno != ENOTDIR)
+ return 4;
+
+ errno = 0;
+ d = opendir ("scaffold/tests/readdir.dir");
+ if (!d)
+ return 5;
+
+ if (errno)
+ return 6;
+
+ int i = 0;
+ char* list[6] = {0};
+ struct dirent *entry = readdir (d);
+ if (!entry)
+ return 7;
+ oputs (entry->d_name);
+ oputs ("\n");
+ list[i++] = entry->d_name;
+
+ entry = readdir (d);
+ if (!entry)
+ return 8;
+ oputs (entry->d_name);
+ oputs ("\n");
+ list[i++] = entry->d_name;
+
+ entry = readdir (d);
+ if (!entry)
+ return 9;
+ oputs (entry->d_name);
+ oputs ("\n");
+ list[i++] = entry->d_name;
+
+ entry = readdir (d);
+ if (!entry)
+ return 10;
+ oputs (entry->d_name);
+ oputs ("\n");
+ list[i++] = entry->d_name;
+
+ entry = readdir (d);
+ if (!entry)
+ return 11;
+ oputs (entry->d_name);
+ oputs ("\n");
+ list[i++] = entry->d_name;
+
+ entry = readdir (d);
+ if (entry)
+ return 12;
+
+ oputs ("\nls:\n");
+ qsort (list, 5, sizeof (char*), qsort_strcmp);
+ for (int i = 0; i < 5; i++)
+ {
+ oputs (list[i]); oputs ("\n");
+ }
+
+ if (strcmp (list[0], "."))
+ return 13;
+
+ if (strcmp (list[4], "link"))
+ return 14;
+
+ return 0;
+}
--- /dev/null
+file
\ No newline at end of file