LCOV - code coverage report
Current view: top level - cmdline - touch.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 28 28 100.0 %
Date: 2026-04-29 15:04:44 Functions: 1 1 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-3.0-or-later
       2             : // Copyright (C) 2014 Andrea Mazzoleni
       3             : 
       4             : #include "portable.h"
       5             : 
       6             : #include "support.h"
       7             : #include "elem.h"
       8             : #include "state.h"
       9             : #include "handle.h"
      10             : 
      11           1 : void state_touch(struct snapraid_state* state)
      12             : {
      13             :         tommy_node* i;
      14             :         char esc_buffer[ESC_MAX];
      15             : 
      16           1 :         msg_progress("Setting sub-second timestamps...\n");
      17             : 
      18             :         /* for all disks */
      19           7 :         for (i = state->disklist; i != 0; i = i->next) {
      20           6 :                 struct snapraid_disk* disk = i->data;
      21             :                 tommy_node* j;
      22             : 
      23             :                 /* for all files */
      24        5734 :                 for (j = disk->filelist; j != 0; j = j->next) {
      25        5728 :                         struct snapraid_file* file = j->data;
      26             : 
      27             :                         /*
      28             :                          * If the file has a zero nanosecond timestamp
      29             :                          * note that symbolic links are not in the file list
      30             :                          * and then are not processed
      31             :                          */
      32        5728 :                         if (file->mtime_nsec == 0) {
      33             :                                 char path[PATH_MAX];
      34             :                                 struct stat st;
      35             :                                 int f;
      36             :                                 int ret;
      37             :                                 int nsec;
      38             :                                 int flags;
      39             : 
      40          16 :                                 pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub);
      41             : 
      42             :                                 /* set a new nanosecond timestamp different than 0 */
      43             :                                 do {
      44             :                                         uint32_t nano;
      45             : 
      46             :                                         /* get a random nanosecond value */
      47          16 :                                         if (randomize(&nano, sizeof(nano)) != 0) {
      48             :                                                 /* LCOV_EXCL_START */
      49             :                                                 log_fatal(errno, "Failed to retrieve random values.\n");
      50             :                                                 exit(EXIT_FAILURE);
      51             :                                                 /* LCOV_EXCL_STOP */
      52             :                                         }
      53             : 
      54          16 :                                         nsec = nano % 1000000000;
      55          16 :                                 } while (nsec == 0);
      56             : 
      57             :                                 /*
      58             :                                  * O_BINARY: open as binary file (Windows only)
      59             :                                  * O_NOFOLLOW: do not follow links to ensure to open the real file
      60             :                                  */
      61          16 :                                 flags = O_BINARY | O_NOFOLLOW;
      62             : #ifdef _WIN32
      63             :                                 /* in Windows we must have write access at the file */
      64             :                                 flags |= O_RDWR;
      65             : #else
      66             :                                 /* in all others platforms, read access is enough */
      67          16 :                                 flags |= O_RDONLY;
      68             : #endif
      69             : 
      70             :                                 /* open it */
      71          16 :                                 f = open(path, flags);
      72          16 :                                 if (f == -1) {
      73             :                                         /* LCOV_EXCL_START */
      74             :                                         log_error(errno, "Error opening file '%s'. %s.\n", path, strerror(errno));
      75             :                                         continue;
      76             :                                         /* LCOV_EXCL_STOP */
      77             :                                 }
      78             : 
      79             :                                 /*
      80             :                                  * Get the present timestamp, that may be different than the one
      81             :                                  * in the content file
      82             :                                  */
      83          16 :                                 ret = fstat(f, &st);
      84          16 :                                 if (ret == -1) {
      85             :                                         /* LCOV_EXCL_START */
      86             :                                         close(f);
      87             :                                         log_error(errno, "Error accessing file '%s'. %s.\n", path, strerror(errno));
      88             :                                         continue;
      89             :                                         /* LCOV_EXCL_STOP */
      90             :                                 }
      91             : 
      92             :                                 /* set the tweaked modification time, with new nano seconds */
      93          16 :                                 ret = fmtime(f, st.st_mtime, nsec);
      94          16 :                                 if (ret != 0) {
      95             :                                         /* LCOV_EXCL_START */
      96             :                                         close(f);
      97             :                                         log_error(errno, "Error timing file '%s'. %s.\n", path, strerror(errno));
      98             :                                         continue;
      99             :                                         /* LCOV_EXCL_STOP */
     100             :                                 }
     101             : 
     102             :                                 /*
     103             :                                  * Uses fstat again to get the present timestamp
     104             :                                  * this is needed because the value read
     105             :                                  * may be different than the written one
     106             :                                  */
     107          16 :                                 ret = fstat(f, &st);
     108          16 :                                 if (ret == -1) {
     109             :                                         /* LCOV_EXCL_START */
     110             :                                         close(f);
     111             :                                         log_error(errno, "Error accessing file '%s'. %s.\n", path, strerror(errno));
     112             :                                         continue;
     113             :                                         /* LCOV_EXCL_STOP */
     114             :                                 }
     115             : 
     116             :                                 /* close it */
     117          16 :                                 ret = close(f);
     118          16 :                                 if (ret != 0) {
     119             :                                         /* LCOV_EXCL_START */
     120             :                                         log_error(errno, "Error closing file '%s'. %s.\n", path, strerror(errno));
     121             :                                         continue;
     122             :                                         /* LCOV_EXCL_STOP */
     123             :                                 }
     124             : 
     125             :                                 /*
     126             :                                  * Set the same nanosecond value in the content file
     127             :                                  * note that if the seconds value is already matching
     128             :                                  * the file won't be synced because the content file will
     129             :                                  * contain the new updated timestamp
     130             :                                  */
     131          16 :                                 file->mtime_nsec = STAT_NSEC(&st);
     132             : 
     133             :                                 /* state changed, we need to update it */
     134          16 :                                 state->need_write = 1;
     135             : 
     136          16 :                                 log_tag("touch:%s:%s: %" PRIu64 ".%d\n", disk->name, esc_tag(file->sub, esc_buffer), (uint64_t)st.st_mtime, STAT_NSEC(&st));
     137          16 :                                 msg_info("touch %s\n", fmt_term(disk, file->sub, esc_buffer));
     138             :                         }
     139             :                 }
     140             :         }
     141           1 : }
     142             : 

Generated by: LCOV version 1.0