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: 2017-11-06 22:14:04 Functions: 1 1 100.0 %

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

Generated by: LCOV version 1.13