test-fs-open-flags.c
Go to the documentation of this file.
1 /* Copyright libuv project contributors. All rights reserved.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21 
22 #ifdef _WIN32
23 
24 #include "uv.h"
25 #include "task.h"
26 
27 #if defined(__unix__) || defined(__POSIX__) || \
28  defined(__APPLE__) || defined(__sun) || \
29  defined(_AIX) || defined(__MVS__) || \
30  defined(__HAIKU__)
31 # include <unistd.h> /* unlink, rmdir */
32 #else
33 # include <direct.h>
34 # define rmdir _rmdir
35 # define unlink _unlink
36 #endif
37 
38 static int flags;
39 
40 static uv_fs_t close_req;
41 static uv_fs_t mkdir_req;
42 static uv_fs_t open_req;
43 static uv_fs_t read_req;
44 static uv_fs_t rmdir_req;
45 static uv_fs_t unlink_req;
46 static uv_fs_t write_req;
47 
48 static char buf[32];
49 static uv_buf_t iov;
50 
51 /* Opening the same file multiple times quickly can cause uv_fs_open to fail
52  * with EBUSY, so append an identifier to the file name for each operation */
53 static int sid = 0;
54 
55 #define FILE_NAME_SIZE 128
56 static char absent_file[FILE_NAME_SIZE];
57 static char empty_file[FILE_NAME_SIZE];
58 static char dummy_file[FILE_NAME_SIZE];
59 static char empty_dir[] = "empty_dir";
60 
61 static void setup() {
62  int r;
63 
64  /* empty_dir */
65  r = uv_fs_rmdir(NULL, &rmdir_req, empty_dir, NULL);
66  ASSERT(r == 0 || r == UV_ENOENT);
67  ASSERT(rmdir_req.result == 0 || rmdir_req.result == UV_ENOENT);
69 
70  r = uv_fs_mkdir(NULL, &mkdir_req, empty_dir, 0755, NULL);
71  ASSERT(r == 0);
72  ASSERT(mkdir_req.result == 0);
74 }
75 
76 static void refresh() {
77  int r;
78 
79  /* absent_file */
80  sprintf(absent_file, "test_file_%d", sid++);
81 
82  r = uv_fs_unlink(NULL, &unlink_req, absent_file, NULL);
83  ASSERT(r == 0 || r == UV_ENOENT);
84  ASSERT(unlink_req.result == 0 || unlink_req.result == UV_ENOENT);
86 
87  /* empty_file */
88  sprintf(empty_file, "test_file_%d", sid++);
89 
90  r = uv_fs_open(NULL, &open_req, empty_file,
91  UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, NULL);
92  ASSERT(r >= 0);
93  ASSERT(open_req.result >= 0);
95 
96  r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
97  ASSERT(r == 0);
98  ASSERT(close_req.result == 0);
100 
101  /* dummy_file */
102  sprintf(dummy_file, "test_file_%d", sid++);
103 
104  r = uv_fs_open(NULL, &open_req, dummy_file,
105  UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, NULL);
106  ASSERT(r >= 0);
107  ASSERT(open_req.result >= 0);
109 
110  iov = uv_buf_init("a", 1);
111  r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
112  ASSERT(r == 1);
113  ASSERT(write_req.result == 1);
115 
116  r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
117  ASSERT(r == 0);
118  ASSERT(close_req.result == 0);
120 }
121 
122 static void cleanup() {
123  unlink(absent_file);
124  unlink(empty_file);
125  unlink(dummy_file);
126 }
127 
128 static void openFail(char *file, int error) {
129  int r;
130 
131  refresh();
132 
133  r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL);
134  ASSERT(r == error);
137 
138  /* Ensure the first call does not create the file */
139  r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL);
140  ASSERT(r == error);
143 
144  cleanup();
145 }
146 
147 static void refreshOpen(char *file) {
148  int r;
149 
150  refresh();
151 
152  r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL);
153  ASSERT(r >= 0);
154  ASSERT(open_req.result >= 0);
156 }
157 
158 static void writeExpect(char *file, char *expected, int size) {
159  int r;
160 
161  refreshOpen(file);
162 
163  iov = uv_buf_init("b", 1);
164  r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
165  ASSERT(r == 1);
166  ASSERT(write_req.result == 1);
168 
169  iov = uv_buf_init("c", 1);
170  r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
171  ASSERT(r == 1);
172  ASSERT(write_req.result == 1);
174 
175  r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
176  ASSERT(r == 0);
177  ASSERT(close_req.result == 0);
179 
180  /* Check contents */
181  r = uv_fs_open(NULL, &open_req, file, UV_FS_O_RDONLY, S_IWUSR | S_IRUSR, NULL);
182  ASSERT(r >= 0);
183  ASSERT(open_req.result >= 0);
185 
186  iov = uv_buf_init(buf, sizeof(buf));
187  r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
188  ASSERT(r == size);
190  ASSERT(strncmp(buf, expected, size) == 0);
192 
193  r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
194  ASSERT(r == 0);
195  ASSERT(close_req.result == 0);
197 
198  cleanup();
199 }
200 
201 static void writeFail(char *file, int error) {
202  int r;
203 
204  refreshOpen(file);
205 
206  iov = uv_buf_init("z", 1);
207  r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
208  ASSERT(r == error);
209  ASSERT(write_req.result == error);
211 
212  iov = uv_buf_init("z", 1);
213  r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
214  ASSERT(r == error);
215  ASSERT(write_req.result == error);
217 
218  r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
219  ASSERT(r == 0);
220  ASSERT(close_req.result == 0);
222 
223  cleanup();
224 }
225 
226 static void readExpect(char *file, char *expected, int size) {
227  int r;
228 
229  refreshOpen(file);
230 
231  iov = uv_buf_init(buf, sizeof(buf));
232  r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
233  ASSERT(r == size);
235  ASSERT(strncmp(buf, expected, size) == 0);
237 
238  r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
239  ASSERT(r == 0);
240  ASSERT(close_req.result == 0);
242 
243  cleanup();
244 }
245 
246 static void readFail(char *file, int error) {
247  int r;
248 
249  refreshOpen(file);
250 
251  iov = uv_buf_init(buf, sizeof(buf));
252  r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
253  ASSERT(r == error);
256 
257  iov = uv_buf_init(buf, sizeof(buf));
258  r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
259  ASSERT(r == error);
262 
263  r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
264  ASSERT(r == 0);
265  ASSERT(close_req.result == 0);
267 
268  cleanup();
269 }
270 
271 static void fs_open_flags(int add_flags) {
272  /* Follow the order from
273  * https://github.com/nodejs/node/blob/1a96abe849/lib/internal/fs/utils.js#L329-L354
274  */
275 
276  /* r */
277  flags = add_flags | UV_FS_O_RDONLY;
278  openFail(absent_file, UV_ENOENT);
279  writeFail(empty_file, UV_EPERM);
280  readExpect(empty_file, "", 0);
281  writeFail(dummy_file, UV_EPERM);
282  readExpect(dummy_file, "a", 1);
283  writeFail(empty_dir, UV_EPERM);
284  readFail(empty_dir, UV_EISDIR);
285 
286  /* rs */
287  flags = add_flags | UV_FS_O_RDONLY | UV_FS_O_SYNC;
288  openFail(absent_file, UV_ENOENT);
289  writeFail(empty_file, UV_EPERM);
290  readExpect(empty_file, "", 0);
291  writeFail(dummy_file, UV_EPERM);
292  readExpect(dummy_file, "a", 1);
293  writeFail(empty_dir, UV_EPERM);
294  readFail(empty_dir, UV_EISDIR);
295 
296  /* r+ */
297  flags = add_flags | UV_FS_O_RDWR;
298  openFail(absent_file, UV_ENOENT);
299  writeExpect(empty_file, "bc", 2);
300  readExpect(empty_file, "", 0);
301  writeExpect(dummy_file, "bc", 2);
302  readExpect(dummy_file, "a", 1);
303  writeFail(empty_dir, UV_EISDIR);
304  readFail(empty_dir, UV_EISDIR);
305 
306  /* rs+ */
307  flags = add_flags | UV_FS_O_RDWR | UV_FS_O_SYNC;
308  openFail(absent_file, UV_ENOENT);
309  writeExpect(empty_file, "bc", 2);
310  readExpect(empty_file, "", 0);
311  writeExpect(dummy_file, "bc", 2);
312  readExpect(dummy_file, "a", 1);
313  writeFail(empty_dir, UV_EISDIR);
314  readFail(empty_dir, UV_EISDIR);
315 
316  /* w */
318  writeExpect(absent_file, "bc", 2);
319  readFail(absent_file, UV_EPERM);
320  writeExpect(empty_file, "bc", 2);
321  readFail(empty_file, UV_EPERM);
322  writeExpect(dummy_file, "bc", 2);
323  readFail(dummy_file, UV_EPERM);
324  openFail(empty_dir, UV_EISDIR);
325 
326  /* wx */
327  flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY |
328  UV_FS_O_EXCL;
329  writeExpect(absent_file, "bc", 2);
330  readFail(absent_file, UV_EPERM);
331  openFail(empty_file, UV_EEXIST);
332  openFail(dummy_file, UV_EEXIST);
333  openFail(empty_dir, UV_EEXIST);
334 
335  /* w+ */
336  flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_RDWR;
337  writeExpect(absent_file, "bc", 2);
338  readExpect(absent_file, "", 0);
339  writeExpect(empty_file, "bc", 2);
340  readExpect(empty_file, "", 0);
341  writeExpect(dummy_file, "bc", 2);
342  readExpect(dummy_file, "", 0);
343  openFail(empty_dir, UV_EISDIR);
344 
345  /* wx+ */
346  flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_RDWR |
347  UV_FS_O_EXCL;
348  writeExpect(absent_file, "bc", 2);
349  readExpect(absent_file, "", 0);
350  openFail(empty_file, UV_EEXIST);
351  openFail(dummy_file, UV_EEXIST);
352  openFail(empty_dir, UV_EEXIST);
353 
354  /* a */
356  writeExpect(absent_file, "bc", 2);
357  readFail(absent_file, UV_EPERM);
358  writeExpect(empty_file, "bc", 2);
359  readFail(empty_file, UV_EPERM);
360  writeExpect(dummy_file, "abc", 3);
361  readFail(dummy_file, UV_EPERM);
362  writeFail(empty_dir, UV_EISDIR);
363  readFail(empty_dir, UV_EPERM);
364 
365  /* ax */
367  UV_FS_O_EXCL;
368  writeExpect(absent_file, "bc", 2);
369  readFail(absent_file, UV_EPERM);
370  openFail(empty_file, UV_EEXIST);
371  openFail(dummy_file, UV_EEXIST);
372  openFail(empty_dir, UV_EEXIST);
373 
374  /* as */
376  UV_FS_O_SYNC;
377  writeExpect(absent_file, "bc", 2);
378  readFail(absent_file, UV_EPERM);
379  writeExpect(empty_file, "bc", 2);
380  readFail(empty_file, UV_EPERM);
381  writeExpect(dummy_file, "abc", 3);
382  readFail(dummy_file, UV_EPERM);
383  writeFail(empty_dir, UV_EISDIR);
384  readFail(empty_dir, UV_EPERM);
385 
386  /* a+ */
388  writeExpect(absent_file, "bc", 2);
389  readExpect(absent_file, "", 0);
390  writeExpect(empty_file, "bc", 2);
391  readExpect(empty_file, "", 0);
392  writeExpect(dummy_file, "abc", 3);
393  readExpect(dummy_file, "a", 1);
394  writeFail(empty_dir, UV_EISDIR);
395  readFail(empty_dir, UV_EISDIR);
396 
397  /* ax+ */
398  flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR |
399  UV_FS_O_EXCL;
400  writeExpect(absent_file, "bc", 2);
401  readExpect(absent_file, "", 0);
402  openFail(empty_file, UV_EEXIST);
403  openFail(dummy_file, UV_EEXIST);
404  openFail(empty_dir, UV_EEXIST);
405 
406  /* as+ */
407  flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR |
408  UV_FS_O_SYNC;
409  writeExpect(absent_file, "bc", 2);
410  readExpect(absent_file, "", 0);
411  writeExpect(empty_file, "bc", 2);
412  readExpect(empty_file, "", 0);
413  writeExpect(dummy_file, "abc", 3);
414  readExpect(dummy_file, "a", 1);
415  writeFail(empty_dir, UV_EISDIR);
416  readFail(empty_dir, UV_EISDIR);
417 }
418 TEST_IMPL(fs_open_flags) {
419  setup();
420 
421  fs_open_flags(0);
422  fs_open_flags(UV_FS_O_FILEMAP);
423 
424  /* Cleanup. */
425  rmdir(empty_dir);
426 
428  return 0;
429 }
430 
431 #else
432 
433 typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
434 
435 #endif /* ifndef _WIN32 */
uv_fs_rmdir
UV_EXTERN int uv_fs_rmdir(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)
Definition: unix/fs.c:1931
unlink_req
static uv_fs_t unlink_req
Definition: test-fs.c:107
uv_fs_open
UV_EXTERN int uv_fs_open(uv_loop_t *loop, uv_fs_t *req, const char *path, int flags, int mode, uv_fs_cb cb)
Definition: unix/fs.c:1812
task.h
cleanup
void cleanup(void)
Definition: bloaty/third_party/zlib/examples/enough.c:182
rmdir
#define rmdir
Definition: test-fs.c:45
TEST_IMPL
#define TEST_IMPL(name)
Definition: task.h:236
read_req
uv_fs_t read_req
Definition: libuv/docs/code/uvcat/main.c:10
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
error
grpc_error_handle error
Definition: retry_filter.cc:499
UV_FS_O_FILEMAP
#define UV_FS_O_FILEMAP
Definition: unix.h:499
ASSERT
#define ASSERT(expr)
Definition: task.h:102
file
Definition: bloaty/third_party/zlib/examples/gzappend.c:170
UV_FS_O_RDONLY
#define UV_FS_O_RDONLY
Definition: unix.h:470
write_req
Definition: benchmark-tcp-write-batch.c:31
UV_FS_O_CREAT
#define UV_FS_O_CREAT
Definition: unix.h:406
rmdir_req
static uv_fs_t rmdir_req
Definition: test-fs.c:115
uv_fs_s::result
ssize_t result
Definition: uv.h:1299
uv_fs_s
Definition: uv.h:1294
uv_fs_mkdir
UV_EXTERN int uv_fs_mkdir(uv_loop_t *loop, uv_fs_t *req, const char *path, int mode, uv_fs_cb cb)
Definition: unix/fs.c:1776
UV_FS_O_TRUNC
#define UV_FS_O_TRUNC
Definition: unix.h:490
UV_FS_O_RDWR
#define UV_FS_O_RDWR
Definition: unix.h:475
iov
static uv_buf_t iov
Definition: libuv/docs/code/uvcat/main.c:15
uv_fs_unlink
UV_EXTERN int uv_fs_unlink(uv_loop_t *loop, uv_fs_t *req, const char *path, uv_fs_cb cb)
Definition: unix/fs.c:1974
UV_FS_O_APPEND
#define UV_FS_O_APPEND
Definition: unix.h:401
UV_FS_O_WRONLY
#define UV_FS_O_WRONLY
Definition: unix.h:495
close_req
static uv_fs_t close_req
Definition: test-fs.c:108
UV_FS_O_EXCL
#define UV_FS_O_EXCL
Definition: unix.h:440
uv_fs_close
UV_EXTERN int uv_fs_close(uv_loop_t *loop, uv_fs_t *req, uv_file file, uv_fs_cb cb)
Definition: unix/fs.c:1651
uv_fs_read
UV_EXTERN int uv_fs_read(uv_loop_t *loop, uv_fs_t *req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb)
Definition: unix/fs.c:1826
uv.h
MAKE_VALGRIND_HAPPY
#define MAKE_VALGRIND_HAPPY()
Definition: task.h:229
uv_buf_t
Definition: unix.h:121
mkdir_req
static uv_fs_t mkdir_req
Definition: test-fs.c:109
absl::flags_internal
Definition: abseil-cpp/absl/flags/commandlineflag.h:40
uv_fs_write
UV_EXTERN int uv_fs_write(uv_loop_t *loop, uv_fs_t *req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb)
Definition: unix/fs.c:1995
file_has_no_tests
int file_has_no_tests
Definition: test-fs-open-flags.c:433
fix_build_deps.r
r
Definition: fix_build_deps.py:491
uv_buf_init
UV_EXTERN uv_buf_t uv_buf_init(char *base, unsigned int len)
Definition: uv-common.c:157
unlink
#define unlink
Definition: test-fs-copyfile.c:33
uv_fs_req_cleanup
UV_EXTERN void uv_fs_req_cleanup(uv_fs_t *req)
Definition: unix/fs.c:2024
UV_FS_O_SYNC
#define UV_FS_O_SYNC
Definition: unix.h:485
flags
uint32_t flags
Definition: retry_filter.cc:632
write_req
uv_write_t write_req
Definition: libuv/docs/code/tty-gravity/main.c:9
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
open_req
uv_fs_t open_req
Definition: libuv/docs/code/uvcat/main.c:9
grpc::testing::setup
static void setup()
Definition: bm_cq_multiple_threads.cc:117


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:01:29