]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * file related system call shims and definitions | |
3 | * | |
4 | * Copyright (c) 2013 Stacey D. Son | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | #ifndef BSD_FILE_H | |
21 | #define BSD_FILE_H | |
22 | ||
23 | #include "qemu/path.h" | |
24 | ||
25 | extern struct iovec *lock_iovec(int type, abi_ulong target_addr, int count, | |
26 | int copy); | |
27 | extern void unlock_iovec(struct iovec *vec, abi_ulong target_addr, int count, | |
28 | int copy); | |
29 | ||
30 | ssize_t safe_read(int fd, void *buf, size_t nbytes); | |
31 | ssize_t safe_pread(int fd, void *buf, size_t nbytes, off_t offset); | |
32 | ssize_t safe_readv(int fd, const struct iovec *iov, int iovcnt); | |
33 | ssize_t safe_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset); | |
34 | ||
35 | ssize_t safe_write(int fd, void *buf, size_t nbytes); | |
36 | ssize_t safe_pwrite(int fd, void *buf, size_t nbytes, off_t offset); | |
37 | ssize_t safe_writev(int fd, const struct iovec *iov, int iovcnt); | |
38 | ssize_t safe_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset); | |
39 | ||
40 | /* read(2) */ | |
41 | static abi_long do_bsd_read(abi_long arg1, abi_long arg2, abi_long arg3) | |
42 | { | |
43 | abi_long ret; | |
44 | void *p; | |
45 | ||
46 | p = lock_user(VERIFY_WRITE, arg2, arg3, 0); | |
47 | if (p == NULL) { | |
48 | return -TARGET_EFAULT; | |
49 | } | |
50 | ret = get_errno(safe_read(arg1, p, arg3)); | |
51 | unlock_user(p, arg2, ret); | |
52 | ||
53 | return ret; | |
54 | } | |
55 | ||
56 | /* pread(2) */ | |
57 | static abi_long do_bsd_pread(void *cpu_env, abi_long arg1, | |
58 | abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) | |
59 | { | |
60 | abi_long ret; | |
61 | void *p; | |
62 | ||
63 | p = lock_user(VERIFY_WRITE, arg2, arg3, 0); | |
64 | if (p == NULL) { | |
65 | return -TARGET_EFAULT; | |
66 | } | |
67 | if (regpairs_aligned(cpu_env) != 0) { | |
68 | arg4 = arg5; | |
69 | arg5 = arg6; | |
70 | } | |
71 | ret = get_errno(safe_pread(arg1, p, arg3, target_arg64(arg4, arg5))); | |
72 | unlock_user(p, arg2, ret); | |
73 | ||
74 | return ret; | |
75 | } | |
76 | ||
77 | /* readv(2) */ | |
78 | static abi_long do_bsd_readv(abi_long arg1, abi_long arg2, abi_long arg3) | |
79 | { | |
80 | abi_long ret; | |
81 | struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0); | |
82 | ||
83 | if (vec != NULL) { | |
84 | ret = get_errno(safe_readv(arg1, vec, arg3)); | |
85 | unlock_iovec(vec, arg2, arg3, 1); | |
86 | } else { | |
87 | ret = -host_to_target_errno(errno); | |
88 | } | |
89 | ||
90 | return ret; | |
91 | } | |
92 | ||
93 | /* preadv(2) */ | |
94 | static abi_long do_bsd_preadv(void *cpu_env, abi_long arg1, | |
95 | abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) | |
96 | { | |
97 | abi_long ret; | |
98 | struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 1); | |
99 | ||
100 | if (vec != NULL) { | |
101 | if (regpairs_aligned(cpu_env) != 0) { | |
102 | arg4 = arg5; | |
103 | arg5 = arg6; | |
104 | } | |
105 | ret = get_errno(safe_preadv(arg1, vec, arg3, target_arg64(arg4, arg5))); | |
106 | unlock_iovec(vec, arg2, arg3, 0); | |
107 | } else { | |
108 | ret = -host_to_target_errno(errno); | |
109 | } | |
110 | ||
111 | return ret; | |
112 | } | |
113 | ||
114 | /* write(2) */ | |
115 | static abi_long do_bsd_write(abi_long arg1, abi_long arg2, abi_long arg3) | |
116 | { | |
117 | abi_long nbytes, ret; | |
118 | void *p; | |
119 | ||
120 | /* nbytes < 0 implies that it was larger than SIZE_MAX. */ | |
121 | nbytes = arg3; | |
122 | if (nbytes < 0) { | |
123 | return -TARGET_EINVAL; | |
124 | } | |
125 | p = lock_user(VERIFY_READ, arg2, nbytes, 1); | |
126 | if (p == NULL) { | |
127 | return -TARGET_EFAULT; | |
128 | } | |
129 | ret = get_errno(safe_write(arg1, p, arg3)); | |
130 | unlock_user(p, arg2, 0); | |
131 | ||
132 | return ret; | |
133 | } | |
134 | ||
135 | /* pwrite(2) */ | |
136 | static abi_long do_bsd_pwrite(void *cpu_env, abi_long arg1, | |
137 | abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) | |
138 | { | |
139 | abi_long ret; | |
140 | void *p; | |
141 | ||
142 | p = lock_user(VERIFY_READ, arg2, arg3, 1); | |
143 | if (p == NULL) { | |
144 | return -TARGET_EFAULT; | |
145 | } | |
146 | if (regpairs_aligned(cpu_env) != 0) { | |
147 | arg4 = arg5; | |
148 | arg5 = arg6; | |
149 | } | |
150 | ret = get_errno(safe_pwrite(arg1, p, arg3, target_arg64(arg4, arg5))); | |
151 | unlock_user(p, arg2, 0); | |
152 | ||
153 | return ret; | |
154 | } | |
155 | ||
156 | /* writev(2) */ | |
157 | static abi_long do_bsd_writev(abi_long arg1, abi_long arg2, abi_long arg3) | |
158 | { | |
159 | abi_long ret; | |
160 | struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); | |
161 | ||
162 | if (vec != NULL) { | |
163 | ret = get_errno(safe_writev(arg1, vec, arg3)); | |
164 | unlock_iovec(vec, arg2, arg3, 0); | |
165 | } else { | |
166 | ret = -host_to_target_errno(errno); | |
167 | } | |
168 | ||
169 | return ret; | |
170 | } | |
171 | ||
172 | /* pwritev(2) */ | |
173 | static abi_long do_bsd_pwritev(void *cpu_env, abi_long arg1, | |
174 | abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) | |
175 | { | |
176 | abi_long ret; | |
177 | struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); | |
178 | ||
179 | if (vec != NULL) { | |
180 | if (regpairs_aligned(cpu_env) != 0) { | |
181 | arg4 = arg5; | |
182 | arg5 = arg6; | |
183 | } | |
184 | ret = get_errno(safe_pwritev(arg1, vec, arg3, target_arg64(arg4, arg5))); | |
185 | unlock_iovec(vec, arg2, arg3, 0); | |
186 | } else { | |
187 | ret = -host_to_target_errno(errno); | |
188 | } | |
189 | ||
190 | return ret; | |
191 | } | |
192 | ||
193 | #endif /* BSD_FILE_H */ |