diff mbox series

[02/10] bsd-user: Implement symlink, symlinkat, readlink and readlinkat

Message ID 20220620174220.22179-3-imp@bsdimp.com (mailing list archive)
State New, archived
Headers show
Series bsd-user: More file-related system calls | expand

Commit Message

Warner Losh June 20, 2022, 5:42 p.m. UTC
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           | 75 +++++++++++++++++++++++++++++++++++
 bsd-user/freebsd/os-syscall.c | 16 ++++++++
 2 files changed, 91 insertions(+)

Comments

Richard Henderson June 20, 2022, 6:28 p.m. UTC | #1
On 6/20/22 10:42, Warner Losh wrote:
> +static abi_long do_bsd_readlink(CPUArchState *env, abi_long arg1,
> +        abi_long arg2, abi_long arg3)
> +{
> +    abi_long ret;
> +    void *p1, *p2;
> +
> +    LOCK_PATH(p1, arg1);
> +    p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
> +    if (p2 == NULL) {
> +        UNLOCK_PATH(p1, arg1);
> +        return -TARGET_EFAULT;
> +    }
> +#ifdef __FreeBSD__
> +    if (strcmp(p1, "/proc/curproc/file") == 0) {
> +        CPUState *cpu = env_cpu(env);
> +        TaskState *ts = (TaskState *)cpu->opaque;
> +        strncpy(p2, ts->bprm->fullpath, arg3);
> +        ret = MIN((abi_long)strlen(ts->bprm->fullpath), arg3);
> +    } else
> +#endif

Unfortunate ifdef.  Do we really need it while the other bsds are presumably still 
non-functional?  I see that HOST_DEFAULT_BSD_TYPE isn't hooked up either...


r~
Warner Losh June 20, 2022, 8:17 p.m. UTC | #2
On Mon, Jun 20, 2022 at 12:28 PM Richard Henderson <
richard.henderson@linaro.org> wrote:

> On 6/20/22 10:42, Warner Losh wrote:
> > +static abi_long do_bsd_readlink(CPUArchState *env, abi_long arg1,
> > +        abi_long arg2, abi_long arg3)
> > +{
> > +    abi_long ret;
> > +    void *p1, *p2;
> > +
> > +    LOCK_PATH(p1, arg1);
> > +    p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
> > +    if (p2 == NULL) {
> > +        UNLOCK_PATH(p1, arg1);
> > +        return -TARGET_EFAULT;
> > +    }
> > +#ifdef __FreeBSD__
> > +    if (strcmp(p1, "/proc/curproc/file") == 0) {
> > +        CPUState *cpu = env_cpu(env);
> > +        TaskState *ts = (TaskState *)cpu->opaque;
> > +        strncpy(p2, ts->bprm->fullpath, arg3);
> > +        ret = MIN((abi_long)strlen(ts->bprm->fullpath), arg3);
> > +    } else
> > +#endif
>
> Unfortunate ifdef.  Do we really need it while the other bsds are
> presumably still
> non-functional?  I see that HOST_DEFAULT_BSD_TYPE isn't hooked up either...
>

I can remove the ifdef for now and add it to the TODO file as something to
check
when we try to support NetBSD/OpenBSD again.

Warner
diff mbox series

Patch

diff --git a/bsd-user/bsd-file.h b/bsd-user/bsd-file.h
index 4545df3a056..e5133268546 100644
--- a/bsd-user/bsd-file.h
+++ b/bsd-user/bsd-file.h
@@ -601,4 +601,79 @@  static abi_long do_bsd_nmount(abi_long arg1, abi_long count,
     return ret;
 }
 
+/* symlink(2) */
+static abi_long do_bsd_symlink(abi_long arg1, abi_long arg2)
+{
+    abi_long ret;
+    void *p1, *p2;
+
+    LOCK_PATH2(p1, arg1, p2, arg2);
+    ret = get_errno(symlink(p1, p2)); /* XXX path(p1), path(p2) */
+    UNLOCK_PATH2(p1, arg1, p2, arg2);
+
+    return ret;
+}
+
+/* symlinkat(2) */
+static abi_long do_bsd_symlinkat(abi_long arg1, abi_long arg2,
+        abi_long arg3)
+{
+    abi_long ret;
+    void *p1, *p2;
+
+    LOCK_PATH2(p1, arg1, p2, arg3);
+    ret = get_errno(symlinkat(p1, arg2, p2)); /* XXX path(p1), path(p2) */
+    UNLOCK_PATH2(p1, arg1, p2, arg3);
+
+    return ret;
+}
+
+/* readlink(2) */
+static abi_long do_bsd_readlink(CPUArchState *env, abi_long arg1,
+        abi_long arg2, abi_long arg3)
+{
+    abi_long ret;
+    void *p1, *p2;
+
+    LOCK_PATH(p1, arg1);
+    p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
+    if (p2 == NULL) {
+        UNLOCK_PATH(p1, arg1);
+        return -TARGET_EFAULT;
+    }
+#ifdef __FreeBSD__
+    if (strcmp(p1, "/proc/curproc/file") == 0) {
+        CPUState *cpu = env_cpu(env);
+        TaskState *ts = (TaskState *)cpu->opaque;
+        strncpy(p2, ts->bprm->fullpath, arg3);
+        ret = MIN((abi_long)strlen(ts->bprm->fullpath), arg3);
+    } else
+#endif
+    ret = get_errno(readlink(path(p1), p2, arg3));
+    unlock_user(p2, arg2, ret);
+    UNLOCK_PATH(p1, arg1);
+
+    return ret;
+}
+
+/* readlinkat(2) */
+static abi_long do_bsd_readlinkat(abi_long arg1, abi_long arg2,
+        abi_long arg3, abi_long arg4)
+{
+    abi_long ret;
+    void *p1, *p2;
+
+    LOCK_PATH(p1, arg2);
+    p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
+    if (p2 == NULL) {
+        UNLOCK_PATH(p1, arg2);
+        return -TARGET_EFAULT;
+    }
+    ret = get_errno(readlinkat(arg1, p1, p2, arg4));
+    unlock_user(p2, arg3, ret);
+    UNLOCK_PATH(p1, arg2);
+
+    return ret;
+}
+
 #endif /* BSD_FILE_H */
diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c
index bd4dfa6ddc7..80ec9dd4954 100644
--- a/bsd-user/freebsd/os-syscall.c
+++ b/bsd-user/freebsd/os-syscall.c
@@ -386,6 +386,22 @@  static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1,
         ret = do_bsd_nmount(arg1, arg2, arg3);
         break;
 
+    case TARGET_FREEBSD_NR_symlink: /* symlink(2) */
+        ret = do_bsd_symlink(arg1, arg2);
+        break;
+
+    case TARGET_FREEBSD_NR_symlinkat: /* symlinkat(2) */
+        ret = do_bsd_symlinkat(arg1, arg2, arg3);
+        break;
+
+    case TARGET_FREEBSD_NR_readlink: /* readlink(2) */
+        ret = do_bsd_readlink(cpu_env, arg1, arg2, arg3);
+        break;
+
+    case TARGET_FREEBSD_NR_readlinkat: /* readlinkat(2) */
+        ret = do_bsd_readlinkat(arg1, arg2, arg3, arg4);
+        break;
+
     default:
         qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
         ret = -TARGET_ENOSYS;