1 /*
2  *
3  *   Copyright (c) International Business Machines  Corp., 2001
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
17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 /*
21  * NAME
22  *	getcwd02
23  *
24  * DESCRIPTION
25  *	Testcase to check the basic functionality of the getcwd(2) system call.
26  *
27  * ALGORITHM
28  *	Get the path name of the current working directory from the current
29  *	shell through a pipe, and compare it with what is returned by
30  *	getcwd(2) system call.
31  *
32  *  Blocks 1-4 are with char[], #4 is special case where address is -1
33  *
34  *	Block 1: Call getcwd(2) with valid cwd[]:
35  *              Should work fine
36  *	Block 2: Call getcwd(2) with valid cwd[], size = 0:
37  *              Should return NULL, errno = EINVAL
38  *	Block 3: Call getcwd(2) with valid cwd[], size <= strlen(path):
39  *              i.e. size = 1, Should return NULL, errno = ERANGE
40  *      Block 4: Call getcwd(2) with cwd address = -1, size > strlen(path):
41  *              Should return NULL, errno = EFAULT
42  *
43  *  Blocks 5-7 are with char*
44  *
45  *	Block 5: Call getcwd(2) with *buffer = NULL, size = 0:
46  * 		Should allocate buffer, and work fine
47  *	Block 6: Call getcwd(2) with *buffer = NULL, size <= strlen(path):
48  * 		i.e. size = 1, Should return NULL, errno = ERANGE
49  *      Block 7: Call getcwd(2) with *buffer = NULL, size > strlen(path):
50  *              Should work fine and allocate buffer
51  *
52  * HISTORY
53  *	07/2001 Ported by Wayne Boyer
54  *      02/2002 Added more testcases, cleaned up by wjh
55  *
56  * RESTRICTIONS
57  *	NONE
58  */
59 #include <stdio.h>
60 #include <string.h>
61 #include <errno.h>
62 #include "test.h"
63 #define FAILED 1
64 
65 #ifdef ANDROID
66 char *pwd = "/system/bin/pwd";
67 #else
68 char *pwd = "/bin/pwd";
69 #endif
70 int flag;
71 char *TCID = "getcwd02";
72 int TST_TOTAL = 7;
73 
74 void cleanup(void);
75 void setup(void);
76 void do_block1(void);
77 void do_block2(void);
78 void do_block3(void);
79 void do_block4(void);
80 void do_block5(void);
81 void do_block6(void);
82 void do_block7(void);
83 
84 char pwd_buf[BUFSIZ];		//holds results of pwd pipe
85 char cwd[BUFSIZ];		//used as our valid buffer
86 char *buffer = NULL;		//catches the return value from getcwd when passing NULL
87 char *cwd_ptr = NULL;		//catches the return value from getcwd() when passing cwd[]
88 
main(int ac,char ** av)89 int main(int ac, char **av)
90 {
91 	FILE *fin;
92 	char *cp;
93 	int lc;
94 
95 	tst_parse_opts(ac, av, NULL, NULL);
96 	setup();
97 
98 	/*
99 	 * The following loop checks looping state if -i option given
100 	 */
101 	for (lc = 0; TEST_LOOPING(lc); lc++) {
102 		tst_count = 0;
103 
104 		if ((fin = popen(pwd, "r")) == NULL) {
105 			tst_resm(TINFO, "%s: can't run %s", TCID, pwd);
106 			tst_brkm(TBROK, cleanup, "%s FAILED", TCID);
107 		}
108 		while (fgets(pwd_buf, sizeof(pwd_buf), fin) != NULL) {
109 			if ((cp = strchr(pwd_buf, '\n')) == NULL) {
110 				tst_brkm(TBROK, cleanup, "pwd output too long");
111 			}
112 			*cp = 0;
113 		}
114 		pclose(fin);
115 
116 		do_block1();
117 		do_block2();
118 		do_block3();
119 		do_block4();
120 		do_block5();
121 		do_block6();
122 		do_block7();
123 	}
124 	cleanup();
125 	tst_exit();
126 }
127 
do_block1(void)128 void do_block1(void)		//valid cwd[]: -> Should work fine
129 {
130 	int flag = 0;
131 	tst_resm(TINFO, "Enter Block 1");
132 
133 	if ((cwd_ptr = getcwd(cwd, sizeof(cwd))) == NULL) {
134 		tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly");
135 		flag = FAILED;
136 	}
137 	if ((flag != FAILED) && (strcmp(pwd_buf, cwd) != 0)) {
138 		tst_resm(TFAIL, "getcwd() returned unexpected working "
139 			 "directory: expected: %s, got: %s\n", pwd_buf, cwd);
140 		flag = FAILED;
141 	}
142 	tst_resm(TINFO, "Exit Block 1");
143 	if (flag == FAILED) {
144 		tst_resm(TFAIL, "Block 1 FAILED");
145 	} else {
146 		tst_resm(TPASS, "Block 1 PASSED");
147 	}
148 }
149 
do_block2(void)150 void do_block2(void)		//valid cwd[], size = 0: -> Should return NULL, errno = EINVAL
151 {
152 	int flag = 0;
153 	tst_resm(TINFO, "Enter Block 2");
154 
155 	if (((cwd_ptr = getcwd(cwd, 0)) == NULL)
156 	    && (errno != EINVAL)) {
157 		tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly (wanted EINVAL)");
158 		flag = FAILED;
159 	}
160 	tst_resm(TINFO, "Exit Block 2");
161 	if (flag == FAILED) {
162 		tst_resm(TFAIL, "Block 2 FAILED");
163 	} else {
164 		tst_resm(TPASS, "Block 2 PASSED");
165 	}
166 }
167 
do_block3(void)168 void do_block3(void)		//valid cwd[], size = 1 -> Should return NULL, errno = ERANGE
169 {
170 	int flag = 0;
171 	tst_resm(TINFO, "Enter Block 3");
172 
173 	if (((cwd_ptr = getcwd(cwd, 1)) != NULL)
174 	    || (errno != ERANGE)) {
175 		tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly (wanted ERANGE)");
176 		flag = FAILED;
177 	}
178 	tst_resm(TINFO, "Exit Block 3");
179 	if (flag == FAILED) {
180 		tst_resm(TFAIL, "Block 3 FAILED");
181 	} else {
182 		tst_resm(TPASS, "Block 3 PASSED");
183 	}
184 }
185 
do_block4(void)186 void do_block4(void)		//invalid cwd[] = -1, size = BUFSIZ: -> return NULL, errno = FAULT
187 {
188 /* Skip since uClinux does not implement memory protection */
189 #ifndef UCLINUX
190 	int flag = 0;
191 	tst_resm(TINFO, "Enter Block 4");
192 
193 	if (((cwd_ptr = getcwd((char *)-1, sizeof(cwd))) != NULL)
194 	    || (errno != EFAULT)) {
195 		tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly (wanted EFAULT)");
196 		flag = FAILED;
197 	}
198 	tst_resm(TINFO, "Exit Block 4");
199 	if (flag == FAILED) {
200 		tst_resm(TFAIL, "Block 4 FAILED");
201 	} else {
202 		tst_resm(TPASS, "Block 4 PASSED");
203 	}
204 #else
205 	tst_resm(TINFO, "Skipping Block 4 on uClinux");
206 #endif
207 }
208 
do_block5(void)209 void do_block5(void)		//buffer = NULL, and size = 0, should succeed
210 {
211 	int flag = 0;
212 	tst_resm(TINFO, "Enter Block 5");
213 
214 	if ((buffer = getcwd(NULL, 0)) == NULL) {
215 		tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly");
216 		flag = FAILED;
217 	}
218 	if ((flag != FAILED) && (strcmp(pwd_buf, buffer) != 0)) {
219 		tst_resm(TFAIL, "getcwd() returned unexpected working "
220 			 "directory: expected: %s, got: %s\n", pwd_buf, buffer);
221 		flag = FAILED;
222 	}
223 	tst_resm(TINFO, "Exit Block 5");
224 	if (flag == FAILED) {
225 		tst_resm(TFAIL, "Block 5 FAILED");
226 	} else {
227 		tst_resm(TPASS, "Block 5 PASSED");
228 	}
229 	free(buffer);
230 	buffer = NULL;
231 }
232 
do_block6(void)233 void do_block6(void)		//buffer = NULL, size = 1: -> return NULL, errno = ERANGE
234 {
235 	int flag = 0;
236 	tst_resm(TINFO, "Enter Block 6");
237 
238 	if (((buffer = getcwd(NULL, 1)) != NULL)
239 	    || (errno != ERANGE)) {
240 		tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly (wanted ERANGE)");
241 		flag = FAILED;
242 	}
243 	tst_resm(TINFO, "Exit Block 6");
244 	if (flag == FAILED) {
245 		tst_resm(TFAIL, "Block 6 FAILED");
246 	} else {
247 		tst_resm(TPASS, "Block 6 PASSED");
248 	}
249 }
250 
do_block7(void)251 void do_block7(void)		//buffer = NULL, size = BUFSIZ: -> work fine, allocate buffer
252 {
253 	int flag = 0;
254 	tst_resm(TINFO, "Enter Block 7");
255 
256 	if ((buffer = getcwd(NULL, sizeof(cwd))) == NULL) {
257 		tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly");
258 		flag = FAILED;
259 	}
260 	if ((flag != FAILED) && (strcmp(pwd_buf, buffer) != 0)) {
261 		tst_resm(TFAIL, "getcwd() returned unexpected working "
262 			 "directory: expected: %s, got: %s\n", pwd_buf, buffer);
263 		flag = FAILED;
264 	}
265 	tst_resm(TINFO, "Exit Block 7");
266 	if (flag == FAILED) {
267 		tst_resm(TFAIL, "Block 7 FAILED");
268 	} else {
269 		tst_resm(TPASS, "Block 7 PASSED");
270 	}
271 	free(buffer);
272 	buffer = NULL;
273 }
274 
setup(void)275 void setup(void)
276 {
277 	/* FORK is set here because of the popen() call above */
278 	tst_sig(FORK, DEF_HANDLER, cleanup);
279 
280 	TEST_PAUSE;
281 
282 	/* create a test directory and cd into it */
283 	tst_tmpdir();
284 }
285 
cleanup(void)286 void cleanup(void)
287 {
288 	/* remove the test directory */
289 	tst_rmdir();
290 }
291