1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-10-27 04:40:59 +01:00

26754: tweak zgetdir() and test for realpath()

This commit is contained in:
Peter Stephenson 2009-03-19 15:00:18 +00:00
parent 9e1a3e6d06
commit cb6856d115
5 changed files with 69 additions and 8 deletions

View file

@ -1,3 +1,8 @@
2009-03-19 Peter Stephenson <pws@csr.com>
* 26754: configure.ac, Doc/Zsh/expn.yo, Src/compat.c, Src/hist.c:
tweak zgetdir() (but don't use it) and test for realpath().
2009-03-18 Peter Stephenson <p.w.stephenson@ntlworld.com>
* 26752: Src/hist.c: fix ../ removal in :a and metafication
@ -11443,5 +11448,5 @@
*****************************************************
* This is used by the shell to define $ZSH_PATCHLEVEL
* $Revision: 1.4624 $
* $Revision: 1.4625 $
*****************************************************

View file

@ -223,7 +223,8 @@ if necessary, and resolves any use of `tt(..)' and `tt(.)' in the path.
item(tt(A))(
As `tt(a)', but also resolve use of symbolic links where possible.
Note that resolution of `tt(..)' occurs em(before) resolution of symbolic
links.
links. This call is equivalent to tt(a) unless your system has the
tt(realpath) system call (modern systems do).
)
item(tt(e))(
Remove all but the extension.

View file

@ -227,6 +227,26 @@ zopenmax(void)
}
#endif
/*
* Rationalise the current directory, returning the string.
*
* If "d" is not NULL, it is used to store information about the
* directory. The returned name is also present in d->dirname and is in
* permanently allocated memory. The handling of this case depends on
* whether the fchdir() system call is available; if it is, it is assumed
* the caller is able to restore the current directory. On successfully
* identifying the directory the function returns immediately rather
* than ascending the hierarchy.
*
* If "d" is NULL, no assumption about the caller's behaviour is
* made. The returned string is in heap memory. This case is
* always handled by changing directory up the hierarchy.
*
* On Cygwin or other systems where USE_GETCWD is defined (at the
* time of writing only QNX), we skip all the above and use the
* getcwd() system call.
*/
/**/
mod_export char *
zgetdir(struct dirsav *d)
@ -257,25 +277,30 @@ zgetdir(struct dirsav *d)
return buf;
}
/* Record the initial inode and device */
pino = sbuf.st_ino;
pdev = sbuf.st_dev;
if (d)
d->ino = pino, d->dev = pdev;
#if !defined(__CYGWIN__) && !defined(USE_GETCWD)
#ifdef HAVE_FCHDIR
else
#endif
#if !defined(__CYGWIN__) && !defined(USE_GETCWD)
holdintr();
for (;;) {
/* Examine the parent of the current directory. */
if (stat("..", &sbuf) < 0)
break;
/* Inode and device of curtent directory */
ino = pino;
dev = pdev;
/* Inode and device of current directory's parent */
pino = sbuf.st_ino;
pdev = sbuf.st_dev;
/* If they're the same, we've reached the root directory. */
if (ino == pino && dev == pdev) {
if (!buf[pos])
buf[--pos] = '/';
@ -291,6 +316,7 @@ zgetdir(struct dirsav *d)
return buf + pos;
}
/* Search the parent for the current directory. */
if (!(dir = opendir("..")))
break;
@ -303,6 +329,7 @@ zgetdir(struct dirsav *d)
continue;
#ifdef HAVE_STRUCT_DIRENT_D_STAT
if(de->d_stat.st_dev == dev && de->d_stat.st_ino == ino) {
/* Found the directory we're currently in */
strncpy(nbuf + 3, fn, PATH_MAX);
break;
}
@ -311,6 +338,7 @@ zgetdir(struct dirsav *d)
if (dev != pdev || (ino_t) de->d_ino == ino)
# endif /* HAVE_STRUCT_DIRENT_D_INO */
{
/* Maybe found directory, need to check device & inode */
strncpy(nbuf + 3, fn, PATH_MAX);
lstat(nbuf, &sbuf);
if (sbuf.st_dev == dev && sbuf.st_ino == ino)
@ -320,7 +348,7 @@ zgetdir(struct dirsav *d)
}
closedir(dir);
if (!de)
break;
break; /* Not found */
len = strlen(nbuf + 2);
pos -= len;
while (pos <= 1) {

View file

@ -1579,7 +1579,14 @@ chabspath(char **junkptr)
int
chrealpath(char **junkptr)
{
char *str;
#ifdef HAVE_CANONICALIZE_FILE_NAME
char *lastpos, *nonreal, *real;
#else
# ifdef HAVE_REAL_PATH
char *lastpos, *nonreal, real[PATH_MAX];
# endif
#endif
if (!**junkptr)
return 1;
@ -1588,6 +1595,9 @@ chrealpath(char **junkptr)
if (!chabspath(junkptr))
return 0;
#if !defined(HAVE_REALPATH) && !defined(HAVE_CANONICALIZE_FILE_NAME)
return 1;
#else
/*
* Notice that this means you cannot pass relative paths into this
* function!
@ -1600,7 +1610,19 @@ chrealpath(char **junkptr)
lastpos = strend(*junkptr);
nonreal = lastpos + 1;
while (!realpath(*junkptr, real)) {
while (!
#ifdef HAVE_CANONICALIZE_FILE_NAME
/*
* This is a GNU extension to realpath(); it's the
* same as calling realpath() with a NULL second argument
* which uses malloc() to get memory. The alternative
* interface is easier to test for, however.
*/
(real = canonicalize_file_name(*junkptr))
#else
realpath(*junkptr, real)
#endif
) {
if (errno == EINVAL || errno == ELOOP ||
errno == ENAMETOOLONG || errno == ENOMEM)
return 0;
@ -1615,7 +1637,7 @@ chrealpath(char **junkptr)
*nonreal = '\0';
}
char *str = nonreal;
str = nonreal;
while (str <= lastpos) {
if (*str == '\0')
*str = '/';
@ -1623,6 +1645,10 @@ chrealpath(char **junkptr)
}
*junkptr = metafy(bicat(real, nonreal), -1, META_HEAPDUP);
#ifdef HAVE_CANONICALIZE_FILE_NAME
free(real);
#endif
#endif
return 1;
}

View file

@ -1157,7 +1157,8 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \
grantpt unlockpt ptsname \
htons ntohs \
regcomp regexec regerror regfree \
gdbm_open getxattr)
gdbm_open getxattr \
realpath canonicalize_file_name)
AC_FUNC_STRCOLL
if test x$enable_cap = xyes; then