1bf14f13dSStacey Son /* 2bf14f13dSStacey Son * stat related system call shims and definitions 3bf14f13dSStacey Son * 4bf14f13dSStacey Son * Copyright (c) 2013 Stacey D. Son 5bf14f13dSStacey Son * 6bf14f13dSStacey Son * This program is free software; you can redistribute it and/or modify 7bf14f13dSStacey Son * it under the terms of the GNU General Public License as published by 8bf14f13dSStacey Son * the Free Software Foundation; either version 2 of the License, or 9bf14f13dSStacey Son * (at your option) any later version. 10bf14f13dSStacey Son * 11bf14f13dSStacey Son * This program is distributed in the hope that it will be useful, 12bf14f13dSStacey Son * but WITHOUT ANY WARRANTY; without even the implied warranty of 13bf14f13dSStacey Son * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14bf14f13dSStacey Son * GNU General Public License for more details. 15bf14f13dSStacey Son * 16bf14f13dSStacey Son * You should have received a copy of the GNU General Public License 17bf14f13dSStacey Son * along with this program; if not, see <http://www.gnu.org/licenses/>. 18bf14f13dSStacey Son */ 19bf14f13dSStacey Son 20bf14f13dSStacey Son #ifndef BSD_USER_FREEBSD_OS_STAT_H 21bf14f13dSStacey Son #define BSD_USER_FREEBSD_OS_STAT_H 22bf14f13dSStacey Son 23b4432977SMichal Meloun int freebsd11_stat(const char *path, struct freebsd11_stat *stat); 24b4432977SMichal Meloun __sym_compat(stat, freebsd11_stat, FBSD_1.0); 25b4432977SMichal Meloun int freebsd11_lstat(const char *path, struct freebsd11_stat *stat); 26b4432977SMichal Meloun __sym_compat(lstat, freebsd11_lstat, FBSD_1.0); 2733d73068SMichal Meloun int freebsd11_fstat(int fd, struct freebsd11_stat *stat); 2833d73068SMichal Meloun __sym_compat(fstat, freebsd11_fstat, FBSD_1.0); 2933d73068SMichal Meloun int freebsd11_fstatat(int fd, const char *path, struct freebsd11_stat *stat, 3033d73068SMichal Meloun int flag); 3133d73068SMichal Meloun __sym_compat(fstatat, freebsd11_fstatat, FBSD_1.1); 3233d73068SMichal Meloun 3333d73068SMichal Meloun int freebsd11_fhstat(const fhandle_t *fhandle, struct freebsd11_stat *stat); 3433d73068SMichal Meloun __sym_compat(fhstat, freebsd11_fhstat, FBSD_1.0); 35196da9d3SMichal Meloun int freebsd11_getfsstat(struct freebsd11_statfs *buf, long bufsize, int mode); 36196da9d3SMichal Meloun __sym_compat(getfsstat, freebsd11_getfsstat, FBSD_1.0); 3733d73068SMichal Meloun int freebsd11_fhstatfs(const fhandle_t *fhandle, struct freebsd11_statfs * buf); 3833d73068SMichal Meloun __sym_compat(fhstatfs, freebsd11_fhstatfs, FBSD_1.0); 3933d73068SMichal Meloun int freebsd11_statfs(const char *path, struct freebsd11_statfs *buf); 40196da9d3SMichal Meloun __sym_compat(statfs, freebsd11_statfs, FBSD_1.0); 41196da9d3SMichal Meloun int freebsd11_fstatfs(int fd, struct freebsd11_statfs *buf); 42196da9d3SMichal Meloun __sym_compat(fstatfs, freebsd11_fstatfs, FBSD_1.0); 43196da9d3SMichal Meloun 4491a98c9bSMichal Meloun ssize_t freebsd11_getdirentries(int fd, char *buf, size_t nbytes, off_t *basep); 4591a98c9bSMichal Meloun __sym_compat(getdirentries, freebsd11_getdirentries, FBSD_1.0); 4691a98c9bSMichal Meloun ssize_t freebsd11_getdents(int fd, char *buf, size_t nbytes); 4791a98c9bSMichal Meloun __sym_compat(getdents, freebsd11_getdents, FBSD_1.0); 4891a98c9bSMichal Meloun 49292f00c0SMichal Meloun /* undocumented nstat system calls */ 50292f00c0SMichal Meloun int freebsd11_nstat(const char *path, struct freebsd11_stat *sb); 51292f00c0SMichal Meloun __sym_compat(nstat, freebsd11_nstat, FBSD_1.0); 52292f00c0SMichal Meloun int freebsd11_nlstat(const char *path, struct freebsd11_stat *sb); 53292f00c0SMichal Meloun __sym_compat(nlstat, freebsd11_nlstat, FBSD_1.0); 54292f00c0SMichal Meloun int freebsd11_nfstat(int fd, struct freebsd11_stat *sb); 55292f00c0SMichal Meloun __sym_compat(nfstat, freebsd11_nfstat, FBSD_1.0); 56b4432977SMichal Meloun 57bf14f13dSStacey Son /* stat(2) */ 58bf14f13dSStacey Son static inline abi_long do_freebsd11_stat(abi_long arg1, abi_long arg2) 59bf14f13dSStacey Son { 60bf14f13dSStacey Son abi_long ret; 61bf14f13dSStacey Son void *p; 62bf14f13dSStacey Son struct freebsd11_stat st; 63bf14f13dSStacey Son 64bf14f13dSStacey Son LOCK_PATH(p, arg1); 65bf14f13dSStacey Son ret = get_errno(freebsd11_stat(path(p), &st)); 66bf14f13dSStacey Son UNLOCK_PATH(p, arg1); 67bf14f13dSStacey Son if (!is_error(ret)) { 68bf14f13dSStacey Son ret = h2t_freebsd11_stat(arg2, &st); 69bf14f13dSStacey Son } 70bf14f13dSStacey Son return ret; 71bf14f13dSStacey Son } 72bf14f13dSStacey Son 73bf14f13dSStacey Son /* lstat(2) */ 74bf14f13dSStacey Son static inline abi_long do_freebsd11_lstat(abi_long arg1, abi_long arg2) 75bf14f13dSStacey Son { 76bf14f13dSStacey Son abi_long ret; 77bf14f13dSStacey Son void *p; 78bf14f13dSStacey Son struct freebsd11_stat st; 79bf14f13dSStacey Son 80bf14f13dSStacey Son LOCK_PATH(p, arg1); 81bf14f13dSStacey Son ret = get_errno(freebsd11_lstat(path(p), &st)); 82bf14f13dSStacey Son UNLOCK_PATH(p, arg1); 83bf14f13dSStacey Son if (!is_error(ret)) { 84bf14f13dSStacey Son ret = h2t_freebsd11_stat(arg2, &st); 85bf14f13dSStacey Son } 86bf14f13dSStacey Son return ret; 87bf14f13dSStacey Son } 88bf14f13dSStacey Son 89bf14f13dSStacey Son /* fstat(2) */ 9033d73068SMichal Meloun static inline abi_long do_freebsd11_fstat(abi_long arg1, abi_long arg2) 9133d73068SMichal Meloun { 9233d73068SMichal Meloun abi_long ret; 9333d73068SMichal Meloun struct freebsd11_stat st; 9433d73068SMichal Meloun 9533d73068SMichal Meloun ret = get_errno(freebsd11_fstat(arg1, &st)); 9633d73068SMichal Meloun if (!is_error(ret)) { 9733d73068SMichal Meloun ret = h2t_freebsd11_stat(arg2, &st); 9833d73068SMichal Meloun } 9933d73068SMichal Meloun return ret; 10033d73068SMichal Meloun } 10133d73068SMichal Meloun 10233d73068SMichal Meloun /* fstat(2) */ 103bf14f13dSStacey Son static inline abi_long do_freebsd_fstat(abi_long arg1, abi_long arg2) 104bf14f13dSStacey Son { 105bf14f13dSStacey Son abi_long ret; 106bf14f13dSStacey Son struct stat st; 107bf14f13dSStacey Son 108bf14f13dSStacey Son ret = get_errno(fstat(arg1, &st)); 109bf14f13dSStacey Son if (!is_error(ret)) { 110bf14f13dSStacey Son ret = h2t_freebsd_stat(arg2, &st); 111bf14f13dSStacey Son } 112bf14f13dSStacey Son return ret; 113bf14f13dSStacey Son } 114bf14f13dSStacey Son 115bf14f13dSStacey Son /* fstatat(2) */ 11633d73068SMichal Meloun static inline abi_long do_freebsd11_fstatat(abi_long arg1, abi_long arg2, 11733d73068SMichal Meloun abi_long arg3, abi_long arg4) 11833d73068SMichal Meloun { 11933d73068SMichal Meloun abi_long ret; 12033d73068SMichal Meloun void *p; 12133d73068SMichal Meloun struct freebsd11_stat st; 12233d73068SMichal Meloun 12333d73068SMichal Meloun LOCK_PATH(p, arg2); 12433d73068SMichal Meloun ret = get_errno(freebsd11_fstatat(arg1, p, &st, arg4)); 12533d73068SMichal Meloun UNLOCK_PATH(p, arg2); 12633d73068SMichal Meloun if (!is_error(ret) && arg3) { 12733d73068SMichal Meloun ret = h2t_freebsd11_stat(arg3, &st); 12833d73068SMichal Meloun } 12933d73068SMichal Meloun return ret; 13033d73068SMichal Meloun } 13133d73068SMichal Meloun 13233d73068SMichal Meloun /* fstatat(2) */ 133bf14f13dSStacey Son static inline abi_long do_freebsd_fstatat(abi_long arg1, abi_long arg2, 134bf14f13dSStacey Son abi_long arg3, abi_long arg4) 135bf14f13dSStacey Son { 136bf14f13dSStacey Son abi_long ret; 137bf14f13dSStacey Son void *p; 138bf14f13dSStacey Son struct stat st; 139bf14f13dSStacey Son 140bf14f13dSStacey Son LOCK_PATH(p, arg2); 141bf14f13dSStacey Son ret = get_errno(fstatat(arg1, p, &st, arg4)); 142bf14f13dSStacey Son UNLOCK_PATH(p, arg2); 143bf14f13dSStacey Son if (!is_error(ret) && arg3) { 144bf14f13dSStacey Son ret = h2t_freebsd_stat(arg3, &st); 145bf14f13dSStacey Son } 146bf14f13dSStacey Son return ret; 147bf14f13dSStacey Son } 148bf14f13dSStacey Son 149bf14f13dSStacey Son /* undocummented nstat(char *path, struct nstat *ub) syscall */ 150bf14f13dSStacey Son static abi_long do_freebsd11_nstat(abi_long arg1, abi_long arg2) 151bf14f13dSStacey Son { 152bf14f13dSStacey Son abi_long ret; 153bf14f13dSStacey Son void *p; 154bf14f13dSStacey Son struct freebsd11_stat st; 155bf14f13dSStacey Son 156bf14f13dSStacey Son LOCK_PATH(p, arg1); 157bf14f13dSStacey Son ret = get_errno(freebsd11_nstat(path(p), &st)); 158bf14f13dSStacey Son UNLOCK_PATH(p, arg1); 159bf14f13dSStacey Son if (!is_error(ret)) { 160bf14f13dSStacey Son ret = h2t_freebsd11_nstat(arg2, &st); 161bf14f13dSStacey Son } 162bf14f13dSStacey Son return ret; 163bf14f13dSStacey Son } 164bf14f13dSStacey Son 165bf14f13dSStacey Son /* undocummented nfstat(int fd, struct nstat *sb) syscall */ 166bf14f13dSStacey Son static abi_long do_freebsd11_nfstat(abi_long arg1, abi_long arg2) 167bf14f13dSStacey Son { 168bf14f13dSStacey Son abi_long ret; 169bf14f13dSStacey Son struct freebsd11_stat st; 170bf14f13dSStacey Son 171bf14f13dSStacey Son ret = get_errno(freebsd11_nfstat(arg1, &st)); 172bf14f13dSStacey Son if (!is_error(ret)) { 173bf14f13dSStacey Son ret = h2t_freebsd11_nstat(arg2, &st); 174bf14f13dSStacey Son } 175bf14f13dSStacey Son return ret; 176bf14f13dSStacey Son } 177bf14f13dSStacey Son 178bf14f13dSStacey Son /* undocummented nlstat(char *path, struct nstat *ub) syscall */ 179bf14f13dSStacey Son static abi_long do_freebsd11_nlstat(abi_long arg1, abi_long arg2) 180bf14f13dSStacey Son { 181bf14f13dSStacey Son abi_long ret; 182bf14f13dSStacey Son void *p; 183bf14f13dSStacey Son struct freebsd11_stat st; 184bf14f13dSStacey Son 185bf14f13dSStacey Son LOCK_PATH(p, arg1); 186bf14f13dSStacey Son ret = get_errno(freebsd11_nlstat(path(p), &st)); 187bf14f13dSStacey Son UNLOCK_PATH(p, arg1); 188bf14f13dSStacey Son if (!is_error(ret)) { 189bf14f13dSStacey Son ret = h2t_freebsd11_nstat(arg2, &st); 190bf14f13dSStacey Son } 191bf14f13dSStacey Son return ret; 192bf14f13dSStacey Son } 193bf14f13dSStacey Son 194db8ee08fSStacey Son /* getfh(2) */ 195db8ee08fSStacey Son static abi_long do_freebsd_getfh(abi_long arg1, abi_long arg2) 196db8ee08fSStacey Son { 197db8ee08fSStacey Son abi_long ret; 198db8ee08fSStacey Son void *p; 199db8ee08fSStacey Son fhandle_t host_fh; 200db8ee08fSStacey Son 201db8ee08fSStacey Son LOCK_PATH(p, arg1); 202db8ee08fSStacey Son ret = get_errno(getfh(path(p), &host_fh)); 203db8ee08fSStacey Son UNLOCK_PATH(p, arg1); 204db8ee08fSStacey Son if (is_error(ret)) { 205db8ee08fSStacey Son return ret; 206db8ee08fSStacey Son } 207db8ee08fSStacey Son return h2t_freebsd_fhandle(arg2, &host_fh); 208db8ee08fSStacey Son } 209db8ee08fSStacey Son 210db8ee08fSStacey Son /* lgetfh(2) */ 211db8ee08fSStacey Son static inline abi_long do_freebsd_lgetfh(abi_long arg1, abi_long arg2) 212db8ee08fSStacey Son { 213db8ee08fSStacey Son abi_long ret; 214db8ee08fSStacey Son void *p; 215db8ee08fSStacey Son fhandle_t host_fh; 216db8ee08fSStacey Son 217db8ee08fSStacey Son LOCK_PATH(p, arg1); 218db8ee08fSStacey Son ret = get_errno(lgetfh(path(p), &host_fh)); 219db8ee08fSStacey Son UNLOCK_PATH(p, arg1); 220db8ee08fSStacey Son if (is_error(ret)) { 221db8ee08fSStacey Son return ret; 222db8ee08fSStacey Son } 223db8ee08fSStacey Son return h2t_freebsd_fhandle(arg2, &host_fh); 224db8ee08fSStacey Son } 225db8ee08fSStacey Son 226db8ee08fSStacey Son /* fhopen(2) */ 227db8ee08fSStacey Son static inline abi_long do_freebsd_fhopen(abi_long arg1, abi_long arg2) 228db8ee08fSStacey Son { 229db8ee08fSStacey Son abi_long ret; 230db8ee08fSStacey Son fhandle_t host_fh; 231db8ee08fSStacey Son 232db8ee08fSStacey Son ret = t2h_freebsd_fhandle(&host_fh, arg1); 233db8ee08fSStacey Son if (is_error(ret)) { 234db8ee08fSStacey Son return ret; 235db8ee08fSStacey Son } 236db8ee08fSStacey Son 237db8ee08fSStacey Son return get_errno(fhopen(&host_fh, arg2)); 238db8ee08fSStacey Son } 239db8ee08fSStacey Son 240db8ee08fSStacey Son /* fhstat(2) */ 24133d73068SMichal Meloun static inline abi_long do_freebsd11_fhstat(abi_long arg1, abi_long arg2) 24233d73068SMichal Meloun { 24333d73068SMichal Meloun abi_long ret; 24433d73068SMichal Meloun fhandle_t host_fh; 24533d73068SMichal Meloun struct freebsd11_stat host_sb; 24633d73068SMichal Meloun 24733d73068SMichal Meloun ret = t2h_freebsd_fhandle(&host_fh, arg1); 24833d73068SMichal Meloun if (is_error(ret)) { 24933d73068SMichal Meloun return ret; 25033d73068SMichal Meloun } 25133d73068SMichal Meloun ret = get_errno(freebsd11_fhstat(&host_fh, &host_sb)); 25233d73068SMichal Meloun if (is_error(ret)) { 25333d73068SMichal Meloun return ret; 25433d73068SMichal Meloun } 25533d73068SMichal Meloun return h2t_freebsd11_stat(arg2, &host_sb); 25633d73068SMichal Meloun } 25733d73068SMichal Meloun 25833d73068SMichal Meloun /* fhstat(2) */ 259db8ee08fSStacey Son static inline abi_long do_freebsd_fhstat(abi_long arg1, abi_long arg2) 260db8ee08fSStacey Son { 261db8ee08fSStacey Son abi_long ret; 262db8ee08fSStacey Son fhandle_t host_fh; 263db8ee08fSStacey Son struct stat host_sb; 264db8ee08fSStacey Son 265db8ee08fSStacey Son ret = t2h_freebsd_fhandle(&host_fh, arg1); 266db8ee08fSStacey Son if (is_error(ret)) { 267db8ee08fSStacey Son return ret; 268db8ee08fSStacey Son } 269db8ee08fSStacey Son ret = get_errno(fhstat(&host_fh, &host_sb)); 270db8ee08fSStacey Son if (is_error(ret)) { 271db8ee08fSStacey Son return ret; 272db8ee08fSStacey Son } 273db8ee08fSStacey Son return h2t_freebsd_stat(arg2, &host_sb); 274db8ee08fSStacey Son } 275db8ee08fSStacey Son 276db8ee08fSStacey Son /* fhstatfs(2) */ 27733d73068SMichal Meloun static inline abi_long do_freebsd11_fhstatfs(abi_ulong target_fhp_addr, 27833d73068SMichal Meloun abi_ulong target_stfs_addr) 27933d73068SMichal Meloun { 28033d73068SMichal Meloun abi_long ret; 28133d73068SMichal Meloun fhandle_t host_fh; 28233d73068SMichal Meloun struct freebsd11_statfs host_stfs; 28333d73068SMichal Meloun 28433d73068SMichal Meloun ret = t2h_freebsd_fhandle(&host_fh, target_fhp_addr); 28533d73068SMichal Meloun if (is_error(ret)) { 28633d73068SMichal Meloun return ret; 28733d73068SMichal Meloun } 28833d73068SMichal Meloun ret = get_errno(freebsd11_fhstatfs(&host_fh, &host_stfs)); 28933d73068SMichal Meloun if (is_error(ret)) { 29033d73068SMichal Meloun return ret; 29133d73068SMichal Meloun } 29233d73068SMichal Meloun return h2t_freebsd11_statfs(target_stfs_addr, &host_stfs); 29333d73068SMichal Meloun } 29433d73068SMichal Meloun 29533d73068SMichal Meloun /* fhstatfs(2) */ 296db8ee08fSStacey Son static inline abi_long do_freebsd_fhstatfs(abi_ulong target_fhp_addr, 297db8ee08fSStacey Son abi_ulong target_stfs_addr) 298db8ee08fSStacey Son { 299db8ee08fSStacey Son abi_long ret; 300db8ee08fSStacey Son fhandle_t host_fh; 301db8ee08fSStacey Son struct statfs host_stfs; 302db8ee08fSStacey Son 303db8ee08fSStacey Son ret = t2h_freebsd_fhandle(&host_fh, target_fhp_addr); 304db8ee08fSStacey Son if (is_error(ret)) { 305db8ee08fSStacey Son return ret; 306db8ee08fSStacey Son } 307db8ee08fSStacey Son ret = get_errno(fhstatfs(&host_fh, &host_stfs)); 308db8ee08fSStacey Son if (is_error(ret)) { 309db8ee08fSStacey Son return ret; 310db8ee08fSStacey Son } 311db8ee08fSStacey Son return h2t_freebsd_statfs(target_stfs_addr, &host_stfs); 312db8ee08fSStacey Son } 313db8ee08fSStacey Son 314191fe50dSStacey Son /* statfs(2) */ 315196da9d3SMichal Meloun static inline abi_long do_freebsd11_statfs(abi_long arg1, abi_long arg2) 316196da9d3SMichal Meloun { 317196da9d3SMichal Meloun abi_long ret; 318196da9d3SMichal Meloun void *p; 319196da9d3SMichal Meloun struct freebsd11_statfs host_stfs; 320196da9d3SMichal Meloun 321196da9d3SMichal Meloun LOCK_PATH(p, arg1); 322196da9d3SMichal Meloun ret = get_errno(freebsd11_statfs(path(p), &host_stfs)); 323196da9d3SMichal Meloun UNLOCK_PATH(p, arg1); 324196da9d3SMichal Meloun if (is_error(ret)) { 325196da9d3SMichal Meloun return ret; 326196da9d3SMichal Meloun } 327196da9d3SMichal Meloun 328196da9d3SMichal Meloun return h2t_freebsd11_statfs(arg2, &host_stfs); 329196da9d3SMichal Meloun } 330196da9d3SMichal Meloun 331196da9d3SMichal Meloun /* statfs(2) */ 332191fe50dSStacey Son static inline abi_long do_freebsd_statfs(abi_long arg1, abi_long arg2) 333191fe50dSStacey Son { 334191fe50dSStacey Son abi_long ret; 335191fe50dSStacey Son void *p; 336191fe50dSStacey Son struct statfs host_stfs; 337191fe50dSStacey Son 338191fe50dSStacey Son LOCK_PATH(p, arg1); 339191fe50dSStacey Son ret = get_errno(statfs(path(p), &host_stfs)); 340191fe50dSStacey Son UNLOCK_PATH(p, arg1); 341191fe50dSStacey Son if (is_error(ret)) { 342191fe50dSStacey Son return ret; 343191fe50dSStacey Son } 344191fe50dSStacey Son 345191fe50dSStacey Son return h2t_freebsd_statfs(arg2, &host_stfs); 346191fe50dSStacey Son } 347191fe50dSStacey Son 348191fe50dSStacey Son /* fstatfs(2) */ 349196da9d3SMichal Meloun static inline abi_long do_freebsd11_fstatfs(abi_long fd, abi_ulong target_addr) 350196da9d3SMichal Meloun { 351196da9d3SMichal Meloun abi_long ret; 352196da9d3SMichal Meloun struct freebsd11_statfs host_stfs; 353196da9d3SMichal Meloun 354196da9d3SMichal Meloun ret = get_errno(freebsd11_fstatfs(fd, &host_stfs)); 355196da9d3SMichal Meloun if (is_error(ret)) { 356196da9d3SMichal Meloun return ret; 357196da9d3SMichal Meloun } 358196da9d3SMichal Meloun 359196da9d3SMichal Meloun return h2t_freebsd11_statfs(target_addr, &host_stfs); 360196da9d3SMichal Meloun } 361196da9d3SMichal Meloun 362196da9d3SMichal Meloun /* fstatfs(2) */ 363191fe50dSStacey Son static inline abi_long do_freebsd_fstatfs(abi_long fd, abi_ulong target_addr) 364191fe50dSStacey Son { 365191fe50dSStacey Son abi_long ret; 366191fe50dSStacey Son struct statfs host_stfs; 367191fe50dSStacey Son 368191fe50dSStacey Son ret = get_errno(fstatfs(fd, &host_stfs)); 369191fe50dSStacey Son if (is_error(ret)) { 370191fe50dSStacey Son return ret; 371191fe50dSStacey Son } 372191fe50dSStacey Son 373191fe50dSStacey Son return h2t_freebsd_statfs(target_addr, &host_stfs); 374191fe50dSStacey Son } 375191fe50dSStacey Son 376191fe50dSStacey Son /* getfsstat(2) */ 377196da9d3SMichal Meloun static inline abi_long do_freebsd11_getfsstat(abi_ulong target_addr, 378196da9d3SMichal Meloun abi_long bufsize, abi_long flags) 379196da9d3SMichal Meloun { 380196da9d3SMichal Meloun abi_long ret; 381196da9d3SMichal Meloun struct freebsd11_statfs *host_stfs; 382196da9d3SMichal Meloun int count; 383196da9d3SMichal Meloun long host_bufsize; 384196da9d3SMichal Meloun 385196da9d3SMichal Meloun count = bufsize / sizeof(struct target_freebsd11_statfs); 386196da9d3SMichal Meloun 387196da9d3SMichal Meloun /* if user buffer is NULL then return number of mounted FS's */ 388196da9d3SMichal Meloun if (target_addr == 0 || count == 0) { 389196da9d3SMichal Meloun return get_errno(freebsd11_getfsstat(NULL, 0, flags)); 390196da9d3SMichal Meloun } 391196da9d3SMichal Meloun 392196da9d3SMichal Meloun /* XXX check count to be reasonable */ 393196da9d3SMichal Meloun host_bufsize = sizeof(struct freebsd11_statfs) * count; 394196da9d3SMichal Meloun host_stfs = alloca(host_bufsize); 395196da9d3SMichal Meloun if (!host_stfs) { 396196da9d3SMichal Meloun return -TARGET_EINVAL; 397196da9d3SMichal Meloun } 398196da9d3SMichal Meloun 399196da9d3SMichal Meloun ret = count = get_errno(freebsd11_getfsstat(host_stfs, host_bufsize, flags)); 400196da9d3SMichal Meloun if (is_error(ret)) { 401196da9d3SMichal Meloun return ret; 402196da9d3SMichal Meloun } 403196da9d3SMichal Meloun 404196da9d3SMichal Meloun while (count--) { 405196da9d3SMichal Meloun if (h2t_freebsd11_statfs((target_addr + 406196da9d3SMichal Meloun (count * sizeof(struct target_freebsd11_statfs))), 407196da9d3SMichal Meloun &host_stfs[count])) { 408196da9d3SMichal Meloun return -TARGET_EFAULT; 409196da9d3SMichal Meloun } 410196da9d3SMichal Meloun } 411196da9d3SMichal Meloun return ret; 412196da9d3SMichal Meloun } 413196da9d3SMichal Meloun 414196da9d3SMichal Meloun /* getfsstat(2) */ 415191fe50dSStacey Son static inline abi_long do_freebsd_getfsstat(abi_ulong target_addr, 416191fe50dSStacey Son abi_long bufsize, abi_long flags) 417191fe50dSStacey Son { 418191fe50dSStacey Son abi_long ret; 419191fe50dSStacey Son struct statfs *host_stfs; 420191fe50dSStacey Son int count; 421191fe50dSStacey Son long host_bufsize; 422191fe50dSStacey Son 423191fe50dSStacey Son count = bufsize / sizeof(struct target_statfs); 424191fe50dSStacey Son 425191fe50dSStacey Son /* if user buffer is NULL then return number of mounted FS's */ 426191fe50dSStacey Son if (target_addr == 0 || count == 0) { 427191fe50dSStacey Son return get_errno(freebsd11_getfsstat(NULL, 0, flags)); 428191fe50dSStacey Son } 429191fe50dSStacey Son 430191fe50dSStacey Son /* XXX check count to be reasonable */ 431191fe50dSStacey Son host_bufsize = sizeof(struct statfs) * count; 432191fe50dSStacey Son host_stfs = alloca(host_bufsize); 433191fe50dSStacey Son if (!host_stfs) { 434191fe50dSStacey Son return -TARGET_EINVAL; 435191fe50dSStacey Son } 436191fe50dSStacey Son 437191fe50dSStacey Son ret = count = get_errno(getfsstat(host_stfs, host_bufsize, flags)); 438191fe50dSStacey Son if (is_error(ret)) { 439191fe50dSStacey Son return ret; 440191fe50dSStacey Son } 441191fe50dSStacey Son 442191fe50dSStacey Son while (count--) { 443191fe50dSStacey Son if (h2t_freebsd_statfs((target_addr + 444191fe50dSStacey Son (count * sizeof(struct target_statfs))), 445191fe50dSStacey Son &host_stfs[count])) { 446191fe50dSStacey Son return -TARGET_EFAULT; 447191fe50dSStacey Son } 448191fe50dSStacey Son } 449191fe50dSStacey Son return ret; 450191fe50dSStacey Son } 451191fe50dSStacey Son 45221344452SStacey Son /* getdents(2) */ 45321344452SStacey Son static inline abi_long do_freebsd11_getdents(abi_long arg1, 45421344452SStacey Son abi_ulong arg2, abi_long nbytes) 45521344452SStacey Son { 45621344452SStacey Son abi_long ret; 45721344452SStacey Son struct freebsd11_dirent *dirp; 45821344452SStacey Son 45921344452SStacey Son dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0); 46021344452SStacey Son if (dirp == NULL) { 46121344452SStacey Son return -TARGET_EFAULT; 46221344452SStacey Son } 46321344452SStacey Son ret = get_errno(freebsd11_getdents(arg1, (char *)dirp, nbytes)); 46421344452SStacey Son if (!is_error(ret)) { 46521344452SStacey Son struct freebsd11_dirent *de; 46621344452SStacey Son int len = ret; 46721344452SStacey Son int reclen; 46821344452SStacey Son 46921344452SStacey Son de = dirp; 47021344452SStacey Son while (len > 0) { 47121344452SStacey Son reclen = de->d_reclen; 47221344452SStacey Son if (reclen > len) { 47321344452SStacey Son return -TARGET_EFAULT; 47421344452SStacey Son } 47521344452SStacey Son de->d_reclen = tswap16(reclen); 47621344452SStacey Son de->d_fileno = tswap32(de->d_fileno); 47721344452SStacey Son len -= reclen; 47821344452SStacey Son } 47921344452SStacey Son } 48021344452SStacey Son return ret; 48121344452SStacey Son } 48221344452SStacey Son 48321344452SStacey Son /* getdirecentries(2) */ 48491a98c9bSMichal Meloun static inline abi_long do_freebsd11_getdirentries(abi_long arg1, 48591a98c9bSMichal Meloun abi_ulong arg2, abi_long nbytes, abi_ulong arg4) 48691a98c9bSMichal Meloun { 48791a98c9bSMichal Meloun abi_long ret; 48891a98c9bSMichal Meloun struct freebsd11_dirent *dirp; 48991a98c9bSMichal Meloun long basep; 49091a98c9bSMichal Meloun 49191a98c9bSMichal Meloun dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0); 49291a98c9bSMichal Meloun if (dirp == NULL) { 49391a98c9bSMichal Meloun return -TARGET_EFAULT; 49491a98c9bSMichal Meloun } 49591a98c9bSMichal Meloun ret = get_errno(freebsd11_getdirentries(arg1, (char *)dirp, nbytes, &basep)); 49691a98c9bSMichal Meloun if (!is_error(ret)) { 49791a98c9bSMichal Meloun struct freebsd11_dirent *de; 49891a98c9bSMichal Meloun int len = ret; 49991a98c9bSMichal Meloun int reclen; 50091a98c9bSMichal Meloun 50191a98c9bSMichal Meloun de = dirp; 50291a98c9bSMichal Meloun while (len > 0) { 50391a98c9bSMichal Meloun reclen = de->d_reclen; 50491a98c9bSMichal Meloun if (reclen > len) { 50591a98c9bSMichal Meloun return -TARGET_EFAULT; 50691a98c9bSMichal Meloun } 50791a98c9bSMichal Meloun de->d_reclen = tswap16(reclen); 50891a98c9bSMichal Meloun de->d_fileno = tswap32(de->d_fileno); 50991a98c9bSMichal Meloun len -= reclen; 51091a98c9bSMichal Meloun de = (struct freebsd11_dirent *)((void *)de + reclen); 51191a98c9bSMichal Meloun } 51291a98c9bSMichal Meloun } 51391a98c9bSMichal Meloun unlock_user(dirp, arg2, ret); 51491a98c9bSMichal Meloun if (arg4) { 51591a98c9bSMichal Meloun if (put_user(basep, arg4, abi_ulong)) { 51691a98c9bSMichal Meloun return -TARGET_EFAULT; 51791a98c9bSMichal Meloun } 51891a98c9bSMichal Meloun } 51991a98c9bSMichal Meloun return ret; 52091a98c9bSMichal Meloun } 52191a98c9bSMichal Meloun 52291a98c9bSMichal Meloun /* getdirecentries(2) */ 52321344452SStacey Son static inline abi_long do_freebsd_getdirentries(abi_long arg1, 52421344452SStacey Son abi_ulong arg2, abi_long nbytes, abi_ulong arg4) 52521344452SStacey Son { 52621344452SStacey Son abi_long ret; 52721344452SStacey Son struct dirent *dirp; 52821344452SStacey Son long basep; 52921344452SStacey Son 53021344452SStacey Son dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0); 53121344452SStacey Son if (dirp == NULL) { 53221344452SStacey Son return -TARGET_EFAULT; 53321344452SStacey Son } 53421344452SStacey Son ret = get_errno(getdirentries(arg1, (char *)dirp, nbytes, &basep)); 53521344452SStacey Son if (!is_error(ret)) { 53621344452SStacey Son struct dirent *de; 53721344452SStacey Son int len = ret; 53821344452SStacey Son int reclen; 53921344452SStacey Son 54021344452SStacey Son de = dirp; 54121344452SStacey Son while (len > 0) { 54221344452SStacey Son reclen = de->d_reclen; 54321344452SStacey Son if (reclen > len) { 54421344452SStacey Son return -TARGET_EFAULT; 54521344452SStacey Son } 54621344452SStacey Son de->d_fileno = tswap64(de->d_fileno); 54721344452SStacey Son de->d_off = tswap64(de->d_off); 54821344452SStacey Son de->d_reclen = tswap16(de->d_reclen); 54921344452SStacey Son de->d_namlen = tswap16(de->d_namlen); 55021344452SStacey Son len -= reclen; 55121344452SStacey Son de = (struct dirent *)((void *)de + reclen); 55221344452SStacey Son } 55321344452SStacey Son } 55421344452SStacey Son unlock_user(dirp, arg2, ret); 55521344452SStacey Son if (arg4) { 55621344452SStacey Son if (put_user(basep, arg4, abi_ulong)) { 55721344452SStacey Son return -TARGET_EFAULT; 55821344452SStacey Son } 55921344452SStacey Son } 56021344452SStacey Son return ret; 56121344452SStacey Son } 56221344452SStacey Son 563c0023204SStacey Son /* fcntl(2) */ 564c0023204SStacey Son static inline abi_long do_freebsd_fcntl(abi_long arg1, abi_long arg2, 565c0023204SStacey Son abi_ulong arg3) 566c0023204SStacey Son { 567c0023204SStacey Son abi_long ret; 568c0023204SStacey Son int host_cmd; 569c0023204SStacey Son struct flock fl; 570c0023204SStacey Son struct target_freebsd_flock *target_fl; 571c0023204SStacey Son 572c0023204SStacey Son host_cmd = target_to_host_fcntl_cmd(arg2); 573c0023204SStacey Son if (host_cmd < 0) { 574c0023204SStacey Son return host_cmd; 575c0023204SStacey Son } 576c0023204SStacey Son switch (arg2) { 577c0023204SStacey Son case TARGET_F_GETLK: 578c0023204SStacey Son if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) { 579c0023204SStacey Son return -TARGET_EFAULT; 580c0023204SStacey Son } 581c0023204SStacey Son __get_user(fl.l_type, &target_fl->l_type); 582c0023204SStacey Son __get_user(fl.l_whence, &target_fl->l_whence); 583c0023204SStacey Son __get_user(fl.l_start, &target_fl->l_start); 584c0023204SStacey Son __get_user(fl.l_len, &target_fl->l_len); 585c0023204SStacey Son __get_user(fl.l_pid, &target_fl->l_pid); 586c0023204SStacey Son __get_user(fl.l_sysid, &target_fl->l_sysid); 587c0023204SStacey Son unlock_user_struct(target_fl, arg3, 0); 588c0023204SStacey Son ret = get_errno(safe_fcntl(arg1, host_cmd, &fl)); 589c0023204SStacey Son if (!is_error(ret)) { 590c0023204SStacey Son if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0)) { 591c0023204SStacey Son return -TARGET_EFAULT; 592c0023204SStacey Son } 593c0023204SStacey Son __put_user(fl.l_type, &target_fl->l_type); 594c0023204SStacey Son __put_user(fl.l_whence, &target_fl->l_whence); 595c0023204SStacey Son __put_user(fl.l_start, &target_fl->l_start); 596c0023204SStacey Son __put_user(fl.l_len, &target_fl->l_len); 597c0023204SStacey Son __put_user(fl.l_pid, &target_fl->l_pid); 598c0023204SStacey Son __put_user(fl.l_sysid, &target_fl->l_sysid); 599c0023204SStacey Son unlock_user_struct(target_fl, arg3, 1); 600c0023204SStacey Son } 601c0023204SStacey Son break; 602c0023204SStacey Son 603c0023204SStacey Son case TARGET_F_SETLK: 604c0023204SStacey Son case TARGET_F_SETLKW: 605c0023204SStacey Son if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) { 606c0023204SStacey Son return -TARGET_EFAULT; 607c0023204SStacey Son } 608c0023204SStacey Son __get_user(fl.l_type, &target_fl->l_type); 609c0023204SStacey Son __get_user(fl.l_whence, &target_fl->l_whence); 610c0023204SStacey Son __get_user(fl.l_start, &target_fl->l_start); 611c0023204SStacey Son __get_user(fl.l_len, &target_fl->l_len); 612c0023204SStacey Son __get_user(fl.l_pid, &target_fl->l_pid); 613c0023204SStacey Son __get_user(fl.l_sysid, &target_fl->l_sysid); 614c0023204SStacey Son unlock_user_struct(target_fl, arg3, 0); 615c0023204SStacey Son ret = get_errno(safe_fcntl(arg1, host_cmd, &fl)); 616c0023204SStacey Son break; 617c0023204SStacey Son 618c0023204SStacey Son case TARGET_F_DUPFD: 619c0023204SStacey Son case TARGET_F_DUP2FD: 620c0023204SStacey Son case TARGET_F_GETOWN: 621c0023204SStacey Son case TARGET_F_SETOWN: 622c0023204SStacey Son case TARGET_F_GETFD: 623c0023204SStacey Son case TARGET_F_SETFD: 624c0023204SStacey Son case TARGET_F_GETFL: 625c0023204SStacey Son case TARGET_F_SETFL: 626c0023204SStacey Son case TARGET_F_READAHEAD: 627c0023204SStacey Son case TARGET_F_RDAHEAD: 628c0023204SStacey Son case TARGET_F_ADD_SEALS: 629c0023204SStacey Son case TARGET_F_GET_SEALS: 630c0023204SStacey Son default: 631c0023204SStacey Son ret = get_errno(safe_fcntl(arg1, host_cmd, arg3)); 632c0023204SStacey Son break; 633c0023204SStacey Son } 634c0023204SStacey Son return ret; 635c0023204SStacey Son } 636c0023204SStacey Son 637*292bfd0fSMikaël Urankar #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300080 638*292bfd0fSMikaël Urankar extern int __realpathat(int fd, const char *path, char *buf, size_t size, 639*292bfd0fSMikaël Urankar int flags); 640*292bfd0fSMikaël Urankar /* https://svnweb.freebsd.org/base?view=revision&revision=358172 */ 641*292bfd0fSMikaël Urankar /* no man page */ 642*292bfd0fSMikaël Urankar static inline abi_long do_freebsd_realpathat(abi_long arg1, abi_long arg2, 643*292bfd0fSMikaël Urankar abi_long arg3, abi_long arg4, abi_long arg5) 644*292bfd0fSMikaël Urankar { 645*292bfd0fSMikaël Urankar abi_long ret; 646*292bfd0fSMikaël Urankar void *p, *b; 647*292bfd0fSMikaël Urankar 648*292bfd0fSMikaël Urankar LOCK_PATH(p, arg2); 649*292bfd0fSMikaël Urankar b = lock_user(VERIFY_WRITE, arg3, arg4, 0); 650*292bfd0fSMikaël Urankar if (b == NULL) { 651*292bfd0fSMikaël Urankar UNLOCK_PATH(p, arg2); 652*292bfd0fSMikaël Urankar return -TARGET_EFAULT; 653*292bfd0fSMikaël Urankar } 654*292bfd0fSMikaël Urankar 655*292bfd0fSMikaël Urankar ret = get_errno(__realpathat(arg1, p, b, arg4, arg5)); 656*292bfd0fSMikaël Urankar UNLOCK_PATH(p, arg2); 657*292bfd0fSMikaël Urankar unlock_user(b, arg3, ret); 658*292bfd0fSMikaël Urankar 659*292bfd0fSMikaël Urankar return ret; 660*292bfd0fSMikaël Urankar } 661*292bfd0fSMikaël Urankar #endif 662*292bfd0fSMikaël Urankar 663bf14f13dSStacey Son #endif /* BSD_USER_FREEBSD_OS_STAT_H */ 664