about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Src/Modules/files.c19
-rw-r--r--Src/Modules/parameter.c32
-rw-r--r--Src/compat.c90
-rw-r--r--Src/system.h9
5 files changed, 103 insertions, 53 deletions
diff --git a/ChangeLog b/ChangeLog
index 8d2f8c573..7e35b2ead 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2000-08-04  Bart Schaefer  <schaefer@zsh.org>
+
+	* 12516: Src/compat.c, Src/system.h, Src/Modules/files.c,
+	Src/Modules/parameter.c: Rewrite the pathconf() support using a
+	wrapper function in compat.c to isolate the #ifdefs.
+
 2000-08-03  Peter Stephenson  <pws@csr.com>
 
 	* Andrej: 12501: Src/params.c: getenv etc. become zgetenv etc.
diff --git a/Src/Modules/files.c b/Src/Modules/files.c
index b5e0b5f62..d01a59b03 100644
--- a/Src/Modules/files.c
+++ b/Src/Modules/files.c
@@ -71,9 +71,6 @@ bin_mkdir(char *nam, char **args, char *ops, int func)
     mode_t oumask = umask(0);
     mode_t mode = 0777 & ~oumask;
     int err = 0;
-#ifdef HAVE_PATHCONF
-    int pathmax = 0;
-#endif
 
     umask(oumask);
     if(ops['m']) {
@@ -94,21 +91,11 @@ bin_mkdir(char *nam, char **args, char *ops, int func)
 
 	while(ptr > *args + (**args == '/') && *--ptr == '/')
 	    *ptr = 0;
-#ifdef HAVE_PATHCONF
-	errno = 0;
-	if(((pathmax = pathconf(*args,_PC_PATH_MAX)) == -1) && errno) {
-	  zwarnnam(nam, "%s: %e", *args, errno);
-	  err = 1;
-	  continue;
-	}
-	else if((ztrlen(*args) > pathmax - 1) && errno != -1) {
-#else
-	  if(ztrlen(*args) > PATH_MAX - 1) {
-#endif
-	    zwarnnam(nam, "%s: %e", *args, ENAMETOOLONG);
+	if(zpathmax(unmeta(*args)) < 0) {
+	    zwarnnam(nam, "%s: %e", *args, errno);
 	    err = 1;
 	    continue;
-	  }
+	}
 	if(ops['p']) {
 	    char *ptr = *args;
 
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index 2328eae51..b2b3657c0 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -1397,20 +1397,9 @@ scanpmjobdirs(HashTable ht, ScanFunc func, int flags)
 static void
 setpmnameddir(Param pm, char *value)
 {
-#ifdef HAVE_PATHCONF
-    int pathmax = 0;
-
     errno = 0;
-    pathmax = pathconf(value, _PC_PATH_MAX);
-    if ((pathmax == -1) && errno) {
-      zwarn("%s: %e", value, errno);
-    }
-    else if (!value || *value != '/' || ((strlen(value) >= pathmax) &&
-            pathmax != -1))
-#else
-    if (!value || *value != '/' || strlen(value) >= PATH_MAX)
-#endif
-	zwarn("invalid value: %s", value, 0);
+    if (!value || *value != '/' || zpathmax(value) < 0)
+	zwarn((errno ? "%s: %e" : "invalid value: %s"), value, errno);
     else
 	adduserdir(pm->nam, value, 0, 1);
     zsfree(value);
@@ -1432,9 +1421,6 @@ setpmnameddirs(Param pm, HashTable ht)
 {
     int i;
     HashNode hn, next, hd;
-#ifdef HAVE_PATHCONF
-    int pathmax = 0;
-#endif
 
     if (!ht)
 	return;
@@ -1457,19 +1443,9 @@ setpmnameddirs(Param pm, HashTable ht)
 	    v.arr = NULL;
 	    v.pm = (Param) hn;
 
-#ifdef HAVE_PATHCONF
 	    errno = 0;
-            if((((pathmax = pathconf(val, _PC_PATH_MAX)) == -1)) && errno)
-                zwarn("%s: %e", val, errno);
-            else
-#endif
-	    if (!(val = getstrvalue(&v)) || *val != '/' ||
-#ifdef HAVE_PATHCONF
-                ((strlen(val) >= pathmax)) && pathmax != -1)
-#else
-		strlen(val) >= PATH_MAX)
-#endif
-		zwarn("invalid value: %s", val, 0);
+	    if (!(val = getstrvalue(&v)) || *val != '/' || zpathmax(val) < 0)
+		zwarn((errno ? "%s: %e" : "invalid value: %s"), val, errno);
 	    else
 		adduserdir(hn->nam, val, 0, 1);
 	}
diff --git a/Src/compat.c b/Src/compat.c
index ca9c57aac..2f6628f33 100644
--- a/Src/compat.c
+++ b/Src/compat.c
@@ -105,20 +105,62 @@ strerror(int errnum)
 #endif
 
 
+#ifdef HAVE_PATHCONF
+
+/* The documentation for pathconf() says something like:             *
+ *     The limit is returned, if one exists.  If the system  does    *
+ *     not  have  a  limit  for  the  requested  resource,  -1 is    *
+ *     returned, and errno is unchanged.  If there is  an  error,    *
+ *     -1  is returned, and errno is set to reflect the nature of    *
+ *     the error.                                                    *
+ *                                                                   *
+ * This is less useful than may be, as one must reset errno to 0 (or *
+ * 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."                                           *
+ *                                                                   *
+ * This is replaced by a macro from system.h if not HAVE_PATHCONF.   */
+
 /**/
-char *
+mod_export long
+zpathmax(char *dir)
+{
+    long pathmax;
+    errno = 0;
+    if ((pathmax = pathconf(dir, _PC_PATH_MAX)) >= 0) {
+	if (strlen(dir) < pathmax)
+	    return pathmax;
+	else
+	    errno = ENAMETOOLONG;
+    }
+    if (errno)
+	return -1;
+    else
+	return 0; /* pathmax should be considered unlimited */
+}
+#endif
+
+
+/**/
+mod_export char *
 zgetdir(struct dirsav *d)
 {
     char nbuf[PATH_MAX+3];
     char *buf;
-    int bufsiz, pos, len;
+    int bufsiz, pos;
     struct stat sbuf;
+    ino_t pino;
+    dev_t pdev;
+#if !defined(__CYGWIN__) && !defined(USE_GETCWD)
     struct dirent *de;
     DIR *dir;
-    ino_t ino, pino;
-    dev_t dev, pdev;
+    dev_t dev;
+    ino_t ino;
+    int len;
+#endif
 
-    buf = halloc(bufsiz = PATH_MAX);
+    buf = zhalloc(bufsiz = PATH_MAX);
     pos = bufsiz - 1;
     buf[pos] = '\0';
     strcpy(nbuf, "../");
@@ -137,6 +179,7 @@ zgetdir(struct dirsav *d)
 #ifdef HAVE_FCHDIR
     else
 #endif
+#if !defined(__CYGWIN__) && !defined(USE_GETCWD)
 	holdintr();
 
     for (;;) {
@@ -196,7 +239,7 @@ zgetdir(struct dirsav *d)
 	len = strlen(nbuf + 2);
 	pos -= len;
 	while (pos <= 1) {
-	    char *newbuf = halloc(2*bufsiz);
+	    char *newbuf = zhalloc(2*bufsiz);
 	    memcpy(newbuf + bufsiz, buf, bufsiz);
 	    buf = newbuf;
 	    pos += bufsiz;
@@ -221,6 +264,21 @@ zgetdir(struct dirsav *d)
     if (*buf)
 	zchdir(buf + pos + 1);
     noholdintr();
+
+#else  /* __CYGWIN__, USE_GETCWD cases */
+
+    if (!getcwd(buf, bufsiz)) {
+	if (d) {
+	    return NULL;
+	}
+    } else {
+	if (d) {
+	    return d->dirname = ztrdup(buf);
+	}
+	return buf;
+    }
+#endif
+
     buf[0] = '.';
     buf[1] = '\0';
     return buf;
@@ -237,7 +295,7 @@ zgetcwd(void)
  * faliliure and -2 when chdir failed and the current directory is lost.  */
 
 /**/
-int
+mod_export int
 zchdir(char *dir)
 {
     char *s;
@@ -283,3 +341,21 @@ zchdir(char *dir)
     return currdir == -2 ? -1 : -2;
 #endif
 }
+
+/*
+ * How to print out a 64 bit integer.  This isn't needed (1) if longs
+ * are 64 bit, since ordinary %ld will work (2) if we couldn't find a
+ * 64 bit type anyway.
+ */
+/**/
+#ifdef ZSH_64_BIT_TYPE
+/**/
+mod_export char *
+output64(zlong val)
+{
+    static char llbuf[DIGBUFSIZE];
+    convbase(llbuf, val, 0);
+    return llbuf;
+}
+/**/
+#endif /* ZSH_64_BIT_TYPE */
diff --git a/Src/system.h b/Src/system.h
index cba80a5f6..ba83e005e 100644
--- a/Src/system.h
+++ b/Src/system.h
@@ -194,8 +194,8 @@ struct timezone {
 # define VARARR(X,Y,Z)	X *(Y) = (X *) alloca(sizeof(X) * (Z))
 #endif
 
-/* we should be getting this value from pathconf(_PC_PATH_MAX) */
-/* but this is too much trouble                                */
+/* we should handle unlimited sizes from pathconf(_PC_PATH_MAX) */
+/* but this is too much trouble                                 */
 #ifndef PATH_MAX
 # ifdef MAXPATHLEN
 #  define PATH_MAX MAXPATHLEN
@@ -204,6 +204,11 @@ struct timezone {
 #  define PATH_MAX 1024
 # endif
 #endif
+#ifndef HAVE_PATHCONF
+# define zpathmax(X) ((long)((strlen(X) >= PATH_MAX) ? \
+			     ((errno = ENAMETOOLONG), -1) : \
+			     ((errno = 0), PATH_MAX))
+#endif
 
 /* we should be getting this value from sysconf(_SC_OPEN_MAX) */
 /* but this is too much trouble                               */