Skip to contentSkip to conversation

add open/openat + O_TMPFILE tests

PATCH Superseded Alexey Kodanev 3 participants 13 messages Jan 29, 2016 – Apr 26, 2016 Library code

lore
Share & tools
lore
#0 lore raw

v3 cover add open/openat + O_TMPFILE tests

v3:
* squash last patch into the previous,
* open: make use of SAFE_OPEN during the test,
* openat: add tst_openat_tmp(int mode),
* remove test_dir, use ".",
* use tst_brkm(TFAIL, ...) for test assertions,
* strncmp() -> memcpy(),
* more verbose test-case's TPASS message.

v2:
* move dir_not_empty() -> tst_dir_is_empty() to a library,
* add SAFE_LINKAT, SAFE_READLINK macros,
* move O_TMPFILE definition to lapi/fcntl.h
* use relative path for test_dir,
* enable len_strict in SAFE_WRITE,
* set constant buffer size.

Alexey Kodanev (5):
lib/tst_dir_is_empty: add a library function include/lapi/fcntl.h: add O_TMPFILE definition lib/safe_macros: add linkat()
lib/safe_macros: add readlink() kernel/syscalls: add new test with 'open() + O_TMPFILE'

 include/lapi/fcntl.h                        |    4 +
 include/safe_macros.h                       |   13 ++
 include/test.h                              |    8 +
 lib/safe_macros.c                           |   35 ++++
 lib/tst_dir_is_empty.c                      |   49 +++++
 runtest/syscalls                            |    2 +
 testcases/kernel/syscalls/.gitignore        |    2 +
 testcases/kernel/syscalls/open/open14.c     |  253 ++++++++++++++++++++++++++
 testcases/kernel/syscalls/openat/openat03.c |  263 +++++++++++++++++++++++++++
 9 files changed, 629 insertions(+), 0 deletions(-)
 create mode 100644 lib/tst_dir_is_empty.c
 create mode 100644 testcases/kernel/syscalls/open/open14.c
 create mode 100644 testcases/kernel/syscalls/openat/openat03.c
#1 lore raw

PATCH v3 1/5 lib/tst_dir_is_empty: add a library function

Checks if a given directory is empty.

---
 include/test.h         |    8 +++++++
 lib/tst_dir_is_empty.c |   49 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 0 deletions(-)
 create mode 100644 lib/tst_dir_is_empty.c
