diff options
Diffstat (limited to 'ports')
33 files changed, 670 insertions, 130 deletions
diff --git a/ports/linux/guts/close_range.c b/ports/linux/guts/close_range.c new file mode 100644 index 0000000..4bd2fe1 --- /dev/null +++ b/ports/linux/guts/close_range.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021 Richard Purdie + * + * SPDX-License-Identifier: LGPL-2.1-only + * + * int close_range(unsigned int lowfd, unsigned int maxfd, int flags) + * int rc = -1; + */ + + (void) lowfd; + (void) maxfd; + (void) flags; + /* for now pretend the kernel doesn't support it regardless + which users are supposed to be able to handle */ + errno = ENOSYS; + rc = -1; + +/* return rc; + * } + */ diff --git a/ports/linux/guts/closefrom.c b/ports/linux/guts/closefrom.c new file mode 100644 index 0000000..1350506 --- /dev/null +++ b/ports/linux/guts/closefrom.c @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021 Richard Purdie + * + * SPDX-License-Identifier: LGPL-2.1-only + * + * void closefrom(int fd) + */ + pseudo_msg_t *msg; + /* this cleans up internal tables, and shouldn't make it to the server. Avoids pseudo's internal fds */ + msg = pseudo_client_op(OP_CLOSEFROM, 0, fd, -1, 0, 0); + /* fds between fd and msg->fd are closed within the above function avoiding pseudo's own fds */ + real_closefrom(msg->fd); + +/* return; + * } + */ diff --git a/ports/linux/guts/fcntl.c b/ports/linux/guts/fcntl.c index 4dd9796..ffb50be 100644 --- a/ports/linux/guts/fcntl.c +++ b/ports/linux/guts/fcntl.c @@ -8,6 +8,22 @@ * wrap_fcntl(int fd, int cmd, ...struct flock *lock) { * int rc = -1; */ +#if !defined(F_GETPIPE_SZ) +#define F_GETPIPE_SZ (1032) +#endif + +#if F_GETPIPE_SZ != 1032 +#error System F_GETPIPE_SZ has unexpected value +#endif + +#if !defined(F_SETPIPE_SZ) +#define F_SETPIPE_SZ (1031) +#endif + +#if F_SETPIPE_SZ != 1031 +#error System F_SETPIPE_SZ has unexpected value +#endif + long arg; int save_errno; @@ -31,12 +47,17 @@ } errno = save_errno; break; + case F_SETPIPE_SZ: + /* actually do something */ + rc = real_fcntl(fd, cmd, arg); + break; /* no argument: */ case F_GETFD: case F_GETFL: case F_GETOWN: case F_GETSIG: case F_GETLEASE: + case F_GETPIPE_SZ: rc = real_fcntl(fd, cmd); break; /* long argument */ @@ -52,6 +73,11 @@ case F_GETLK: case F_SETLK: case F_SETLKW: +#ifdef F_OFD_GETLK + case F_OFD_GETLK: + case F_OFD_SETLK: + case F_OFD_SETLKW: +#endif rc = real_fcntl(fd, cmd, lock); break; #if defined(F_GETLK64) && (F_GETLK64 != F_GETLK) diff --git a/ports/linux/guts/fcntl64.c b/ports/linux/guts/fcntl64.c new file mode 100644 index 0000000..99de43d --- /dev/null +++ b/ports/linux/guts/fcntl64.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2008-2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * SPDX-License-Identifier: LGPL-2.1-only + * + * static int + * wrap_fcntl64(int fd, int cmd, ...struct flock *lock) { + * int rc = -1; + */ +#if !defined(F_GETPIPE_SZ) +#define F_GETPIPE_SZ (1032) +#endif + +#if F_GETPIPE_SZ != 1032 +#error System F_GETPIPE_SZ has unexpected value +#endif + +#if !defined(F_SETPIPE_SZ) +#define F_SETPIPE_SZ (1031) +#endif + +#if F_SETPIPE_SZ != 1031 +#error System F_SETPIPE_SZ has unexpected value +#endif + + long arg; + int save_errno; + + /* we don't know whether we need lock or arg; grab both, which + * should be safe enough on Linuxy systems. */ + va_start(ap, cmd); + arg = va_arg(ap, long); + va_end(ap); + + switch (cmd) { + case F_DUPFD: +#ifdef F_DUPFD_CLOEXEC + case F_DUPFD_CLOEXEC: +#endif + /* actually do something */ + rc = real_fcntl64(fd, cmd, arg); + save_errno = errno; + if (rc != -1) { + pseudo_debug(PDBGF_OP, "fcntl64_dup: %d->%d\n", fd, rc); + pseudo_client_op(OP_DUP, 0, fd, rc, 0, 0); + } + errno = save_errno; + break; + case F_SETPIPE_SZ: + /* actually do something */ + rc = real_fcntl64(fd, cmd, arg); + break; + /* no argument: */ + case F_GETFD: + case F_GETFL: + case F_GETOWN: + case F_GETSIG: + case F_GETLEASE: + case F_GETPIPE_SZ: + rc = real_fcntl64(fd, cmd); + break; + /* long argument */ + case F_SETFD: + case F_SETFL: + case F_SETOWN: + case F_SETSIG: + case F_SETLEASE: + case F_NOTIFY: + rc = real_fcntl64(fd, cmd, arg); + break; + /* struct flock * argument */ + case F_GETLK: + case F_SETLK: + case F_SETLKW: +#ifdef F_OFD_GETLK + case F_OFD_GETLK: + case F_OFD_SETLK: + case F_OFD_SETLKW: +#endif + rc = real_fcntl64(fd, cmd, lock); + break; +#if defined(F_GETLK64) && (F_GETLK64 != F_GETLK) + /* the cast is safe, all struct pointers must smell the same */ + case F_GETLK64: + case F_SETLK64: + case F_SETLKW64: + rc = real_fcntl64(fd, cmd, (struct flock64 *) lock); + break; +#endif + default: + pseudo_diag("unknown fcntl64 argument %d, assuming long argument.\n", + cmd); + rc = real_fcntl64(fd, cmd, arg); + break; + } +/* return rc; + * } + */ diff --git a/ports/linux/guts/fstatat.c b/ports/linux/guts/fstatat.c new file mode 100644 index 0000000..3267641 --- /dev/null +++ b/ports/linux/guts/fstatat.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021 Linux Foundation; see + * guts/COPYRIGHT for information. + * + * SPDX-License-Identifier: LGPL-2.1-only + * + * int fstatat(int dirfd, const char *path, struct stat *buf, int flags) + * int rc = -1; + */ + + rc = wrap___fxstatat(_STAT_VER, dirfd, path, buf, flags); + +/* return rc; + * } + */ diff --git a/ports/linux/guts/fstatat64.c b/ports/linux/guts/fstatat64.c new file mode 100644 index 0000000..c981e14 --- /dev/null +++ b/ports/linux/guts/fstatat64.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021 Linux Foundation; see + * guts/COPYRIGHT for information. + * + * SPDX-License-Identifier: LGPL-2.1-only + * + * int fstatat64(int dirfd, const char *path, struct stat64 *buf, int flags) + * int rc = -1; + */ + + rc = wrap___fxstatat64(_STAT_VER, dirfd, path, buf, flags); + +/* return rc; + * } + */ diff --git a/ports/linux/guts/lchmod.c b/ports/linux/guts/lchmod.c new file mode 100644 index 0000000..da330a7 --- /dev/null +++ b/ports/linux/guts/lchmod.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021 Linux Foundation + * + * SPDX-License-Identifier: LGPL-2.1-only + * + * static int + * wrap_lchmod(const char *path, mode_t mode) { + */ + + rc = wrap_fchmodat(AT_FDCWD, path, mode, AT_SYMLINK_NOFOLLOW); + +/* return rc; + * } + */ diff --git a/ports/linux/guts/mkostemp64.c b/ports/linux/guts/mkostemp64.c new file mode 100644 index 0000000..502211b --- /dev/null +++ b/ports/linux/guts/mkostemp64.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2010 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * SPDX-License-Identifier: LGPL-2.1-only + * + * static int + * wrap_mkstemp64(char *template, int oflags) { + * int rc = -1; + */ + struct stat64 buf; + int save_errno; + size_t len; + char *tmp_template; + + if (!template) { + errno = EFAULT; + return 0; + } + + len = strlen(template); + tmp_template = PSEUDO_ROOT_PATH(AT_FDCWD, template, AT_SYMLINK_NOFOLLOW); + + if (!tmp_template) { + errno = ENOENT; + return -1; + } + + /* mkstemp64 wrapper uses this code and mkostemp64 not present in some glibc versions */ + if (oflags == 0) + rc = real_mkstemp64(tmp_template); + else + rc = real_mkostemp64(tmp_template, oflags); + + if (rc != -1) { + save_errno = errno; + + if (real___fxstat64(_STAT_VER, rc, &buf) != -1) { + real_fchmod(rc, PSEUDO_FS_MODE(0600, 0)); + pseudo_client_op(OP_CREAT, 0, -1, -1, tmp_template, &buf); + pseudo_client_op(OP_OPEN, PSA_READ | PSA_WRITE, rc, -1, tmp_template, &buf); + } else { + pseudo_debug(PDBGF_CONSISTENCY, "mkstemp (fd %d) succeeded, but fstat failed (%s).\n", + rc, strerror(errno)); + pseudo_client_op(OP_OPEN, PSA_READ | PSA_WRITE, rc, -1, tmp_template, 0); + } + errno = save_errno; + } + /* mkstemp only changes the XXXXXX at the end. */ + memcpy(template + len - 6, tmp_template + strlen(tmp_template) - 6, 6); +/* return rc; + * } + */ diff --git a/ports/linux/guts/mkstemp64.c b/ports/linux/guts/mkstemp64.c index aa7bb58..487f256 100644 --- a/ports/linux/guts/mkstemp64.c +++ b/ports/linux/guts/mkstemp64.c @@ -8,42 +8,9 @@ * wrap_mkstemp64(char *template) { * int rc = -1; */ - struct stat64 buf; - int save_errno; - size_t len; - char *tmp_template; + /* mkstemp64() is just like mkostemp64() with no flags */ + rc = wrap_mkostemp64(template, 0); - if (!template) { - errno = EFAULT; - return 0; - } - - len = strlen(template); - tmp_template = PSEUDO_ROOT_PATH(AT_FDCWD, template, AT_SYMLINK_NOFOLLOW); - - if (!tmp_template) { - errno = ENOENT; - return -1; - } - - rc = real_mkstemp64(tmp_template); - - if (rc != -1) { - save_errno = errno; - - if (real___fxstat64(_STAT_VER, rc, &buf) != -1) { - real_fchmod(rc, PSEUDO_FS_MODE(0600, 0)); - pseudo_client_op(OP_CREAT, 0, -1, -1, tmp_template, &buf); - pseudo_client_op(OP_OPEN, PSA_READ | PSA_WRITE, rc, -1, tmp_template, &buf); - } else { - pseudo_debug(PDBGF_CONSISTENCY, "mkstemp (fd %d) succeeded, but fstat failed (%s).\n", - rc, strerror(errno)); - pseudo_client_op(OP_OPEN, PSA_READ | PSA_WRITE, rc, -1, tmp_template, 0); - } - errno = save_errno; - } - /* mkstemp only changes the XXXXXX at the end. */ - memcpy(template + len - 6, tmp_template + strlen(tmp_template) - 6, 6); /* return rc; * } */ diff --git a/ports/linux/guts/openat.c b/ports/linux/guts/openat.c index 673ea6e..656ac2b 100644 --- a/ports/linux/guts/openat.c +++ b/ports/linux/guts/openat.c @@ -55,9 +55,13 @@ if (flags & O_CREAT) { save_errno = errno; #ifdef PSEUDO_NO_REAL_AT_FUNCTIONS - rc = real___xstat64(_STAT_VER, path, &buf); + if (flags & O_NOFOLLOW) { + rc = real___lxstat64(_STAT_VER, path, &buf); + } else { + rc = real___xstat64(_STAT_VER, path, &buf); + } #else - rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, 0); + rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, (flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0); #endif existed = (rc != -1); if (!existed) @@ -72,9 +76,13 @@ if (!(flags & O_NONBLOCK) && ((flags & (O_WRONLY | O_RDONLY | O_RDWR)) != O_RDWR)) { save_errno = errno; #ifdef PSEUDO_NO_REAL_AT_FUNCTIONS - rc = real___xstat64(_STAT_VER, path, &buf); + if (flags & O_NOFOLLOW) { + rc = real___lxstat64(_STAT_VER, path, &buf); + } else { + rc = real___xstat64(_STAT_VER, path, &buf); + } #else - rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, 0); + rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, (flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0); #endif if (rc != -1 && S_ISFIFO(buf.st_mode)) { overly_magic_nonblocking = 1; @@ -126,11 +134,17 @@ } #endif #ifdef PSEUDO_NO_REAL_AT_FUNCTIONS - stat_rc = real___xstat64(_STAT_VER, path, &buf); + if (flags & O_NOFOLLOW) { + stat_rc = real___lxstat64(_STAT_VER, path, &buf); + } else { + stat_rc = real___xstat64(_STAT_VER, path, &buf); + } #else - stat_rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, 0); + stat_rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, (flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0); #endif + pseudo_debug(PDBGF_FILE, "openat(path %s), flags %o, stat rc %d, stat mode %o\n", + path, flags, stat_rc, buf.st_mode); if (stat_rc != -1) { buf.st_mode = PSEUDO_DB_MODE(buf.st_mode, mode); if (!existed) { diff --git a/ports/linux/nostatx/portdefs.h b/ports/linux/nostatx/portdefs.h new file mode 100644 index 0000000..ded8ff9 --- /dev/null +++ b/ports/linux/nostatx/portdefs.h @@ -0,0 +1,38 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copy of the statx struct to allow a pseudo built on a system without + * statx to work on one with statx and hence work with OE's uninative + */ + +struct statx_timestamp +{ + __int64_t tv_sec; + __uint32_t tv_nsec; + __int32_t __statx_timestamp_pad1[1]; +}; + +struct statx +{ + __uint32_t stx_mask; + __uint32_t stx_blksize; + __uint64_t stx_attributes; + __uint32_t stx_nlink; + __uint32_t stx_uid; + __uint32_t stx_gid; + __uint16_t stx_mode; + __uint16_t __statx_pad1[1]; + __uint64_t stx_ino; + __uint64_t stx_size; + __uint64_t stx_blocks; + __uint64_t stx_attributes_mask; + struct statx_timestamp stx_atime; + struct statx_timestamp stx_btime; + struct statx_timestamp stx_ctime; + struct statx_timestamp stx_mtime; + __uint32_t stx_rdev_major; + __uint32_t stx_rdev_minor; + __uint32_t stx_dev_major; + __uint32_t stx_dev_minor; + __uint64_t __statx_pad2[14]; +}; diff --git a/ports/linux/portdefs.h b/ports/linux/portdefs.h index d419365..9545550 100644 --- a/ports/linux/portdefs.h +++ b/ports/linux/portdefs.h @@ -32,3 +32,24 @@ GLIBC_COMPAT_SYMBOL(memcpy,2.0); #include <linux/capability.h> #include <sys/syscall.h> +#include <sys/prctl.h> +#include <linux/seccomp.h> + +#ifndef _STAT_VER +#if defined (__aarch64__) +#define _STAT_VER 0 +#elif defined (__x86_64__) +#define _STAT_VER 1 +#else +#define _STAT_VER 3 +#endif +#endif +#ifndef _MKNOD_VER +#if defined (__aarch64__) +#define _MKNOD_VER 0 +#elif defined (__x86_64__) +#define _MKNOD_VER 0 +#else +#define _MKNOD_VER 1 +#endif +#endif diff --git a/ports/linux/pseudo_wrappers.c b/ports/linux/pseudo_wrappers.c index cd7e173..7659897 100644 --- a/ports/linux/pseudo_wrappers.c +++ b/ports/linux/pseudo_wrappers.c @@ -57,6 +57,7 @@ int pseudo_capset(cap_user_header_t hdrp, const cap_user_data_t datap) { long syscall(long number, ...) { long rc = -1; + va_list ap; if (!pseudo_check_wrappers() || !real_syscall) { /* rc was initialized to the "failure" value */ @@ -77,11 +78,25 @@ syscall(long number, ...) { (void) number; #endif +#ifdef SYS_seccomp + /* pseudo and seccomp are incompatible as pseudo uses different syscalls + * so pretend to enable seccomp but really do nothing */ + if (number == SYS_seccomp) { + unsigned long cmd; + va_start(ap, number); + cmd = va_arg(ap, unsigned long); + va_end(ap); + if (cmd == SECCOMP_SET_MODE_FILTER) { + return 0; + } + } +#endif + /* gcc magic to attempt to just pass these args to syscall. we have to * guess about the number of args; the docs discuss calling conventions * up to 7, so let's try that? */ - void *res = __builtin_apply((void (*)()) real_syscall, __builtin_apply_args(), sizeof(long) * 7); + void *res = __builtin_apply((void (*)(void)) real_syscall, __builtin_apply_args(), sizeof(long) * 7); __builtin_return(res); } @@ -92,3 +107,44 @@ static long wrap_syscall(long nr, va_list ap) { (void) ap; return -1; } + +int +prctl(int option, ...) { + int rc = -1; + va_list ap; + + if (!pseudo_check_wrappers() || !real_prctl) { + /* rc was initialized to the "failure" value */ + pseudo_enosys("prctl"); + return rc; + } + +#ifdef SECCOMP_SET_MODE_FILTER + /* pseudo and seccomp are incompatible as pseudo uses different syscalls + * so pretend to enable seccomp but really do nothing */ + if (option == PR_SET_SECCOMP) { + unsigned long cmd; + va_start(ap, option); + cmd = va_arg(ap, unsigned long); + va_end(ap); + if (cmd == SECCOMP_SET_MODE_FILTER) { + return 0; + } + } +#endif + + /* gcc magic to attempt to just pass these args to prctl. we have to + * guess about the number of args; the docs discuss calling conventions + * up to 5, so let's try that? + */ + void *res = __builtin_apply((void (*)(void)) real_prctl, __builtin_apply_args(), sizeof(long) * 5); + __builtin_return(res); +} + +/* unused. + */ +static int wrap_prctl(int option, va_list ap) { + (void) option; + (void) ap; + return -1; +} diff --git a/ports/linux/statvfs/guts/statvfs64.c b/ports/linux/statvfs/guts/statvfs64.c new file mode 100644 index 0000000..856d3db --- /dev/null +++ b/ports/linux/statvfs/guts/statvfs64.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018 Wind River Systems; see + * guts/COPYRIGHT for information. + * + * SPDX-License-Identifier: LGPL-2.1-only + * + * int statvfs64(const char *path, struct statvfs64 *buf) + * int rc = -1; + */ + + rc = real_statvfs64(path, buf); + +/* return rc; + * } + */ diff --git a/ports/linux/statvfs/wrapfuncs.in b/ports/linux/statvfs/wrapfuncs.in index 1afb64d..6a59660 100644 --- a/ports/linux/statvfs/wrapfuncs.in +++ b/ports/linux/statvfs/wrapfuncs.in @@ -1 +1,2 @@ int statvfs(const char *path, struct statvfs *buf); +int statvfs64(const char *path, struct statvfs64 *buf); diff --git a/ports/linux/statx/guts/statx.c b/ports/linux/statx/guts/statx.c new file mode 100644 index 0000000..42aebe5 --- /dev/null +++ b/ports/linux/statx/guts/statx.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019 Linux Foundation + * Author: Richard Purdie + * + * SPDX-License-Identifier: LGPL-2.1-only + * + * int + * statx(int dirfd, const char *path, int flags, unsigned int mask, struct statx *statxbuf) { + * int rc = -1; + */ + pseudo_msg_t *msg; + PSEUDO_STATBUF buf; + int save_errno; + + rc = real_statx(dirfd, path, flags, mask, statxbuf); + save_errno = errno; + if (rc == -1) { + return rc; + } + + buf.st_uid = statxbuf->stx_uid; + buf.st_gid = statxbuf->stx_gid; + buf.st_dev = makedev(statxbuf->stx_dev_major, statxbuf->stx_dev_minor); + buf.st_ino = statxbuf->stx_ino; + buf.st_mode = statxbuf->stx_mode; + buf.st_rdev = makedev(statxbuf->stx_rdev_major, statxbuf->stx_rdev_minor); + buf.st_nlink = statxbuf->stx_nlink; + msg = pseudo_client_op(OP_STAT, 0, -1, dirfd, path, &buf); + if (msg && msg->result == RESULT_SUCCEED) { + pseudo_debug(PDBGF_FILE, "statx(path %s), flags %o, stat rc %d, stat uid %o\n", path, flags, rc, statxbuf->stx_uid); + statxbuf->stx_uid = msg->uid; + statxbuf->stx_gid = msg->gid; + statxbuf->stx_mode = msg->mode; + statxbuf->stx_rdev_major = major(msg->rdev); + statxbuf->stx_rdev_minor = minor(msg->rdev); + } else { + pseudo_debug(PDBGF_FILE, "statx(path %s) failed, flags %o, stat rc %d, stat uid %o\n", path, flags, rc, statxbuf->stx_uid); + } + errno = save_errno; +/* return rc; + * } + */ diff --git a/ports/linux/statx/portdefs.h b/ports/linux/statx/portdefs.h new file mode 100644 index 0000000..bf934dc --- /dev/null +++ b/ports/linux/statx/portdefs.h @@ -0,0 +1,6 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-only + * + */ +#include <sys/stat.h> +#include <sys/sysmacros.h> diff --git a/ports/linux/statx/wrapfuncs.in b/ports/linux/statx/wrapfuncs.in new file mode 100644 index 0000000..168234f --- /dev/null +++ b/ports/linux/statx/wrapfuncs.in @@ -0,0 +1 @@ +int statx(int dirfd, const char *path, int flags, unsigned int mask, struct statx *statxbuf); diff --git a/ports/linux/subports b/ports/linux/subports index a29044a..099ea59 100755 --- a/ports/linux/subports +++ b/ports/linux/subports @@ -29,11 +29,12 @@ fi if $port_xattr; then cat > dummy.c <<EOF #include <sys/types.h> -#include <attr/xattr.h> +#include <sys/xattr.h> +#include <attr/attributes.h> int i; EOF if ! ${CC} -c -o dummy.o dummy.c >/dev/null 2>&1; then - echo >&2 "Warning: Can't compile trivial program using <attr/xattr.h>". + echo >&2 "Warning: Can't compile trivial program using <attr/attributes.h>". echo >&2 " xattr support will require that header." fi echo "linux/xattr" @@ -54,3 +55,18 @@ else fi rm -f dummy.c dummy.o +# For statx, we want a pseudo which can work with OE's uninative, i.e. build on a system without +# statx but work on one with it. We have a header in nostatx to allow this. +cat > dummy.c <<EOF +#define _GNU_SOURCE +#include <sys/stat.h> +struct statx x; +EOF +if ${CC} -c -o dummy.o dummy.c >/dev/null 2>&1; then + echo "linux/statx" +else + echo "linux/nostatx" + echo "linux/statx" +fi +rm -f dummy.c dummy.o + diff --git a/ports/linux/wrapfuncs.in b/ports/linux/wrapfuncs.in index 4cdbc9c..97b16c2 100644 --- a/ports/linux/wrapfuncs.in +++ b/ports/linux/wrapfuncs.in @@ -1,41 +1,46 @@ -int open(const char *path, int flags, ...{mode_t mode}); /* flags=flags|O_NOFOLLOW */ +int open(const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW, noignore_path=1 */ char *get_current_dir_name(void); int __xstat(int ver, const char *path, struct stat *buf); int __lxstat(int ver, const char *path, struct stat *buf); /* flags=AT_SYMLINK_NOFOLLOW */ int __fxstat(int ver, int fd, struct stat *buf); +int lchmod(const char *path, mode_t mode); /* flags=AT_SYMLINK_NOFOLLOW */ int lchown(const char *path, uid_t owner, gid_t group); /* flags=AT_SYMLINK_NOFOLLOW */ int __fxstatat(int ver, int dirfd, const char *path, struct stat *buf, int flags); -int openat(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=flags|O_NOFOLLOW */ -int __openat_2(int dirfd, const char *path, int flags); /* flags=flags|O_NOFOLLOW */ +int openat(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW, noignore_path=1 */ +int __openat_2(int dirfd, const char *path, int flags); /* flags=flags&O_NOFOLLOW, noignore_path=1 */ int mknod(const char *path, mode_t mode, dev_t dev); /* real_func=pseudo_mknod */ int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev); /* real_func=pseudo_mknodat */ int __xmknod(int ver, const char *path, mode_t mode, dev_t *dev); /* flags=AT_SYMLINK_NOFOLLOW */ int __xmknodat(int ver, int dirfd, const char *path, mode_t mode, dev_t *dev); /* flags=AT_SYMLINK_NOFOLLOW */ -int fcntl(int fd, int cmd, ...{struct flock *lock}); +int fcntl(int fd, int cmd, ...{struct flock *lock}); /* noignore_path=1 */ +int fcntl64(int fd, int cmd, ...{struct flock *lock}); /* noignore_path=1 */ # just so we know the inums of symlinks char *canonicalize_file_name(const char *filename); int eaccess(const char *path, int mode); -int open64(const char *path, int flags, ...{mode_t mode}); /* flags=flags|O_NOFOLLOW */ -int openat64(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=flags|O_NOFOLLOW */ -int __openat64_2(int dirfd, const char *path, int flags); /* flags=flags|O_NOFOLLOW */ +int open64(const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW, noignore_path=1 */ +int openat64(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW, noignore_path=1 */ +int __openat64_2(int dirfd, const char *path, int flags); /* flags=flags&O_NOFOLLOW, noignore_path=1 */ int creat64(const char *path, mode_t mode); int stat(const char *path, struct stat *buf); /* real_func=pseudo_stat */ int lstat(const char *path, struct stat *buf); /* real_func=pseudo_lstat, flags=AT_SYMLINK_NOFOLLOW */ int fstat(int fd, struct stat *buf); /* real_func=pseudo_fstat */ +int fstatat(int dirfd, const char *path, struct stat *buf, int flags); int stat64(const char *path, struct stat64 *buf); /* real_func=pseudo_stat64 */ int lstat64(const char *path, struct stat64 *buf); /* real_func=pseudo_lstat64, flags=AT_SYMLINK_NOFOLLOW */ int fstat64(int fd, struct stat64 *buf); /* real_func=pseudo_fstat64 */ +int fstatat64(int dirfd, const char *path, struct stat64 *buf, int flags); int __xstat64(int ver, const char *path, struct stat64 *buf); int __lxstat64(int ver, const char *path, struct stat64 *buf); /* flags=AT_SYMLINK_NOFOLLOW */ int __fxstat64(int ver, int fd, struct stat64 *buf); int __fxstatat64(int ver, int dirfd, const char *path, struct stat64 *buf, int flags); -FILE *fopen64(const char *path, const char *mode); -int nftw64(const char *path, int (*fn)(const char *, const struct stat64 *, int, struct FTW *), int nopenfd, int flag); -FILE *freopen64(const char *path, const char *mode, FILE *stream); +FILE *fopen64(const char *path, const char *mode); /* noignore_path=1 */ +int nftw64(const char *path, int (*fn)(const char *, const struct stat64 *, int, struct FTW *), int nopenfd, int flag); /* noignore_path=1 */ +FILE *freopen64(const char *path, const char *mode, FILE *stream); /* noignore_path=1 */ int ftw64(const char *path, int (*fn)(const char *, const struct stat64 *, int), int nopenfd); int glob64(const char *pattern, int flags, int (*errfunc)(const char *, int), glob64_t *pglob); int scandir64(const char *path, struct dirent64 ***namelist, int (*filter)(const struct dirent64 *), int (*compar)()); int truncate64(const char *path, off64_t length); +int mkostemp64(char *template, int oflags); /* flags=AT_SYMLINK_NOFOLLOW */ int mkstemp64(char *template); /* flags=AT_SYMLINK_NOFOLLOW */ int getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups); int setgroups(size_t size, const gid_t *list); @@ -56,3 +61,6 @@ int getgrent_r(struct group *gbuf, char *buf, size_t buflen, struct group **gbuf int capset(cap_user_header_t hdrp, const cap_user_data_t datap); /* real_func=pseudo_capset */ long syscall(long nr, ...); /* hand_wrapped=1 */ int renameat2(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, unsigned int flags); /* flags=AT_SYMLINK_NOFOLLOW */ +int prctl(int option, ...); /* hand_wrapped=1 */ +int close_range(unsigned int lowfd, unsigned int maxfd, int flags); +void closefrom(int fd); diff --git a/ports/linux/xattr/portdefs.h b/ports/linux/xattr/portdefs.h index 56cd3ca..beab7d0 100644 --- a/ports/linux/xattr/portdefs.h +++ b/ports/linux/xattr/portdefs.h @@ -2,5 +2,9 @@ * SPDX-License-Identifier: LGPL-2.1-only * */ -#include <attr/xattr.h> +#include <sys/xattr.h> #include <stdint.h> + +#ifndef ENOATTR +#define ENOATTR ENODATA +#endif diff --git a/ports/linux/xattr/pseudo_wrappers.c b/ports/linux/xattr/pseudo_wrappers.c index 590af30..0b65920 100644 --- a/ports/linux/xattr/pseudo_wrappers.c +++ b/ports/linux/xattr/pseudo_wrappers.c @@ -134,7 +134,7 @@ static ssize_t shared_getxattr(const char *path, int fd, const char *name, void pseudo_debug(PDBGF_XATTR, "getxattr(%s [fd %d], %s)\n", path ? path : "<no path>", fd, name); pseudo_msg_t *result = pseudo_client_op(OP_GET_XATTR, 0, fd, -1, path, &buf, name); - if (result->result != RESULT_SUCCEED) { + if (!result || result->result != RESULT_SUCCEED) { errno = ENOATTR; return -1; } @@ -197,7 +197,7 @@ static int shared_setxattr(const char *path, int fd, const char *name, const voi mode |= get_special_bits(path, fd); pseudo_debug(PDBGF_XATTR, "posix_acl_access translated to mode %04o. Remaining attribute(s): %d.\n", mode, extra); - buf.st_mode = mode; + /* we want to actually issue a corresponding chmod, * as well, or else the file ends up 0600 on the * host. Using the slightly-less-efficient wrap_chmod @@ -254,7 +254,7 @@ static int shared_setxattr(const char *path, int fd, const char *name, const voi static ssize_t shared_listxattr(const char *path, int fd, char *list, size_t size) { RC_AND_BUF pseudo_msg_t *result = pseudo_client_op(OP_LIST_XATTR, 0, fd, -1, path, &buf); - if (result->result != RESULT_SUCCEED) { + if (!result || result->result != RESULT_SUCCEED) { pseudo_debug(PDBGF_XATTR, "listxattr: no success.\n"); errno = ENOATTR; return -1; @@ -276,7 +276,7 @@ static int shared_removexattr(const char *path, int fd, const char *name) { RC_AND_BUF pseudo_msg_t *result = pseudo_client_op(OP_REMOVE_XATTR, 0, fd, -1, path, &buf, name); - if (result->result != RESULT_SUCCEED) { + if (!result || result->result != RESULT_SUCCEED) { /* docs say ENOATTR, but I don't have one */ errno = ENOENT; return -1; diff --git a/ports/linux/xattr/wrapfuncs.in b/ports/linux/xattr/wrapfuncs.in index c37f78a..09eba23 100644 --- a/ports/linux/xattr/wrapfuncs.in +++ b/ports/linux/xattr/wrapfuncs.in @@ -1,12 +1,12 @@ -ssize_t getxattr(const char *path, const char *name, void *value, size_t size); /* flags=0 */ -ssize_t lgetxattr(const char *path, const char *name, void *value, size_t size); /* flags=AT_SYMLINK_NOFOLLOW */ -ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size); -int setxattr(const char *path, const char *name, const void *value, size_t size, int xflags); /* flags=0 */ -int lsetxattr(const char *path, const char *name, const void *value, size_t size, int xflags); /* flags=AT_SYMLINK_NOFOLLOW */ -int fsetxattr(int filedes, const char *name, const void *value, size_t size, int xflags); -ssize_t listxattr(const char *path, char *list, size_t size); /* flags=0 */ -ssize_t llistxattr(const char *path, char *list, size_t size); /* flags=AT_SYMLINK_NOFOLLOW */ -ssize_t flistxattr(int filedes, char *list, size_t size); -int removexattr(const char *path, const char *name); /* flags=0 */ -int lremovexattr(const char *path, const char *name); /* flags=AT_SYMLINK_NOFOLLOW */ -int fremovexattr(int filedes, const char *name); +ssize_t getxattr(const char *path, const char *name, void *value, size_t size); /* flags=0, version="GLIBC_2.3", version-aarch64="GLIBC_2.17" */ +ssize_t lgetxattr(const char *path, const char *name, void *value, size_t size); /* flags=AT_SYMLINK_NOFOLLOW, version="GLIBC_2.3", version-aarch64="GLIBC_2.17" */ +ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size); /* version="GLIBC_2.3", version-aarch64="GLIBC_2.17" */ +int setxattr(const char *path, const char *name, const void *value, size_t size, int xflags); /* flags=0, version="GLIBC_2.3", version-aarch64="GLIBC_2.17" */ +int lsetxattr(const char *path, const char *name, const void *value, size_t size, int xflags); /* flags=AT_SYMLINK_NOFOLLOW, version="GLIBC_2.3", version-aarch64="GLIBC_2.17" */ +int fsetxattr(int filedes, const char *name, const void *value, size_t size, int xflags); /* version="GLIBC_2.3", version-aarch64="GLIBC_2.17" */ +ssize_t listxattr(const char *path, char *list, size_t size); /* flags=0, version="GLIBC_2.3", version-aarch64="GLIBC_2.17" */ +ssize_t llistxattr(const char *path, char *list, size_t size); /* flags=AT_SYMLINK_NOFOLLOW, version="GLIBC_2.3", version-aarch64="GLIBC_2.17" */ +ssize_t flistxattr(int filedes, char *list, size_t size); /* version="GLIBC_2.3", version-aarch64="GLIBC_2.17" */ +int removexattr(const char *path, const char *name); /* flags=0, version="GLIBC_2.3", version-aarch64="GLIBC_2.17" */ +int lremovexattr(const char *path, const char *name); /* flags=AT_SYMLINK_NOFOLLOW, version="GLIBC_2.3", version-aarch64="GLIBC_2.17" */ +int fremovexattr(int filedes, const char *name); /* version="GLIBC_2.3", version-aarch64="GLIBC_2.17" */ diff --git a/ports/unix/guts/access.c b/ports/unix/guts/access.c index 1cc8d58..4725f49 100644 --- a/ports/unix/guts/access.c +++ b/ports/unix/guts/access.c @@ -21,7 +21,7 @@ if (buf.st_mode & 0111) { return 0; } else { - errno = EPERM; + errno = EACCES; return -1; } } else { diff --git a/ports/unix/guts/faccessat.c b/ports/unix/guts/faccessat.c new file mode 100644 index 0000000..02515ee --- /dev/null +++ b/ports/unix/guts/faccessat.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, Linux Foundation; see + * guts/COPYRIGHT for information. + * + * SPDX-License-Identifier: LGPL-2.1-only + * + * static int + * wrap_fsaccessat(int dirfd, const char *path, int mode, int flags) { + * int rc = -1; + */ + rc = wrap_faccessat2(dirfd, path, mode, flags); + +/* return rc; + * } + */ diff --git a/ports/unix/guts/faccessat2.c b/ports/unix/guts/faccessat2.c new file mode 100644 index 0000000..1283cc6 --- /dev/null +++ b/ports/unix/guts/faccessat2.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021, Linux Foundation; see + * guts/COPYRIGHT for information. + * + * SPDX-License-Identifier: LGPL-2.1-only + * + * static int + * wrap_fsaccessat2(int dirfd, const char *path, int mode, int flags) { + * int rc = -1; + */ + PSEUDO_STATBUF buf; + +#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS + if (dirfd != AT_FDCWD) { + errno = ENOSYS; + return -1; + } + if (flags & AT_SYMLINK_NOFOLLOW) { + rc = base_lstat(path, &buf); + } else { + rc = base_stat(path, &buf); + } +#else + rc = base_fstatat(dirfd, path, &buf, flags & AT_SYMLINK_NOFOLLOW); +#endif + if (rc == -1) + return rc; + + /* note: no attempt to handle the case where user isn't + * root. + */ + + if (mode & X_OK) { + if (buf.st_mode & 0111) { + return 0; + } else { + errno = EACCES; + return -1; + } + } else { + return 0; + } + +/* return rc; + * } + */ diff --git a/ports/unix/guts/fchmodat.c b/ports/unix/guts/fchmodat.c index 55dbd35..5a31151 100644 --- a/ports/unix/guts/fchmodat.c +++ b/ports/unix/guts/fchmodat.c @@ -11,16 +11,16 @@ PSEUDO_STATBUF buf; int save_errno = errno; - if (flags & AT_SYMLINK_NOFOLLOW) { - errno = ENOTSUP; - return -1; - } #ifdef PSEUDO_NO_REAL_AT_FUNCTIONS if (dirfd != AT_FDCWD) { errno = ENOSYS; return -1; } - rc = base_stat(path, &buf); + if (flags & AT_SYMLINK_NOFOLLOW) { + rc = base_lstat(path, &buf); + } else { + rc = base_stat(path, &buf); + } #else rc = base_fstatat(dirfd, path, &buf, flags); #endif @@ -28,9 +28,8 @@ return rc; } if (S_ISLNK(buf.st_mode)) { - /* we don't really support chmod of a symlink */ - errno = ENOSYS; - return -1; + /* according to docs, "chmod on a symbolic link always succeeds and has no effect" */ + return 0; } save_errno = errno; diff --git a/ports/unix/guts/linkat.c b/ports/unix/guts/linkat.c index 381f9d0..7d8dff4 100644 --- a/ports/unix/guts/linkat.c +++ b/ports/unix/guts/linkat.c @@ -116,6 +116,7 @@ * if the thing linked is a symlink. */ pseudo_client_op(OP_LINK, 0, -1, -1, newpath, &buf); + pseudo_client_linked_paths(oldpath, newpath); errno = save_errno; diff --git a/ports/unix/guts/realpath.c b/ports/unix/guts/realpath.c index 085d2cb..8d8118b 100644 --- a/ports/unix/guts/realpath.c +++ b/ports/unix/guts/realpath.c @@ -14,7 +14,14 @@ errno = ENAMETOOLONG; return NULL; } - if ((len = strlen(rname)) >= pseudo_sys_path_max()) { + len = strlen(rname); + char *ep = rname + len - 1; + while (ep > rname && *ep == '/') { + --len; + *(ep--) = '\0'; + } + + if (len >= pseudo_sys_path_max()) { errno = ENAMETOOLONG; return NULL; } diff --git a/ports/unix/guts/rename.c b/ports/unix/guts/rename.c index 5073c71..80bbf41 100644 --- a/ports/unix/guts/rename.c +++ b/ports/unix/guts/rename.c @@ -13,7 +13,8 @@ int oldrc, newrc; int save_errno; int old_db_entry = 0; - int may_unlinked = 0; + int may_unlink_new = 0; + int may_unlink_old = 0; pseudo_debug(PDBGF_OP, "rename: %s->%s\n", oldpath ? oldpath : "<nil>", @@ -29,41 +30,51 @@ newrc = base_lstat(newpath, &newbuf); oldrc = base_lstat(oldpath, &oldbuf); + /* nothing to do for a "rename" of a link to itself */ + if (newrc != -1 && oldrc != -1 && + newbuf.st_dev == oldbuf.st_dev && + newbuf.st_ino == oldbuf.st_ino) { + pseudo_debug(PDBGF_OP, "rename: paths are the same\n"); + return real_rename(oldpath, newpath); + } + errno = save_errno; /* newpath must be removed. */ /* as with unlink, we have to mark that the file may get deleted */ msg = pseudo_client_op(OP_MAY_UNLINK, 0, -1, -1, newpath, newrc ? NULL : &newbuf); if (msg && msg->result == RESULT_SUCCEED) - may_unlinked = 1; + may_unlink_new = 1; + /* oldpath is also likely to disappear. Something could call stat() after + real_rename so we need to mark as MAY_UNLINK too */ + msg = pseudo_client_op(OP_MAY_UNLINK, 0, -1, -1, oldpath, oldrc ? NULL : &oldbuf); + if (msg && msg->result == RESULT_SUCCEED) + may_unlink_old = 1; + msg = pseudo_client_op(OP_STAT, 0, -1, -1, oldpath, oldrc ? NULL : &oldbuf); if (msg && msg->result == RESULT_SUCCEED) old_db_entry = 1; rc = real_rename(oldpath, newpath); save_errno = errno; - if (may_unlinked) { - if (rc == -1) { - /* since we failed, that wasn't really unlinked -- put - * it back. - */ - pseudo_client_op(OP_CANCEL_UNLINK, 0, -1, -1, newpath, &newbuf); - } else { - /* confirm that the file was removed */ - pseudo_client_op(OP_DID_UNLINK, 0, -1, -1, newpath, &newbuf); - } - } + if (rc == -1) { + /* since we failed, that wasn't really unlinked -- put + * it back. + */ + if (may_unlink_new) + pseudo_client_op(OP_CANCEL_UNLINK, 0, -1, -1, newpath, &newbuf); + if (may_unlink_old) + pseudo_client_op(OP_CANCEL_UNLINK, 0, -1, -1, oldpath, &oldbuf); /* and we're done. */ errno = save_errno; return rc; } + + /* confirm that the file was removed */ + if (may_unlink_new) + pseudo_client_op(OP_DID_UNLINK, 0, -1, -1, newpath, &newbuf); + /* OP_DID_UNLINK for oldpath is handled by the server */ save_errno = errno; - /* nothing to do for a "rename" of a link to itself */ - if (newrc != -1 && oldrc != -1 && - newbuf.st_dev == oldbuf.st_dev && - newbuf.st_ino == oldbuf.st_ino) { - return rc; - } /* rename(3) is not mv(1). rename(file, dir) fails; you must provide * the corrected path yourself. You can rename over a directory only diff --git a/ports/unix/guts/renameat.c b/ports/unix/guts/renameat.c index 735a60a..5ac63f9 100644 --- a/ports/unix/guts/renameat.c +++ b/ports/unix/guts/renameat.c @@ -13,7 +13,8 @@ int oldrc, newrc; int save_errno; int old_db_entry = 0; - int may_unlinked = 0; + int may_unlink_new = 0; + int may_unlink_old = 0; pseudo_debug(PDBGF_FILE, "renameat: %d,%s->%d,%s\n", olddirfd, oldpath ? oldpath : "<nil>", @@ -41,42 +42,51 @@ newrc = base_fstatat(newdirfd, newpath, &newbuf, AT_SYMLINK_NOFOLLOW); #endif + /* nothing to do for a "rename" of a link to itself */ + if (newrc != -1 && oldrc != -1 && + newbuf.st_dev == oldbuf.st_dev && + newbuf.st_ino == oldbuf.st_ino) { + pseudo_debug(PDBGF_OP, "renameat: paths are the same\n"); + return real_renameat(olddirfd, oldpath, newdirfd, newpath); + } + errno = save_errno; /* newpath must be removed. */ /* as with unlink, we have to mark that the file may get deleted */ msg = pseudo_client_op(OP_MAY_UNLINK, 0, -1, newdirfd, newpath, newrc ? NULL : &newbuf); if (msg && msg->result == RESULT_SUCCEED) - may_unlinked = 1; + may_unlink_new = 1; + /* oldpath is also likely to disappear. Something could call stat() after + real_rename so we need to mark as MAY_UNLINK too */ + msg = pseudo_client_op(OP_MAY_UNLINK, 0, -1, olddirfd, oldpath, oldrc ? NULL : &oldbuf); + if (msg && msg->result == RESULT_SUCCEED) + may_unlink_old = 1; + msg = pseudo_client_op(OP_STAT, 0, -1, olddirfd, oldpath, oldrc ? NULL : &oldbuf); if (msg && msg->result == RESULT_SUCCEED) old_db_entry = 1; rc = real_renameat(olddirfd, oldpath, newdirfd, newpath); save_errno = errno; - if (may_unlinked) { - if (rc == -1) { - /* since we failed, that wasn't really unlinked -- put - * it back. - */ - pseudo_client_op(OP_CANCEL_UNLINK, 0, -1, newdirfd, newpath, &newbuf); - } else { - /* confirm that the file was removed */ - pseudo_client_op(OP_DID_UNLINK, 0, -1, newdirfd, newpath, &newbuf); - } - } if (rc == -1) { + /* since we failed, that wasn't really unlinked -- put + * it back. + */ + if (may_unlink_new) + pseudo_client_op(OP_CANCEL_UNLINK, 0, -1, newdirfd, newpath, &newbuf); + if (may_unlink_old) + pseudo_client_op(OP_CANCEL_UNLINK, 0, -1, olddirfd, oldpath, &oldbuf); /* and we're done. */ errno = save_errno; return rc; } + + /* confirm that the file was removed */ + if (may_unlink_new) + pseudo_client_op(OP_DID_UNLINK, 0, -1, newdirfd, newpath, &newbuf); + /* OP_DID_UNLINK for oldpath is handled by the server */ save_errno = errno; - /* nothing to do for a "rename" of a link to itself */ - if (newrc != -1 && oldrc != -1 && - newbuf.st_dev == oldbuf.st_dev && - newbuf.st_ino == oldbuf.st_ino) { - return rc; - } /* rename(3) is not mv(1). rename(file, dir) fails; you must provide * the corrected path yourself. You can rename over a directory only diff --git a/ports/unix/subports b/ports/unix/subports index e41b036..bd5a2f6 100755 --- a/ports/unix/subports +++ b/ports/unix/subports @@ -1,11 +1,13 @@ #!/bin/sh cat > dummy.c <<EOF +#define _GNU_SOURCE #include <unistd.h> int main(void) { syncfs(0); return 0; } EOF + if ${CC} -o dummy dummy.c > /dev/null 2>&1; then echo "unix/syncfs" fi diff --git a/ports/unix/wrapfuncs.in b/ports/unix/wrapfuncs.in index 3910fae..7724fc7 100644 --- a/ports/unix/wrapfuncs.in +++ b/ports/unix/wrapfuncs.in @@ -1,15 +1,17 @@ int creat(const char *path, mode_t mode); char *getcwd(char *buf, size_t size); char *getwd(char *buf); -int close(int fd); +int close(int fd); /* noignore_path=1 */ int fchmod(int fd, mode_t mode); int fchown(int fd, uid_t owner, gid_t group); int lchown(const char *path, uid_t owner, gid_t group); /* flags=AT_SYMLINK_NOFOLLOW */ -int dup2(int oldfd, int newfd); -int dup(int fd); -int chdir(const char *path); -int fchdir(int dirfd); +int dup2(int oldfd, int newfd); /* noignore_path=1 */ +int dup(int fd); /* noignore_path=1 */ +int chdir(const char *path); /* noignore_path=1 */ +int fchdir(int dirfd); /* noignore_path=1 */ int access(const char *path, int mode); +int faccessat(int dirfd, const char *path, int mode, int flags); +int faccessat2(int dirfd, const char *path, int mode, int flags); FTS *fts_open(char * const *path_argv, int options, int (*compar)(const FTSENT **, const FTSENT **)); /* inode64=1 */ int ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int nopenfd); int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int nopenfd, int flag); @@ -20,18 +22,18 @@ char *mktemp(char *template); long pathconf(const char *path, int name); char *realpath(const char *name, char *resolved_name); /* version="GLIBC_2.3" */ int remove(const char *path); /* flags=AT_SYMLINK_NOFOLLOW */ -DIR *opendir(const char *path); -int closedir(DIR *dirp); +DIR *opendir(const char *path); /* noignore_path=1 */ +int closedir(DIR *dirp); /* noignore_path=1 */ char *tempnam(const char *template, const char *pfx); char *tmpnam(char *s); int truncate(const char *path, off_t length); int utime(const char *path, const struct utimbuf *buf); int utimes(const char *path, const struct timeval *times); # needed because libc stdio does horrible things with inline asm syscalls -FILE *fopen(const char *path, const char *mode); -int fclose(FILE *fp); -FILE *freopen(const char *path, const char *mode, FILE *stream); -int chroot(const char *path); +FILE *fopen(const char *path, const char *mode); /* noignore_path=1 */ +int fclose(FILE *fp); /* noignore_path=1 */ +FILE *freopen(const char *path, const char *mode, FILE *stream); /* noignore_path=1 */ +int chroot(const char *path); /* noignore_path=1 */ int acct(const char *path); int chmod(const char *path, mode_t mode); int chown(const char *path, uid_t owner, gid_t group); |