linux: Add openat2 (BZ 31664)

It was added on Linux 5.6, as an extension of openat.  Different
than other open-like function, the kernel only provides the LFS
variant (so files larger than 4GB always succeed, as other functions
with offset larget than off_t).  Similar to other open function,
the new symbol is a cancellable entrypoint.

The testcase added only stress some of the syscall provided
functionalities and it is based on existent kernel selftest.  Since
the prototype does not use variadic arguments, there is no need to
add fortify wrapper to catch wrong usages.

Checked on x86_64-linux-gnu.
This commit is contained in:
Adhemerval Zanella 2024-04-23 16:45:59 -03:00
parent f4724843ad
commit 921efb18ef
35 changed files with 482 additions and 0 deletions

4
NEWS
View File

@ -26,6 +26,10 @@ Major new features:
more extensive verification tests for AT_SECURE programs and not meant to
be a security feature.
* On Linux, the openat2 function has been added. It is an extension of
openat and provides a superset of its functionality. It is supported only
in LFS mode and as other open like it is a cancellable entrypoint.
Deprecated and removed features, and other changes affecting compatibility:
* Architectures which use a 32-bit seconds-since-epoch field in struct

View File

@ -133,6 +133,7 @@ sysdep_headers += \
bits/mman-linux.h \
bits/mman-map-flags-generic.h \
bits/mman-shared.h \
bits/openat2.h \
bits/procfs-extra.h \
bits/procfs-id.h \
bits/procfs-prregset.h \
@ -593,6 +594,7 @@ sysdep_routines += \
open_nocancel \
openat64_nocancel \
openat_nocancel \
openat2 \
pread64_nocancel \
read_nocancel \
stat_t64_cp \
@ -607,11 +609,23 @@ sysdep_headers += \
# sysdep_headers
tests += \
tst-openat2 \
tst-fallocate \
tst-fallocate64 \
tst-getcwd-smallbuff \
tst-o_path-locks \
# tests
tests-special += \
$(objpfx)tst-openat2-consts.out \
# tests-special
$(objpfx)tst-openat2-consts.out: ../sysdeps/unix/sysv/linux/tst-openat2-consts.py
$(sysdeps-linux-python) \
../sysdeps/unix/sysv/linux/tst-openat2-consts.py \
$(sysdeps-linux-python-cc) \
< /dev/null > $@ 2>&1; $(evaluate-test)
$(objpfx)tst-openat2-consts.out: $(sysdeps-linux-python-deps)
endif
ifeq ($(subdir),elf)

View File

