xref: /openbmc/qemu/bsd-user/bsd-file.h (revision b9f88dc0)
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 */
194