• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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