From 7850fc5a2cbdbcec1da405f4d3eba65abf3293f8 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 8 Jun 2010 08:51:03 +0000 Subject: 28006: make zgetcwd() fall back to pwd, only use "." if setting pwd --- ChangeLog | 8 +++++++- Src/builtin.c | 2 ++ Src/compat.c | 50 +++++++++++++++++++++++++++++++++++++++----------- Src/init.c | 4 +++- 4 files changed, 51 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 80d16851e..a51fe9cf9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-06-08 Peter Stephenson + + * 28006: Src/builtin.c, Src/compat.c, Src/init.c: Make zgetcwd() + fall back to pwd in preference to returning "."; only use "." if + we're trying to set pwd at that point. + 2010-06-08 Doug Kearns * unposted: Completion/Mandriva/Command/_urpmi: fix typo in parameter @@ -13257,5 +13263,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.4995 $ +* $Revision: 1.4996 $ ***************************************************** diff --git a/Src/builtin.c b/Src/builtin.c index e9e8e3bff..6dbd1597f 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -805,6 +805,7 @@ bin_cd(char *nam, char **argv, Options ops, int func) if (stat(unmeta(pwd), &st1) < 0) { setjobpwd(); zsfree(pwd); + pwd = NULL; pwd = metafy(zgetcwd(), -1, META_DUP); } else if (stat(".", &st2) < 0) { if (chdir(unmeta(pwd)) < 0) @@ -813,6 +814,7 @@ bin_cd(char *nam, char **argv, Options ops, int func) if (chasinglinks) { setjobpwd(); zsfree(pwd); + pwd = NULL; pwd = metafy(zgetcwd(), -1, META_DUP); } else if (chdir(unmeta(pwd)) < 0) zwarn("unable to chdir(%s): %e", pwd, errno); diff --git a/Src/compat.c b/Src/compat.c index 5400f627f..e72bf6268 100644 --- a/Src/compat.c +++ b/Src/compat.c @@ -275,11 +275,7 @@ zgetdir(struct dirsav *d) buf[pos] = '\0'; strcpy(nbuf, "../"); if (stat(".", &sbuf) < 0) { - if (d) - return NULL; - buf[0] = '.'; - buf[1] = '\0'; - return buf; + return NULL; } /* Record the initial inode and device */ @@ -354,6 +350,11 @@ zgetdir(struct dirsav *d) closedir(dir); if (!de) break; /* Not found */ + /* + * We get the "/" free just by copying from nbuf+2 instead + * of nbuf+3, which is where we copied the path component. + * This means buf[pos] is always a "/". + */ len = strlen(nbuf + 2); pos -= len; while (pos <= 1) { @@ -371,15 +372,22 @@ zgetdir(struct dirsav *d) if (chdir("..")) break; } + + /* + * Fix up the directory, if necessary. + * We're changing back down the hierarchy, ignore the + * "/" at buf[pos]. + */ if (d) { #ifndef HAVE_FCHDIR - if (*buf) + if (buf[pos]) zchdir(buf + pos + 1); noholdintr(); #endif return NULL; } - if (*buf) + + if (buf[pos]) zchdir(buf + pos + 1); noholdintr(); @@ -397,16 +405,36 @@ zgetdir(struct dirsav *d) } #endif - buf[0] = '.'; - buf[1] = '\0'; - return buf; + /* + * Something bad happened. + * This has been seen when inside a special directory, + * such as the Netapp .snapshot directory, that doesn't + * appear as a directory entry in the parent directory. + * We'll just need our best guess. + * + * We only get here from zgetcwd(); let that fall back to pwd. + */ + + return NULL; } +/* + * Try to find the current directory. + * If it fails, fall back to pwd; if zgetcwd() is being used + * to set pwd, pwd should be NULL and we just return ".". + * We could fall back to getcwd() instead. + */ + /**/ char * zgetcwd(void) { - return zgetdir(NULL); + char *ret = zgetdir(NULL); + if (!ret) + ret = pwd; + if (!ret) + ret = dupstring("."); + return ret; } /* chdir with arbitrary long pathname. Returns 0 on success, -1 on normal * diff --git a/Src/init.c b/Src/init.c index dea9aff40..06f177725 100644 --- a/Src/init.c +++ b/Src/init.c @@ -861,8 +861,10 @@ setupvals(void) else if ((ptr = zgetenv("PWD")) && (strlen(ptr) < PATH_MAX) && (ptr = metafy(ptr, -1, META_STATIC), ispwd(ptr))) pwd = ztrdup(ptr); - else + else { + pwd = NULL; pwd = metafy(zgetcwd(), -1, META_DUP); + } oldpwd = ztrdup(pwd); /* initialize `OLDPWD' = `PWD' */ -- cgit 1.4.1