diff --git a/check.t b/check.t index ef66a4c..afc6e1f 100644 --- a/check.t +++ b/check.t @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/check.t,v 1.431 2011/03/21 21:57:32 tg Exp $ +# $MirOS: src/bin/mksh/check.t,v 1.432 2011/03/23 18:47:04 tg Exp $ # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $ @@ -25,7 +25,7 @@ # http://www.research.att.com/~gsf/public/ifs.sh expected-stdout: - @(#)MIRBSD KSH R39 2011/03/21 + @(#)MIRBSD KSH R39 2011/03/23 description: Check version of shell. stdin: @@ -8384,6 +8384,36 @@ expected-stdout: 24 ?lnnix/nix =lnnix/nix: No such file or directory !2 25 ?lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself =lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself: Too many levels of symbolic links !62 --- +name: realpath-2 +description: + Ensure that exactly two leading slashes are not collapsed + POSIX guarantees this exception, e.g. for UNC paths on Cygwin +category: os:mirbsd +stdin: + ln -s /bin t1 + ln -s //bin t2 + ln -s ///bin t3 + realpath /bin + realpath //bin + realpath ///bin + realpath /usr/bin + realpath /usr//bin + realpath /usr///bin + realpath t1 + realpath t2 + realpath t3 + rm -f t1 t2 t3 +expected-stdout: + /bin + //bin + /bin + /usr/bin + /usr/bin + /usr/bin + /bin + //bin + /bin +--- name: crash-1 description: Crashed during March 2011, fixed on vernal equinōx ☺ diff --git a/funcs.c b/funcs.c index ead7b0b..b7c0485 100644 --- a/funcs.c +++ b/funcs.c @@ -38,7 +38,7 @@ #endif #endif -__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.177 2011/03/16 20:56:32 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.178 2011/03/23 18:47:06 tg Exp $"); #if HAVE_KILLPG /* @@ -242,6 +242,9 @@ do_realpath(const char *upath) /* ipath and upath are in memory at the same time -> unchecked */ Xinit(xs, xp, strlen(ip = ipath) + 1, ATEMP); + /* now jump into the deep of the loop */ + goto beginning_of_a_pathname; + while (*ip) { /* skip slashes in input */ while (*ip == '/') @@ -328,11 +331,25 @@ do_realpath(const char *upath) * restart if symlink target is an absolute path, * otherwise continue with currently resolved prefix */ - xp = (ldest[0] == '/') ? Xstring(xs, xp) : - Xrestpos(xs, xp, pos); + /* append rest of current input path to link target */ tp = shf_smprintf("%s%s%s", ldest, *ip ? "/" : "", ip); afree(ipath, ATEMP); ip = ipath = tp; + if (ldest[0] != '/') { + /* symlink target is a relative path */ + xp = Xrestpos(xs, xp, pos); + } else { + /* symlink target is an absolute path */ + xp = Xstring(xs, xp); + beginning_of_a_pathname: + /* assert: (ip == ipath)[0] == '/' */ + /* assert: xp == xs.beg => start of path */ + + if (ip[1] == '/' && ip[2] != '/') { + /* keep UNC names, per POSIX */ + Xput(xs, xp, '/'); + } + } } /* otherwise (no symlink) merely go on */ } diff --git a/sh.h b/sh.h index 444da3e..5b2c5b1 100644 --- a/sh.h +++ b/sh.h @@ -154,9 +154,9 @@ #endif #ifdef EXTERN -__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.450 2011/03/21 21:57:33 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.451 2011/03/23 18:47:07 tg Exp $"); #endif -#define MKSH_VERSION "R39 2011/03/21" +#define MKSH_VERSION "R39 2011/03/23" #ifndef MKSH_INCLUDES_ONLY