]>
Commit | Line | Data |
---|---|---|
5915ce22 | 1 | /* Tests for fcntl. |
568035b7 | 2 | Copyright (C) 2000-2013 Free Software Foundation, Inc. |
41bdb6e2 | 3 | This file is part of the GNU C Library. |
5915ce22 UD |
4 | Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000. |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
7 | modify it under the terms of the GNU Lesser General Public |
8 | License as published by the Free Software Foundation; either | |
9 | version 2.1 of the License, or (at your option) any later version. | |
5915ce22 UD |
10 | |
11 | The GNU C Library is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 14 | Lesser General Public License for more details. |
5915ce22 | 15 | |
41bdb6e2 | 16 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
17 | License along with the GNU C Library; if not, see |
18 | <http://www.gnu.org/licenses/>. */ | |
5915ce22 UD |
19 | |
20 | #include <errno.h> | |
21 | #include <fcntl.h> | |
22 | #include <paths.h> | |
23 | #include <string.h> | |
24 | #include <unistd.h> | |
25 | #include <sys/stat.h> | |
26 | ||
27 | ||
28 | /* Prototype for our test function. */ | |
29 | extern void do_prepare (int argc, char *argv[]); | |
30 | extern int do_test (int argc, char *argv[]); | |
31 | ||
32 | /* We have a preparation function. */ | |
33 | #define PREPARE do_prepare | |
34 | ||
35 | #include "../test-skeleton.c" | |
36 | ||
37 | ||
38 | /* Name of the temporary files. */ | |
39 | static char *name; | |
40 | ||
41 | void | |
42 | do_prepare (int argc, char *argv[]) | |
43 | { | |
30aa5785 | 44 | size_t name_len; |
5915ce22 UD |
45 | |
46 | name_len = strlen (test_dir); | |
47 | name = malloc (name_len + sizeof ("/fcntlXXXXXX")); | |
48 | mempcpy (mempcpy (name, test_dir, name_len), | |
49 | "/fcntlXXXXXX", sizeof ("/fcntlXXXXXX")); | |
50 | add_temp_file (name); | |
51 | } | |
52 | ||
53 | ||
54 | int | |
55 | do_test (int argc, char *argv[]) | |
56 | { | |
57 | int fd; | |
58 | int fd2; | |
59 | int fd3; | |
60 | struct stat64 st; | |
61 | int val; | |
62 | int result = 0; | |
63 | ||
64 | /* Create the temporary file. */ | |
65 | fd = mkstemp (name); | |
66 | if (fd == -1) | |
67 | { | |
68 | printf ("cannot open temporary file: %m\n"); | |
69 | return 1; | |
70 | } | |
71 | if (fstat64 (fd, &st) != 0) | |
72 | { | |
73 | printf ("cannot stat test file: %m\n"); | |
74 | return 1; | |
75 | } | |
76 | if (! S_ISREG (st.st_mode) || st.st_size != 0) | |
77 | { | |
78 | puts ("file not created correctly"); | |
79 | return 1; | |
80 | } | |
81 | ||
82 | /* Get the flags with fcntl(). */ | |
83 | val = fcntl (fd, F_GETFL); | |
84 | if (val == -1) | |
85 | { | |
86 | printf ("fcntl(fd, F_GETFL) failed: %m\n"); | |
87 | result = 1; | |
88 | } | |
89 | else if ((val & O_ACCMODE) != O_RDWR) | |
90 | { | |
91 | puts ("temporary file not opened for read and write"); | |
92 | result = 1; | |
93 | } | |
94 | ||
95 | /* Set the flags to something else. */ | |
96 | if (fcntl (fd, F_SETFL, O_RDONLY) == -1) | |
97 | { | |
98 | printf ("fcntl(fd, F_SETFL, O_RDONLY) failed: %m\n"); | |
99 | result = 1; | |
100 | } | |
101 | ||
102 | val = fcntl (fd, F_GETFL); | |
103 | if (val == -1) | |
104 | { | |
105 | printf ("fcntl(fd, F_GETFL) after F_SETFL failed: %m\n"); | |
106 | result = 1; | |
107 | } | |
108 | else if ((val & O_ACCMODE) != O_RDWR) | |
109 | { | |
110 | puts ("temporary file access mode changed"); | |
111 | result = 1; | |
112 | } | |
113 | ||
114 | /* Set the flags to something else. */ | |
115 | if (fcntl (fd, F_SETFL, O_APPEND) == -1) | |
116 | { | |
117 | printf ("fcntl(fd, F_SETFL, O_APPEND) failed: %m\n"); | |
118 | result = 1; | |
119 | } | |
120 | ||
121 | val = fcntl (fd, F_GETFL); | |
122 | if (val == -1) | |
123 | { | |
124 | printf ("fcntl(fd, F_GETFL) after second F_SETFL failed: %m\n"); | |
125 | result = 1; | |
126 | } | |
127 | else if ((val & O_APPEND) == 0) | |
128 | { | |
129 | puts ("O_APPEND not set"); | |
130 | result = 1; | |
131 | } | |
132 | ||
133 | val = fcntl (fd, F_GETFD); | |
134 | if (val == -1) | |
135 | { | |
136 | printf ("fcntl(fd, F_GETFD) failed: %m\n"); | |
137 | result = 1; | |
138 | } | |
139 | else if (fcntl (fd, F_SETFD, val | FD_CLOEXEC) == -1) | |
140 | { | |
141 | printf ("fcntl(fd, F_SETFD, FD_CLOEXEC) failed: %m\n"); | |
142 | result = 1; | |
143 | } | |
144 | else | |
145 | { | |
146 | val = fcntl (fd, F_GETFD); | |
147 | if (val == -1) | |
148 | { | |
149 | printf ("fcntl(fd, F_GETFD) after F_SETFD failed: %m\n"); | |
150 | result = 1; | |
151 | } | |
152 | else if ((val & FD_CLOEXEC) == 0) | |
153 | { | |
154 | puts ("FD_CLOEXEC not set"); | |
155 | result = 1; | |
156 | } | |
157 | } | |
158 | ||
159 | /* Get a number of a free descriptor. If /dev/null is not available | |
160 | don't continue testing. */ | |
161 | fd2 = open (_PATH_DEVNULL, O_RDWR); | |
162 | if (fd2 == -1) | |
163 | return result; | |
164 | close (fd2); | |
165 | ||
166 | fd3 = fcntl (fd, F_DUPFD, fd2 + 1); | |
167 | if (fd3 == -1) | |
168 | { | |
169 | printf ("fcntl(fd, F_DUPFD, %d) failed: %m\n", fd2 + 1); | |
170 | result = 1; | |
171 | } | |
172 | else if (fd3 <= fd2) | |
173 | { | |
174 | printf ("F_DUPFD returned %d which is not larger than %d\n", fd3, fd2); | |
175 | result = 1; | |
176 | } | |
177 | ||
178 | if (fd3 != -1) | |
179 | { | |
180 | val = fcntl (fd3, F_GETFD); | |
181 | if (val == -1) | |
182 | { | |
183 | printf ("fcntl(fd3, F_GETFD) after F_DUPFD failed: %m\n"); | |
184 | result = 1; | |
185 | } | |
186 | else if ((val & FD_CLOEXEC) != 0) | |
187 | { | |
188 | puts ("FD_CLOEXEC still set"); | |
189 | result = 1; | |
190 | } | |
191 | ||
192 | close (fd3); | |
193 | } | |
194 | ||
195 | return result; | |
196 | } |