#include <sys/epoll.h>
#endif
#ifdef CONFIG_ATTR
-#include "qemu-xattr.h"
+#include "qemu/xattr.h"
#endif
#define termios host_termios
extern int setgroups(int, gid_t *);
/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
-#ifdef TARGET_ARM
+#ifdef TARGET_ARM
static inline int regpairs_aligned(void *cpu_env) {
return ((((CPUARMState *)cpu_env)->eabi) == 1) ;
}
#elif defined(TARGET_MIPS)
static inline int regpairs_aligned(void *cpu_env) { return 1; }
+#elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
+/* SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs
+ * of registers which translates to the same as ARM/MIPS, because we start with
+ * r3 as arg1 */
+static inline int regpairs_aligned(void *cpu_env) { return 1; }
#else
static inline int regpairs_aligned(void *cpu_env) { return 0; }
#endif
return ret;
}
-/* FIXME
- * lock_iovec()/unlock_iovec() have a return code of 0 for success where
- * other lock functions have a return code of 0 for failure.
- */
-static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
- int count, int copy)
+static struct iovec *lock_iovec(int type, abi_ulong target_addr,
+ int count, int copy)
{
struct target_iovec *target_vec;
- abi_ulong base;
+ struct iovec *vec;
+ abi_ulong total_len, max_len;
int i;
- target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
- if (!target_vec)
- return -TARGET_EFAULT;
- for(i = 0;i < count; i++) {
- base = tswapal(target_vec[i].iov_base);
- vec[i].iov_len = tswapal(target_vec[i].iov_len);
- if (vec[i].iov_len != 0) {
- vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
- /* Don't check lock_user return value. We must call writev even
- if a element has invalid base address. */
+ if (count == 0) {
+ errno = 0;
+ return NULL;
+ }
+ if (count > IOV_MAX) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ vec = calloc(count, sizeof(struct iovec));
+ if (vec == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ target_vec = lock_user(VERIFY_READ, target_addr,
+ count * sizeof(struct target_iovec), 1);
+ if (target_vec == NULL) {
+ errno = EFAULT;
+ goto fail2;
+ }
+
+ /* ??? If host page size > target page size, this will result in a
+ value larger than what we can actually support. */
+ max_len = 0x7fffffff & TARGET_PAGE_MASK;
+ total_len = 0;
+
+ for (i = 0; i < count; i++) {
+ abi_ulong base = tswapal(target_vec[i].iov_base);
+ abi_long len = tswapal(target_vec[i].iov_len);
+
+ if (len < 0) {
+ errno = EINVAL;
+ goto fail;
+ } else if (len == 0) {
+ /* Zero length pointer is ignored. */
+ vec[i].iov_base = 0;
} else {
- /* zero length pointer is ignored */
- vec[i].iov_base = NULL;
+ vec[i].iov_base = lock_user(type, base, len, copy);
+ if (!vec[i].iov_base) {
+ errno = EFAULT;
+ goto fail;
+ }
+ if (len > max_len - total_len) {
+ len = max_len - total_len;
+ }
}
+ vec[i].iov_len = len;
+ total_len += len;
}
- unlock_user (target_vec, target_addr, 0);
- return 0;
+
+ unlock_user(target_vec, target_addr, 0);
+ return vec;
+
+ fail:
+ free(vec);
+ fail2:
+ unlock_user(target_vec, target_addr, 0);
+ return NULL;
}
-static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
- int count, int copy)
+static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
+ int count, int copy)
{
struct target_iovec *target_vec;
- abi_ulong base;
int i;
- target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
- if (!target_vec)
- return -TARGET_EFAULT;
- for(i = 0;i < count; i++) {
- if (target_vec[i].iov_base) {
- base = tswapal(target_vec[i].iov_base);
+ target_vec = lock_user(VERIFY_READ, target_addr,
+ count * sizeof(struct target_iovec), 1);
+ if (target_vec) {
+ for (i = 0; i < count; i++) {
+ abi_ulong base = tswapal(target_vec[i].iov_base);
+ abi_long len = tswapal(target_vec[i].iov_base);
+ if (len < 0) {
+ break;
+ }
unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
}
+ unlock_user(target_vec, target_addr, 0);
}
- unlock_user (target_vec, target_addr, 0);
- return 0;
+ free(vec);
}
/* do_socket() Must return target values and target errnos. */
ret = target_to_host_sockaddr(msg.msg_name, tswapal(msgp->msg_name),
msg.msg_namelen);
if (ret) {
- unlock_user_struct(msgp, target_msg, send ? 0 : 1);
- return ret;
+ goto out2;
}
} else {
msg.msg_name = NULL;
msg.msg_flags = tswap32(msgp->msg_flags);
count = tswapal(msgp->msg_iovlen);
- vec = alloca(count * sizeof(struct iovec));
target_vec = tswapal(msgp->msg_iov);
- lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
+ vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
+ target_vec, count, send);
+ if (vec == NULL) {
+ ret = -host_to_target_errno(errno);
+ goto out2;
+ }
msg.msg_iovlen = count;
msg.msg_iov = vec;
out:
unlock_iovec(vec, target_vec, count, !send);
+out2:
unlock_user_struct(msgp, target_msg, send ? 0 : 1);
return ret;
}
unlock_user(argptr, arg, target_size);
}
out:
- if (big_buf) {
- free(big_buf);
- }
+ g_free(big_buf);
return ret;
}
/* Map host to target signal numbers for the wait family of syscalls.
Assume all other status bits are the same. */
-static int host_to_target_waitstatus(int status)
+int host_to_target_waitstatus(int status)
{
if (WIFSIGNALED(status)) {
return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
dprintf(fd, "%08llx-%08llx rw-p %08llx 00:00 0 [stack]\n",
(unsigned long long)ts->info->stack_limit,
- (unsigned long long)(ts->stack_base + (TARGET_PAGE_SIZE - 1))
- & TARGET_PAGE_MASK,
+ (unsigned long long)(ts->info->start_stack +
+ (TARGET_PAGE_SIZE - 1)) & TARGET_PAGE_MASK,
(unsigned long long)0);
#endif
__put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
__put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
__put_user(stfs.f_namelen, &target_stfs->f_namelen);
+ __put_user(stfs.f_frsize, &target_stfs->f_frsize);
+ memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
unlock_user_struct(target_stfs, arg2, 1);
}
break;
__put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
__put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
__put_user(stfs.f_namelen, &target_stfs->f_namelen);
+ __put_user(stfs.f_frsize, &target_stfs->f_frsize);
+ memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
unlock_user_struct(target_stfs, arg3, 1);
}
break;
ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
#elif defined(TARGET_CRIS)
ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
+#elif defined(TARGET_MICROBLAZE)
+ ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
#elif defined(TARGET_S390X)
ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
#else
tde = target_dirp;
while (len > 0) {
reclen = de->d_reclen;
- treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
+ 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);
- tnamelen = treclen - (2 * sizeof(abi_long) + 2);
- if (tnamelen > 256)
- tnamelen = 256;
- /* XXX: may not be correct */
- pstrcpy(tde->d_name, tnamelen, de->d_name);
+ memcpy(tde->d_name, de->d_name, tnamelen);
de = (struct linux_dirent *)((char *)de + reclen);
len -= reclen;
tde = (struct target_dirent *)((char *)tde + treclen);
break;
case TARGET_NR_readv:
{
- int count = arg3;
- struct iovec *vec;
-
- vec = alloca(count * sizeof(struct iovec));
- if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
- goto efault;
- ret = get_errno(readv(arg1, vec, count));
- unlock_iovec(vec, arg2, count, 1);
+ struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
+ if (vec != NULL) {
+ ret = get_errno(readv(arg1, vec, arg3));
+ unlock_iovec(vec, arg2, arg3, 1);
+ } else {
+ ret = -host_to_target_errno(errno);
+ }
}
break;
case TARGET_NR_writev:
{
- int count = arg3;
- struct iovec *vec;
-
- vec = alloca(count * sizeof(struct iovec));
- if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
- goto efault;
- ret = get_errno(writev(arg1, vec, count));
- unlock_iovec(vec, arg2, count, 0);
+ struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
+ if (vec != NULL) {
+ ret = get_errno(writev(arg1, vec, arg3));
+ unlock_iovec(vec, arg2, arg3, 0);
+ } else {
+ ret = -host_to_target_errno(errno);
+ }
}
break;
case TARGET_NR_getsid:
goto unimplemented;
#endif
#endif
-#ifdef TARGET_NR_pread
- case TARGET_NR_pread:
- if (regpairs_aligned(cpu_env))
- arg4 = arg5;
- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
- goto efault;
- ret = get_errno(pread(arg1, p, arg3, arg4));
- unlock_user(p, arg2, ret);
- break;
- case TARGET_NR_pwrite:
- if (regpairs_aligned(cpu_env))
- arg4 = arg5;
- if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
- goto efault;
- ret = get_errno(pwrite(arg1, p, arg3, arg4));
- unlock_user(p, arg2, 0);
- break;
-#endif
#ifdef TARGET_NR_pread64
case TARGET_NR_pread64:
+ if (regpairs_aligned(cpu_env)) {
+ arg4 = arg5;
+ arg5 = arg6;
+ }
if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
goto efault;
ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
unlock_user(p, arg2, ret);
break;
case TARGET_NR_pwrite64:
+ if (regpairs_aligned(cpu_env)) {
+ arg4 = arg5;
+ arg5 = arg6;
+ }
if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
goto efault;
ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
#ifdef TARGET_NR_vmsplice
case TARGET_NR_vmsplice:
{
- int count = arg3;
- struct iovec *vec;
-
- vec = alloca(count * sizeof(struct iovec));
- if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
- goto efault;
- ret = get_errno(vmsplice(arg1, vec, count, arg4));
- unlock_iovec(vec, arg2, count, 0);
+ struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
+ if (vec != NULL) {
+ ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
+ unlock_iovec(vec, arg2, arg3, 0);
+ } else {
+ ret = -host_to_target_errno(errno);
+ }
}
break;
#endif
}
break;
}
+#endif
+#ifdef TARGET_NR_gethostname
+ case TARGET_NR_gethostname:
+ {
+ char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
+ if (name) {
+ ret = get_errno(gethostname(name, arg2));
+ unlock_user(name, arg1, arg2);
+ } else {
+ ret = -TARGET_EFAULT;
+ }
+ break;
+ }
#endif
default:
unimplemented: