(root)/
glibc-2.38/
sysdeps/
mach/
hurd/
utime-helper.c
       1  /* Helpers for utimes/utimens conversions.
       2     Copyright (C) 2015-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 <hurd/hurd_types.h>
      21  #include <stddef.h>
      22  #include <sys/time.h>
      23  
      24  /* Initializes atime/mtime timespec structures from an array of timeval.  */
      25  static inline void
      26  utime_ts_from_tval (const struct timeval tvp[2],
      27                      struct timespec *atime, struct timespec *mtime)
      28  {
      29    if (tvp == NULL)
      30      {
      31        /* Setting the number of nanoseconds to UTIME_NOW tells the
      32           underlying filesystems to use the current time.  */
      33        atime->tv_sec = 0;
      34        atime->tv_nsec = UTIME_NOW;
      35        mtime->tv_sec = 0;
      36        mtime->tv_nsec = UTIME_NOW;
      37      }
      38    else
      39      {
      40        TIMEVAL_TO_TIMESPEC (&tvp[0], atime);
      41        TIMEVAL_TO_TIMESPEC (&tvp[1], mtime);
      42      }
      43  }
      44  
      45  /* Initializes atime/mtime time_value_t structures from an array of timeval.  */
      46  static inline void
      47  utime_tvalue_from_tval (const struct timeval tvp[2],
      48                          time_value_t *atime, time_value_t *mtime)
      49  {
      50    if (tvp == NULL)
      51      /* Setting the number of microseconds to `-1' tells the
      52         underlying filesystems to use the current time.  */
      53      atime->microseconds = mtime->microseconds = -1;
      54    else
      55      {
      56        atime->seconds = tvp[0].tv_sec;
      57        atime->microseconds = tvp[0].tv_usec;
      58        mtime->seconds = tvp[1].tv_sec;
      59        mtime->microseconds = tvp[1].tv_usec;
      60      }
      61  }
      62  
      63  /* Changes the access time of the file behind PORT using a timeval array.  */
      64  static inline error_t
      65  hurd_futimes (const file_t port, const struct timeval tvp[2])
      66  {
      67    error_t err;
      68    struct timespec atime, mtime;
      69  
      70    utime_ts_from_tval (tvp, &atime, &mtime);
      71  
      72    err = __file_utimens (port, atime, mtime);
      73  
      74    if (err == MIG_BAD_ID || err == EOPNOTSUPP)
      75      {
      76        time_value_t atim, mtim;
      77  
      78        utime_tvalue_from_tval (tvp, &atim, &mtim);
      79  
      80        err = __file_utimes (port, atim, mtim);
      81      }
      82  
      83    return err;
      84  }
      85  
      86  /* Initializes atime/mtime timespec structures from an array of timespec.  */
      87  static inline void
      88  utime_ts_from_tspec (const struct timespec tsp[2],
      89                       struct timespec *atime, struct timespec *mtime)
      90  {
      91    if (tsp == NULL)
      92      {
      93        /* Setting the number of nanoseconds to UTIME_NOW tells the
      94           underlying filesystems to use the current time.  */
      95        atime->tv_sec = 0;
      96        atime->tv_nsec = UTIME_NOW;
      97        mtime->tv_sec = 0;
      98        mtime->tv_nsec = UTIME_NOW;
      99      }
     100    else
     101      {
     102        *atime = tsp[0];
     103        *mtime = tsp[1];
     104      }
     105  }
     106  
     107  /* Initializes atime/mtime time_value_t structures from an array of timespec.  */
     108  static inline void
     109  utime_tvalue_from_tspec (const struct timespec tsp[2],
     110                           time_value_t *atime, time_value_t *mtime)
     111  {
     112    if (tsp == NULL)
     113      /* Setting the number of microseconds to `-1' tells the
     114         underlying filesystems to use the current time.  */
     115      atime->microseconds = mtime->microseconds = -1;
     116    else
     117      {
     118        if (tsp[0].tv_nsec == UTIME_NOW)
     119  	atime->microseconds = -1;
     120        else if (tsp[0].tv_nsec == UTIME_OMIT)
     121  	atime->microseconds = -2;
     122        else
     123  	TIMESPEC_TO_TIME_VALUE (atime, &(tsp[0]));
     124        if (tsp[1].tv_nsec == UTIME_NOW)
     125  	mtime->microseconds = -1;
     126        else if (tsp[1].tv_nsec == UTIME_OMIT)
     127  	mtime->microseconds = -2;
     128        else
     129  	TIMESPEC_TO_TIME_VALUE (mtime, &(tsp[1]));
     130      }
     131  }
     132  
     133  /* Changes the access time of the file behind PORT using a timespec array.  */
     134  static inline error_t
     135  hurd_futimens (const file_t port, const struct timespec tsp[2])
     136  {
     137    error_t err;
     138    struct timespec atime, mtime;
     139  
     140    utime_ts_from_tspec (tsp, &atime, &mtime);
     141  
     142    err = __file_utimens (port, atime, mtime);
     143  
     144    if (err == MIG_BAD_ID || err == EOPNOTSUPP)
     145      {
     146        time_value_t atim, mtim;
     147  
     148        utime_tvalue_from_tspec (tsp, &atim, &mtim);
     149  
     150        err = __file_utimes (port, atim, mtim);
     151      }
     152  
     153    return err;
     154  }