(root)/
glibc-2.38/
sysdeps/
unix/
sysv/
linux/
utimensat.c
       1  /* Change access and modification times of open file.  Linux version.
       2     Copyright (C) 2007-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <errno.h>
      20  #include <sys/stat.h>
      21  #include <sysdep.h>
      22  #include <time.h>
      23  #include <kernel-features.h>
      24  
      25  /* Helper function defined for easy reusage of the code which calls utimensat
      26     and utimensat_time64 syscall.  */
      27  int
      28  __utimensat64_helper (int fd, const char *file,
      29                        const struct __timespec64 tsp64[2], int flags)
      30  {
      31  #ifndef __NR_utimensat_time64
      32  # define __NR_utimensat_time64 __NR_utimensat
      33  #endif
      34  
      35  #ifdef __ASSUME_TIME64_SYSCALLS
      36    return INLINE_SYSCALL_CALL (utimensat_time64, fd, file, &tsp64[0], flags);
      37  #else
      38    /* For UTIME_NOW and UTIME_OMIT the value of tv_sec field is ignored.  */
      39  # define TS_SPECIAL(ts) \
      40    ((ts).tv_nsec == UTIME_NOW || (ts).tv_nsec == UTIME_OMIT)
      41  
      42    bool need_time64 = tsp64 != NULL
      43  		     && ((!TS_SPECIAL (tsp64[0])
      44  			  && !in_int32_t_range (tsp64[0].tv_sec))
      45  			 || (!TS_SPECIAL (tsp64[1])
      46  			     && !in_int32_t_range (tsp64[1].tv_sec)));
      47    if (need_time64)
      48      {
      49        int r = INLINE_SYSCALL_CALL (utimensat_time64, fd, file, &tsp64[0],
      50  				   flags);
      51        if (r == 0 || errno != ENOSYS)
      52  	return r;
      53        __set_errno (EOVERFLOW);
      54        return -1;
      55      }
      56  
      57    struct timespec tsp32[2], *ptsp32 = NULL;
      58    if (tsp64)
      59      {
      60        tsp32[0] = valid_timespec64_to_timespec (tsp64[0]);
      61        tsp32[1] = valid_timespec64_to_timespec (tsp64[1]);
      62        ptsp32 = tsp32;
      63      }
      64  
      65    return INLINE_SYSCALL_CALL (utimensat, fd, file, ptsp32, flags);
      66  #endif
      67  }
      68  libc_hidden_def (__utimensat64_helper)
      69  
      70  /* Change the access time of FILE to TSP[0] and
      71     the modification time of FILE to TSP[1].
      72  
      73     Starting with 2.6.22 the Linux kernel has the utimensat syscall.  */
      74  int
      75  __utimensat64 (int fd, const char *file, const struct __timespec64 tsp64[2],
      76                 int flags)
      77  {
      78    if (file == NULL)
      79      return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
      80  
      81    return __utimensat64_helper (fd, file, &tsp64[0], flags);
      82  }
      83  
      84  #if __TIMESIZE != 64
      85  libc_hidden_def (__utimensat64)
      86  
      87  int
      88  __utimensat (int fd, const char *file, const struct timespec tsp[2],
      89               int flags)
      90  {
      91    struct __timespec64 tsp64[2];
      92    if (tsp)
      93      {
      94        tsp64[0] = valid_timespec_to_timespec64 (tsp[0]);
      95        tsp64[1] = valid_timespec_to_timespec64 (tsp[1]);
      96      }
      97  
      98    return __utimensat64 (fd, file, tsp ? &tsp64[0] : NULL, flags);
      99  }
     100  #endif
     101  weak_alias (__utimensat, utimensat)