blob: 2de03ccba8bb7bc98bc2c09eb375df90ad19bad8 [file] [log] [blame]
/*
*
* 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;
}