qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

bsd-file.h (21127B)


      1 /*
      2  *  file 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_FILE_H
     21 #define BSD_FILE_H
     22 
     23 #include "qemu/path.h"
     24 
     25 #define LOCK_PATH(p, arg)                   \
     26 do {                                        \
     27     (p) = lock_user_string(arg);            \
     28     if ((p) == NULL) {                      \
     29         return -TARGET_EFAULT;              \
     30     }                                       \
     31 } while (0)
     32 
     33 #define UNLOCK_PATH(p, arg)     unlock_user(p, arg, 0)
     34 
     35 #define LOCK_PATH2(p1, arg1, p2, arg2)      \
     36 do {                                        \
     37     (p1) = lock_user_string(arg1);          \
     38     if ((p1) == NULL) {                     \
     39         return -TARGET_EFAULT;              \
     40     }                                       \
     41     (p2) = lock_user_string(arg2);          \
     42     if ((p2) == NULL) {                     \
     43         unlock_user(p1, arg1, 0);           \
     44         return -TARGET_EFAULT;              \
     45     }                                       \
     46 } while (0)
     47 
     48 #define UNLOCK_PATH2(p1, arg1, p2, arg2)    \
     49 do {                                        \
     50     unlock_user(p2, arg2, 0);               \
     51     unlock_user(p1, arg1, 0);               \
     52 } while (0)
     53 
     54 extern struct iovec *lock_iovec(int type, abi_ulong target_addr, int count,
     55         int copy);
     56 extern void unlock_iovec(struct iovec *vec, abi_ulong target_addr, int count,
     57         int copy);
     58 
     59 int safe_open(const char *path, int flags, mode_t mode);
     60 int safe_openat(int fd, const char *path, int flags, mode_t mode);
     61 
     62 ssize_t safe_read(int fd, void *buf, size_t nbytes);
     63 ssize_t safe_pread(int fd, void *buf, size_t nbytes, off_t offset);
     64 ssize_t safe_readv(int fd, const struct iovec *iov, int iovcnt);
     65 ssize_t safe_preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
     66 
     67 ssize_t safe_write(int fd, void *buf, size_t nbytes);
     68 ssize_t safe_pwrite(int fd, void *buf, size_t nbytes, off_t offset);
     69 ssize_t safe_writev(int fd, const struct iovec *iov, int iovcnt);
     70 ssize_t safe_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
     71 
     72 /* read(2) */
     73 static abi_long do_bsd_read(abi_long arg1, abi_long arg2, abi_long arg3)
     74 {
     75     abi_long ret;
     76     void *p;
     77 
     78     p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
     79     if (p == NULL) {
     80         return -TARGET_EFAULT;
     81     }
     82     ret = get_errno(safe_read(arg1, p, arg3));
     83     unlock_user(p, arg2, ret);
     84 
     85     return ret;
     86 }
     87 
     88 /* pread(2) */
     89 static abi_long do_bsd_pread(void *cpu_env, abi_long arg1,
     90     abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
     91 {
     92     abi_long ret;
     93     void *p;
     94 
     95     p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
     96     if (p == NULL) {
     97         return -TARGET_EFAULT;
     98     }
     99     if (regpairs_aligned(cpu_env) != 0) {
    100         arg4 = arg5;
    101         arg5 = arg6;
    102     }
    103     ret = get_errno(safe_pread(arg1, p, arg3, target_arg64(arg4, arg5)));
    104     unlock_user(p, arg2, ret);
    105 
    106     return ret;
    107 }
    108 
    109 /* readv(2) */
    110 static abi_long do_bsd_readv(abi_long arg1, abi_long arg2, abi_long arg3)
    111 {
    112     abi_long ret;
    113     struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
    114 
    115     if (vec != NULL) {
    116         ret = get_errno(safe_readv(arg1, vec, arg3));
    117         unlock_iovec(vec, arg2, arg3, 1);
    118     } else {
    119         ret = -host_to_target_errno(errno);
    120     }
    121 
    122     return ret;
    123 }
    124 
    125 /* preadv(2) */
    126 static abi_long do_bsd_preadv(void *cpu_env, abi_long arg1,
    127     abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
    128 {
    129     abi_long ret;
    130     struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 1);
    131 
    132     if (vec != NULL) {
    133         if (regpairs_aligned(cpu_env) != 0) {
    134             arg4 = arg5;
    135             arg5 = arg6;
    136         }
    137         ret = get_errno(safe_preadv(arg1, vec, arg3, target_arg64(arg4, arg5)));
    138         unlock_iovec(vec, arg2, arg3, 0);
    139     } else {
    140         ret = -host_to_target_errno(errno);
    141     }
    142 
    143     return ret;
    144 }
    145 
    146 /* write(2) */
    147 static abi_long do_bsd_write(abi_long arg1, abi_long arg2, abi_long arg3)
    148 {
    149     abi_long nbytes, ret;
    150     void *p;
    151 
    152     /* nbytes < 0 implies that it was larger than SIZE_MAX. */
    153     nbytes = arg3;
    154     if (nbytes < 0) {
    155         return -TARGET_EINVAL;
    156     }
    157     p = lock_user(VERIFY_READ, arg2, nbytes, 1);
    158     if (p == NULL) {
    159         return -TARGET_EFAULT;
    160     }
    161     ret = get_errno(safe_write(arg1, p, arg3));
    162     unlock_user(p, arg2, 0);
    163 
    164     return ret;
    165 }
    166 
    167 /* pwrite(2) */
    168 static abi_long do_bsd_pwrite(void *cpu_env, abi_long arg1,
    169     abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
    170 {
    171     abi_long ret;
    172     void *p;
    173 
    174     p = lock_user(VERIFY_READ, arg2, arg3, 1);
    175     if (p == NULL) {
    176         return -TARGET_EFAULT;
    177     }
    178     if (regpairs_aligned(cpu_env) != 0) {
    179         arg4 = arg5;
    180         arg5 = arg6;
    181     }
    182     ret = get_errno(safe_pwrite(arg1, p, arg3, target_arg64(arg4, arg5)));
    183     unlock_user(p, arg2, 0);
    184 
    185     return ret;
    186 }
    187 
    188 /* writev(2) */
    189 static abi_long do_bsd_writev(abi_long arg1, abi_long arg2, abi_long arg3)
    190 {
    191     abi_long ret;
    192     struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
    193 
    194     if (vec != NULL) {
    195         ret = get_errno(safe_writev(arg1, vec, arg3));
    196         unlock_iovec(vec, arg2, arg3, 0);
    197     } else {
    198         ret = -host_to_target_errno(errno);
    199     }
    200 
    201     return ret;
    202 }
    203 
    204 /* pwritev(2) */
    205 static abi_long do_bsd_pwritev(void *cpu_env, abi_long arg1,
    206     abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
    207 {
    208     abi_long ret;
    209     struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
    210 
    211     if (vec != NULL) {
    212         if (regpairs_aligned(cpu_env) != 0) {
    213             arg4 = arg5;
    214             arg5 = arg6;
    215         }
    216         ret = get_errno(safe_pwritev(arg1, vec, arg3, target_arg64(arg4, arg5)));
    217         unlock_iovec(vec, arg2, arg3, 0);
    218     } else {
    219         ret = -host_to_target_errno(errno);
    220     }
    221 
    222     return ret;
    223 }
    224 
    225 /* open(2) */
    226 static abi_long do_bsd_open(abi_long arg1, abi_long arg2, abi_long arg3)
    227 {
    228     abi_long ret;
    229     void *p;
    230 
    231     LOCK_PATH(p, arg1);
    232     ret = get_errno(safe_open(path(p), target_to_host_bitmask(arg2,
    233                 fcntl_flags_tbl), arg3));
    234     UNLOCK_PATH(p, arg1);
    235 
    236     return ret;
    237 }
    238 
    239 /* openat(2) */
    240 static abi_long do_bsd_openat(abi_long arg1, abi_long arg2,
    241         abi_long arg3, abi_long arg4)
    242 {
    243     abi_long ret;
    244     void *p;
    245 
    246     LOCK_PATH(p, arg2);
    247     ret = get_errno(safe_openat(arg1, path(p),
    248                 target_to_host_bitmask(arg3, fcntl_flags_tbl), arg4));
    249     UNLOCK_PATH(p, arg2);
    250 
    251     return ret;
    252 }
    253 
    254 /* close(2) */
    255 static abi_long do_bsd_close(abi_long arg1)
    256 {
    257     return get_errno(close(arg1));
    258 }
    259 
    260 /* fdatasync(2) */
    261 static abi_long do_bsd_fdatasync(abi_long arg1)
    262 {
    263     return get_errno(fdatasync(arg1));
    264 }
    265 
    266 /* fsync(2) */
    267 static abi_long do_bsd_fsync(abi_long arg1)
    268 {
    269     return get_errno(fsync(arg1));
    270 }
    271 
    272 /* closefrom(2) */
    273 static abi_long do_bsd_closefrom(abi_long arg1)
    274 {
    275     closefrom(arg1);  /* returns void */
    276     return get_errno(0);
    277 }
    278 
    279 /* revoke(2) */
    280 static abi_long do_bsd_revoke(abi_long arg1)
    281 {
    282     abi_long ret;
    283     void *p;
    284 
    285     LOCK_PATH(p, arg1);
    286     ret = get_errno(revoke(p)); /* XXX path(p)? */
    287     UNLOCK_PATH(p, arg1);
    288 
    289     return ret;
    290 }
    291 
    292 /* access(2) */
    293 static abi_long do_bsd_access(abi_long arg1, abi_long arg2)
    294 {
    295     abi_long ret;
    296     void *p;
    297 
    298     LOCK_PATH(p, arg1);
    299     ret = get_errno(access(path(p), arg2));
    300     UNLOCK_PATH(p, arg1);
    301 
    302     return ret;
    303 }
    304 
    305 /* eaccess(2) */
    306 static abi_long do_bsd_eaccess(abi_long arg1, abi_long arg2)
    307 {
    308     abi_long ret;
    309     void *p;
    310 
    311     LOCK_PATH(p, arg1);
    312     ret = get_errno(eaccess(path(p), arg2));
    313     UNLOCK_PATH(p, arg1);
    314 
    315     return ret;
    316 }
    317 
    318 /* faccessat(2) */
    319 static abi_long do_bsd_faccessat(abi_long arg1, abi_long arg2,
    320         abi_long arg3, abi_long arg4)
    321 {
    322     abi_long ret;
    323     void *p;
    324 
    325     LOCK_PATH(p, arg2);
    326     ret = get_errno(faccessat(arg1, p, arg3, arg4)); /* XXX path(p)? */
    327     UNLOCK_PATH(p, arg2);
    328 
    329     return ret;
    330 }
    331 
    332 /* chdir(2) */
    333 static abi_long do_bsd_chdir(abi_long arg1)
    334 {
    335     abi_long ret;
    336     void *p;
    337 
    338     LOCK_PATH(p, arg1);
    339     ret = get_errno(chdir(p)); /* XXX  path(p)? */
    340     UNLOCK_PATH(p, arg1);
    341 
    342     return ret;
    343 }
    344 
    345 /* fchdir(2) */
    346 static abi_long do_bsd_fchdir(abi_long arg1)
    347 {
    348     return get_errno(fchdir(arg1));
    349 }
    350 
    351 /* rename(2) */
    352 static abi_long do_bsd_rename(abi_long arg1, abi_long arg2)
    353 {
    354     abi_long ret;
    355     void *p1, *p2;
    356 
    357     LOCK_PATH2(p1, arg1, p2, arg2);
    358     ret = get_errno(rename(p1, p2)); /* XXX path(p1), path(p2) */
    359     UNLOCK_PATH2(p1, arg1, p2, arg2);
    360 
    361     return ret;
    362 }
    363 
    364 /* renameat(2) */
    365 static abi_long do_bsd_renameat(abi_long arg1, abi_long arg2,
    366         abi_long arg3, abi_long arg4)
    367 {
    368     abi_long ret;
    369     void *p1, *p2;
    370 
    371     LOCK_PATH2(p1, arg2, p2, arg4);
    372     ret = get_errno(renameat(arg1, p1, arg3, p2));
    373     UNLOCK_PATH2(p1, arg2, p2, arg4);
    374 
    375     return ret;
    376 }
    377 
    378 /* link(2) */
    379 static abi_long do_bsd_link(abi_long arg1, abi_long arg2)
    380 {
    381     abi_long ret;
    382     void *p1, *p2;
    383 
    384     LOCK_PATH2(p1, arg1, p2, arg2);
    385     ret = get_errno(link(p1, p2)); /* XXX path(p1), path(p2) */
    386     UNLOCK_PATH2(p1, arg1, p2, arg2);
    387 
    388     return ret;
    389 }
    390 
    391 /* linkat(2) */
    392 static abi_long do_bsd_linkat(abi_long arg1, abi_long arg2,
    393         abi_long arg3, abi_long arg4, abi_long arg5)
    394 {
    395     abi_long ret;
    396     void *p1, *p2;
    397 
    398     LOCK_PATH2(p1, arg2, p2, arg4);
    399     ret = get_errno(linkat(arg1, p1, arg3, p2, arg5));
    400     UNLOCK_PATH2(p1, arg2, p2, arg4);
    401 
    402     return ret;
    403 }
    404 
    405 /* unlink(2) */
    406 static abi_long do_bsd_unlink(abi_long arg1)
    407 {
    408     abi_long ret;
    409     void *p;
    410 
    411     LOCK_PATH(p, arg1);
    412     ret = get_errno(unlink(p)); /* XXX path(p) */
    413     UNLOCK_PATH(p, arg1);
    414 
    415     return ret;
    416 }
    417 
    418 /* unlinkat(2) */
    419 static abi_long do_bsd_unlinkat(abi_long arg1, abi_long arg2,
    420         abi_long arg3)
    421 {
    422     abi_long ret;
    423     void *p;
    424 
    425     LOCK_PATH(p, arg2);
    426     ret = get_errno(unlinkat(arg1, p, arg3)); /* XXX path(p) */
    427     UNLOCK_PATH(p, arg2);
    428 
    429     return ret;
    430 }
    431 
    432 /* mkdir(2) */
    433 static abi_long do_bsd_mkdir(abi_long arg1, abi_long arg2)
    434 {
    435     abi_long ret;
    436     void *p;
    437 
    438     LOCK_PATH(p, arg1);
    439     ret = get_errno(mkdir(p, arg2)); /* XXX path(p) */
    440     UNLOCK_PATH(p, arg1);
    441 
    442     return ret;
    443 }
    444 
    445 /* mkdirat(2) */
    446 static abi_long do_bsd_mkdirat(abi_long arg1, abi_long arg2,
    447         abi_long arg3)
    448 {
    449     abi_long ret;
    450     void *p;
    451 
    452     LOCK_PATH(p, arg2);
    453     ret = get_errno(mkdirat(arg1, p, arg3));
    454     UNLOCK_PATH(p, arg2);
    455 
    456     return ret;
    457 }
    458 
    459 /* rmdir(2) */
    460 static abi_long do_bsd_rmdir(abi_long arg1)
    461 {
    462     abi_long ret;
    463     void *p;
    464 
    465     LOCK_PATH(p, arg1);
    466     ret = get_errno(rmdir(p)); /* XXX path(p)? */
    467     UNLOCK_PATH(p, arg1);
    468 
    469     return ret;
    470 }
    471 
    472 /* undocumented __getcwd(char *buf, size_t len)  system call */
    473 static abi_long do_bsd___getcwd(abi_long arg1, abi_long arg2)
    474 {
    475     abi_long ret;
    476     void *p;
    477 
    478     p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
    479     if (p == NULL) {
    480         return -TARGET_EFAULT;
    481     }
    482     ret = safe_syscall(SYS___getcwd, p, arg2);
    483     unlock_user(p, arg1, ret == 0 ? strlen(p) + 1 : 0);
    484 
    485     return get_errno(ret);
    486 }
    487 
    488 /* dup(2) */
    489 static abi_long do_bsd_dup(abi_long arg1)
    490 {
    491     return get_errno(dup(arg1));
    492 }
    493 
    494 /* dup2(2) */
    495 static abi_long do_bsd_dup2(abi_long arg1, abi_long arg2)
    496 {
    497     return get_errno(dup2(arg1, arg2));
    498 }
    499 
    500 /* truncate(2) */
    501 static abi_long do_bsd_truncate(void *cpu_env, abi_long arg1,
    502         abi_long arg2, abi_long arg3, abi_long arg4)
    503 {
    504     abi_long ret;
    505     void *p;
    506 
    507     LOCK_PATH(p, arg1);
    508     if (regpairs_aligned(cpu_env) != 0) {
    509         arg2 = arg3;
    510         arg3 = arg4;
    511     }
    512     ret = get_errno(truncate(p, target_arg64(arg2, arg3)));
    513     UNLOCK_PATH(p, arg1);
    514 
    515     return ret;
    516 }
    517 
    518 /* ftruncate(2) */
    519 static abi_long do_bsd_ftruncate(void *cpu_env, abi_long arg1,
    520         abi_long arg2, abi_long arg3, abi_long arg4)
    521 {
    522     if (regpairs_aligned(cpu_env) != 0) {
    523         arg2 = arg3;
    524         arg3 = arg4;
    525     }
    526     return get_errno(ftruncate(arg1, target_arg64(arg2, arg3)));
    527 }
    528 
    529 /* acct(2) */
    530 static abi_long do_bsd_acct(abi_long arg1)
    531 {
    532     abi_long ret;
    533     void *p;
    534 
    535     if (arg1 == 0) {
    536         ret = get_errno(acct(NULL));
    537     } else {
    538         LOCK_PATH(p, arg1);
    539         ret = get_errno(acct(path(p)));
    540         UNLOCK_PATH(p, arg1);
    541     }
    542     return ret;
    543 }
    544 
    545 /* sync(2) */
    546 static abi_long do_bsd_sync(void)
    547 {
    548     sync();
    549     return 0;
    550 }
    551 
    552 /* mount(2) */
    553 static abi_long do_bsd_mount(abi_long arg1, abi_long arg2, abi_long arg3,
    554         abi_long arg4)
    555 {
    556     abi_long ret;
    557     void *p1, *p2;
    558 
    559     LOCK_PATH2(p1, arg1, p2, arg2);
    560     /*
    561      * XXX arg4 should be locked, but it isn't clear how to do that since it may
    562      * be not be a NULL-terminated string.
    563      */
    564     if (arg4 == 0) {
    565         ret = get_errno(mount(p1, p2, arg3, NULL)); /* XXX path(p2)? */
    566     } else {
    567         ret = get_errno(mount(p1, p2, arg3, g2h_untagged(arg4))); /* XXX path(p2)? */
    568     }
    569     UNLOCK_PATH2(p1, arg1, p2, arg2);
    570 
    571     return ret;
    572 }
    573 
    574 /* unmount(2) */
    575 static abi_long do_bsd_unmount(abi_long arg1, abi_long arg2)
    576 {
    577     abi_long ret;
    578     void *p;
    579 
    580     LOCK_PATH(p, arg1);
    581     ret = get_errno(unmount(p, arg2)); /* XXX path(p)? */
    582     UNLOCK_PATH(p, arg1);
    583 
    584     return ret;
    585 }
    586 
    587 /* nmount(2) */
    588 static abi_long do_bsd_nmount(abi_long arg1, abi_long count,
    589         abi_long flags)
    590 {
    591     abi_long ret;
    592     struct iovec *vec = lock_iovec(VERIFY_READ, arg1, count, 1);
    593 
    594     if (vec != NULL) {
    595         ret = get_errno(nmount(vec, count, flags));
    596         unlock_iovec(vec, arg1, count, 0);
    597     } else {
    598         return -TARGET_EFAULT;
    599     }
    600 
    601     return ret;
    602 }
    603 
    604 /* symlink(2) */
    605 static abi_long do_bsd_symlink(abi_long arg1, abi_long arg2)
    606 {
    607     abi_long ret;
    608     void *p1, *p2;
    609 
    610     LOCK_PATH2(p1, arg1, p2, arg2);
    611     ret = get_errno(symlink(p1, p2)); /* XXX path(p1), path(p2) */
    612     UNLOCK_PATH2(p1, arg1, p2, arg2);
    613 
    614     return ret;
    615 }
    616 
    617 /* symlinkat(2) */
    618 static abi_long do_bsd_symlinkat(abi_long arg1, abi_long arg2,
    619         abi_long arg3)
    620 {
    621     abi_long ret;
    622     void *p1, *p2;
    623 
    624     LOCK_PATH2(p1, arg1, p2, arg3);
    625     ret = get_errno(symlinkat(p1, arg2, p2)); /* XXX path(p1), path(p2) */
    626     UNLOCK_PATH2(p1, arg1, p2, arg3);
    627 
    628     return ret;
    629 }
    630 
    631 /* readlink(2) */
    632 static abi_long do_bsd_readlink(CPUArchState *env, abi_long arg1,
    633         abi_long arg2, abi_long arg3)
    634 {
    635     abi_long ret;
    636     void *p1, *p2;
    637 
    638     LOCK_PATH(p1, arg1);
    639     p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
    640     if (p2 == NULL) {
    641         UNLOCK_PATH(p1, arg1);
    642         return -TARGET_EFAULT;
    643     }
    644     if (strcmp(p1, "/proc/curproc/file") == 0) {
    645         CPUState *cpu = env_cpu(env);
    646         TaskState *ts = (TaskState *)cpu->opaque;
    647         strncpy(p2, ts->bprm->fullpath, arg3);
    648         ret = MIN((abi_long)strlen(ts->bprm->fullpath), arg3);
    649     } else {
    650         ret = get_errno(readlink(path(p1), p2, arg3));
    651     }
    652     unlock_user(p2, arg2, ret);
    653     UNLOCK_PATH(p1, arg1);
    654 
    655     return ret;
    656 }
    657 
    658 /* readlinkat(2) */
    659 static abi_long do_bsd_readlinkat(abi_long arg1, abi_long arg2,
    660         abi_long arg3, abi_long arg4)
    661 {
    662     abi_long ret;
    663     void *p1, *p2;
    664 
    665     LOCK_PATH(p1, arg2);
    666     p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
    667     if (p2 == NULL) {
    668         UNLOCK_PATH(p1, arg2);
    669         return -TARGET_EFAULT;
    670     }
    671     ret = get_errno(readlinkat(arg1, p1, p2, arg4));
    672     unlock_user(p2, arg3, ret);
    673     UNLOCK_PATH(p1, arg2);
    674 
    675     return ret;
    676 }
    677 
    678 /* chmod(2) */
    679 static abi_long do_bsd_chmod(abi_long arg1, abi_long arg2)
    680 {
    681     abi_long ret;
    682     void *p;
    683 
    684     LOCK_PATH(p, arg1);
    685     ret = get_errno(chmod(p, arg2)); /* XXX path(p)? */
    686     UNLOCK_PATH(p, arg1);
    687 
    688     return ret;
    689 }
    690 
    691 /* fchmod(2) */
    692 static abi_long do_bsd_fchmod(abi_long arg1, abi_long arg2)
    693 {
    694     return get_errno(fchmod(arg1, arg2));
    695 }
    696 
    697 /* lchmod(2) */
    698 static abi_long do_bsd_lchmod(abi_long arg1, abi_long arg2)
    699 {
    700     abi_long ret;
    701     void *p;
    702 
    703     LOCK_PATH(p, arg1);
    704     ret = get_errno(lchmod(p, arg2)); /* XXX path(p)? */
    705     UNLOCK_PATH(p, arg1);
    706 
    707     return ret;
    708 }
    709 
    710 /* fchmodat(2) */
    711 static abi_long do_bsd_fchmodat(abi_long arg1, abi_long arg2,
    712         abi_long arg3, abi_long arg4)
    713 {
    714     abi_long ret;
    715     void *p;
    716 
    717     LOCK_PATH(p, arg2);
    718     ret = get_errno(fchmodat(arg1, p, arg3, arg4));
    719     UNLOCK_PATH(p, arg2);
    720 
    721     return ret;
    722 }
    723 
    724 /* pre-ino64 mknod(2) */
    725 static abi_long do_bsd_freebsd11_mknod(abi_long arg1, abi_long arg2, abi_long arg3)
    726 {
    727     abi_long ret;
    728     void *p;
    729 
    730     LOCK_PATH(p, arg1);
    731     ret = get_errno(syscall(SYS_freebsd11_mknod, p, arg2, arg3));
    732     UNLOCK_PATH(p, arg1);
    733 
    734     return ret;
    735 }
    736 
    737 /* pre-ino64 mknodat(2) */
    738 static abi_long do_bsd_freebsd11_mknodat(abi_long arg1, abi_long arg2,
    739         abi_long arg3, abi_long arg4)
    740 {
    741     abi_long ret;
    742     void *p;
    743 
    744     LOCK_PATH(p, arg2);
    745     ret = get_errno(syscall(SYS_freebsd11_mknodat, arg1, p, arg3, arg4));
    746     UNLOCK_PATH(p, arg2);
    747 
    748     return ret;
    749 }
    750 
    751 /* post-ino64 mknodat(2) */
    752 static abi_long do_bsd_mknodat(void *cpu_env, abi_long arg1,
    753         abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5,
    754         abi_long arg6)
    755 {
    756     abi_long ret;
    757     void *p;
    758 
    759     LOCK_PATH(p, arg2);
    760        /* 32-bit arch's use two 32 registers for 64 bit return value */
    761     if (regpairs_aligned(cpu_env) != 0) {
    762         ret = get_errno(mknodat(arg1, p, arg3, target_arg64(arg5, arg6)));
    763     } else {
    764         ret = get_errno(mknodat(arg1, p, arg3, target_arg64(arg4, arg5)));
    765     }
    766     UNLOCK_PATH(p, arg2);
    767 
    768     return ret;
    769 }
    770 
    771 /* chown(2) */
    772 static abi_long do_bsd_chown(abi_long arg1, abi_long arg2, abi_long arg3)
    773 {
    774     abi_long ret;
    775     void *p;
    776 
    777     LOCK_PATH(p, arg1);
    778     ret = get_errno(chown(p, arg2, arg3)); /* XXX path(p)? */
    779     UNLOCK_PATH(p, arg1);
    780 
    781     return ret;
    782 }
    783 
    784 /* fchown(2) */
    785 static abi_long do_bsd_fchown(abi_long arg1, abi_long arg2,
    786         abi_long arg3)
    787 {
    788     return get_errno(fchown(arg1, arg2, arg3));
    789 }
    790 
    791 /* lchown(2) */
    792 static abi_long do_bsd_lchown(abi_long arg1, abi_long arg2,
    793         abi_long arg3)
    794 {
    795     abi_long ret;
    796     void *p;
    797 
    798     LOCK_PATH(p, arg1);
    799     ret = get_errno(lchown(p, arg2, arg3)); /* XXX path(p)? */
    800     UNLOCK_PATH(p, arg1);
    801 
    802     return ret;
    803 }
    804 
    805 /* fchownat(2) */
    806 static abi_long do_bsd_fchownat(abi_long arg1, abi_long arg2,
    807         abi_long arg3, abi_long arg4, abi_long arg5)
    808 {
    809     abi_long ret;
    810     void *p;
    811 
    812     LOCK_PATH(p, arg2);
    813     ret = get_errno(fchownat(arg1, p, arg3, arg4, arg5)); /* XXX path(p)? */
    814     UNLOCK_PATH(p, arg2);
    815 
    816     return ret;
    817 }
    818 
    819 /* chflags(2) */
    820 static abi_long do_bsd_chflags(abi_long arg1, abi_long arg2)
    821 {
    822     abi_long ret;
    823     void *p;
    824 
    825     LOCK_PATH(p, arg1);
    826     ret = get_errno(chflags(p, arg2)); /* XXX path(p)? */
    827     UNLOCK_PATH(p, arg1);
    828 
    829     return ret;
    830 }
    831 
    832 /* lchflags(2) */
    833 static abi_long do_bsd_lchflags(abi_long arg1, abi_long arg2)
    834 {
    835     abi_long ret;
    836     void *p;
    837 
    838     LOCK_PATH(p, arg1);
    839     ret = get_errno(lchflags(p, arg2)); /* XXX path(p)? */
    840     UNLOCK_PATH(p, arg1);
    841 
    842     return ret;
    843 }
    844 
    845 /* fchflags(2) */
    846 static abi_long do_bsd_fchflags(abi_long arg1, abi_long arg2)
    847 {
    848     return get_errno(fchflags(arg1, arg2));
    849 }
    850 
    851 /* chroot(2) */
    852 static abi_long do_bsd_chroot(abi_long arg1)
    853 {
    854     abi_long ret;
    855     void *p;
    856 
    857     LOCK_PATH(p, arg1);
    858     ret = get_errno(chroot(p)); /* XXX path(p)? */
    859     UNLOCK_PATH(p, arg1);
    860 
    861     return ret;
    862 }
    863 
    864 /* flock(2) */
    865 static abi_long do_bsd_flock(abi_long arg1, abi_long arg2)
    866 {
    867     return get_errno(flock(arg1, arg2));
    868 }
    869 
    870 /* mkfifo(2) */
    871 static abi_long do_bsd_mkfifo(abi_long arg1, abi_long arg2)
    872 {
    873     abi_long ret;
    874     void *p;
    875 
    876     LOCK_PATH(p, arg1);
    877     ret = get_errno(mkfifo(p, arg2)); /* XXX path(p)? */
    878     UNLOCK_PATH(p, arg1);
    879 
    880     return ret;
    881 }
    882 
    883 /* mkfifoat(2) */
    884 static abi_long do_bsd_mkfifoat(abi_long arg1, abi_long arg2,
    885         abi_long arg3)
    886 {
    887     abi_long ret;
    888     void *p;
    889 
    890     LOCK_PATH(p, arg2);
    891     ret = get_errno(mkfifoat(arg1, p, arg3));
    892     UNLOCK_PATH(p, arg2);
    893 
    894     return ret;
    895 }
    896 
    897 /* pathconf(2) */
    898 static abi_long do_bsd_pathconf(abi_long arg1, abi_long arg2)
    899 {
    900     abi_long ret;
    901     void *p;
    902 
    903     LOCK_PATH(p, arg1);
    904     ret = get_errno(pathconf(p, arg2)); /* XXX path(p)? */
    905     UNLOCK_PATH(p, arg1);
    906 
    907     return ret;
    908 }
    909 
    910 /* lpathconf(2) */
    911 static abi_long do_bsd_lpathconf(abi_long arg1, abi_long arg2)
    912 {
    913     abi_long ret;
    914     void *p;
    915 
    916     LOCK_PATH(p, arg1);
    917     ret = get_errno(lpathconf(p, arg2)); /* XXX path(p)? */
    918     UNLOCK_PATH(p, arg1);
    919 
    920     return ret;
    921 }
    922 
    923 /* fpathconf(2) */
    924 static abi_long do_bsd_fpathconf(abi_long arg1, abi_long arg2)
    925 {
    926     return get_errno(fpathconf(arg1, arg2));
    927 }
    928 
    929 /* undelete(2) */
    930 static abi_long do_bsd_undelete(abi_long arg1)
    931 {
    932     abi_long ret;
    933     void *p;
    934 
    935     LOCK_PATH(p, arg1);
    936     ret = get_errno(undelete(p)); /* XXX path(p)? */
    937     UNLOCK_PATH(p, arg1);
    938 
    939     return ret;
    940 }
    941 
    942 #endif /* BSD_FILE_H */