Index: sys/compat/common/compat_util.c =================================================================== RCS file: /space/netbsd/NetBSD-cvs/src/sys/compat/common/compat_util.c,v retrieving revision 1.29 diff -u -r1.29 compat_util.c --- sys/compat/common/compat_util.c 29 May 2005 22:08:16 -0000 1.29 +++ sys/compat/common/compat_util.c 1 Sep 2005 19:42:30 -0000 @@ -55,6 +55,8 @@ #include +#include + #include /* @@ -318,3 +320,64 @@ msg, mp->mnt_stat.f_mntonname, mp->mnt_stat.f_mntfromname); uprintf("%s: dir offset too large for emulated program\n", msg); } + +int +emul_sys___getcwd(struct lwp *l, void *v, register_t *retval) +{ + struct sys___getcwd_args /* { + syscallarg(char *) bufp; + syscallarg(size_t) length; + } */ *uap = v; + + struct proc *p = l->l_proc; + struct nameidata nd; + char *bufp; + int emul_path_len, bufp_len; + int length = SCARG(uap, length); + int error = sys___getcwd(l, v, retval); + + if (error) + return error; + + bufp = malloc(length, M_TEMP, M_WAITOK); + + error = copyin(SCARG(uap, bufp), bufp, length); + if (error) + { + free(bufp, M_TEMP); + return error; + } + + NDINIT(&nd, LOOKUP, FOLLOW|SAVENAME, UIO_SYSSPACE, + p->p_emul->e_path, p); + if ((error = namei(&nd)) != 0) + { + free(bufp, M_TEMP); + return error; + } + + // Can't use strlen: might not be null terminated! + emul_path_len = nd.ni_cnd.cn_namelen + + (nd.ni_cnd.cn_nameptr - nd.ni_cnd.cn_pnbuf); + bufp_len = strlen(bufp); + + if (strncmp(bufp, nd.ni_cnd.cn_pnbuf, emul_path_len) == 0) + { + if (bufp_len == emul_path_len || + (bufp[emul_path_len] == '/' && + bufp_len == emul_path_len + 1)) + { + error = copyout("/", SCARG(uap, bufp), 2); + } + else if (bufp[emul_path_len] == '/') + { + int newlen = bufp_len - emul_path_len; + memmove(bufp, bufp + emul_path_len, newlen + 1); + error = copyout(bufp, SCARG(uap, bufp), newlen + 1); + } + } + + PNBUF_PUT(nd.ni_cnd.cn_pnbuf); + free(bufp, M_TEMP); + return error; +} Index: sys/compat/common/compat_util.h =================================================================== RCS file: /space/netbsd/NetBSD-cvs/src/sys/compat/common/compat_util.h,v retrieving revision 1.15 diff -u -r1.15 compat_util.h --- sys/compat/common/compat_util.h 29 May 2005 22:08:16 -0000 1.15 +++ sys/compat/common/compat_util.h 1 Sep 2005 16:51:52 -0000 @@ -89,6 +89,8 @@ void compat_offseterr(struct vnode *, const char *); +int emul_sys___getcwd(struct lwp *l, void *v, register_t *retval); + #define CHECK_ALT_FL_EXISTS 0 #define CHECK_ALT_FL_CREAT 1 #define CHECK_ALT_FL_SYMLINK 2 Index: sys/compat/linux/arch/i386/linux_syscall.h =================================================================== RCS file: /space/netbsd/NetBSD-cvs/src/sys/compat/linux/arch/i386/linux_syscall.h,v retrieving revision 1.57 diff -u -r1.57 linux_syscall.h --- sys/compat/linux/arch/i386/linux_syscall.h 16 May 2005 21:18:19 -0000 1.57 +++ sys/compat/linux/arch/i386/linux_syscall.h 1 Sep 2005 17:54:19 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_syscall.h,v 1.57 2005/05/16 21:18:19 fvdl Exp $ */ +/* $NetBSD$ */ /* * System call numbers. Index: sys/compat/linux/arch/i386/linux_syscallargs.h =================================================================== RCS file: /space/netbsd/NetBSD-cvs/src/sys/compat/linux/arch/i386/linux_syscallargs.h,v retrieving revision 1.57 diff -u -r1.57 linux_syscallargs.h --- sys/compat/linux/arch/i386/linux_syscallargs.h 16 May 2005 21:18:19 -0000 1.57 +++ sys/compat/linux/arch/i386/linux_syscallargs.h 1 Sep 2005 17:54:19 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_syscallargs.h,v 1.57 2005/05/16 21:18:19 fvdl Exp $ */ +/* $NetBSD$ */ /* * System call argument lists. @@ -528,6 +528,11 @@ syscallarg(int) gid; }; +struct emul_sys___getcwd_args { + syscallarg(char *) bufp; + syscallarg(size_t) length; +}; + struct linux_sys_sigaltstack_args { syscallarg(const struct linux_sigaltstack *) ss; syscallarg(struct linux_sigaltstack *) oss; @@ -1037,7 +1042,7 @@ int linux_sys_chown16(struct lwp *, void *, register_t *); -int sys___getcwd(struct lwp *, void *, register_t *); +int emul_sys___getcwd(struct lwp *, void *, register_t *); int linux_sys_sigaltstack(struct lwp *, void *, register_t *); Index: sys/compat/linux/arch/i386/linux_sysent.c =================================================================== RCS file: /space/netbsd/NetBSD-cvs/src/sys/compat/linux/arch/i386/linux_sysent.c,v retrieving revision 1.57 diff -u -r1.57 linux_sysent.c --- sys/compat/linux/arch/i386/linux_sysent.c 16 May 2005 21:18:19 -0000 1.57 +++ sys/compat/linux/arch/i386/linux_sysent.c 1 Sep 2005 17:54:19 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_sysent.c,v 1.57 2005/05/16 21:18:19 fvdl Exp $ */ +/* $NetBSD$ */ /* * System call switch table. @@ -8,7 +8,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: linux_sysent.c,v 1.57 2005/05/16 21:18:19 fvdl Exp $"); +__KERNEL_RCSID(0, "$NetBSD$"); #if defined(_KERNEL_OPT) #include "opt_compat_43.h" @@ -396,8 +396,8 @@ linux_sys_pwrite }, /* 181 = pwrite */ { 3, s(struct linux_sys_chown16_args), 0, linux_sys_chown16 }, /* 182 = chown16 */ - { 2, s(struct sys___getcwd_args), 0, - sys___getcwd }, /* 183 = __getcwd */ + { 2, s(struct emul_sys___getcwd_args), 0, + emul_sys___getcwd }, /* 183 = __getcwd */ { 0, 0, 0, linux_sys_nosys }, /* 184 = unimplemented capget */ { 0, 0, 0, Index: sys/compat/linux/arch/i386/syscalls.master =================================================================== RCS file: /space/netbsd/NetBSD-cvs/src/sys/compat/linux/arch/i386/syscalls.master,v retrieving revision 1.73 diff -u -r1.73 syscalls.master --- sys/compat/linux/arch/i386/syscalls.master 16 May 2005 21:17:11 -0000 1.73 +++ sys/compat/linux/arch/i386/syscalls.master 1 Sep 2005 17:54:12 -0000 @@ -313,7 +313,7 @@ size_t nbyte, linux_off_t offset); } 182 STD { int linux_sys_chown16(const char *path, int uid, \ int gid); } -183 NOARGS { int sys___getcwd(char *bufp, size_t length); } +183 STD { int emul_sys___getcwd(char *bufp, size_t length); } 184 UNIMPL capget 185 UNIMPL capset 186 STD { int linux_sys_sigaltstack( \