add a do_realpath() implementation replacing the use of the external
libc function realpath(3) which may not be available on the target system; compile the realpath builtin unconditionally looks fine to me, but review is appreciated; this is (very) lightly based upon MirBSD libc’s realpath(3) and pdksh’s get_phys_path()
This commit is contained in:
parent
75a7eb63e1
commit
31e02e59f7
20
Build.sh
20
Build.sh
@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.422 2009/08/28 17:37:47 tg Exp $'
|
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.423 2009/08/30 13:22:37 tg Exp $'
|
||||||
#-
|
#-
|
||||||
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||||
# Thorsten Glaser <tg@mirbsd.org>
|
# Thorsten Glaser <tg@mirbsd.org>
|
||||||
@ -919,7 +919,6 @@ if ac_ifcpp 'ifdef MKSH_SMALL' isset_MKSH_SMALL '' \
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
: ${HAVE_MKNOD=0}
|
: ${HAVE_MKNOD=0}
|
||||||
: ${HAVE_REALPATH=0}
|
|
||||||
: ${HAVE_REVOKE=0}
|
: ${HAVE_REVOKE=0}
|
||||||
: ${HAVE_PERSISTENT_HISTORY=0}
|
: ${HAVE_PERSISTENT_HISTORY=0}
|
||||||
check_categories=$check_categories,smksh
|
check_categories=$check_categories,smksh
|
||||||
@ -1168,23 +1167,6 @@ ac_test nice <<-'EOF'
|
|||||||
int main(void) { return (nice(4)); }
|
int main(void) { return (nice(4)); }
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
ac_test realpath <<-'EOF'
|
|
||||||
#if HAVE_SYS_PARAM_H
|
|
||||||
#include <sys/param.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#ifndef PATH_MAX
|
|
||||||
#define PATH_MAX 1024
|
|
||||||
#endif
|
|
||||||
char *res, dst[PATH_MAX];
|
|
||||||
const char src[] = ".";
|
|
||||||
int main(void) {
|
|
||||||
res = realpath(src, dst);
|
|
||||||
return (res == NULL ? 1 : 0);
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
ac_test revoke <<-'EOF'
|
ac_test revoke <<-'EOF'
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#if HAVE_LIBUTIL_H
|
#if HAVE_LIBUTIL_H
|
||||||
|
162
funcs.c
162
funcs.c
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.125 2009/08/28 21:51:51 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.126 2009/08/30 13:22:38 tg Exp $");
|
||||||
|
|
||||||
#if HAVE_KILLPG
|
#if HAVE_KILLPG
|
||||||
/*
|
/*
|
||||||
@ -102,9 +102,7 @@ const struct builtin mkshbuiltins[] = {
|
|||||||
#if HAVE_MKNOD
|
#if HAVE_MKNOD
|
||||||
{"mknod", c_mknod},
|
{"mknod", c_mknod},
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_REALPATH
|
|
||||||
{"realpath", c_realpath},
|
{"realpath", c_realpath},
|
||||||
#endif
|
|
||||||
{"rename", c_rename},
|
{"rename", c_rename},
|
||||||
{NULL, (int (*)(const char **))NULL}
|
{NULL, (int (*)(const char **))NULL}
|
||||||
};
|
};
|
||||||
@ -173,6 +171,146 @@ static void ptest_error(Test_env *, int, const char *);
|
|||||||
static char *kill_fmt_entry(const void *, int, char *, int);
|
static char *kill_fmt_entry(const void *, int, char *, int);
|
||||||
static void p_time(struct shf *, bool, long, int, int,
|
static void p_time(struct shf *, bool, long, int, int,
|
||||||
const char *, const char *) __attribute__((nonnull (6, 7)));
|
const char *, const char *) __attribute__((nonnull (6, 7)));
|
||||||
|
static char *do_realpath(const char *);
|
||||||
|
|
||||||
|
static char *
|
||||||
|
do_realpath(const char *upath)
|
||||||
|
{
|
||||||
|
char *xp, *ip, *tp, *ipath, *ldest = NULL;
|
||||||
|
XString xs;
|
||||||
|
ptrdiff_t pos;
|
||||||
|
size_t len;
|
||||||
|
int symlinks = 32; /* max. recursion depth */
|
||||||
|
int llen;
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
if (upath[0] == '/') {
|
||||||
|
/* upath is an absolute pathname */
|
||||||
|
strdupx(ipath, upath, ATEMP);
|
||||||
|
} else {
|
||||||
|
/* upath is a relative pathname, prepend cwd */
|
||||||
|
if ((tp = ksh_get_wd(NULL)) == NULL || tp[0] != '/')
|
||||||
|
return (NULL);
|
||||||
|
ipath = shf_smprintf("%s/%s", tp, upath);
|
||||||
|
afree(tp, ATEMP);
|
||||||
|
}
|
||||||
|
|
||||||
|
Xinit(xs, xp, strlen(ip = ipath) + 1, ATEMP);
|
||||||
|
|
||||||
|
while (*ip) {
|
||||||
|
/* skip slashes in input */
|
||||||
|
while (*ip == '/')
|
||||||
|
++ip;
|
||||||
|
if (!*ip)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* get next pathname component from input */
|
||||||
|
tp = ip;
|
||||||
|
while (*ip && *ip != '/')
|
||||||
|
++ip;
|
||||||
|
len = ip - tp;
|
||||||
|
|
||||||
|
/* check input for "." and ".." */
|
||||||
|
if (tp[0] == '.') {
|
||||||
|
if (len == 1)
|
||||||
|
/* just continue with the next one */
|
||||||
|
continue;
|
||||||
|
else if (len == 2 && tp[1] == '.') {
|
||||||
|
/* strip off last pathname component */
|
||||||
|
while (xp > Xstring(xs, xp))
|
||||||
|
if (*--xp == '/')
|
||||||
|
break;
|
||||||
|
/* then continue with the next one */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store output position away, then append slash to output */
|
||||||
|
pos = Xsavepos(xs, xp);
|
||||||
|
Xcheck(xs, xp);
|
||||||
|
Xput(xs, xp, '/');
|
||||||
|
|
||||||
|
/* append next pathname component to output */
|
||||||
|
XcheckN(xs, xp, len + 1);
|
||||||
|
memcpy(xp, tp, len);
|
||||||
|
xp += len;
|
||||||
|
*xp = '\0';
|
||||||
|
|
||||||
|
/* lstat the current output, see if it's a symlink */
|
||||||
|
if (lstat(Xstring(xs, xp), &sb)) {
|
||||||
|
/* lstat failed */
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
/* because the pathname does not exist */
|
||||||
|
while (*ip == '/')
|
||||||
|
/* skip any trailing slashes */
|
||||||
|
++ip;
|
||||||
|
/* no more components left? */
|
||||||
|
if (!*ip)
|
||||||
|
/* we can still return successfully */
|
||||||
|
break;
|
||||||
|
/* more components left? fall through */
|
||||||
|
}
|
||||||
|
/* not ENOENT or not at the end of ipath */
|
||||||
|
goto notfound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if we encountered a symlink? */
|
||||||
|
if (S_ISLNK(sb.st_mode)) {
|
||||||
|
/* reached maximum recursion depth? */
|
||||||
|
if (!symlinks--) {
|
||||||
|
/* yep, prevent infinite loops */
|
||||||
|
errno = ELOOP;
|
||||||
|
goto notfound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get symlink(7) target */
|
||||||
|
if (!ldest)
|
||||||
|
ldest = alloc(PATH_MAX + 1, ATEMP);
|
||||||
|
if ((llen = readlink(Xstring(xs, xp), ldest,
|
||||||
|
PATH_MAX)) < 0)
|
||||||
|
/* oops... */
|
||||||
|
goto notfound;
|
||||||
|
ldest[llen] = '\0';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* restart if symlink target is an absolute path,
|
||||||
|
* otherwise continue with currently resolved prefix
|
||||||
|
*/
|
||||||
|
xp = (ldest[0] == '/') ? Xstring(xs, xp) :
|
||||||
|
Xrestpos(xs, xp, pos);
|
||||||
|
tp = shf_smprintf("%s/%s", ldest, ip);
|
||||||
|
afree(ipath, ATEMP);
|
||||||
|
ip = ipath = tp;
|
||||||
|
}
|
||||||
|
/* otherwise (no symlink) merely go on */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* either found the target and successfully resolved it,
|
||||||
|
* or found its parent directory and may create it
|
||||||
|
*/
|
||||||
|
if (Xlength(xs, xp) == 0)
|
||||||
|
/*
|
||||||
|
* if the resolved pathname is "", make it "/",
|
||||||
|
* otherwise do not add a trailing slash
|
||||||
|
*/
|
||||||
|
Xput(xs, xp, '/');
|
||||||
|
Xput(xs, xp, '\0');
|
||||||
|
|
||||||
|
if (ldest != NULL)
|
||||||
|
afree(ldest, ATEMP);
|
||||||
|
afree(ipath, ATEMP);
|
||||||
|
return (Xclose(xs, xp));
|
||||||
|
|
||||||
|
notfound:
|
||||||
|
llen = errno; /* save; free(3) might trash it */
|
||||||
|
if (ldest != NULL)
|
||||||
|
afree(ldest, ATEMP);
|
||||||
|
afree(ipath, ATEMP);
|
||||||
|
Xfree(xs, xp);
|
||||||
|
errno = llen;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
c_cd(const char **wp)
|
c_cd(const char **wp)
|
||||||
@ -3124,11 +3262,11 @@ c_rename(const char **wp)
|
|||||||
return (rv);
|
return (rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_REALPATH
|
|
||||||
int
|
int
|
||||||
c_realpath(const char **wp)
|
c_realpath(const char **wp)
|
||||||
{
|
{
|
||||||
int rv = 1;
|
int rv = 1;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
if (wp != NULL && wp[0] != NULL && wp[1] != NULL) {
|
if (wp != NULL && wp[0] != NULL && wp[1] != NULL) {
|
||||||
if (strcmp(wp[1], "--")) {
|
if (strcmp(wp[1], "--")) {
|
||||||
@ -3146,17 +3284,15 @@ c_realpath(const char **wp)
|
|||||||
|
|
||||||
if (rv)
|
if (rv)
|
||||||
bi_errorf(T_synerr);
|
bi_errorf(T_synerr);
|
||||||
else {
|
else if ((buf = do_realpath(*wp)) == NULL) {
|
||||||
char *buf;
|
rv = errno;
|
||||||
|
bi_errorf("%s: %s", *wp, strerror(rv));
|
||||||
if (realpath(*wp, (buf = alloc(PATH_MAX, ATEMP))) == NULL) {
|
if ((unsigned int)rv > 255)
|
||||||
rv = errno;
|
rv = 255;
|
||||||
bi_errorf("%s: %s", *wp, strerror(rv));
|
} else {
|
||||||
} else
|
shprintf("%s\n", buf);
|
||||||
shprintf("%s\n", buf);
|
|
||||||
afree(buf, ATEMP);
|
afree(buf, ATEMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (rv);
|
return (rv);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
4
sh.h
4
sh.h
@ -134,7 +134,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EXTERN
|
#ifdef EXTERN
|
||||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.334 2009/08/28 22:46:21 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.335 2009/08/30 13:22:39 tg Exp $");
|
||||||
#endif
|
#endif
|
||||||
#define MKSH_VERSION "R39 2009/08/28"
|
#define MKSH_VERSION "R39 2009/08/28"
|
||||||
|
|
||||||
@ -1434,9 +1434,7 @@ int c_test(const char **);
|
|||||||
#if HAVE_MKNOD
|
#if HAVE_MKNOD
|
||||||
int c_mknod(const char **);
|
int c_mknod(const char **);
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_REALPATH
|
|
||||||
int c_realpath(const char **);
|
int c_realpath(const char **);
|
||||||
#endif
|
|
||||||
int c_rename(const char **);
|
int c_rename(const char **);
|
||||||
/* histrap.c */
|
/* histrap.c */
|
||||||
void init_histvec(void);
|
void init_histvec(void);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user