~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to linux-user/uaccess.c

  • Committer: bellard
  • Date: 2007-02-05 20:46:55 UTC
  • Revision ID: git-v1:7b9c30c5eecdbfc08ce18e4d386a5486289f0f78
update


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2394 c046a42c-6fe2-441c-8c8c-71466251a162

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* User memory access */
2
 
#include <stdio.h>
3
 
#include <string.h>
4
 
 
5
 
#include "qemu.h"
6
 
 
7
 
/* copy_from_user() and copy_to_user() are usually used to copy data
8
 
 * buffers between the target and host.  These internally perform
9
 
 * locking/unlocking of the memory.
10
 
 */
11
 
abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len)
12
 
{
13
 
    abi_long ret = 0;
14
 
    void *ghptr;
15
 
 
16
 
    if ((ghptr = lock_user(VERIFY_READ, gaddr, len, 1))) {
17
 
        memcpy(hptr, ghptr, len);
18
 
        unlock_user(ghptr, gaddr, 0);
19
 
    } else
20
 
        ret = -TARGET_EFAULT;
21
 
 
22
 
    return ret;
23
 
}
24
 
 
25
 
 
26
 
abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len)
27
 
{
28
 
    abi_long ret = 0;
29
 
    void *ghptr;
30
 
 
31
 
    if ((ghptr = lock_user(VERIFY_WRITE, gaddr, len, 0))) {
32
 
        memcpy(ghptr, hptr, len);
33
 
        unlock_user(ghptr, gaddr, len);
34
 
    } else
35
 
        ret = -TARGET_EFAULT;
36
 
 
37
 
    return ret;
38
 
}
39
 
 
40
 
/* XXX: use host strnlen if available ? */
41
 
static int qemu_strnlen(const char *s, int max_len)
42
 
{
43
 
    int i;
44
 
    for(i = 0; i < max_len; i++) {
45
 
        if (s[i] == '\0')
46
 
            break;
47
 
    }
48
 
    return i;
49
 
}
50
 
 
51
 
/* Return the length of a string in target memory or -TARGET_EFAULT if
52
 
   access error  */
53
 
abi_long target_strlen(abi_ulong guest_addr1)
54
 
{
55
 
    uint8_t *ptr;
56
 
    abi_ulong guest_addr;
57
 
    int max_len, len;
58
 
 
59
 
    guest_addr = guest_addr1;
60
 
    for(;;) {
61
 
        max_len = TARGET_PAGE_SIZE - (guest_addr & ~TARGET_PAGE_MASK);
62
 
        ptr = lock_user(VERIFY_READ, guest_addr, max_len, 1);
63
 
        if (!ptr)
64
 
            return -TARGET_EFAULT;
65
 
        len = qemu_strnlen((const char *)ptr, max_len);
66
 
        unlock_user(ptr, guest_addr, 0);
67
 
        guest_addr += len;
68
 
        /* we don't allow wrapping or integer overflow */
69
 
        if (guest_addr == 0 || 
70
 
            (guest_addr - guest_addr1) > 0x7fffffff)
71
 
            return -TARGET_EFAULT;
72
 
        if (len != max_len)
73
 
            break;
74
 
    }
75
 
    return guest_addr - guest_addr1;
76
 
}