1 /*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program 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
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /*
21 * NAME
22 * fcntl06.c
23 *
24 * DESCRIPTION
25 * Error checking conditions for remote locking of regions of a file.
26 *
27 * CALLS
28 * open(2), write(2), fcntl(2)
29 *
30 * ALGORITHM
31 * Test unlocking sections around a write lock using remote Lock/Unlock
32 * call which should all fail.
33 *
34 * USAGE
35 * fcntl06
36 *
37 * HISTORY
38 * 07/2001 Ported by Wayne Boyer
39 *
40 * RESTRICTIONS
41 * Currently Linux kernel doesn't implement R_GETLK/R_SETLK facility,
42 * but this facility seems to be present in other standard flavours of
43 * Unix. Currently this program has all the testing done under
44 * "#ifdef LINUX_FILE_REGION_LOCK", when Linux implements the regions
45 * locking then, this testcase should be recompiled accordingly with the
46 * "ifdef" removed.
47 */
48
49 #include <fcntl.h>
50 #include <errno.h>
51 #include <signal.h>
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include "test.h"
55
56 #define F_RGETLK 10 /* kludge code */
57 #define F_RSETLK 11 /* kludge code */
58
59 char *TCID = "fcntl06";
60 int TST_TOTAL = 1;
61
62 void setup();
63 void cleanup();
64
65 #define STRINGSIZE 27
66 #define STRING "abcdefghijklmnopqrstuvwxyz\n"
67
68 int fd;
69 void unlock_file();
70 int do_lock(int, short, short, int, int);
71
main(int ac,char ** av)72 int main(int ac, char **av)
73 {
74 int fail = 0;
75
76 tst_parse_opts(ac, av, NULL, NULL);
77
78 setup(); /* global setup */
79
80 fail = 0;
81
82 #ifdef LINUX_FILE_REGION_LOCK
83 if (fcntl(fd, F_RGETLK, &tl) == -1) {
84 if (errno == EINVAL)
85 tst_brkm(TCONF, cleanup,
86 "fcntl remote locking feature not implemented in "
87 "the kernel");
88 else {
89 /*
90 * FIXME (garrcoop): having it always pass on
91 * non-EINVAL is a bad test.
92 */
93 tst_resm(TPASS, "fcntl on file failed");
94 }
95 }
96
97 /*
98 * Add a write lock to the middle of the file and unlock a section
99 * just before the lock
100 */
101 if (do_lock(F_RSETLK, F_WRLCK, 0, 10, 5) == -1)
102 tst_resm(TFAIL, "F_RSETLK WRLCK failed");
103
104 if (do_lock(F_RSETLK, F_UNLCK, 0, 5, 5) == -1)
105 tst_resm(TFAIL | TERRNO, "F_RSETLK UNLOCK failed");
106
107 unlock_file();
108 #else
109 tst_resm(TCONF, "system doesn't have LINUX_LOCK_FILE_REGION support");
110 #endif
111
112 cleanup();
113 tst_exit();
114 }
115
setup(void)116 void setup(void)
117 {
118 char *buf = STRING;
119 char template[PATH_MAX];
120
121 tst_sig(FORK, DEF_HANDLER, cleanup);
122
123 umask(0);
124
125 TEST_PAUSE;
126
127 tst_tmpdir();
128
129 snprintf(template, PATH_MAX, "fcntl06XXXXXX");
130
131 if ((fd = mkstemp(template)) == -1)
132 tst_resm(TBROK | TERRNO, "mkstemp failed");
133
134 if (write(fd, buf, STRINGSIZE) == -1)
135 tst_resm(TBROK | TERRNO, "write failed");
136 }
137
do_lock(int cmd,short type,short whence,int start,int len)138 int do_lock(int cmd, short type, short whence, int start, int len)
139 {
140 struct flock fl;
141
142 fl.l_type = type;
143 fl.l_whence = whence;
144 fl.l_start = start;
145 fl.l_len = len;
146 return (fcntl(fd, cmd, &fl));
147 }
148
unlock_file(void)149 void unlock_file(void)
150 {
151 if (do_lock(F_RSETLK, (short)F_UNLCK, (short)0, 0, 0) == -1) {
152 /* Same as FIXME comment above. */
153 tst_resm(TPASS | TERRNO, "fcntl on file failed");
154 }
155 }
156
cleanup(void)157 void cleanup(void)
158 {
159
160 if (close(fd) == -1)
161 tst_resm(TWARN | TERRNO, "close failed");
162
163 tst_rmdir();
164
165 }
166