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
,
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
);
58 static inline abi_long
do_freebsd11_stat(abi_long arg1
, abi_long arg2
)
62 struct freebsd11_stat st
;
65 ret
= get_errno(freebsd11_stat(path(p
), &st
));
68 ret
= h2t_freebsd11_stat(arg2
, &st
);
74 static inline abi_long
do_freebsd11_lstat(abi_long arg1
, abi_long arg2
)
78 struct freebsd11_stat st
;
81 ret
= get_errno(freebsd11_lstat(path(p
), &st
));
84 ret
= h2t_freebsd11_stat(arg2
, &st
);
90 static inline abi_long
do_freebsd11_fstat(abi_long arg1
, abi_long arg2
)
93 struct freebsd11_stat st
;
95 ret
= get_errno(freebsd11_fstat(arg1
, &st
));
97 ret
= h2t_freebsd11_stat(arg2
, &st
);
103 static inline abi_long
do_freebsd_fstat(abi_long arg1
, abi_long arg2
)
108 ret
= get_errno(fstat(arg1
, &st
));
109 if (!is_error(ret
)) {
110 ret
= h2t_freebsd_stat(arg2
, &st
);
116 static inline abi_long
do_freebsd11_fstatat(abi_long arg1
, abi_long arg2
,
117 abi_long arg3
, abi_long arg4
)
121 struct freebsd11_stat st
;
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
);
133 static inline abi_long
do_freebsd_fstatat(abi_long arg1
, abi_long arg2
,
134 abi_long arg3
, abi_long arg4
)
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
);
149 /* undocumented nstat(char *path, struct nstat *ub) syscall */
150 static abi_long
do_freebsd11_nstat(abi_long arg1
, abi_long arg2
)
154 struct freebsd11_stat st
;
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
);
165 /* undocumented nfstat(int fd, struct nstat *sb) syscall */
166 static abi_long
do_freebsd11_nfstat(abi_long arg1
, abi_long arg2
)
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
);
178 /* undocumented nlstat(char *path, struct nstat *ub) syscall */
179 static abi_long
do_freebsd11_nlstat(abi_long arg1
, abi_long arg2
)
183 struct freebsd11_stat st
;
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
);
195 static abi_long
do_freebsd_getfh(abi_long arg1
, abi_long arg2
)
202 ret
= get_errno(getfh(path(p
), &host_fh
));
203 UNLOCK_PATH(p
, arg1
);
207 return h2t_freebsd_fhandle(arg2
, &host_fh
);
211 static inline abi_long
do_freebsd_lgetfh(abi_long arg1
, abi_long arg2
)
218 ret
= get_errno(lgetfh(path(p
), &host_fh
));
219 UNLOCK_PATH(p
, arg1
);
223 return h2t_freebsd_fhandle(arg2
, &host_fh
);
227 static inline abi_long
do_freebsd_fhopen(abi_long arg1
, abi_long arg2
)
232 ret
= t2h_freebsd_fhandle(&host_fh
, arg1
);
237 return get_errno(fhopen(&host_fh
, arg2
));
241 static inline abi_long
do_freebsd11_fhstat(abi_long arg1
, abi_long arg2
)
245 struct freebsd11_stat host_sb
;
247 ret
= t2h_freebsd_fhandle(&host_fh
, arg1
);
251 ret
= get_errno(freebsd11_fhstat(&host_fh
, &host_sb
));
255 return h2t_freebsd11_stat(arg2
, &host_sb
);
259 static inline abi_long
do_freebsd_fhstat(abi_long arg1
, abi_long arg2
)
265 ret
= t2h_freebsd_fhandle(&host_fh
, arg1
);
269 ret
= get_errno(fhstat(&host_fh
, &host_sb
));
273 return h2t_freebsd_stat(arg2
, &host_sb
);
277 static inline abi_long
do_freebsd11_fhstatfs(abi_ulong target_fhp_addr
,
278 abi_ulong target_stfs_addr
)
282 struct freebsd11_statfs host_stfs
;
284 ret
= t2h_freebsd_fhandle(&host_fh
, target_fhp_addr
);
288 ret
= get_errno(freebsd11_fhstatfs(&host_fh
, &host_stfs
));
292 return h2t_freebsd11_statfs(target_stfs_addr
, &host_stfs
);
296 static inline abi_long
do_freebsd_fhstatfs(abi_ulong target_fhp_addr
,
297 abi_ulong target_stfs_addr
)
301 struct statfs host_stfs
;
303 ret
= t2h_freebsd_fhandle(&host_fh
, target_fhp_addr
);
307 ret
= get_errno(fhstatfs(&host_fh
, &host_stfs
));
311 return h2t_freebsd_statfs(target_stfs_addr
, &host_stfs
);
315 static inline abi_long
do_freebsd11_statfs(abi_long arg1
, abi_long arg2
)
319 struct freebsd11_statfs host_stfs
;
322 ret
= get_errno(freebsd11_statfs(path(p
), &host_stfs
));
323 UNLOCK_PATH(p
, arg1
);
328 return h2t_freebsd11_statfs(arg2
, &host_stfs
);
332 static inline abi_long
do_freebsd_statfs(abi_long arg1
, abi_long arg2
)
336 struct statfs host_stfs
;
339 ret
= get_errno(statfs(path(p
), &host_stfs
));
340 UNLOCK_PATH(p
, arg1
);
345 return h2t_freebsd_statfs(arg2
, &host_stfs
);
349 static inline abi_long
do_freebsd11_fstatfs(abi_long fd
, abi_ulong target_addr
)
352 struct freebsd11_statfs host_stfs
;
354 ret
= get_errno(freebsd11_fstatfs(fd
, &host_stfs
));
359 return h2t_freebsd11_statfs(target_addr
, &host_stfs
);
363 static inline abi_long
do_freebsd_fstatfs(abi_long fd
, abi_ulong target_addr
)
366 struct statfs host_stfs
;
368 ret
= get_errno(fstatfs(fd
, &host_stfs
));
373 return h2t_freebsd_statfs(target_addr
, &host_stfs
);
377 static inline abi_long
do_freebsd11_getfsstat(abi_ulong target_addr
,
378 abi_long bufsize
, abi_long flags
)
381 struct freebsd11_statfs
*host_stfs
;
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
);
396 return -TARGET_EINVAL
;
399 ret
= count
= get_errno(freebsd11_getfsstat(host_stfs
, host_bufsize
, flags
));
405 if (h2t_freebsd11_statfs((target_addr
+
406 (count
* sizeof(struct target_freebsd11_statfs
))),
407 &host_stfs
[count
])) {
408 return -TARGET_EFAULT
;
415 static inline abi_long
do_freebsd_getfsstat(abi_ulong target_addr
,
416 abi_long bufsize
, abi_long flags
)
419 struct statfs
*host_stfs
;
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
);
434 return -TARGET_EINVAL
;
437 ret
= count
= get_errno(getfsstat(host_stfs
, host_bufsize
, flags
));
443 if (h2t_freebsd_statfs((target_addr
+
444 (count
* sizeof(struct target_statfs
))),
445 &host_stfs
[count
])) {
446 return -TARGET_EFAULT
;
453 static inline abi_long
do_freebsd11_getdents(abi_long arg1
,
454 abi_ulong arg2
, abi_long nbytes
)
457 struct freebsd11_dirent
*dirp
;
459 dirp
= lock_user(VERIFY_WRITE
, arg2
, nbytes
, 0);
461 return -TARGET_EFAULT
;
463 ret
= get_errno(freebsd11_getdents(arg1
, (char *)dirp
, nbytes
));
464 if (!is_error(ret
)) {
465 struct freebsd11_dirent
*de
;
471 reclen
= de
->d_reclen
;
473 return -TARGET_EFAULT
;
475 de
->d_reclen
= tswap16(reclen
);
476 de
->d_fileno
= tswap32(de
->d_fileno
);
483 /* getdirecentries(2) */
484 static inline abi_long
do_freebsd11_getdirentries(abi_long arg1
,
485 abi_ulong arg2
, abi_long nbytes
, abi_ulong arg4
)
488 struct freebsd11_dirent
*dirp
;
491 dirp
= lock_user(VERIFY_WRITE
, arg2
, nbytes
, 0);
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
;
503 reclen
= de
->d_reclen
;
505 return -TARGET_EFAULT
;
507 de
->d_reclen
= tswap16(reclen
);
508 de
->d_fileno
= tswap32(de
->d_fileno
);
510 de
= (struct freebsd11_dirent
*)((void *)de
+ reclen
);
513 unlock_user(dirp
, arg2
, ret
);
515 if (put_user(basep
, arg4
, abi_ulong
)) {
516 return -TARGET_EFAULT
;
522 /* getdirecentries(2) */
523 static inline abi_long
do_freebsd_getdirentries(abi_long arg1
,
524 abi_ulong arg2
, abi_long nbytes
, abi_ulong arg4
)
530 dirp
= lock_user(VERIFY_WRITE
, arg2
, nbytes
, 0);
532 return -TARGET_EFAULT
;
534 ret
= get_errno(getdirentries(arg1
, (char *)dirp
, nbytes
, &basep
));
535 if (!is_error(ret
)) {
542 reclen
= de
->d_reclen
;
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
);
551 de
= (struct dirent
*)((void *)de
+ reclen
);
554 unlock_user(dirp
, arg2
, ret
);
556 if (put_user(basep
, arg4
, abi_ulong
)) {
557 return -TARGET_EFAULT
;
564 static inline abi_long
do_freebsd_fcntl(abi_long arg1
, abi_long arg2
,
570 struct target_freebsd_flock
*target_fl
;
572 host_cmd
= target_to_host_fcntl_cmd(arg2
);
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);
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
));
619 case TARGET_F_DUP2FD
:
620 case TARGET_F_GETOWN
:
621 case TARGET_F_SETOWN
:
626 case TARGET_F_READAHEAD
:
627 case TARGET_F_RDAHEAD
:
628 case TARGET_F_ADD_SEALS
:
629 case TARGET_F_GET_SEALS
:
631 ret
= get_errno(safe_fcntl(arg1
, host_cmd
, arg3
));
637 #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300080
638 extern int __realpathat(int fd
, const char *path
, char *buf
, size_t size
,
640 /* https://svnweb.freebsd.org/base?view=revision&revision=358172 */
642 static inline abi_long
do_freebsd_realpathat(abi_long arg1
, abi_long arg2
,
643 abi_long arg3
, abi_long arg4
, abi_long arg5
)
649 b
= lock_user(VERIFY_WRITE
, arg3
, arg4
, 0);
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
);
663 #endif /* BSD_USER_FREEBSD_OS_STAT_H */