Adds openat() stubs (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 26 Dec 2014 22:17:05 +0000 (14:17 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 31 Dec 2014 18:03:09 +0000 (13:03 -0500)
Glibc now implements the POSIX/UNIX opendir() with openat().  The kernel
doesn't support openat() yet, but we can still use the interface for absolute
or AT_FDCWD as a wrapper around open().  When we do support it, the utest ought
to pass.

This fixes things like 'ls' and tab completion in busybox (which needs to do an
ls).

tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/openat.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/openat64.c [new file with mode: 0644]
user/utest/file-posix.c [new file with mode: 0644]

diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/openat.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/openat.c
new file mode 100644 (file)
index 0000000..a0c3646
--- /dev/null
@@ -0,0 +1,88 @@
+/* Copyright (C) 2005-2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <kernel-features.h>
+
+/* Some mostly-generic code (e.g. sysdeps/posix/getcwd.c) uses this variable
+   if __ASSUME_ATFCTS is not defined.  */
+#ifndef __ASSUME_ATFCTS
+int __have_atfcts;
+#endif
+
+/* Open FILE with access OFLAG.  Interpret relative paths relative to
+   the directory associated with FD.  If OFLAG includes O_CREAT, a
+   third argument is the file protection.  */
+int
+__openat (fd, file, oflag)
+     int fd;
+     const char *file;
+     int oflag;
+{
+  int mode;
+
+  if (file == NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  if (fd != AT_FDCWD && file[0] != '/')
+    {
+      /* Check FD is associated with a directory.  */
+      struct stat64 st;
+      if (__fxstat64 (_STAT_VER, fd, &st) != 0)
+       return -1;
+
+      if (!S_ISDIR (st.st_mode))
+       {
+         __set_errno (ENOTDIR);
+         return -1;
+       }
+    }
+
+  if (oflag & O_CREAT)
+    {
+      va_list arg;
+      va_start (arg, oflag);
+      mode = va_arg (arg, int);
+      va_end (arg);
+    }
+
+
+       /* TODO: actually implement openat as the primary kernel interface.  for
+        * now, only allow absolute or relative-to-CWD paths. */
+       if (fd != AT_FDCWD && file[0] != '/') {
+               char openat_err[] = "openat not implemented";
+               memcpy(errstr(), openat_err, MIN(sizeof(openat_err), MAX_ERRSTR_LEN));
+               __set_errno (ENOSYS);
+               return -1;
+       }
+       return ros_syscall(SYS_open, file, strlen(file), oflag, mode, 0, 0);
+}
+libc_hidden_def (__openat)
+weak_alias (__openat, openat)
+
+/* openat64 is the same as openat for akaros */
+weak_alias (__openat, __openat64)
+libc_hidden_weak (__openat64)
+weak_alias (__openat, openat64)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/openat64.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/openat64.c
new file mode 100644 (file)
index 0000000..15d9d6a
--- /dev/null
@@ -0,0 +1 @@
+/* openat64 is defined in openat.c as an alias.  */
diff --git a/user/utest/file-posix.c b/user/utest/file-posix.c
new file mode 100644 (file)
index 0000000..59398f3
--- /dev/null
@@ -0,0 +1,51 @@
+#define _LARGEFILE64_SOURCE /* needed to use lseek64 */
+
+#include <stdio.h> 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <arch/arch.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <utest.h>
+
+TEST_SUITE("FILE POSIX");
+
+/* <--- Begin definition of test cases ---> */
+
+bool test_openat(void)
+{
+       int dfd = open("/dir1", O_RDONLY);
+       if (dfd < 0) {
+               perror("open dir1");
+               return FALSE;
+       }
+       int ffd = openat(dfd, "f1.txt", O_RDWR);
+       if (ffd < 0) {
+               perror("open f1.txt");
+               close(dfd);
+               return FALSE;
+       }
+       close(ffd);
+       close(dfd);
+       return TRUE;
+}
+
+/* <--- End definition of test cases ---> */
+
+struct utest utests[] = {
+       UTEST_REG(openat),
+};
+int num_utests = sizeof(utests) / sizeof(struct utest);
+
+int main(int argc, char *argv[])
+{
+       // Run test suite passing it all the args as whitelist of what tests to run.
+       char **whitelist = &argv[1];
+       int whitelist_len = argc - 1;
+       RUN_TEST_SUITE(utests, num_utests, whitelist, whitelist_len);
+}