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:
Stefan Farfeleder 2008-02-24 16:50:55 +00:00
parent 628f51d275
commit 55d2c5b573
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=176521

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;
}