diff --git a/check.t b/check.t index 08c9be5..b463c9f 100644 --- a/check.t +++ b/check.t @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/check.t,v 1.386 2010/07/25 11:35:38 tg Exp $ +# $MirOS: src/bin/mksh/check.t,v 1.387 2010/08/24 14:42:00 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 2010/07/25 + @(#)MIRBSD KSH R39 2010/08/24 description: Check version of shell. stdin: @@ -7372,3 +7372,74 @@ stdin: expected-stdout: 1 . --- +name: realpath-1 +description: + Check proper return values for realpath +stdin: + wd=$(realpath .) + mkdir dir + :>file + :>dir/file + ln -s dir lndir + ln -s file lnfile + ln -s nix lnnix + ln -s . lnself + i=0 + chk() { + typeset x y + x=$(realpath "$wd/$1" 2>&1); y=$? + print $((++i)) "?$1" =${x##*$wd/} !$y + } + chk dir + chk dir/ + chk dir/file + chk dir/nix + chk file + chk file/ + chk file/file + chk file/nix + chk nix + chk nix/ + chk nix/file + chk nix/nix + chk lndir + chk lndir/ + chk lndir/file + chk lndir/nix + chk lnfile + chk lnfile/ + chk lnfile/file + chk lnfile/nix + chk lnnix + chk lnnix/ + chk lnnix/file + chk lnnix/nix + chk 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 + rm lnself +expected-stdout: + 1 ?dir =dir !0 + 2 ?dir/ =dir !0 + 3 ?dir/file =dir/file !0 + 4 ?dir/nix =dir/nix !0 + 5 ?file =file !0 + 6 ?file/ =file/: Not a directory !20 + 7 ?file/file =file/file: Not a directory !20 + 8 ?file/nix =file/nix: Not a directory !20 + 9 ?nix =nix !0 + 10 ?nix/ =nix !0 + 11 ?nix/file =nix/file: No such file or directory !2 + 12 ?nix/nix =nix/nix: No such file or directory !2 + 13 ?lndir =dir !0 + 14 ?lndir/ =dir !0 + 15 ?lndir/file =dir/file !0 + 16 ?lndir/nix =dir/nix !0 + 17 ?lnfile =file !0 + 18 ?lnfile/ =lnfile/: Not a directory !20 + 19 ?lnfile/file =lnfile/file: Not a directory !20 + 20 ?lnfile/nix =lnfile/nix: Not a directory !20 + 21 ?lnnix =nix !0 + 22 ?lnnix/ =nix !0 + 23 ?lnnix/file =lnnix/file: No such file or directory !2 + 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 +--- diff --git a/funcs.c b/funcs.c index 4ec5dab..9d9c03a 100644 --- a/funcs.c +++ b/funcs.c @@ -25,7 +25,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.156 2010/07/17 22:09:34 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.157 2010/08/24 14:42:01 tg Exp $"); #if HAVE_KILLPG /* @@ -290,7 +290,7 @@ do_realpath(const char *upath) */ xp = (ldest[0] == '/') ? Xstring(xs, xp) : Xrestpos(xs, xp, pos); - tp = shf_smprintf("%s/%s", ldest, ip); + tp = shf_smprintf("%s%s%s", ldest, *ip ? "/" : "", ip); afree(ipath, ATEMP); ip = ipath = tp; } @@ -309,6 +309,22 @@ do_realpath(const char *upath) Xput(xs, xp, '/'); Xput(xs, xp, '\0'); + /* + * if source path had a trailing slash, check if target path + * is not a non-directory existing file + */ + if (ip > ipath && ip[-1] == '/') { + if (stat(Xstring(xs, xp), &sb)) { + if (errno != ENOENT) + goto notfound; + } else if (!S_ISDIR(sb.st_mode)) { + errno = ENOTDIR; + goto notfound; + } + /* target now either does not exist or is a directory */ + } + + /* return target path */ if (ldest != NULL) afree(ldest, ATEMP); afree(ipath, ATEMP); diff --git a/mksh.1 b/mksh.1 index 597ef30..74ef458 100644 --- a/mksh.1 +++ b/mksh.1 @@ -1,4 +1,4 @@ -.\" $MirOS: src/bin/mksh/mksh.1,v 1.234 2010/08/14 20:13:10 tg Exp $ +.\" $MirOS: src/bin/mksh/mksh.1,v 1.235 2010/08/24 14:42:03 tg Exp $ .\" $OpenBSD: ksh.1,v 1.136 2010/07/15 20:04:35 schwarze Exp $ .\"- .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 @@ -71,7 +71,7 @@ .\" with -mandoc, it might implement .Mx itself, but we want to .\" use our own definition. And .Dd must come *first*, always. .\" -.Dd $Mdocdate: August 14 2010 $ +.Dd $Mdocdate: August 24 2010 $ .\" .\" Check which macro package we use .\" @@ -3629,6 +3629,14 @@ printed. .Xc Prints the resolved absolute pathname corresponding to .Ar name . +If +.Ar name +ends with a slash +.Pq Sq / , +it's also checked for existence and whether it is a directory; otherwise, +.Ic realpath +returns 0 if the pathname either exists or can be created immediately, +i.e. all but the last component exist and are directories. .Pp .It Ic rename Ar from to Renames the file diff --git a/sh.h b/sh.h index 70361f0..15f709b 100644 --- a/sh.h +++ b/sh.h @@ -150,9 +150,9 @@ #endif #ifdef EXTERN -__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.403 2010/08/14 21:35:13 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.404 2010/08/24 14:42:04 tg Exp $"); #endif -#define MKSH_VERSION "R39 2010/07/25" +#define MKSH_VERSION "R39 2010/08/24" #ifndef MKSH_INCLUDES_ONLY