about summary refs log tree commit diff
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' */