]>
Commit | Line | Data |
---|---|---|
e442e40d | 1 | /* Test POSIX lock on an open file (lockf). |
dff8da6b | 2 | Copyright (C) 2019-2024 Free Software Foundation, Inc. |
e442e40d AZ |
3 | |
4 | This program is free software; you can redistribute it and/or | |
5 | modify it under the terms of the GNU General Public License | |
6 | as published by the Free Software Foundation; either version 2 | |
7 | of the License, or (at your option) any later version. | |
8 | ||
9 | This program is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | GNU General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU General Public License | |
5a82c748 | 15 | along with this program; if not, see <https://www.gnu.org/licenses/>. |
e442e40d AZ |
16 | */ |
17 | ||
18 | #include <unistd.h> | |
19 | #include <stdint.h> | |
20 | #include <errno.h> | |
21 | #include <stdio.h> | |
22 | ||
23 | #include <support/temp_file.h> | |
24 | #include <support/capture_subprocess.h> | |
25 | #include <support/check.h> | |
26 | ||
4d0fe291 AZ |
27 | #ifndef TST_LOCKFD |
28 | # define TST_LOCKFD "tst-lockfd." | |
29 | #endif | |
30 | #ifndef LOCKF | |
31 | # define LOCKF lockf | |
32 | #endif | |
33 | #ifndef LOCKF64 | |
34 | # define LOCKF64 lockf64 | |
35 | #endif | |
36 | ||
e442e40d AZ |
37 | static char *temp_filename; |
38 | static int temp_fd; | |
39 | ||
40 | static void | |
41 | do_prepare (int argc, char **argv) | |
42 | { | |
4d0fe291 | 43 | temp_fd = create_temp_file (TST_LOCKFD, &temp_filename); |
e442e40d AZ |
44 | TEST_VERIFY_EXIT (temp_fd != -1); |
45 | } | |
46 | #define PREPARE do_prepare | |
47 | ||
48 | static void | |
49 | do_test_child_lockf (void *closure) | |
50 | { | |
51 | /* Check if parent has [0, 1024) locked. */ | |
52 | TEST_COMPARE (lseek (temp_fd, 0, SEEK_SET), 0); | |
4d0fe291 | 53 | TEST_COMPARE (LOCKF (temp_fd, F_TLOCK, 1024), -1); |
e442e40d | 54 | TEST_COMPARE (errno, EAGAIN); |
4d0fe291 | 55 | TEST_COMPARE (LOCKF (temp_fd, F_TEST, 1024), -1); |
e442e40d AZ |
56 | TEST_COMPARE (errno, EACCES); |
57 | /* Also Check if parent has last 1024 bytes locked. */ | |
58 | TEST_COMPARE (lseek (temp_fd, INT32_MAX-1024, SEEK_SET), INT32_MAX-1024); | |
4d0fe291 | 59 | TEST_COMPARE (LOCKF (temp_fd, F_TEST, 1024), -1); |
e442e40d AZ |
60 | |
61 | /* And try to lock [1024, 2048). */ | |
62 | TEST_COMPARE (lseek (temp_fd, 1024, SEEK_SET), 1024); | |
4d0fe291 | 63 | TEST_COMPARE (LOCKF (temp_fd, F_LOCK, 1024), 0); |
e442e40d AZ |
64 | |
65 | /* Check if non-LFS interface cap access to 32-bif off_t. */ | |
66 | TEST_COMPARE (lseek64 (temp_fd, (off64_t)INT32_MAX, SEEK_SET), | |
67 | (off64_t)INT32_MAX); | |
4d0fe291 | 68 | TEST_COMPARE (LOCKF64 (temp_fd, F_TEST, 1024), 0); |
e442e40d AZ |
69 | } |
70 | ||
71 | static void | |
72 | do_test_child_lockf64 (void *closure) | |
73 | { | |
74 | /* Check if parent has [0, 1024) locked. */ | |
75 | TEST_COMPARE (lseek64 (temp_fd, 0, SEEK_SET), 0); | |
4d0fe291 | 76 | TEST_COMPARE (LOCKF64 (temp_fd, F_TLOCK, 1024), -1); |
e442e40d | 77 | TEST_COMPARE (errno, EAGAIN); |
4d0fe291 | 78 | TEST_COMPARE (LOCKF64 (temp_fd, F_TEST, 1024), -1); |
e442e40d AZ |
79 | TEST_COMPARE (errno, EACCES); |
80 | /* Also Check if parent has last 1024 bytes locked. */ | |
81 | TEST_COMPARE (lseek64 (temp_fd, INT32_MAX-1024, SEEK_SET), INT32_MAX-1024); | |
4d0fe291 | 82 | TEST_COMPARE (LOCKF64 (temp_fd, F_TEST, 1024), -1); |
e442e40d AZ |
83 | |
84 | /* And try to lock [1024, 2048). */ | |
85 | TEST_COMPARE (lseek64 (temp_fd, 1024, SEEK_SET), 1024); | |
4d0fe291 | 86 | TEST_COMPARE (LOCKF64 (temp_fd, F_LOCK, 1024), 0); |
e442e40d AZ |
87 | |
88 | /* And also [INT32_MAX, INT32_MAX+1024). */ | |
89 | { | |
90 | off64_t off = (off64_t)INT32_MAX; | |
91 | TEST_COMPARE (lseek64 (temp_fd, off, SEEK_SET), off); | |
4d0fe291 | 92 | TEST_COMPARE (LOCKF64 (temp_fd, F_LOCK, 1024), 0); |
e442e40d AZ |
93 | } |
94 | ||
95 | /* Check if [INT32_MAX+1024, INT64_MAX) is locked. */ | |
96 | { | |
97 | off64_t off = (off64_t)INT32_MAX+1024; | |
98 | TEST_COMPARE (lseek64 (temp_fd, off, SEEK_SET), off); | |
4d0fe291 | 99 | TEST_COMPARE (LOCKF64 (temp_fd, F_TLOCK, 1024), -1); |
e442e40d | 100 | TEST_COMPARE (errno, EAGAIN); |
4d0fe291 | 101 | TEST_COMPARE (LOCKF64 (temp_fd, F_TEST, 1024), -1); |
e442e40d AZ |
102 | TEST_COMPARE (errno, EACCES); |
103 | } | |
104 | } | |
105 | ||
106 | static int | |
107 | do_test (void) | |
108 | { | |
109 | /* Basic tests to check if a lock can be obtained and checked. */ | |
4d0fe291 AZ |
110 | TEST_COMPARE (LOCKF (temp_fd, F_LOCK, 1024), 0); |
111 | TEST_COMPARE (LOCKF (temp_fd, F_LOCK, INT32_MAX), 0); | |
112 | TEST_COMPARE (LOCKF (temp_fd, F_TLOCK, 1024), 0); | |
113 | TEST_COMPARE (LOCKF (temp_fd, F_TEST, 1024), 0); | |
e442e40d | 114 | TEST_COMPARE (lseek (temp_fd, 1024, SEEK_SET), 1024); |
4d0fe291 | 115 | TEST_COMPARE (LOCKF (temp_fd, F_ULOCK, 1024), 0); |
e442e40d AZ |
116 | /* Parent process should have ([0, 1024), [2048, INT32_MAX)) ranges locked. */ |
117 | ||
118 | { | |
119 | struct support_capture_subprocess result; | |
120 | result = support_capture_subprocess (do_test_child_lockf, NULL); | |
4d0fe291 | 121 | support_capture_subprocess_check (&result, "LOCKF", 0, sc_allow_none); |
e442e40d AZ |
122 | } |
123 | ||
124 | if (sizeof (off_t) != sizeof (off64_t)) | |
125 | { | |
126 | /* Check if previously locked regions with LFS symbol. */ | |
127 | TEST_COMPARE (lseek (temp_fd, 0, SEEK_SET), 0); | |
4d0fe291 AZ |
128 | TEST_COMPARE (LOCKF64 (temp_fd, F_LOCK, 1024), 0); |
129 | TEST_COMPARE (LOCKF64 (temp_fd, F_TLOCK, 1024), 0); | |
130 | TEST_COMPARE (LOCKF64 (temp_fd, F_TEST, 1024), 0); | |
e442e40d AZ |
131 | /* Lock region [INT32_MAX+1024, INT64_MAX). */ |
132 | off64_t off = (off64_t)INT32_MAX + 1024; | |
133 | TEST_COMPARE (lseek64 (temp_fd, off, SEEK_SET), off); | |
4d0fe291 | 134 | TEST_COMPARE (LOCKF64 (temp_fd, F_LOCK, 1024), 0); |
e442e40d AZ |
135 | /* Parent process should have ([0, 1024), [2048, INT32_MAX), |
136 | [INT32_MAX+1024, INT64_MAX)) ranges locked. */ | |
137 | ||
138 | { | |
139 | struct support_capture_subprocess result; | |
140 | result = support_capture_subprocess (do_test_child_lockf64, NULL); | |
4d0fe291 | 141 | support_capture_subprocess_check (&result, "LOCKF", 0, sc_allow_none); |
e442e40d AZ |
142 | } |
143 | } | |
144 | ||
145 | return 0; | |
146 | } | |
147 | ||
148 | #include <support/test-driver.c> |