fix realpath builtin’s handling of (source) pathnames with a trailing slash
as per POSIX (if a trailing slash is part of the symlink target it fails as well, like GNU readlink -f does)
This commit is contained in:
parent
8b946de857
commit
7fdc42cead
75
check.t
75
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
|
||||
---
|
||||
|
20
funcs.c
20
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);
|
||||
|
12
mksh.1
12
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
|
||||
|
4
sh.h
4
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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user