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 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);
32
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);
43
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);
48
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);
56
57 /* stat(2) */
do_freebsd11_stat(abi_long arg1,abi_long arg2)58 static inline abi_long do_freebsd11_stat(abi_long arg1, abi_long arg2)
59 {
60 abi_long ret;
61 void *p;
62 struct freebsd11_stat st;
63
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);
69 }
70 return ret;
71 }
72
73 /* lstat(2) */
do_freebsd11_lstat(abi_long arg1,abi_long arg2)74 static inline abi_long do_freebsd11_lstat(abi_long arg1, abi_long arg2)
75 {
76 abi_long ret;
77 void *p;
78 struct freebsd11_stat st;
79
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);
85 }
86 return ret;
87 }
88
89 /* fstat(2) */
do_freebsd11_fstat(abi_long arg1,abi_long arg2)90 static inline abi_long do_freebsd11_fstat(abi_long arg1, abi_long arg2)
91 {
92 abi_long ret;
93 struct freebsd11_stat st;
94
95 ret = get_errno(freebsd11_fstat(arg1, &st));
96 if (!is_error(ret)) {
97 ret = h2t_freebsd11_stat(arg2, &st);
98 }
99 return ret;
100 }
101
102 /* fstat(2) */
do_freebsd_fstat(abi_long arg1,abi_long arg2)103 static inline abi_long do_freebsd_fstat(abi_long arg1, abi_long arg2)
104 {
105 abi_long ret;
106 struct stat st;
107
108 ret = get_errno(fstat(arg1, &st));
109 if (!is_error(ret)) {
110 ret = h2t_freebsd_stat(arg2, &st);
111 }
112 return ret;
113 }
114
115 /* fstatat(2) */
do_freebsd11_fstatat(abi_long arg1,abi_long arg2,abi_long arg3,abi_long arg4)116 static inline abi_long do_freebsd11_fstatat(abi_long arg1, abi_long arg2,
117 abi_long arg3, abi_long arg4)
118 {
119 abi_long ret;
120 void *p;
121 struct freebsd11_stat st;
122
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);
128 }
129 return ret;
130 }
131
132 /* fstatat(2) */
do_freebsd_fstatat(abi_long arg1,abi_long arg2,abi_long arg3,abi_long arg4)133 static inline abi_long do_freebsd_fstatat(abi_long arg1, abi_long arg2,
134 abi_long arg3, abi_long arg4)
135 {
136 abi_long ret;
137 void *p;
138 struct stat st;
139
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);
145 }
146 return ret;
147 }
148
149 /* undocumented nstat(char *path, struct nstat *ub) syscall */
do_freebsd11_nstat(abi_long arg1,abi_long arg2)150 static abi_long do_freebsd11_nstat(abi_long arg1, abi_long arg2)
151 {
152 abi_long ret;
153 void *p;
154 struct freebsd11_stat st;
155
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);
161 }
162 return ret;
163 }
164
165 /* undocumented nfstat(int fd, struct nstat *sb) syscall */
do_freebsd11_nfstat(abi_long arg1,abi_long arg2)166 static abi_long do_freebsd11_nfstat(abi_long arg1, abi_long arg2)
167 {
168 abi_long ret;
169 struct freebsd11_stat st;
170
171 ret = get_errno(freebsd11_nfstat(arg1, &st));
172 if (!is_error(ret)) {
173 ret = h2t_freebsd11_nstat(arg2, &st);
174 }
175 return ret;
176 }
177
178 /* undocumented nlstat(char *path, struct nstat *ub) syscall */
do_freebsd11_nlstat(abi_long arg1,abi_long arg2)179 static abi_long do_freebsd11_nlstat(abi_long arg1, abi_long arg2)
180 {
181 abi_long ret;
182 void *p;
183 struct freebsd11_stat st;
184
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);
190 }
191 return ret;
192 }
193
194 /* getfh(2) */
do_freebsd_getfh(abi_long arg1,abi_long arg2)195 static abi_long do_freebsd_getfh(abi_long arg1, abi_long arg2)
196 {
197 abi_long ret;
198 void *p;
199 fhandle_t host_fh;
200
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;
206 }
207 return h2t_freebsd_fhandle(arg2, &host_fh);
208 }
209
210 /* lgetfh(2) */
do_freebsd_lgetfh(abi_long arg1,abi_long arg2)211 static inline abi_long do_freebsd_lgetfh(abi_long arg1, abi_long arg2)
212 {
213 abi_long ret;
214 void *p;
215 fhandle_t host_fh;
216
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;
222 }
223 return h2t_freebsd_fhandle(arg2, &host_fh);
224 }
225
226 /* fhopen(2) */
do_freebsd_fhopen(abi_long arg1,abi_long arg2)227 static inline abi_long do_freebsd_fhopen(abi_long arg1, abi_long arg2)
228 {
229 abi_long ret;
230 fhandle_t host_fh;
231
232 ret = t2h_freebsd_fhandle(&host_fh, arg1);
233 if (is_error(ret)) {
234 return ret;
235 }
236
237 return get_errno(fhopen(&host_fh, arg2));
238 }
239
240 /* fhstat(2) */
do_freebsd11_fhstat(abi_long arg1,abi_long arg2)241 static inline abi_long do_freebsd11_fhstat(abi_long arg1, abi_long arg2)
242 {
243 abi_long ret;
244 fhandle_t host_fh;
245 struct freebsd11_stat host_sb;
246
247 ret = t2h_freebsd_fhandle(&host_fh, arg1);
248 if (is_error(ret)) {
249 return ret;
250 }
251 ret = get_errno(freebsd11_fhstat(&host_fh, &host_sb));
252 if (is_error(ret)) {
253 return ret;
254 }
255 return h2t_freebsd11_stat(arg2, &host_sb);
256 }
257
258 /* fhstat(2) */
do_freebsd_fhstat(abi_long arg1,abi_long arg2)259 static inline abi_long do_freebsd_fhstat(abi_long arg1, abi_long arg2)
260 {
261 abi_long ret;
262 fhandle_t host_fh;
263 struct stat host_sb;
264
265 ret = t2h_freebsd_fhandle(&host_fh, arg1);
266 if (is_error(ret)) {
267 return ret;
268 }
269 ret = get_errno(fhstat(&host_fh, &host_sb));
270 if (is_error(ret)) {
271 return ret;
272 }
273 return h2t_freebsd_stat(arg2, &host_sb);
274 }
275
276 /* fhstatfs(2) */
do_freebsd11_fhstatfs(abi_ulong target_fhp_addr,abi_ulong target_stfs_addr)277 static inline abi_long do_freebsd11_fhstatfs(abi_ulong target_fhp_addr,
278 abi_ulong target_stfs_addr)
279 {
280 abi_long ret;
281 fhandle_t host_fh;
282 struct freebsd11_statfs host_stfs;
283
284 ret = t2h_freebsd_fhandle(&host_fh, target_fhp_addr);
285 if (is_error(ret)) {
286 return ret;
287 }
288 ret = get_errno(freebsd11_fhstatfs(&host_fh, &host_stfs));
289 if (is_error(ret)) {
290 return ret;
291 }
292 return h2t_freebsd11_statfs(target_stfs_addr, &host_stfs);
293 }
294
295 /* fhstatfs(2) */
do_freebsd_fhstatfs(abi_ulong target_fhp_addr,abi_ulong target_stfs_addr)296 static inline abi_long do_freebsd_fhstatfs(abi_ulong target_fhp_addr,
297 abi_ulong target_stfs_addr)
298 {
299 abi_long ret;
300 fhandle_t host_fh;
301 struct statfs host_stfs;
302
303 ret = t2h_freebsd_fhandle(&host_fh, target_fhp_addr);
304 if (is_error(ret)) {
305 return ret;
306 }
307 ret = get_errno(fhstatfs(&host_fh, &host_stfs));
308 if (is_error(ret)) {
309 return ret;
310 }
311 return h2t_freebsd_statfs(target_stfs_addr, &host_stfs);
312 }
313
314 /* statfs(2) */
do_freebsd11_statfs(abi_long arg1,abi_long arg2)315 static inline abi_long do_freebsd11_statfs(abi_long arg1, abi_long arg2)
316 {
317 abi_long ret;
318 void *p;
319 struct freebsd11_statfs host_stfs;
320
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;
326 }
327
328 return h2t_freebsd11_statfs(arg2, &host_stfs);
329 }
330
331 /* statfs(2) */
do_freebsd_statfs(abi_long arg1,abi_long arg2)332 static inline abi_long do_freebsd_statfs(abi_long arg1, abi_long arg2)
333 {
334 abi_long ret;
335 void *p;
336 struct statfs host_stfs;
337
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;
343 }
344
345 return h2t_freebsd_statfs(arg2, &host_stfs);
346 }
347
348 /* fstatfs(2) */
do_freebsd11_fstatfs(abi_long fd,abi_ulong target_addr)349 static inline abi_long do_freebsd11_fstatfs(abi_long fd, abi_ulong target_addr)
350 {
351 abi_long ret;
352 struct freebsd11_statfs host_stfs;
353
354 ret = get_errno(freebsd11_fstatfs(fd, &host_stfs));
355 if (is_error(ret)) {
356 return ret;
357 }
358
359 return h2t_freebsd11_statfs(target_addr, &host_stfs);
360 }
361
362 /* fstatfs(2) */
do_freebsd_fstatfs(abi_long fd,abi_ulong target_addr)363 static inline abi_long do_freebsd_fstatfs(abi_long fd, abi_ulong target_addr)
364 {
365 abi_long ret;
366 struct statfs host_stfs;
367
368 ret = get_errno(fstatfs(fd, &host_stfs));
369 if (is_error(ret)) {
370 return ret;
371 }
372
373 return h2t_freebsd_statfs(target_addr, &host_stfs);
374 }
375
376 /* getfsstat(2) */
do_freebsd11_getfsstat(abi_ulong target_addr,abi_long bufsize,abi_long flags)377 static inline abi_long do_freebsd11_getfsstat(abi_ulong target_addr,
378 abi_long bufsize, abi_long flags)
379 {
380 abi_long ret;
381 struct freebsd11_statfs *host_stfs;
382 int count;
383 long host_bufsize;
384
385 count = bufsize / sizeof(struct target_freebsd11_statfs);
386
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));
390 }
391
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;
397 }
398
399 ret = count = get_errno(freebsd11_getfsstat(host_stfs, host_bufsize, flags));
400 if (is_error(ret)) {
401 return ret;
402 }
403
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;
409 }
410 }
411 return ret;
412 }
413
414 /* getfsstat(2) */
do_freebsd_getfsstat(abi_ulong target_addr,abi_long bufsize,abi_long flags)415 static inline abi_long do_freebsd_getfsstat(abi_ulong target_addr,
416 abi_long bufsize, abi_long flags)
417 {
418 abi_long ret;
419 struct statfs *host_stfs;
420 int count;
421 long host_bufsize;
422
423 count = bufsize / sizeof(struct target_statfs);
424
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));
428 }
429
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;
435 }
436
437 ret = count = get_errno(getfsstat(host_stfs, host_bufsize, flags));
438 if (is_error(ret)) {
439 return ret;
440 }
441
442 while (count--) {
443 if (h2t_freebsd_statfs((target_addr +
444 (count * sizeof(struct target_statfs))),
445 &host_stfs[count])) {
446 return -TARGET_EFAULT;
447 }
448 }
449 return ret;
450 }
451
452 /* getdents(2) */
do_freebsd11_getdents(abi_long arg1,abi_ulong arg2,abi_long nbytes)453 static inline abi_long do_freebsd11_getdents(abi_long arg1,
454 abi_ulong arg2, abi_long nbytes)
455 {
456 abi_long ret;
457 struct freebsd11_dirent *dirp;
458
459 dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0);
460 if (dirp == NULL) {
461 return -TARGET_EFAULT;
462 }
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;
468
469 de = dirp;
470 while (len > 0) {
471 reclen = de->d_reclen;
472 if (reclen > len) {
473 return -TARGET_EFAULT;
474 }
475 de->d_reclen = tswap16(reclen);
476 de->d_fileno = tswap32(de->d_fileno);
477 len -= reclen;
478 }
479 }
480 return ret;
481 }
482
483 /* getdirecentries(2) */
do_freebsd11_getdirentries(abi_long arg1,abi_ulong arg2,abi_long nbytes,abi_ulong arg4)484 static inline abi_long do_freebsd11_getdirentries(abi_long arg1,
485 abi_ulong arg2, abi_long nbytes, abi_ulong arg4)
486 {
487 abi_long ret;
488 struct freebsd11_dirent *dirp;
489 long basep;
490
491 dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0);
492 if (dirp == NULL) {
493 return -TARGET_EFAULT;
494 }
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;
500
501 de = dirp;
502 while (len > 0) {
503 reclen = de->d_reclen;
504 if (reclen > len) {
505 return -TARGET_EFAULT;
506 }
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);
511 }
512 }
513 unlock_user(dirp, arg2, ret);
514 if (arg4) {
515 if (put_user(basep, arg4, abi_ulong)) {
516 return -TARGET_EFAULT;
517 }
518 }
519 return ret;
520 }
521
522 /* getdirecentries(2) */
do_freebsd_getdirentries(abi_long arg1,abi_ulong arg2,abi_long nbytes,abi_ulong arg4)523 static inline abi_long do_freebsd_getdirentries(abi_long arg1,
524 abi_ulong arg2, abi_long nbytes, abi_ulong arg4)
525 {
526 abi_long ret;
527 struct dirent *dirp;
528 long basep;
529
530 dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0);
531 if (dirp == NULL) {
532 return -TARGET_EFAULT;
533 }
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;
539
540 de = dirp;
541 while (len > 0) {
542 reclen = de->d_reclen;
543 if (reclen > len) {
544 return -TARGET_EFAULT;
545 }
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);
552 }
553 }
554 unlock_user(dirp, arg2, ret);
555 if (arg4) {
556 if (put_user(basep, arg4, abi_ulong)) {
557 return -TARGET_EFAULT;
558 }
559 }
560 return ret;
561 }
562
563 /* fcntl(2) */
do_freebsd_fcntl(abi_long arg1,abi_long arg2,abi_ulong arg3)564 static inline abi_long do_freebsd_fcntl(abi_long arg1, abi_long arg2,
565 abi_ulong arg3)
566 {
567 abi_long ret;
568 int host_cmd;
569 struct flock fl;
570 struct target_freebsd_flock *target_fl;
571
572 host_cmd = target_to_host_fcntl_cmd(arg2);
573 if (host_cmd < 0) {
574 return host_cmd;
575 }
576 switch (arg2) {
577 case TARGET_F_GETLK:
578 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) {
579 return -TARGET_EFAULT;
580 }
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;
592 }
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);
600 }
601 break;
602
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;
607 }
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;
617
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;
633 }
634 return ret;
635 }
636
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 */
do_freebsd_realpathat(abi_long arg1,abi_long arg2,abi_long arg3,abi_long arg4,abi_long arg5)642 static inline abi_long do_freebsd_realpathat(abi_long arg1, abi_long arg2,
643 abi_long arg3, abi_long arg4, abi_long arg5)
644 {
645 abi_long ret;
646 void *p, *b;
647
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;
653 }
654
655 ret = get_errno(__realpathat(arg1, p, b, arg4, arg5));
656 UNLOCK_PATH(p, arg2);
657 unlock_user(b, arg3, ret);
658
659 return ret;
660 }
661 #endif
662
663 #endif /* BSD_USER_FREEBSD_OS_STAT_H */
664