Split updatepwd() into two smaller functions. The first one, findpwd(),

computes the new path and the second one, updatepwd(), updates the variables
PWD, OLDPWD and the path used for the pwd builtin according to the new
directory.  For a logical directory change, chdir() is now called between
those two functions, no longer causing wrong values to be stored in PWD etc. if
it fails.

PR:	64990, 101316, 120571
This commit is contained in:
stefanf 2008-02-24 16:50:55 +00:00
parent 0d54671a48
commit fe9202bf0f

View File

@ -68,7 +68,9 @@ STATIC int cdlogical(char *);
STATIC int cdphysical(char *);
STATIC int docd(char *, int, int);
STATIC char *getcomponent(void);
STATIC int updatepwd(char *);
STATIC char *findcwd(char *);
STATIC void updatepwd(char *);
STATIC char *getpwd2(char *, size_t);
STATIC char *curdir = NULL; /* current working directory */
STATIC char *prevdir; /* previous working directory */
@ -201,10 +203,11 @@ cdlogical(char *dest)
}
INTOFF;
if (updatepwd(badstat ? NULL : dest) < 0 || chdir(curdir) < 0) {
if ((p = findcwd(badstat ? NULL : dest)) == NULL || chdir(p) < 0) {
INTON;
return (-1);
}
updatepwd(p);
INTON;
return (0);
}
@ -212,12 +215,14 @@ cdlogical(char *dest)
STATIC int
cdphysical(char *dest)
{
char *p;
INTOFF;
if (chdir(dest) < 0 || updatepwd(NULL) < 0) {
if (chdir(dest) < 0 || (p = findcwd(NULL)) == NULL) {
INTON;
return (-1);
}
updatepwd(p);
INTON;
return (0);
}
@ -247,38 +252,20 @@ getcomponent(void)
}
/*
* Update curdir (the name of the current directory) in response to a
* cd command. We also call hashcd to let the routines in exec.c know
* that the current directory has changed.
*/
STATIC int
updatepwd(char *dir)
STATIC char *
findcwd(char *dir)
{
char *new;
char *p;
hashcd(); /* update command hash table */
/*
* If our argument is NULL, we don't know the current directory
* any more because we traversed a symbolic link or something
* we couldn't stat().
*/
if (dir == NULL || curdir == NULL) {
if (prevdir)
ckfree(prevdir);
INTOFF;
prevdir = curdir;
curdir = NULL;
if (getpwd() == NULL) {
INTON;
return (-1);
}
setvar("PWD", curdir, VEXPORT);
setvar("OLDPWD", prevdir, VEXPORT);
INTON;
return (0);
p = stalloc(PATH_MAX);
return getpwd2(p, PATH_MAX);
}
cdcomppath = stalloc(strlen(dir) + 1);
scopy(dir, cdcomppath);
@ -302,16 +289,25 @@ updatepwd(char *dir)
if (new == stackblock())
STPUTC('/', new);
STACKSTRNUL(new);
INTOFF;
return stackblock();
}
/*
* Update curdir (the name of the current directory) in response to a
* cd command. We also call hashcd to let the routines in exec.c know
* that the current directory has changed.
*/
STATIC void
updatepwd(char *dir)
{
hashcd(); /* update command hash table */
if (prevdir)
ckfree(prevdir);
prevdir = curdir;
curdir = savestr(stackblock());
curdir = savestr(dir);
setvar("PWD", curdir, VEXPORT);
setvar("OLDPWD", prevdir, VEXPORT);
INTON;
return (0);
}
int
@ -355,17 +351,31 @@ pwdcmd(int argc, char **argv)
}
/*
* Find out what the current directory is. If we already know the current
* directory, this routine returns immediately.
* Get the current directory and cache the result in curdir.
*/
char *
getpwd(void)
{
char buf[PATH_MAX];
char *p;
if (curdir)
return curdir;
if (getcwd(buf, sizeof(buf)) == NULL) {
p = getpwd2(buf, sizeof(buf));
if (p != NULL)
curdir = savestr(p);
return curdir;
}
/*
* Return the current directory.
*/
STATIC char *
getpwd2(char *buf, size_t size)
{
if (getcwd(buf, size) == NULL) {
char *pwd = getenv("PWD");
struct stat stdot, stpwd;
@ -373,12 +383,9 @@ getpwd(void)
stat(pwd, &stpwd) != -1 &&
stdot.st_dev == stpwd.st_dev &&
stdot.st_ino == stpwd.st_ino) {
curdir = savestr(pwd);
return curdir;
return pwd;
}
return NULL;
}
curdir = savestr(buf);
return curdir;
return buf;
}