os-stat.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  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. #ifndef BSD_USER_FREEBSD_OS_STAT_H
  20. #define BSD_USER_FREEBSD_OS_STAT_H
  21. int freebsd11_stat(const char *path, struct freebsd11_stat *stat);
  22. __sym_compat(stat, freebsd11_stat, FBSD_1.0);
  23. int freebsd11_lstat(const char *path, struct freebsd11_stat *stat);
  24. __sym_compat(lstat, freebsd11_lstat, FBSD_1.0);
  25. int freebsd11_fstat(int fd, struct freebsd11_stat *stat);
  26. __sym_compat(fstat, freebsd11_fstat, FBSD_1.0);
  27. int freebsd11_fstatat(int fd, const char *path, struct freebsd11_stat *stat,
  28. int flag);
  29. __sym_compat(fstatat, freebsd11_fstatat, FBSD_1.1);
  30. int freebsd11_fhstat(const fhandle_t *fhandle, struct freebsd11_stat *stat);
  31. __sym_compat(fhstat, freebsd11_fhstat, FBSD_1.0);
  32. int freebsd11_getfsstat(struct freebsd11_statfs *buf, long bufsize, int mode);
  33. __sym_compat(getfsstat, freebsd11_getfsstat, FBSD_1.0);
  34. int freebsd11_fhstatfs(const fhandle_t *fhandle, struct freebsd11_statfs * buf);
  35. __sym_compat(fhstatfs, freebsd11_fhstatfs, FBSD_1.0);
  36. int freebsd11_statfs(const char *path, struct freebsd11_statfs *buf);
  37. __sym_compat(statfs, freebsd11_statfs, FBSD_1.0);
  38. int freebsd11_fstatfs(int fd, struct freebsd11_statfs *buf);
  39. __sym_compat(fstatfs, freebsd11_fstatfs, FBSD_1.0);
  40. ssize_t freebsd11_getdirentries(int fd, char *buf, size_t nbytes, off_t *basep);
  41. __sym_compat(getdirentries, freebsd11_getdirentries, FBSD_1.0);
  42. ssize_t freebsd11_getdents(int fd, char *buf, size_t nbytes);
  43. __sym_compat(getdents, freebsd11_getdents, FBSD_1.0);
  44. /* undocumented nstat system calls */
  45. int freebsd11_nstat(const char *path, struct freebsd11_stat *sb);
  46. __sym_compat(nstat, freebsd11_nstat, FBSD_1.0);
  47. int freebsd11_nlstat(const char *path, struct freebsd11_stat *sb);
  48. __sym_compat(nlstat, freebsd11_nlstat, FBSD_1.0);
  49. int freebsd11_nfstat(int fd, struct freebsd11_stat *sb);
  50. __sym_compat(nfstat, freebsd11_nfstat, FBSD_1.0);
  51. /* stat(2) */
  52. static inline abi_long do_freebsd11_stat(abi_long arg1, abi_long arg2)
  53. {
  54. abi_long ret;
  55. void *p;
  56. struct freebsd11_stat st;
  57. LOCK_PATH(p, arg1);
  58. ret = get_errno(freebsd11_stat(path(p), &st));
  59. UNLOCK_PATH(p, arg1);
  60. if (!is_error(ret)) {
  61. ret = h2t_freebsd11_stat(arg2, &st);
  62. }
  63. return ret;
  64. }
  65. /* lstat(2) */
  66. static inline abi_long do_freebsd11_lstat(abi_long arg1, abi_long arg2)
  67. {
  68. abi_long ret;
  69. void *p;
  70. struct freebsd11_stat st;
  71. LOCK_PATH(p, arg1);
  72. ret = get_errno(freebsd11_lstat(path(p), &st));
  73. UNLOCK_PATH(p, arg1);
  74. if (!is_error(ret)) {
  75. ret = h2t_freebsd11_stat(arg2, &st);
  76. }
  77. return ret;
  78. }
  79. /* fstat(2) */
  80. static inline abi_long do_freebsd11_fstat(abi_long arg1, abi_long arg2)
  81. {
  82. abi_long ret;
  83. struct freebsd11_stat st;
  84. ret = get_errno(freebsd11_fstat(arg1, &st));
  85. if (!is_error(ret)) {
  86. ret = h2t_freebsd11_stat(arg2, &st);
  87. }
  88. return ret;
  89. }
  90. /* fstat(2) */
  91. static inline abi_long do_freebsd_fstat(abi_long arg1, abi_long arg2)
  92. {
  93. abi_long ret;
  94. struct stat st;
  95. ret = get_errno(fstat(arg1, &st));
  96. if (!is_error(ret)) {
  97. ret = h2t_freebsd_stat(arg2, &st);
  98. }
  99. return ret;
  100. }
  101. /* fstatat(2) */
  102. static inline abi_long do_freebsd11_fstatat(abi_long arg1, abi_long arg2,
  103. abi_long arg3, abi_long arg4)
  104. {
  105. abi_long ret;
  106. void *p;
  107. struct freebsd11_stat st;
  108. LOCK_PATH(p, arg2);
  109. ret = get_errno(freebsd11_fstatat(arg1, p, &st, arg4));
  110. UNLOCK_PATH(p, arg2);
  111. if (!is_error(ret) && arg3) {
  112. ret = h2t_freebsd11_stat(arg3, &st);
  113. }
  114. return ret;
  115. }
  116. /* fstatat(2) */
  117. static inline abi_long do_freebsd_fstatat(abi_long arg1, abi_long arg2,
  118. abi_long arg3, abi_long arg4)
  119. {
  120. abi_long ret;
  121. void *p;
  122. struct stat st;
  123. LOCK_PATH(p, arg2);
  124. ret = get_errno(fstatat(arg1, p, &st, arg4));
  125. UNLOCK_PATH(p, arg2);
  126. if (!is_error(ret) && arg3) {
  127. ret = h2t_freebsd_stat(arg3, &st);
  128. }
  129. return ret;
  130. }
  131. /* undocumented nstat(char *path, struct nstat *ub) syscall */
  132. static abi_long do_freebsd11_nstat(abi_long arg1, abi_long arg2)
  133. {
  134. abi_long ret;
  135. void *p;
  136. struct freebsd11_stat st;
  137. LOCK_PATH(p, arg1);
  138. ret = get_errno(freebsd11_nstat(path(p), &st));
  139. UNLOCK_PATH(p, arg1);
  140. if (!is_error(ret)) {
  141. ret = h2t_freebsd11_nstat(arg2, &st);
  142. }
  143. return ret;
  144. }
  145. /* undocumented nfstat(int fd, struct nstat *sb) syscall */
  146. static abi_long do_freebsd11_nfstat(abi_long arg1, abi_long arg2)
  147. {
  148. abi_long ret;
  149. struct freebsd11_stat st;
  150. ret = get_errno(freebsd11_nfstat(arg1, &st));
  151. if (!is_error(ret)) {
  152. ret = h2t_freebsd11_nstat(arg2, &st);
  153. }
  154. return ret;
  155. }
  156. /* undocumented nlstat(char *path, struct nstat *ub) syscall */
  157. static abi_long do_freebsd11_nlstat(abi_long arg1, abi_long arg2)
  158. {
  159. abi_long ret;
  160. void *p;
  161. struct freebsd11_stat st;
  162. LOCK_PATH(p, arg1);
  163. ret = get_errno(freebsd11_nlstat(path(p), &st));
  164. UNLOCK_PATH(p, arg1);
  165. if (!is_error(ret)) {
  166. ret = h2t_freebsd11_nstat(arg2, &st);
  167. }
  168. return ret;
  169. }
  170. /* getfh(2) */
  171. static abi_long do_freebsd_getfh(abi_long arg1, abi_long arg2)
  172. {
  173. abi_long ret;
  174. void *p;
  175. fhandle_t host_fh;
  176. LOCK_PATH(p, arg1);
  177. ret = get_errno(getfh(path(p), &host_fh));
  178. UNLOCK_PATH(p, arg1);
  179. if (is_error(ret)) {
  180. return ret;
  181. }
  182. return h2t_freebsd_fhandle(arg2, &host_fh);
  183. }
  184. /* lgetfh(2) */
  185. static inline abi_long do_freebsd_lgetfh(abi_long arg1, abi_long arg2)
  186. {
  187. abi_long ret;
  188. void *p;
  189. fhandle_t host_fh;
  190. LOCK_PATH(p, arg1);
  191. ret = get_errno(lgetfh(path(p), &host_fh));
  192. UNLOCK_PATH(p, arg1);
  193. if (is_error(ret)) {
  194. return ret;
  195. }
  196. return h2t_freebsd_fhandle(arg2, &host_fh);
  197. }
  198. /* fhopen(2) */
  199. static inline abi_long do_freebsd_fhopen(abi_long arg1, abi_long arg2)
  200. {
  201. abi_long ret;
  202. fhandle_t host_fh;
  203. ret = t2h_freebsd_fhandle(&host_fh, arg1);
  204. if (is_error(ret)) {
  205. return ret;
  206. }
  207. return get_errno(fhopen(&host_fh, arg2));
  208. }
  209. /* fhstat(2) */
  210. static inline abi_long do_freebsd11_fhstat(abi_long arg1, abi_long arg2)
  211. {
  212. abi_long ret;
  213. fhandle_t host_fh;
  214. struct freebsd11_stat host_sb;
  215. ret = t2h_freebsd_fhandle(&host_fh, arg1);
  216. if (is_error(ret)) {
  217. return ret;
  218. }
  219. ret = get_errno(freebsd11_fhstat(&host_fh, &host_sb));
  220. if (is_error(ret)) {
  221. return ret;
  222. }
  223. return h2t_freebsd11_stat(arg2, &host_sb);
  224. }
  225. /* fhstat(2) */
  226. static inline abi_long do_freebsd_fhstat(abi_long arg1, abi_long arg2)
  227. {
  228. abi_long ret;
  229. fhandle_t host_fh;
  230. struct stat host_sb;
  231. ret = t2h_freebsd_fhandle(&host_fh, arg1);
  232. if (is_error(ret)) {
  233. return ret;
  234. }
  235. ret = get_errno(fhstat(&host_fh, &host_sb));
  236. if (is_error(ret)) {
  237. return ret;
  238. }
  239. return h2t_freebsd_stat(arg2, &host_sb);
  240. }
  241. /* fhstatfs(2) */
  242. static inline abi_long do_freebsd11_fhstatfs(abi_ulong target_fhp_addr,
  243. abi_ulong target_stfs_addr)
  244. {
  245. abi_long ret;
  246. fhandle_t host_fh;
  247. struct freebsd11_statfs host_stfs;
  248. ret = t2h_freebsd_fhandle(&host_fh, target_fhp_addr);
  249. if (is_error(ret)) {
  250. return ret;
  251. }
  252. ret = get_errno(freebsd11_fhstatfs(&host_fh, &host_stfs));
  253. if (is_error(ret)) {
  254. return ret;
  255. }
  256. return h2t_freebsd11_statfs(target_stfs_addr, &host_stfs);
  257. }
  258. /* fhstatfs(2) */
  259. static inline abi_long do_freebsd_fhstatfs(abi_ulong target_fhp_addr,
  260. abi_ulong target_stfs_addr)
  261. {
  262. abi_long ret;
  263. fhandle_t host_fh;
  264. struct statfs host_stfs;
  265. ret = t2h_freebsd_fhandle(&host_fh, target_fhp_addr);
  266. if (is_error(ret)) {
  267. return ret;
  268. }
  269. ret = get_errno(fhstatfs(&host_fh, &host_stfs));
  270. if (is_error(ret)) {
  271. return ret;
  272. }
  273. return h2t_freebsd_statfs(target_stfs_addr, &host_stfs);
  274. }
  275. /* statfs(2) */
  276. static inline abi_long do_freebsd11_statfs(abi_long arg1, abi_long arg2)
  277. {
  278. abi_long ret;
  279. void *p;
  280. struct freebsd11_statfs host_stfs;
  281. LOCK_PATH(p, arg1);
  282. ret = get_errno(freebsd11_statfs(path(p), &host_stfs));
  283. UNLOCK_PATH(p, arg1);
  284. if (is_error(ret)) {
  285. return ret;
  286. }
  287. return h2t_freebsd11_statfs(arg2, &host_stfs);
  288. }
  289. /* statfs(2) */
  290. static inline abi_long do_freebsd_statfs(abi_long arg1, abi_long arg2)
  291. {
  292. abi_long ret;
  293. void *p;
  294. struct statfs host_stfs;
  295. LOCK_PATH(p, arg1);
  296. ret = get_errno(statfs(path(p), &host_stfs));
  297. UNLOCK_PATH(p, arg1);
  298. if (is_error(ret)) {
  299. return ret;
  300. }
  301. return h2t_freebsd_statfs(arg2, &host_stfs);
  302. }
  303. /* fstatfs(2) */
  304. static inline abi_long do_freebsd11_fstatfs(abi_long fd, abi_ulong target_addr)
  305. {
  306. abi_long ret;
  307. struct freebsd11_statfs host_stfs;
  308. ret = get_errno(freebsd11_fstatfs(fd, &host_stfs));
  309. if (is_error(ret)) {
  310. return ret;
  311. }
  312. return h2t_freebsd11_statfs(target_addr, &host_stfs);
  313. }
  314. /* fstatfs(2) */
  315. static inline abi_long do_freebsd_fstatfs(abi_long fd, abi_ulong target_addr)
  316. {
  317. abi_long ret;
  318. struct statfs host_stfs;
  319. ret = get_errno(fstatfs(fd, &host_stfs));
  320. if (is_error(ret)) {
  321. return ret;
  322. }
  323. return h2t_freebsd_statfs(target_addr, &host_stfs);
  324. }
  325. /* getfsstat(2) */
  326. static inline abi_long do_freebsd11_getfsstat(abi_ulong target_addr,
  327. abi_long bufsize, abi_long flags)
  328. {
  329. abi_long ret;
  330. struct freebsd11_statfs *host_stfs;
  331. int count;
  332. long host_bufsize;
  333. count = bufsize / sizeof(struct target_freebsd11_statfs);
  334. /* if user buffer is NULL then return number of mounted FS's */
  335. if (target_addr == 0 || count == 0) {
  336. return get_errno(freebsd11_getfsstat(NULL, 0, flags));
  337. }
  338. /* XXX check count to be reasonable */
  339. host_bufsize = sizeof(struct freebsd11_statfs) * count;
  340. host_stfs = alloca(host_bufsize);
  341. if (!host_stfs) {
  342. return -TARGET_EINVAL;
  343. }
  344. ret = count = get_errno(freebsd11_getfsstat(host_stfs, host_bufsize, flags));
  345. if (is_error(ret)) {
  346. return ret;
  347. }
  348. while (count--) {
  349. if (h2t_freebsd11_statfs((target_addr +
  350. (count * sizeof(struct target_freebsd11_statfs))),
  351. &host_stfs[count])) {
  352. return -TARGET_EFAULT;
  353. }
  354. }
  355. return ret;
  356. }
  357. /* getfsstat(2) */
  358. static inline abi_long do_freebsd_getfsstat(abi_ulong target_addr,
  359. abi_long bufsize, abi_long flags)
  360. {
  361. abi_long ret;
  362. struct statfs *host_stfs;
  363. int count;
  364. long host_bufsize;
  365. count = bufsize / sizeof(struct target_statfs);
  366. /* if user buffer is NULL then return number of mounted FS's */
  367. if (target_addr == 0 || count == 0) {
  368. return get_errno(freebsd11_getfsstat(NULL, 0, flags));
  369. }
  370. /* XXX check count to be reasonable */
  371. host_bufsize = sizeof(struct statfs) * count;
  372. host_stfs = alloca(host_bufsize);
  373. if (!host_stfs) {
  374. return -TARGET_EINVAL;
  375. }
  376. ret = count = get_errno(getfsstat(host_stfs, host_bufsize, flags));
  377. if (is_error(ret)) {
  378. return ret;
  379. }
  380. while (count--) {
  381. if (h2t_freebsd_statfs((target_addr +
  382. (count * sizeof(struct target_statfs))),
  383. &host_stfs[count])) {
  384. return -TARGET_EFAULT;
  385. }
  386. }
  387. return ret;
  388. }
  389. /* getdents(2) */
  390. static inline abi_long do_freebsd11_getdents(abi_long arg1,
  391. abi_ulong arg2, abi_long nbytes)
  392. {
  393. abi_long ret;
  394. struct freebsd11_dirent *dirp;
  395. dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0);
  396. if (dirp == NULL) {
  397. return -TARGET_EFAULT;
  398. }
  399. ret = get_errno(freebsd11_getdents(arg1, (char *)dirp, nbytes));
  400. if (!is_error(ret)) {
  401. struct freebsd11_dirent *de;
  402. int len = ret;
  403. int reclen;
  404. de = dirp;
  405. while (len > 0) {
  406. reclen = de->d_reclen;
  407. if (reclen > len) {
  408. return -TARGET_EFAULT;
  409. }
  410. de->d_reclen = tswap16(reclen);
  411. de->d_fileno = tswap32(de->d_fileno);
  412. len -= reclen;
  413. }
  414. }
  415. return ret;
  416. }
  417. /* getdirecentries(2) */
  418. static inline abi_long do_freebsd11_getdirentries(abi_long arg1,
  419. abi_ulong arg2, abi_long nbytes, abi_ulong arg4)
  420. {
  421. abi_long ret;
  422. struct freebsd11_dirent *dirp;
  423. long basep;
  424. dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0);
  425. if (dirp == NULL) {
  426. return -TARGET_EFAULT;
  427. }
  428. ret = get_errno(freebsd11_getdirentries(arg1, (char *)dirp, nbytes, &basep));
  429. if (!is_error(ret)) {
  430. struct freebsd11_dirent *de;
  431. int len = ret;
  432. int reclen;
  433. de = dirp;
  434. while (len > 0) {
  435. reclen = de->d_reclen;
  436. if (reclen > len) {
  437. return -TARGET_EFAULT;
  438. }
  439. de->d_reclen = tswap16(reclen);
  440. de->d_fileno = tswap32(de->d_fileno);
  441. len -= reclen;
  442. de = (struct freebsd11_dirent *)((void *)de + reclen);
  443. }
  444. }
  445. unlock_user(dirp, arg2, ret);
  446. if (arg4) {
  447. if (put_user(basep, arg4, abi_ulong)) {
  448. return -TARGET_EFAULT;
  449. }
  450. }
  451. return ret;
  452. }
  453. /* getdirecentries(2) */
  454. static inline abi_long do_freebsd_getdirentries(abi_long arg1,
  455. abi_ulong arg2, abi_long nbytes, abi_ulong arg4)
  456. {
  457. abi_long ret;
  458. struct dirent *dirp;
  459. long basep;
  460. dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0);
  461. if (dirp == NULL) {
  462. return -TARGET_EFAULT;
  463. }
  464. ret = get_errno(getdirentries(arg1, (char *)dirp, nbytes, &basep));
  465. if (!is_error(ret)) {
  466. struct dirent *de;
  467. int len = ret;
  468. int reclen;
  469. de = dirp;
  470. while (len > 0) {
  471. reclen = de->d_reclen;
  472. if (reclen > len) {
  473. return -TARGET_EFAULT;
  474. }
  475. de->d_fileno = tswap64(de->d_fileno);
  476. de->d_off = tswap64(de->d_off);
  477. de->d_reclen = tswap16(de->d_reclen);
  478. de->d_namlen = tswap16(de->d_namlen);
  479. len -= reclen;
  480. de = (struct dirent *)((void *)de + reclen);
  481. }
  482. }
  483. unlock_user(dirp, arg2, ret);
  484. if (arg4) {
  485. if (put_user(basep, arg4, abi_ulong)) {
  486. return -TARGET_EFAULT;
  487. }
  488. }
  489. return ret;
  490. }
  491. /* fcntl(2) */
  492. static inline abi_long do_freebsd_fcntl(abi_long arg1, abi_long arg2,
  493. abi_ulong arg3)
  494. {
  495. abi_long ret;
  496. int host_cmd;
  497. struct flock fl;
  498. struct target_freebsd_flock *target_fl;
  499. host_cmd = target_to_host_fcntl_cmd(arg2);
  500. if (host_cmd < 0) {
  501. return host_cmd;
  502. }
  503. switch (arg2) {
  504. case TARGET_F_GETLK:
  505. if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) {
  506. return -TARGET_EFAULT;
  507. }
  508. __get_user(fl.l_type, &target_fl->l_type);
  509. __get_user(fl.l_whence, &target_fl->l_whence);
  510. __get_user(fl.l_start, &target_fl->l_start);
  511. __get_user(fl.l_len, &target_fl->l_len);
  512. __get_user(fl.l_pid, &target_fl->l_pid);
  513. __get_user(fl.l_sysid, &target_fl->l_sysid);
  514. unlock_user_struct(target_fl, arg3, 0);
  515. ret = get_errno(safe_fcntl(arg1, host_cmd, &fl));
  516. if (!is_error(ret)) {
  517. if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0)) {
  518. return -TARGET_EFAULT;
  519. }
  520. __put_user(fl.l_type, &target_fl->l_type);
  521. __put_user(fl.l_whence, &target_fl->l_whence);
  522. __put_user(fl.l_start, &target_fl->l_start);
  523. __put_user(fl.l_len, &target_fl->l_len);
  524. __put_user(fl.l_pid, &target_fl->l_pid);
  525. __put_user(fl.l_sysid, &target_fl->l_sysid);
  526. unlock_user_struct(target_fl, arg3, 1);
  527. }
  528. break;
  529. case TARGET_F_SETLK:
  530. case TARGET_F_SETLKW:
  531. if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) {
  532. return -TARGET_EFAULT;
  533. }
  534. __get_user(fl.l_type, &target_fl->l_type);
  535. __get_user(fl.l_whence, &target_fl->l_whence);
  536. __get_user(fl.l_start, &target_fl->l_start);
  537. __get_user(fl.l_len, &target_fl->l_len);
  538. __get_user(fl.l_pid, &target_fl->l_pid);
  539. __get_user(fl.l_sysid, &target_fl->l_sysid);
  540. unlock_user_struct(target_fl, arg3, 0);
  541. ret = get_errno(safe_fcntl(arg1, host_cmd, &fl));
  542. break;
  543. case TARGET_F_DUPFD:
  544. case TARGET_F_DUP2FD:
  545. case TARGET_F_GETOWN:
  546. case TARGET_F_SETOWN:
  547. case TARGET_F_GETFD:
  548. case TARGET_F_SETFD:
  549. case TARGET_F_GETFL:
  550. case TARGET_F_SETFL:
  551. case TARGET_F_READAHEAD:
  552. case TARGET_F_RDAHEAD:
  553. case TARGET_F_ADD_SEALS:
  554. case TARGET_F_GET_SEALS:
  555. default:
  556. ret = get_errno(safe_fcntl(arg1, host_cmd, arg3));
  557. break;
  558. }
  559. return ret;
  560. }
  561. #if defined(__FreeBSD_version) && __FreeBSD_version >= 1300080
  562. extern int __realpathat(int fd, const char *path, char *buf, size_t size,
  563. int flags);
  564. /* https://svnweb.freebsd.org/base?view=revision&revision=358172 */
  565. /* no man page */
  566. static inline abi_long do_freebsd_realpathat(abi_long arg1, abi_long arg2,
  567. abi_long arg3, abi_long arg4, abi_long arg5)
  568. {
  569. abi_long ret;
  570. void *p, *b;
  571. LOCK_PATH(p, arg2);
  572. b = lock_user(VERIFY_WRITE, arg3, arg4, 0);
  573. if (b == NULL) {
  574. UNLOCK_PATH(p, arg2);
  575. return -TARGET_EFAULT;
  576. }
  577. ret = get_errno(__realpathat(arg1, p, b, arg4, arg5));
  578. UNLOCK_PATH(p, arg2);
  579. unlock_user(b, arg3, ret);
  580. return ret;
  581. }
  582. #endif
  583. #endif /* BSD_USER_FREEBSD_OS_STAT_H */