include/test.h +8 -0
index fc07dae..c364b75 100644
@@ -441,6 +441,14 @@ int tst_fs_fill_hardlinks(void (*cleanup) (void), const char *dir);
 int tst_fs_fill_subdirs(void (*cleanup) (void), const char *dir);
 
 /*
+ * lib/tst_dir_is_empty.c
+ *
+ * Checks if a given directory contains any entities,
+ * returns 1 if directory is empty, 0 otherwise
+ */
+int tst_dir_is_empty(void (*cleanup) (void), const char *name, int verbose);
+
+/*
  * lib/tst_pid.c
  *
  * Get a pid value not used by the OS
lib/tst_dir_is_empty.c new file +49 -0

49 lines not on this page · raw message

Signature · 1 line
1.7.1
#2 lore raw

PATCH v3 2/5 include/lapi/fcntl.h: add O_TMPFILE definition

In reply to Alexey Kodanev
---
 include/lapi/fcntl.h |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
include/lapi/fcntl.h +4 -0
index d0bb713..1ea3fb4 100644
@@ -23,6 +23,10 @@
 # define O_CLOEXEC 02000000
 #endif
 
+#ifndef O_TMPFILE
+# define O_TMPFILE (020000000 | O_DIRECTORY)
+#endif
+
 #ifndef F_DUPFD_CLOEXEC
 # define F_DUPFD_CLOEXEC 1030
 #endif
Signature · 1 line
1.7.1
#3 lore raw

PATCH v3 3/5 lib/safe_macros: add linkat()

In reply to Alexey Kodanev
---
 include/safe_macros.h |    7 +++++++
 lib/safe_macros.c     |   18 ++++++++++++++++++
 2 files changed, 25 insertions(+), 0 deletions(-)
include/safe_macros.h +7 -0
index ab09699..e4041d4 100644
@@ -157,6 +157,13 @@ int	safe_link(const char *file, const int lineno,
 #define SAFE_LINK(cleanup_fn, oldpath, newpath) \
         safe_link(__FILE__, __LINE__, cleanup_fn, (oldpath), (newpath))
 
+int	safe_linkat(const char *file, const int lineno,
+		    void (cleanup_fn)(void), int olddirfd, const char *oldpath,
+		    int newdirfd, const char *newpath, int flags);
+#define SAFE_LINKAT(cleanup_fn, olddirfd, oldpath, newdirfd, newpath, flags) \
+	safe_linkat(__FILE__, __LINE__, cleanup_fn, (olddirfd), (oldpath), \
+		    (newdirfd), (newpath), (flags))
+
 int	safe_symlink(const char *file, const int lineno,
                      void (cleanup_fn)(void), const char *oldpath,
                      const char *newpath);
lib/safe_macros.c +18 -0
index 173d72f..9fa6ac4 100644
@@ -391,6 +391,24 @@ int safe_link(const char *file, const int lineno,
 	return rval;
 }
 
+int safe_linkat(const char *file, const int lineno,
+		void (cleanup_fn)(void), int olddirfd, const char *oldpath,
+		int newdirfd, const char *newpath, int flags)
+{
+	int rval;
+
+	rval = linkat(olddirfd, oldpath, newdirfd, newpath, flags);
+
+	if (rval == -1) {
+		tst_brkm(TBROK | TERRNO, cleanup_fn,
+			 "%s:%d: linkat(%d,%s,%d,%s,%d) failed",
+			 file, lineno, olddirfd, oldpath, newdirfd,
+			 newpath, flags);
+	}
+
+	return rval;
+}
+
 int safe_symlink(const char *file, const int lineno,
                  void (cleanup_fn)(void), const char *oldpath,
                  const char *newpath)
Signature · 1 line
1.7.1
#4 lore raw

PATCH v3 4/5 lib/safe_macros: add readlink()

In reply to Alexey Kodanev
---
 include/safe_macros.h |    6 ++++++
 lib/safe_macros.c     |   17 +++++++++++++++++
 2 files changed, 23 insertions(+), 0 deletions(-)
include/safe_macros.h +6 -0
index e4041d4..8545c97 100644
@@ -164,6 +164,12 @@ int	safe_linkat(const char *file, const int lineno,
 	safe_linkat(__FILE__, __LINE__, cleanup_fn, (olddirfd), (oldpath), \
 		    (newdirfd), (newpath), (flags))
 
+ssize_t	safe_readlink(const char *file, const int lineno,
+		      void (cleanup_fn)(void), const char *path,
+		      char *buf, size_t bufsize);
+#define SAFE_READLINK(cleanup_fn, path, buf, bufsize) \
+	safe_readlink(__FILE__, __LINE__, cleanup_fn, (path), (buf), (bufsize))
+
 int	safe_symlink(const char *file, const int lineno,
                      void (cleanup_fn)(void), const char *oldpath,
                      const char *newpath);
lib/safe_macros.c +17 -0
index 9fa6ac4..5a05c84 100644
@@ -409,6 +409,23 @@ int safe_linkat(const char *file, const int lineno,
 	return rval;
 }
 
+ssize_t safe_readlink(const char *file, const int lineno,
+		  void (cleanup_fn)(void), const char *path,
+		  char *buf, size_t bufsize)
+{
+	ssize_t rval;
+
+	rval = readlink(path, buf, bufsize);
+
+	if (rval == -1) {
+		tst_brkm(TBROK | TERRNO, cleanup_fn,
+			 "%s:%d: readlink(%s,%p,%zu) failed",
+			 file, lineno, path, buf, bufsize);
+	}
+
+	return rval;
+}
+
 int safe_symlink(const char *file, const int lineno,
                  void (cleanup_fn)(void), const char *oldpath,
                  const char *newpath)
Signature · 1 line
1.7.1
#5 lore raw

PATCH v3 5/5 kernel/syscalls: add new test with 'open() + O_TMPFILE'

In reply to Alexey Kodanev

Test does the following steps:
* create an unnamed temporary file in TMP directory,
* write data into it,
* check that file not visible in the filesystem,
* name the file and check that it becomes visible in FS,
* create multiple directories and related temporary files,
* create multiple directories and link files into them. Check that files permissions correspond to the ones specified with open()/openat().

'openat() + O_TMPFILE' test repeats the same steps.

---
 runtest/syscalls                            |    2 +
 testcases/kernel/syscalls/.gitignore        |    2 +
 testcases/kernel/syscalls/open/open14.c     |  253 ++++++++++++++++++++++++++
 testcases/kernel/syscalls/openat/openat03.c |  263 +++++++++++++++++++++++++++
 4 files changed, 520 insertions(+), 0 deletions(-)
 create mode 100644 testcases/kernel/syscalls/open/open14.c
 create mode 100644 testcases/kernel/syscalls/openat/openat03.c
runtest/syscalls +2 -0
index 7173f22..3439948 100644
@@ -721,10 +721,12 @@ open10 open10
 open11 open11
 open12 open12
 open13 open13
+open14 open14
 
 #openat test cases
 openat01 openat01
 openat02 openat02
+openat03 openat03
 
 mincore01 mincore01
 mincore02 mincore02
testcases/kernel/syscalls/.gitignore +2 -0
index d5f21ef..6451dc4 100644
@@ -624,9 +624,11 @@
 /open/open12
 /open/open12_child
 /open/open13
+/open/open14
 /openat/openat01
 /openat/openat02
 /openat/openat02_child
+/openat/openat03
 /pathconf/pathconf01
 /pause/pause01
 /pause/pause02
testcases/kernel/syscalls/open/open14.c new file +253 -0

253 lines not on this page · raw message

testcases/kernel/syscalls/openat/openat03.c new file +263 -0

263 lines not on this page · raw message

Signature · 1 line
1.7.1
#6 lore raw

PATCH v3 5/5 kernel/syscalls: add new test with 'open() + O_TMPFILE'

Hi!

Quoted 112 lines
testcases/kernel/syscalls/open/open14.c new file +112 -0
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "test.h"
+#include "safe_macros.h"
+#include "lapi/fcntl.h"
+
+char *TCID = "open14";
+int TST_TOTAL = 3;
+static ssize_t size;
+static char buf[1024];
+static const ssize_t blocks_num = 4;
+static struct stat st;
+
+static void cleanup(void)
+{
+	tst_rmdir();
+}
+
+static void setup(void)
+{
+	tst_tmpdir();
+
+	size = sizeof(buf);
+
+	memset(buf, 1, size);
+
+	int fd = open(".", O_TMPFILE | O_RDWR, 0600);
+
+	if (fd == -1) {
+		if (errno == EISDIR)
+			tst_brkm(TCONF, cleanup, "O_TMPFILE not supported");
+
+		tst_brkm(TBROK | TERRNO, cleanup, "open() failed");
+	}
+
+	SAFE_CLOSE(cleanup, fd);
+}
+
+static void write_file(int fd)
+{
+	int i;
+
+	for (i = 0; i < blocks_num; ++i)
+		SAFE_WRITE(cleanup, 1, fd, buf, size);
+}
+
+void test01(void)
+{
+	int fd;
+	char path[PATH_MAX], tmp[PATH_MAX];
+
+	tst_resm(TINFO, "creating a file with O_TMPFILE flag");
+	fd = SAFE_OPEN(cleanup, ".", O_TMPFILE | O_RDWR, 0600);
+
+	tst_resm(TINFO, "writing data to the file");
+	write_file(fd);
+
+	SAFE_FSTAT(cleanup, fd, &st);
+	tst_resm(TINFO, "file size is '%zu'", st.st_size);
+
+	if (st.st_size != blocks_num * size) {
+		tst_resm(TFAIL, "not expected size: '%zu' != '%zu'",
+			 st.st_size, blocks_num * size);
+		SAFE_CLOSE(cleanup, fd);
+		return;
+	}
+
+	tst_resm(TINFO, "looking for the file in '.'");
+	if (!tst_dir_is_empty(cleanup, ".", 1))
+		tst_brkm(TFAIL, cleanup, "found a file, this is not expected");
+	tst_resm(TINFO, "file not found, OK");
+
+	snprintf(path, PATH_MAX,  "/proc/self/fd/%d", fd);
+	SAFE_READLINK(cleanup, path, tmp, PATH_MAX);
+
+	tst_resm(TINFO, "renaming '%s' -> 'tmpfile'", tmp);
+	SAFE_LINKAT(cleanup, AT_FDCWD, path, AT_FDCWD, "tmpfile",
+		    AT_SYMLINK_FOLLOW);
+
+	if (tst_dir_is_empty(cleanup, ".", 1))
+		tst_brkm(TFAIL, cleanup, "file not found");
+
+	SAFE_UNLINK(cleanup, "tmpfile");
+	SAFE_CLOSE(cleanup, fd);
+
+	tst_resm(TPASS, "single file tests passed");
+}
+
+static void read_file(int fd)
+{
+	int i;
+	char tmp[size];
+
+	SAFE_LSEEK(cleanup, fd, 0, SEEK_SET);
+
+	for (i = 0; i < blocks_num; ++i) {
+		SAFE_READ(cleanup, 0, fd, tmp, size);
+		if (memcmp(buf, tmp, size))
+			tst_brkm(TFAIL, cleanup, "got unexepected data");
+	}
+}
+
+static void test02(void)
+{
+	const int files_num = 100;
+	int i, fd[files_num];
+	char path[PATH_MAX];

testcases/kernel/syscalls/open/open14.c line 142

Quoted 10 lines
testcases/kernel/syscalls/open/open14.c new file +10 -0
+
+	tst_resm(TINFO, "create files in multiple directories");
+	for (i = 0; i < files_num; ++i) {
+		snprintf(path, PATH_MAX, "tst02_%d", i);
+		SAFE_MKDIR(cleanup, path, 0700);
+		SAFE_CHDIR(cleanup, path);
+
+		fd[i] = SAFE_OPEN(cleanup, ".", O_TMPFILE | O_RDWR, 0600);
+
+		write_file(fd[i]);

We don't have to write the file here, if I'm not mistaken.

Quoted 46 lines
testcases/kernel/syscalls/open/open14.c new file +46 -0
+	}
+
+	tst_resm(TINFO, "removing test directories");
+	for (i = files_num - 1; i >= 0; --i) {
+		SAFE_CHDIR(cleanup, "..");
+		snprintf(path, PATH_MAX, "tst02_%d", i);
+		SAFE_RMDIR(cleanup, path);
+	}
+
+	tst_resm(TINFO, "writing/reading temporary files");
+	for (i = 0; i < files_num; ++i) {
+		write_file(fd[i]);
+		read_file(fd[i]);
+	}
+
+	tst_resm(TINFO, "closing temporary files");
+	for (i = 0; i < files_num; ++i)
+		SAFE_CLOSE(cleanup, fd[i]);
+
+	tst_resm(TPASS, "multiple files tests passed");
+}
+
+static void link_tmp_file(int fd)
+{
+	char path1[PATH_MAX], path2[PATH_MAX];
+
+	snprintf(path1, PATH_MAX,  "/proc/self/fd/%d", fd);
+	snprintf(path2, PATH_MAX,  "tmpfile_%d", fd);
+
+	SAFE_LINKAT(cleanup, AT_FDCWD, path1, AT_FDCWD, path2,
+		    AT_SYMLINK_FOLLOW);
+}
+
+static const int tst_perm[] = { 0, 07777, 001, 0755, 0644, 0440 };
+
+static void test03(void)
+{
+	const int files_num = 100;
+	int i, fd[files_num];
+	char path[PATH_MAX];
+	struct stat st;
+	unsigned int j;
+	mode_t mask = umask(0);
+
+	umask(mask);
+

testcases/kernel/syscalls/open/open14.c line 198

Quoted 10 lines
testcases/kernel/syscalls/open/open14.c new file +10 -0
+	tst_resm(TINFO, "create multiple directories, link files into them");
+	tst_resm(TINFO, "and check file permissions");
+	for (i = 0, j = 0; i < files_num; ++i) {
+
+		snprintf(path, PATH_MAX, "tst03_%d", i);
+		SAFE_MKDIR(cleanup, path, 0700);
+		SAFE_CHDIR(cleanup, path);
+
+		fd[i] = SAFE_OPEN(cleanup, ".", O_TMPFILE | O_RDWR,
+				  tst_perm[j]);

You can just use i % ARRAY_SIZE(tst_perms) instead of the j variable.

Quoted 124 lines
testcases/kernel/syscalls/open/open14.c new file +55 -0
+
+		write_file(fd[i]);
+		read_file(fd[i]);
+
+		link_tmp_file(fd[i]);
+
+		snprintf(path, PATH_MAX, "tmpfile_%d", fd[i]);
+
+		SAFE_LSTAT(cleanup, path, &st);
+
+		mode_t exp_mode = tst_perm[j] & ~mask;
+
+		if ((st.st_mode & ~S_IFMT) != exp_mode) {
+			tst_brkm(TFAIL, cleanup,
+				"file mode read %o, but expected %o",
+				st.st_mode & ~S_IFMT, exp_mode);
+		}
+
+		if (++j >= ARRAY_SIZE(tst_perm))
+			j = 0;
+	}
+
+	tst_resm(TINFO, "remove files, directories");
+	for (i = files_num - 1; i >= 0; --i) {
+		snprintf(path, PATH_MAX, "tmpfile_%d", fd[i]);
+		SAFE_UNLINK(cleanup, path);
+		SAFE_CLOSE(cleanup, fd[i]);
+
+		SAFE_CHDIR(cleanup, "..");
+
+		snprintf(path, PATH_MAX, "tst03_%d", i);
+		SAFE_RMDIR(cleanup, path);
+	}
+
+	tst_resm(TPASS, "file permission tests passed");
+}
+
+int main(int ac, char *av[])
+{
+	int lc;
+
+	tst_parse_opts(ac, av, NULL, NULL);
+
+	setup();
+
+	for (lc = 0; TEST_LOOPING(lc); ++lc) {
+		tst_count = 0;
+		test01();
+		test02();
+		test03();
+	}
+
+	cleanup();
+	tst_exit();
+}
testcases/kernel/syscalls/openat/openat03.c new file +63 -0
new file mode 100644
index 0000000..441c84b
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2015-2016 Oracle and/or its affiliates. All Rights Reserved.
+ *
+ * This program 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 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Alexey Kodanev <[email protected]>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "test.h"
+#include "safe_macros.h"
+#include "lapi/fcntl.h"
+#include "openat.h"
+
+char *TCID = "openat03";
+int TST_TOTAL = 3;
+static ssize_t size;
+static char buf[1024];
+static const ssize_t blocks_num = 4;
+static struct stat st;
+
+static void cleanup(void)
+{
+	tst_rmdir();
+}
+
+static void setup(void)
+{
+	tst_tmpdir();
+
+	size = sizeof(buf);
+
+	memset(buf, 1, size);
+
+	int fd = openat(AT_FDCWD, ".", O_TMPFILE | O_RDWR, 0600);
+
+	if (fd == -1) {
+		if (errno == EISDIR)
+			tst_brkm(TCONF, cleanup, "O_TMPFILE not supported");
+
+		tst_brkm(TBROK | TERRNO, cleanup, "openat() failed");
+	}
+
+	SAFE_CLOSE(cleanup, fd);
+}

testcases/kernel/syscalls/openat/openat03.c line 73

Quoted 10 lines
testcases/kernel/syscalls/openat/openat03.c new file +10 -0
+
+static int tst_openat_tmp(int mode)
+{
+	int fd = openat(AT_FDCWD, ".", O_TMPFILE | O_RDWR, mode);
+
+	if (fd >= 0)
+		return fd;
+
+	tst_brkm(TBROK | TERRNO, cleanup, "openat() failed");
+}

Any identifier that starts with tst_ or TST_ is reserved for test library. Can you rename it to something else (do_openat) or so that we avoid possible future collision.

Quoted 69 lines
testcases/kernel/syscalls/openat/openat03.c new file +69 -0
+static void write_file(int fd)
+{
+	int i;
+
+	for (i = 0; i < blocks_num; ++i)
+		SAFE_WRITE(cleanup, 1, fd, buf, size);
+}
+
+void test01(void)
+{
+	int fd;
+	char path[PATH_MAX], tmp[PATH_MAX];
+
+	tst_resm(TINFO, "creating a file with O_TMPFILE flag");
+	fd = tst_openat_tmp(0600);
+
+	tst_resm(TINFO, "writing data to the file");
+	write_file(fd);
+
+	SAFE_FSTAT(cleanup, fd, &st);
+	tst_resm(TINFO, "file size is '%zu'", st.st_size);
+
+	if (st.st_size != blocks_num * size) {
+		tst_resm(TFAIL, "not expected size: '%zu' != '%zu'",
+			 st.st_size, blocks_num * size);
+		SAFE_CLOSE(cleanup, fd);
+		return;
+	}
+
+	tst_resm(TINFO, "looking for the file in '.'");
+	if (!tst_dir_is_empty(cleanup, ".", 1))
+		tst_brkm(TFAIL, cleanup, "found a file, this is not expected");
+	tst_resm(TINFO, "file not found, OK");
+
+	snprintf(path, PATH_MAX,  "/proc/self/fd/%d", fd);
+	SAFE_READLINK(cleanup, path, tmp, PATH_MAX);
+
+	tst_resm(TINFO, "renaming '%s' -> 'tmpfile'", tmp);
+	SAFE_LINKAT(cleanup, AT_FDCWD, path, AT_FDCWD, "tmpfile",
+		    AT_SYMLINK_FOLLOW);
+
+	if (tst_dir_is_empty(cleanup, ".", 1))
+		tst_brkm(TFAIL, cleanup, "file not found");
+
+	SAFE_UNLINK(cleanup, "tmpfile");
+	SAFE_CLOSE(cleanup, fd);
+
+	tst_resm(TPASS, "single file tests passed");
+}
+
+static void read_file(int fd)
+{
+	int i;
+	char tmp[size];
+
+	SAFE_LSEEK(cleanup, fd, 0, SEEK_SET);
+
+	for (i = 0; i < blocks_num; ++i) {
+		SAFE_READ(cleanup, 0, fd, tmp, size);
+		if (memcmp(buf, tmp, size))
+			tst_brkm(TFAIL, cleanup, "got unexepected data");
+	}
+}
+
+static void test02(void)
+{
+	const int files_num = 100;
+	int i, fd[files_num];
+	char path[PATH_MAX];

testcases/kernel/syscalls/openat/openat03.c line 153

Quoted 10 lines
testcases/kernel/syscalls/openat/openat03.c new file +10 -0
+
+	tst_resm(TINFO, "create files in multiple directories");
+	for (i = 0; i < files_num; ++i) {
+		snprintf(path, PATH_MAX, "tst02_%d", i);
+		SAFE_MKDIR(cleanup, path, 0700);
+		SAFE_CHDIR(cleanup, path);
+
+		fd[i] = tst_openat_tmp(0600);
+
+		write_file(fd[i]);

Here as well.

Quoted 45 lines
testcases/kernel/syscalls/openat/openat03.c new file +45 -0
+	}
+
+	tst_resm(TINFO, "removing test directories");
+	for (i = files_num - 1; i >= 0; --i) {
+		SAFE_CHDIR(cleanup, "..");
+		snprintf(path, PATH_MAX, "tst02_%d", i);
+		SAFE_RMDIR(cleanup, path);
+	}
+
+	tst_resm(TINFO, "writing/reading temporary files");
+	for (i = 0; i < files_num; ++i) {
+		write_file(fd[i]);
+		read_file(fd[i]);
+	}
+
+	tst_resm(TINFO, "closing temporary files");
+	for (i = 0; i < files_num; ++i)
+		SAFE_CLOSE(cleanup, fd[i]);
+
+	tst_resm(TPASS, "multiple files tests passed");
+}
+
+static void link_tmp_file(int fd)
+{
+	char path1[PATH_MAX], path2[PATH_MAX];
+
+	snprintf(path1, PATH_MAX,  "/proc/self/fd/%d", fd);
+	snprintf(path2, PATH_MAX,  "tmpfile_%d", fd);
+
+	SAFE_LINKAT(cleanup, AT_FDCWD, path1, AT_FDCWD, path2,
+		    AT_SYMLINK_FOLLOW);
+}
+
+static const int tst_perm[] = { 0, 07777, 001, 0755, 0644, 0440 };
+
+static void test03(void)
+{
+	const int files_num = 100;
+	int i, fd[files_num];
+	char path[PATH_MAX];
+	struct stat st;
+	unsigned int j;
+	mode_t mask = umask(0);
+
+	umask(mask);

testcases/kernel/syscalls/openat/openat03.c line 208

Quoted 10 lines
testcases/kernel/syscalls/openat/openat03.c new file +10 -0
+
+	tst_resm(TINFO, "create multiple directories, link files into them");
+	tst_resm(TINFO, "and check file permissions");
+	for (i = 0, j = 0; i < files_num; ++i) {
+
+		snprintf(path, PATH_MAX, "tst03_%d", i);
+		SAFE_MKDIR(cleanup, path, 0700);
+		SAFE_CHDIR(cleanup, path);
+
+		fd[i] = tst_openat_tmp(tst_perm[j]);

Here as well.

Quoted 44 lines
testcases/kernel/syscalls/openat/openat03.c new file +44 -0
+		write_file(fd[i]);
+		read_file(fd[i]);
+
+		link_tmp_file(fd[i]);
+
+		snprintf(path, PATH_MAX, "tmpfile_%d", fd[i]);
+
+		SAFE_LSTAT(cleanup, path, &st);
+
+		mode_t exp_mode = tst_perm[j] & ~mask;
+
+		if ((st.st_mode & ~S_IFMT) != exp_mode) {
+			tst_brkm(TFAIL, cleanup,
+				"file mode read %o, but expected %o",
+				st.st_mode & ~S_IFMT, exp_mode);
+		}
+
+		if (++j >= ARRAY_SIZE(tst_perm))
+			j = 0;
+	}
+
+	tst_resm(TINFO, "remove files, directories");
+	for (i = files_num - 1; i >= 0; --i) {
+		snprintf(path, PATH_MAX, "tmpfile_%d", fd[i]);
+		SAFE_UNLINK(cleanup, path);
+		SAFE_CLOSE(cleanup, fd[i]);
+
+		SAFE_CHDIR(cleanup, "..");
+
+		snprintf(path, PATH_MAX, "tst03_%d", i);
+		SAFE_RMDIR(cleanup, path);
+	}
+
+	tst_resm(TPASS, "file permission tests passed");
+}
+
+int main(int ac, char *av[])
+{
+	int lc;
+
+	tst_parse_opts(ac, av, NULL, NULL);
+
+	setup();
+

testcases/kernel/syscalls/openat/openat03.c line 261

Quoted 10 lines
testcases/kernel/syscalls/openat/openat03.c new file +10 -0
+	for (lc = 0; TEST_LOOPING(lc); ++lc) {
+		tst_count = 0;
+		test01();
+		test02();
+		test03();
+	}
+
+	cleanup();
+	tst_exit();
+}

The rest of the patchset looks good.

Acked with the minor issues I pointed out fixed.

Signature · 2 lines
Cyril Hrubis
[email protected]
#7 lore raw

PATCH v3 5/5 kernel/syscalls: add new test with 'open() + O_TMPFILE'

Hi,

Quoted 2 lines · Cyril Hrubis

The rest of the patchset looks good.
Acked with the minor issues I pointed out fixed.

Thank you for review, fixed patch-set applied.

Best regards,
Alexey

#8 lore raw

PATCH v3 5/5 kernel/syscalls: add new test with 'open() + O_TMPFILE'

In reply to Alexey Kodanev

----- Original Message -----

Quoted 16 lines

From: "Alexey Kodanev" <[email protected]>
To: [email protected]
Cc: "vasily isaenko" <[email protected]>
Sent: Friday, 29 January, 2016 1:05:50 PM
Subject: [LTP] [PATCH v3 5/5] kernel/syscalls: add new test with 'open() + O_TMPFILE'

Test does the following steps:
* create an unnamed temporary file in TMP directory,
* write data into it,
* check that file not visible in the filesystem,
* name the file and check that it becomes visible in FS,
* create multiple directories and related temporary files,
* create multiple directories and link files into them. Check that files permissions correspond to the ones specified with open()/openat().

Quoted 3 lines

'openat() + O_TMPFILE' test repeats the same steps.

Alexey,

do you know if this maybe depends on some config option or support on glibc side?

I'm running 4.5 kernel and both open14 and openat03 are failing for me. I tried xfs and ext4, both failed.

...

chdir("/tmp/opepC2qHH")                 = 0
openat(AT_FDCWD, ".", O_RDWR|O_DIRECTORY|0x400000) = 3
close(3)                                = 0
umask(0)                                = 022
umask(022)                              = 0

fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0 mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x3ff816c0000
write(1, "open14 0 TINFO : create "..., 75open14 0 TINFO : create multiple directories, link files into them
) = 75
write(1, "open14 0 TINFO : and che"..., 52open14 0 TINFO : and check file permissions
) = 52

mkdirat(AT_FDCWD, "tst03_0", 0700)      = 0
chdir("tst03_0")                        = 0
openat(AT_FDCWD, ".", O_RDWR|O_DIRECTORY|0x400000) = 3

write(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024 write(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024 write(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024 write(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024
lseek(3, 0, SEEK_SET) = 0
read(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024 read(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024 read(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024 read(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024 linkat(AT_FDCWD, "/proc/self/fd/3", AT_FDCWD, "tmpfile_3", AT_SYMLINK_FOLLOW) = 0 newfstatat(AT_FDCWD, "tmpfile_3", {st_mode=S_IFREG, st_size=4096, ...}, AT_SYMLINK_NOFOLLOW) = 0
write(1, "open14 1 TFAIL : open14."..., 74open14 1 TFAIL : open14.c:212: file mode read 0, but expected 755

Regards,
Jan

#9 lore raw

PATCH v3 5/5 kernel/syscalls: add new test with 'open() + O_TMPFILE'

Hi!

Quoted 2 lines

I'm running 4.5 kernel and both open14 and openat03 are failing for me. I tried xfs and ext4, both failed.

For me openat03 fails on ext4 and tmpfs as well but open14 works fine on 4.1.13. Which is kind of strange.

Signature · 2 lines
Cyril Hrubis
[email protected]
#10 lore raw

PATCH v3 5/5 kernel/syscalls: add new test with 'open() + O_TMPFILE'

In reply to Jan Stancek

Hi Jan,

Quoted 46 lines · Jan Stancek

----- Original Message -----

Quoted 16 lines

From: "Alexey Kodanev" <[email protected]>
To: [email protected]
Cc: "vasily isaenko" <[email protected]>
Sent: Friday, 29 January, 2016 1:05:50 PM
Subject: [LTP] [PATCH v3 5/5] kernel/syscalls: add new test with 'open() + O_TMPFILE'

Test does the following steps:
* create an unnamed temporary file in TMP directory,
* write data into it,
* check that file not visible in the filesystem,
* name the file and check that it becomes visible in FS,
* create multiple directories and related temporary files,
* create multiple directories and link files into them. Check that files permissions correspond to the ones specified with open()/openat().

Quoted 3 lines

'openat() + O_TMPFILE' test repeats the same steps.

Alexey,

do you know if this maybe depends on some config option or support on glibc side?

I'm running 4.5 kernel and both open14 and openat03 are failing for me. I tried xfs and ext4, both failed.

...

chdir("/tmp/opepC2qHH")                 = 0
openat(AT_FDCWD, ".", O_RDWR|O_DIRECTORY|0x400000) = 3
close(3)                                = 0
umask(0)                                = 022
umask(022)                              = 0

fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0 mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x3ff816c0000
write(1, "open14 0 TINFO : create "..., 75open14 0 TINFO : create multiple directories, link files into them
) = 75
write(1, "open14 0 TINFO : and che"..., 52open14 0 TINFO : and check file permissions
) = 52

mkdirat(AT_FDCWD, "tst03_0", 0700)      = 0
chdir("tst03_0")                        = 0
openat(AT_FDCWD, ".", O_RDWR|O_DIRECTORY|0x400000) = 3
Quoted 12 lines

write(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024 write(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024 write(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024 write(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024
lseek(3, 0, SEEK_SET) = 0
read(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024 read(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024 read(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024 read(3, "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"..., 1024) = 1024 linkat(AT_FDCWD, "/proc/self/fd/3", AT_FDCWD, "tmpfile_3", AT_SYMLINK_FOLLOW) = 0 newfstatat(AT_FDCWD, "tmpfile_3", {st_mode=S_IFREG, st_size=4096, ...}, AT_SYMLINK_NOFOLLOW) = 0
write(1, "open14 1 TFAIL : open14."..., 74open14 1 TFAIL : open14.c:212: file mode read 0, but expected 755

If the issue with mode... it can be because glibc doesn't process mode argument unless O_CREAT is found. In our case we have O_TMPFILE instead.

Here is the link to bugzilla:

"open() and openat() ignore 'mode' with O_TMPFILE"
https://sourceware.org/bugzilla/show_bug.cgi?id=17523

Thanks,
Alexey

Quoted 2 lines

Regards,
Jan

#11 lore raw

PATCH v3 5/5 kernel/syscalls: add new test with 'open() + O_TMPFILE'

Hi!

Quoted 7 lines

If the issue with mode... it can be because glibc doesn't process mode argument unless O_CREAT is found. In our case we have O_TMPFILE instead.

Here is the link to bugzilla:

"open() and openat() ignore 'mode' with O_TMPFILE"
https://sourceware.org/bugzilla/show_bug.cgi?id=17523

What I see matches the the behavior in Comment 5.

Signature · 2 lines
Cyril Hrubis
[email protected]
#12 lore raw

PATCH v3 5/5 kernel/syscalls: add new test with 'open() + O_TMPFILE'

----- Original Message -----

Quoted 6 lines

From: "Cyril Hrubis" <[email protected]>
To: "Alexey Kodanev" <[email protected]>
Cc: "Jan Stancek" <[email protected]>, "vasily isaenko" <[email protected]>, [email protected]
Sent: Monday, 25 April, 2016 5:07:35 PM
Subject: Re: [LTP] [PATCH v3 5/5] kernel/syscalls: add new test with 'open() + O_TMPFILE'

Quoted 8 lines

Hi!

Quoted 7 lines

If the issue with mode... it can be because glibc doesn't process mode argument unless O_CREAT is found. In our case we have O_TMPFILE instead.

Here is the link to bugzilla:

"open() and openat() ignore 'mode' with O_TMPFILE"
https://sourceware.org/bugzilla/show_bug.cgi?id=17523

Thanks. Jeff Bastian independently found this BZ as well. systemtap confirms, that mode remains 0, even when testcase is passing non-zero values.

sys_openat ., dfd=0xffffffffffffff9c filename=0x40ac50 flags=0x404002 mode=0x0

Quoted 2 lines

What I see matches the the behavior in Comment 5.

I'm on aarch64, so that may explain why both fail for me.

After applying this patch:
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=65f6f938cd562a614a68e15d0581a34b177ec29d
both testcases passed.

Regards,
Jan