handle drive-qualified nōn-absolute pathnames in do_realpath(), untested

the idea here is that:

- /foo/bar and a:/foo/bar are absolute
- foo/bar is relative
- a:foo/bar needs to be handled specially,
  mostly per making it into an absolute (“a:/” + getcwd(a:) + “foo/bar”)
This commit is contained in:
tg 2017-10-11 23:23:03 +00:00
parent d5a29d5e60
commit 5db583cd81
3 changed files with 79 additions and 13 deletions

35
misc.c
View File

@ -32,7 +32,7 @@
#include <grp.h>
#endif
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.283 2017/10/11 21:49:06 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.284 2017/10/11 23:23:02 tg Exp $");
#define KSH_CHVT_FLAG
#ifdef MKSH_SMALL
@ -1661,6 +1661,15 @@ do_realpath(const char *upath)
if (mksh_abspath(upath)) {
/* upath is an absolute pathname */
strdupx(ipath, upath, ATEMP);
#ifdef MKSH_DOSPATH
} else if (mksh_drvltr(upath)) {
/* upath is a drive-relative pathname */
if (!getdrvwd(&ldest, ord(*upath)))
return (NULL);
/* A:foo -> A:/cwd/foo; A: -> A:/cwd */
ipath = shf_smprintf(Tf_sss, ldest,
upath[2] ? "/" : "", upath + 2);
#endif
} else {
/* upath is a relative pathname, prepend cwd */
if ((tp = ksh_get_wd()) == NULL || !mksh_abspath(tp))
@ -1762,11 +1771,23 @@ do_realpath(const char *upath)
* restart if symlink target is an absolute path,
* otherwise continue with currently resolved prefix
*/
#ifdef MKSH_DOSPATH
assemble_symlink:
#endif
/* append rest of current input path to link target */
tp = shf_smprintf(Tf_sss, ldest, *ip ? "/" : "", ip);
afree(ipath, ATEMP);
ip = ipath = tp;
if (!mksh_abspath(ldest)) {
if (!mksh_abspath(ipath)) {
#ifdef MKSH_DOSPATH
/* symlink target might be drive-relative */
if (mksh_drvltr(ipath)) {
if (!getdrvwd(&ldest, ord(*ipath)))
goto notfound;
ip += 2;
goto assemble_symlink;
}
#endif
/* symlink target is a relative path */
xp = Xrestpos(xs, xp, pos);
} else
@ -1775,7 +1796,7 @@ do_realpath(const char *upath)
/* symlink target is an absolute path */
xp = Xstring(xs, xp);
beginning_of_a_pathname:
/* assert: mksh_cdirsep((ip == ipath)[0]) */
/* assert: mksh_abspath(ip == ipath) */
/* assert: xp == xs.beg => start of path */
/* exactly two leading slashes? (SUSv4 3.266) */
@ -1789,14 +1810,6 @@ do_realpath(const char *upath)
/* keep it */
Xput(xs, xp, *ip++);
Xput(xs, xp, *ip++);
/*
* XXX if (!mksh_cdirsep(*ip)): we
* XXX must get the cwd on that drive
* XXX and prepend it here as this is
* XXX a drive-qualified relative path
* XXX which we are supposed to convert
* XXX to an absolute (with drive) one
*/
}
#endif
}

54
os2.c
View File

@ -21,16 +21,19 @@
*/
#define INCL_DOS
#define INCL_DOSFILEMGR
#define INCL_DOSMISC
#include <os2.h>
#include "sh.h"
#include <klibc/startup.h>
#include <errno.h>
#include <io.h>
#include <unistd.h>
#include <process.h>
__RCSID("$MirOS: src/bin/mksh/os2.c,v 1.2 2017/04/29 22:04:29 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/os2.c,v 1.3 2017/10/11 23:23:03 tg Exp $");
static char *remove_trailing_dots(char *);
static int access_stat_ex(int (*)(), const char *, void *);
@ -557,3 +560,52 @@ cleanup(void)
{
cleanup_temps();
}
int
getdrvwd(char **cpp, unsigned int drvltr)
{
PBYTE *cp;
ULONG sz;
APIRET rc;
ULONG drvno;
if (DosQuerySysInfo(QSV_MAX_PATH_LENGTH, QSV_MAX_PATH_LENGTH,
&sz, sizeof(sz)) != 0) {
errno = EDOOFUS;
return (-1);
}
/* allocate 'X:/' plus sz plus NUL */
checkoktoadd((size_t)sz, (size_t)4);
cp = aresize(*cpp, (size_t)sz + (size_t)4, ATEMP);
cp[0] = drvltr;
cp[1] = ':';
cp[2] = '/';
drvno = (rtt2asc(drvltr) | 0x20U) - rtt2asc('a') + 1;
/* NUL is part of space within buffer passed */
++sz;
if ((rc = DosQueryCurrentDir(drvno, cp + 3, &sz)) == 0) {
/* success! */
*cpp = cp;
return (0);
}
afree(cp, ATEMP);
*cpp = NULL;
switch (rc) {
case 15: /* invalid drive */
errno = ENOTBLK;
break;
case 26: /* not dos disk */
errno = ENODEV;
break;
case 108: /* drive locked */
errno = EDEADLK;
break;
case 111: /* buffer overflow */
errno = ENAMETOOLONG;
break;
default:
errno = EINVAL;
}
return (-1);
}

3
sh.h
View File

@ -182,7 +182,7 @@
#endif
#ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.846 2017/10/11 21:52:46 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.847 2017/10/11 23:23:03 tg Exp $");
#endif
#define MKSH_VERSION "R56 2017/08/29"
@ -2566,6 +2566,7 @@ void setextlibpath(const char *, const char *);
int access_ex(int (*)(const char *, int), const char *, int);
int stat_ex(const char *, struct stat *);
const char *real_exec_name(const char *);
int getdrvwd(char **, unsigned int);
#endif
/* shf.c */
struct shf *shf_open(const char *, int, int, int);