Line data Source code
1 : /* Test of opening a file descriptor.
2 : Copyright (C) 2007-2020 Free Software Foundation, Inc.
3 :
4 : This program is free software: you can redistribute it and/or modify
5 : it under the terms of the GNU General Public License as published by
6 : the Free Software Foundation; either version 3 of the License, or
7 : (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
15 : along with this program. If not, see <https://www.gnu.org/licenses/>. */
16 :
17 : /* Written by Bruno Haible <bruno@clisp.org>, 2007. */
18 :
19 : /* Make test_open always inline if we're using Fortify, which defines
20 : __always_inline to do that. Do nothing otherwise. This works
21 : around a glibc bug whereby 'open' cannot be used as a function
22 : pointer when _FORTIFY_SOURCE is positive. */
23 :
24 : #if __GLIBC__ && defined __always_inline
25 : # define ALWAYS_INLINE __always_inline
26 : #else
27 : # define ALWAYS_INLINE
28 : #endif
29 :
30 : /* This file is designed to test both open(n,buf[,mode]) and
31 : openat(AT_FDCWD,n,buf[,mode]). FUNC is the function to test.
32 : Assumes that BASE and ASSERT are already defined, and that
33 : appropriate headers are already included. If PRINT, warn before
34 : skipping symlink tests with status 77. */
35 :
36 : static ALWAYS_INLINE int
37 : test_open (int (*func) (char const *, int, ...), bool print)
38 : {
39 : int fd;
40 :
41 : /* Remove anything from prior partial run. */
42 1 : unlink (BASE "file");
43 1 : unlink (BASE "e.exe");
44 1 : unlink (BASE "link");
45 :
46 : /* Cannot create directory. */
47 1 : errno = 0;
48 1 : ASSERT (func ("nonexist.ent/", O_CREAT | O_RDONLY, 0600) == -1);
49 1 : ASSERT (errno == ENOTDIR || errno == EISDIR || errno == ENOENT
50 : || errno == EINVAL);
51 :
52 : /* Create a regular file. */
53 1 : fd = func (BASE "file", O_CREAT | O_RDONLY, 0600);
54 1 : ASSERT (0 <= fd);
55 1 : ASSERT (close (fd) == 0);
56 :
57 : /* Create an executable regular file. */
58 1 : fd = func (BASE "e.exe", O_CREAT | O_RDONLY, 0700);
59 1 : ASSERT (0 <= fd);
60 1 : ASSERT (close (fd) == 0);
61 :
62 : /* Trailing slash handling. */
63 1 : errno = 0;
64 1 : ASSERT (func (BASE "file/", O_RDONLY) == -1);
65 1 : ASSERT (errno == ENOTDIR || errno == EISDIR || errno == EINVAL);
66 :
67 : /* Directories cannot be opened for writing. */
68 1 : errno = 0;
69 1 : ASSERT (func (".", O_WRONLY) == -1);
70 1 : ASSERT (errno == EISDIR || errno == EACCES);
71 :
72 : /* /dev/null must exist, and be writable. */
73 1 : fd = func ("/dev/null", O_RDONLY);
74 1 : ASSERT (0 <= fd);
75 : {
76 : char c;
77 1 : ASSERT (read (fd, &c, 1) == 0);
78 : }
79 1 : ASSERT (close (fd) == 0);
80 1 : fd = func ("/dev/null", O_WRONLY);
81 1 : ASSERT (0 <= fd);
82 1 : ASSERT (write (fd, "c", 1) == 1);
83 1 : ASSERT (close (fd) == 0);
84 :
85 : /* Although O_NONBLOCK on regular files can be ignored, it must not
86 : cause a failure. */
87 1 : fd = func (BASE "file", O_NONBLOCK | O_RDONLY);
88 1 : ASSERT (0 <= fd);
89 1 : ASSERT (close (fd) == 0);
90 :
91 : /* O_CLOEXEC must be honoured. */
92 : if (O_CLOEXEC)
93 : {
94 : /* Since the O_CLOEXEC handling goes through a special code path at its
95 : first invocation, test it twice. */
96 : int i;
97 :
98 3 : for (i = 0; i < 2; i++)
99 : {
100 : int flags;
101 :
102 2 : fd = func (BASE "file", O_CLOEXEC | O_RDONLY);
103 2 : ASSERT (0 <= fd);
104 2 : flags = fcntl (fd, F_GETFD);
105 2 : ASSERT (flags >= 0);
106 2 : ASSERT ((flags & FD_CLOEXEC) != 0);
107 2 : ASSERT (close (fd) == 0);
108 : }
109 : }
110 :
111 : /* Symlink handling, where supported. */
112 1 : if (symlink (BASE "file", BASE "link") != 0)
113 : {
114 0 : ASSERT (unlink (BASE "file") == 0);
115 0 : if (print)
116 0 : fputs ("skipping test: symlinks not supported on this file system\n",
117 : stderr);
118 0 : return 77;
119 : }
120 1 : errno = 0;
121 1 : ASSERT (func (BASE "link/", O_RDONLY) == -1);
122 1 : ASSERT (errno == ENOTDIR);
123 1 : fd = func (BASE "link", O_RDONLY);
124 1 : ASSERT (0 <= fd);
125 1 : ASSERT (close (fd) == 0);
126 :
127 : /* Cleanup. */
128 1 : ASSERT (unlink (BASE "file") == 0);
129 1 : ASSERT (unlink (BASE "e.exe") == 0);
130 1 : ASSERT (unlink (BASE "link") == 0);
131 :
132 1 : return 0;
133 : }
|