mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-08 12:01:21 +02:00
12547: Handle ENOENT and ENOTDIR in zpathmax().
This commit is contained in:
parent
45ffc3b6c8
commit
1ff8518b16
4 changed files with 42 additions and 32 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
2000-08-04 Bart Schaefer <schaefer@zsh.org>
|
||||||
|
|
||||||
|
* 12547: configure.in, Src/compat.c, Src/Modules/files.c:
|
||||||
|
Handle ENOENT and ENOTDIR within zpathmax(), and therefore back
|
||||||
|
out the changes from 12541 and 12533.
|
||||||
|
|
||||||
2000-08-04 Clint Adams <schizo@debian.org>
|
2000-08-04 Clint Adams <schizo@debian.org>
|
||||||
|
|
||||||
* 12541: configure.in, Src/compat.c: zrealpath wrapper around
|
* 12541: configure.in, Src/compat.c: zrealpath wrapper around
|
||||||
|
|
|
@ -71,7 +71,6 @@ bin_mkdir(char *nam, char **args, char *ops, int func)
|
||||||
mode_t oumask = umask(0);
|
mode_t oumask = umask(0);
|
||||||
mode_t mode = 0777 & ~oumask;
|
mode_t mode = 0777 & ~oumask;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
char *head;
|
|
||||||
|
|
||||||
umask(oumask);
|
umask(oumask);
|
||||||
if(ops['m']) {
|
if(ops['m']) {
|
||||||
|
@ -92,19 +91,8 @@ bin_mkdir(char *nam, char **args, char *ops, int func)
|
||||||
|
|
||||||
while(ptr > *args + (**args == '/') && *--ptr == '/')
|
while(ptr > *args + (**args == '/') && *--ptr == '/')
|
||||||
*ptr = 0;
|
*ptr = 0;
|
||||||
|
if(zpathmax(unmeta(*args)) < 0) {
|
||||||
/* Drop the tail so that pathconf receives a potentially valid pathname */
|
zwarnnam(nam, "%s: %e", *args, errno);
|
||||||
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);
|
|
||||||
err = 1;
|
err = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -133,8 +121,6 @@ bin_mkdir(char *nam, char **args, char *ops, int func)
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
err |= domkdir(nam, *args, mode, 0);
|
err |= domkdir(nam, *args, mode, 0);
|
||||||
|
|
||||||
free(head);
|
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
48
Src/compat.c
48
Src/compat.c
|
@ -118,21 +118,52 @@ strerror(int errnum)
|
||||||
* some other flag value) in order to determine that the resource is *
|
* some other flag value) in order to determine that the resource is *
|
||||||
* unlimited. What use is leaving errno unchanged? Instead, define *
|
* unlimited. What use is leaving errno unchanged? Instead, define *
|
||||||
* a wrapper that resets errno to 0 and returns 0 for "the system *
|
* 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
|
mod_export long
|
||||||
zpathmax(char *dir)
|
zpathmax(char *dir)
|
||||||
{
|
{
|
||||||
long pathmax;
|
long pathmax;
|
||||||
|
|
||||||
|
if (!dir || !*dir)
|
||||||
|
dir = ".";
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if ((pathmax = pathconf(dir, _PC_PATH_MAX)) >= 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)
|
if (strlen(dir) < pathmax)
|
||||||
return pathmax;
|
return pathmax;
|
||||||
else
|
else
|
||||||
errno = ENAMETOOLONG;
|
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)
|
if (errno)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -141,19 +172,6 @@ zpathmax(char *dir)
|
||||||
}
|
}
|
||||||
#endif
|
#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 *
|
mod_export char *
|
||||||
|
|
|
@ -864,7 +864,7 @@ AC_CHECK_FUNCS(strftime difftime gettimeofday \
|
||||||
signgam \
|
signgam \
|
||||||
putenv getenv \
|
putenv getenv \
|
||||||
brk sbrk \
|
brk sbrk \
|
||||||
pathconf realpath)
|
pathconf)
|
||||||
AC_FUNC_STRCOLL
|
AC_FUNC_STRCOLL
|
||||||
|
|
||||||
if test $ac_cv_func_setpgrp = yes; then
|
if test $ac_cv_func_setpgrp = yes; then
|
||||||
|
|
Loading…
Reference in a new issue