]> git.proxmox.com Git - mirror_qemu.git/blame - bsd-user/freebsd/os-stat.h
bsd-user: Implement stat related syscalls
[mirror_qemu.git] / bsd-user / freebsd / os-stat.h
CommitLineData
bf14f13d
SS
1/*
2 * stat 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_USER_FREEBSD_OS_STAT_H
21#define BSD_USER_FREEBSD_OS_STAT_H
22
23/* stat(2) */
24static inline abi_long do_freebsd11_stat(abi_long arg1, abi_long arg2)
25{
26 abi_long ret;
27 void *p;
28 struct freebsd11_stat st;
29
30 LOCK_PATH(p, arg1);
31 ret = get_errno(freebsd11_stat(path(p), &st));
32 UNLOCK_PATH(p, arg1);
33 if (!is_error(ret)) {
34 ret = h2t_freebsd11_stat(arg2, &st);
35 }
36 return ret;
37}
38
39/* lstat(2) */
40static inline abi_long do_freebsd11_lstat(abi_long arg1, abi_long arg2)
41{
42 abi_long ret;
43 void *p;
44 struct freebsd11_stat st;
45
46 LOCK_PATH(p, arg1);
47 ret = get_errno(freebsd11_lstat(path(p), &st));
48 UNLOCK_PATH(p, arg1);
49 if (!is_error(ret)) {
50 ret = h2t_freebsd11_stat(arg2, &st);
51 }
52 return ret;
53}
54
55/* fstat(2) */
56static inline abi_long do_freebsd_fstat(abi_long arg1, abi_long arg2)
57{
58 abi_long ret;
59 struct stat st;
60
61 ret = get_errno(fstat(arg1, &st));
62 if (!is_error(ret)) {
63 ret = h2t_freebsd_stat(arg2, &st);
64 }
65 return ret;
66}
67
68/* fstatat(2) */
69static inline abi_long do_freebsd_fstatat(abi_long arg1, abi_long arg2,
70 abi_long arg3, abi_long arg4)
71{
72 abi_long ret;
73 void *p;
74 struct stat st;
75
76 LOCK_PATH(p, arg2);
77 ret = get_errno(fstatat(arg1, p, &st, arg4));
78 UNLOCK_PATH(p, arg2);
79 if (!is_error(ret) && arg3) {
80 ret = h2t_freebsd_stat(arg3, &st);
81 }
82 return ret;
83}
84
85/* undocummented nstat(char *path, struct nstat *ub) syscall */
86static abi_long do_freebsd11_nstat(abi_long arg1, abi_long arg2)
87{
88 abi_long ret;
89 void *p;
90 struct freebsd11_stat st;
91
92 LOCK_PATH(p, arg1);
93 ret = get_errno(freebsd11_nstat(path(p), &st));
94 UNLOCK_PATH(p, arg1);
95 if (!is_error(ret)) {
96 ret = h2t_freebsd11_nstat(arg2, &st);
97 }
98 return ret;
99}
100
101/* undocummented nfstat(int fd, struct nstat *sb) syscall */
102static abi_long do_freebsd11_nfstat(abi_long arg1, abi_long arg2)
103{
104 abi_long ret;
105 struct freebsd11_stat st;
106
107 ret = get_errno(freebsd11_nfstat(arg1, &st));
108 if (!is_error(ret)) {
109 ret = h2t_freebsd11_nstat(arg2, &st);
110 }
111 return ret;
112}
113
114/* undocummented nlstat(char *path, struct nstat *ub) syscall */
115static abi_long do_freebsd11_nlstat(abi_long arg1, abi_long arg2)
116{
117 abi_long ret;
118 void *p;
119 struct freebsd11_stat st;
120
121 LOCK_PATH(p, arg1);
122 ret = get_errno(freebsd11_nlstat(path(p), &st));
123 UNLOCK_PATH(p, arg1);
124 if (!is_error(ret)) {
125 ret = h2t_freebsd11_nstat(arg2, &st);
126 }
127 return ret;
128}
129
db8ee08f
SS
130/* getfh(2) */
131static abi_long do_freebsd_getfh(abi_long arg1, abi_long arg2)
132{
133 abi_long ret;
134 void *p;
135 fhandle_t host_fh;
136
137 LOCK_PATH(p, arg1);
138 ret = get_errno(getfh(path(p), &host_fh));
139 UNLOCK_PATH(p, arg1);
140 if (is_error(ret)) {
141 return ret;
142 }
143 return h2t_freebsd_fhandle(arg2, &host_fh);
144}
145
146/* lgetfh(2) */
147static inline abi_long do_freebsd_lgetfh(abi_long arg1, abi_long arg2)
148{
149 abi_long ret;
150 void *p;
151 fhandle_t host_fh;
152
153 LOCK_PATH(p, arg1);
154 ret = get_errno(lgetfh(path(p), &host_fh));
155 UNLOCK_PATH(p, arg1);
156 if (is_error(ret)) {
157 return ret;
158 }
159 return h2t_freebsd_fhandle(arg2, &host_fh);
160}
161
162/* fhopen(2) */
163static inline abi_long do_freebsd_fhopen(abi_long arg1, abi_long arg2)
164{
165 abi_long ret;
166 fhandle_t host_fh;
167
168 ret = t2h_freebsd_fhandle(&host_fh, arg1);
169 if (is_error(ret)) {
170 return ret;
171 }
172
173 return get_errno(fhopen(&host_fh, arg2));
174}
175
176/* fhstat(2) */
177static inline abi_long do_freebsd_fhstat(abi_long arg1, abi_long arg2)
178{
179 abi_long ret;
180 fhandle_t host_fh;
181 struct stat host_sb;
182
183 ret = t2h_freebsd_fhandle(&host_fh, arg1);
184 if (is_error(ret)) {
185 return ret;
186 }
187 ret = get_errno(fhstat(&host_fh, &host_sb));
188 if (is_error(ret)) {
189 return ret;
190 }
191 return h2t_freebsd_stat(arg2, &host_sb);
192}
193
194/* fhstatfs(2) */
195static inline abi_long do_freebsd_fhstatfs(abi_ulong target_fhp_addr,
196 abi_ulong target_stfs_addr)
197{
198 abi_long ret;
199 fhandle_t host_fh;
200 struct statfs host_stfs;
201
202 ret = t2h_freebsd_fhandle(&host_fh, target_fhp_addr);
203 if (is_error(ret)) {
204 return ret;
205 }
206 ret = get_errno(fhstatfs(&host_fh, &host_stfs));
207 if (is_error(ret)) {
208 return ret;
209 }
210 return h2t_freebsd_statfs(target_stfs_addr, &host_stfs);
211}
212
191fe50d
SS
213/* statfs(2) */
214static inline abi_long do_freebsd_statfs(abi_long arg1, abi_long arg2)
215{
216 abi_long ret;
217 void *p;
218 struct statfs host_stfs;
219
220 LOCK_PATH(p, arg1);
221 ret = get_errno(statfs(path(p), &host_stfs));
222 UNLOCK_PATH(p, arg1);
223 if (is_error(ret)) {
224 return ret;
225 }
226
227 return h2t_freebsd_statfs(arg2, &host_stfs);
228}
229
230/* fstatfs(2) */
231static inline abi_long do_freebsd_fstatfs(abi_long fd, abi_ulong target_addr)
232{
233 abi_long ret;
234 struct statfs host_stfs;
235
236 ret = get_errno(fstatfs(fd, &host_stfs));
237 if (is_error(ret)) {
238 return ret;
239 }
240
241 return h2t_freebsd_statfs(target_addr, &host_stfs);
242}
243
244/* getfsstat(2) */
245static inline abi_long do_freebsd_getfsstat(abi_ulong target_addr,
246 abi_long bufsize, abi_long flags)
247{
248 abi_long ret;
249 struct statfs *host_stfs;
250 int count;
251 long host_bufsize;
252
253 count = bufsize / sizeof(struct target_statfs);
254
255 /* if user buffer is NULL then return number of mounted FS's */
256 if (target_addr == 0 || count == 0) {
257 return get_errno(freebsd11_getfsstat(NULL, 0, flags));
258 }
259
260 /* XXX check count to be reasonable */
261 host_bufsize = sizeof(struct statfs) * count;
262 host_stfs = alloca(host_bufsize);
263 if (!host_stfs) {
264 return -TARGET_EINVAL;
265 }
266
267 ret = count = get_errno(getfsstat(host_stfs, host_bufsize, flags));
268 if (is_error(ret)) {
269 return ret;
270 }
271
272 while (count--) {
273 if (h2t_freebsd_statfs((target_addr +
274 (count * sizeof(struct target_statfs))),
275 &host_stfs[count])) {
276 return -TARGET_EFAULT;
277 }
278 }
279 return ret;
280}
281
21344452
SS
282/* getdents(2) */
283static inline abi_long do_freebsd11_getdents(abi_long arg1,
284 abi_ulong arg2, abi_long nbytes)
285{
286 abi_long ret;
287 struct freebsd11_dirent *dirp;
288
289 dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0);
290 if (dirp == NULL) {
291 return -TARGET_EFAULT;
292 }
293 ret = get_errno(freebsd11_getdents(arg1, (char *)dirp, nbytes));
294 if (!is_error(ret)) {
295 struct freebsd11_dirent *de;
296 int len = ret;
297 int reclen;
298
299 de = dirp;
300 while (len > 0) {
301 reclen = de->d_reclen;
302 if (reclen > len) {
303 return -TARGET_EFAULT;
304 }
305 de->d_reclen = tswap16(reclen);
306 de->d_fileno = tswap32(de->d_fileno);
307 len -= reclen;
308 }
309 }
310 return ret;
311}
312
313/* getdirecentries(2) */
314static inline abi_long do_freebsd_getdirentries(abi_long arg1,
315 abi_ulong arg2, abi_long nbytes, abi_ulong arg4)
316{
317 abi_long ret;
318 struct dirent *dirp;
319 long basep;
320
321 dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0);
322 if (dirp == NULL) {
323 return -TARGET_EFAULT;
324 }
325 ret = get_errno(getdirentries(arg1, (char *)dirp, nbytes, &basep));
326 if (!is_error(ret)) {
327 struct dirent *de;
328 int len = ret;
329 int reclen;
330
331 de = dirp;
332 while (len > 0) {
333 reclen = de->d_reclen;
334 if (reclen > len) {
335 return -TARGET_EFAULT;
336 }
337 de->d_fileno = tswap64(de->d_fileno);
338 de->d_off = tswap64(de->d_off);
339 de->d_reclen = tswap16(de->d_reclen);
340 de->d_namlen = tswap16(de->d_namlen);
341 len -= reclen;
342 de = (struct dirent *)((void *)de + reclen);
343 }
344 }
345 unlock_user(dirp, arg2, ret);
346 if (arg4) {
347 if (put_user(basep, arg4, abi_ulong)) {
348 return -TARGET_EFAULT;
349 }
350 }
351 return ret;
352}
353
c0023204
SS
354/* fcntl(2) */
355static inline abi_long do_freebsd_fcntl(abi_long arg1, abi_long arg2,
356 abi_ulong arg3)
357{
358 abi_long ret;
359 int host_cmd;
360 struct flock fl;
361 struct target_freebsd_flock *target_fl;
362
363 host_cmd = target_to_host_fcntl_cmd(arg2);
364 if (host_cmd < 0) {
365 return host_cmd;
366 }
367 switch (arg2) {
368 case TARGET_F_GETLK:
369 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) {
370 return -TARGET_EFAULT;
371 }
372 __get_user(fl.l_type, &target_fl->l_type);
373 __get_user(fl.l_whence, &target_fl->l_whence);
374 __get_user(fl.l_start, &target_fl->l_start);
375 __get_user(fl.l_len, &target_fl->l_len);
376 __get_user(fl.l_pid, &target_fl->l_pid);
377 __get_user(fl.l_sysid, &target_fl->l_sysid);
378 unlock_user_struct(target_fl, arg3, 0);
379 ret = get_errno(safe_fcntl(arg1, host_cmd, &fl));
380 if (!is_error(ret)) {
381 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0)) {
382 return -TARGET_EFAULT;
383 }
384 __put_user(fl.l_type, &target_fl->l_type);
385 __put_user(fl.l_whence, &target_fl->l_whence);
386 __put_user(fl.l_start, &target_fl->l_start);
387 __put_user(fl.l_len, &target_fl->l_len);
388 __put_user(fl.l_pid, &target_fl->l_pid);
389 __put_user(fl.l_sysid, &target_fl->l_sysid);
390 unlock_user_struct(target_fl, arg3, 1);
391 }
392 break;
393
394 case TARGET_F_SETLK:
395 case TARGET_F_SETLKW:
396 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) {
397 return -TARGET_EFAULT;
398 }
399 __get_user(fl.l_type, &target_fl->l_type);
400 __get_user(fl.l_whence, &target_fl->l_whence);
401 __get_user(fl.l_start, &target_fl->l_start);
402 __get_user(fl.l_len, &target_fl->l_len);
403 __get_user(fl.l_pid, &target_fl->l_pid);
404 __get_user(fl.l_sysid, &target_fl->l_sysid);
405 unlock_user_struct(target_fl, arg3, 0);
406 ret = get_errno(safe_fcntl(arg1, host_cmd, &fl));
407 break;
408
409 case TARGET_F_DUPFD:
410 case TARGET_F_DUP2FD:
411 case TARGET_F_GETOWN:
412 case TARGET_F_SETOWN:
413 case TARGET_F_GETFD:
414 case TARGET_F_SETFD:
415 case TARGET_F_GETFL:
416 case TARGET_F_SETFL:
417 case TARGET_F_READAHEAD:
418 case TARGET_F_RDAHEAD:
419 case TARGET_F_ADD_SEALS:
420 case TARGET_F_GET_SEALS:
421 default:
422 ret = get_errno(safe_fcntl(arg1, host_cmd, arg3));
423 break;
424 }
425 return ret;
426}
427
bf14f13d 428#endif /* BSD_USER_FREEBSD_OS_STAT_H */