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
);
29 static inline abi_long
do_freebsd11_stat(abi_long arg1
, abi_long arg2
)
33 struct freebsd11_stat st
;
36 ret
= get_errno(freebsd11_stat(path(p
), &st
));
39 ret
= h2t_freebsd11_stat(arg2
, &st
);
45 static inline abi_long
do_freebsd11_lstat(abi_long arg1
, abi_long arg2
)
49 struct freebsd11_stat st
;
52 ret
= get_errno(freebsd11_lstat(path(p
), &st
));
55 ret
= h2t_freebsd11_stat(arg2
, &st
);
61 static inline abi_long
do_freebsd_fstat(abi_long arg1
, abi_long arg2
)
66 ret
= get_errno(fstat(arg1
, &st
));
68 ret
= h2t_freebsd_stat(arg2
, &st
);
74 static inline abi_long
do_freebsd_fstatat(abi_long arg1
, abi_long arg2
,
75 abi_long arg3
, abi_long arg4
)
82 ret
= get_errno(fstatat(arg1
, p
, &st
, arg4
));
84 if (!is_error(ret
) && arg3
) {
85 ret
= h2t_freebsd_stat(arg3
, &st
);
90 /* undocummented nstat(char *path, struct nstat *ub) syscall */
91 static abi_long
do_freebsd11_nstat(abi_long arg1
, abi_long arg2
)
95 struct freebsd11_stat st
;
98 ret
= get_errno(freebsd11_nstat(path(p
), &st
));
100 if (!is_error(ret
)) {
101 ret
= h2t_freebsd11_nstat(arg2
, &st
);
106 /* undocummented nfstat(int fd, struct nstat *sb) syscall */
107 static abi_long
do_freebsd11_nfstat(abi_long arg1
, abi_long arg2
)
110 struct freebsd11_stat st
;
112 ret
= get_errno(freebsd11_nfstat(arg1
, &st
));
113 if (!is_error(ret
)) {
114 ret
= h2t_freebsd11_nstat(arg2
, &st
);
119 /* undocummented nlstat(char *path, struct nstat *ub) syscall */
120 static abi_long
do_freebsd11_nlstat(abi_long arg1
, abi_long arg2
)
124 struct freebsd11_stat st
;
127 ret
= get_errno(freebsd11_nlstat(path(p
), &st
));
128 UNLOCK_PATH(p
, arg1
);
129 if (!is_error(ret
)) {
130 ret
= h2t_freebsd11_nstat(arg2
, &st
);
136 static abi_long
do_freebsd_getfh(abi_long arg1
, abi_long arg2
)
143 ret
= get_errno(getfh(path(p
), &host_fh
));
144 UNLOCK_PATH(p
, arg1
);
148 return h2t_freebsd_fhandle(arg2
, &host_fh
);
152 static inline abi_long
do_freebsd_lgetfh(abi_long arg1
, abi_long arg2
)
159 ret
= get_errno(lgetfh(path(p
), &host_fh
));
160 UNLOCK_PATH(p
, arg1
);
164 return h2t_freebsd_fhandle(arg2
, &host_fh
);
168 static inline abi_long
do_freebsd_fhopen(abi_long arg1
, abi_long arg2
)
173 ret
= t2h_freebsd_fhandle(&host_fh
, arg1
);
178 return get_errno(fhopen(&host_fh
, arg2
));
182 static inline abi_long
do_freebsd_fhstat(abi_long arg1
, abi_long arg2
)
188 ret
= t2h_freebsd_fhandle(&host_fh
, arg1
);
192 ret
= get_errno(fhstat(&host_fh
, &host_sb
));
196 return h2t_freebsd_stat(arg2
, &host_sb
);
200 static inline abi_long
do_freebsd_fhstatfs(abi_ulong target_fhp_addr
,
201 abi_ulong target_stfs_addr
)
205 struct statfs host_stfs
;
207 ret
= t2h_freebsd_fhandle(&host_fh
, target_fhp_addr
);
211 ret
= get_errno(fhstatfs(&host_fh
, &host_stfs
));
215 return h2t_freebsd_statfs(target_stfs_addr
, &host_stfs
);
219 static inline abi_long
do_freebsd_statfs(abi_long arg1
, abi_long arg2
)
223 struct statfs host_stfs
;
226 ret
= get_errno(statfs(path(p
), &host_stfs
));
227 UNLOCK_PATH(p
, arg1
);
232 return h2t_freebsd_statfs(arg2
, &host_stfs
);
236 static inline abi_long
do_freebsd_fstatfs(abi_long fd
, abi_ulong target_addr
)
239 struct statfs host_stfs
;
241 ret
= get_errno(fstatfs(fd
, &host_stfs
));
246 return h2t_freebsd_statfs(target_addr
, &host_stfs
);
250 static inline abi_long
do_freebsd_getfsstat(abi_ulong target_addr
,
251 abi_long bufsize
, abi_long flags
)
254 struct statfs
*host_stfs
;
258 count
= bufsize
/ sizeof(struct target_statfs
);
260 /* if user buffer is NULL then return number of mounted FS's */
261 if (target_addr
== 0 || count
== 0) {
262 return get_errno(freebsd11_getfsstat(NULL
, 0, flags
));
265 /* XXX check count to be reasonable */
266 host_bufsize
= sizeof(struct statfs
) * count
;
267 host_stfs
= alloca(host_bufsize
);
269 return -TARGET_EINVAL
;
272 ret
= count
= get_errno(getfsstat(host_stfs
, host_bufsize
, flags
));
278 if (h2t_freebsd_statfs((target_addr
+
279 (count
* sizeof(struct target_statfs
))),
280 &host_stfs
[count
])) {
281 return -TARGET_EFAULT
;
288 static inline abi_long
do_freebsd11_getdents(abi_long arg1
,
289 abi_ulong arg2
, abi_long nbytes
)
292 struct freebsd11_dirent
*dirp
;
294 dirp
= lock_user(VERIFY_WRITE
, arg2
, nbytes
, 0);
296 return -TARGET_EFAULT
;
298 ret
= get_errno(freebsd11_getdents(arg1
, (char *)dirp
, nbytes
));
299 if (!is_error(ret
)) {
300 struct freebsd11_dirent
*de
;
306 reclen
= de
->d_reclen
;
308 return -TARGET_EFAULT
;
310 de
->d_reclen
= tswap16(reclen
);
311 de
->d_fileno
= tswap32(de
->d_fileno
);
318 /* getdirecentries(2) */
319 static inline abi_long
do_freebsd_getdirentries(abi_long arg1
,
320 abi_ulong arg2
, abi_long nbytes
, abi_ulong arg4
)
326 dirp
= lock_user(VERIFY_WRITE
, arg2
, nbytes
, 0);
328 return -TARGET_EFAULT
;
330 ret
= get_errno(getdirentries(arg1
, (char *)dirp
, nbytes
, &basep
));
331 if (!is_error(ret
)) {
338 reclen
= de
->d_reclen
;
340 return -TARGET_EFAULT
;
342 de
->d_fileno
= tswap64(de
->d_fileno
);
343 de
->d_off
= tswap64(de
->d_off
);
344 de
->d_reclen
= tswap16(de
->d_reclen
);
345 de
->d_namlen
= tswap16(de
->d_namlen
);
347 de
= (struct dirent
*)((void *)de
+ reclen
);
350 unlock_user(dirp
, arg2
, ret
);
352 if (put_user(basep
, arg4
, abi_ulong
)) {
353 return -TARGET_EFAULT
;
360 static inline abi_long
do_freebsd_fcntl(abi_long arg1
, abi_long arg2
,
366 struct target_freebsd_flock
*target_fl
;
368 host_cmd
= target_to_host_fcntl_cmd(arg2
);
374 if (!lock_user_struct(VERIFY_READ
, target_fl
, arg3
, 1)) {
375 return -TARGET_EFAULT
;
377 __get_user(fl
.l_type
, &target_fl
->l_type
);
378 __get_user(fl
.l_whence
, &target_fl
->l_whence
);
379 __get_user(fl
.l_start
, &target_fl
->l_start
);
380 __get_user(fl
.l_len
, &target_fl
->l_len
);
381 __get_user(fl
.l_pid
, &target_fl
->l_pid
);
382 __get_user(fl
.l_sysid
, &target_fl
->l_sysid
);
383 unlock_user_struct(target_fl
, arg3
, 0);
384 ret
= get_errno(safe_fcntl(arg1
, host_cmd
, &fl
));
385 if (!is_error(ret
)) {
386 if (!lock_user_struct(VERIFY_WRITE
, target_fl
, arg3
, 0)) {
387 return -TARGET_EFAULT
;
389 __put_user(fl
.l_type
, &target_fl
->l_type
);
390 __put_user(fl
.l_whence
, &target_fl
->l_whence
);
391 __put_user(fl
.l_start
, &target_fl
->l_start
);
392 __put_user(fl
.l_len
, &target_fl
->l_len
);
393 __put_user(fl
.l_pid
, &target_fl
->l_pid
);
394 __put_user(fl
.l_sysid
, &target_fl
->l_sysid
);
395 unlock_user_struct(target_fl
, arg3
, 1);
400 case TARGET_F_SETLKW
:
401 if (!lock_user_struct(VERIFY_READ
, target_fl
, arg3
, 1)) {
402 return -TARGET_EFAULT
;
404 __get_user(fl
.l_type
, &target_fl
->l_type
);
405 __get_user(fl
.l_whence
, &target_fl
->l_whence
);
406 __get_user(fl
.l_start
, &target_fl
->l_start
);
407 __get_user(fl
.l_len
, &target_fl
->l_len
);
408 __get_user(fl
.l_pid
, &target_fl
->l_pid
);
409 __get_user(fl
.l_sysid
, &target_fl
->l_sysid
);
410 unlock_user_struct(target_fl
, arg3
, 0);
411 ret
= get_errno(safe_fcntl(arg1
, host_cmd
, &fl
));
415 case TARGET_F_DUP2FD
:
416 case TARGET_F_GETOWN
:
417 case TARGET_F_SETOWN
:
422 case TARGET_F_READAHEAD
:
423 case TARGET_F_RDAHEAD
:
424 case TARGET_F_ADD_SEALS
:
425 case TARGET_F_GET_SEALS
:
427 ret
= get_errno(safe_fcntl(arg1
, host_cmd
, arg3
));
433 #endif /* BSD_USER_FREEBSD_OS_STAT_H */