Message ID | 20160914202008.14119-5-aleksandar.markovic@rt-rk.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Le 14/09/2016 à 22:19, Aleksandar Markovic a écrit : > From: Aleksandar Markovic <aleksandar.markovic@imgtec.com> > > This patch implements Qemu user mode ustat() syscall support. > > Syscall ustat() returns information about a mounted filesystem. > > The implementation is similar to the implementations of statfs(), > fstatfs() and other related syscalls. It is based on invocation of > host's ustat(), and its key part is in the correspondent case segment > of the main switch statement of the function do_syscall(), in file > linux-user/syscalls.c. All necessary conversions of data structures > from target to host and from host to target are covered. Sufficient > support for "-strace" option for this syscall is already present, > and this patch does not change it. > > This patch also fixes failures of LTP tests ustat01, and ustat02, if > executed on Qemu-emulated systems. > > Signed-off-by: Aleksandar Markovic <aleksandar.markovic@imgtec.com> > --- > linux-user/syscall.c | 25 ++++++++++++++++++++++++- > 1 file changed, 24 insertions(+), 1 deletion(-) > > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > index 3436ee6..7f8ae41 100644 > --- a/linux-user/syscall.c > +++ b/linux-user/syscall.c > @@ -48,6 +48,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base, > #include <sys/shm.h> > #include <sys/sem.h> > #include <sys/statfs.h> > +#include <ustat.h> > #include <utime.h> > #include <sys/sysinfo.h> > #include <sys/signalfd.h> > @@ -8098,7 +8099,29 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, > break; > #ifdef TARGET_NR_ustat > case TARGET_NR_ustat: > - goto unimplemented; > + { > + struct ustat ust; > + int cnt; > + ret = get_errno(ustat(arg1, &ust)); > + > + if (!is_error(ret)) { > + struct ustat *target_ust; You must define your own "struct target_ustat" as __kernel_daddr_t and __kernel_ino_t are long (or int). > + > + if (!lock_user_struct(VERIFY_WRITE, target_ust, arg2, 0)) { > + goto efault; > + } > + > + __put_user(ust.f_tfree, &target_ust->f_tfree); > + __put_user(ust.f_tinode, &target_ust->f_tinode); > + > + for (cnt = 0; cnt < 6; cnt++) { > + __put_user(ust.f_fname[cnt], &target_ust->f_fname[cnt]); > + __put_user(ust.f_fpack[cnt], &target_ust->f_fpack[cnt]); > + } As the structure is locked and they are "char", you can do memcpy(). > + unlock_user_struct(target_ust, arg2, 1); > + } > + break; > + } > #endif > #ifdef TARGET_NR_dup2 > case TARGET_NR_dup2: > Laurent
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 3436ee6..7f8ae41 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -48,6 +48,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include <sys/shm.h> #include <sys/sem.h> #include <sys/statfs.h> +#include <ustat.h> #include <utime.h> #include <sys/sysinfo.h> #include <sys/signalfd.h> @@ -8098,7 +8099,29 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #ifdef TARGET_NR_ustat case TARGET_NR_ustat: - goto unimplemented; + { + struct ustat ust; + int cnt; + ret = get_errno(ustat(arg1, &ust)); + + if (!is_error(ret)) { + struct ustat *target_ust; + + if (!lock_user_struct(VERIFY_WRITE, target_ust, arg2, 0)) { + goto efault; + } + + __put_user(ust.f_tfree, &target_ust->f_tfree); + __put_user(ust.f_tinode, &target_ust->f_tinode); + + for (cnt = 0; cnt < 6; cnt++) { + __put_user(ust.f_fname[cnt], &target_ust->f_fname[cnt]); + __put_user(ust.f_fpack[cnt], &target_ust->f_fpack[cnt]); + } + unlock_user_struct(target_ust, arg2, 1); + } + break; + } #endif #ifdef TARGET_NR_dup2 case TARGET_NR_dup2: