brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.5 KiB · e740190 Raw
87 lines · cpp
1//===-- Linux implementation of utimes ------------------------------------===//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/sys/time/utimes.h"10 11#include "hdr/fcntl_macros.h"12#include "hdr/types/struct_timespec.h"13#include "hdr/types/struct_timeval.h"14 15#include "src/__support/OSUtil/syscall.h"16#include "src/__support/common.h"17 18#include "src/__support/libc_errno.h"19 20#include <sys/syscall.h>21 22namespace LIBC_NAMESPACE_DECL {23 24LLVM_LIBC_FUNCTION(int, utimes,25                   (const char *path, const struct timeval times[2])) {26  int ret;27 28#ifdef SYS_utimes29  // No need to define a timespec struct, use the syscall directly.30  ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_utimes, path, times);31#elif defined(SYS_utimensat) || defined(SYS_utimensat_time64)32 33#if defined(SYS_utimensat)34  constexpr auto UTIMES_SYSCALL_ID = SYS_utimensat;35#elif defined(SYS_utimensat_time64)36  constexpr auto UTIMES_SYSCALL_ID = SYS_utimensat_time64;37#endif38 39  // the utimensat syscall requires a timespec struct, not timeval.40  struct timespec ts[2];41  struct timespec *ts_ptr = nullptr; // default value if times is nullptr42 43  // convert the microsec values in timeval struct times44  // to nanosecond values in timespec struct ts45  if (times != nullptr) {46 47    // ensure consistent values48    if ((times[0].tv_usec < 0 || times[1].tv_usec < 0) ||49        (times[0].tv_usec >= 1000000 || times[1].tv_usec >= 1000000)) {50      libc_errno = EINVAL;51      return -1;52    }53 54    // set seconds in ts55    ts[0].tv_sec = times[0].tv_sec;56    ts[1].tv_sec = times[1].tv_sec;57 58    // convert u-seconds to nanoseconds59    ts[0].tv_nsec =60        static_cast<decltype(ts[0].tv_nsec)>(times[0].tv_usec * 1000);61    ts[1].tv_nsec =62        static_cast<decltype(ts[1].tv_nsec)>(times[1].tv_usec * 1000);63 64    ts_ptr = ts;65  }66 67  // If times was nullptr, ts_ptr remains nullptr, which utimensat interprets68  // as setting times to the current time.69 70  // utimensat syscall.71  // flags=0 means don't follow symlinks (like utimes)72  ret = LIBC_NAMESPACE::syscall_impl<int>(UTIMES_SYSCALL_ID, AT_FDCWD, path,73                                          ts_ptr, 0);74 75#else76#error "utimes, utimensat, utimensat_time64,  syscalls not available."77#endif // SYS_utimensat78 79  if (ret < 0) {80    libc_errno = -ret;81    return -1;82  }83 84  return 0;85}86} // namespace LIBC_NAMESPACE_DECL87