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