AnyPS5/docs/dev/debt/libkernel_sys.md

8.1 KiB

libkernel_sys technical debt

Functional

  • fchdir (libkernel_sys) changes the guest working directory to the descriptor's directory: on Windows through the path recorded when the descriptor was opened, on Linux through the /proc/self/fd link target. It returns EBADF for a descriptor that is not open and ENOTDIR for one that is not a directory. FreeBSD change_dir's search-permission check (EACCES) is not modelled, and a directory renamed after it was opened is still reached through the recorded path. Console behaviour is unverified
  • openat (libkernel_sys) passes AT_FDCWD (-100) and absolute paths to open. Any other relative path is joined to the descriptor's host directory, found the same way as for fchdir, so guest path aliases and case-insensitive name matching do not apply to it, and a .. component is not kept inside the guest root. It returns EBADF for a descriptor that is not open and ENOTDIR for one that is not a directory. As with open, O_NOFOLLOW and O_NONBLOCK are ignored. PPSA99003 opens directory entries this way. Console behaviour is unverified
  • fchmodat (libkernel_sys) passes AT_FDCWD (-100) and absolute paths to chmod; any other relative path is joined to the descriptor's host directory the same way as for openat, so guest path aliases and case-insensitive name matching do not apply to it and a .. component is not kept inside the guest root. A flag other than 0 or AT_SYMLINK_NOFOLLOW (0x200) returns EINVAL; the mode is masked to 07777. With AT_SYMLINK_NOFOLLOW a symbolic link throws, since the host cannot change a link's own mode, while a regular file is changed either way. The mode maps to the host file mode, which on Windows is only the CRT's read-only bit. PPSA99621 calls it through std::filesystem::permissions. Console behaviour is unverified
  • pathconf (libkernel_sys) looks the path up as FreeBSD 11's kern_pathconf does (links followed, ENAMETOOLONG for a path of 1024 bytes or more or a component over 255) and returns the constants of FreeBSD 11's UFS ufs_pathconf for files and directories alike: _PC_LINK_MAX 32767, _PC_NAME_MAX 255, _PC_PATH_MAX and _PC_SYMLINK_MAX 1024, _PC_PIPE_BUF 512, _PC_CHOWN_RESTRICTED and _PC_NO_TRUNC 1, _PC_FILESIZEBITS 64, _PC_REC_MAX_XFER_SIZE -1, _PC_PRIO_IO and _PC_SYNC_IO 0. Whether the console's filesystems report the same is not verified. It throws for the names whose UFS value depends on the mount (_PC_ALLOC_SIZE_MIN, _PC_REC_INCR_XFER_SIZE, _PC_REC_MIN_XFER_SIZE, _PC_MIN_HOLE_SIZE), the kernel options (_PC_ACL_EXTENDED, _PC_ACL_PATH_MAX, _PC_ACL_NFS4, _PC_MAC_PRESENT) or the page size (_PC_REC_XFER_ALIGN), and on which UFS and vop_stdpathconf disagree (_PC_MAX_CANON, _PC_MAX_INPUT, _PC_VDISABLE, _PC_ASYNC_IO); other names fail with EINVAL
  • mkdirat (libkernel_sys) passes AT_FDCWD (-100) and absolute paths to mkdir. Any other relative path is joined to the descriptor's host directory, found the same way as for fchdir, so guest path aliases and case-insensitive name matching do not apply to it, and a .. component is not kept inside the guest root. It returns EBADF for a descriptor that is not open and ENOTDIR for one that is not a directory. On Windows, mode is ignored. Console behaviour is unverified
  • readlink (libkernel_sys) on Windows reads a symbolic link's target from its reparse data and returns it with / separators, only when the target is relative, as symlink creates them. A symbolic link with an absolute target and a junction throw, as a host path has no guest form. Any other reparse point throws too, where FreeBSD reports EINVAL for a file that is not a link
  • readlinkat (libkernel_sys) passes AT_FDCWD (-100) and absolute paths to readlink. Any other relative path is joined to the descriptor's host directory, found the same way as for fchdir, so guest path aliases and case-insensitive name matching do not apply to it, and a .. component is not kept inside the guest root. It returns EBADF for a descriptor that is not open and ENOTDIR for one that is not a directory. Console behaviour is unverified
  • unlinkat (libkernel_sys) passes AT_FDCWD (-100) and absolute paths to rmdir (with AT_REMOVEDIR, 0x800) or unlink. Any other relative path is joined to the descriptor's host directory, found the same way as for fchdir, so guest path aliases and case-insensitive name matching do not apply to it, and a .. component is not kept inside the guest root. It returns EBADF for a descriptor that is not open and ENOTDIR for one that is not a directory. Removing a directory without AT_REMOVEDIR fails with EPERM, removing . or .. with AT_REMOVEDIR fails with EINVAL, and flags other than AT_REMOVEDIR fail with EINVAL. Console behaviour is unverified
  • renameat (libkernel_sys) passes AT_FDCWD (-100) and absolute paths to rename. Any other relative path is joined to its descriptor's host directory, found the same way as for fchdir, so guest path aliases and case-insensitive name matching do not apply to relative descriptors, and a .. component is not kept inside the guest root. It returns EBADF for a descriptor that is not open and ENOTDIR for one that is not a directory. Console behaviour is unverified
  • fork (libkernel_sys) throws: creating a child process is not supported. PPSA19111 imports it and fails to load without it. Its engine calls fork in Posix_Daemonize, only with -daemonize, and in Platform_ShellExecute before execvp("xdg-open"), which the main menu's Previews button reaches, so pressing Previews ends in this throw. setsid fails with EPERM, as FreeBSD's does for a process group leader, since the guest is taken to lead its own process group (see kill). umask keeps the guest's mask (initially 022, masked to 07777) and returns the previous one, Linux named shared-memory creation applies it, but ordinary files are still created with the host process's mask
  • chroot (libkernel_sys) follows FreeBSD 11.4's sys_chroot and pwd_chroot for a root caller: EFAULT for a null path, ENOENT for an empty or missing one, ENAMETOOLONG for a path of 1024 bytes or more or a component over 255, and ENOTDIR for a path that is not a directory or passes through a file. A directory that is the guest root (/, /.., or . after fchdir to a descriptor of /) succeeds and changes nothing, as the root stays the same directory; the guest is taken never to have changed its root, so open directory descriptors do not make it fail with EPERM (kern.chroot_allow_open_directories 1). Any other directory throws, naming the path: the guest path resolver has a fixed root and mount aliases (/app0, /savedata0) that do not move with it. On the console a title starts in a sandbox root, where pwd_chroot refuses with EPERM while a directory is open; whether that holds for titles, and whether a title holds PRIV_VFS_CHROOT, are unverified. Porpoise (PPSA99764) weak-imports it and calls it only as fchdir to its saved descriptor of / then chroot("."), to put its sandbox root back after a jailbreak daemon replaced it (put_root_back)