In perl.git, the branch blead has been updated <http://perl5.git.perl.org/perl.git/commitdiff/c5fb6bf8085ed840a95d03bfc398ea2cbb5af237?hp=0d314ba30623b19c36dfc97ac4b6ecb94cb406f4>
- Log ----------------------------------------------------------------- commit c5fb6bf8085ed840a95d03bfc398ea2cbb5af237 Author: Karl Williamson <[email protected]> Date: Mon Feb 2 22:32:26 2015 -0700 Extend Cwd to work on z/OS sysplexed systems On sysplexed os390 systems, the literal string "$SYSNAME" in a directory path appears to the code to be a symbolic link to itself. If one wants to walk $SYSNAME/tmp, for example, one keeps recursing, adding $SYSNAMEs on to the front of the path until our fail-safe limit is reached. This would like something like $SYSNAME/$SYSNAME/.../$SYSNAME /tmp never reaching the tmp. What this commit does is to replace all instances of $SYSNAME/foo simply by /foo, for all foo when $SYSNAME is a symbolic link. Then the above would resolve simply to /tmp. There appears to not be a problem with the pure perl version M dist/PathTools/Cwd.xs commit 84d69ee45a9fb53bd8ad6eedb0a982473b16f758 Author: Karl Williamson <[email protected]> Date: Sat Jan 31 22:13:19 2015 -0700 dist/PathTools/Cwd.xs: rename variable 'left' implies to me a direction, especially in this context where we are parsing a path from left to right; instead it here means 'remaining', which I've renamed it to. M dist/PathTools/Cwd.xs commit 1a2852080e59eb00ee837f96af934664d2ac55b7 Author: Karl Williamson <[email protected]> Date: Thu Jan 29 10:00:40 2015 -0700 dist/PathTools/Cwd.xs: White-space/comment only Bring indentation style of bsd_realpath() into line with the rest of Perl M dist/PathTools/Cwd.xs commit 7e590c5b093dcc44d6a40f8d64e3d90f56caed66 Author: Karl Williamson <[email protected]> Date: Thu Mar 12 21:05:46 2015 -0600 Bump version of dist/PathTools to 3.55 M dist/PathTools/Cwd.pm M dist/PathTools/lib/File/Spec.pm M dist/PathTools/lib/File/Spec/Cygwin.pm M dist/PathTools/lib/File/Spec/Epoc.pm M dist/PathTools/lib/File/Spec/Functions.pm M dist/PathTools/lib/File/Spec/Mac.pm M dist/PathTools/lib/File/Spec/OS2.pm M dist/PathTools/lib/File/Spec/Unix.pm M dist/PathTools/lib/File/Spec/VMS.pm M dist/PathTools/lib/File/Spec/Win32.pm ----------------------------------------------------------------------- Summary of changes: dist/PathTools/Cwd.pm | 2 +- dist/PathTools/Cwd.xs | 279 ++++++++++++++++-------------- dist/PathTools/lib/File/Spec.pm | 2 +- dist/PathTools/lib/File/Spec/Cygwin.pm | 2 +- dist/PathTools/lib/File/Spec/Epoc.pm | 2 +- dist/PathTools/lib/File/Spec/Functions.pm | 2 +- dist/PathTools/lib/File/Spec/Mac.pm | 2 +- dist/PathTools/lib/File/Spec/OS2.pm | 2 +- dist/PathTools/lib/File/Spec/Unix.pm | 2 +- dist/PathTools/lib/File/Spec/VMS.pm | 2 +- dist/PathTools/lib/File/Spec/Win32.pm | 2 +- 11 files changed, 163 insertions(+), 136 deletions(-) diff --git a/dist/PathTools/Cwd.pm b/dist/PathTools/Cwd.pm index 1811a24..fd24b6e 100644 --- a/dist/PathTools/Cwd.pm +++ b/dist/PathTools/Cwd.pm @@ -3,7 +3,7 @@ use strict; use Exporter; use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION); -$VERSION = '3.54'; +$VERSION = '3.55'; my $xs_version = $VERSION; $VERSION =~ tr/_//; diff --git a/dist/PathTools/Cwd.xs b/dist/PathTools/Cwd.xs index 1f174bf..9c43d23 100644 --- a/dist/PathTools/Cwd.xs +++ b/dist/PathTools/Cwd.xs @@ -1,3 +1,13 @@ +/* + * Local variables: + * c-indentation-style: bsd + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * + * ex: set ts=8 sts=4 sw=4 et: + */ + #define PERL_NO_GET_CONTEXT #include "EXTERN.h" @@ -11,6 +21,10 @@ # include <unistd.h> #endif +/* For special handling of os390 sysplexed systems */ +#define SYSNAME "$SYSNAME" +#define SYSNAME_LEN (sizeof(SYSNAME) - 1) + /* The realpath() implementation from OpenBSD 3.9 to 4.2 (realpath.c 1.13) * Renamed here to bsd_realpath() to avoid library conflicts. */ @@ -68,144 +82,157 @@ char * bsd_realpath(const char *path, char resolved[MAXPATHLEN]) { char *p, *q, *s; - size_t left_len, resolved_len; + size_t remaining_len, resolved_len; unsigned symlinks; int serrno; - char left[MAXPATHLEN], next_token[MAXPATHLEN]; + char remaining[MAXPATHLEN], next_token[MAXPATHLEN]; serrno = errno; symlinks = 0; if (path[0] == '/') { - resolved[0] = '/'; - resolved[1] = '\0'; - if (path[1] == '\0') - return (resolved); - resolved_len = 1; - left_len = my_strlcpy(left, path + 1, sizeof(left)); + resolved[0] = '/'; + resolved[1] = '\0'; + if (path[1] == '\0') + return (resolved); + resolved_len = 1; + remaining_len = my_strlcpy(remaining, path + 1, sizeof(remaining)); } else { - if (getcwd(resolved, MAXPATHLEN) == NULL) { - my_strlcpy(resolved, ".", MAXPATHLEN); - return (NULL); - } - resolved_len = strlen(resolved); - left_len = my_strlcpy(left, path, sizeof(left)); + if (getcwd(resolved, MAXPATHLEN) == NULL) { + my_strlcpy(resolved, ".", MAXPATHLEN); + return (NULL); + } + resolved_len = strlen(resolved); + remaining_len = my_strlcpy(remaining, path, sizeof(remaining)); } - if (left_len >= sizeof(left) || resolved_len >= MAXPATHLEN) { - errno = ENAMETOOLONG; - return (NULL); + if (remaining_len >= sizeof(remaining) || resolved_len >= MAXPATHLEN) { + errno = ENAMETOOLONG; + return (NULL); } /* - * Iterate over path components in 'left'. + * Iterate over path components in 'remaining'. */ - while (left_len != 0) { - /* - * Extract the next path component and adjust 'left' - * and its length. - */ - p = strchr(left, '/'); - s = p ? p : left + left_len; - if ((STRLEN)(s - left) >= (STRLEN)sizeof(next_token)) { - errno = ENAMETOOLONG; - return (NULL); - } - memcpy(next_token, left, s - left); - next_token[s - left] = '\0'; - left_len -= s - left; - if (p != NULL) - memmove(left, s + 1, left_len + 1); - if (resolved[resolved_len - 1] != '/') { - if (resolved_len + 1 >= MAXPATHLEN) { - errno = ENAMETOOLONG; - return (NULL); - } - resolved[resolved_len++] = '/'; - resolved[resolved_len] = '\0'; - } - if (next_token[0] == '\0') - continue; - else if (strcmp(next_token, ".") == 0) - continue; - else if (strcmp(next_token, "..") == 0) { - /* - * Strip the last path component except when we have - * single "/" - */ - if (resolved_len > 1) { - resolved[resolved_len - 1] = '\0'; - q = strrchr(resolved, '/') + 1; - *q = '\0'; - resolved_len = q - resolved; - } - continue; - } - - /* - * Append the next path component and lstat() it. If - * lstat() fails we still can return successfully if - * there are no more path components left. - */ - resolved_len = my_strlcat(resolved, next_token, MAXPATHLEN); - if (resolved_len >= MAXPATHLEN) { - errno = ENAMETOOLONG; - return (NULL); - } + while (remaining_len != 0) { + + /* + * Extract the next path component and adjust 'remaining' + * and its length. + */ + + p = strchr(remaining, '/'); + s = p ? p : remaining + remaining_len; + if ((STRLEN)(s - remaining) >= (STRLEN)sizeof(next_token)) { + errno = ENAMETOOLONG; + return (NULL); + } + memcpy(next_token, remaining, s - remaining); + next_token[s - remaining] = '\0'; + remaining_len -= s - remaining; + if (p != NULL) + memmove(remaining, s + 1, remaining_len + 1); + if (resolved[resolved_len - 1] != '/') { + if (resolved_len + 1 >= MAXPATHLEN) { + errno = ENAMETOOLONG; + return (NULL); + } + resolved[resolved_len++] = '/'; + resolved[resolved_len] = '\0'; + } + if (next_token[0] == '\0') + continue; + else if (strcmp(next_token, ".") == 0) + continue; + else if (strcmp(next_token, "..") == 0) { + /* + * Strip the last path component except when we have + * single "/" + */ + if (resolved_len > 1) { + resolved[resolved_len - 1] = '\0'; + q = strrchr(resolved, '/') + 1; + *q = '\0'; + resolved_len = q - resolved; + } + continue; + } + + /* + * Append the next path component and lstat() it. If + * lstat() fails we still can return successfully if + * there are no more path components left. + */ + resolved_len = my_strlcat(resolved, next_token, MAXPATHLEN); + if (resolved_len >= MAXPATHLEN) { + errno = ENAMETOOLONG; + return (NULL); + } #if defined(HAS_LSTAT) && defined(HAS_READLINK) && defined(HAS_SYMLINK) - { - struct stat sb; - if (lstat(resolved, &sb) != 0) { - if (errno == ENOENT && p == NULL) { - errno = serrno; - return (resolved); - } - return (NULL); - } - if (S_ISLNK(sb.st_mode)) { - int slen; - char symlink[MAXPATHLEN]; - - if (symlinks++ > MAXSYMLINKS) { - errno = ELOOP; - return (NULL); - } - slen = readlink(resolved, symlink, sizeof(symlink) - 1); - if (slen < 0) - return (NULL); - symlink[slen] = '\0'; - if (symlink[0] == '/') { - resolved[1] = 0; - resolved_len = 1; - } else if (resolved_len > 1) { - /* Strip the last path component. */ - resolved[resolved_len - 1] = '\0'; - q = strrchr(resolved, '/') + 1; - *q = '\0'; - resolved_len = q - resolved; - } - - /* - * If there are any path components left, then - * append them to symlink. The result is placed - * in 'left'. - */ - if (p != NULL) { - if (symlink[slen - 1] != '/') { - if ((STRLEN)(slen + 1) >= (STRLEN)sizeof(symlink)) { - errno = ENAMETOOLONG; - return (NULL); - } - symlink[slen] = '/'; - symlink[slen + 1] = 0; - } - left_len = my_strlcat(symlink, left, sizeof(symlink)); - if (left_len >= sizeof(left)) { - errno = ENAMETOOLONG; - return (NULL); - } - } - left_len = my_strlcpy(left, symlink, sizeof(left)); - } - } + { + struct stat sb; + if (lstat(resolved, &sb) != 0) { + if (errno == ENOENT && p == NULL) { + errno = serrno; + return (resolved); + } + return (NULL); + } + if (S_ISLNK(sb.st_mode)) { + int slen; + char symlink[MAXPATHLEN]; + + if (symlinks++ > MAXSYMLINKS) { + errno = ELOOP; + return (NULL); + } + slen = readlink(resolved, symlink, sizeof(symlink) - 1); + if (slen < 0) + return (NULL); + symlink[slen] = '\0'; +#ifdef EBCDIC /* XXX Probably this should be only os390 */ + /* Replace all instances of $SYSNAME/foo simply by /foo */ + if (slen > SYSNAME_LEN + strlen(next_token) + && strnEQ(symlink, SYSNAME, SYSNAME_LEN) + && *(symlink + SYSNAME_LEN) == '/' + && strEQ(symlink + SYSNAME_LEN + 1, next_token)) + { + goto not_symlink; + } +#endif + if (symlink[0] == '/') { + resolved[1] = 0; + resolved_len = 1; + } else if (resolved_len > 1) { + /* Strip the last path component. */ + resolved[resolved_len - 1] = '\0'; + q = strrchr(resolved, '/') + 1; + *q = '\0'; + resolved_len = q - resolved; + } + + /* + * If there are any path components left, then + * append them to symlink. The result is placed + * in 'remaining'. + */ + if (p != NULL) { + if (symlink[slen - 1] != '/') { + if ((STRLEN)(slen + 1) >= (STRLEN)sizeof(symlink)) { + errno = ENAMETOOLONG; + return (NULL); + } + symlink[slen] = '/'; + symlink[slen + 1] = 0; + } + remaining_len = my_strlcat(symlink, remaining, sizeof(symlink)); + if (remaining_len >= sizeof(remaining)) { + errno = ENAMETOOLONG; + return (NULL); + } + } + remaining_len = my_strlcpy(remaining, symlink, sizeof(remaining)); + } + not_symlink: ; + } #endif } @@ -214,7 +241,7 @@ bsd_realpath(const char *path, char resolved[MAXPATHLEN]) * is a single "/". */ if (resolved_len > 1 && resolved[resolved_len - 1] == '/') - resolved[resolved_len - 1] = '\0'; + resolved[resolved_len - 1] = '\0'; return (resolved); } #endif diff --git a/dist/PathTools/lib/File/Spec.pm b/dist/PathTools/lib/File/Spec.pm index 7da1ce4..688ea00 100644 --- a/dist/PathTools/lib/File/Spec.pm +++ b/dist/PathTools/lib/File/Spec.pm @@ -3,7 +3,7 @@ package File::Spec; use strict; use vars qw(@ISA $VERSION); -$VERSION = '3.53'; +$VERSION = '3.55'; $VERSION =~ tr/_//; my %module = (MacOS => 'Mac', diff --git a/dist/PathTools/lib/File/Spec/Cygwin.pm b/dist/PathTools/lib/File/Spec/Cygwin.pm index c81292c..ab917c5 100644 --- a/dist/PathTools/lib/File/Spec/Cygwin.pm +++ b/dist/PathTools/lib/File/Spec/Cygwin.pm @@ -4,7 +4,7 @@ use strict; use vars qw(@ISA $VERSION); require File::Spec::Unix; -$VERSION = '3.54'; +$VERSION = '3.55'; $VERSION =~ tr/_//; @ISA = qw(File::Spec::Unix); diff --git a/dist/PathTools/lib/File/Spec/Epoc.pm b/dist/PathTools/lib/File/Spec/Epoc.pm index 0f9f71a..8c3b64c 100644 --- a/dist/PathTools/lib/File/Spec/Epoc.pm +++ b/dist/PathTools/lib/File/Spec/Epoc.pm @@ -3,7 +3,7 @@ package File::Spec::Epoc; use strict; use vars qw($VERSION @ISA); -$VERSION = '3.54'; +$VERSION = '3.55'; $VERSION =~ tr/_//; require File::Spec::Unix; diff --git a/dist/PathTools/lib/File/Spec/Functions.pm b/dist/PathTools/lib/File/Spec/Functions.pm index 3f87865..1ded427 100644 --- a/dist/PathTools/lib/File/Spec/Functions.pm +++ b/dist/PathTools/lib/File/Spec/Functions.pm @@ -5,7 +5,7 @@ use strict; use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION); -$VERSION = '3.54'; +$VERSION = '3.55'; $VERSION =~ tr/_//; require Exporter; diff --git a/dist/PathTools/lib/File/Spec/Mac.pm b/dist/PathTools/lib/File/Spec/Mac.pm index 7aaf302..2b0935b 100644 --- a/dist/PathTools/lib/File/Spec/Mac.pm +++ b/dist/PathTools/lib/File/Spec/Mac.pm @@ -4,7 +4,7 @@ use strict; use vars qw(@ISA $VERSION); require File::Spec::Unix; -$VERSION = '3.54'; +$VERSION = '3.55'; $VERSION =~ tr/_//; @ISA = qw(File::Spec::Unix); diff --git a/dist/PathTools/lib/File/Spec/OS2.pm b/dist/PathTools/lib/File/Spec/OS2.pm index 291ac97..92d95f7 100644 --- a/dist/PathTools/lib/File/Spec/OS2.pm +++ b/dist/PathTools/lib/File/Spec/OS2.pm @@ -4,7 +4,7 @@ use strict; use vars qw(@ISA $VERSION); require File::Spec::Unix; -$VERSION = '3.54'; +$VERSION = '3.55'; $VERSION =~ tr/_//; @ISA = qw(File::Spec::Unix); diff --git a/dist/PathTools/lib/File/Spec/Unix.pm b/dist/PathTools/lib/File/Spec/Unix.pm index 6860209..98a232d 100644 --- a/dist/PathTools/lib/File/Spec/Unix.pm +++ b/dist/PathTools/lib/File/Spec/Unix.pm @@ -3,7 +3,7 @@ package File::Spec::Unix; use strict; use vars qw($VERSION); -$VERSION = '3.54'; +$VERSION = '3.55'; my $xs_version = $VERSION; $VERSION =~ tr/_//; diff --git a/dist/PathTools/lib/File/Spec/VMS.pm b/dist/PathTools/lib/File/Spec/VMS.pm index 1fe08a8..d74c0be 100644 --- a/dist/PathTools/lib/File/Spec/VMS.pm +++ b/dist/PathTools/lib/File/Spec/VMS.pm @@ -4,7 +4,7 @@ use strict; use vars qw(@ISA $VERSION); require File::Spec::Unix; -$VERSION = '3.54'; +$VERSION = '3.55'; $VERSION =~ tr/_//; @ISA = qw(File::Spec::Unix); diff --git a/dist/PathTools/lib/File/Spec/Win32.pm b/dist/PathTools/lib/File/Spec/Win32.pm index d148271..bbaf0e3 100644 --- a/dist/PathTools/lib/File/Spec/Win32.pm +++ b/dist/PathTools/lib/File/Spec/Win32.pm @@ -5,7 +5,7 @@ use strict; use vars qw(@ISA $VERSION); require File::Spec::Unix; -$VERSION = '3.54'; +$VERSION = '3.55'; $VERSION =~ tr/_//; @ISA = qw(File::Spec::Unix); -- Perl5 Master Repository
