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 <pwd.h>
55 #include <sys/mman.h>
56 #include <sys/types.h>
57 #include <sys/stat.h>
58 #include <sys/mount.h>
59
60 #include "tst_test.h"
61
62 #define TEST_FILE "test_dir"
63 #define NO_DIR "testfile/testdir"
64 #define NOT_DIR "file1/testdir"
65 #define TEST6_FILE "dir6/file6"
66 #define TEST7_FILE "file7"
67 #define TEST8_FILE "mntpoint/tmp"
68
69 #define MODE1 0444
70 #define MODE2 0666
71
72 static void setup(void);
73 static void cleanup(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 static const char *device;
83 static int mount_flag;
84
85 static struct test_case_t {
86 char *fname;
87 int mode;
88 int error;
89 void (*setup)();
90 void (*cleanup)(void);
91 } tcases[] = {
92 {TEST_FILE, MODE1, EISDIR, NULL, NULL},
93 {long_name, MODE1, ENAMETOOLONG, NULL, NULL},
94 {NO_DIR, MODE1, ENOENT, NULL, NULL},
95 {NOT_DIR, MODE1, ENOTDIR, NULL, NULL},
96 #if !defined(UCLINUX)
97 {NULL, MODE1, EFAULT, bad_addr_setup, NULL},
98 #endif
99 {TEST6_FILE, MODE1, EACCES, test6_setup, test6_cleanup},
100 {TEST7_FILE, MODE1, ELOOP, NULL, NULL},
101 {TEST8_FILE, MODE1, EROFS, NULL, NULL},
102 };
103
verify_creat(unsigned int i)104 static void verify_creat(unsigned int i)
105 {
106 if (tcases[i].setup != NULL)
107 tcases[i].setup(i);
108
109 TEST(creat(tcases[i].fname, tcases[i].mode));
110
111 if (tcases[i].cleanup != NULL)
112 tcases[i].cleanup();
113
114 if (TEST_RETURN != -1) {
115 tst_res(TFAIL, "call succeeded unexpectedly");
116 return;
117 }
118
119 if (TEST_ERRNO == tcases[i].error) {
120 tst_res(TPASS | TTERRNO, "got expected failure");
121 return;
122 }
123
124 tst_res(TFAIL | TTERRNO, "expected %s",
125 tst_strerrno(tcases[i].error));
126 }
127
128
setup(void)129 static void setup(void)
130 {
131 ltpuser = SAFE_GETPWNAM("nobody");
132
133 SAFE_MKDIR(TEST_FILE, MODE2);
134
135 memset(long_name, 'a', PATH_MAX+1);
136
137 SAFE_TOUCH("file1", MODE1, NULL);
138
139 SAFE_MKDIR("dir6", MODE2);
140
141 SAFE_SYMLINK(TEST7_FILE, "test_file_eloop2");
142 SAFE_SYMLINK("test_file_eloop2", TEST7_FILE);
143
144 SAFE_MKFS(tst_device->dev, tst_device->fs_type, NULL, NULL);
145
146 SAFE_MKDIR("mntpoint", 0777);
147 SAFE_MOUNT(tst_device->dev, "mntpoint", tst_device->fs_type,
148 MS_RDONLY, NULL);
149 mount_flag = 1;
150 }
151
152 #if !defined(UCLINUX)
bad_addr_setup(int i)153 static void bad_addr_setup(int i)
154 {
155 if (tcases[i].fname)
156 return;
157
158 tcases[i].fname = SAFE_MMAP(0, 1, PROT_NONE,
159 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
160 }
161 #endif
162
test6_setup(void)163 static void test6_setup(void)
164 {
165 SAFE_SETEUID(ltpuser->pw_uid);
166 }
167
test6_cleanup(void)168 static void test6_cleanup(void)
169 {
170 SAFE_SETEUID(0);
171 }
172
cleanup(void)173 static void cleanup(void)
174 {
175 if (mount_flag && tst_umount("mntpoint") < 0)
176 tst_brk(TBROK | TERRNO, "umount device:%s failed", device);
177 }
178
179 static struct tst_test test = {
180 .tid = "creat06",
181 .tcnt = ARRAY_SIZE(tcases),
182 .test = verify_creat,
183 .needs_root = 1,
184 .needs_tmpdir = 1,
185 .needs_device = 1,
186 .cleanup = cleanup,
187 .setup = setup,
188 };
189