1 /*
2 * Copyright (c) International Business Machines Corp., 2001
3 * Ported by Wayne Boyer
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 Foundation,
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /*
21 * DESCRIPTION
22 * Testcase to check creat(2) sets the following errnos correctly:
23 * 1. EISDIR
24 * 2. ENAMETOOLONG
25 * 3. ENOENT
26 * 4. ENOTDIR
27 * 5. EFAULT
28 * 6. EACCES
29 * 7. ELOOP
30 * 8. EROFS
31 *
32 *
33 * ALGORITHM
34 * 1. Attempt to creat(2) an existing directory, and test for
35 * EISDIR
36 * 2. Attempt to creat(2) a file whose name is more than
37 * VFS_MAXNAMLEN and test for ENAMETOOLONG.
38 * 3. Attempt to creat(2) a file inside a directory which doesn't
39 * exist, and test for ENOENT
40 * 4. Attempt to creat(2) a file, the pathname of which comprises
41 * a component which is a file, test for ENOTDIR.
42 * 5. Attempt to creat(2) a file with a bad address
43 * and test for EFAULT
44 * 6. Attempt to creat(2) a file in a directory with no
45 * execute permission and test for EACCES
46 * 7. Attempt to creat(2) a file which links the other file that
47 * links the former and test for ELOOP
48 * 8. Attempt to creat(2) a file in a Read-only file system
49 * and test for EROFS
50 */
51
52 #include <errno.h>
53 #include <string.h>
54 #include <limits.h>
55 #include <pwd.h>
56 #include <sys/mman.h>
57 #include <sys/types.h>
58 #include <sys/stat.h>
59 #include <sys/mount.h>
60
61 #include "tst_test.h"
62
63 #define TEST_FILE "test_dir"
64 #define NO_DIR "testfile/testdir"
65 #define NOT_DIR "file1/testdir"
66 #define TEST6_FILE "dir6/file6"
67 #define TEST7_FILE "file7"
68 #define TEST8_FILE "mntpoint/tmp"
69
70 #define MODE1 0444
71 #define MODE2 0666
72
73 static void setup(void);
74 static void test6_setup(void);
75 static void test6_cleanup(void);
76 #if !defined(UCLINUX)
77 static void bad_addr_setup(int);
78 #endif
79
80 static struct passwd *ltpuser;
81 static char long_name[PATH_MAX+2];
82
83 static struct test_case_t {
84 char *fname;
85 int mode;
86 int error;
87 void (*setup)();
88 void (*cleanup)(void);
89 } tcases[] = {
90 {TEST_FILE, MODE1, EISDIR, NULL, NULL},
91 {long_name, MODE1, ENAMETOOLONG, NULL, NULL},
92 {NO_DIR, MODE1, ENOENT, NULL, NULL},
93 {NOT_DIR, MODE1, ENOTDIR, NULL, NULL},
94 #if !defined(UCLINUX)
95 {NULL, MODE1, EFAULT, bad_addr_setup, NULL},
96 #endif
97 {TEST6_FILE, MODE1, EACCES, test6_setup, test6_cleanup},
98 {TEST7_FILE, MODE1, ELOOP, NULL, NULL},
99 {TEST8_FILE, MODE1, EROFS, NULL, NULL},
100 };
101
verify_creat(unsigned int i)102 static void verify_creat(unsigned int i)
103 {
104 if (tcases[i].setup != NULL)
105 tcases[i].setup(i);
106
107 TEST(creat(tcases[i].fname, tcases[i].mode));
108
109 if (tcases[i].cleanup != NULL)
110 tcases[i].cleanup();
111
112 if (TST_RET != -1) {
113 tst_res(TFAIL, "call succeeded unexpectedly");
114 return;
115 }
116
117 if (TST_ERR == tcases[i].error) {
118 tst_res(TPASS | TTERRNO, "got expected failure");
119 return;
120 }
121
122 tst_res(TFAIL | TTERRNO, "expected %s",
123 tst_strerrno(tcases[i].error));
124 }
125
126
setup(void)127 static void setup(void)
128 {
129 ltpuser = SAFE_GETPWNAM("nobody");
130
131 SAFE_MKDIR(TEST_FILE, MODE2);
132
133 memset(long_name, 'a', PATH_MAX+1);
134
135 SAFE_TOUCH("file1", MODE1, NULL);
136
137 SAFE_MKDIR("dir6", MODE2);
138
139 SAFE_SYMLINK(TEST7_FILE, "test_file_eloop2");
140 SAFE_SYMLINK("test_file_eloop2", TEST7_FILE);
141 }
142
143 #if !defined(UCLINUX)
bad_addr_setup(int i)144 static void bad_addr_setup(int i)
145 {
146 if (tcases[i].fname)
147 return;
148
149 tcases[i].fname = SAFE_MMAP(0, 1, PROT_NONE,
150 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
151 }
152 #endif
153
test6_setup(void)154 static void test6_setup(void)
155 {
156 SAFE_SETEUID(ltpuser->pw_uid);
157 }
158
test6_cleanup(void)159 static void test6_cleanup(void)
160 {
161 SAFE_SETEUID(0);
162 }
163
164 static struct tst_test test = {
165 .tcnt = ARRAY_SIZE(tcases),
166 .test = verify_creat,
167 .needs_root = 1,
168 .needs_rofs = 1,
169 .needs_tmpdir = 1,
170 .mntpoint = "mntpoint",
171 .setup = setup,
172 };
173