| /* |
| * |
| * Copyright (c) International Business Machines Corp., 2001 |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
| * the GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| /* |
| * NAME |
| * getcwd03 |
| * |
| * DESCRIPTION |
| * Testcase to check the basic functionality of the getcwd(2) system call |
| * for symbolically linked directories. |
| * |
| * ALGORITHM |
| * This testcase checks for the functionality of the getcwd(2) system call |
| * on a symbolic link. First create a directory (dir1), and create a |
| * symbolic link (dir2) to it at the same directory level. Then, chdir() |
| * to dir1, and get the working directory (cwd1), and its pathname (pwd1). |
| * Then, chdir() to dir2, and get the working directory (cwd2), its |
| * pathname (pwd2), and its readlink info (link2). |
| * Testcase succeeds if: |
| * i. pwd1 == pwd2 |
| * ii. cwd1 == cwd2 |
| * iii. link2 == basename(cwd1) |
| * |
| * USAGE: <for command-line> |
| * getcwd03 [-c n] [-i n] [-I x] [-P x] [-t] |
| * where, -c n : Run n copies concurrently. |
| * -i n : Execute test n times. |
| * -I x : Execute test for x seconds. |
| * -P x : Pause for x seconds between iterations. |
| * -t : Turn on syscall timing. |
| * |
| * HISTORY |
| * 07/2001 Ported by Wayne Boyer |
| * |
| * RESTRICTIONS |
| * NONE |
| */ |
| #define _GNU_SOURCE 1 |
| #include <stdio.h> |
| #include <string.h> |
| #include <errno.h> |
| #include "test.h" |
| #include <stdlib.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| #include <stdlib.h> |
| #define FAILED 1 |
| |
| int flag; |
| char *TCID = "getcwd03"; |
| int TST_TOTAL = 1; |
| |
| void cleanup(void); |
| void setup(void); |
| char *getpwd(void); |
| |
| int main(int ac, char **av) |
| { |
| char dir1[BUFSIZ], dir2[BUFSIZ]; |
| char cwd1[BUFSIZ], cwd2[BUFSIZ]; |
| char *pwd1, *pwd2; |
| char link2[BUFSIZ]; |
| int n; |
| int lc; |
| const char *msg; /* parse_opts() return message */ |
| |
| if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) { |
| tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); |
| } |
| |
| setup(); |
| |
| /* |
| * The following loop checks looping state if -i option given |
| */ |
| for (lc = 0; TEST_LOOPING(lc); lc++) { |
| tst_count = 0; |
| |
| flag = 0; |
| |
| /* |
| * Create dir1, then chdir to dir1, and get the pwd, |
| * and cwd informations |
| */ |
| sprintf(dir1, "getcwd1.%d", getpid()); |
| if (mkdir(dir1, 00755) < 0) { |
| tst_brkm(TBROK, cleanup, "mkdir(2) failed"); |
| } |
| if (chdir(dir1) != 0) { |
| tst_brkm(TBROK, cleanup, "chdir(2) failed"); |
| } |
| |
| pwd1 = getpwd(); |
| if (getcwd(cwd1, sizeof cwd1) == NULL) { |
| tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly"); |
| flag = FAILED; |
| } |
| if ((flag != FAILED) && (strcmp(pwd1, cwd1) != 0)) { |
| tst_brkm(TFAIL, cleanup, "getcwd() returned unexpected " |
| "working directory: expected: %s, got: %s\n", |
| pwd1, cwd1); |
| } |
| |
| tst_resm(TINFO, "getcwd(2) succeeded in returning correct path " |
| "for dir1"); |
| |
| /* |
| * Now create dir2, then chdir to dir2, and get the pwd, |
| * cwd, and link informations |
| */ |
| chdir(".."); |
| flag = 0; |
| |
| sprintf(dir2, "getcwd2.%d", getpid()); |
| if (symlink(dir1, dir2) < 0) { |
| tst_brkm(TBROK, cleanup, "symlink(2) failed: errno: %d", |
| errno); |
| } |
| |
| if (chdir(dir2) != 0) { |
| tst_brkm(TBROK, cleanup, "chdir(2) failed: errno: %d", |
| errno); |
| } |
| |
| pwd2 = getpwd(); |
| if (getcwd(cwd2, sizeof cwd2) == NULL) { |
| tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly"); |
| flag = FAILED; |
| } |
| |
| chdir(".."); |
| if ((flag != FAILED) && |
| ((n = readlink(dir2, link2, sizeof(link2))) < 0)) { |
| tst_brkm(TBROK, cleanup, "readlink(2) failed: errno:%d", |
| errno); |
| } |
| |
| /* |
| * Finally compare the pwd, cwd, link informations: |
| * The test should pass iff all the following are true: |
| * a. pwd1 == pwd2 |
| * b. cwd1 == cwd2 |
| * c. link2 == basename(cwd1) |
| */ |
| if (flag != FAILED) { |
| if (strcmp(pwd1, pwd2) != 0) { |
| tst_resm(TFAIL, "pwd1: %s, pwd2: %s", |
| pwd1, pwd2); |
| flag = FAILED; |
| } |
| if (strcmp(cwd1, cwd2) != 0) { |
| tst_resm(TFAIL, "cwd1: %s, cwd2: %s", |
| cwd1, cwd2); |
| flag = FAILED; |
| } |
| if (memcmp(link2, (char *)basename(cwd1), n) != 0) { |
| tst_resm(TFAIL, "link2: %s, cwd1: %s", |
| link2, cwd1); |
| flag = FAILED; |
| } |
| if (flag != FAILED) { |
| tst_resm(TINFO, "getcwd(2) succeeded in " |
| "returning correct path for symbolic " |
| "link dir2 -> dir1"); |
| } |
| } |
| |
| if (flag == FAILED) { |
| tst_resm(TFAIL, "Test FAILED"); |
| } else { |
| tst_resm(TPASS, "Test PASSED"); |
| } |
| |
| /* clean up things in case we are looping */ |
| if (unlink(dir2) == -1) { |
| tst_brkm(TBROK, cleanup, "couldnt remove dir2"); |
| } |
| if (rmdir(dir1) == -1) { |
| tst_brkm(TBROK, cleanup, "couldnt remove dir1"); |
| } |
| } |
| cleanup(); |
| |
| tst_exit(); |
| } |
| |
| void setup(void) |
| { |
| /* FORK is set here because of the popen() call below */ |
| tst_sig(FORK, DEF_HANDLER, cleanup); |
| |
| TEST_PAUSE; |
| |
| /* create a test directory and cd into it */ |
| tst_tmpdir(); |
| } |
| |
| void cleanup(void) |
| { |
| /* remove the test directory */ |
| tst_rmdir(); |
| } |
| |
| char *getpwd(void) |
| { |
| FILE *fin; |
| char *pwd = "/bin/pwd"; |
| char *cp; |
| char *buf; |
| |
| buf = malloc(BUFSIZ); |
| if ((fin = popen(pwd, "r")) == NULL) { |
| tst_resm(TINFO, "%s: can't run %s", TCID, pwd); |
| tst_brkm(TBROK, cleanup, "%s FAILED", TCID); |
| } |
| while (fgets(buf, BUFSIZ, fin) != NULL) { |
| if ((cp = strchr(buf, '\n')) == NULL) { |
| tst_brkm(TBROK, cleanup, "pwd output too long"); |
| } |
| *cp = 0; |
| } |
| pclose(fin); |
| return buf; |
| } |