[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 060/108] linux-user: Split out getdents, getdents
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PATCH v2 060/108] linux-user: Split out getdents, getdents64 |
Date: |
Sat, 9 Jun 2018 17:01:32 -1000 |
Signed-off-by: Richard Henderson <address@hidden>
---
linux-user/syscall.c | 329 ++++++++++++++++++++++---------------------
1 file changed, 170 insertions(+), 159 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f5f21658a8..600702ea3e 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8121,6 +8121,170 @@ IMPL(futimesat)
}
#endif
+#ifdef TARGET_NR_getdents
+IMPL(getdents)
+{
+ abi_long ret;
+# ifdef EMULATE_GETDENTS_WITH_GETDENTS
+# if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
+ struct target_dirent *target_dirp;
+ struct linux_dirent *dirp;
+ abi_long count = arg3;
+
+ dirp = g_try_malloc(count);
+ if (!dirp) {
+ return -TARGET_ENOMEM;
+ }
+
+ ret = get_errno(sys_getdents(arg1, dirp, count));
+ if (!is_error(ret)) {
+ struct linux_dirent *de;
+ struct target_dirent *tde;
+ int len = ret;
+ int reclen, treclen;
+ int count1, tnamelen;
+
+ count1 = 0;
+ de = dirp;
+ target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
+ if (!target_dirp) {
+ return -TARGET_EFAULT;
+ }
+ tde = target_dirp;
+ while (len > 0) {
+ reclen = de->d_reclen;
+ tnamelen = reclen - offsetof(struct linux_dirent, d_name);
+ assert(tnamelen >= 0);
+ treclen = tnamelen + offsetof(struct target_dirent, d_name);
+ assert(count1 + treclen <= count);
+ tde->d_reclen = tswap16(treclen);
+ tde->d_ino = tswapal(de->d_ino);
+ tde->d_off = tswapal(de->d_off);
+ memcpy(tde->d_name, de->d_name, tnamelen);
+ de = (struct linux_dirent *)((char *)de + reclen);
+ len -= reclen;
+ tde = (struct target_dirent *)((char *)tde + treclen);
+ count1 += treclen;
+ }
+ ret = count1;
+ unlock_user(target_dirp, arg2, ret);
+ }
+ g_free(dirp);
+# else
+ struct linux_dirent *dirp;
+ abi_long count = arg3;
+
+ dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
+ if (!dirp) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(sys_getdents(arg1, dirp, count));
+ if (!is_error(ret)) {
+ struct linux_dirent *de = dirp;
+ int len = ret;
+ int reclen;
+
+ while (len > 0) {
+ reclen = de->d_reclen;
+ if (reclen > len) {
+ break;
+ }
+ de->d_reclen = tswap16(reclen);
+ tswapls(&de->d_ino);
+ tswapls(&de->d_off);
+ de = (struct linux_dirent *)((char *)de + reclen);
+ len -= reclen;
+ }
+ }
+ unlock_user(dirp, arg2, ret);
+# endif
+# else
+ /* Implement getdents in terms of getdents64 */
+ struct linux_dirent64 *dirp;
+ abi_long count = arg3;
+
+ dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
+ if (!dirp) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(sys_getdents64(arg1, dirp, count));
+ if (!is_error(ret)) {
+ /* Convert the dirent64 structs to target dirent. We do this
+ * in-place, since we can guarantee that a target_dirent is no
+ * larger than a dirent64; however this means we have to be
+ * careful to read everything before writing in the new format.
+ */
+ struct linux_dirent64 *de = dirp;
+ struct target_dirent *tde = (struct target_dirent *)dirp;
+ int len = ret;
+ int tlen = 0;
+
+ while (len > 0) {
+ int namelen, treclen;
+ int reclen = de->d_reclen;
+ uint64_t ino = de->d_ino;
+ int64_t off = de->d_off;
+ uint8_t type = de->d_type;
+
+ namelen = strlen(de->d_name);
+ treclen = offsetof(struct target_dirent, d_name) + namelen + 2;
+ treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long));
+
+ memmove(tde->d_name, de->d_name, namelen + 1);
+ tde->d_ino = tswapal(ino);
+ tde->d_off = tswapal(off);
+ tde->d_reclen = tswap16(treclen);
+ /* The target_dirent type is in what was formerly a padding
+ * byte at the end of the structure:
+ */
+ *(((char *)tde) + treclen - 1) = type;
+
+ de = (struct linux_dirent64 *)((char *)de + reclen);
+ tde = (struct target_dirent *)((char *)tde + treclen);
+ len -= reclen;
+ tlen += treclen;
+ }
+ ret = tlen;
+ }
+ unlock_user(dirp, arg2, ret);
+# endif
+ return ret;
+}
+#endif
+
+#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
+IMPL(getdents64)
+{
+ struct linux_dirent64 *dirp;
+ abi_long count = arg3;
+ abi_long ret;
+
+ dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
+ if (!dirp) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(sys_getdents64(arg1, dirp, count));
+ if (!is_error(ret)) {
+ struct linux_dirent64 *de = dirp;
+ int len = ret;
+
+ while (len > 0) {
+ int reclen = de->d_reclen;
+ if (reclen > len) {
+ break;
+ }
+ de->d_reclen = tswap16(reclen);
+ tswap64s((uint64_t *)&de->d_ino);
+ tswap64s((uint64_t *)&de->d_off);
+ de = (struct linux_dirent64 *)((char *)de + reclen);
+ len -= reclen;
+ }
+ }
+ unlock_user(dirp, arg2, ret);
+ return ret;
+}
+#endif /* TARGET_NR_getdents64 */
+
IMPL(getitimer)
{
struct itimerval value;
@@ -10485,165 +10649,6 @@ static abi_long do_syscall1(void *cpu_env, unsigned
num, abi_long arg1,
void *p;
switch(num) {
-#ifdef TARGET_NR_getdents
- case TARGET_NR_getdents:
-#ifdef EMULATE_GETDENTS_WITH_GETDENTS
-#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
- {
- struct target_dirent *target_dirp;
- struct linux_dirent *dirp;
- abi_long count = arg3;
-
- dirp = g_try_malloc(count);
- if (!dirp) {
- return -TARGET_ENOMEM;
- }
-
- ret = get_errno(sys_getdents(arg1, dirp, count));
- if (!is_error(ret)) {
- struct linux_dirent *de;
- struct target_dirent *tde;
- int len = ret;
- int reclen, treclen;
- int count1, tnamelen;
-
- count1 = 0;
- de = dirp;
- if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
- return -TARGET_EFAULT;
- tde = target_dirp;
- while (len > 0) {
- reclen = de->d_reclen;
- tnamelen = reclen - offsetof(struct linux_dirent, d_name);
- assert(tnamelen >= 0);
- treclen = tnamelen + offsetof(struct target_dirent,
d_name);
- assert(count1 + treclen <= count);
- tde->d_reclen = tswap16(treclen);
- tde->d_ino = tswapal(de->d_ino);
- tde->d_off = tswapal(de->d_off);
- memcpy(tde->d_name, de->d_name, tnamelen);
- de = (struct linux_dirent *)((char *)de + reclen);
- len -= reclen;
- tde = (struct target_dirent *)((char *)tde + treclen);
- count1 += treclen;
- }
- ret = count1;
- unlock_user(target_dirp, arg2, ret);
- }
- g_free(dirp);
- }
-#else
- {
- struct linux_dirent *dirp;
- abi_long count = arg3;
-
- if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
- return -TARGET_EFAULT;
- ret = get_errno(sys_getdents(arg1, dirp, count));
- if (!is_error(ret)) {
- struct linux_dirent *de;
- int len = ret;
- int reclen;
- de = dirp;
- while (len > 0) {
- reclen = de->d_reclen;
- if (reclen > len)
- break;
- de->d_reclen = tswap16(reclen);
- tswapls(&de->d_ino);
- tswapls(&de->d_off);
- de = (struct linux_dirent *)((char *)de + reclen);
- len -= reclen;
- }
- }
- unlock_user(dirp, arg2, ret);
- }
-#endif
-#else
- /* Implement getdents in terms of getdents64 */
- {
- struct linux_dirent64 *dirp;
- abi_long count = arg3;
-
- dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
- if (!dirp) {
- return -TARGET_EFAULT;
- }
- ret = get_errno(sys_getdents64(arg1, dirp, count));
- if (!is_error(ret)) {
- /* Convert the dirent64 structs to target dirent. We do this
- * in-place, since we can guarantee that a target_dirent is no
- * larger than a dirent64; however this means we have to be
- * careful to read everything before writing in the new format.
- */
- struct linux_dirent64 *de;
- struct target_dirent *tde;
- int len = ret;
- int tlen = 0;
-
- de = dirp;
- tde = (struct target_dirent *)dirp;
- while (len > 0) {
- int namelen, treclen;
- int reclen = de->d_reclen;
- uint64_t ino = de->d_ino;
- int64_t off = de->d_off;
- uint8_t type = de->d_type;
-
- namelen = strlen(de->d_name);
- treclen = offsetof(struct target_dirent, d_name)
- + namelen + 2;
- treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long));
-
- memmove(tde->d_name, de->d_name, namelen + 1);
- tde->d_ino = tswapal(ino);
- tde->d_off = tswapal(off);
- tde->d_reclen = tswap16(treclen);
- /* The target_dirent type is in what was formerly a padding
- * byte at the end of the structure:
- */
- *(((char *)tde) + treclen - 1) = type;
-
- de = (struct linux_dirent64 *)((char *)de + reclen);
- tde = (struct target_dirent *)((char *)tde + treclen);
- len -= reclen;
- tlen += treclen;
- }
- ret = tlen;
- }
- unlock_user(dirp, arg2, ret);
- }
-#endif
- return ret;
-#endif /* TARGET_NR_getdents */
-#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
- case TARGET_NR_getdents64:
- {
- struct linux_dirent64 *dirp;
- abi_long count = arg3;
- if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
- return -TARGET_EFAULT;
- ret = get_errno(sys_getdents64(arg1, dirp, count));
- if (!is_error(ret)) {
- struct linux_dirent64 *de;
- int len = ret;
- int reclen;
- de = dirp;
- while (len > 0) {
- reclen = de->d_reclen;
- if (reclen > len)
- break;
- de->d_reclen = tswap16(reclen);
- tswap64s((uint64_t *)&de->d_ino);
- tswap64s((uint64_t *)&de->d_off);
- de = (struct linux_dirent64 *)((char *)de + reclen);
- len -= reclen;
- }
- }
- unlock_user(dirp, arg2, ret);
- }
- return ret;
-#endif /* TARGET_NR_getdents64 */
#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
# ifdef TARGET_NR_poll
case TARGET_NR_poll:
@@ -12939,6 +12944,12 @@ static impl_fn *syscall_table(unsigned num)
SYSCALL(ftruncate);
#ifdef TARGET_NR_futimesat
SYSCALL(futimesat);
+#endif
+#ifdef TARGET_NR_getdents
+ SYSCALL(getdents);
+#endif
+#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
+ SYSCALL(getdents64);
#endif
SYSCALL(getitimer);
#ifdef TARGET_NR_getpeername
--
2.17.1
- [Qemu-devel] [PATCH v2 050/108] linux-user: Split out getitimer, setitimer, syslog, (continued)
- [Qemu-devel] [PATCH v2 050/108] linux-user: Split out getitimer, setitimer, syslog, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 051/108] linux-user: Split out fstat, lstat, stat, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 052/108] linux-user: Unwrap TARGET_NR_syscall early, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 053/108] linux-user: Split out swapoff, sysinfo, vhangup, wait4, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 054/108] linux-user: Split out ipc, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 055/108] linux-user: Split out ipc syscalls, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 056/108] linux-user: Split out clone, exit_group, fsync, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 057/108] linux-user: Split out modify_ldt, setdomainname, uname, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 058/108] linux-user: Split out adjtimex, clock_adjtime, vm86, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 059/108] linux-user: Split out fchdir, getpgid, llseek, personality, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 060/108] linux-user: Split out getdents, getdents64,
Richard Henderson <=
- [Qemu-devel] [PATCH v2 061/108] linux-user: Split out poll, ppoll, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 062/108] linux-user: Split out flock, preadv, pwritev, readv, writev, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 063/108] linux-user: Split out fdatasync, getsid, _sysctl, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 065/108] linux-user: Split out getcpu, nanosleep, prctl, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 064/108] linux-user: Split out sched syscalls, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 066/108] linux-user: Split out arch_prctl, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 067/108] linux-user: Split out getcwd, pread64, pwrite64, sigaltstack, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 068/108] linux-user: Split out capget, capset, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 070/108] linux-user: Split out ftruncate64, truncate64, ugetrlimit, vfork, Richard Henderson, 2018/06/09
- [Qemu-devel] [PATCH v2 069/108] linux-user: Split out sendfile, sendfile64, Richard Henderson, 2018/06/09