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 
49 static void setup(void);
50 static void cleanup(void);
51 
52 #if !defined(UCLINUX)
53 extern char *get_high_address();
54 int TST_TOTAL = 6;
55 #else
56 int TST_TOTAL = 4;
57 #endif
58 
59 char *TCID = "rmdir05";
60 
61 static struct stat stat_buf;
62 static char dir_name[256];
63 
64 static char *bad_addr = NULL;
65 
main(int argc,char ** argv)66 int main(int argc, char **argv)
67 {
68 	int lc;
69 
70 	tst_parse_opts(argc, argv, NULL, NULL);
71 
72 	setup();
73 
74 	for (lc = 0; TEST_LOOPING(lc); lc++) {
75 		tst_count = 0;
76 
77 		/*
78 		 * TEST CASE: 1
79 		 * path points to the current directory
80 		 */
81 		TEST(rmdir("."));
82 
83 		if (TEST_RETURN == -1) {
84 			if (TEST_ERRNO & (EBUSY | ENOTEMPTY)) {
85 				/* For functionality tests, verify that the
86 				 * directory wasn't removed.
87 				 */
88 				if (stat(".", &stat_buf) == -1) {
89 					tst_resm(TFAIL,
90 						 "rmdir(\".\") removed the current working directory when it should have failed.");
91 				} else {
92 					tst_resm(TPASS,
93 						 "rmdir(\".\") failed to remove the current working directory. Returned %d : %s",
94 						 TEST_ERRNO,
95 						 strerror(TEST_ERRNO));
96 				}
97 			} else {
98 				tst_resm(TFAIL,
99 					 "rmdir(\".\") failed with errno %d : %s but expected %d (EBUSY)",
100 					 TEST_ERRNO,
101 					 strerror(TEST_ERRNO), EBUSY);
102 			}
103 		} else {
104 			tst_resm(TFAIL,
105 				 "rmdir(\".\") succeeded unexpectedly.");
106 		}
107 
108 		/*
109 		 * TEST CASE: 2
110 		 * path points to the "." (dot) entry of a directory
111 		 */
112 		tst_resm(TCONF, "rmdir on \"dir/.\" supported on Linux");
113 
114 		tst_resm(TCONF,
115 			 "linked directories test not implemented on Linux");
116 
117 		/*
118 		 * TEST CASE: 4
119 		 * path argument points below the minimum allocated address space
120 		 */
121 #if !defined(UCLINUX)
122 		TEST(rmdir(bad_addr));
123 
124 		if (TEST_RETURN == -1) {
125 		}
126 
127 		if (TEST_RETURN == -1) {
128 			if (TEST_ERRNO == EFAULT) {
129 				tst_resm(TPASS,
130 					 "rmdir() - path argument points below the minimum allocated address space failed as expected with errno %d : %s",
131 					 TEST_ERRNO,
132 					 strerror(TEST_ERRNO));
133 			} else {
134 				tst_resm(TFAIL,
135 					 "rmdir() - path argument points below the minimum allocated address space failed with errno %d : %s but expected %d (EFAULT)",
136 					 TEST_ERRNO,
137 					 strerror(TEST_ERRNO), EFAULT);
138 			}
139 		} else {
140 			tst_resm(TFAIL,
141 				 "rmdir() - path argument points below the minimum allocated address space succeeded unexpectedly.");
142 		}
143 
144 		/*
145 		 * TEST CASE: 5
146 		 * path argument points above the maximum allocated address space
147 		 */
148 
149 		TEST(rmdir(get_high_address()));
150 
151 		if (TEST_RETURN == -1) {
152 		}
153 
154 		if (TEST_RETURN == -1) {
155 			if (TEST_ERRNO == EFAULT) {
156 				tst_resm(TPASS,
157 					 "rmdir() - path argument points above the maximum allocated address space failed as expected with errno %d : %s",
158 					 TEST_ERRNO,
159 					 strerror(TEST_ERRNO));
160 			} else {
161 				tst_resm(TFAIL,
162 					 "rmdir() - path argument points above the maximum allocated address space failed with errno %d : %s but expected %d (EFAULT)",
163 					 TEST_ERRNO,
164 					 strerror(TEST_ERRNO), EFAULT);
165 			}
166 		} else {
167 			tst_resm(TFAIL,
168 				 "rmdir() - path argument points above the maximum allocated address space succeeded unexpectedly.");
169 		}
170 #endif
171 
172 		/*
173 		 * TEST CASE: 6
174 		 * able to remove a directory
175 		 */
176 
177 		if (mkdir(dir_name, 0777) != 0) {
178 			tst_brkm(TBROK, cleanup,
179 				 "mkdir(\"%s\") failed with errno %d : %s",
180 				 dir_name, errno, strerror(errno));
181 		}
182 
183 		TEST(rmdir(dir_name));
184 
185 		if (TEST_RETURN == -1) {
186 			tst_resm(TFAIL,
187 				 "rmdir(\"%s\") failed when it should have passed. Returned %d : %s",
188 				 dir_name, TEST_ERRNO, strerror(TEST_ERRNO));
189 		} else {
190 			/* Verify the directory was removed. */
191 			if (stat(dir_name, &stat_buf) != 0) {
192 				tst_resm(TPASS,
193 					 "rmdir(\"%s\") removed the directory as expected.",
194 					 dir_name);
195 			} else {
196 				tst_resm(TFAIL,
197 					 "rmdir(\"%s\") returned a zero exit status but failed to remove the directory.",
198 					 dir_name);
199 			}
200 		}
201 
202 	}
203 
204 	cleanup();
205 	tst_exit();
206 }
207 
setup(void)208 void setup(void)
209 {
210 	tst_sig(FORK, DEF_HANDLER, cleanup);
211 
212 	TEST_PAUSE;
213 
214 	tst_tmpdir();
215 
216 	/* Create a directory. */
217 	if (mkdir("dir1", 0777) == -1) {
218 		tst_brkm(TBROK, cleanup, "mkdir() failed to create dir1.");
219 	}
220 
221 	/* Create a unique directory name. */
222 	sprintf(dir_name, "./dir_%d", getpid());
223 
224 #if !defined(UCLINUX)
225 	bad_addr = mmap(0, 1, PROT_NONE,
226 			MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
227 	if (bad_addr == MAP_FAILED) {
228 		tst_brkm(TBROK, cleanup, "mmap failed");
229 	}
230 #endif
231 }
232 
cleanup(void)233 void cleanup(void)
234 {
235 	tst_rmdir();
236 }
237