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 66char *pwd = "/system/bin/pwd"; 67#else 68char *pwd = "/bin/pwd"; 69#endif 70int flag; 71char *TCID = "getcwd02"; 72int TST_TOTAL = 7; 73 74void cleanup(void); 75void setup(void); 76void do_block1(void); 77void do_block2(void); 78void do_block3(void); 79void do_block4(void); 80void do_block5(void); 81void do_block6(void); 82void do_block7(void); 83 84char pwd_buf[BUFSIZ]; //holds results of pwd pipe 85char cwd[BUFSIZ]; //used as our valid buffer 86char *buffer = NULL; //catches the return value from getcwd when passing NULL 87char *cwd_ptr = NULL; //catches the return value from getcwd() when passing cwd[] 88 89int 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 128void 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 150void 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 168void 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 186void 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 209void 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 233void 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 251void 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 275void 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 286void cleanup(void) 287{ 288 /* remove the test directory */ 289 tst_rmdir(); 290} 291