From patchwork Tue Sep 20 18:51:51 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 672412 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3sdsLn04tvz9sC7 for ; Wed, 21 Sep 2016 04:52:16 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b=UTBt75my; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:to:from:subject:message-id:date:mime-version :content-type; q=dns; s=default; b=N0isVldi/IqbJbtHwqc+OfJIQ/loU TwvqWdsteymkQxeBpevyWf7EdAUFi54YjK1Rb9y3ykWpct1m5sHPCUOaCNRoqrzP io4J60igZEVJnRm3huLI3sfdSx9TB490MYUBXqHeIbNs7wOOrKrski4WjsZS2BeP aihw1ae8kcpoms= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:to:from:subject:message-id:date:mime-version :content-type; s=default; bh=7AMZc7hQtNxjOu4mAoRZXQPn3zE=; b=UTB t75mytUlK6QfLOHrs6yegXrJRLiDhAAXjcG/M+bFvEBuQ5wCYJPFCXXGHHl7ZFAb +8RPMFrw1N1kW5xtWhZvjntVcp9xgBDdK07GAH7MnOYPkIoaB2mfK1/cmUZEYknD 6r1vdrnxWoRHeqcoSTVhvVgxqBUnS8xJrWD28bCg= Received: (qmail 74828 invoked by alias); 20 Sep 2016 18:52:05 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 74757 invoked by uid 89); 20 Sep 2016 18:52:04 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-5.0 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=hats, 3.10, objpfx X-HELO: mx1.redhat.com To: GNU C Library From: Florian Weimer Subject: [PATCH] Add test case for O_TMPFILE handling in open, openat Message-ID: Date: Tue, 20 Sep 2016 20:51:51 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.3.0 MIME-Version: 1.0 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 * 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 + . */ + +#include +#include +#include +#include +#include +#include +#include + +#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"