mescc: Mes C Library: Add closedir, opendir, readdir.

* 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.
This commit is contained in:
Jan Nieuwenhuizen 2018-08-26 18:34:53 +02:00
parent 7ca72fefcd
commit fa4ba916ea
No known key found for this signature in database
GPG key ID: F3C1A0D9C1D65273
18 changed files with 534 additions and 7 deletions

View file

@ -141,6 +141,7 @@ t
96-strto
97-fopen
98-fopen
99-readdir
"
# 90: needs GNU, fails for mescc, passes for tcc

76
include/dirent.h Normal file
View file

@ -0,0 +1,76 @@
/* -*-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

55
include/dirstream.h Normal file
View file

@ -0,0 +1,55 @@
/* -*-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

View file

@ -32,10 +32,11 @@
#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_CREAT 0x40
#define O_EXCL 0x80
#define O_TRUNC 0x200
#define O_APPEND 0x400
#define O_DIRECTORY 0x10000
#define FD_CLOEXEC 1

View file

@ -38,6 +38,8 @@
#define LONG_MIN -2147483648
#define LONG_MAX 2147483647
#define _POSIX_OPEN_MAX 16
#define PATH_MAX 512
#define NAME_MAX 255
#endif // ! WITH_GLIBC

View file

@ -66,5 +66,6 @@
#define SYS_setitimer 0x68
#define SYS_fstat 0x6c
#define SYS_nanosleep 0xa2
#define SYS_getdents 0x8d
#endif // __MES_LINUX_X86_SYSCALL_H

View file

@ -63,5 +63,6 @@
#define SYS_setitimer 0x26
#define SYS_fstat 0x05
#define SYS_nanosleep 0x33
#define SYS_getdents 0x4e
#endif // __MES_LINUX_X86_64_SYSCALL_H

View file

@ -69,6 +69,12 @@ typedef int gid_t;
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
@ -81,6 +87,12 @@ typedef long 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

View file

@ -0,0 +1,35 @@
/* -*-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);
}

54
lib/dirent/closedir.c Normal file
View file

@ -0,0 +1,54 @@
/* -*-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);
}

81
lib/dirent/opendir.c Normal file
View file

@ -0,0 +1,81 @@
/* -*-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;
}

85
lib/dirent/readdir.c Normal file
View file

@ -0,0 +1,85 @@
/* -*-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;
}

View file

@ -98,3 +98,8 @@
#include <stdlib/__exit.c>
#include <stub/__cleanup.c>
#include <dirent/__getdirentries.c>
#include <dirent/closedir.c>
#include <dirent/opendir.c>
#include <dirent/readdir.c>

View file

@ -145,3 +145,9 @@ fstat (int fd, struct stat *statbuf)
{
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);
}

110
scaffold/tests/99-readdir.c Normal file
View file

@ -0,0 +1,110 @@
/* -*-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;
}

View file

View file

@ -0,0 +1 @@
file

View file

@ -0,0 +1 @@
file