brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.2 KiB · 08db485 Raw
143 lines · cpp
1//===-- Implementation of internal fcntl ----------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "src/__support/OSUtil/fcntl.h"10 11#include "hdr/errno_macros.h"12#include "hdr/fcntl_macros.h"13#include "hdr/types/mode_t.h"14#include "hdr/types/off_t.h"15#include "hdr/types/struct_f_owner_ex.h"16#include "hdr/types/struct_flock.h"17#include "hdr/types/struct_flock64.h"18#include "src/__support/OSUtil/syscall.h" // For internal syscall function.19#include "src/__support/common.h"20#include "src/__support/error_or.h"21#include "src/__support/macros/config.h"22 23#include <sys/syscall.h> // For syscall numbers.24 25namespace LIBC_NAMESPACE_DECL {26namespace internal {27 28ErrorOr<int> fcntl(int fd, int cmd, void *arg) {29#if SYS_fcntl30  constexpr auto FCNTL_SYSCALL_ID = SYS_fcntl;31#elif defined(SYS_fcntl64)32  constexpr auto FCNTL_SYSCALL_ID = SYS_fcntl64;33#else34#error "fcntl and fcntl64 syscalls not available."35#endif36 37  switch (cmd) {38  case F_OFD_SETLKW: {39    struct flock *flk = reinterpret_cast<struct flock *>(arg);40    // convert the struct to a flock6441    struct flock64 flk64;42    flk64.l_type = flk->l_type;43    flk64.l_whence = flk->l_whence;44    flk64.l_start = flk->l_start;45    flk64.l_len = flk->l_len;46    flk64.l_pid = flk->l_pid;47    // create a syscall48    int ret =49        LIBC_NAMESPACE::syscall_impl<int>(FCNTL_SYSCALL_ID, fd, cmd, &flk64);50    if (ret < 0)51      return Error(-ret);52    return ret;53  }54  case F_OFD_GETLK:55  case F_OFD_SETLK: {56    struct flock *flk = reinterpret_cast<struct flock *>(arg);57    // convert the struct to a flock6458    struct flock64 flk64;59    flk64.l_type = flk->l_type;60    flk64.l_whence = flk->l_whence;61    flk64.l_start = flk->l_start;62    flk64.l_len = flk->l_len;63    flk64.l_pid = flk->l_pid;64    // create a syscall65    int ret =66        LIBC_NAMESPACE::syscall_impl<int>(FCNTL_SYSCALL_ID, fd, cmd, &flk64);67    // On failure, return68    if (ret < 0)69      return Error(-ret);70    // Check for overflow, i.e. the offsets are not the same when cast71    // to off_t from off64_t.72    if (static_cast<off_t>(flk64.l_len) != flk64.l_len ||73        static_cast<off_t>(flk64.l_start) != flk64.l_start)74      return Error(EOVERFLOW);75 76    // Now copy back into flk, in case flk64 got modified77    flk->l_type = flk64.l_type;78    flk->l_whence = flk64.l_whence;79    flk->l_start = static_cast<decltype(flk->l_start)>(flk64.l_start);80    flk->l_len = static_cast<decltype(flk->l_len)>(flk64.l_len);81    flk->l_pid = flk64.l_pid;82    return ret;83  }84  case F_GETOWN: {85    struct f_owner_ex fex;86    int ret = LIBC_NAMESPACE::syscall_impl<int>(FCNTL_SYSCALL_ID, fd,87                                                F_GETOWN_EX, &fex);88    if (ret < 0)89      return Error(-ret);90    return fex.type == F_OWNER_PGRP ? -fex.pid : fex.pid;91  }92#ifdef SYS_fcntl6493  case F_GETLK: {94    if constexpr (FCNTL_SYSCALL_ID == SYS_fcntl64)95      cmd = F_GETLK64;96    break;97  }98  case F_SETLK: {99    if constexpr (FCNTL_SYSCALL_ID == SYS_fcntl64)100      cmd = F_SETLK64;101    break;102  }103  case F_SETLKW: {104    if constexpr (FCNTL_SYSCALL_ID == SYS_fcntl64)105      cmd = F_SETLKW64;106    break;107  }108#endif109  }110 111  // default, but may use rewritten cmd from above.112  int ret = LIBC_NAMESPACE::syscall_impl<int>(FCNTL_SYSCALL_ID, fd, cmd,113                                              reinterpret_cast<void *>(arg));114  if (ret < 0)115    return Error(-ret);116  return ret;117}118 119ErrorOr<int> open(const char *path, int flags, mode_t mode_flags) {120#ifdef SYS_open121  int fd = LIBC_NAMESPACE::syscall_impl<int>(SYS_open, path, flags, mode_flags);122#else123  int fd = LIBC_NAMESPACE::syscall_impl<int>(SYS_openat, AT_FDCWD, path, flags,124                                             mode_flags);125#endif126  if (fd < 0)127    return Error(-fd);128 129  return fd;130}131 132ErrorOr<int> close(int fd) {133  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_close, fd);134 135  if (ret < 0)136    return Error(-ret);137 138  return ret;139}140 141} // namespace internal142} // namespace LIBC_NAMESPACE_DECL143