@ -328,6 +328,9 @@ libc {
posix_spawnattr_getcgroup_np;
posix_spawnattr_setcgroup_np;
}
GLIBC_2.40 {
openat2;
}
GLIBC_PRIVATE {
# functions used in other libraries
__syscall_rt_sigqueueinfo;

View File

@ -2748,3 +2748,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
GLIBC_2.39 stdc_trailing_zeros_ul F
GLIBC_2.39 stdc_trailing_zeros_ull F
GLIBC_2.39 stdc_trailing_zeros_us F
GLIBC_2.40 openat2 F

View File

@ -3095,6 +3095,7 @@ GLIBC_2.4 wcstold F
GLIBC_2.4 wcstold_l F
GLIBC_2.4 wprintf F
GLIBC_2.4 wscanf F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -2509,3 +2509,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
GLIBC_2.39 stdc_trailing_zeros_ul F
GLIBC_2.39 stdc_trailing_zeros_ull F
GLIBC_2.39 stdc_trailing_zeros_us F
GLIBC_2.40 openat2 F

View File

@ -2798,6 +2798,7 @@ GLIBC_2.4 xdrstdio_create F
GLIBC_2.4 xencrypt F
GLIBC_2.4 xprt_register F
GLIBC_2.4 xprt_unregister F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -451,6 +451,28 @@ extern int name_to_handle_at (int __dfd, const char *__name,
extern int open_by_handle_at (int __mountdirfd, struct file_handle *__handle,
int __flags);
#ifdef __has_include
# if __has_include ("linux/openat2.h")
# include "linux/openat2.h"
# define __glibc_has_open_how 1
# endif
#endif
#include <bits/openat2.h>
/* Similar to `openat' but the arguments are packed on HOW with the size
USIZE. If flags and mode from HOW are non-zero, then openat2 operates
like openat.
Unlike openat2, unknown or invalid flags result in an error (EINVAL),
rather than being ignored. The mode must be zero unless one O_CREAT
or O_TMPFILE are set.
The kernel does not support legacy non-LFS interface. */
extern int openat2 (int __dfd, const char *__filename, struct open_how *__how,
size_t __usize)
__nonnull ((2, 3));
#endif /* use GNU */
__END_DECLS

View File

@ -0,0 +1,61 @@
/* openat2 definition. Linux specific.
Copyright (C) 2024 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
<https://www.gnu.org/licenses/>. */
#ifndef _FCNTL_H
# error "Never use <bits/openat2.h> directly; include <fcntl.h> instead."
#endif
#ifndef __glibc_has_open_how
/* Arguments for how openat2 should open the target path. */
struct open_how
{
__uint64_t flags;
__uint64_t mode;
__uint64_t resolve;
};
#endif
/* how->resolve flags for openat2. */
#ifndef RESOLVE_NO_XDEV
# define RESOLVE_NO_XDEV 0x01 /* Block mount-point crossings
(includes bind-mounts). */
#endif
#ifndef RESOLVE_NO_MAGICLINKS
# define RESOLVE_NO_MAGICLINKS 0x02 /* Block traversal through procfs-style
"magic-links". */
#endif
#ifndef RESOLVE_NO_SYMLINKS
# define RESOLVE_NO_SYMLINKS 0x04 /* Block traversal through all symlinks
(implies OEXT_NO_MAGICLINKS). */
#endif
#ifndef RESOLVE_BENEATH
# define RESOLVE_BENEATH 0x08 /* Block "lexical" trickery like
"..", symlinks, and absolute
paths which escape the dirfd. */
#endif
#ifndef RESOLVE_IN_ROOT
# define RESOLVE_IN_ROOT 0x10 /* Make all jumps to "/" and ".."
be scoped inside the dirfd
(similar to chroot). */
#endif
#ifndef RESOLVE_CACHED
# define RESOLVE_CACHED 0x20 /* Only complete if resolution can be
completed through cached lookup. May
return -EAGAIN if that's not
possible. */
#endif

View File

@ -2785,3 +2785,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
GLIBC_2.39 stdc_trailing_zeros_ul F
GLIBC_2.39 stdc_trailing_zeros_ull F
GLIBC_2.39 stdc_trailing_zeros_us F
GLIBC_2.40 openat2 F

View File

@ -2821,6 +2821,7 @@ GLIBC_2.4 sys_errlist D 0x400
GLIBC_2.4 sys_nerr D 0x4
GLIBC_2.4 unlinkat F
GLIBC_2.4 unshare F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -3005,6 +3005,7 @@ GLIBC_2.4 sys_errlist D 0x210
GLIBC_2.4 sys_nerr D 0x4
GLIBC_2.4 unlinkat F
GLIBC_2.4 unshare F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -2269,3 +2269,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
GLIBC_2.39 stdc_trailing_zeros_ul F
GLIBC_2.39 stdc_trailing_zeros_ull F
GLIBC_2.39 stdc_trailing_zeros_us F
GLIBC_2.40 openat2 F

View File

@ -2948,6 +2948,7 @@ GLIBC_2.4 sys_errlist D 0x210
GLIBC_2.4 sys_nerr D 0x4
GLIBC_2.4 unlinkat F
GLIBC_2.4 unshare F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -2834,3 +2834,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
GLIBC_2.39 stdc_trailing_zeros_ul F
GLIBC_2.39 stdc_trailing_zeros_ull F
GLIBC_2.39 stdc_trailing_zeros_us F
GLIBC_2.40 openat2 F

View File

@ -2909,6 +2909,7 @@ GLIBC_2.4 renameat F
GLIBC_2.4 symlinkat F
GLIBC_2.4 unlinkat F
GLIBC_2.4 unshare F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -2915,6 +2915,7 @@ GLIBC_2.4 renameat F
GLIBC_2.4 symlinkat F
GLIBC_2.4 unlinkat F
GLIBC_2.4 unshare F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -2817,6 +2817,7 @@ GLIBC_2.4 renameat F
GLIBC_2.4 symlinkat F
GLIBC_2.4 unlinkat F
GLIBC_2.4 unshare F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -2873,3 +2873,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
GLIBC_2.39 stdc_trailing_zeros_ul F
GLIBC_2.39 stdc_trailing_zeros_ull F
GLIBC_2.39 stdc_trailing_zeros_us F
GLIBC_2.40 openat2 F

View File

@ -0,0 +1,29 @@
/* Linux openat2 syscall implementation.
Copyright (C) 2024 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
<https://www.gnu.org/licenses/>. */
#include <fcntl.h>
#include <bits/openat2.h>
#include <sysdep-cancel.h>
int
__openat2 (int dfd, const char *filename, struct open_how *how,
size_t usize)
{
return SYSCALL_CANCEL (openat2, dfd, filename, how, usize);
}
weak_alias (__openat2, openat2)

View File

@ -2255,3 +2255,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
GLIBC_2.39 stdc_trailing_zeros_ul F
GLIBC_2.39 stdc_trailing_zeros_ull F
GLIBC_2.39 stdc_trailing_zeros_us F
GLIBC_2.40 openat2 F

View File

@ -3138,6 +3138,7 @@ GLIBC_2.4 wcstold F
GLIBC_2.4 wcstold_l F
GLIBC_2.4 wprintf F
GLIBC_2.4 wscanf F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -2892,6 +2892,7 @@ GLIBC_2.4 wcstold F
GLIBC_2.4 wcstold_l F
GLIBC_2.4 wprintf F
GLIBC_2.4 wscanf F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -2968,3 +2968,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
GLIBC_2.39 stdc_trailing_zeros_ul F
GLIBC_2.39 stdc_trailing_zeros_ull F
GLIBC_2.39 stdc_trailing_zeros_us F
GLIBC_2.40 openat2 F

View File

@ -2512,3 +2512,4 @@ GLIBC_2.39 stdc_trailing_zeros_ul F
GLIBC_2.39 stdc_trailing_zeros_ull F
GLIBC_2.39 stdc_trailing_zeros_us F
GLIBC_2.40 __riscv_hwprobe F
GLIBC_2.40 openat2 F

View File

@ -2712,3 +2712,4 @@ GLIBC_2.39 stdc_trailing_zeros_ul F
GLIBC_2.39 stdc_trailing_zeros_ull F
GLIBC_2.39 stdc_trailing_zeros_us F
GLIBC_2.40 __riscv_hwprobe F
GLIBC_2.40 openat2 F

View File

@ -3136,6 +3136,7 @@ GLIBC_2.4 wcstold F
GLIBC_2.4 wcstold_l F
GLIBC_2.4 wprintf F
GLIBC_2.4 wscanf F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -2929,6 +2929,7 @@ GLIBC_2.4 wcstold F
GLIBC_2.4 wcstold_l F
GLIBC_2.4 wprintf F
GLIBC_2.4 wscanf F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -2825,6 +2825,7 @@ GLIBC_2.4 sys_errlist D 0x210
GLIBC_2.4 sys_nerr D 0x4
GLIBC_2.4 unlinkat F
GLIBC_2.4 unshare F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -3157,6 +3157,7 @@ GLIBC_2.4 wcstold F
GLIBC_2.4 wcstold_l F
GLIBC_2.4 wprintf F
GLIBC_2.4 wscanf F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -2793,6 +2793,7 @@ GLIBC_2.4 sys_errlist D 0x430
GLIBC_2.4 sys_nerr D 0x4
GLIBC_2.4 unlinkat F
GLIBC_2.4 unshare F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -0,0 +1,63 @@
#!/usr/bin/python3
# Test that glibc's sys/openat2.h constants match the kernel's.
# Copyright (C) 2024 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
# <https://www.gnu.org/licenses/>.
import argparse
import sys
import glibcextract
import glibcsyscalls
def main():
"""The main entry point."""
parser = argparse.ArgumentParser(
description="Test that glibc's sys/openat2.h constants "
"match the kernel's.")
parser.add_argument('--cc', metavar='CC',
help='C compiler (including options) to use')
args = parser.parse_args()
if glibcextract.compile_c_snippet(
'#include <linux/openat2.h>',
args.cc).returncode != 0:
sys.exit (77)
linux_version_headers = glibcsyscalls.linux_kernel_version(args.cc)
# Constants in glibc were updated to match Linux v6.8. When glibc
# constants are updated this value should be updated to match the
# released kernel version from which the constants were taken.
linux_version_glibc = (6, 8)
def check(cte, exclude=None):
return glibcextract.compare_macro_consts(
'#define _FCNTL_H\n'
'#include <stdint.h>\n'
'#include <bits/openat2.h>\n',
'#include <asm/fcntl.h>\n'
'#include <linux/openat2.h>\n',
args.cc,
cte,
exclude,
linux_version_glibc > linux_version_headers,
linux_version_headers > linux_version_glibc)
status = check('RESOLVE.*')
sys.exit(status)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,259 @@
/* Linux openat2 tests.
Copyright (C) 2024 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
<https://www.gnu.org/licenses/>. */
/* openat2 is only support in LFS mode. */
#define _FILE_OFFSET_BITS 64
#include <array_length.h>
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <support/check.h>
#include <support/temp_file.h>
#include <support/xunistd.h>
static int dir_fd;
static void
do_prepare (int argc, char *argv[])
{
char *temp_dir = support_create_temp_directory ("tst-openat2");
dir_fd = xopen (temp_dir, O_RDONLY | O_DIRECTORY, 0);
}
#define PREPARE do_prepare
static int
do_test_struct (void)
{
static struct struct_test
{
struct open_how_ext
{
struct open_how inner;
int extra1;
int extra2;
int extra3;
} arg;
size_t size;
int err;
} tests[] =
{
{
/* Zero size. */
.arg.inner.flags = O_RDONLY,
.size = 0,
.err = EINVAL,
},
{
/* Normal struct. */
.arg.inner.flags = O_RDONLY,
.size = sizeof (struct open_how),
},
{
/* Larger struct, zeroed out the unused values. */
.arg.inner.flags = O_RDONLY,
.size = sizeof (struct open_how_ext),
},
{
/* Larger struct, non-zeroed out the unused values. */
.arg.inner.flags = O_RDONLY,
.arg.extra1 = 0xdeadbeef,
.size = sizeof (struct open_how_ext),
.err = E2BIG,
},
{
/* Larger struct, non-zeroed out the unused values. */
.arg.inner.flags = O_RDONLY,
.arg.extra2 = 0xdeadbeef,
.size = sizeof (struct open_how_ext),
.err = E2BIG,
},
};
for (struct struct_test *t = tests; t != array_end (tests); t++)
{
int fd = openat2 (AT_FDCWD, ".", (struct open_how *) &t->arg, t->size);
if (fd == -1 && errno == ENOSYS)
FAIL_UNSUPPORTED ("openat2 is not supported by the kernel");
if (t->err != 0)
{
TEST_COMPARE (fd, -1);
TEST_COMPARE (errno, t->err);
}
else
TEST_VERIFY (fd >= 0);
}
return 0;
}
static int
do_test_flags (void)
{
static struct flag_test
{
struct open_how how;
int err;
} tests[] =
{
/* O_TMPFILE is incompatible with O_PATH and O_CREAT. */
{ .how.flags = O_TMPFILE | O_PATH | O_RDWR, .err = EINVAL },
{ .how.flags = O_TMPFILE | O_CREAT | O_RDWR, .err = EINVAL },
/* O_PATH only permits certain other flags to be set ... */
{ .how.flags = O_PATH | O_CLOEXEC },
{ .how.flags = O_PATH | O_DIRECTORY },
{ .how.flags = O_PATH | O_NOFOLLOW },
/* ... and others are absolutely not permitted. */
{ .how.flags = O_PATH | O_RDWR, .err = EINVAL },
{ .how.flags = O_PATH | O_CREAT, .err = EINVAL },
{ .how.flags = O_PATH | O_EXCL, .err = EINVAL },
{ .how.flags = O_PATH | O_NOCTTY, .err = EINVAL },
{ .how.flags = O_PATH | O_DIRECT, .err = EINVAL },
/* ->mode must only be set with O_{CREAT,TMPFILE}. */
{ .how.flags = O_RDONLY, .how.mode = 0600, .err = EINVAL },
{ .how.flags = O_PATH, .how.mode = 0600, .err = EINVAL },
{ .how.flags = O_CREAT, .how.mode = 0600 },
{ .how.flags = O_TMPFILE | O_RDWR, .how.mode = 0600 },
/* ->mode must only contain 0777 bits. */
{ .how.flags = O_CREAT, .how.mode = 0xFFFF, .err = EINVAL },
{ .how.flags = O_CREAT, .how.mode = 0xC000000000000000ULL, .err = EINVAL },
{ .how.flags = O_TMPFILE | O_RDWR, .how.mode = 0x1337, .err = EINVAL },
{ .how.flags = O_TMPFILE | O_RDWR, .how.mode = 0x0000A00000000000ULL,
.err = EINVAL },
/* ->resolve flags must not conflict. */
{ .how.flags = O_RDONLY,
.how.resolve = RESOLVE_BENEATH | RESOLVE_IN_ROOT,
.err = EINVAL },
/* ->resolve must only contain RESOLVE_* flags. */
{ .how.flags = O_RDONLY,
.how.resolve = 0x1337, .err = EINVAL },
{ .how.flags = O_CREAT,
.how.resolve = 0x1337, .err = EINVAL },
{ .how.flags = O_TMPFILE | O_RDWR,
.how.resolve = 0x1337, .err = EINVAL },
{ .how.flags = O_PATH,
.how.resolve = 0x1337, .err = EINVAL },
/* currently unknown upper 32 bit rejected. */
{ .how.flags = O_RDONLY | (1ULL << 63),
.how.resolve = 0, .err = EINVAL },
};
for (struct flag_test *t = tests; t != array_end (tests); t++)
{
char *path;
if (t->how.flags & O_CREAT)
{
int temp_fd = create_temp_file ("tst-openat2.", &path);
TEST_VERIFY_EXIT (temp_fd != -1);
xunlink (path);
}
else
path = (char *) ".";
int fd = openat2 (AT_FDCWD, path, &t->how, sizeof (struct open_how));
if (fd != 0 && errno == EOPNOTSUPP)
{
/* Skip the testcase if FS does not support the operation (e.g.
valid O_TMPFILE on NFS). */
continue;
}
if (t->err != 0)
{
TEST_COMPARE (fd, -1);
TEST_COMPARE (errno, t->err);
}
else
TEST_VERIFY (fd >= 0);
}
return 0;
}
static int
do_test_basic (void)
{
int fd;
fd = openat2 (dir_fd,
"some-file",
&(struct open_how)
{
.flags = O_CREAT|O_RDWR|O_EXCL,
.mode = 0666,
},
sizeof (struct open_how));
TEST_VERIFY (fd != -1);
xwrite (fd, "hello", 5);
/* Before closing the file, try using this file descriptor to open
another file. This must fail. */
{
int fd2 = openat2 (fd,
"should-not-work",
&(struct open_how)
{
.flags = O_CREAT|O_RDWR|O_EXCL,
.mode = 0666,
},
sizeof (struct open_how));
TEST_COMPARE (fd2, -1);
TEST_COMPARE (errno, ENOTDIR);
}
/* Remove the created file. */
int cwdfd = xopen (".", O_RDONLY | O_DIRECTORY, 0);
TEST_COMPARE (fchdir (dir_fd), 0);
xunlink ("some-file");
TEST_COMPARE (fchdir (cwdfd), 0);
xclose (dir_fd);
xclose (cwdfd);
fd = openat2 (dir_fd,
"some-file",
&(struct open_how)
{
.flags = O_CREAT|O_RDWR|O_EXCL,
.mode = 0666,
},
sizeof (struct open_how));
TEST_COMPARE (fd, -1);
TEST_COMPARE (errno, EBADF);
return 0;
}
static int
do_test (void)
{
do_test_struct ();
do_test_flags ();
do_test_basic ();
return 0;
}
#include <support/test-driver.c>

View File

@ -2744,6 +2744,7 @@ GLIBC_2.4 sys_errlist D 0x420
GLIBC_2.4 sys_nerr D 0x4
GLIBC_2.4 unlinkat F
GLIBC_2.4 unshare F
GLIBC_2.40 openat2 F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
GLIBC_2.5 inet6_opt_find F

View File

@ -2763,3 +2763,4 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
GLIBC_2.39 stdc_trailing_zeros_ul F
GLIBC_2.39 stdc_trailing_zeros_ull F
GLIBC_2.39 stdc_trailing_zeros_us F
GLIBC_2.40 openat2 F