1/* Test that closing O_PATH descriptors does not release POSIX advisory locks.
2 Copyright (C) 2020-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <errno.h>
20#include <fcntl.h>
21#include <stdbool.h>
22#include <stdlib.h>
23#include <support/check.h>
24#include <support/namespace.h>
25#include <support/support.h>
26#include <support/temp_file.h>
27#include <support/xunistd.h>
28
29/* The subprocess writes the errno value of the lock operation
30 here. */
31static int *shared_errno;
32
33/* The path of the temporary file which is locked. */
34static char *path;
35
36/* Try to obtain an exclusive lock on the file at path. */
37static void
38subprocess (void *closure)
39{
40 int fd = xopen (path, O_RDWR, 0);
41 struct flock64 lock = { .l_type = F_WRLCK, };
42 int ret = fcntl64 (fd: fd, F_SETLK, &lock);
43 if (ret == 0)
44 *shared_errno = 0;
45 else
46 *shared_errno = errno;
47 xclose (fd);
48}
49
50/* Return true if the file at path is currently locked, false if
51 not. */
52static bool
53probe_lock (void)
54{
55 *shared_errno = -1;
56 support_isolate_in_subprocess (callback: subprocess, NULL);
57 if (*shared_errno == 0)
58 /* Lock was acquired by the subprocess, so this process has not
59 locked it. */
60 return false;
61 else
62 {
63 /* POSIX allows both EACCES and EAGAIN. Linux use EACCES. */
64 TEST_COMPARE (*shared_errno, EAGAIN);
65 return true;
66 }
67}
68
69static int
70do_test (void)
71{
72 shared_errno = support_shared_allocate (size: sizeof (*shared_errno));
73 int fd = create_temp_file (base: "tst-o_path-locks-", filename: &path);
74
75 /* The file is not locked initially. */
76 TEST_VERIFY (!probe_lock ());
77
78 struct flock64 lock = { .l_type = F_WRLCK, };
79 TEST_COMPARE (fcntl64 (fd, F_SETLK, &lock), 0);
80
81 /* The lock has been acquired. */
82 TEST_VERIFY (probe_lock ());
83
84 /* Closing the same file via a different descriptor releases the
85 lock. */
86 xclose (xopen (path, O_RDONLY, 0));
87 TEST_VERIFY (!probe_lock ());
88
89 /* But not if it is an O_PATH descriptor. */
90 TEST_COMPARE (fcntl64 (fd, F_SETLK, &lock), 0);
91 xclose (xopen (path, O_PATH, 0));
92 TEST_VERIFY (probe_lock ());
93
94 xclose (fd);
95 free (ptr: path);
96 support_shared_free (shared_errno);
97 return 0;
98}
99
100#include <support/test-driver.c>
101

source code of glibc/sysdeps/unix/sysv/linux/tst-o_path-locks.c