root/maint/gnulib/tests/test-utimens.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. test_utimens

   1 /* Test of file timestamp modification functions.
   2    Copyright (C) 2009-2021 Free Software Foundation, Inc.
   3 
   4    This program is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU General Public License as published by
   6    the Free Software Foundation; either version 3 of the License, or
   7    (at your option) any later version.
   8 
   9    This program is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU General Public License for more details.
  13 
  14    You should have received a copy of the GNU General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 #include "test-utimens-common.h"
  18 
  19 /* This file is designed to test both utimens(a,b) and
  20    utimensat(AT_FDCWD,a,b,0).  FUNC is the function to test.  Assumes
  21    that BASE and ASSERT are already defined.  If PRINT, warn before
  22    skipping tests with status 77.  */
  23 static int
  24 test_utimens (int (*func) (char const *, struct timespec const *), bool print)
     /* [previous][next][first][last][top][bottom][index][help] */
  25 {
  26   struct stat st1;
  27   struct stat st2;
  28 
  29   ASSERT (close (creat (BASE "file", 0600)) == 0);
  30   /* If utimens truncates to worse resolution than the file system
  31      supports, then time can appear to go backwards between now and a
  32      follow-up utimens with UTIME_NOW or a NULL timespec.  Use
  33      UTIMECMP_TRUNCATE_SOURCE to compensate, with st1 as the
  34      source.  */
  35   ASSERT (stat (BASE "file", &st1) == 0);
  36   nap ();
  37   ASSERT (func (BASE "file", NULL) == 0);
  38   ASSERT (stat (BASE "file", &st2) == 0);
  39   ASSERT (0 <= utimecmp (BASE "file", &st2, &st1, UTIMECMP_TRUNCATE_SOURCE));
  40   if (check_ctime)
  41     ASSERT (ctime_compare (&st1, &st2) < 0);
  42   {
  43     /* On some NFS systems, the 'now' timestamp of creat or a NULL
  44        timespec is determined by the server, but the 'now' timestamp
  45        determined by gettime() (as is done when using UTIME_NOW) is
  46        determined by the client; since the two machines are not
  47        necessarily on the same clock, this is another case where time
  48        can appear to go backwards.  The rest of this test cares about
  49        client time, so manually use gettime() to set both times.  */
  50     struct timespec ts[2];
  51     gettime (&ts[0]);
  52     ts[1] = ts[0];
  53     ASSERT (func (BASE "file", ts) == 0);
  54     ASSERT (stat (BASE "file", &st1) == 0);
  55     nap ();
  56   }
  57 
  58   /* Invalid arguments.  */
  59   errno = 0;
  60   ASSERT (func ("no_such", NULL) == -1);
  61   ASSERT (errno == ENOENT);
  62   errno = 0;
  63   ASSERT (func ("no_such/", NULL) == -1);
  64   ASSERT (errno == ENOENT || errno == ENOTDIR);
  65   errno = 0;
  66   ASSERT (func ("", NULL) == -1);
  67   ASSERT (errno == ENOENT);
  68   {
  69     struct timespec ts[2];
  70     ts[0].tv_sec = Y2K;
  71     ts[0].tv_nsec = UTIME_BOGUS_POS;
  72     ts[1].tv_sec = Y2K;
  73     ts[1].tv_nsec = 0;
  74     errno = 0;
  75     ASSERT (func (BASE "file", ts) == -1);
  76     ASSERT (errno == EINVAL);
  77   }
  78   {
  79     struct timespec ts[2];
  80     ts[0].tv_sec = Y2K;
  81     ts[0].tv_nsec = 0;
  82     ts[1].tv_sec = Y2K;
  83     ts[1].tv_nsec = UTIME_BOGUS_NEG;
  84     errno = 0;
  85     ASSERT (func (BASE "file", ts) == -1);
  86     ASSERT (errno == EINVAL);
  87   }
  88   {
  89     struct timespec ts[2];
  90     ts[0].tv_sec = Y2K;
  91     ts[0].tv_nsec = 0;
  92     ts[1] = ts[0];
  93     errno = 0;
  94     ASSERT (func (BASE "file/", ts) == -1);
  95     ASSERT (errno == ENOTDIR || errno == EINVAL);
  96   }
  97   ASSERT (stat (BASE "file", &st2) == 0);
  98   ASSERT (st1.st_atime == st2.st_atime);
  99   ASSERT (get_stat_atime_ns (&st1) == get_stat_atime_ns (&st2));
 100   ASSERT (utimecmp (BASE "file", &st1, &st2, 0) == 0);
 101 
 102   /* Set both times.  */
 103   {
 104     struct timespec ts[2];
 105     ts[0].tv_sec = Y2K;
 106     ts[0].tv_nsec = BILLION / 2 - 1;
 107     ts[1].tv_sec = Y2K;
 108     ts[1].tv_nsec = BILLION - 1;
 109     ASSERT (func (BASE "file", ts) == 0);
 110     ASSERT (stat (BASE "file", &st2) == 0);
 111     ASSERT (st2.st_atime == Y2K);
 112     ASSERT (0 <= get_stat_atime_ns (&st2));
 113     ASSERT (get_stat_atime_ns (&st2) < BILLION / 2);
 114     ASSERT (st2.st_mtime == Y2K);
 115     ASSERT (0 <= get_stat_mtime_ns (&st2));
 116     ASSERT (get_stat_mtime_ns (&st2) < BILLION);
 117     if (check_ctime)
 118       ASSERT (ctime_compare (&st1, &st2) < 0);
 119   }
 120 
 121   /* Play with UTIME_OMIT, UTIME_NOW.  */
 122   {
 123     struct stat st3;
 124     struct timespec ts[2];
 125     ts[0].tv_sec = BILLION;
 126     ts[0].tv_nsec = UTIME_OMIT;
 127     ts[1].tv_sec = 0;
 128     ts[1].tv_nsec = UTIME_NOW;
 129     nap ();
 130     ASSERT (func (BASE "file", ts) == 0);
 131     ASSERT (stat (BASE "file", &st3) == 0);
 132     ASSERT (st3.st_atime == Y2K);
 133     ASSERT (0 <= get_stat_atime_ns (&st3));
 134     ASSERT (get_stat_atime_ns (&st3) < BILLION / 2);
 135     /* See comment above about this utimecmp call.  */
 136     ASSERT (0 <= utimecmp (BASE "file", &st3, &st1, UTIMECMP_TRUNCATE_SOURCE));
 137     if (check_ctime)
 138       ASSERT (ctime_compare (&st2, &st3) < 0);
 139     nap ();
 140     ts[0].tv_nsec = 0;
 141     ts[1].tv_nsec = UTIME_OMIT;
 142     ASSERT (func (BASE "file", ts) == 0);
 143     ASSERT (stat (BASE "file", &st2) == 0);
 144     ASSERT (st2.st_atime == BILLION);
 145     ASSERT (get_stat_atime_ns (&st2) == 0);
 146     ASSERT (st3.st_mtime == st2.st_mtime);
 147     ASSERT (get_stat_mtime_ns (&st3) == get_stat_mtime_ns (&st2));
 148     if (check_ctime > 0)
 149       ASSERT (ctime_compare (&st3, &st2) < 0);
 150   }
 151 
 152   /* Make sure this dereferences symlinks.  */
 153   if (symlink (BASE "file", BASE "link"))
 154     {
 155       ASSERT (unlink (BASE "file") == 0);
 156       if (print)
 157         fputs ("skipping test: symlinks not supported on this file system\n",
 158                stderr);
 159       return 77;
 160     }
 161   ASSERT (lstat (BASE "link", &st1) == 0);
 162   ASSERT (st1.st_mtime != Y2K);
 163   errno = 0;
 164   ASSERT (func (BASE "link/", NULL) == -1);
 165   ASSERT (errno == ENOTDIR);
 166   {
 167     struct timespec ts[2];
 168     ts[0].tv_sec = Y2K;
 169     ts[0].tv_nsec = 0;
 170     ts[1] = ts[0];
 171     ASSERT (func (BASE "link", ts) == 0);
 172     ASSERT (lstat (BASE "link", &st2) == 0);
 173     /* Can't compare atimes, since lstat() changes symlink atime on cygwin.  */
 174     ASSERT (st1.st_mtime == st2.st_mtime);
 175     ASSERT (stat (BASE "link", &st2) == 0);
 176     ASSERT (st2.st_mtime == Y2K);
 177     ASSERT (get_stat_mtime_ns (&st2) == 0);
 178   }
 179 
 180   /* Cleanup.  */
 181   ASSERT (unlink (BASE "link") == 0);
 182   ASSERT (unlink (BASE "file") == 0);
 183   return 0;
 184 }

/* [previous][next][first][last][top][bottom][index][help] */