diff options
Diffstat (limited to 'io/tst-open-tmpfile.c')
-rw-r--r-- | io/tst-open-tmpfile.c | 318 |
1 files changed, 0 insertions, 318 deletions
diff --git a/io/tst-open-tmpfile.c b/io/tst-open-tmpfile.c deleted file mode 100644 index 485109706f..0000000000 --- a/io/tst-open-tmpfile.c +++ /dev/null @@ -1,318 +0,0 @@ -/* Test open and openat with O_TMPFILE. - Copyright (C) 2016-2017 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/>. */ - -/* This test verifies that open and openat work as expected, i.e. they - create a deleted file with the requested file mode. */ - -#include <errno.h> -#include <fcntl.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> - -#include <support/support.h> - -#ifdef O_TMPFILE -typedef int (*wrapper_func) (const char *, int, mode_t); - -/* Error-checking wrapper for the open function, compatible with the - wrapper_func type. */ -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; -} - -/* Error-checking wrapper for the openat function, compatible with the - wrapper_func type. */ -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; -} - -/* Error-checking wrapper for the open64 function, compatible with the - wrapper_func type. */ -static int -wrap_open64 (const char *path, int flags, mode_t mode) -{ - int ret = open64 (path, flags, mode); - if (ret < 0) - { - printf ("error: open64 (\"%s\", 0x%x, 0%03o): %m\n", path, flags, mode); - exit (1); - } - return ret; -} - -/* Error-checking wrapper for the openat64 function, compatible with the - wrapper_func type. */ -static int -wrap_openat64 (const char *path, int flags, mode_t mode) -{ - int ret = openat64 (AT_FDCWD, path, flags, mode); - if (ret < 0) - { - printf ("error: openat64 (\"%s\", 0x%x, 0%03o): %m\n", path, flags, mode); - exit (1); - } - return ret; -} - -/* Return true if FD is flagged as deleted in /proc/self/fd, false if - not. */ -static bool -is_file_deteted (int fd) -{ - char *proc_fd_path = xasprintf ("/proc/self/fd/%d", fd); - char file_path[4096]; - ssize_t file_path_length - = readlink (proc_fd_path, file_path, sizeof (file_path)); - if (file_path_length < 0) - { - printf ("error: readlink (\"%s\"): %m", proc_fd_path); - free (proc_fd_path); - exit (1); - } - free (proc_fd_path); - if (file_path_length == sizeof (file_path)) - { - printf ("error: path in /proc resolves to overlong file name: %.*s\n", - (int) file_path_length, file_path); - exit (1); - } - const char *deleted = " (deleted)"; - if (file_path_length < strlen (deleted)) - { - printf ("error: path in /proc is too short: %.*s\n", - (int) file_path_length, file_path); - exit (1); - } - return memcmp (file_path + file_path_length - strlen (deleted), - deleted, strlen (deleted)) == 0; -} - -/* Obtain a file name which is difficult to guess. */ -static char * -get_random_name (void) -{ - unsigned long long bytes[2]; - int random_device = open ("/dev/urandom", O_RDONLY); - if (random_device < 0) - { - printf ("error: open (\"/dev/urandom\"): %m\n"); - exit (1); - } - ssize_t ret = read (random_device, bytes, sizeof (bytes)); - if (ret < 0) - { - printf ("error: read (\"/dev/urandom\"): %m\n"); - exit (1); - } - if (ret != sizeof (bytes)) - { - printf ("error: short read from /dev/urandom: %zd\n", ret); - exit (1); - } - close (random_device); - return xasprintf ("tst-open-tmpfile-%08llx%08llx.tmp", bytes[0], bytes[1]); -} - -/* Check open/openat (as specified by OP and WRAPPER) with a specific - PATH/FLAGS/MODE combination. */ -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); - } - - /* Verify that the mode was correctly processed. */ - 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); - } - - /* Check that the file is marked as deleted in /proc. */ - if (!is_file_deteted (fd)) - { - printf ("error: path in /proc is not marked as deleted\n"); - exit (1); - } - - /* Check that the file can be turned into a regular file with - linkat. Open a file descriptor for the directory at PATH. Use - AT_FDCWD if PATH is ".", to exercise that functionality as - well. */ - int path_fd; - if (strcmp (path, ".") == 0) - path_fd = AT_FDCWD; - else - { - path_fd = open (path, O_RDONLY | O_DIRECTORY); - if (path_fd < 0) - { - printf ("error: open (\"%s\"): %m\n", path); - exit (1); - } - } - - /* Use a hard-to-guess name for the new directory entry. */ - char *new_name = get_random_name (); - - /* linkat does not require privileges if the path in /proc/self/fd - is used. */ - char *proc_fd_path = xasprintf ("/proc/self/fd/%d", fd); - if (linkat (AT_FDCWD, proc_fd_path, path_fd, new_name, - AT_SYMLINK_FOLLOW) == 0) - { - if (unlinkat (path_fd, new_name, 0) != 0 && errno != ENOENT) - { - printf ("error: unlinkat (\"%s/%s\"): %m\n", path, new_name); - exit (1); - } - } - else - { - /* linkat failed. This is expected if O_EXCL was specified. */ - if ((flags & O_EXCL) == 0) - { - printf ("error: linkat failed after %s (\"%s\", 0x%x, 0%03o): %m\n", - op, path, flags, mode); - exit (1); - } - } - - free (proc_fd_path); - free (new_name); - if (path_fd != AT_FDCWD) - close (path_fd); - close (fd); -} - -/* Check OP/WRAPPER with various flags at a specific PATH and - MODE. */ -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_WRONLY, mode); - check_wrapper_flags_mode (op, wrapper, path, O_WRONLY | O_EXCL, mode); - check_wrapper_flags_mode (op, wrapper, path, O_RDWR, mode); - check_wrapper_flags_mode (op, wrapper, path, O_RDWR | O_EXCL, mode); -} - -/* Check open/openat with varying permissions. */ -static void -check_wrapper (const char *op, wrapper_func wrapper, - const char *path) -{ - printf ("info: testing %s at: %s\n", op, 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); -} - -/* Verify that the directory at PATH supports O_TMPFILE. Exit with - status 77 (unsupported) if the kernel does not support O_TMPFILE. - Even with kernel support, not all file systems O_TMPFILE, so return - true if the directory supports O_TMPFILE, false if not. */ -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]); - check_wrapper ("open64", wrap_open64, paths[i]); - check_wrapper ("openat64", wrap_openat64, paths[i]); - } - - if (!supported) - return 77; - - return 0; -} - -#else /* !O_TMPFILE */ - -static int -do_test (void) -{ - return 77; -} - -#endif /* O_TMPFILE */ - -#include <support/test-driver.c> |