This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Add test case for O_TMPFILE handling in open, openat


I noticed that we do not seem to have a test case for O_TMPFILE handling.

I have tested the attached patch with recent kernels and Red Hat's 3.10 kernels (where it prints UNSUPPORTED). I verified that probe_path works as intended with a vfat file system (which does not support O_TMPFILE even on a supported kernel).

Thanks,
Florian
Add test case for O_TMPFILE handling in open, openat

2016-09-20  Florian Weimer  <fweimer@redhat.com>

	* io/tst-open-tmpfile.c: New test.
	* io/Makefile (tests): Add it.

diff --git a/io/Makefile b/io/Makefile
index deb6100..f5977af 100644
--- a/io/Makefile
+++ b/io/Makefile
@@ -71,7 +71,8 @@ tests		:= test-utime test-stat test-stat2 test-lfs tst-getcwd \
 		   tst-renameat tst-fchownat tst-fchmodat tst-faccessat \
 		   tst-symlinkat tst-linkat tst-readlinkat tst-mkdirat \
 		   tst-mknodat tst-mkfifoat tst-ttyname_r bug-ftw5 \
-		   tst-posix_fallocate tst-fts tst-fts-lfs
+		   tst-posix_fallocate tst-fts tst-fts-lfs \
+		   tst-open-tmpfile
 
 ifeq ($(run-built-tests),yes)
 tests-special += $(objpfx)ftwtest.out
diff --git a/io/tst-open-tmpfile.c b/io/tst-open-tmpfile.c
new file mode 100644
index 0000000..33ec4ab
--- /dev/null
+++ b/io/tst-open-tmpfile.c
@@ -0,0 +1,151 @@
+/* Test open and openat with O_TMPFILE.
+   Copyright (C) 2016 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 <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#ifdef O_TMPFILE
+static int
+wrap_open (const char *path, int flags, mode_t mode)
+{
+  int ret = open (path, flags, mode);
+  if (ret < 0)
+    {
+      printf ("error: open (\"%s\", 0x%x, 0%03o): %m\n", path, flags, mode);
+      exit (1);
+    }
+  return ret;
+}
+
+static int
+wrap_openat (const char *path, int flags, mode_t mode)
+{
+  int ret = openat (AT_FDCWD, path, flags, mode);
+  if (ret < 0)
+    {
+      printf ("error: openat (\"%s\", 0x%x, 0%03o): %m\n", path, flags, mode);
+      exit (1);
+    }
+  return ret;
+}
+
+typedef int (*wrapper_func) (const char *, int, mode_t);
+
+static void
+check_wrapper_flags_mode (const char *op, wrapper_func wrapper,
+                          const char *path, int flags, mode_t mode)
+{
+  int fd = wrapper (path, flags | O_TMPFILE, mode);
+  struct stat64 st;
+  if (fstat64 (fd, &st) != 0)
+    {
+      printf ("error: fstat64: %m\n");
+      exit (1);
+    }
+  int actual_mode = st.st_mode & 0777;
+  if (actual_mode != mode)
+    {
+      printf ("error: unexpected mode; expected 0%03o, actual 0%03o\n",
+              mode, actual_mode);
+      exit (1);
+    }
+  close (fd);
+}
+
+    static void
+check_wrapper_mode (const char *op, wrapper_func wrapper,
+                    const char *path, mode_t mode)
+{
+  check_wrapper_flags_mode (op, wrapper, path, O_RDWR, mode);
+  check_wrapper_flags_mode (op, wrapper, path, O_RDWR | O_EXCL, mode);
+}
+
+static void
+check_wrapper (const char *op, wrapper_func wrapper,
+                    const char *path)
+{
+  check_wrapper_mode (op, wrapper, path, 0);
+  check_wrapper_mode (op, wrapper, path, 0640);
+  check_wrapper_mode (op, wrapper, path, 0600);
+  check_wrapper_mode (op, wrapper, path, 0755);
+  check_wrapper_mode (op, wrapper, path, 0750);
+}
+
+static bool
+probe_path (const char *path)
+{
+  int fd = openat (AT_FDCWD, path, O_TMPFILE | O_RDWR, 0);
+  if (fd < 0)
+    {
+      if (errno == EISDIR)
+        /* The system does not support O_TMPFILE.  */
+        {
+          printf ("info: kernel does not support O_TMPFILE\n");
+          exit (77);
+        }
+      if (errno == EOPNOTSUPP)
+        {
+          printf ("info: path does not support O_TMPFILE: %s\n", path);
+          return false;
+        }
+      printf ("error: openat (\"%s\", O_TMPFILE | O_RDWR): %m\n", path);
+      exit (1);
+    }
+  close (fd);
+  return true;
+}
+
+static int
+do_test (void)
+{
+  umask (0);
+  const char *paths[] = { ".", "/dev/shm", "/tmp",
+                          getenv ("TEST_TMPFILE_PATH"),
+                          NULL };
+  bool supported = false;
+  for (int i = 0; paths[i] != NULL; ++i)
+    if (probe_path (paths[i]))
+      {
+        supported = true;
+        check_wrapper ("open", wrap_open, paths[i]);
+        check_wrapper ("openat", wrap_openat, paths[i]);
+      }
+
+  if (!supported)
+    return 77;
+
+  return 0;
+}
+
+#else  /* !O_TMPFILE */
+
+static int
+do_test (void)
+{
+  return 77;
+}
+
+#endif  /* O_TMPFILE */
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]