summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--Src/builtin.c2
-rw-r--r--Src/compat.c50
-rw-r--r--Src/init.c4
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 <pws@csr.com>
+
+ * 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 <dougkearns@gmail.com>
* 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' */