]> git.proxmox.com Git - mirror_qemu.git/blame - bsd-user/freebsd/os-stat.h
Merge tag 'firmware/edk2-20231213-pull-request' of https://gitlab.com/kraxel/qemu...
[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
b4432977
MM
23int freebsd11_stat(const char *path, struct freebsd11_stat *stat);
24__sym_compat(stat, freebsd11_stat, FBSD_1.0);
25int freebsd11_lstat(const char *path, struct freebsd11_stat *stat);
26__sym_compat(lstat, freebsd11_lstat, FBSD_1.0);
33d73068
MM
27int freebsd11_fstat(int fd, struct freebsd11_stat *stat);
28__sym_compat(fstat, freebsd11_fstat, FBSD_1.0);
29int freebsd11_fstatat(int fd, const char *path, struct freebsd11_stat *stat,
30 int flag);
31__sym_compat(fstatat, freebsd11_fstatat, FBSD_1.1);
32
33int freebsd11_fhstat(const fhandle_t *fhandle, struct freebsd11_stat *stat);
34__sym_compat(fhstat, freebsd11_fhstat, FBSD_1.0);
196da9d3
MM
35int freebsd11_getfsstat(struct freebsd11_statfs *buf, long bufsize, int mode);
36__sym_compat(getfsstat, freebsd11_getfsstat, FBSD_1.0);
33d73068
MM
37int freebsd11_fhstatfs(const fhandle_t *fhandle, struct freebsd11_statfs * buf);
38__sym_compat(fhstatfs, freebsd11_fhstatfs, FBSD_1.0);
39int freebsd11_statfs(const char *path, struct freebsd11_statfs *buf);
196da9d3
MM
40__sym_compat(statfs, freebsd11_statfs, FBSD_1.0);
41int freebsd11_fstatfs(int fd, struct freebsd11_statfs *buf);
42__sym_compat(fstatfs, freebsd11_fstatfs, FBSD_1.0);
43
91a98c9b
MM
44ssize_t freebsd11_getdirentries(int fd, char *buf, size_t nbytes, off_t *basep);
45__sym_compat(getdirentries, freebsd11_getdirentries, FBSD_1.0);
46ssize_t freebsd11_getdents(int fd, char *buf, size_t nbytes);
47__sym_compat(getdents, freebsd11_getdents, FBSD_1.0);
48
292f00c0
MM
49/* undocumented nstat system calls */
50int freebsd11_nstat(const char *path, struct freebsd11_stat *sb);
51__sym_compat(nstat, freebsd11_nstat, FBSD_1.0);
52int freebsd11_nlstat(const char *path, struct freebsd11_stat *sb);
53__sym_compat(nlstat, freebsd11_nlstat, FBSD_1.0);
54int freebsd11_nfstat(int fd, struct freebsd11_stat *sb);
55__sym_compat(nfstat, freebsd11_nfstat, FBSD_1.0);
b4432977 56
bf14f13d
SS
57/* stat(2) */
58static 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) */
74static 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
33d73068
MM
89/* fstat(2) */
90static 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
bf14f13d
SS
102/* fstat(2) */
103static 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
33d73068
MM
115/* fstatat(2) */
116static 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
bf14f13d
SS
132/* fstatat(2) */
133static 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
9bfba08a 149/* undocumented nstat(char *path, struct nstat *ub) syscall */
bf14f13d
SS
150static 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
9bfba08a 165/* undocumented nfstat(int fd, struct nstat *sb) syscall */
bf14f13d
SS
166static 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
9bfba08a 178/* undocumented nlstat(char *path, struct nstat *ub) syscall */
bf14f13d
SS
179static 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
db8ee08f
SS
194/* getfh(2) */
195static 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) */
211static 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) */
227static 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
33d73068
MM
240/* fhstat(2) */
241static 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
db8ee08f
SS
258/* fhstat(2) */
259static 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
33d73068
MM
276/* fhstatfs(2) */
277static 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
db8ee08f
SS
295/* fhstatfs(2) */
296static 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
196da9d3
MM
314/* statfs(2) */
315static 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
191fe50d
SS
331/* statfs(2) */
332static 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
196da9d3
MM
348/* fstatfs(2) */
349static 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
191fe50d
SS
362/* fstatfs(2) */
363static 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
196da9d3
MM
376/* getfsstat(2) */
377static 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
191fe50d
SS
414/* getfsstat(2) */
415static 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
21344452
SS
452/* getdents(2) */
453static 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
91a98c9b
MM
483/* getdirecentries(2) */
484static 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
21344452
SS
522/* getdirecentries(2) */
523static 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
c0023204
SS
563/* fcntl(2) */
564static 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
292bfd0f
MU
637#if defined(__FreeBSD_version) && __FreeBSD_version >= 1300080
638extern 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 */
642static 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
bf14f13d 663#endif /* BSD_USER_FREEBSD_OS_STAT_H */