Merge tag 'v9.0.0-rc3'
[qemu/ar7.git] / bsd-user / freebsd / os-stat.h
blob3bdc66aa9849314ce380df1d7c802a64993071b0
1 /*
2 * stat related system call shims and definitions
4 * Copyright (c) 2013 Stacey D. Son
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.
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.
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/>.
20 #ifndef BSD_USER_FREEBSD_OS_STAT_H
21 #define BSD_USER_FREEBSD_OS_STAT_H
23 int freebsd11_stat(const char *path, struct freebsd11_stat *stat);
24 __sym_compat(stat, freebsd11_stat, FBSD_1.0);
25 int freebsd11_lstat(const char *path, struct freebsd11_stat *stat);
26 __sym_compat(lstat, freebsd11_lstat, FBSD_1.0);
27 int freebsd11_fstat(int fd, struct freebsd11_stat *stat);
28 __sym_compat(fstat, freebsd11_fstat, FBSD_1.0);
29 int freebsd11_fstatat(int fd, const char *path, struct freebsd11_stat *stat,
30 int flag);
31 __sym_compat(fstatat, freebsd11_fstatat, FBSD_1.1);
33 int freebsd11_fhstat(const fhandle_t *fhandle, struct freebsd11_stat *stat);
34 __sym_compat(fhstat, freebsd11_fhstat, FBSD_1.0);
35 int freebsd11_getfsstat(struct freebsd11_statfs *buf, long bufsize, int mode);
36 __sym_compat(getfsstat, freebsd11_getfsstat, FBSD_1.0);
37 int freebsd11_fhstatfs(const fhandle_t *fhandle, struct freebsd11_statfs * buf);
38 __sym_compat(fhstatfs, freebsd11_fhstatfs, FBSD_1.0);
39 int freebsd11_statfs(const char *path, struct freebsd11_statfs *buf);
40 __sym_compat(statfs, freebsd11_statfs, FBSD_1.0);
41 int freebsd11_fstatfs(int fd, struct freebsd11_statfs *buf);
42 __sym_compat(fstatfs, freebsd11_fstatfs, FBSD_1.0);
44 ssize_t freebsd11_getdirentries(int fd, char *buf, size_t nbytes, off_t *basep);
45 __sym_compat(getdirentries, freebsd11_getdirentries, FBSD_1.0);
46 ssize_t freebsd11_getdents(int fd, char *buf, size_t nbytes);
47 __sym_compat(getdents, freebsd11_getdents, FBSD_1.0);
49 /* undocumented nstat system calls */
50 int freebsd11_nstat(const char *path, struct freebsd11_stat *sb);
51 __sym_compat(nstat, freebsd11_nstat, FBSD_1.0);
52 int freebsd11_nlstat(const char *path, struct freebsd11_stat *sb);
53 __sym_compat(nlstat, freebsd11_nlstat, FBSD_1.0);
54 int freebsd11_nfstat(int fd, struct freebsd11_stat *sb);
55 __sym_compat(nfstat, freebsd11_nfstat, FBSD_1.0);
57 /* stat(2) */
58 static inline abi_long do_freebsd11_stat(abi_long arg1, abi_long arg2)
60 abi_long ret;
61 void *p;
62 struct freebsd11_stat st;
64 LOCK_PATH(p, arg1);
65 ret = get_errno(freebsd11_stat(path(p), &st));
66 UNLOCK_PATH(p, arg1);
67 if (!is_error(ret)) {
68 ret = h2t_freebsd11_stat(arg2, &st);
70 return ret;
73 /* lstat(2) */
74 static inline abi_long do_freebsd11_lstat(abi_long arg1, abi_long arg2)
76 abi_long ret;
77 void *p;
78 struct freebsd11_stat st;
80 LOCK_PATH(p, arg1);
81 ret = get_errno(freebsd11_lstat(path(p), &st));
82 UNLOCK_PATH(p, arg1);
83 if (!is_error(ret)) {
84 ret = h2t_freebsd11_stat(arg2, &st);
86 return ret;
89 /* fstat(2) */
90 static inline abi_long do_freebsd11_fstat(abi_long arg1, abi_long arg2)
92 abi_long ret;
93 struct freebsd11_stat st;
95 ret = get_errno(freebsd11_fstat(arg1, &st));
96 if (!is_error(ret)) {
97 ret = h2t_freebsd11_stat(arg2, &st);
99 return ret;
102 /* fstat(2) */
103 static inline abi_long do_freebsd_fstat(abi_long arg1, abi_long arg2)
105 abi_long ret;
106 struct stat st;
108 ret = get_errno(fstat(arg1, &st));
109 if (!is_error(ret)) {
110 ret = h2t_freebsd_stat(arg2, &st);
112 return ret;
115 /* fstatat(2) */
116 static inline abi_long do_freebsd11_fstatat(abi_long arg1, abi_long arg2,
117 abi_long arg3, abi_long arg4)
119 abi_long ret;
120 void *p;
121 struct freebsd11_stat st;
123 LOCK_PATH(p, arg2);
124 ret = get_errno(freebsd11_fstatat(arg1, p, &st, arg4));
125 UNLOCK_PATH(p, arg2);
126 if (!is_error(ret) && arg3) {
127 ret = h2t_freebsd11_stat(arg3, &st);
129 return ret;
132 /* fstatat(2) */
133 static inline abi_long do_freebsd_fstatat(abi_long arg1, abi_long arg2,
134 abi_long arg3, abi_long arg4)
136 abi_long ret;
137 void *p;
138 struct stat st;
140 LOCK_PATH(p, arg2);
141 ret = get_errno(fstatat(arg1, p, &st, arg4));
142 UNLOCK_PATH(p, arg2);
143 if (!is_error(ret) && arg3) {
144 ret = h2t_freebsd_stat(arg3, &st);
146 return ret;
149 /* undocumented nstat(char *path, struct nstat *ub) syscall */
150 static abi_long do_freebsd11_nstat(abi_long arg1, abi_long arg2)
152 abi_long ret;
153 void *p;
154 struct freebsd11_stat st;
156 LOCK_PATH(p, arg1);
157 ret = get_errno(freebsd11_nstat(path(p), &st));
158 UNLOCK_PATH(p, arg1);
159 if (!is_error(ret)) {
160 ret = h2t_freebsd11_nstat(arg2, &st);
162 return ret;
165 /* undocumented nfstat(int fd, struct nstat *sb) syscall */
166 static abi_long do_freebsd11_nfstat(abi_long arg1, abi_long arg2)
168 abi_long ret;
169 struct freebsd11_stat st;
171 ret = get_errno(freebsd11_nfstat(arg1, &st));
172 if (!is_error(ret)) {
173 ret = h2t_freebsd11_nstat(arg2, &st);
175 return ret;
178 /* undocumented nlstat(char *path, struct nstat *ub) syscall */
179 static abi_long do_freebsd11_nlstat(abi_long arg1, abi_long arg2)
181 abi_long ret;
182 void *p;
183 struct freebsd11_stat st;
185 LOCK_PATH(p, arg1);
186 ret = get_errno(freebsd11_nlstat(path(p), &st));
187 UNLOCK_PATH(p, arg1);
188 if (!is_error(ret)) {
189 ret = h2t_freebsd11_nstat(arg2, &st);
191 return ret;
194 /* getfh(2) */
195 static abi_long do_freebsd_getfh(abi_long arg1, abi_long arg2)
197 abi_long ret;
198 void *p;
199 fhandle_t host_fh;
201 LOCK_PATH(p, arg1);
202 ret = get_errno(getfh(path(p), &host_fh));
203 UNLOCK_PATH(p, arg1);
204 if (is_error(ret)) {
205 return ret;
207 return h2t_freebsd_fhandle(arg2, &host_fh);
210 /* lgetfh(2) */
211 static inline abi_long do_freebsd_lgetfh(abi_long arg1, abi_long arg2)
213 abi_long ret;
214 void *p;
215 fhandle_t host_fh;
217 LOCK_PATH(p, arg1);
218 ret = get_errno(lgetfh(path(p), &host_fh));
219 UNLOCK_PATH(p, arg1);
220 if (is_error(ret)) {
221 return ret;
223 return h2t_freebsd_fhandle(arg2, &host_fh);
226 /* fhopen(2) */
227 static inline abi_long do_freebsd_fhopen(abi_long arg1, abi_long arg2)
229 abi_long ret;
230 fhandle_t host_fh;
232 ret = t2h_freebsd_fhandle(&host_fh, arg1);
233 if (is_error(ret)) {
234 return ret;
237 return get_errno(fhopen(&host_fh, arg2));
240 /* fhstat(2) */
241 static inline abi_long do_freebsd11_fhstat(abi_long arg1, abi_long arg2)
243 abi_long ret;
244 fhandle_t host_fh;
245 struct freebsd11_stat host_sb;
247 ret = t2h_freebsd_fhandle(&host_fh, arg1);
248 if (is_error(ret)) {
249 return ret;
251 ret = get_errno(freebsd11_fhstat(&host_fh, &host_sb));
252 if (is_error(ret)) {
253 return ret;
255 return h2t_freebsd11_stat(arg2, &host_sb);
258 /* fhstat(2) */
259 static inline abi_long do_freebsd_fhstat(abi_long arg1, abi_long arg2)
261 abi_long ret;
262 fhandle_t host_fh;
263 struct stat host_sb;
265 ret = t2h_freebsd_fhandle(&host_fh, arg1);
266 if (is_error(ret)) {
267 return ret;
269 ret = get_errno(fhstat(&host_fh, &host_sb));
270 if (is_error(ret)) {
271 return ret;
273 return h2t_freebsd_stat(arg2, &host_sb);
276 /* fhstatfs(2) */
277 static inline abi_long do_freebsd11_fhstatfs(abi_ulong target_fhp_addr,
278 abi_ulong target_stfs_addr)
280 abi_long ret;
281 fhandle_t host_fh;
282 struct freebsd11_statfs host_stfs;
284 ret = t2h_freebsd_fhandle(&host_fh, target_fhp_addr);
285 if (is_error(ret)) {
286 return ret;
288 ret = get_errno(freebsd11_fhstatfs(&host_fh, &host_stfs));
289 if (is_error(ret)) {
290 return ret;
292 return h2t_freebsd11_statfs(target_stfs_addr, &host_stfs);
295 /* fhstatfs(2) */
296 static inline abi_long do_freebsd_fhstatfs(abi_ulong target_fhp_addr,
297 abi_ulong target_stfs_addr)
299 abi_long ret;
300 fhandle_t host_fh;
301 struct statfs host_stfs;
303 ret = t2h_freebsd_fhandle(&host_fh, target_fhp_addr);
304 if (is_error(ret)) {
305 return ret;
307 ret = get_errno(fhstatfs(&host_fh, &host_stfs));
308 if (is_error(ret)) {
309 return ret;
311 return h2t_freebsd_statfs(target_stfs_addr, &host_stfs);
314 /* statfs(2) */
315 static inline abi_long do_freebsd11_statfs(abi_long arg1, abi_long arg2)
317 abi_long ret;
318 void *p;
319 struct freebsd11_statfs host_stfs;
321 LOCK_PATH(p, arg1);
322 ret = get_errno(freebsd11_statfs(path(p), &host_stfs));
323 UNLOCK_PATH(p, arg1);
324 if (is_error(ret)) {
325 return ret;
328 return h2t_freebsd11_statfs(arg2, &host_stfs);
331 /* statfs(2) */
332 static inline abi_long do_freebsd_statfs(abi_long arg1, abi_long arg2)
334 abi_long ret;
335 void *p;
336 struct statfs host_stfs;
338 LOCK_PATH(p, arg1);
339 ret = get_errno(statfs(path(p), &host_stfs));
340 UNLOCK_PATH(p, arg1);
341 if (is_error(ret)) {
342 return ret;
345 return h2t_freebsd_statfs(arg2, &host_stfs);
348 /* fstatfs(2) */
349 static inline abi_long do_freebsd11_fstatfs(abi_long fd, abi_ulong target_addr)
351 abi_long ret;
352 struct freebsd11_statfs host_stfs;
354 ret = get_errno(freebsd11_fstatfs(fd, &host_stfs));
355 if (is_error(ret)) {
356 return ret;
359 return h2t_freebsd11_statfs(target_addr, &host_stfs);
362 /* fstatfs(2) */
363 static inline abi_long do_freebsd_fstatfs(abi_long fd, abi_ulong target_addr)
365 abi_long ret;
366 struct statfs host_stfs;
368 ret = get_errno(fstatfs(fd, &host_stfs));
369 if (is_error(ret)) {
370 return ret;
373 return h2t_freebsd_statfs(target_addr, &host_stfs);
376 /* getfsstat(2) */
377 static inline abi_long do_freebsd11_getfsstat(abi_ulong target_addr,
378 abi_long bufsize, abi_long flags)
380 abi_long ret;
381 struct freebsd11_statfs *host_stfs;
382 int count;
383 long host_bufsize;
385 count = bufsize / sizeof(struct target_freebsd11_statfs);
387 /* if user buffer is NULL then return number of mounted FS's */
388 if (target_addr == 0 || count == 0) {
389 return get_errno(freebsd11_getfsstat(NULL, 0, flags));
392 /* XXX check count to be reasonable */
393 host_bufsize = sizeof(struct freebsd11_statfs) * count;
394 host_stfs = alloca(host_bufsize);
395 if (!host_stfs) {
396 return -TARGET_EINVAL;
399 ret = count = get_errno(freebsd11_getfsstat(host_stfs, host_bufsize, flags));
400 if (is_error(ret)) {
401 return ret;
404 while (count--) {
405 if (h2t_freebsd11_statfs((target_addr +
406 (count * sizeof(struct target_freebsd11_statfs))),
407 &host_stfs[count])) {
408 return -TARGET_EFAULT;
411 return ret;
414 /* getfsstat(2) */
415 static inline abi_long do_freebsd_getfsstat(abi_ulong target_addr,
416 abi_long bufsize, abi_long flags)
418 abi_long ret;
419 struct statfs *host_stfs;
420 int count;
421 long host_bufsize;
423 count = bufsize / sizeof(struct target_statfs);
425 /* if user buffer is NULL then return number of mounted FS's */
426 if (target_addr == 0 || count == 0) {
427 return get_errno(freebsd11_getfsstat(NULL, 0, flags));
430 /* XXX check count to be reasonable */
431 host_bufsize = sizeof(struct statfs) * count;
432 host_stfs = alloca(host_bufsize);
433 if (!host_stfs) {
434 return -TARGET_EINVAL;
437 ret = count = get_errno(getfsstat(host_stfs, host_bufsize, flags));
438 if (is_error(ret)) {
439 return ret;
442 while (count--) {
443 if (h2t_freebsd_statfs((target_addr +
444 (count * sizeof(struct target_statfs))),
445 &host_stfs[count])) {
446 return -TARGET_EFAULT;
449 return ret;
452 /* getdents(2) */
453 static inline abi_long do_freebsd11_getdents(abi_long arg1,
454 abi_ulong arg2, abi_long nbytes)
456 abi_long ret;
457 struct freebsd11_dirent *dirp;
459 dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0);
460 if (dirp == NULL) {
461 return -TARGET_EFAULT;
463 ret = get_errno(freebsd11_getdents(arg1, (char *)dirp, nbytes));
464 if (!is_error(ret)) {
465 struct freebsd11_dirent *de;
466 int len = ret;
467 int reclen;
469 de = dirp;
470 while (len > 0) {
471 reclen = de->d_reclen;
472 if (reclen > len) {
473 return -TARGET_EFAULT;
475 de->d_reclen = tswap16(reclen);
476 de->d_fileno = tswap32(de->d_fileno);
477 len -= reclen;
480 return ret;
483 /* getdirecentries(2) */
484 static inline abi_long do_freebsd11_getdirentries(abi_long arg1,
485 abi_ulong arg2, abi_long nbytes, abi_ulong arg4)
487 abi_long ret;
488 struct freebsd11_dirent *dirp;
489 long basep;
491 dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0);
492 if (dirp == NULL) {
493 return -TARGET_EFAULT;
495 ret = get_errno(freebsd11_getdirentries(arg1, (char *)dirp, nbytes, &basep));
496 if (!is_error(ret)) {
497 struct freebsd11_dirent *de;
498 int len = ret;
499 int reclen;
501 de = dirp;
502 while (len > 0) {
503 reclen = de->d_reclen;
504 if (reclen > len) {
505 return -TARGET_EFAULT;
507 de->d_reclen = tswap16(reclen);
508 de->d_fileno = tswap32(de->d_fileno);
509 len -= reclen;
510 de = (struct freebsd11_dirent *)((void *)de + reclen);
513 unlock_user(dirp, arg2, ret);
514 if (arg4) {
515 if (put_user(basep, arg4, abi_ulong)) {
516 return -TARGET_EFAULT;
519 return ret;
522 /* getdirecentries(2) */
523 static inline abi_long do_freebsd_getdirentries(abi_long arg1,
524 abi_ulong arg2, abi_long nbytes, abi_ulong arg4)
526 abi_long ret;
527 struct dirent *dirp;
528 long basep;
530 dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0);
531 if (dirp == NULL) {
532 return -TARGET_EFAULT;
534 ret = get_errno(getdirentries(arg1, (char *)dirp, nbytes, &basep));
535 if (!is_error(ret)) {
536 struct dirent *de;
537 int len = ret;
538 int reclen;
540 de = dirp;
541 while (len > 0) {
542 reclen = de->d_reclen;
543 if (reclen > len) {
544 return -TARGET_EFAULT;
546 de->d_fileno = tswap64(de->d_fileno);
547 de->d_off = tswap64(de->d_off);
548 de->d_reclen = tswap16(de->d_reclen);
549 de->d_namlen = tswap16(de->d_namlen);
550 len -= reclen;
551 de = (struct dirent *)((void *)de + reclen);
554 unlock_user(dirp, arg2, ret);
555 if (arg4) {
556 if (put_user(basep, arg4, abi_ulong)) {
557 return -TARGET_EFAULT;
560 return ret;
563 /* fcntl(2) */
564 static inline abi_long do_freebsd_fcntl(abi_long arg1, abi_long arg2,
565 abi_ulong arg3)
567 abi_long ret;
568 int host_cmd;
569 struct flock fl;
570 struct target_freebsd_flock *target_fl;
572 host_cmd = target_to_host_fcntl_cmd(arg2);
573 if (host_cmd < 0) {
574 return host_cmd;
576 switch (arg2) {
577 case TARGET_F_GETLK:
578 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) {
579 return -TARGET_EFAULT;
581 __get_user(fl.l_type, &target_fl->l_type);
582 __get_user(fl.l_whence, &target_fl->l_whence);
583 __get_user(fl.l_start, &target_fl->l_start);
584 __get_user(fl.l_len, &target_fl->l_len);
585 __get_user(fl.l_pid, &target_fl->l_pid);
586 __get_user(fl.l_sysid, &target_fl->l_sysid);
587 unlock_user_struct(target_fl, arg3, 0);
588 ret = get_errno(safe_fcntl(arg1, host_cmd, &fl));
589 if (!is_error(ret)) {
590 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0)) {
591 return -TARGET_EFAULT;
593 __put_user(fl.l_type, &target_fl->l_type);
594 __put_user(fl.l_whence, &target_fl->l_whence);
595 __put_user(fl.l_start, &target_fl->l_start);
596 __put_user(fl.l_len, &target_fl->l_len);
597 __put_user(fl.l_pid, &target_fl->l_pid);
598 __put_user(fl.l_sysid, &target_fl->l_sysid);
599 unlock_user_struct(target_fl, arg3, 1);
601 break;
603 case TARGET_F_SETLK:
604 case TARGET_F_SETLKW:
605 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) {
606 return -TARGET_EFAULT;
608 __get_user(fl.l_type, &target_fl->l_type);
609 __get_user(fl.l_whence, &target_fl->l_whence);
610 __get_user(fl.l_start, &target_fl->l_start);
611 __get_user(fl.l_len, &target_fl->l_len);
612 __get_user(fl.l_pid, &target_fl->l_pid);
613 __get_user(fl.l_sysid, &target_fl->l_sysid);
614 unlock_user_struct(target_fl, arg3, 0);
615 ret = get_errno(safe_fcntl(arg1, host_cmd, &fl));
616 break;
618 case TARGET_F_DUPFD:
619 case TARGET_F_DUP2FD:
620 case TARGET_F_GETOWN:
621 case TARGET_F_SETOWN:
622 case TARGET_F_GETFD:
623 case TARGET_F_SETFD:
624 case TARGET_F_GETFL:
625 case TARGET_F_SETFL:
626 case TARGET_F_READAHEAD:
627 case TARGET_F_RDAHEAD:
628 case TARGET_F_ADD_SEALS:
629 case TARGET_F_GET_SEALS:
630 default:
631 ret = get_errno(safe_fcntl(arg1, host_cmd, arg3));
632 break;
634 return ret;
637 #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300080
638 extern int __realpathat(int fd, const char *path, char *buf, size_t size,
639 int flags);
640 /* https://svnweb.freebsd.org/base?view=revision&revision=358172 */
641 /* no man page */
642 static inline abi_long do_freebsd_realpathat(abi_long arg1, abi_long arg2,
643 abi_long arg3, abi_long arg4, abi_long arg5)
645 abi_long ret;
646 void *p, *b;
648 LOCK_PATH(p, arg2);
649 b = lock_user(VERIFY_WRITE, arg3, arg4, 0);
650 if (b == NULL) {
651 UNLOCK_PATH(p, arg2);
652 return -TARGET_EFAULT;
655 ret = get_errno(__realpathat(arg1, p, b, arg4, arg5));
656 UNLOCK_PATH(p, arg2);
657 unlock_user(b, arg3, ret);
659 return ret;
661 #endif
663 #endif /* BSD_USER_FREEBSD_OS_STAT_H */