1 /*
2  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3  *    AUTHOR		: Bill Branum
4  *    CO-PILOT		: Steve Shaw
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of version 2 of the GNU General Public License as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it would be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  *
14  * Further, this software is distributed without any warranty that it is
15  * free of the rightful claim of any third person regarding infringement
16  * or the like.  Any license provided herein, whether implied or
17  * otherwise, applies only to this software file.  Patent licenses, if
18  * any, provided herein do not apply to combinations of this program with
19  * other software, or any other product whatsoever.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  *
25  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
26  * Mountain View, CA  94043, or:
27  *
28  * http://www.sgi.com
29  *
30  * For further information regarding this notice, see:
31  *
32  * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
33  *
34  */
35  /*
36   * TEST CASES
37   *  rmdir(2) test for errno(s) EINVAL, EMLINK, EFAULT
38   */
39 
40 #include <errno.h>
41 #include <signal.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <sys/mman.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include "test.h"
48 #include "safe_macros.h"
49 
50 static void setup(void);
51 static void cleanup(void);
52 
53 #if !defined(UCLINUX)
54 extern char *get_high_address();
55 int TST_TOTAL = 6;
56 #else
57 int TST_TOTAL = 4;
58 #endif
59 
60 char *TCID = "rmdir05";
61 
62 static struct stat stat_buf;
63 static char dir_name[256];
64 
65 static char *bad_addr = NULL;
66 
main(int argc,char ** argv)67 int main(int argc, char **argv)
68 {
69 	int lc;
70 
71 	tst_parse_opts(argc, argv, NULL, NULL);
72 
73 	setup();
74 
75 	for (lc = 0; TEST_LOOPING(lc); lc++) {
76 		tst_count = 0;
77 
78 		/*
79 		 * TEST CASE: 1
80 		 * path points to the current directory
81 		 */
82 		TEST(rmdir("."));
83 
84 		if (TEST_RETURN == -1) {
85 			if (TEST_ERRNO & (EBUSY | ENOTEMPTY)) {
86 				/* For functionality tests, verify that the
87 				 * directory wasn't removed.
88 				 */
89 				if (stat(".", &stat_buf) == -1) {
90 					tst_resm(TFAIL,
91 						 "rmdir(\".\") removed the current working directory when it should have failed.");
92 				} else {
93 					tst_resm(TPASS,
94 						 "rmdir(\".\") failed to remove the current working directory. Returned %d : %s",
95 						 TEST_ERRNO,
96 						 strerror(TEST_ERRNO));
97 				}
98 			} else {
99 				tst_resm(TFAIL,
100 					 "rmdir(\".\") failed with errno %d : %s but expected %d (EBUSY)",
101 					 TEST_ERRNO,
102 					 strerror(TEST_ERRNO), EBUSY);
103 			}
104 		} else {
105 			tst_resm(TFAIL,
106 				 "rmdir(\".\") succeeded unexpectedly.");
107 		}
108 
109 		/*
110 		 * TEST CASE: 2
111 		 * path points to the "." (dot) entry of a directory
112 		 */
113 		tst_resm(TCONF, "rmdir on \"dir/.\" supported on Linux");
114 
115 		tst_resm(TCONF,
116 			 "linked directories test not implemented on Linux");
117 
118 		/*
119 		 * TEST CASE: 4
120 		 * path argument points below the minimum allocated address space
121 		 */
122 #if !defined(UCLINUX)
123 		TEST(rmdir(bad_addr));
124 
125 		if (TEST_RETURN == -1) {
126 		}
127 
128 		if (TEST_RETURN == -1) {
129 			if (TEST_ERRNO == EFAULT) {
130 				tst_resm(TPASS,
131 					 "rmdir() - path argument points below the minimum allocated address space failed as expected with errno %d : %s",
132 					 TEST_ERRNO,
133 					 strerror(TEST_ERRNO));
134 			} else {
135 				tst_resm(TFAIL,
136 					 "rmdir() - path argument points below the minimum allocated address space failed with errno %d : %s but expected %d (EFAULT)",
137 					 TEST_ERRNO,
138 					 strerror(TEST_ERRNO), EFAULT);
139 			}
140 		} else {
141 			tst_resm(TFAIL,
142 				 "rmdir() - path argument points below the minimum allocated address space succeeded unexpectedly.");
143 		}
144 
145 		/*
146 		 * TEST CASE: 5
147 		 * path argument points above the maximum allocated address space
148 		 */
149 
150 		TEST(rmdir(get_high_address()));
151 
152 		if (TEST_RETURN == -1) {
153 		}
154 
155 		if (TEST_RETURN == -1) {
156 			if (TEST_ERRNO == EFAULT) {
157 				tst_resm(TPASS,
158 					 "rmdir() - path argument points above the maximum allocated address space failed as expected with errno %d : %s",
159 					 TEST_ERRNO,
160 					 strerror(TEST_ERRNO));
161 			} else {
162 				tst_resm(TFAIL,
163 					 "rmdir() - path argument points above the maximum allocated address space failed with errno %d : %s but expected %d (EFAULT)",
164 					 TEST_ERRNO,
165 					 strerror(TEST_ERRNO), EFAULT);
166 			}
167 		} else {
168 			tst_resm(TFAIL,
169 				 "rmdir() - path argument points above the maximum allocated address space succeeded unexpectedly.");
170 		}
171 #endif
172 
173 		/*
174 		 * TEST CASE: 6
175 		 * able to remove a directory
176 		 */
177 
178 		if (mkdir(dir_name, 0777) != 0) {
179 			tst_brkm(TBROK, cleanup,
180 				 "mkdir(\"%s\") failed with errno %d : %s",
181 				 dir_name, errno, strerror(errno));
182 		}
183 
184 		TEST(rmdir(dir_name));
185 
186 		if (TEST_RETURN == -1) {
187 			tst_resm(TFAIL,
188 				 "rmdir(\"%s\") failed when it should have passed. Returned %d : %s",
189 				 dir_name, TEST_ERRNO, strerror(TEST_ERRNO));
190 		} else {
191 			/* Verify the directory was removed. */
192 			if (stat(dir_name, &stat_buf) != 0) {
193 				tst_resm(TPASS,
194 					 "rmdir(\"%s\") removed the directory as expected.",
195 					 dir_name);
196 			} else {
197 				tst_resm(TFAIL,
198 					 "rmdir(\"%s\") returned a zero exit status but failed to remove the directory.",
199 					 dir_name);
200 			}
201 		}
202 
203 	}
204 
205 	cleanup();
206 	tst_exit();
207 }
208 
setup(void)209 void setup(void)
210 {
211 	tst_sig(FORK, DEF_HANDLER, cleanup);
212 
213 	TEST_PAUSE;
214 
215 	tst_tmpdir();
216 
217 	/* Create a directory. */
218 	SAFE_MKDIR(cleanup, "dir1", 0777);
219 
220 	/* Create a unique directory name. */
221 	sprintf(dir_name, "./dir_%d", getpid());
222 
223 #if !defined(UCLINUX)
224 	bad_addr = mmap(0, 1, PROT_NONE,
225 			MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
226 	if (bad_addr == MAP_FAILED) {
227 		tst_brkm(TBROK, cleanup, "mmap failed");
228 	}
229 #endif
230 }
231 
cleanup(void)232 void cleanup(void)
233 {
234 	tst_rmdir();
235 }
236