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 
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 (TEST_RETURN != -1) {
113 		tst_res(TFAIL, "call succeeded unexpectedly");
114 		return;
115 	}
116 
117 	if (TEST_ERRNO == 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 
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)
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 
154 static void test6_setup(void)
155 {
156 	SAFE_SETEUID(ltpuser->pw_uid);
157 }
158 
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