summaryrefslogtreecommitdiff
path: root/Src
diff options
context:
space:
mode:
authorBart Schaefer <barts@users.sourceforge.net>2000-08-05 05:59:53 +0000
committerBart Schaefer <barts@users.sourceforge.net>2000-08-05 05:59:53 +0000
commit1ff8518b16525776c932d8856d62b79343a53b72 (patch)
tree7c55c4dbe2e3c811b951051c1102a1a0ca49f139 /Src
parent45ffc3b6c8e5cca800a0ed55bbf9b1bb1c362b00 (diff)
downloadzsh-1ff8518b16525776c932d8856d62b79343a53b72.tar.gz
zsh-1ff8518b16525776c932d8856d62b79343a53b72.zip
12547: Handle ENOENT and ENOTDIR in zpathmax().
Diffstat (limited to 'Src')
-rw-r--r--Src/Modules/files.c18
-rw-r--r--Src/compat.c48
2 files changed, 35 insertions, 31 deletions
diff --git a/Src/Modules/files.c b/Src/Modules/files.c
index ac775c75a..d01a59b03 100644
--- a/Src/Modules/files.c
+++ b/Src/Modules/files.c
@@ -71,7 +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;
- char *head;
umask(oumask);
if(ops['m']) {
@@ -92,19 +91,8 @@ bin_mkdir(char *nam, char **args, char *ops, int func)
while(ptr > *args + (**args == '/') && *--ptr == '/')
*ptr = 0;
-
-/* Drop the tail so that pathconf receives a potentially valid pathname */
- head = (char *) ztrdup(*args);
- if ((ptr = strrchr(head, '/')))
- *ptr = 0;
- else {
-/* Relative to current directory */
- *head = '.';
- *(head + 1) = '\0';
- }
-
- if(zpathmax(unmeta(head)) < 0) {
- zwarnnam(nam, "%s: %e", head, errno);
+ if(zpathmax(unmeta(*args)) < 0) {
+ zwarnnam(nam, "%s: %e", *args, errno);
err = 1;
continue;
}
@@ -133,8 +121,6 @@ bin_mkdir(char *nam, char **args, char *ops, int func)
}
} else
err |= domkdir(nam, *args, mode, 0);
-
- free(head);
}
return err;
}
diff --git a/Src/compat.c b/Src/compat.c
index 27c9c740c..f639c8b8a 100644
--- a/Src/compat.c
+++ b/Src/compat.c
@@ -118,21 +118,52 @@ strerror(int errnum)
* 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;
@@ -141,19 +172,6 @@ zpathmax(char *dir)
}
#endif
-/**/
-mod_export char *
-zrealpath(const char *path, char *resolved_path)
-{
-#ifdef HAVE_REALPATH
- return realpath(path, resolved_path);
-#else /* the following block should be replaced with a realpath() equiv. */
- long pathmax;
-
- if ((pathmax = zpathmax(path)) > 0)
- return strncpy(resolved_path, path, pathmax);
-#endif
-}
/**/
mod_export char *