diff mbox series

[08/11] bsd-user: Implement rmdir and undocumented -_getcwd

Message ID 20220612204851.19914-9-imp@bsdimp.com (mailing list archive)
State New, archived
Headers show
Series bsd-user: Next round of syscalls | expand

Commit Message

Warner Losh June 12, 2022, 8:48 p.m. UTC
Implemenet rmdir and __getcwd. Declare __getcwd as extern because
there's no installed FreeBSD header that has it. It's used internally by
libc, which doesn't provide an external declaration, but does export the
symbol.

Signed-off-by: Stacey Son <sson@FreeBSD.org>
Signed-off-by: Jung-uk Kim <jkim@FreeBSD.org>
Signed-off-by: Warner Losh <imp@bsdimp.com>
---
 bsd-user/bsd-file.h           | 30 ++++++++++++++++++++++++++++++
 bsd-user/freebsd/os-syscall.c |  8 ++++++++
 2 files changed, 38 insertions(+)

Comments

Richard Henderson June 13, 2022, 7:52 p.m. UTC | #1
On 6/12/22 13:48, Warner Losh wrote:
> Implemenet rmdir and __getcwd. Declare __getcwd as extern because
> there's no installed FreeBSD header that has it. It's used internally by
> libc, which doesn't provide an external declaration, but does export the
> symbol.

Typo in subject: s/-/_/.

> @@ -55,6 +55,7 @@ extern struct iovec *lock_iovec(int type, abi_ulong target_addr, int count,
>           int copy);
>   extern void unlock_iovec(struct iovec *vec, abi_ulong target_addr, int count,
>           int copy);
> +extern int __getcwd(char *path, size_t len);

Do you really want to rely on this export?
Unless it does something special, I'd just declare a local version of the syscall as you 
do with safe_*.

> +/* undocumented __getcwd(char *buf, size_t len)  system call */

Surely the syscall itself is documented?


r~
Warner Losh June 13, 2022, 11:45 p.m. UTC | #2
On Mon, Jun 13, 2022 at 1:52 PM Richard Henderson <
richard.henderson@linaro.org> wrote:

> On 6/12/22 13:48, Warner Losh wrote:
> > Implemenet rmdir and __getcwd. Declare __getcwd as extern because
> > there's no installed FreeBSD header that has it. It's used internally by
> > libc, which doesn't provide an external declaration, but does export the
> > symbol.
>
> Typo in subject: s/-/_/.
>

Indeed.


> > @@ -55,6 +55,7 @@ extern struct iovec *lock_iovec(int type, abi_ulong
> target_addr, int count,
> >           int copy);
> >   extern void unlock_iovec(struct iovec *vec, abi_ulong target_addr, int
> count,
> >           int copy);
> > +extern int __getcwd(char *path, size_t len);
>
> Do you really want to rely on this export?
> Unless it does something special, I'd just declare a local version of the
> syscall as you
> do with safe_*.
>

Indeed not. I was just copying what we've been running, but I see now that
was unwise.
I'll do a safe_syscall directly here since we don't need to call it
anywhere else. I'll do a
sanity check on our upstream and make sure I can still run my favorite
shells, which
I believe use this call.


> > +/* undocumented __getcwd(char *buf, size_t len)  system call */
>
> Surely the syscall itself is documented?
>

One would think it was documented, but there's no man page for it and the
getcwd()
call has some extensions that it implements, plus there's some weird
special cases
that __getcwd() can sometimes return that getcwd() knows how to unwind (the
oddest being that sometimes paths are returned backwards). All these quirks
are not,
alas, documented in any place except the code. Hence the characterization
that this
is undocumented :)... I was rather surprised by this when I went looking.

Warner
diff mbox series

Patch

diff --git a/bsd-user/bsd-file.h b/bsd-user/bsd-file.h
index 35036364ad8..500d6ba78b9 100644
--- a/bsd-user/bsd-file.h
+++ b/bsd-user/bsd-file.h
@@ -55,6 +55,7 @@  extern struct iovec *lock_iovec(int type, abi_ulong target_addr, int count,
         int copy);
 extern void unlock_iovec(struct iovec *vec, abi_ulong target_addr, int count,
         int copy);
+extern int __getcwd(char *path, size_t len);
 
 int safe_open(const char *path, int flags, mode_t mode);
 int safe_openat(int fd, const char *path, int flags, mode_t mode);
@@ -461,4 +462,33 @@  static abi_long do_bsd_mkdirat(abi_long arg1, abi_long arg2,
     return ret;
 }
 
+/* rmdir(2) */
+static abi_long do_bsd_rmdir(abi_long arg1)
+{
+    abi_long ret;
+    void *p;
+
+    LOCK_PATH(p, arg1);
+    ret = get_errno(rmdir(p)); /* XXX path(p)? */
+    UNLOCK_PATH(p, arg1);
+
+    return ret;
+}
+
+/* undocumented __getcwd(char *buf, size_t len)  system call */
+static abi_long do_bsd___getcwd(abi_long arg1, abi_long arg2)
+{
+    abi_long ret;
+    void *p;
+
+    p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
+    if (p == NULL) {
+        return -TARGET_EFAULT;
+    }
+    ret = __getcwd(p, arg2);
+    unlock_user(p, arg1, ret == 0 ? strlen(p) + 1 : 0);
+
+    return get_errno(ret);
+}
+
 #endif /* BSD_FILE_H */
diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c
index 9381ddb5be1..e28a566d6c3 100644
--- a/bsd-user/freebsd/os-syscall.c
+++ b/bsd-user/freebsd/os-syscall.c
@@ -341,6 +341,14 @@  static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1,
         ret = do_bsd_mkdirat(arg1, arg2, arg3);
         break;
 
+    case TARGET_FREEBSD_NR_rmdir: /* rmdir(2) (XXX no rmdirat()?) */
+        ret = do_bsd_rmdir(arg1);
+        break;
+
+    case TARGET_FREEBSD_NR___getcwd: /* undocumented __getcwd() */
+        ret = do_bsd___getcwd(arg1, arg2);
+        break;
+
     default:
         qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
         ret = -TARGET_ENOSYS;