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