zsh-workers
 help / color / mirror / code / Atom feed
* PATCH: Handle ENOENT/ENOTDIR in zpathmax()
@ 2000-08-05  5:51 Bart Schaefer
  2000-08-05  6:24 ` Bart Schaefer
  0 siblings, 1 reply; 2+ messages in thread
From: Bart Schaefer @ 2000-08-05  5:51 UTC (permalink / raw)
  To: zsh-workers

When I commit this, I'm going to also back out 12541 and 12533.

Index: Src/compat.c
===================================================================
@@ -118,21 +118,52 @@
  * some other flag value) in order to determine that the resource is *
  * unlimited.  What use is leaving errno unchanged?  Instead, define *
  * a wrapper that resets errno to 0 and returns 0 for "the system    *
- * does not have a limit."                                           *
+ * does not have a limit," so that -1 always means a real error.     *
  *                                                                   *
- * This is replaced by a macro from system.h if not HAVE_PATHCONF.   */
+ * This is replaced by a macro from system.h if not HAVE_PATHCONF.   *
+ *
+ * Note that the length of a relative path is compared without first *
+ * prepending the current directory, if pathconf() does not return   *
+ * an error.  This is for consistency with the macro and with older  *
+ * zsh behavior; it may be problematic in the ENOENT/ENOTDIR cases.  */
 
 /**/
 mod_export long
 zpathmax(char *dir)
 {
     long pathmax;
+
+    if (!dir || !*dir)
+	dir = ".";
     errno = 0;
     if ((pathmax = pathconf(dir, _PC_PATH_MAX)) >= 0) {
+	/* This code is redundant if pathconf works correctly, but   *
+	 * some versions of glibc pathconf return a hardwired value. */
 	if (strlen(dir) < pathmax)
 	    return pathmax;
 	else
 	    errno = ENAMETOOLONG;
+    } else if (errno == ENOENT || errno == ENOTDIR) {
+	/* Work backward to find a directory, until we run out of path. */
+	char *tail = strrchr(dir, '/');
+	while (tail > dir && tail[-1] == '/')
+	    --tail;
+	if (tail > dir) {
+	    *tail = 0;
+	    pathmax = zpathmax(dir);
+	    *tail = '/';
+	    if (pathmax > 0) {
+		if (strlen(dir) < pathmax)
+		    return pathmax;
+		else
+		    errno = ENAMETOOLONG;
+	    }
+	}
+	/* else                                                          *
+	 * Either we're at the root (tail == dir) or we're on the first  *
+	 * component of a relative path (tail == NULL).  Either way we   *
+	 * have nothing to do here, the error from pathconf() is real.   *
+	 * Perhaps our current working directory has been removed?       */
     }
     if (errno)
 	return -1;

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: PATCH: Handle ENOENT/ENOTDIR in zpathmax()
  2000-08-05  5:51 PATCH: Handle ENOENT/ENOTDIR in zpathmax() Bart Schaefer
@ 2000-08-05  6:24 ` Bart Schaefer
  0 siblings, 0 replies; 2+ messages in thread
From: Bart Schaefer @ 2000-08-05  6:24 UTC (permalink / raw)
  To: zsh-workers

On Aug 5,  5:51am, Bart Schaefer wrote:
} +	/* else                                                          *
} +	 * Either we're at the root (tail == dir) or we're on the first  *
} +	 * component of a relative path (tail == NULL).  Either way we   *
} +	 * have nothing to do here, the error from pathconf() is real.   *
} +	 * Perhaps our current working directory has been removed?       */

I just realized that the above mishandles base cases of the recursion.
(I have the stupid hardwired glibc pathconf so I can't easily test that
branch.)  That is, I suspect `mkdir notadir' or `mkdir /notadir' would
fail with 12547 and a working pathconf().

So the below might call pathconf() twice if dir = "." and the current
directory has been removed, or if pathconf("/") fails, but I figured both
of those are rare enough not to be worth a special-case test in the code.

I also decided to go back to letting pathconf() choke on NULL or "" if it
wants to.

Index: Src/compat.c
===================================================================
@@ -133,8 +133,6 @@
 {
     long pathmax;
 
-    if (!dir || !*dir)
-	dir = ".";
     errno = 0;
     if ((pathmax = pathconf(dir, _PC_PATH_MAX)) >= 0) {
 	/* This code is redundant if pathconf works correctly, but   *
@@ -152,18 +150,19 @@
 	    *tail = 0;
 	    pathmax = zpathmax(dir);
 	    *tail = '/';
-	    if (pathmax > 0) {
-		if (strlen(dir) < pathmax)
-		    return pathmax;
-		else
-		    errno = ENAMETOOLONG;
-	    }
+	} else {
+	    errno = 0;
+	    if (tail)
+		pathmax = pathconf("/", _PC_PATH_MAX);
+	    else
+		pathmax = pathconf(".", _PC_PATH_MAX);
 	}
-	/* else                                                          *
-	 * Either we're at the root (tail == dir) or we're on the first  *
-	 * component of a relative path (tail == NULL).  Either way we   *
-	 * have nothing to do here, the error from pathconf() is real.   *
-	 * Perhaps our current working directory has been removed?       */
+	if (pathmax > 0) {
+	    if (strlen(dir) < pathmax)
+		return pathmax;
+	    else
+		errno = ENAMETOOLONG;
+	}
     }
     if (errno)
 	return -1;

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2000-08-05  6:25 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-08-05  5:51 PATCH: Handle ENOENT/ENOTDIR in zpathmax() Bart Schaefer
2000-08-05  6:24 ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).