mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
1956 lines
199 KiB
HTML
1956 lines
199 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
<title>LCOV - lcov.info - cmdline/scan.c</title>
|
|
<link rel="stylesheet" type="text/css" href="../gcov.css">
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<table width="100%" border=0 cellspacing=0 cellpadding=0>
|
|
<tr><td class="title">LCOV - code coverage report</td></tr>
|
|
<tr><td class="ruler"><img src="../glass.png" width=3 height=3 alt=""></td></tr>
|
|
|
|
<tr>
|
|
<td width="100%">
|
|
<table cellpadding=1 border=0 width="100%">
|
|
<tr>
|
|
<td width="10%" class="headerItem">Current view:</td>
|
|
<td width="35%" class="headerValue"><a href="../index.html">top level</a> - <a href="index.html">cmdline</a> - scan.c<span style="font-size: 80%;"> (source / <a href="scan.c.func.html">functions</a>)</span></td>
|
|
<td width="5%"></td>
|
|
<td width="15%"></td>
|
|
<td width="10%" class="headerCovTableHead">Hit</td>
|
|
<td width="10%" class="headerCovTableHead">Total</td>
|
|
<td width="15%" class="headerCovTableHead">Coverage</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="headerItem">Test:</td>
|
|
<td class="headerValue">lcov.info</td>
|
|
<td></td>
|
|
<td class="headerItem">Lines:</td>
|
|
<td class="headerCovTableEntry">565</td>
|
|
<td class="headerCovTableEntry">631</td>
|
|
<td class="headerCovTableEntryMed">89.5 %</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="headerItem">Date:</td>
|
|
<td class="headerValue">2016-11-21</td>
|
|
<td></td>
|
|
<td class="headerItem">Functions:</td>
|
|
<td class="headerCovTableEntry">23</td>
|
|
<td class="headerCovTableEntry">23</td>
|
|
<td class="headerCovTableEntryHi">100.0 %</td>
|
|
</tr>
|
|
<tr><td><img src="../glass.png" width=3 height=3 alt=""></td></tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr><td class="ruler"><img src="../glass.png" width=3 height=3 alt=""></td></tr>
|
|
</table>
|
|
|
|
<table cellpadding=0 cellspacing=0 border=0>
|
|
<tr>
|
|
<td><br></td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<pre class="sourceHeading"> Line data Source code</pre>
|
|
<pre class="source">
|
|
<a name="1"><span class="lineNum"> 1 </span> : /*</a>
|
|
<span class="lineNum"> 2 </span> : * Copyright (C) 2011 Andrea Mazzoleni
|
|
<span class="lineNum"> 3 </span> : *
|
|
<span class="lineNum"> 4 </span> : * This program is free software: you can redistribute it and/or modify
|
|
<span class="lineNum"> 5 </span> : * it under the terms of the GNU General Public License as published by
|
|
<span class="lineNum"> 6 </span> : * the Free Software Foundation, either version 3 of the License, or
|
|
<span class="lineNum"> 7 </span> : * (at your option) any later version.
|
|
<span class="lineNum"> 8 </span> : *
|
|
<span class="lineNum"> 9 </span> : * This program is distributed in the hope that it will be useful,
|
|
<span class="lineNum"> 10 </span> : * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
<span class="lineNum"> 11 </span> : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
<span class="lineNum"> 12 </span> : * GNU General Public License for more details.
|
|
<span class="lineNum"> 13 </span> : *
|
|
<span class="lineNum"> 14 </span> : * You should have received a copy of the GNU General Public License
|
|
<span class="lineNum"> 15 </span> : * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
<span class="lineNum"> 16 </span> : */
|
|
<span class="lineNum"> 17 </span> :
|
|
<span class="lineNum"> 18 </span> : #include "portable.h"
|
|
<span class="lineNum"> 19 </span> :
|
|
<span class="lineNum"> 20 </span> : #include "support.h"
|
|
<span class="lineNum"> 21 </span> : #include "elem.h"
|
|
<span class="lineNum"> 22 </span> : #include "state.h"
|
|
<span class="lineNum"> 23 </span> : #include "parity.h"
|
|
<span class="lineNum"> 24 </span> :
|
|
<span class="lineNum"> 25 </span> : struct snapraid_scan {
|
|
<span class="lineNum"> 26 </span> : struct snapraid_state* state; /**< State used. */
|
|
<span class="lineNum"> 27 </span> : struct snapraid_disk* disk; /**< Disk used. */
|
|
<span class="lineNum"> 28 </span> :
|
|
<span class="lineNum"> 29 </span> : /**
|
|
<span class="lineNum"> 30 </span> : * Counters of changes.
|
|
<span class="lineNum"> 31 </span> : */
|
|
<span class="lineNum"> 32 </span> : unsigned count_equal; /**< Files equal. */
|
|
<span class="lineNum"> 33 </span> : unsigned count_move; /**< Files with a different name, but equal inode, size and timestamp in the same disk. */
|
|
<span class="lineNum"> 34 </span> : unsigned count_restore; /**< Files with equal name, size and timestamp, but different inode. */
|
|
<span class="lineNum"> 35 </span> : unsigned count_change; /**< Files with same name, but different size and/or timestamp. */
|
|
<span class="lineNum"> 36 </span> : unsigned count_copy; /**< Files new, with same name size and timestamp of a file in a different disk. */
|
|
<span class="lineNum"> 37 </span> : unsigned count_insert; /**< Files new. */
|
|
<span class="lineNum"> 38 </span> : unsigned count_remove; /**< Files removed. */
|
|
<span class="lineNum"> 39 </span> :
|
|
<span class="lineNum"> 40 </span> : tommy_list file_insert_list; /**< Files to insert. */
|
|
<span class="lineNum"> 41 </span> : tommy_list link_insert_list; /**< Links to insert. */
|
|
<span class="lineNum"> 42 </span> : tommy_list dir_insert_list; /**< Dirs to insert. */
|
|
<span class="lineNum"> 43 </span> :
|
|
<span class="lineNum"> 44 </span> : /* nodes for data structures */
|
|
<span class="lineNum"> 45 </span> : tommy_node node;
|
|
<span class="lineNum"> 46 </span> : };
|
|
<span class="lineNum"> 47 </span> :
|
|
<span class="lineNum"> 48 </span> : /**
|
|
<a name="49"><span class="lineNum"> 49 </span> : * Remove the specified link from the data set.</a>
|
|
<span class="lineNum"> 50 </span> : */
|
|
<span class="lineNum"> 51 </span><span class="lineCov"> 956 : static void scan_link_remove(struct snapraid_scan* scan, struct snapraid_link* slink)</span>
|
|
<span class="lineNum"> 52 </span> : {
|
|
<span class="lineNum"> 53 </span><span class="lineCov"> 956 : struct snapraid_state* state = scan->state;</span>
|
|
<span class="lineNum"> 54 </span><span class="lineCov"> 956 : struct snapraid_disk* disk = scan->disk;</span>
|
|
<span class="lineNum"> 55 </span> :
|
|
<span class="lineNum"> 56 </span> : /* state changed */
|
|
<span class="lineNum"> 57 </span><span class="lineCov"> 956 : state->need_write = 1;</span>
|
|
<span class="lineNum"> 58 </span> :
|
|
<span class="lineNum"> 59 </span> : /* remove the file from the link containers */
|
|
<span class="lineNum"> 60 </span><span class="lineCov"> 956 : tommy_hashdyn_remove_existing(&disk->linkset, &slink->nodeset);</span>
|
|
<span class="lineNum"> 61 </span><span class="lineCov"> 956 : tommy_list_remove_existing(&disk->linklist, &slink->nodelist);</span>
|
|
<span class="lineNum"> 62 </span> :
|
|
<span class="lineNum"> 63 </span> : /* deallocate */
|
|
<span class="lineNum"> 64 </span><span class="lineCov"> 956 : link_free(slink);</span>
|
|
<span class="lineNum"> 65 </span><span class="lineCov"> 956 : }</span>
|
|
<span class="lineNum"> 66 </span> :
|
|
<span class="lineNum"> 67 </span> : /**
|
|
<a name="68"><span class="lineNum"> 68 </span> : * Insert the specified link in the data set.</a>
|
|
<span class="lineNum"> 69 </span> : */
|
|
<span class="lineNum"> 70 </span><span class="lineCov"> 2457 : static void scan_link_insert(struct snapraid_scan* scan, struct snapraid_link* slink)</span>
|
|
<span class="lineNum"> 71 </span> : {
|
|
<span class="lineNum"> 72 </span><span class="lineCov"> 2457 : struct snapraid_state* state = scan->state;</span>
|
|
<span class="lineNum"> 73 </span><span class="lineCov"> 2457 : struct snapraid_disk* disk = scan->disk;</span>
|
|
<span class="lineNum"> 74 </span> :
|
|
<span class="lineNum"> 75 </span> : /* state changed */
|
|
<span class="lineNum"> 76 </span><span class="lineCov"> 2457 : state->need_write = 1;</span>
|
|
<span class="lineNum"> 77 </span> :
|
|
<span class="lineNum"> 78 </span> : /* insert the link in the link containers */
|
|
<span class="lineNum"> 79 </span><span class="lineCov"> 2457 : tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub));</span>
|
|
<span class="lineNum"> 80 </span><span class="lineCov"> 2457 : tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink);</span>
|
|
<span class="lineNum"> 81 </span><span class="lineCov"> 2457 : }</span>
|
|
<span class="lineNum"> 82 </span> :
|
|
<span class="lineNum"> 83 </span> : /**
|
|
<a name="84"><span class="lineNum"> 84 </span> : * Process a symbolic link.</a>
|
|
<span class="lineNum"> 85 </span> : */
|
|
<span class="lineNum"> 86 </span><span class="lineCov"> 36184 : static void scan_link(struct snapraid_scan* scan, int is_diff, const char* sub, const char* linkto, unsigned link_flag)</span>
|
|
<span class="lineNum"> 87 </span> : {
|
|
<span class="lineNum"> 88 </span><span class="lineCov"> 36184 : struct snapraid_state* state = scan->state;</span>
|
|
<span class="lineNum"> 89 </span><span class="lineCov"> 36184 : struct snapraid_disk* disk = scan->disk;</span>
|
|
<span class="lineNum"> 90 </span> : struct snapraid_link* slink;
|
|
<span class="lineNum"> 91 </span> : char esc_buffer[ESC_MAX];
|
|
<span class="lineNum"> 92 </span> :
|
|
<span class="lineNum"> 93 </span> : /* check if the link already exists */
|
|
<span class="lineNum"> 94 </span><span class="lineCov"> 36184 : slink = tommy_hashdyn_search(&disk->linkset, link_name_compare_to_arg, sub, link_name_hash(sub));</span>
|
|
<span class="lineNum"> 95 </span><span class="lineCov"> 36184 : if (slink) {</span>
|
|
<span class="lineNum"> 96 </span> : /* check if multiple files have the same name */
|
|
<span class="lineNum"> 97 </span><span class="lineCov"> 33727 : if (link_flag_has(slink, FILE_IS_PRESENT)) {</span>
|
|
<span class="lineNum"> 98 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 99 </span> : log_fatal("Internal inconsistency for link '%s%s'\n", disk->dir, sub);
|
|
<span class="lineNum"> 100 </span> : os_abort();
|
|
<span class="lineNum"> 101 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 102 </span> : }
|
|
<span class="lineNum"> 103 </span> :
|
|
<span class="lineNum"> 104 </span> : /* mark as present */
|
|
<span class="lineNum"> 105 </span><span class="lineCov"> 33727 : link_flag_set(slink, FILE_IS_PRESENT);</span>
|
|
<span class="lineNum"> 106 </span> :
|
|
<span class="lineNum"> 107 </span> : /* check if the link is not changed and it's of the same kind */
|
|
<span class="lineNum"> 108 </span><span class="lineCov"> 33727 : if (strcmp(slink->linkto, linkto) == 0 && link_flag == link_flag_get(slink, FILE_IS_LINK_MASK)) {</span>
|
|
<span class="lineNum"> 109 </span> : /* it's equal */
|
|
<span class="lineNum"> 110 </span><span class="lineCov"> 33721 : ++scan->count_equal;</span>
|
|
<span class="lineNum"> 111 </span> :
|
|
<span class="lineNum"> 112 </span><span class="lineCov"> 67442 : if (state->opt.gui) {</span>
|
|
<span class="lineNum"> 113 </span><span class="lineCov"> 829 : log_tag("scan:equal:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer));</span>
|
|
<span class="lineNum"> 114 </span> : }
|
|
<span class="lineNum"> 115 </span> : } else {
|
|
<span class="lineNum"> 116 </span> : /* it's an update */
|
|
<span class="lineNum"> 117 </span> :
|
|
<span class="lineNum"> 118 </span> : /* we have to save the linkto/type */
|
|
<span class="lineNum"> 119 </span><span class="lineCov"> 6 : state->need_write = 1;</span>
|
|
<span class="lineNum"> 120 </span> :
|
|
<span class="lineNum"> 121 </span><span class="lineCov"> 6 : ++scan->count_change;</span>
|
|
<span class="lineNum"> 122 </span> :
|
|
<span class="lineNum"> 123 </span><span class="lineCov"> 6 : log_tag("scan:update:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer));</span>
|
|
<span class="lineNum"> 124 </span><span class="lineCov"> 6 : if (is_diff) {</span>
|
|
<span class="lineNum"> 125 </span><span class="lineCov"> 3 : printf("update %s\n", fmt_term(disk, slink->sub, esc_buffer));</span>
|
|
<span class="lineNum"> 126 </span> : }
|
|
<span class="lineNum"> 127 </span> :
|
|
<span class="lineNum"> 128 </span> : /* update it */
|
|
<span class="lineNum"> 129 </span><span class="lineCov"> 6 : free(slink->linkto);</span>
|
|
<span class="lineNum"> 130 </span><span class="lineCov"> 6 : slink->linkto = strdup_nofail(linkto);</span>
|
|
<span class="lineNum"> 131 </span><span class="lineCov"> 6 : link_flag_let(slink, link_flag, FILE_IS_LINK_MASK);</span>
|
|
<span class="lineNum"> 132 </span> : }
|
|
<span class="lineNum"> 133 </span> :
|
|
<span class="lineNum"> 134 </span> : /* nothing more to do */
|
|
<span class="lineNum"> 135 </span><span class="lineCov"> 69911 : return;</span>
|
|
<span class="lineNum"> 136 </span> : } else {
|
|
<span class="lineNum"> 137 </span> : /* create the new link */
|
|
<span class="lineNum"> 138 </span><span class="lineCov"> 2457 : ++scan->count_insert;</span>
|
|
<span class="lineNum"> 139 </span> :
|
|
<span class="lineNum"> 140 </span><span class="lineCov"> 2457 : log_tag("scan:add:%s:%s\n", disk->name, esc_tag(sub, esc_buffer));</span>
|
|
<span class="lineNum"> 141 </span><span class="lineCov"> 2457 : if (is_diff) {</span>
|
|
<span class="lineNum"> 142 </span><span class="lineCov"> 599 : printf("add %s\n", fmt_term(disk, sub, esc_buffer));</span>
|
|
<span class="lineNum"> 143 </span> : }
|
|
<span class="lineNum"> 144 </span> :
|
|
<span class="lineNum"> 145 </span> : /* and continue to insert it */
|
|
<span class="lineNum"> 146 </span> : }
|
|
<span class="lineNum"> 147 </span> :
|
|
<span class="lineNum"> 148 </span> : /* insert it */
|
|
<span class="lineNum"> 149 </span><span class="lineCov"> 2457 : slink = link_alloc(sub, linkto, link_flag);</span>
|
|
<span class="lineNum"> 150 </span> :
|
|
<span class="lineNum"> 151 </span> : /* mark it as present */
|
|
<span class="lineNum"> 152 </span><span class="lineCov"> 2457 : link_flag_set(slink, FILE_IS_PRESENT);</span>
|
|
<span class="lineNum"> 153 </span> :
|
|
<span class="lineNum"> 154 </span> : /* insert it in the delayed insert list */
|
|
<span class="lineNum"> 155 </span><span class="lineCov"> 2457 : tommy_list_insert_tail(&scan->link_insert_list, &slink->nodelist, slink);</span>
|
|
<span class="lineNum"> 156 </span> : }
|
|
<span class="lineNum"> 157 </span> :
|
|
<span class="lineNum"> 158 </span> : /**
|
|
<a name="159"><span class="lineNum"> 159 </span> : * Insert the specified file in the parity.</a>
|
|
<span class="lineNum"> 160 </span> : */
|
|
<span class="lineNum"> 161 </span><span class="lineCov"> 101881 : static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file* file)</span>
|
|
<span class="lineNum"> 162 </span> : {
|
|
<span class="lineNum"> 163 </span><span class="lineCov"> 101881 : struct snapraid_state* state = scan->state;</span>
|
|
<span class="lineNum"> 164 </span><span class="lineCov"> 101881 : struct snapraid_disk* disk = scan->disk;</span>
|
|
<span class="lineNum"> 165 </span> : block_off_t i;
|
|
<span class="lineNum"> 166 </span> : block_off_t parity_pos;
|
|
<span class="lineNum"> 167 </span> :
|
|
<span class="lineNum"> 168 </span> : /* state changed */
|
|
<span class="lineNum"> 169 </span><span class="lineCov"> 101881 : state->need_write = 1;</span>
|
|
<span class="lineNum"> 170 </span> :
|
|
<span class="lineNum"> 171 </span> : /* allocate the blocks of the file */
|
|
<span class="lineNum"> 172 </span><span class="lineCov"> 101881 : parity_pos = disk->first_free_block;</span>
|
|
<span class="lineNum"> 173 </span><span class="lineCov"> 353073 : for (i = 0; i < file->blockmax; ++i) {</span>
|
|
<span class="lineNum"> 174 </span> : struct snapraid_block* block;
|
|
<span class="lineNum"> 175 </span> : struct snapraid_block* over_block;
|
|
<span class="lineNum"> 176 </span> : snapraid_info info;
|
|
<span class="lineNum"> 177 </span> :
|
|
<span class="lineNum"> 178 </span> : /* increment the position until the first really free block */
|
|
<span class="lineNum"> 179 </span><span class="lineCov"> 1022715 : while (block_has_file(fs_par2block_find(disk, parity_pos)))</span>
|
|
<span class="lineNum"> 180 </span><span class="lineCov"> 520331 : ++parity_pos;</span>
|
|
<span class="lineNum"> 181 </span> :
|
|
<span class="lineNum"> 182 </span> : /* get block we are going to overwrite, if any */
|
|
<span class="lineNum"> 183 </span><span class="lineCov"> 251192 : over_block = fs_par2block_find(disk, parity_pos);</span>
|
|
<span class="lineNum"> 184 </span> :
|
|
<span class="lineNum"> 185 </span> : /* deallocate it */
|
|
<span class="lineNum"> 186 </span><span class="lineCov"> 251192 : if (over_block != BLOCK_NULL)</span>
|
|
<span class="lineNum"> 187 </span><span class="lineCov"> 95279 : fs_deallocate(disk, parity_pos);</span>
|
|
<span class="lineNum"> 188 </span> :
|
|
<span class="lineNum"> 189 </span> : /* get block specific info */
|
|
<span class="lineNum"> 190 </span><span class="lineCov"> 251192 : info = info_get(&state->infoarr, parity_pos);</span>
|
|
<span class="lineNum"> 191 </span> :
|
|
<span class="lineNum"> 192 </span> : /* get the new block we are going to write */
|
|
<span class="lineNum"> 193 </span><span class="lineCov"> 251192 : block = fs_file2block_get(file, i);</span>
|
|
<span class="lineNum"> 194 </span> :
|
|
<span class="lineNum"> 195 </span> : /* if the file block already has an updated hash without rehash */
|
|
<span class="lineNum"> 196 </span><span class="lineCov"> 251192 : if (block_has_updated_hash(block) && !info_get_rehash(info)) {</span>
|
|
<span class="lineNum"> 197 </span> : /* the only possible case is for REP blocks */
|
|
<span class="lineNum"> 198 </span><span class="lineCov"> 86215 : assert(block_state_get(block) == BLOCK_STATE_REP);</span>
|
|
<span class="lineNum"> 199 </span> :
|
|
<span class="lineNum"> 200 </span> : /* convert to a REP block */
|
|
<span class="lineNum"> 201 </span><span class="lineCov"> 86215 : block_state_set(block, BLOCK_STATE_REP);</span>
|
|
<span class="lineNum"> 202 </span> :
|
|
<span class="lineNum"> 203 </span> : /* and keep the hash as it's */
|
|
<span class="lineNum"> 204 </span> : } else {
|
|
<span class="lineNum"> 205 </span> : unsigned over_state;
|
|
<span class="lineNum"> 206 </span> :
|
|
<span class="lineNum"> 207 </span> : /* convert to a CHG block */
|
|
<span class="lineNum"> 208 </span><span class="lineCov"> 164977 : block_state_set(block, BLOCK_STATE_CHG);</span>
|
|
<span class="lineNum"> 209 </span> :
|
|
<span class="lineNum"> 210 </span> : /* state of the block we are going to overwrite */
|
|
<span class="lineNum"> 211 </span><span class="lineCov"> 164977 : over_state = block_state_get(over_block);</span>
|
|
<span class="lineNum"> 212 </span> :
|
|
<span class="lineNum"> 213 </span> : /* if the block is an empty one */
|
|
<span class="lineNum"> 214 </span><span class="lineCov"> 164977 : if (over_state == BLOCK_STATE_EMPTY) {</span>
|
|
<span class="lineNum"> 215 </span> : /* the block was empty and filled with zeros */
|
|
<span class="lineNum"> 216 </span> : /* set the hash to the special ZERO value */
|
|
<span class="lineNum"> 217 </span><span class="lineCov"> 115543 : hash_zero_set(block->hash);</span>
|
|
<span class="lineNum"> 218 </span> : } else {
|
|
<span class="lineNum"> 219 </span> : /* otherwise it's a DELETED one */
|
|
<span class="lineNum"> 220 </span><span class="lineCov"> 49434 : assert(over_state == BLOCK_STATE_DELETED);</span>
|
|
<span class="lineNum"> 221 </span> :
|
|
<span class="lineNum"> 222 </span> : /* copy the past hash of the block */
|
|
<span class="lineNum"> 223 </span><span class="lineCov"> 49434 : memcpy(block->hash, over_block->hash, BLOCK_HASH_SIZE);</span>
|
|
<span class="lineNum"> 224 </span> :
|
|
<span class="lineNum"> 225 </span> : /* if we have not already cleared the past hash */
|
|
<span class="lineNum"> 226 </span><span class="lineCov"> 49434 : if (!state->clear_past_hash) {</span>
|
|
<span class="lineNum"> 227 </span> : /* in this case we don't know if the old state is still the one */
|
|
<span class="lineNum"> 228 </span> : /* stored inside the parity, because after an aborted sync, the parity */
|
|
<span class="lineNum"> 229 </span> : /* may be or may be not have been updated with the new data */
|
|
<span class="lineNum"> 230 </span> : /* Then we reset the hash to a bogus value */
|
|
<span class="lineNum"> 231 </span> : /* For example: */
|
|
<span class="lineNum"> 232 </span> : /* - One file is deleted */
|
|
<span class="lineNum"> 233 </span> : /* - Sync aborted after, updating the parity to the new state, */
|
|
<span class="lineNum"> 234 </span> : /* but without saving the content file representing this new state. */
|
|
<span class="lineNum"> 235 </span> : /* - Another file is added again (exactly here) */
|
|
<span class="lineNum"> 236 </span> : /* with the hash of DELETED block not representing the real parity state */
|
|
<span class="lineNum"> 237 </span><span class="lineCov"> 421 : hash_invalid_set(block->hash);</span>
|
|
<span class="lineNum"> 238 </span> : }
|
|
<span class="lineNum"> 239 </span> : }
|
|
<span class="lineNum"> 240 </span> : }
|
|
<span class="lineNum"> 241 </span> :
|
|
<span class="lineNum"> 242 </span> : /* store in the disk map, after invalidating all the other blocks */
|
|
<span class="lineNum"> 243 </span><span class="lineCov"> 251192 : fs_allocate(disk, parity_pos, file, i);</span>
|
|
<span class="lineNum"> 244 </span> :
|
|
<span class="lineNum"> 245 </span> : /* set the new free position */
|
|
<span class="lineNum"> 246 </span><span class="lineCov"> 251192 : disk->first_free_block = parity_pos + 1;</span>
|
|
<span class="lineNum"> 247 </span> : }
|
|
<span class="lineNum"> 248 </span> :
|
|
<span class="lineNum"> 249 </span> : /* insert in the list of contained files */
|
|
<span class="lineNum"> 250 </span><span class="lineCov"> 101881 : tommy_list_insert_tail(&disk->filelist, &file->nodelist, file);</span>
|
|
<span class="lineNum"> 251 </span><span class="lineCov"> 101881 : }</span>
|
|
<span class="lineNum"> 252 </span> :
|
|
<span class="lineNum"> 253 </span> : /**
|
|
<span class="lineNum"> 254 </span> : * Delete the specified file from the parity.
|
|
<span class="lineNum"> 255 </span> : *
|
|
<span class="lineNum"> 256 </span> : * Note that the parity remains allocated, but the blocks and the file are marked as DELETED.
|
|
<span class="lineNum"> 257 </span> : * The file is then inserted in the deleted set, and it should not be deallocated,
|
|
<a name="258"><span class="lineNum"> 258 </span> : * as the parity still references it.</a>
|
|
<span class="lineNum"> 259 </span> : */
|
|
<span class="lineNum"> 260 </span><span class="lineCov"> 57015 : static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_file* file)</span>
|
|
<span class="lineNum"> 261 </span> : {
|
|
<span class="lineNum"> 262 </span><span class="lineCov"> 57015 : struct snapraid_state* state = scan->state;</span>
|
|
<span class="lineNum"> 263 </span><span class="lineCov"> 57015 : struct snapraid_disk* disk = scan->disk;</span>
|
|
<span class="lineNum"> 264 </span> : block_off_t i;
|
|
<span class="lineNum"> 265 </span> :
|
|
<span class="lineNum"> 266 </span> : /* remove from the list of contained files */
|
|
<span class="lineNum"> 267 </span><span class="lineCov"> 57015 : tommy_list_remove_existing(&disk->filelist, &file->nodelist);</span>
|
|
<span class="lineNum"> 268 </span> :
|
|
<span class="lineNum"> 269 </span> : /* state changed */
|
|
<span class="lineNum"> 270 </span><span class="lineCov"> 57015 : state->need_write = 1;</span>
|
|
<span class="lineNum"> 271 </span> :
|
|
<span class="lineNum"> 272 </span> : /* here we are supposed to adjust the ::first_free_block position */
|
|
<span class="lineNum"> 273 </span> : /* with the parity position we are deleting */
|
|
<span class="lineNum"> 274 </span> : /* but we also know that we do only delayed insert, after all the deletion, */
|
|
<span class="lineNum"> 275 </span> : /* so at this point ::first_free_block is always at 0, and we don't need to update it */
|
|
<span class="lineNum"> 276 </span><span class="lineCov"> 57015 : if (disk->first_free_block != 0) {</span>
|
|
<span class="lineNum"> 277 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 278 </span> : log_fatal("Internal inconsistency for first free position at '%u' deallocating file '%s'\n", disk->first_free_block, file->sub);
|
|
<span class="lineNum"> 279 </span> : os_abort();
|
|
<span class="lineNum"> 280 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 281 </span> : }
|
|
<span class="lineNum"> 282 </span> :
|
|
<span class="lineNum"> 283 </span> : /* free all the blocks of the file */
|
|
<span class="lineNum"> 284 </span><span class="lineCov"> 197592 : for (i = 0; i < file->blockmax; ++i) {</span>
|
|
<span class="lineNum"> 285 </span><span class="lineCov"> 140577 : struct snapraid_block* block = fs_file2block_get(file, i);</span>
|
|
<span class="lineNum"> 286 </span> : unsigned block_state;
|
|
<span class="lineNum"> 287 </span> :
|
|
<span class="lineNum"> 288 </span> : /* in case we scan after an aborted sync, */
|
|
<span class="lineNum"> 289 </span> : /* we could get also intermediate states */
|
|
<span class="lineNum"> 290 </span><span class="lineCov"> 140577 : block_state = block_state_get(block);</span>
|
|
<span class="lineNum"> 291 </span><span class="lineCov"> 140577 : switch (block_state) {</span>
|
|
<span class="lineNum"> 292 </span> : case BLOCK_STATE_BLK :
|
|
<span class="lineNum"> 293 </span> : /* we keep the hash making it an "old" hash, because the parity is still containing data for it */
|
|
<span class="lineNum"> 294 </span><span class="lineCov"> 35580 : break;</span>
|
|
<span class="lineNum"> 295 </span> : case BLOCK_STATE_CHG :
|
|
<span class="lineNum"> 296 </span> : /* if we have not already cleared the past hash */
|
|
<span class="lineNum"> 297 </span><span class="lineCov"> 28040 : if (!state->clear_past_hash) {</span>
|
|
<span class="lineNum"> 298 </span> : /* in these cases we don't know if the old state is still the one */
|
|
<span class="lineNum"> 299 </span> : /* stored inside the parity, because after an aborted sync, the parity */
|
|
<span class="lineNum"> 300 </span> : /* may be or may be not have been updated with the data that it's now */
|
|
<span class="lineNum"> 301 </span> : /* deleted. Then we reset the hash to a bogus value. */
|
|
<span class="lineNum"> 302 </span> : /* For example: */
|
|
<span class="lineNum"> 303 </span> : /* - One file is added */
|
|
<span class="lineNum"> 304 </span> : /* - Sync aborted after updating the parity to the new state, */
|
|
<span class="lineNum"> 305 </span> : /* but without saving the content file representing this new state. */
|
|
<span class="lineNum"> 306 </span> : /* - File is now deleted after the aborted sync */
|
|
<span class="lineNum"> 307 </span> : /* - Sync again, deleting the blocks (exactly here) */
|
|
<span class="lineNum"> 308 </span> : /* with the hash of CHG block not representing the real parity state */
|
|
<span class="lineNum"> 309 </span><span class="lineCov"> 40 : hash_invalid_set(block->hash);</span>
|
|
<span class="lineNum"> 310 </span> : }
|
|
<span class="lineNum"> 311 </span><span class="lineCov"> 28040 : break;</span>
|
|
<span class="lineNum"> 312 </span> : case BLOCK_STATE_REP :
|
|
<span class="lineNum"> 313 </span> : /* we just don't know the old hash, and then we set it to invalid */
|
|
<span class="lineNum"> 314 </span><span class="lineCov"> 76957 : hash_invalid_set(block->hash);</span>
|
|
<span class="lineNum"> 315 </span><span class="lineCov"> 76957 : break;</span>
|
|
<span class="lineNum"> 316 </span> : default :
|
|
<span class="lineNum"> 317 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 318 </span> : log_fatal("Internal inconsistency in file '%s' deallocating block '%u:%u' state %u\n", file->sub, i, file->blockmax, block_state);
|
|
<span class="lineNum"> 319 </span> : os_abort();
|
|
<span class="lineNum"> 320 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 321 </span> : }
|
|
<span class="lineNum"> 322 </span> :
|
|
<span class="lineNum"> 323 </span> : /* set the block as deleted */
|
|
<span class="lineNum"> 324 </span><span class="lineCov"> 140577 : block_state_set(block, BLOCK_STATE_DELETED);</span>
|
|
<span class="lineNum"> 325 </span> : }
|
|
<span class="lineNum"> 326 </span> :
|
|
<span class="lineNum"> 327 </span> : /* mark the file as deleted */
|
|
<span class="lineNum"> 328 </span><span class="lineCov"> 57015 : file_flag_set(file, FILE_IS_DELETED);</span>
|
|
<span class="lineNum"> 329 </span> :
|
|
<span class="lineNum"> 330 </span> : /* insert it in the list of deleted blocks */
|
|
<span class="lineNum"> 331 </span><span class="lineCov"> 57015 : tommy_list_insert_tail(&disk->deletedlist, &file->nodelist, file);</span>
|
|
<a name="332"><span class="lineNum"> 332 </span><span class="lineCov"> 57015 : }</span></a>
|
|
<span class="lineNum"> 333 </span> :
|
|
<span class="lineNum"> 334 </span><span class="lineCov"> 101881 : static void scan_file_delayed_allocate(struct snapraid_scan* scan, struct snapraid_file* file)</span>
|
|
<span class="lineNum"> 335 </span> : {
|
|
<span class="lineNum"> 336 </span><span class="lineCov"> 101881 : struct snapraid_state* state = scan->state;</span>
|
|
<span class="lineNum"> 337 </span><span class="lineCov"> 101881 : struct snapraid_disk* disk = scan->disk;</span>
|
|
<span class="lineNum"> 338 </span> :
|
|
<span class="lineNum"> 339 </span> : /* if we sort for physical offsets we have to read them for new files */
|
|
<span class="lineNum"> 340 </span><span class="lineCov"> 101881 : if (state->opt.force_order == SORT_PHYSICAL</span>
|
|
<span class="lineNum"> 341 </span><span class="lineCov"> 11432 : && file->physical == FILEPHY_UNREAD_OFFSET</span>
|
|
<span class="lineNum"> 342 </span> : ) {
|
|
<span class="lineNum"> 343 </span> : char path_next[PATH_MAX];
|
|
<span class="lineNum"> 344 </span> :
|
|
<span class="lineNum"> 345 </span><span class="lineCov"> 11432 : pathprint(path_next, sizeof(path_next), "%s%s", disk->dir, file->sub);</span>
|
|
<span class="lineNum"> 346 </span> :
|
|
<span class="lineNum"> 347 </span><span class="lineCov"> 11432 : if (filephy(path_next, file->size, &file->physical) != 0) {</span>
|
|
<span class="lineNum"> 348 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 349 </span> : log_fatal("Error in getting the physical offset of file '%s'. %s.\n", path_next, strerror(errno));
|
|
<span class="lineNum"> 350 </span> : exit(EXIT_FAILURE);
|
|
<span class="lineNum"> 351 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 352 </span> : }
|
|
<span class="lineNum"> 353 </span> : }
|
|
<span class="lineNum"> 354 </span> :
|
|
<span class="lineNum"> 355 </span> : /* insert in the delayed list */
|
|
<span class="lineNum"> 356 </span><span class="lineCov"> 101881 : tommy_list_insert_tail(&scan->file_insert_list, &file->nodelist, file);</span>
|
|
<span class="lineNum"> 357 </span><span class="lineCov"> 101881 : }</span>
|
|
<span class="lineNum"> 358 </span> :
|
|
<span class="lineNum"> 359 </span> : /**
|
|
<span class="lineNum"> 360 </span> : * Check if a file is completely formed of blocks with invalid parity,
|
|
<a name="361"><span class="lineNum"> 361 </span> : * and no rehash is tagged, and if it has at least one block.</a>
|
|
<span class="lineNum"> 362 </span> : */
|
|
<span class="lineNum"> 363 </span><span class="lineCov"> 1025550 : static int file_is_full_invalid_parity_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file)</span>
|
|
<span class="lineNum"> 364 </span> : {
|
|
<span class="lineNum"> 365 </span> : block_off_t i;
|
|
<span class="lineNum"> 366 </span> :
|
|
<span class="lineNum"> 367 </span> : /* with no block, it never has an invalid parity */
|
|
<span class="lineNum"> 368 </span><span class="lineCov"> 1025550 : if (file->blockmax == 0)</span>
|
|
<span class="lineNum"> 369 </span><span class="lineCov"> 1439 : return 0;</span>
|
|
<span class="lineNum"> 370 </span> :
|
|
<span class="lineNum"> 371 </span> : /* check all blocks */
|
|
<span class="lineNum"> 372 </span><span class="lineCov"> 1080079 : for (i = 0; i < file->blockmax; ++i) {</span>
|
|
<span class="lineNum"> 373 </span> : snapraid_info info;
|
|
<span class="lineNum"> 374 </span><span class="lineCov"> 1057392 : struct snapraid_block* block = fs_file2block_get(file, i);</span>
|
|
<span class="lineNum"> 375 </span> : block_off_t parity_pos;
|
|
<span class="lineNum"> 376 </span> :
|
|
<span class="lineNum"> 377 </span> : /* exclude blocks with parity */
|
|
<span class="lineNum"> 378 </span><span class="lineCov"> 1057392 : if (!block_has_invalid_parity(block))</span>
|
|
<span class="lineNum"> 379 </span><span class="lineCov"> 1001424 : return 0;</span>
|
|
<span class="lineNum"> 380 </span> :
|
|
<span class="lineNum"> 381 </span> : /*
|
|
<span class="lineNum"> 382 </span> : * Get the parity position.
|
|
<span class="lineNum"> 383 </span> : *
|
|
<span class="lineNum"> 384 </span> : * Note that here we expect to always have mapped
|
|
<span class="lineNum"> 385 </span> : * parity, because kept files always have it.
|
|
<span class="lineNum"> 386 </span> : *
|
|
<span class="lineNum"> 387 </span> : * Anyway, checking for POS_NULL doesn't hurt.
|
|
<span class="lineNum"> 388 </span> : */
|
|
<span class="lineNum"> 389 </span><span class="lineCov"> 55968 : parity_pos = fs_file2par_find(disk, file, i);</span>
|
|
<span class="lineNum"> 390 </span> :
|
|
<span class="lineNum"> 391 </span> : /* if it's not mapped, it cannot have rehash */
|
|
<span class="lineNum"> 392 </span><span class="lineCov"> 55968 : if (parity_pos != POS_NULL) {</span>
|
|
<span class="lineNum"> 393 </span> : /* get block specific info */
|
|
<span class="lineNum"> 394 </span><span class="lineCov"> 55968 : info = info_get(&state->infoarr, parity_pos);</span>
|
|
<span class="lineNum"> 395 </span> :
|
|
<span class="lineNum"> 396 </span> : /* if rehash fails */
|
|
<span class="lineNum"> 397 </span><span class="lineCov"> 55968 : if (info_get_rehash(info))</span>
|
|
<span class="lineNum"> 398 </span><span class="lineNoCov"> 0 : return 0;</span>
|
|
<span class="lineNum"> 399 </span> : }
|
|
<span class="lineNum"> 400 </span> : }
|
|
<span class="lineNum"> 401 </span> :
|
|
<span class="lineNum"> 402 </span><span class="lineCov"> 22687 : return 1;</span>
|
|
<span class="lineNum"> 403 </span> : }
|
|
<span class="lineNum"> 404 </span> :
|
|
<span class="lineNum"> 405 </span> : /**
|
|
<span class="lineNum"> 406 </span> : * Check if a file is completely formed of blocks with an updated hash,
|
|
<a name="407"><span class="lineNum"> 407 </span> : * and no rehash is tagged, and if it has at least one block.</a>
|
|
<span class="lineNum"> 408 </span> : */
|
|
<span class="lineNum"> 409 </span><span class="lineCov"> 23670 : static int file_is_full_hashed_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file)</span>
|
|
<span class="lineNum"> 410 </span> : {
|
|
<span class="lineNum"> 411 </span> : block_off_t i;
|
|
<span class="lineNum"> 412 </span> :
|
|
<span class="lineNum"> 413 </span> : /* with no block, it never has a hash */
|
|
<span class="lineNum"> 414 </span><span class="lineCov"> 23670 : if (file->blockmax == 0)</span>
|
|
<span class="lineNum"> 415 </span><span class="lineCov"> 27 : return 0;</span>
|
|
<span class="lineNum"> 416 </span> :
|
|
<span class="lineNum"> 417 </span> : /* check all blocks */
|
|
<span class="lineNum"> 418 </span><span class="lineCov"> 81886 : for (i = 0; i < file->blockmax; ++i) {</span>
|
|
<span class="lineNum"> 419 </span> : snapraid_info info;
|
|
<span class="lineNum"> 420 </span><span class="lineCov"> 58250 : struct snapraid_block* block = fs_file2block_get(file, i);</span>
|
|
<span class="lineNum"> 421 </span> : block_off_t parity_pos;
|
|
<span class="lineNum"> 422 </span> :
|
|
<span class="lineNum"> 423 </span> : /* exclude blocks without hash */
|
|
<span class="lineNum"> 424 </span><span class="lineCov"> 58250 : if (!block_has_updated_hash(block))</span>
|
|
<span class="lineNum"> 425 </span><span class="lineCov"> 7 : return 0;</span>
|
|
<span class="lineNum"> 426 </span> :
|
|
<span class="lineNum"> 427 </span> : /*
|
|
<span class="lineNum"> 428 </span> : * Get the parity position.
|
|
<span class="lineNum"> 429 </span> : *
|
|
<span class="lineNum"> 430 </span> : * Note that it's possible to have files
|
|
<span class="lineNum"> 431 </span> : * not mapped into the parity, even if they
|
|
<span class="lineNum"> 432 </span> : * have a valid hash.
|
|
<span class="lineNum"> 433 </span> : *
|
|
<span class="lineNum"> 434 </span> : * This happens for example, for 'copied' files
|
|
<span class="lineNum"> 435 </span> : * that have REP blocks, but not yet mapped.
|
|
<span class="lineNum"> 436 </span> : *
|
|
<span class="lineNum"> 437 </span> : * If there are multiple copies, it's also possible
|
|
<span class="lineNum"> 438 </span> : * that such files are used as 'source' to copy
|
|
<span class="lineNum"> 439 </span> : * hashes, and then to get them inside this function.
|
|
<span class="lineNum"> 440 </span> : */
|
|
<span class="lineNum"> 441 </span><span class="lineCov"> 58243 : parity_pos = fs_file2par_find(disk, file, i);</span>
|
|
<span class="lineNum"> 442 </span> :
|
|
<span class="lineNum"> 443 </span> : /* if it's not mapped, it cannot have rehash */
|
|
<span class="lineNum"> 444 </span><span class="lineCov"> 58243 : if (parity_pos != POS_NULL) {</span>
|
|
<span class="lineNum"> 445 </span> : /* get block specific info */
|
|
<span class="lineNum"> 446 </span><span class="lineCov"> 58235 : info = info_get(&state->infoarr, parity_pos);</span>
|
|
<span class="lineNum"> 447 </span> :
|
|
<span class="lineNum"> 448 </span> : /* exclude blocks needing a rehash */
|
|
<span class="lineNum"> 449 </span><span class="lineCov"> 58235 : if (info_get_rehash(info))</span>
|
|
<span class="lineNum"> 450 </span><span class="lineNoCov"> 0 : return 0;</span>
|
|
<span class="lineNum"> 451 </span> : }
|
|
<span class="lineNum"> 452 </span> : }
|
|
<span class="lineNum"> 453 </span> :
|
|
<span class="lineNum"> 454 </span><span class="lineCov"> 23636 : return 1;</span>
|
|
<span class="lineNum"> 455 </span> : }
|
|
<span class="lineNum"> 456 </span> :
|
|
<span class="lineNum"> 457 </span> : /**
|
|
<span class="lineNum"> 458 </span> : * Refresh the file info.
|
|
<span class="lineNum"> 459 </span> : *
|
|
<span class="lineNum"> 460 </span> : * This is needed by Windows as the normal way to list directories may report not
|
|
<span class="lineNum"> 461 </span> : * updated info. Only the GetFileInformationByHandle() func, called file-by-file,
|
|
<span class="lineNum"> 462 </span> : * really ensures to return synced info.
|
|
<span class="lineNum"> 463 </span> : *
|
|
<a name="464"><span class="lineNum"> 464 </span> : * If this happens, we read also the physical offset, to avoid to read it later.</a>
|
|
<span class="lineNum"> 465 </span> : */
|
|
<span class="lineNum"> 466 </span><span class="lineCov"> 79194 : static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struct stat* st, uint64_t* physical)</span>
|
|
<span class="lineNum"> 467 </span> : {
|
|
<span class="lineNum"> 468 </span> : #if HAVE_LSTAT_SYNC
|
|
<span class="lineNum"> 469 </span> : struct snapraid_state* state = scan->state;
|
|
<span class="lineNum"> 470 </span> : struct snapraid_disk* disk = scan->disk;
|
|
<span class="lineNum"> 471 </span> :
|
|
<span class="lineNum"> 472 </span> : /* if the st_sync is not set, ensure to get synced info */
|
|
<span class="lineNum"> 473 </span> : if (st->st_sync == 0) {
|
|
<span class="lineNum"> 474 </span> : char path_next[PATH_MAX];
|
|
<span class="lineNum"> 475 </span> : struct stat synced_st;
|
|
<span class="lineNum"> 476 </span> :
|
|
<span class="lineNum"> 477 </span> : pathprint(path_next, sizeof(path_next), "%s%s", disk->dir, sub);
|
|
<span class="lineNum"> 478 </span> :
|
|
<span class="lineNum"> 479 </span> : /* if we sort for physical offsets we have to read them for new files */
|
|
<span class="lineNum"> 480 </span> : if (state->opt.force_order == SORT_PHYSICAL
|
|
<span class="lineNum"> 481 </span> : && *physical == FILEPHY_UNREAD_OFFSET
|
|
<span class="lineNum"> 482 </span> : ) {
|
|
<span class="lineNum"> 483 </span> : /* do nothing, leave the pointer to read the physical offset */
|
|
<span class="lineNum"> 484 </span> : } else {
|
|
<span class="lineNum"> 485 </span> : physical = 0; /* set the pointer to 0 to read nothing */
|
|
<span class="lineNum"> 486 </span> : }
|
|
<span class="lineNum"> 487 </span> :
|
|
<span class="lineNum"> 488 </span> : if (lstat_sync(path_next, &synced_st, physical) != 0) {
|
|
<span class="lineNum"> 489 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 490 </span> : log_fatal("Error in stat file '%s'. %s.\n", path_next, strerror(errno));
|
|
<span class="lineNum"> 491 </span> : exit(EXIT_FAILURE);
|
|
<span class="lineNum"> 492 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 493 </span> : }
|
|
<span class="lineNum"> 494 </span> :
|
|
<span class="lineNum"> 495 </span> : if (st->st_mtime != synced_st.st_mtime
|
|
<span class="lineNum"> 496 </span> : || st->st_mtimensec != synced_st.st_mtimensec
|
|
<span class="lineNum"> 497 </span> : ) {
|
|
<span class="lineNum"> 498 </span> : #ifndef _WIN32
|
|
<span class="lineNum"> 499 </span> : /*
|
|
<span class="lineNum"> 500 </span> : * In Windows having different metadata is expected with open files
|
|
<span class="lineNum"> 501 </span> : * because the metadata in the directory is updated only when the file
|
|
<span class="lineNum"> 502 </span> : * is closed.
|
|
<span class="lineNum"> 503 </span> : *
|
|
<span class="lineNum"> 504 </span> : * See also:
|
|
<span class="lineNum"> 505 </span> : * Why is the file size reported incorrectly for files that are still being written to?
|
|
<span class="lineNum"> 506 </span> : * http://blogs.msdn.com/b/oldnewthing/archive/2011/12/26/10251026.aspx
|
|
<span class="lineNum"> 507 </span> : */
|
|
<span class="lineNum"> 508 </span> : log_fatal("WARNING! Detected uncached time change for file '%s'\n", sub);
|
|
<span class="lineNum"> 509 </span> : log_fatal("It's better if you run SnapRAID without other processes running.\n");
|
|
<span class="lineNum"> 510 </span> : #endif
|
|
<span class="lineNum"> 511 </span> : st->st_mtime = synced_st.st_mtime;
|
|
<span class="lineNum"> 512 </span> : st->st_mtimensec = synced_st.st_mtimensec;
|
|
<span class="lineNum"> 513 </span> : }
|
|
<span class="lineNum"> 514 </span> :
|
|
<span class="lineNum"> 515 </span> : if (st->st_size != synced_st.st_size) {
|
|
<span class="lineNum"> 516 </span> : #ifndef _WIN32
|
|
<span class="lineNum"> 517 </span> : log_fatal("WARNING! Detected uncached size change for file '%s'\n", sub);
|
|
<span class="lineNum"> 518 </span> : log_fatal("It's better if you run SnapRAID without other processes running.\n");
|
|
<span class="lineNum"> 519 </span> : #endif
|
|
<span class="lineNum"> 520 </span> : st->st_size = synced_st.st_size;
|
|
<span class="lineNum"> 521 </span> : }
|
|
<span class="lineNum"> 522 </span> :
|
|
<span class="lineNum"> 523 </span> : if (st->st_ino != synced_st.st_ino) {
|
|
<span class="lineNum"> 524 </span> : log_fatal("DANGER! Detected uncached inode change for file '%s'\n", sub);
|
|
<span class="lineNum"> 525 </span> : log_fatal("Please ensure to run SnapRAID without other processes running.\n");
|
|
<span class="lineNum"> 526 </span> : /* at this point, it's too late to change inode */
|
|
<span class="lineNum"> 527 </span> : /* and having inconsistent inodes may result to internal failures */
|
|
<span class="lineNum"> 528 </span> : /* so, it's better to abort */
|
|
<span class="lineNum"> 529 </span> : exit(EXIT_FAILURE);
|
|
<span class="lineNum"> 530 </span> : }
|
|
<span class="lineNum"> 531 </span> : }
|
|
<span class="lineNum"> 532 </span> : #else
|
|
<span class="lineNum"> 533 </span> : (void)scan;
|
|
<span class="lineNum"> 534 </span> : (void)sub;
|
|
<span class="lineNum"> 535 </span> : (void)st;
|
|
<span class="lineNum"> 536 </span> : (void)physical;
|
|
<span class="lineNum"> 537 </span> : #endif
|
|
<span class="lineNum"> 538 </span><span class="lineCov"> 79194 : }</span>
|
|
<span class="lineNum"> 539 </span> :
|
|
<span class="lineNum"> 540 </span> : /**
|
|
<a name="541"><span class="lineNum"> 541 </span> : * Insert the file in the data set.</a>
|
|
<span class="lineNum"> 542 </span> : */
|
|
<span class="lineNum"> 543 </span><span class="lineCov"> 101881 : static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* file)</span>
|
|
<span class="lineNum"> 544 </span> : {
|
|
<span class="lineNum"> 545 </span><span class="lineCov"> 101881 : struct snapraid_disk* disk = scan->disk;</span>
|
|
<span class="lineNum"> 546 </span> :
|
|
<span class="lineNum"> 547 </span> : /* insert the file in the containers */
|
|
<span class="lineNum"> 548 </span><span class="lineCov"> 101881 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))</span>
|
|
<span class="lineNum"> 549 </span><span class="lineCov"> 101881 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));</span>
|
|
<span class="lineNum"> 550 </span><span class="lineCov"> 101881 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));</span>
|
|
<span class="lineNum"> 551 </span><span class="lineCov"> 101881 : tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec));</span>
|
|
<span class="lineNum"> 552 </span> :
|
|
<span class="lineNum"> 553 </span> : /* delayed allocation of the parity */
|
|
<span class="lineNum"> 554 </span><span class="lineCov"> 101881 : scan_file_delayed_allocate(scan, file);</span>
|
|
<span class="lineNum"> 555 </span><span class="lineCov"> 101881 : }</span>
|
|
<span class="lineNum"> 556 </span> :
|
|
<span class="lineNum"> 557 </span> : /**
|
|
<span class="lineNum"> 558 </span> : * Remove the file from the data set.
|
|
<span class="lineNum"> 559 </span> : *
|
|
<a name="560"><span class="lineNum"> 560 </span> : * File is then deleted.</a>
|
|
<span class="lineNum"> 561 </span> : */
|
|
<span class="lineNum"> 562 </span><span class="lineCov"> 57015 : static void scan_file_remove(struct snapraid_scan* scan, struct snapraid_file* file)</span>
|
|
<span class="lineNum"> 563 </span> : {
|
|
<span class="lineNum"> 564 </span><span class="lineCov"> 57015 : struct snapraid_disk* disk = scan->disk;</span>
|
|
<span class="lineNum"> 565 </span> :
|
|
<span class="lineNum"> 566 </span> : /* remove the file from the containers */
|
|
<span class="lineNum"> 567 </span><span class="lineCov"> 57015 : if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))</span>
|
|
<span class="lineNum"> 568 </span><span class="lineCov"> 56941 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);</span>
|
|
<span class="lineNum"> 569 </span><span class="lineCov"> 57015 : tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset);</span>
|
|
<span class="lineNum"> 570 </span><span class="lineCov"> 57015 : tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset);</span>
|
|
<span class="lineNum"> 571 </span> :
|
|
<span class="lineNum"> 572 </span> : /* deallocate the file from the parity */
|
|
<span class="lineNum"> 573 </span><span class="lineCov"> 57015 : scan_file_deallocate(scan, file);</span>
|
|
<span class="lineNum"> 574 </span><span class="lineCov"> 57015 : }</span>
|
|
<span class="lineNum"> 575 </span> :
|
|
<span class="lineNum"> 576 </span> : /**
|
|
<span class="lineNum"> 577 </span> : * Keep the file as it's (or with only a name/inode modification).
|
|
<span class="lineNum"> 578 </span> : *
|
|
<span class="lineNum"> 579 </span> : * If the file is kept, nothing has to be done.
|
|
<span class="lineNum"> 580 </span> : *
|
|
<span class="lineNum"> 581 </span> : * But if a file contains only blocks with invalid parity, it's reallocated to ensure
|
|
<span class="lineNum"> 582 </span> : * to always minimize the space used in the parity.
|
|
<span class="lineNum"> 583 </span> : *
|
|
<span class="lineNum"> 584 </span> : * This could happen after a failed sync, when some other files are deleted,
|
|
<a name="585"><span class="lineNum"> 585 </span> : * and then new ones can be moved backward to fill the hole created.</a>
|
|
<span class="lineNum"> 586 </span> : */
|
|
<span class="lineNum"> 587 </span><span class="lineCov"> 1025550 : static void scan_file_keep(struct snapraid_scan* scan, struct snapraid_file* file)</span>
|
|
<span class="lineNum"> 588 </span> : {
|
|
<span class="lineNum"> 589 </span><span class="lineCov"> 1025550 : struct snapraid_disk* disk = scan->disk;</span>
|
|
<span class="lineNum"> 590 </span> :
|
|
<span class="lineNum"> 591 </span> : /* if the file is full invalid, schedule a reinsert at later stage */
|
|
<span class="lineNum"> 592 </span><span class="lineCov"> 1025550 : if (file_is_full_invalid_parity_and_stable(scan->state, disk, file)) {</span>
|
|
<span class="lineNum"> 593 </span><span class="lineCov"> 22687 : struct snapraid_file* copy = file_dup(file);</span>
|
|
<span class="lineNum"> 594 </span> :
|
|
<span class="lineNum"> 595 </span> : /* remove the file */
|
|
<span class="lineNum"> 596 </span><span class="lineCov"> 22687 : scan_file_remove(scan, file);</span>
|
|
<span class="lineNum"> 597 </span> :
|
|
<span class="lineNum"> 598 </span> : /* reinsert the copy in the delayed list */
|
|
<span class="lineNum"> 599 </span><span class="lineCov"> 22687 : scan_file_insert(scan, copy);</span>
|
|
<span class="lineNum"> 600 </span> : }
|
|
<span class="lineNum"> 601 </span><span class="lineCov"> 1025550 : }</span>
|
|
<span class="lineNum"> 602 </span> :
|
|
<span class="lineNum"> 603 </span> : /**
|
|
<a name="604"><span class="lineNum"> 604 </span> : * Process a file.</a>
|
|
<span class="lineNum"> 605 </span> : */
|
|
<span class="lineNum"> 606 </span><span class="lineCov"> 1104939 : static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, struct stat* st, uint64_t physical)</span>
|
|
<span class="lineNum"> 607 </span> : {
|
|
<span class="lineNum"> 608 </span><span class="lineCov"> 1104939 : struct snapraid_state* state = scan->state;</span>
|
|
<span class="lineNum"> 609 </span><span class="lineCov"> 1104939 : struct snapraid_disk* disk = scan->disk;</span>
|
|
<span class="lineNum"> 610 </span> : struct snapraid_file* file;
|
|
<span class="lineNum"> 611 </span> : tommy_node* i;
|
|
<span class="lineNum"> 612 </span> : int is_original_file_size_different_than_zero;
|
|
<span class="lineNum"> 613 </span> : int is_file_already_present;
|
|
<span class="lineNum"> 614 </span> : data_off_t file_already_present_size;
|
|
<span class="lineNum"> 615 </span> : int64_t file_already_present_mtime_sec;
|
|
<span class="lineNum"> 616 </span> : int file_already_present_mtime_nsec;
|
|
<span class="lineNum"> 617 </span> : int is_file_reported;
|
|
<span class="lineNum"> 618 </span> : char esc_buffer[ESC_MAX];
|
|
<span class="lineNum"> 619 </span> : char esc_buffer_alt[ESC_MAX];
|
|
<span class="lineNum"> 620 </span> :
|
|
<span class="lineNum"> 621 </span> : /*
|
|
<span class="lineNum"> 622 </span> : * If the disk has persistent inodes and UUID, try a search on the past inodes,
|
|
<span class="lineNum"> 623 </span> : * to detect moved files.
|
|
<span class="lineNum"> 624 </span> : *
|
|
<span class="lineNum"> 625 </span> : * For persistent inodes we mean inodes that keep their values when the file-system
|
|
<span class="lineNum"> 626 </span> : * is unmounted and remounted. This don't always happen.
|
|
<span class="lineNum"> 627 </span> : *
|
|
<span class="lineNum"> 628 </span> : * Cases found are:
|
|
<span class="lineNum"> 629 </span> : * - Linux FUSE with exFAT driver from https://code.google.com/p/exfat/.
|
|
<span class="lineNum"> 630 </span> : * Inodes are reassigned at every mount restarting from 1 and incrementing.
|
|
<span class="lineNum"> 631 </span> : * As worse, the exFAT support in FUSE doesn't use sub-second precision in timestamps
|
|
<span class="lineNum"> 632 </span> : * making inode collision more easy (exFAT by design supports 10ms precision).
|
|
<span class="lineNum"> 633 </span> : * - Linux VFAT kernel (3.2) driver. Inodes are fully reassigned at every mount.
|
|
<span class="lineNum"> 634 </span> : *
|
|
<span class="lineNum"> 635 </span> : * In such cases, to avoid possible random collisions, it's better to disable the moved
|
|
<span class="lineNum"> 636 </span> : * file recognition.
|
|
<span class="lineNum"> 637 </span> : *
|
|
<span class="lineNum"> 638 </span> : * For persistent UUID we mean that it has the same UUID as before.
|
|
<span class="lineNum"> 639 </span> : * Otherwise, if the UUID is changed, likely it's a new recreated file-system,
|
|
<span class="lineNum"> 640 </span> : * and then the inode have no meaning.
|
|
<span class="lineNum"> 641 </span> : *
|
|
<span class="lineNum"> 642 </span> : * Note that to disable the search by past inode, we do this implicitly
|
|
<span class="lineNum"> 643 </span> : * removing all the past inode before searching for files.
|
|
<span class="lineNum"> 644 </span> : * This ensures that no file is found with a past inode, but at the same time,
|
|
<span class="lineNum"> 645 </span> : * it allows to find new files with the same inode, to identify them as hardlinks.
|
|
<span class="lineNum"> 646 </span> : */
|
|
<span class="lineNum"> 647 </span><span class="lineCov"> 1104939 : int has_past_inodes = !disk->has_volatile_inodes && !disk->has_different_uuid && !disk->has_unsupported_uuid;</span>
|
|
<span class="lineNum"> 648 </span> :
|
|
<span class="lineNum"> 649 </span> : /* always search with the new inode, in the all new inodes found until now, */
|
|
<span class="lineNum"> 650 </span> : /* with the eventual presence of also the past inodes */
|
|
<span class="lineNum"> 651 </span><span class="lineCov"> 1104939 : uint64_t inode = st->st_ino;</span>
|
|
<span class="lineNum"> 652 </span> :
|
|
<span class="lineNum"> 653 </span><span class="lineCov"> 1104939 : file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode));</span>
|
|
<span class="lineNum"> 654 </span> :
|
|
<span class="lineNum"> 655 </span> : /* identify moved files with past inodes and hardlinks with the new inodes */
|
|
<span class="lineNum"> 656 </span><span class="lineCov"> 1104939 : if (file) {</span>
|
|
<span class="lineNum"> 657 </span> : /* check if the file is not changed */
|
|
<span class="lineNum"> 658 </span><span class="lineCov"> 943901 : if (file->size == st->st_size</span>
|
|
<span class="lineNum"> 659 </span><span class="lineCov"> 935613 : && file->mtime_sec == st->st_mtime</span>
|
|
<span class="lineNum"> 660 </span><span class="lineCov"> 932556 : && (file->mtime_nsec == STAT_NSEC(st)</span>
|
|
<span class="lineNum"> 661 </span> : /* always accept the stored value if it's STAT_NSEC_INVALID */
|
|
<span class="lineNum"> 662 </span> : /* it happens when upgrading from an old version of SnapRAID */
|
|
<span class="lineNum"> 663 </span> : /* not yet supporting the nanosecond field */
|
|
<span class="lineNum"> 664 </span><span class="lineCov"> 1 : || file->mtime_nsec == STAT_NSEC_INVALID</span>
|
|
<span class="lineNum"> 665 </span> : )
|
|
<span class="lineNum"> 666 </span> : ) {
|
|
<span class="lineNum"> 667 </span> : /* check if multiple files have the same inode */
|
|
<span class="lineNum"> 668 </span><span class="lineCov"> 932555 : if (file_flag_has(file, FILE_IS_PRESENT)) {</span>
|
|
<span class="lineNum"> 669 </span> : #if HAVE_STRUCT_STAT_ST_NLINK
|
|
<span class="lineNum"> 670 </span><span class="lineCov"> 195 : if (st->st_nlink <= 1) {</span>
|
|
<span class="lineNum"> 671 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 672 </span> : log_fatal("Internal inode '%" PRIu64 "' inconsistency for file '%s%s' already present\n", (uint64_t)st->st_ino, disk->dir, sub);
|
|
<span class="lineNum"> 673 </span> : os_abort();
|
|
<span class="lineNum"> 674 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 675 </span> : }
|
|
<span class="lineNum"> 676 </span> : #endif
|
|
<span class="lineNum"> 677 </span> : /* it's a hardlink */
|
|
<span class="lineNum"> 678 </span><span class="lineCov"> 195 : scan_link(scan, is_diff, sub, file->sub, FILE_IS_HARDLINK);</span>
|
|
<span class="lineNum"> 679 </span><span class="lineCov"> 195 : return;</span>
|
|
<span class="lineNum"> 680 </span> : }
|
|
<span class="lineNum"> 681 </span> :
|
|
<span class="lineNum"> 682 </span> : /* mark as present */
|
|
<span class="lineNum"> 683 </span><span class="lineCov"> 932360 : file_flag_set(file, FILE_IS_PRESENT);</span>
|
|
<span class="lineNum"> 684 </span> :
|
|
<span class="lineNum"> 685 </span> : /* update the nanoseconds mtime only if different */
|
|
<span class="lineNum"> 686 </span> : /* to avoid unneeded updates */
|
|
<span class="lineNum"> 687 </span><span class="lineCov"> 932360 : if (file->mtime_nsec == STAT_NSEC_INVALID</span>
|
|
<span class="lineNum"> 688 </span><span class="lineNoCov"> 0 : && STAT_NSEC(st) != file->mtime_nsec</span>
|
|
<span class="lineNum"> 689 </span> : ) {
|
|
<span class="lineNum"> 690 </span><span class="lineNoCov"> 0 : file->mtime_nsec = STAT_NSEC(st);</span>
|
|
<span class="lineNum"> 691 </span> :
|
|
<span class="lineNum"> 692 </span> : /* we have to save the new mtime */
|
|
<span class="lineNum"> 693 </span><span class="lineNoCov"> 0 : state->need_write = 1;</span>
|
|
<span class="lineNum"> 694 </span> : }
|
|
<span class="lineNum"> 695 </span> :
|
|
<span class="lineNum"> 696 </span><span class="lineCov"> 932360 : if (strcmp(file->sub, sub) != 0) {</span>
|
|
<span class="lineNum"> 697 </span> : /* if the path is different, it means a moved file with the same inode */
|
|
<span class="lineNum"> 698 </span><span class="lineCov"> 155 : ++scan->count_move;</span>
|
|
<span class="lineNum"> 699 </span> :
|
|
<span class="lineNum"> 700 </span><span class="lineCov"> 155 : log_tag("scan:move:%s:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer), esc_tag(sub, esc_buffer_alt));</span>
|
|
<span class="lineNum"> 701 </span><span class="lineCov"> 155 : if (is_diff) {</span>
|
|
<span class="lineNum"> 702 </span><span class="lineNoCov"> 0 : printf("move %s -> %s\n", fmt_term(disk, file->sub, esc_buffer), fmt_term(disk, sub, esc_buffer_alt));</span>
|
|
<span class="lineNum"> 703 </span> : }
|
|
<span class="lineNum"> 704 </span> :
|
|
<span class="lineNum"> 705 </span> : /* remove from the name set */
|
|
<span class="lineNum"> 706 </span><span class="lineCov"> 155 : tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset);</span>
|
|
<span class="lineNum"> 707 </span> :
|
|
<span class="lineNum"> 708 </span> : /* save the new name */
|
|
<span class="lineNum"> 709 </span><span class="lineCov"> 155 : file_rename(file, sub);</span>
|
|
<span class="lineNum"> 710 </span> :
|
|
<span class="lineNum"> 711 </span> : /* reinsert in the name set */
|
|
<span class="lineNum"> 712 </span><span class="lineCov"> 155 : tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));</span>
|
|
<span class="lineNum"> 713 </span> :
|
|
<span class="lineNum"> 714 </span> : /* we have to save the new name */
|
|
<span class="lineNum"> 715 </span><span class="lineCov"> 155 : state->need_write = 1;</span>
|
|
<span class="lineNum"> 716 </span> : } else {
|
|
<span class="lineNum"> 717 </span> : /* otherwise it's equal */
|
|
<span class="lineNum"> 718 </span><span class="lineCov"> 932205 : ++scan->count_equal;</span>
|
|
<span class="lineNum"> 719 </span> :
|
|
<span class="lineNum"> 720 </span><span class="lineCov"> 932205 : if (state->opt.gui) {</span>
|
|
<span class="lineNum"> 721 </span><span class="lineCov"> 22611 : log_tag("scan:equal:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));</span>
|
|
<span class="lineNum"> 722 </span> : }
|
|
<span class="lineNum"> 723 </span> : }
|
|
<span class="lineNum"> 724 </span> :
|
|
<span class="lineNum"> 725 </span> : /* mark the file as kept */
|
|
<span class="lineNum"> 726 </span><span class="lineCov"> 932360 : scan_file_keep(scan, file);</span>
|
|
<span class="lineNum"> 727 </span> :
|
|
<span class="lineNum"> 728 </span> : /* nothing more to do */
|
|
<span class="lineNum"> 729 </span><span class="lineCov"> 932360 : return;</span>
|
|
<span class="lineNum"> 730 </span> : }
|
|
<span class="lineNum"> 731 </span> :
|
|
<span class="lineNum"> 732 </span> : /* here the file matches the inode, but not the other info */
|
|
<span class="lineNum"> 733 </span> : /* if could be a modified file with the same name, */
|
|
<span class="lineNum"> 734 </span> : /* or a restored/copied file that get assigned a previously used inode, */
|
|
<span class="lineNum"> 735 </span> : /* or a file-system with not persistent inodes */
|
|
<span class="lineNum"> 736 </span> :
|
|
<span class="lineNum"> 737 </span> : /* for sure it cannot be already present */
|
|
<span class="lineNum"> 738 </span><span class="lineCov"> 11346 : if (file_flag_has(file, FILE_IS_PRESENT)) {</span>
|
|
<span class="lineNum"> 739 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 740 </span> : log_fatal("Internal inode '%" PRIu64 "' inconsistency for files '%s%s' and '%s%s' matching and already present but different\n", file->inode, disk->dir, sub, disk->dir, file->sub);
|
|
<span class="lineNum"> 741 </span> : os_abort();
|
|
<span class="lineNum"> 742 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 743 </span> : }
|
|
<span class="lineNum"> 744 </span> :
|
|
<span class="lineNum"> 745 </span> : /* assume a previously used inode, it's the worst case */
|
|
<span class="lineNum"> 746 </span> : /* and we handle it removing the duplicate stored inode. */
|
|
<span class="lineNum"> 747 </span> : /* If the file is found by name later, it will have the inode restored, */
|
|
<span class="lineNum"> 748 </span> : /* otherwise, it will get removed */
|
|
<span class="lineNum"> 749 </span> :
|
|
<span class="lineNum"> 750 </span> : /* remove from the inode set */
|
|
<span class="lineNum"> 751 </span><span class="lineCov"> 11346 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);</span>
|
|
<span class="lineNum"> 752 </span> :
|
|
<span class="lineNum"> 753 </span> : /* clear the inode */
|
|
<span class="lineNum"> 754 </span> : /* this is not really needed for correct functionality */
|
|
<span class="lineNum"> 755 </span> : /* because we are going to set FILE_IS_WITHOUT_INODE */
|
|
<span class="lineNum"> 756 </span> : /* but it's easier for debugging to have invalid inodes set to 0 */
|
|
<span class="lineNum"> 757 </span><span class="lineCov"> 11346 : file->inode = 0;</span>
|
|
<span class="lineNum"> 758 </span> :
|
|
<span class="lineNum"> 759 </span> : /* mark as missing inode */
|
|
<span class="lineNum"> 760 </span><span class="lineCov"> 11346 : file_flag_set(file, FILE_IS_WITHOUT_INODE);</span>
|
|
<span class="lineNum"> 761 </span> :
|
|
<span class="lineNum"> 762 </span> : /* go further to find it by name */
|
|
<span class="lineNum"> 763 </span> : }
|
|
<span class="lineNum"> 764 </span> :
|
|
<span class="lineNum"> 765 </span> : /* initialize for later overwrite */
|
|
<span class="lineNum"> 766 </span><span class="lineCov"> 172384 : is_file_reported = 0;</span>
|
|
<span class="lineNum"> 767 </span><span class="lineCov"> 172384 : is_original_file_size_different_than_zero = 0;</span>
|
|
<span class="lineNum"> 768 </span> :
|
|
<span class="lineNum"> 769 </span> : /* then try finding it by name */
|
|
<span class="lineNum"> 770 </span><span class="lineCov"> 172384 : file = tommy_hashdyn_search(&disk->pathset, file_path_compare_to_arg, sub, file_path_hash(sub));</span>
|
|
<span class="lineNum"> 771 </span> :
|
|
<span class="lineNum"> 772 </span> : /* keep track if the file already exists */
|
|
<span class="lineNum"> 773 </span><span class="lineCov"> 172384 : is_file_already_present = file != 0;</span>
|
|
<span class="lineNum"> 774 </span> :
|
|
<span class="lineNum"> 775 </span><span class="lineCov"> 172384 : if (is_file_already_present) {</span>
|
|
<span class="lineNum"> 776 </span> : /* if the file is without an inode */
|
|
<span class="lineNum"> 777 </span><span class="lineCov"> 97871 : if (file_flag_has(file, FILE_IS_WITHOUT_INODE)) {</span>
|
|
<span class="lineNum"> 778 </span> : /* set it now */
|
|
<span class="lineNum"> 779 </span><span class="lineCov"> 11286 : file->inode = st->st_ino;</span>
|
|
<span class="lineNum"> 780 </span> :
|
|
<span class="lineNum"> 781 </span> : /* insert in the set */
|
|
<span class="lineNum"> 782 </span><span class="lineCov"> 11286 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));</span>
|
|
<span class="lineNum"> 783 </span> :
|
|
<span class="lineNum"> 784 </span> : /* unmark as missing inode */
|
|
<span class="lineNum"> 785 </span><span class="lineCov"> 11286 : file_flag_clear(file, FILE_IS_WITHOUT_INODE);</span>
|
|
<span class="lineNum"> 786 </span> : } else {
|
|
<span class="lineNum"> 787 </span> : /* here the inode has to be different, otherwise we would have found it before */
|
|
<span class="lineNum"> 788 </span><span class="lineCov"> 86585 : if (file->inode == st->st_ino) {</span>
|
|
<span class="lineNum"> 789 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 790 </span> : log_fatal("Internal inconsistency in inode '%" PRIu64 "' for files '%s%s' as unexpected matching\n", file->inode, disk->dir, sub);
|
|
<span class="lineNum"> 791 </span> : os_abort();
|
|
<span class="lineNum"> 792 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 793 </span> : }
|
|
<span class="lineNum"> 794 </span> : }
|
|
<span class="lineNum"> 795 </span> :
|
|
<span class="lineNum"> 796 </span> : /* for sure it cannot be already present */
|
|
<span class="lineNum"> 797 </span><span class="lineCov"> 97871 : if (file_flag_has(file, FILE_IS_PRESENT)) {</span>
|
|
<span class="lineNum"> 798 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 799 </span> : log_fatal("Internal inconsistency in path for file '%s%s' matching and already present\n", disk->dir, sub);
|
|
<span class="lineNum"> 800 </span> : os_abort();
|
|
<span class="lineNum"> 801 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 802 </span> : }
|
|
<span class="lineNum"> 803 </span> :
|
|
<span class="lineNum"> 804 </span> : /* check if the file is not changed */
|
|
<span class="lineNum"> 805 </span><span class="lineCov"> 97871 : if (file->size == st->st_size</span>
|
|
<span class="lineNum"> 806 </span><span class="lineCov"> 97275 : && file->mtime_sec == st->st_mtime</span>
|
|
<span class="lineNum"> 807 </span><span class="lineCov"> 93190 : && (file->mtime_nsec == STAT_NSEC(st)</span>
|
|
<span class="lineNum"> 808 </span> : /* always accept the stored value if it's STAT_NSEC_INVALID */
|
|
<span class="lineNum"> 809 </span> : /* it happens when upgrading from an old version of SnapRAID */
|
|
<span class="lineNum"> 810 </span> : /* not yet supporting the nanosecond field */
|
|
<span class="lineNum"> 811 </span><span class="lineNoCov"> 0 : || file->mtime_nsec == STAT_NSEC_INVALID</span>
|
|
<span class="lineNum"> 812 </span> : )
|
|
<span class="lineNum"> 813 </span> : ) {
|
|
<span class="lineNum"> 814 </span> : /* mark as present */
|
|
<span class="lineNum"> 815 </span><span class="lineCov"> 93190 : file_flag_set(file, FILE_IS_PRESENT);</span>
|
|
<span class="lineNum"> 816 </span> :
|
|
<span class="lineNum"> 817 </span> : /* update the nano seconds mtime only if different */
|
|
<span class="lineNum"> 818 </span> : /* to avoid unneeded updates */
|
|
<span class="lineNum"> 819 </span><span class="lineCov"> 93190 : if (file->mtime_nsec == STAT_NSEC_INVALID</span>
|
|
<span class="lineNum"> 820 </span><span class="lineNoCov"> 0 : && STAT_NSEC(st) != STAT_NSEC_INVALID</span>
|
|
<span class="lineNum"> 821 </span> : ) {
|
|
<span class="lineNum"> 822 </span><span class="lineNoCov"> 0 : file->mtime_nsec = STAT_NSEC(st);</span>
|
|
<span class="lineNum"> 823 </span> :
|
|
<span class="lineNum"> 824 </span> : /* we have to save the new mtime */
|
|
<span class="lineNum"> 825 </span><span class="lineNoCov"> 0 : state->need_write = 1;</span>
|
|
<span class="lineNum"> 826 </span> : }
|
|
<span class="lineNum"> 827 </span> :
|
|
<span class="lineNum"> 828 </span> : /* if when processing the disk we used the past inodes values */
|
|
<span class="lineNum"> 829 </span><span class="lineCov"> 93190 : if (has_past_inodes) {</span>
|
|
<span class="lineNum"> 830 </span> : /* if persistent inodes are supported, we are sure that the inode number */
|
|
<span class="lineNum"> 831 </span> : /* is now different, because otherwise the file would have been found */
|
|
<span class="lineNum"> 832 </span> : /* when searching by inode. */
|
|
<span class="lineNum"> 833 </span> : /* if the inode is different, it means a rewritten file with the same path */
|
|
<span class="lineNum"> 834 </span> : /* like when restoring a backup that restores also the timestamp */
|
|
<span class="lineNum"> 835 </span><span class="lineCov"> 93176 : ++scan->count_restore;</span>
|
|
<span class="lineNum"> 836 </span> :
|
|
<span class="lineNum"> 837 </span><span class="lineCov"> 93176 : log_tag("scan:restore:%s:%s\n", disk->name, esc_tag(sub, esc_buffer));</span>
|
|
<span class="lineNum"> 838 </span><span class="lineCov"> 93176 : if (is_diff) {</span>
|
|
<span class="lineNum"> 839 </span><span class="lineNoCov"> 0 : printf("restore %s\n", fmt_term(disk, sub, esc_buffer));</span>
|
|
<span class="lineNum"> 840 </span> : }
|
|
<span class="lineNum"> 841 </span> :
|
|
<span class="lineNum"> 842 </span> : /* remove from the inode set */
|
|
<span class="lineNum"> 843 </span><span class="lineCov"> 93176 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);</span>
|
|
<span class="lineNum"> 844 </span> :
|
|
<span class="lineNum"> 845 </span> : /* save the new inode */
|
|
<span class="lineNum"> 846 </span><span class="lineCov"> 93176 : file->inode = st->st_ino;</span>
|
|
<span class="lineNum"> 847 </span> :
|
|
<span class="lineNum"> 848 </span> : /* reinsert in the inode set */
|
|
<span class="lineNum"> 849 </span><span class="lineCov"> 93176 : tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));</span>
|
|
<span class="lineNum"> 850 </span> :
|
|
<span class="lineNum"> 851 </span> : /* we have to save the new inode */
|
|
<span class="lineNum"> 852 </span><span class="lineCov"> 93176 : state->need_write = 1;</span>
|
|
<span class="lineNum"> 853 </span> : } else {
|
|
<span class="lineNum"> 854 </span> : /* otherwise it's the case of not persistent inode, where doesn't */
|
|
<span class="lineNum"> 855 </span> : /* matter if the inode is different or equal, because they have no */
|
|
<span class="lineNum"> 856 </span> : /* meaning, and then we don't even save them */
|
|
<span class="lineNum"> 857 </span><span class="lineCov"> 14 : ++scan->count_equal;</span>
|
|
<span class="lineNum"> 858 </span> :
|
|
<span class="lineNum"> 859 </span><span class="lineCov"> 14 : if (state->opt.gui) {</span>
|
|
<span class="lineNum"> 860 </span><span class="lineNoCov"> 0 : log_tag("scan:equal:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));</span>
|
|
<span class="lineNum"> 861 </span> : }
|
|
<span class="lineNum"> 862 </span> : }
|
|
<span class="lineNum"> 863 </span> :
|
|
<span class="lineNum"> 864 </span> : /* mark the file as kept */
|
|
<span class="lineNum"> 865 </span><span class="lineCov"> 93190 : scan_file_keep(scan, file);</span>
|
|
<span class="lineNum"> 866 </span> :
|
|
<span class="lineNum"> 867 </span> : /* nothing more to do */
|
|
<span class="lineNum"> 868 </span><span class="lineCov"> 93190 : return;</span>
|
|
<span class="lineNum"> 869 </span> : }
|
|
<span class="lineNum"> 870 </span> :
|
|
<span class="lineNum"> 871 </span> : /* here if the file is changed but with the correct name */
|
|
<span class="lineNum"> 872 </span> :
|
|
<span class="lineNum"> 873 </span> : /* save the info for later printout */
|
|
<span class="lineNum"> 874 </span><span class="lineCov"> 4681 : file_already_present_size = file->size;</span>
|
|
<span class="lineNum"> 875 </span><span class="lineCov"> 4681 : file_already_present_mtime_sec = file->mtime_sec;</span>
|
|
<span class="lineNum"> 876 </span><span class="lineCov"> 4681 : file_already_present_mtime_nsec = file->mtime_nsec;</span>
|
|
<span class="lineNum"> 877 </span> :
|
|
<span class="lineNum"> 878 </span> : /* keep track if the original file was not of zero size */
|
|
<span class="lineNum"> 879 </span><span class="lineCov"> 4681 : is_original_file_size_different_than_zero = file->size != 0;</span>
|
|
<span class="lineNum"> 880 </span> :
|
|
<span class="lineNum"> 881 </span> : /* remove it, and continue to insert it again */
|
|
<span class="lineNum"> 882 </span><span class="lineCov"> 4681 : scan_file_remove(scan, file);</span>
|
|
<span class="lineNum"> 883 </span> :
|
|
<span class="lineNum"> 884 </span> : /* and continue to insert it again */
|
|
<span class="lineNum"> 885 </span> : } else {
|
|
<span class="lineNum"> 886 </span><span class="lineCov"> 74513 : file_already_present_size = 0;</span>
|
|
<span class="lineNum"> 887 </span><span class="lineCov"> 74513 : file_already_present_mtime_sec = 0;</span>
|
|
<span class="lineNum"> 888 </span><span class="lineCov"> 74513 : file_already_present_mtime_nsec = 0;</span>
|
|
<span class="lineNum"> 889 </span> : }
|
|
<span class="lineNum"> 890 </span> :
|
|
<span class="lineNum"> 891 </span> : /* refresh the info, to ensure that they are synced, */
|
|
<span class="lineNum"> 892 </span> : /* note that we refresh only the info of the new or modified files */
|
|
<span class="lineNum"> 893 </span> : /* because this is slow operation */
|
|
<span class="lineNum"> 894 </span><span class="lineCov"> 79194 : scan_file_refresh(scan, sub, st, &physical);</span>
|
|
<span class="lineNum"> 895 </span> :
|
|
<span class="lineNum"> 896 </span> : #ifndef _WIN32
|
|
<span class="lineNum"> 897 </span> : /* do a safety check to ensure that the common ext4 case of zeroing */
|
|
<span class="lineNum"> 898 </span> : /* the size of a file after a crash doesn't propagate to the backup */
|
|
<span class="lineNum"> 899 </span> : /* this check is specific for Linux, so we disable it on Windows */
|
|
<span class="lineNum"> 900 </span><span class="lineCov"> 79194 : if (is_original_file_size_different_than_zero && st->st_size == 0) {</span>
|
|
<span class="lineNum"> 901 </span><span class="lineNoCov"> 0 : if (!state->opt.force_zero) {</span>
|
|
<span class="lineNum"> 902 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 903 </span> : log_fatal("The file '%s%s' has unexpected zero size!\n", disk->dir, sub);
|
|
<span class="lineNum"> 904 </span> : log_fatal("It's possible that after a kernel crash this file was lost,\n");
|
|
<span class="lineNum"> 905 </span> : log_fatal("and you can use 'snapraid fix -f /%s' to recover it.\n", fmt_poll(disk, sub, esc_buffer));
|
|
<span class="lineNum"> 906 </span> : if (!is_diff) {
|
|
<span class="lineNum"> 907 </span> : log_fatal("If this an expected condition you can '%s' anyway using 'snapraid --force-zero %s'\n", state->command, state->command);
|
|
<span class="lineNum"> 908 </span> : exit(EXIT_FAILURE);
|
|
<span class="lineNum"> 909 </span> : }
|
|
<span class="lineNum"> 910 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 911 </span> : }
|
|
<span class="lineNum"> 912 </span> : }
|
|
<span class="lineNum"> 913 </span> : #else
|
|
<span class="lineNum"> 914 </span> : /* avoid the unused warning in Windows */
|
|
<span class="lineNum"> 915 </span> : (void)is_original_file_size_different_than_zero;
|
|
<span class="lineNum"> 916 </span> : #endif
|
|
<span class="lineNum"> 917 </span> :
|
|
<span class="lineNum"> 918 </span> : /* insert it */
|
|
<span class="lineNum"> 919 </span><span class="lineCov"> 79194 : file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime, STAT_NSEC(st), st->st_ino, physical);</span>
|
|
<span class="lineNum"> 920 </span> :
|
|
<span class="lineNum"> 921 </span> : /* mark it as present */
|
|
<span class="lineNum"> 922 </span><span class="lineCov"> 79194 : file_flag_set(file, FILE_IS_PRESENT);</span>
|
|
<span class="lineNum"> 923 </span> :
|
|
<span class="lineNum"> 924 </span> : /* if copy detection is enabled */
|
|
<span class="lineNum"> 925 </span> : /* note that the copy detection is tried also for updated files */
|
|
<span class="lineNum"> 926 </span> : /* this makes sense because it may happen to have two different copies */
|
|
<span class="lineNum"> 927 </span> : /* of the same file, and we move the right one over the wrong one */
|
|
<span class="lineNum"> 928 </span> : /* in such case we have a "copy" over an "update" */
|
|
<span class="lineNum"> 929 </span><span class="lineCov"> 79194 : if (!state->opt.force_nocopy) {</span>
|
|
<span class="lineNum"> 930 </span><span class="lineCov"> 79194 : tommy_uint32_t hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec);</span>
|
|
<span class="lineNum"> 931 </span> :
|
|
<span class="lineNum"> 932 </span> : /* search for a file with the same name and stamp in all the disks */
|
|
<span class="lineNum"> 933 </span><span class="lineCov"> 423410 : for (i = state->disklist; i != 0; i = i->next) {</span>
|
|
<span class="lineNum"> 934 </span><span class="lineCov"> 367852 : struct snapraid_disk* other_disk = i->data;</span>
|
|
<span class="lineNum"> 935 </span> : struct snapraid_file* other_file;
|
|
<span class="lineNum"> 936 </span> :
|
|
<span class="lineNum"> 937 </span> : /* if the nanosecond part of the time stamp is valid, search */
|
|
<span class="lineNum"> 938 </span> : /* for name and stamp, otherwise for path and stamp */
|
|
<span class="lineNum"> 939 </span><span class="lineCov"> 367852 : if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID)</span>
|
|
<span class="lineNum"> 940 </span><span class="lineCov"> 367744 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash);</span>
|
|
<span class="lineNum"> 941 </span> : else
|
|
<span class="lineNum"> 942 </span><span class="lineCov"> 108 : other_file = tommy_hashdyn_search(&other_disk->stampset, file_pathstamp_compare, file, hash);</span>
|
|
<span class="lineNum"> 943 </span> :
|
|
<span class="lineNum"> 944 </span> : /* if found, and it's a fully hashed file */
|
|
<span class="lineNum"> 945 </span><span class="lineCov"> 367852 : if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_file)) {</span>
|
|
<span class="lineNum"> 946 </span> : /* assume that the file is a copy, and reuse the hash */
|
|
<span class="lineNum"> 947 </span><span class="lineCov"> 23636 : file_copy(other_file, file);</span>
|
|
<span class="lineNum"> 948 </span> :
|
|
<span class="lineNum"> 949 </span> : /* revert old counter and use the copy one */
|
|
<span class="lineNum"> 950 </span><span class="lineCov"> 23636 : ++scan->count_copy;</span>
|
|
<span class="lineNum"> 951 </span> :
|
|
<span class="lineNum"> 952 </span><span class="lineCov"> 23636 : log_tag("scan:copy:%s:%s:%s:%s\n", other_disk->name, esc_tag(other_file->sub, esc_buffer), disk->name, esc_tag(file->sub, esc_buffer_alt));</span>
|
|
<span class="lineNum"> 953 </span><span class="lineCov"> 23636 : if (is_diff) {</span>
|
|
<span class="lineNum"> 954 </span><span class="lineCov"> 31 : printf("copy %s -> %s\n", fmt_term(other_disk, other_file->sub, esc_buffer), fmt_term(disk, file->sub, esc_buffer_alt));</span>
|
|
<span class="lineNum"> 955 </span> : }
|
|
<span class="lineNum"> 956 </span> :
|
|
<span class="lineNum"> 957 </span> : /* mark it as reported */
|
|
<span class="lineNum"> 958 </span><span class="lineCov"> 23636 : is_file_reported = 1;</span>
|
|
<span class="lineNum"> 959 </span> :
|
|
<span class="lineNum"> 960 </span> : /* no need to continue the search */
|
|
<span class="lineNum"> 961 </span><span class="lineCov"> 23636 : break;</span>
|
|
<span class="lineNum"> 962 </span> : }
|
|
<span class="lineNum"> 963 </span> : }
|
|
<span class="lineNum"> 964 </span> : }
|
|
<span class="lineNum"> 965 </span> :
|
|
<span class="lineNum"> 966 </span> : /* if not yet reported, do it now */
|
|
<span class="lineNum"> 967 </span> : /* we postpone this to avoid to print two times the copied files */
|
|
<span class="lineNum"> 968 </span><span class="lineCov"> 79194 : if (!is_file_reported) {</span>
|
|
<span class="lineNum"> 969 </span><span class="lineCov"> 55558 : if (is_file_already_present) {</span>
|
|
<span class="lineNum"> 970 </span><span class="lineCov"> 4681 : ++scan->count_change;</span>
|
|
<span class="lineNum"> 971 </span> :
|
|
<span class="lineNum"> 972 </span><span class="lineCov"> 14043 : log_tag("scan:update:%s:%s: %" PRIu64 " %" PRIu64 ".%d -> %" PRIu64 " %" PRIu64 ".%d\n", disk->name, esc_tag(sub, esc_buffer),</span>
|
|
<span class="lineNum"> 973 </span> : (uint64_t)file_already_present_size, (uint64_t)file_already_present_mtime_sec, file_already_present_mtime_nsec,
|
|
<span class="lineNum"> 974 </span><span class="lineCov"> 9362 : (uint64_t)file->size, (uint64_t)file->mtime_sec, file->mtime_nsec</span>
|
|
<span class="lineNum"> 975 </span> : );
|
|
<span class="lineNum"> 976 </span> :
|
|
<span class="lineNum"> 977 </span><span class="lineCov"> 4681 : if (is_diff) {</span>
|
|
<span class="lineNum"> 978 </span><span class="lineCov"> 118 : printf("update %s\n", fmt_term(disk, sub, esc_buffer));</span>
|
|
<span class="lineNum"> 979 </span> : }
|
|
<span class="lineNum"> 980 </span> : } else {
|
|
<span class="lineNum"> 981 </span><span class="lineCov"> 50877 : ++scan->count_insert;</span>
|
|
<span class="lineNum"> 982 </span> :
|
|
<span class="lineNum"> 983 </span><span class="lineCov"> 50877 : log_tag("scan:add:%s:%s\n", disk->name, esc_tag(sub, esc_buffer));</span>
|
|
<span class="lineNum"> 984 </span><span class="lineCov"> 50877 : if (is_diff) {</span>
|
|
<span class="lineNum"> 985 </span><span class="lineCov"> 17054 : printf("add %s\n", fmt_term(disk, sub, esc_buffer));</span>
|
|
<span class="lineNum"> 986 </span> : }
|
|
<span class="lineNum"> 987 </span> : }
|
|
<span class="lineNum"> 988 </span> : }
|
|
<span class="lineNum"> 989 </span> :
|
|
<span class="lineNum"> 990 </span> : /* insert the file in the delayed list */
|
|
<span class="lineNum"> 991 </span><span class="lineCov"> 79194 : scan_file_insert(scan, file);</span>
|
|
<span class="lineNum"> 992 </span> : }
|
|
<span class="lineNum"> 993 </span> :
|
|
<span class="lineNum"> 994 </span> : /**
|
|
<a name="995"><span class="lineNum"> 995 </span> : * Remove the specified dir from the data set.</a>
|
|
<span class="lineNum"> 996 </span> : */
|
|
<span class="lineNum"> 997 </span><span class="lineCov"> 2 : static void scan_emptydir_remove(struct snapraid_scan* scan, struct snapraid_dir* dir)</span>
|
|
<span class="lineNum"> 998 </span> : {
|
|
<span class="lineNum"> 999 </span><span class="lineCov"> 2 : struct snapraid_state* state = scan->state;</span>
|
|
<span class="lineNum"> 1000 </span><span class="lineCov"> 2 : struct snapraid_disk* disk = scan->disk;</span>
|
|
<span class="lineNum"> 1001 </span> :
|
|
<span class="lineNum"> 1002 </span> : /* state changed */
|
|
<span class="lineNum"> 1003 </span><span class="lineCov"> 2 : state->need_write = 1;</span>
|
|
<span class="lineNum"> 1004 </span> :
|
|
<span class="lineNum"> 1005 </span> : /* remove the file from the dir containers */
|
|
<span class="lineNum"> 1006 </span><span class="lineCov"> 2 : tommy_hashdyn_remove_existing(&disk->dirset, &dir->nodeset);</span>
|
|
<span class="lineNum"> 1007 </span><span class="lineCov"> 2 : tommy_list_remove_existing(&disk->dirlist, &dir->nodelist);</span>
|
|
<span class="lineNum"> 1008 </span> :
|
|
<span class="lineNum"> 1009 </span> : /* deallocate */
|
|
<span class="lineNum"> 1010 </span><span class="lineCov"> 2 : dir_free(dir);</span>
|
|
<span class="lineNum"> 1011 </span><span class="lineCov"> 2 : }</span>
|
|
<span class="lineNum"> 1012 </span> :
|
|
<span class="lineNum"> 1013 </span> : /**
|
|
<a name="1014"><span class="lineNum"> 1014 </span> : * Insert the specified dir in the data set.</a>
|
|
<span class="lineNum"> 1015 </span> : */
|
|
<span class="lineNum"> 1016 </span><span class="lineCov"> 10 : static void scan_emptydir_insert(struct snapraid_scan* scan, struct snapraid_dir* dir)</span>
|
|
<span class="lineNum"> 1017 </span> : {
|
|
<span class="lineNum"> 1018 </span><span class="lineCov"> 10 : struct snapraid_state* state = scan->state;</span>
|
|
<span class="lineNum"> 1019 </span><span class="lineCov"> 10 : struct snapraid_disk* disk = scan->disk;</span>
|
|
<span class="lineNum"> 1020 </span> :
|
|
<span class="lineNum"> 1021 </span> : /* state changed */
|
|
<span class="lineNum"> 1022 </span><span class="lineCov"> 10 : state->need_write = 1;</span>
|
|
<span class="lineNum"> 1023 </span> :
|
|
<span class="lineNum"> 1024 </span> : /* insert the dir in the dir containers */
|
|
<span class="lineNum"> 1025 </span><span class="lineCov"> 10 : tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub));</span>
|
|
<span class="lineNum"> 1026 </span><span class="lineCov"> 10 : tommy_list_insert_tail(&disk->dirlist, &dir->nodelist, dir);</span>
|
|
<span class="lineNum"> 1027 </span><span class="lineCov"> 10 : }</span>
|
|
<span class="lineNum"> 1028 </span> :
|
|
<span class="lineNum"> 1029 </span> : /**
|
|
<a name="1030"><span class="lineNum"> 1030 </span> : * Process a dir.</a>
|
|
<span class="lineNum"> 1031 </span> : */
|
|
<span class="lineNum"> 1032 </span><span class="lineCov"> 259 : static void scan_emptydir(struct snapraid_scan* scan, const char* sub)</span>
|
|
<span class="lineNum"> 1033 </span> : {
|
|
<span class="lineNum"> 1034 </span><span class="lineCov"> 259 : struct snapraid_disk* disk = scan->disk;</span>
|
|
<span class="lineNum"> 1035 </span> : struct snapraid_dir* dir;
|
|
<span class="lineNum"> 1036 </span> :
|
|
<span class="lineNum"> 1037 </span> : /* check if the dir already exists */
|
|
<span class="lineNum"> 1038 </span><span class="lineCov"> 259 : dir = tommy_hashdyn_search(&disk->dirset, dir_name_compare, sub, dir_name_hash(sub));</span>
|
|
<span class="lineNum"> 1039 </span><span class="lineCov"> 259 : if (dir) {</span>
|
|
<span class="lineNum"> 1040 </span> : /* check if multiple files have the same name */
|
|
<span class="lineNum"> 1041 </span><span class="lineCov"> 249 : if (dir_flag_has(dir, FILE_IS_PRESENT)) {</span>
|
|
<span class="lineNum"> 1042 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 1043 </span> : log_fatal("Internal inconsistency for dir '%s%s'\n", disk->dir, sub);
|
|
<span class="lineNum"> 1044 </span> : os_abort();
|
|
<span class="lineNum"> 1045 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 1046 </span> : }
|
|
<span class="lineNum"> 1047 </span> :
|
|
<span class="lineNum"> 1048 </span> : /* mark as present */
|
|
<span class="lineNum"> 1049 </span><span class="lineCov"> 249 : dir_flag_set(dir, FILE_IS_PRESENT);</span>
|
|
<span class="lineNum"> 1050 </span> :
|
|
<span class="lineNum"> 1051 </span> : /* nothing more to do */
|
|
<span class="lineNum"> 1052 </span><span class="lineCov"> 508 : return;</span>
|
|
<span class="lineNum"> 1053 </span> : } else {
|
|
<span class="lineNum"> 1054 </span> : /* and continue to insert it */
|
|
<span class="lineNum"> 1055 </span> : }
|
|
<span class="lineNum"> 1056 </span> :
|
|
<span class="lineNum"> 1057 </span> : /* insert it */
|
|
<span class="lineNum"> 1058 </span><span class="lineCov"> 10 : dir = dir_alloc(sub);</span>
|
|
<span class="lineNum"> 1059 </span> :
|
|
<span class="lineNum"> 1060 </span> : /* mark it as present */
|
|
<span class="lineNum"> 1061 </span><span class="lineCov"> 10 : dir_flag_set(dir, FILE_IS_PRESENT);</span>
|
|
<span class="lineNum"> 1062 </span> :
|
|
<span class="lineNum"> 1063 </span> : /* insert it in the delayed insert list */
|
|
<span class="lineNum"> 1064 </span><span class="lineCov"> 10 : tommy_list_insert_tail(&scan->dir_insert_list, &dir->nodelist, dir);</span>
|
|
<span class="lineNum"> 1065 </span> : }
|
|
<span class="lineNum"> 1066 </span> :
|
|
<span class="lineNum"> 1067 </span> : struct dirent_sorted {
|
|
<span class="lineNum"> 1068 </span> : /* node for data structures */
|
|
<span class="lineNum"> 1069 </span> : tommy_node node;
|
|
<span class="lineNum"> 1070 </span> :
|
|
<span class="lineNum"> 1071 </span> : #if HAVE_STRUCT_DIRENT_D_INO
|
|
<span class="lineNum"> 1072 </span> : uint64_t d_ino; /**< Inode number. */
|
|
<span class="lineNum"> 1073 </span> : #endif
|
|
<span class="lineNum"> 1074 </span> : #if HAVE_STRUCT_DIRENT_D_TYPE
|
|
<span class="lineNum"> 1075 </span> : uint32_t d_type; /**< File type. */
|
|
<span class="lineNum"> 1076 </span> : #endif
|
|
<span class="lineNum"> 1077 </span> : #if HAVE_STRUCT_DIRENT_D_STAT
|
|
<span class="lineNum"> 1078 </span> : struct stat d_stat; /**< Stat result. */
|
|
<span class="lineNum"> 1079 </span> : #endif
|
|
<span class="lineNum"> 1080 </span> : char d_name[]; /**< Variable length name. It must be the last field. */
|
|
<span class="lineNum"> 1081 </span> : };
|
|
<a name="1082"><span class="lineNum"> 1082 </span> : </a>
|
|
<span class="lineNum"> 1083 </span> : #if HAVE_STRUCT_DIRENT_D_INO
|
|
<span class="lineNum"> 1084 </span><span class="lineCov"> 103390 : static int dd_ino_compare(const void* void_a, const void* void_b)</span>
|
|
<span class="lineNum"> 1085 </span> : {
|
|
<span class="lineNum"> 1086 </span><span class="lineCov"> 103390 : const struct dirent_sorted* a = void_a;</span>
|
|
<span class="lineNum"> 1087 </span><span class="lineCov"> 103390 : const struct dirent_sorted* b = void_b;</span>
|
|
<span class="lineNum"> 1088 </span> :
|
|
<span class="lineNum"> 1089 </span><span class="lineCov"> 103390 : if (a->d_ino < b->d_ino)</span>
|
|
<span class="lineNum"> 1090 </span><span class="lineCov"> 49438 : return -1;</span>
|
|
<span class="lineNum"> 1091 </span><span class="lineCov"> 53952 : if (a->d_ino > b->d_ino)</span>
|
|
<span class="lineNum"> 1092 </span><span class="lineCov"> 53952 : return 1;</span>
|
|
<span class="lineNum"> 1093 </span> :
|
|
<span class="lineNum"> 1094 </span><span class="lineNoCov"> 0 : return 0;</span>
|
|
<span class="lineNum"> 1095 </span> : }
|
|
<a name="1096"><span class="lineNum"> 1096 </span> : #endif</a>
|
|
<span class="lineNum"> 1097 </span> :
|
|
<span class="lineNum"> 1098 </span><span class="lineCov"> 11526118 : static int dd_name_compare(const void* void_a, const void* void_b)</span>
|
|
<span class="lineNum"> 1099 </span> : {
|
|
<span class="lineNum"> 1100 </span><span class="lineCov"> 11526118 : const struct dirent_sorted* a = void_a;</span>
|
|
<span class="lineNum"> 1101 </span><span class="lineCov"> 11526118 : const struct dirent_sorted* b = void_b;</span>
|
|
<span class="lineNum"> 1102 </span> :
|
|
<span class="lineNum"> 1103 </span><span class="lineCov"> 11526118 : return strcmp(a->d_name, b->d_name);</span>
|
|
<span class="lineNum"> 1104 </span> : }
|
|
<span class="lineNum"> 1105 </span> :
|
|
<span class="lineNum"> 1106 </span> : /**
|
|
<span class="lineNum"> 1107 </span> : * Return the stat info of a dir entry.
|
|
<span class="lineNum"> 1108 </span> : */
|
|
<span class="lineNum"> 1109 </span> : #if HAVE_STRUCT_DIRENT_D_STAT
|
|
<span class="lineNum"> 1110 </span> : #define DSTAT(file, dd, buf) dstat(dd)
|
|
<span class="lineNum"> 1111 </span> : struct stat* dstat(struct dirent_sorted* dd)
|
|
<span class="lineNum"> 1112 </span> : {
|
|
<span class="lineNum"> 1113 </span> : return &dd->d_stat;
|
|
<span class="lineNum"> 1114 </span> : }
|
|
<a name="1115"><span class="lineNum"> 1115 </span> : #else</a>
|
|
<span class="lineNum"> 1116 </span> : #define DSTAT(file, dd, buf) dstat(file, buf)
|
|
<span class="lineNum"> 1117 </span><span class="lineCov"> 1106210 : struct stat* dstat(const char* file, struct stat* st)</span>
|
|
<span class="lineNum"> 1118 </span> : {
|
|
<span class="lineNum"> 1119 </span><span class="lineCov"> 1106210 : if (lstat(file, st) != 0) {</span>
|
|
<span class="lineNum"> 1120 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 1121 </span> : log_fatal("Error in stat file/directory '%s'. %s.\n", file, strerror(errno));
|
|
<span class="lineNum"> 1122 </span> : exit(EXIT_FAILURE);
|
|
<span class="lineNum"> 1123 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 1124 </span> : }
|
|
<span class="lineNum"> 1125 </span><span class="lineCov"> 1106210 : return st;</span>
|
|
<span class="lineNum"> 1126 </span> : }
|
|
<span class="lineNum"> 1127 </span> : #endif
|
|
<span class="lineNum"> 1128 </span> :
|
|
<span class="lineNum"> 1129 </span> : /**
|
|
<span class="lineNum"> 1130 </span> : * Process a directory.
|
|
<a name="1131"><span class="lineNum"> 1131 </span> : * Return != 0 if at least one file or link is processed.</a>
|
|
<span class="lineNum"> 1132 </span> : */
|
|
<span class="lineNum"> 1133 </span><span class="lineCov"> 1846 : static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const char* dir, const char* sub)</span>
|
|
<span class="lineNum"> 1134 </span> : {
|
|
<span class="lineNum"> 1135 </span><span class="lineCov"> 1846 : struct snapraid_state* state = scan->state;</span>
|
|
<span class="lineNum"> 1136 </span><span class="lineCov"> 1846 : struct snapraid_disk* disk = scan->disk;</span>
|
|
<span class="lineNum"> 1137 </span><span class="lineCov"> 1846 : int processed = 0;</span>
|
|
<span class="lineNum"> 1138 </span> : DIR* d;
|
|
<span class="lineNum"> 1139 </span> : tommy_list list;
|
|
<span class="lineNum"> 1140 </span> : tommy_node* node;
|
|
<span class="lineNum"> 1141 </span> :
|
|
<span class="lineNum"> 1142 </span><span class="lineCov"> 1846 : tommy_list_init(&list);</span>
|
|
<span class="lineNum"> 1143 </span> :
|
|
<span class="lineNum"> 1144 </span><span class="lineCov"> 1846 : d = opendir(dir);</span>
|
|
<span class="lineNum"> 1145 </span><span class="lineCov"> 1846 : if (!d) {</span>
|
|
<span class="lineNum"> 1146 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 1147 </span> : log_fatal("Error opening directory '%s'. %s.\n", dir, strerror(errno));
|
|
<span class="lineNum"> 1148 </span> : if (level == 0)
|
|
<span class="lineNum"> 1149 </span> : log_fatal("If this is the disk mount point, remember to create it manually\n");
|
|
<span class="lineNum"> 1150 </span> : else
|
|
<span class="lineNum"> 1151 </span> : log_fatal("If it's a permission problem, you can exclude it in the config file with:\n\texclude /%s\n", sub);
|
|
<span class="lineNum"> 1152 </span> : exit(EXIT_FAILURE);
|
|
<span class="lineNum"> 1153 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 1154 </span> : }
|
|
<span class="lineNum"> 1155 </span> :
|
|
<span class="lineNum"> 1156 </span> : /* read the full directory */
|
|
<span class="lineNum"> 1157 </span> : while (1) {
|
|
<span class="lineNum"> 1158 </span> : char path_next[PATH_MAX];
|
|
<span class="lineNum"> 1159 </span> : char sub_next[PATH_MAX];
|
|
<span class="lineNum"> 1160 </span> : struct dirent_sorted* entry;
|
|
<span class="lineNum"> 1161 </span> : const char* name;
|
|
<span class="lineNum"> 1162 </span> : struct dirent* dd;
|
|
<span class="lineNum"> 1163 </span> : size_t name_len;
|
|
<span class="lineNum"> 1164 </span> :
|
|
<span class="lineNum"> 1165 </span> : /*
|
|
<span class="lineNum"> 1166 </span> : * Clear errno to differentiate the end of the stream and an error condition
|
|
<span class="lineNum"> 1167 </span> : *
|
|
<span class="lineNum"> 1168 </span> : * From the Linux readdir() manpage:
|
|
<span class="lineNum"> 1169 </span> : * "If the end of the directory stream is reached, NULL is returned and errno is not changed.
|
|
<span class="lineNum"> 1170 </span> : * If an error occurs, NULL is returned and errno is set appropriately."
|
|
<span class="lineNum"> 1171 </span> : */
|
|
<span class="lineNum"> 1172 </span><span class="lineCov"> 1147737 : errno = 0;</span>
|
|
<span class="lineNum"> 1173 </span><span class="lineCov"> 1147737 : dd = readdir(d);</span>
|
|
<span class="lineNum"> 1174 </span><span class="lineCov"> 1147737 : if (dd == 0 && errno != 0) {</span>
|
|
<span class="lineNum"> 1175 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 1176 </span> : log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno));
|
|
<span class="lineNum"> 1177 </span> : log_fatal("You can exclude it in the config file with:\n\texclude /%s\n", sub);
|
|
<span class="lineNum"> 1178 </span> : exit(EXIT_FAILURE);
|
|
<span class="lineNum"> 1179 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 1180 </span> : }
|
|
<span class="lineNum"> 1181 </span><span class="lineCov"> 1147737 : if (dd == 0) {</span>
|
|
<span class="lineNum"> 1182 </span><span class="lineCov"> 1846 : break; /* finished */</span>
|
|
<span class="lineNum"> 1183 </span> : }
|
|
<span class="lineNum"> 1184 </span> :
|
|
<span class="lineNum"> 1185 </span> : /* skip "." and ".." files */
|
|
<span class="lineNum"> 1186 </span><span class="lineCov"> 1145891 : name = dd->d_name;</span>
|
|
<span class="lineNum"> 1187 </span><span class="lineCov"> 1145891 : if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))</span>
|
|
<span class="lineNum"> 1188 </span><span class="lineCov"> 7384 : continue;</span>
|
|
<span class="lineNum"> 1189 </span> :
|
|
<span class="lineNum"> 1190 </span><span class="lineCov"> 1142199 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name);</span>
|
|
<span class="lineNum"> 1191 </span><span class="lineCov"> 1142199 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);</span>
|
|
<span class="lineNum"> 1192 </span> :
|
|
<span class="lineNum"> 1193 </span> : /* check for not supported file names */
|
|
<span class="lineNum"> 1194 </span><span class="lineCov"> 1142199 : if (name[0] == 0) {</span>
|
|
<span class="lineNum"> 1195 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 1196 </span> : log_fatal("Unsupported name '%s' in file '%s'.\n", name, path_next);
|
|
<span class="lineNum"> 1197 </span> : exit(EXIT_FAILURE);
|
|
<span class="lineNum"> 1198 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 1199 </span> : }
|
|
<span class="lineNum"> 1200 </span> :
|
|
<span class="lineNum"> 1201 </span> : /* exclude hidden files even before calling lstat() */
|
|
<span class="lineNum"> 1202 </span><span class="lineCov"> 1142199 : if (filter_hidden(state->filter_hidden, dd) != 0) {</span>
|
|
<span class="lineNum"> 1203 </span><span class="lineNoCov"> 0 : msg_verbose("Excluding hidden '%s'\n", path_next);</span>
|
|
<span class="lineNum"> 1204 </span><span class="lineNoCov"> 0 : continue;</span>
|
|
<span class="lineNum"> 1205 </span> : }
|
|
<span class="lineNum"> 1206 </span> :
|
|
<span class="lineNum"> 1207 </span> : /* exclude content files even before calling lstat() */
|
|
<span class="lineNum"> 1208 </span><span class="lineCov"> 1142199 : if (filter_content(&state->contentlist, path_next) != 0) {</span>
|
|
<span class="lineNum"> 1209 </span><span class="lineNoCov"> 0 : msg_verbose("Excluding content '%s'\n", path_next);</span>
|
|
<span class="lineNum"> 1210 </span><span class="lineNoCov"> 0 : continue;</span>
|
|
<span class="lineNum"> 1211 </span> : }
|
|
<span class="lineNum"> 1212 </span> :
|
|
<span class="lineNum"> 1213 </span><span class="lineCov"> 1142199 : name_len = strlen(dd->d_name);</span>
|
|
<span class="lineNum"> 1214 </span><span class="lineCov"> 1142199 : entry = malloc_nofail(sizeof(struct dirent_sorted) + name_len + 1);</span>
|
|
<span class="lineNum"> 1215 </span> :
|
|
<span class="lineNum"> 1216 </span> : /* copy the dir entry */
|
|
<span class="lineNum"> 1217 </span> : #if HAVE_STRUCT_DIRENT_D_INO
|
|
<span class="lineNum"> 1218 </span><span class="lineCov"> 1142199 : entry->d_ino = dd->d_ino;</span>
|
|
<span class="lineNum"> 1219 </span> : #endif
|
|
<span class="lineNum"> 1220 </span> : #if HAVE_STRUCT_DIRENT_D_TYPE
|
|
<span class="lineNum"> 1221 </span><span class="lineCov"> 1142199 : entry->d_type = dd->d_type;</span>
|
|
<span class="lineNum"> 1222 </span> : #endif
|
|
<span class="lineNum"> 1223 </span> : #if HAVE_STRUCT_DIRENT_D_STAT
|
|
<span class="lineNum"> 1224 </span> : /* convert dirent to lstat result */
|
|
<span class="lineNum"> 1225 </span> : dirent_lstat(dd, &entry->d_stat);
|
|
<span class="lineNum"> 1226 </span> :
|
|
<span class="lineNum"> 1227 </span> : /* note that at this point the st_mode may be 0 */
|
|
<span class="lineNum"> 1228 </span> : #endif
|
|
<span class="lineNum"> 1229 </span><span class="lineCov"> 1142199 : memcpy(entry->d_name, dd->d_name, name_len + 1);</span>
|
|
<span class="lineNum"> 1230 </span> :
|
|
<span class="lineNum"> 1231 </span> : /* insert in the list */
|
|
<span class="lineNum"> 1232 </span><span class="lineCov"> 1142199 : tommy_list_insert_tail(&list, &entry->node, entry);</span>
|
|
<span class="lineNum"> 1233 </span><span class="lineCov"> 1145891 : }</span>
|
|
<span class="lineNum"> 1234 </span> :
|
|
<span class="lineNum"> 1235 </span><span class="lineCov"> 1846 : if (closedir(d) != 0) {</span>
|
|
<span class="lineNum"> 1236 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 1237 </span> : log_fatal("Error closing directory '%s'. %s.\n", dir, strerror(errno));
|
|
<span class="lineNum"> 1238 </span> : exit(EXIT_FAILURE);
|
|
<span class="lineNum"> 1239 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 1240 </span> : }
|
|
<span class="lineNum"> 1241 </span> :
|
|
<span class="lineNum"> 1242 </span><span class="lineCov"> 1846 : if (state->opt.force_order == SORT_ALPHA) {</span>
|
|
<span class="lineNum"> 1243 </span> : /* if requested sort alphabetically */
|
|
<span class="lineNum"> 1244 </span> : /* this is mainly done for testing to ensure to always */
|
|
<span class="lineNum"> 1245 </span> : /* process in the same way in different platforms */
|
|
<span class="lineNum"> 1246 </span><span class="lineCov"> 1810 : tommy_list_sort(&list, dd_name_compare);</span>
|
|
<span class="lineNum"> 1247 </span> : }
|
|
<span class="lineNum"> 1248 </span> : #if HAVE_STRUCT_DIRENT_D_INO
|
|
<span class="lineNum"> 1249 </span><span class="lineCov"> 36 : else if (!disk->has_volatile_inodes) {</span>
|
|
<span class="lineNum"> 1250 </span> : /* if inodes are persistent */
|
|
<span class="lineNum"> 1251 </span> : /* sort the list of dir entries by inodes */
|
|
<span class="lineNum"> 1252 </span><span class="lineCov"> 36 : tommy_list_sort(&list, dd_ino_compare);</span>
|
|
<span class="lineNum"> 1253 </span> : }
|
|
<span class="lineNum"> 1254 </span> : /* otherwise just keep the insertion order */
|
|
<span class="lineNum"> 1255 </span> : #endif
|
|
<span class="lineNum"> 1256 </span> :
|
|
<span class="lineNum"> 1257 </span> : /* process the sorted dir entries */
|
|
<span class="lineNum"> 1258 </span><span class="lineCov"> 1846 : node = list;</span>
|
|
<span class="lineNum"> 1259 </span><span class="lineCov"> 1145891 : while (node != 0) {</span>
|
|
<span class="lineNum"> 1260 </span> : char path_next[PATH_MAX];
|
|
<span class="lineNum"> 1261 </span> : char sub_next[PATH_MAX];
|
|
<span class="lineNum"> 1262 </span> : char out[PATH_MAX];
|
|
<span class="lineNum"> 1263 </span><span class="lineCov"> 1142199 : struct snapraid_filter* reason = 0;</span>
|
|
<span class="lineNum"> 1264 </span><span class="lineCov"> 1142199 : struct dirent_sorted* dd = node->data;</span>
|
|
<span class="lineNum"> 1265 </span><span class="lineCov"> 1142199 : const char* name = dd->d_name;</span>
|
|
<span class="lineNum"> 1266 </span> : struct stat* st;
|
|
<span class="lineNum"> 1267 </span> : int type;
|
|
<span class="lineNum"> 1268 </span> : #if !HAVE_STRUCT_DIRENT_D_STAT
|
|
<span class="lineNum"> 1269 </span> : struct stat st_buf;
|
|
<span class="lineNum"> 1270 </span> : #endif
|
|
<span class="lineNum"> 1271 </span> :
|
|
<span class="lineNum"> 1272 </span><span class="lineCov"> 1142199 : pathprint(path_next, sizeof(path_next), "%s%s", dir, name);</span>
|
|
<span class="lineNum"> 1273 </span><span class="lineCov"> 1142199 : pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);</span>
|
|
<span class="lineNum"> 1274 </span> :
|
|
<span class="lineNum"> 1275 </span> : /* start with an unknown type */
|
|
<span class="lineNum"> 1276 </span><span class="lineCov"> 1142199 : type = -1;</span>
|
|
<span class="lineNum"> 1277 </span><span class="lineCov"> 1142199 : st = 0;</span>
|
|
<span class="lineNum"> 1278 </span> :
|
|
<span class="lineNum"> 1279 </span> : /* if dirent has the type, use it */
|
|
<span class="lineNum"> 1280 </span> : #if HAVE_STRUCT_DIRENT_D_TYPE
|
|
<span class="lineNum"> 1281 </span><span class="lineCov"> 1142199 : switch (dd->d_type) {</span>
|
|
<span class="lineNum"> 1282 </span><span class="lineNoCov"> 0 : case DT_UNKNOWN : break;</span>
|
|
<span class="lineNum"> 1283 </span><span class="lineCov"> 1104939 : case DT_REG : type = 0; break;</span>
|
|
<span class="lineNum"> 1284 </span><span class="lineCov"> 35989 : case DT_LNK : type = 1; break;</span>
|
|
<span class="lineNum"> 1285 </span><span class="lineCov"> 1271 : case DT_DIR : type = 2; break;</span>
|
|
<span class="lineNum"> 1286 </span><span class="lineNoCov"> 0 : default : type = 3; break;</span>
|
|
<span class="lineNum"> 1287 </span> : }
|
|
<span class="lineNum"> 1288 </span> : #endif
|
|
<span class="lineNum"> 1289 </span> :
|
|
<span class="lineNum"> 1290 </span> : /* if type is still unknown */
|
|
<span class="lineNum"> 1291 </span><span class="lineCov"> 1142199 : if (type < 0) {</span>
|
|
<span class="lineNum"> 1292 </span> : /* get the type from stat */
|
|
<span class="lineNum"> 1293 </span><span class="lineNoCov"> 0 : st = DSTAT(path_next, dd, &st_buf);</span>
|
|
<span class="lineNum"> 1294 </span> :
|
|
<span class="lineNum"> 1295 </span> : #if HAVE_STRUCT_DIRENT_D_STAT
|
|
<span class="lineNum"> 1296 </span> : /* if the st_mode field is missing, takes care to fill it using normal lstat() */
|
|
<span class="lineNum"> 1297 </span> : /* at now this can happen only in Windows (with HAVE_STRUCT_DIRENT_D_STAT defined), */
|
|
<span class="lineNum"> 1298 </span> : /* because we use a directory reading method that doesn't read info about ReparsePoint. */
|
|
<span class="lineNum"> 1299 </span> : /* Note that here we cannot call here lstat_sync(), because we don't know what kind */
|
|
<span class="lineNum"> 1300 </span> : /* of file is it, and lstat_sync() doesn't always work */
|
|
<span class="lineNum"> 1301 </span> : if (st->st_mode == 0) {
|
|
<span class="lineNum"> 1302 </span> : if (lstat(path_next, st) != 0) {
|
|
<span class="lineNum"> 1303 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 1304 </span> : log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno));
|
|
<span class="lineNum"> 1305 </span> : exit(EXIT_FAILURE);
|
|
<span class="lineNum"> 1306 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 1307 </span> : }
|
|
<span class="lineNum"> 1308 </span> : }
|
|
<span class="lineNum"> 1309 </span> : #endif
|
|
<span class="lineNum"> 1310 </span> :
|
|
<span class="lineNum"> 1311 </span><span class="lineNoCov"> 0 : if (S_ISREG(st->st_mode))</span>
|
|
<span class="lineNum"> 1312 </span><span class="lineNoCov"> 0 : type = 0;</span>
|
|
<span class="lineNum"> 1313 </span><span class="lineNoCov"> 0 : else if (S_ISLNK(st->st_mode))</span>
|
|
<span class="lineNum"> 1314 </span><span class="lineNoCov"> 0 : type = 1;</span>
|
|
<span class="lineNum"> 1315 </span><span class="lineNoCov"> 0 : else if (S_ISDIR(st->st_mode))</span>
|
|
<span class="lineNum"> 1316 </span><span class="lineNoCov"> 0 : type = 2;</span>
|
|
<span class="lineNum"> 1317 </span> : else
|
|
<span class="lineNum"> 1318 </span><span class="lineNoCov"> 0 : type = 3;</span>
|
|
<span class="lineNum"> 1319 </span> : }
|
|
<span class="lineNum"> 1320 </span> :
|
|
<span class="lineNum"> 1321 </span><span class="lineCov"> 1142199 : if (type == 0) { /* REG */</span>
|
|
<span class="lineNum"> 1322 </span><span class="lineCov"> 1104939 : if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {</span>
|
|
<span class="lineNum"> 1323 </span> :
|
|
<span class="lineNum"> 1324 </span> : /* late stat, if not yet called */
|
|
<span class="lineNum"> 1325 </span><span class="lineCov"> 1104939 : if (!st)</span>
|
|
<span class="lineNum"> 1326 </span><span class="lineCov"> 1104939 : st = DSTAT(path_next, dd, &st_buf);</span>
|
|
<span class="lineNum"> 1327 </span> :
|
|
<span class="lineNum"> 1328 </span> : #if HAVE_LSTAT_SYNC
|
|
<span class="lineNum"> 1329 </span> : /* if the st_ino field is missing, takes care to fill it using the extended lstat() */
|
|
<span class="lineNum"> 1330 </span> : /* this can happen only in Windows */
|
|
<span class="lineNum"> 1331 </span> : if (st->st_ino == 0) {
|
|
<span class="lineNum"> 1332 </span> : if (lstat_sync(path_next, st, 0) != 0) {
|
|
<span class="lineNum"> 1333 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 1334 </span> : log_fatal("Error in stat file '%s'. %s.\n", path_next, strerror(errno));
|
|
<span class="lineNum"> 1335 </span> : exit(EXIT_FAILURE);
|
|
<span class="lineNum"> 1336 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 1337 </span> : }
|
|
<span class="lineNum"> 1338 </span> : }
|
|
<span class="lineNum"> 1339 </span> : #endif
|
|
<span class="lineNum"> 1340 </span> :
|
|
<span class="lineNum"> 1341 </span><span class="lineCov"> 1104939 : scan_file(scan, is_diff, sub_next, st, FILEPHY_UNREAD_OFFSET);</span>
|
|
<span class="lineNum"> 1342 </span><span class="lineCov"> 1104939 : processed = 1;</span>
|
|
<span class="lineNum"> 1343 </span> : } else {
|
|
<span class="lineNum"> 1344 </span><span class="lineNoCov"> 0 : msg_verbose("Excluding file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));</span>
|
|
<span class="lineNum"> 1345 </span> : }
|
|
<span class="lineNum"> 1346 </span><span class="lineCov"> 37260 : } else if (type == 1) { /* LNK */</span>
|
|
<span class="lineNum"> 1347 </span><span class="lineCov"> 35989 : if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {</span>
|
|
<span class="lineNum"> 1348 </span> : char subnew[PATH_MAX];
|
|
<span class="lineNum"> 1349 </span> : int ret;
|
|
<span class="lineNum"> 1350 </span> :
|
|
<span class="lineNum"> 1351 </span><span class="lineCov"> 35989 : ret = readlink(path_next, subnew, sizeof(subnew));</span>
|
|
<span class="lineNum"> 1352 </span><span class="lineCov"> 35989 : if (ret >= PATH_MAX) {</span>
|
|
<span class="lineNum"> 1353 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 1354 </span> : log_fatal("Error in readlink file '%s'. Symlink too long.\n", path_next);
|
|
<span class="lineNum"> 1355 </span> : exit(EXIT_FAILURE);
|
|
<span class="lineNum"> 1356 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 1357 </span> : }
|
|
<span class="lineNum"> 1358 </span><span class="lineCov"> 35989 : if (ret < 0) {</span>
|
|
<span class="lineNum"> 1359 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 1360 </span> : log_fatal("Error in readlink file '%s'. %s.\n", path_next, strerror(errno));
|
|
<span class="lineNum"> 1361 </span> : exit(EXIT_FAILURE);
|
|
<span class="lineNum"> 1362 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 1363 </span> : }
|
|
<span class="lineNum"> 1364 </span><span class="lineCov"> 35989 : if (ret == 0)</span>
|
|
<span class="lineNum"> 1365 </span><span class="lineNoCov"> 0 : log_fatal("WARNING! Empty symbolic link '%s'.\n", path_next);</span>
|
|
<span class="lineNum"> 1366 </span> :
|
|
<span class="lineNum"> 1367 </span> : /* readlink doesn't put the final 0 */
|
|
<span class="lineNum"> 1368 </span><span class="lineCov"> 35989 : subnew[ret] = 0;</span>
|
|
<span class="lineNum"> 1369 </span> :
|
|
<span class="lineNum"> 1370 </span> : /* process as a symbolic link */
|
|
<span class="lineNum"> 1371 </span><span class="lineCov"> 35989 : scan_link(scan, is_diff, sub_next, subnew, FILE_IS_SYMLINK);</span>
|
|
<span class="lineNum"> 1372 </span><span class="lineCov"> 35989 : processed = 1;</span>
|
|
<span class="lineNum"> 1373 </span> : } else {
|
|
<span class="lineNum"> 1374 </span><span class="lineNoCov"> 0 : msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));</span>
|
|
<span class="lineNum"> 1375 </span> : }
|
|
<span class="lineNum"> 1376 </span><span class="lineCov"> 1271 : } else if (type == 2) { /* DIR */</span>
|
|
<span class="lineNum"> 1377 </span><span class="lineCov"> 1271 : if (filter_subdir(&state->filterlist, &reason, disk->name, sub_next) == 0) {</span>
|
|
<span class="lineNum"> 1378 </span> : #ifndef _WIN32
|
|
<span class="lineNum"> 1379 </span> : /* late stat, if not yet called */
|
|
<span class="lineNum"> 1380 </span><span class="lineCov"> 1271 : if (!st)</span>
|
|
<span class="lineNum"> 1381 </span><span class="lineCov"> 1271 : st = DSTAT(path_next, dd, &st_buf);</span>
|
|
<span class="lineNum"> 1382 </span> :
|
|
<span class="lineNum"> 1383 </span> : /* in Unix don't follow mount points in different devices */
|
|
<span class="lineNum"> 1384 </span> : /* in Windows we are already skipping them reporting them as special files */
|
|
<span class="lineNum"> 1385 </span><span class="lineCov"> 1271 : if ((uint64_t)st->st_dev != disk->device) {</span>
|
|
<span class="lineNum"> 1386 </span><span class="lineNoCov"> 0 : log_fatal("WARNING! Ignoring mount point '%s' because it appears to be in a different device\n", path_next);</span>
|
|
<span class="lineNum"> 1387 </span> : } else
|
|
<span class="lineNum"> 1388 </span> : #endif
|
|
<span class="lineNum"> 1389 </span> : {
|
|
<span class="lineNum"> 1390 </span> : char sub_dir[PATH_MAX];
|
|
<span class="lineNum"> 1391 </span> :
|
|
<span class="lineNum"> 1392 </span> : /* recurse */
|
|
<span class="lineNum"> 1393 </span><span class="lineCov"> 1271 : pathslash(path_next, sizeof(path_next));</span>
|
|
<span class="lineNum"> 1394 </span><span class="lineCov"> 1271 : pathcpy(sub_dir, sizeof(sub_dir), sub_next);</span>
|
|
<span class="lineNum"> 1395 </span><span class="lineCov"> 1271 : pathslash(sub_dir, sizeof(sub_dir));</span>
|
|
<span class="lineNum"> 1396 </span><span class="lineCov"> 1271 : if (scan_dir(scan, level + 1, is_diff, path_next, sub_dir) == 0) {</span>
|
|
<span class="lineNum"> 1397 </span> : /* scan the directory as empty dir */
|
|
<span class="lineNum"> 1398 </span><span class="lineCov"> 259 : scan_emptydir(scan, sub_next);</span>
|
|
<span class="lineNum"> 1399 </span> : }
|
|
<span class="lineNum"> 1400 </span> : /* or we processed something internally, or we have added the empty dir */
|
|
<span class="lineNum"> 1401 </span><span class="lineCov"> 1271 : processed = 1;</span>
|
|
<span class="lineNum"> 1402 </span> : }
|
|
<span class="lineNum"> 1403 </span> : } else {
|
|
<span class="lineNum"> 1404 </span><span class="lineNoCov"> 0 : msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));</span>
|
|
<span class="lineNum"> 1405 </span> : }
|
|
<span class="lineNum"> 1406 </span> : } else {
|
|
<span class="lineNum"> 1407 </span><span class="lineNoCov"> 0 : if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {</span>
|
|
<span class="lineNum"> 1408 </span> : /* late stat, if not yet called */
|
|
<span class="lineNum"> 1409 </span><span class="lineNoCov"> 0 : if (!st)</span>
|
|
<span class="lineNum"> 1410 </span><span class="lineNoCov"> 0 : st = DSTAT(path_next, dd, &st_buf);</span>
|
|
<span class="lineNum"> 1411 </span> :
|
|
<span class="lineNum"> 1412 </span><span class="lineNoCov"> 0 : log_fatal("WARNING! Ignoring special '%s' file '%s'\n", stat_desc(st), path_next);</span>
|
|
<span class="lineNum"> 1413 </span> : } else {
|
|
<span class="lineNum"> 1414 </span><span class="lineNoCov"> 0 : msg_verbose("Excluding special file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));</span>
|
|
<span class="lineNum"> 1415 </span> : }
|
|
<span class="lineNum"> 1416 </span> : }
|
|
<span class="lineNum"> 1417 </span> :
|
|
<span class="lineNum"> 1418 </span> : /* next entry */
|
|
<span class="lineNum"> 1419 </span><span class="lineCov"> 1142199 : node = node->next;</span>
|
|
<span class="lineNum"> 1420 </span> :
|
|
<span class="lineNum"> 1421 </span> : /* free the present one */
|
|
<span class="lineNum"> 1422 </span><span class="lineCov"> 1142199 : free(dd);</span>
|
|
<span class="lineNum"> 1423 </span> : }
|
|
<span class="lineNum"> 1424 </span> :
|
|
<span class="lineNum"> 1425 </span><span class="lineCov"> 1846 : return processed;</span>
|
|
<a name="1426"><span class="lineNum"> 1426 </span> : }</a>
|
|
<span class="lineNum"> 1427 </span> :
|
|
<span class="lineNum"> 1428 </span><span class="lineCov"> 96 : static int state_diffscan(struct snapraid_state* state, int is_diff)</span>
|
|
<span class="lineNum"> 1429 </span> : {
|
|
<span class="lineNum"> 1430 </span> : tommy_node* i;
|
|
<span class="lineNum"> 1431 </span> : tommy_node* j;
|
|
<span class="lineNum"> 1432 </span> : tommy_list scanlist;
|
|
<span class="lineNum"> 1433 </span> : int done;
|
|
<span class="lineNum"> 1434 </span> : fptr* msg;
|
|
<span class="lineNum"> 1435 </span> : struct snapraid_scan total;
|
|
<span class="lineNum"> 1436 </span> : int no_difference;
|
|
<span class="lineNum"> 1437 </span> : char esc_buffer[ESC_MAX];
|
|
<span class="lineNum"> 1438 </span> :
|
|
<span class="lineNum"> 1439 </span><span class="lineCov"> 96 : tommy_list_init(&scanlist);</span>
|
|
<span class="lineNum"> 1440 </span> :
|
|
<span class="lineNum"> 1441 </span><span class="lineCov"> 96 : if (is_diff)</span>
|
|
<span class="lineNum"> 1442 </span><span class="lineCov"> 8 : msg_progress("Comparing...\n");</span>
|
|
<span class="lineNum"> 1443 </span> :
|
|
<span class="lineNum"> 1444 </span> : /* first scan all the directory and find new and deleted files */
|
|
<span class="lineNum"> 1445 </span><span class="lineCov"> 671 : for (i = state->disklist; i != 0; i = i->next) {</span>
|
|
<span class="lineNum"> 1446 </span><span class="lineCov"> 575 : struct snapraid_disk* disk = i->data;</span>
|
|
<span class="lineNum"> 1447 </span> : struct snapraid_scan* scan;
|
|
<span class="lineNum"> 1448 </span> : tommy_node* node;
|
|
<span class="lineNum"> 1449 </span> : int ret;
|
|
<span class="lineNum"> 1450 </span> : int has_persistent_inode;
|
|
<span class="lineNum"> 1451 </span> :
|
|
<span class="lineNum"> 1452 </span><span class="lineCov"> 575 : scan = malloc_nofail(sizeof(struct snapraid_scan));</span>
|
|
<span class="lineNum"> 1453 </span><span class="lineCov"> 575 : scan->state = state;</span>
|
|
<span class="lineNum"> 1454 </span><span class="lineCov"> 575 : scan->disk = disk;</span>
|
|
<span class="lineNum"> 1455 </span><span class="lineCov"> 575 : scan->count_equal = 0;</span>
|
|
<span class="lineNum"> 1456 </span><span class="lineCov"> 575 : scan->count_move = 0;</span>
|
|
<span class="lineNum"> 1457 </span><span class="lineCov"> 575 : scan->count_copy = 0;</span>
|
|
<span class="lineNum"> 1458 </span><span class="lineCov"> 575 : scan->count_restore = 0;</span>
|
|
<span class="lineNum"> 1459 </span><span class="lineCov"> 575 : scan->count_change = 0;</span>
|
|
<span class="lineNum"> 1460 </span><span class="lineCov"> 575 : scan->count_remove = 0;</span>
|
|
<span class="lineNum"> 1461 </span><span class="lineCov"> 575 : scan->count_insert = 0;</span>
|
|
<span class="lineNum"> 1462 </span><span class="lineCov"> 575 : tommy_list_init(&scan->file_insert_list);</span>
|
|
<span class="lineNum"> 1463 </span><span class="lineCov"> 575 : tommy_list_init(&scan->link_insert_list);</span>
|
|
<span class="lineNum"> 1464 </span><span class="lineCov"> 575 : tommy_list_init(&scan->dir_insert_list);</span>
|
|
<span class="lineNum"> 1465 </span> :
|
|
<span class="lineNum"> 1466 </span><span class="lineCov"> 575 : tommy_list_insert_tail(&scanlist, &scan->node, scan);</span>
|
|
<span class="lineNum"> 1467 </span> :
|
|
<span class="lineNum"> 1468 </span><span class="lineCov"> 575 : if (!is_diff)</span>
|
|
<span class="lineNum"> 1469 </span><span class="lineCov"> 527 : msg_progress("Scanning disk %s...\n", disk->name);</span>
|
|
<span class="lineNum"> 1470 </span> :
|
|
<span class="lineNum"> 1471 </span> : /* check if the disk supports persistent inodes */
|
|
<span class="lineNum"> 1472 </span><span class="lineCov"> 575 : ret = fsinfo(disk->dir, &has_persistent_inode, 0, 0);</span>
|
|
<span class="lineNum"> 1473 </span><span class="lineCov"> 575 : if (ret < 0) {</span>
|
|
<span class="lineNum"> 1474 </span> : /* LCOV_EXCL_START */
|
|
<span class="lineNum"> 1475 </span> : log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno));
|
|
<span class="lineNum"> 1476 </span> : exit(EXIT_FAILURE);
|
|
<span class="lineNum"> 1477 </span> : /* LCOV_EXCL_STOP */
|
|
<span class="lineNum"> 1478 </span> : }
|
|
<span class="lineNum"> 1479 </span><span class="lineCov"> 575 : if (!has_persistent_inode) {</span>
|
|
<span class="lineNum"> 1480 </span><span class="lineNoCov"> 0 : disk->has_volatile_inodes = 1;</span>
|
|
<span class="lineNum"> 1481 </span> : }
|
|
<span class="lineNum"> 1482 </span> :
|
|
<span class="lineNum"> 1483 </span> : /* if inodes or UUID are not persistent/changed/unsupported */
|
|
<span class="lineNum"> 1484 </span><span class="lineCov"> 575 : if (disk->has_volatile_inodes || disk->has_different_uuid || disk->has_unsupported_uuid) {</span>
|
|
<span class="lineNum"> 1485 </span> : /* remove all the inodes from the inode collection */
|
|
<span class="lineNum"> 1486 </span> : /* if they are not persistent, all of them could be changed now */
|
|
<span class="lineNum"> 1487 </span> : /* and we don't want to find false matching ones */
|
|
<span class="lineNum"> 1488 </span> : /* see scan_file() for more details */
|
|
<span class="lineNum"> 1489 </span><span class="lineCov"> 94 : node = disk->filelist;</span>
|
|
<span class="lineNum"> 1490 </span><span class="lineCov"> 202 : while (node) {</span>
|
|
<span class="lineNum"> 1491 </span><span class="lineCov"> 14 : struct snapraid_file* file = node->data;</span>
|
|
<span class="lineNum"> 1492 </span> :
|
|
<span class="lineNum"> 1493 </span><span class="lineCov"> 14 : node = node->next;</span>
|
|
<span class="lineNum"> 1494 </span> :
|
|
<span class="lineNum"> 1495 </span> : /* remove from the inode set */
|
|
<span class="lineNum"> 1496 </span><span class="lineCov"> 14 : tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);</span>
|
|
<span class="lineNum"> 1497 </span> :
|
|
<span class="lineNum"> 1498 </span> : /* clear the inode */
|
|
<span class="lineNum"> 1499 </span><span class="lineCov"> 14 : file->inode = 0;</span>
|
|
<span class="lineNum"> 1500 </span> :
|
|
<span class="lineNum"> 1501 </span> : /* mark as missing inode */
|
|
<span class="lineNum"> 1502 </span><span class="lineCov"> 14 : file_flag_set(file, FILE_IS_WITHOUT_INODE);</span>
|
|
<span class="lineNum"> 1503 </span> : }
|
|
<span class="lineNum"> 1504 </span> : }
|
|
<span class="lineNum"> 1505 </span> :
|
|
<span class="lineNum"> 1506 </span><span class="lineCov"> 575 : scan_dir(scan, 0, is_diff, disk->dir, "");</span>
|
|
<span class="lineNum"> 1507 </span> : }
|
|
<span class="lineNum"> 1508 </span> :
|
|
<span class="lineNum"> 1509 </span> : /* we split the search in two phases because to detect files */
|
|
<span class="lineNum"> 1510 </span> : /* moved from one disk to another we have to start deletion */
|
|
<span class="lineNum"> 1511 </span> : /* only when all disks have all the new files found */
|
|
<span class="lineNum"> 1512 </span> :
|
|
<span class="lineNum"> 1513 </span> : /* now process all the new and deleted files */
|
|
<span class="lineNum"> 1514 </span><span class="lineCov"> 671 : for (i = scanlist; i != 0; i = i->next) {</span>
|
|
<span class="lineNum"> 1515 </span><span class="lineCov"> 575 : struct snapraid_scan* scan = i->data;</span>
|
|
<span class="lineNum"> 1516 </span><span class="lineCov"> 575 : struct snapraid_disk* disk = scan->disk;</span>
|
|
<span class="lineNum"> 1517 </span> : tommy_node* node;
|
|
<span class="lineNum"> 1518 </span> : unsigned phy_count;
|
|
<span class="lineNum"> 1519 </span> : unsigned phy_dup;
|
|
<span class="lineNum"> 1520 </span> : uint64_t phy_last;
|
|
<span class="lineNum"> 1521 </span> : struct snapraid_file* phy_file_last;
|
|
<span class="lineNum"> 1522 </span> :
|
|
<span class="lineNum"> 1523 </span> : /* check for removed files */
|
|
<span class="lineNum"> 1524 </span><span class="lineCov"> 575 : node = disk->filelist;</span>
|
|
<span class="lineNum"> 1525 </span><span class="lineCov"> 1033660 : while (node) {</span>
|
|
<span class="lineNum"> 1526 </span><span class="lineCov"> 1032510 : struct snapraid_file* file = node->data;</span>
|
|
<span class="lineNum"> 1527 </span> :
|
|
<span class="lineNum"> 1528 </span> : /* next node */
|
|
<span class="lineNum"> 1529 </span><span class="lineCov"> 1032510 : node = node->next;</span>
|
|
<span class="lineNum"> 1530 </span> :
|
|
<span class="lineNum"> 1531 </span> : /* remove if not present */
|
|
<span class="lineNum"> 1532 </span><span class="lineCov"> 1032510 : if (!file_flag_has(file, FILE_IS_PRESENT)) {</span>
|
|
<span class="lineNum"> 1533 </span><span class="lineCov"> 29647 : ++scan->count_remove;</span>
|
|
<span class="lineNum"> 1534 </span> :
|
|
<span class="lineNum"> 1535 </span><span class="lineCov"> 29647 : log_tag("scan:remove:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));</span>
|
|
<span class="lineNum"> 1536 </span><span class="lineCov"> 29647 : if (is_diff) {</span>
|
|
<span class="lineNum"> 1537 </span><span class="lineCov"> 97 : printf("remove %s\n", fmt_term(disk, file->sub, esc_buffer));</span>
|
|
<span class="lineNum"> 1538 </span> : }
|
|
<span class="lineNum"> 1539 </span> :
|
|
<span class="lineNum"> 1540 </span><span class="lineCov"> 29647 : scan_file_remove(scan, file);</span>
|
|
<span class="lineNum"> 1541 </span> : }
|
|
<span class="lineNum"> 1542 </span> : }
|
|
<span class="lineNum"> 1543 </span> :
|
|
<span class="lineNum"> 1544 </span> : /* check for removed links */
|
|
<span class="lineNum"> 1545 </span><span class="lineCov"> 575 : node = disk->linklist;</span>
|
|
<span class="lineNum"> 1546 </span><span class="lineCov"> 35833 : while (node) {</span>
|
|
<span class="lineNum"> 1547 </span><span class="lineCov"> 34683 : struct snapraid_link* slink = node->data;</span>
|
|
<span class="lineNum"> 1548 </span> :
|
|
<span class="lineNum"> 1549 </span> : /* next node */
|
|
<span class="lineNum"> 1550 </span><span class="lineCov"> 34683 : node = node->next;</span>
|
|
<span class="lineNum"> 1551 </span> :
|
|
<span class="lineNum"> 1552 </span> : /* remove if not present */
|
|
<span class="lineNum"> 1553 </span><span class="lineCov"> 34683 : if (!link_flag_has(slink, FILE_IS_PRESENT)) {</span>
|
|
<span class="lineNum"> 1554 </span><span class="lineCov"> 956 : ++scan->count_remove;</span>
|
|
<span class="lineNum"> 1555 </span> :
|
|
<span class="lineNum"> 1556 </span><span class="lineCov"> 956 : log_tag("scan:remove:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer));</span>
|
|
<span class="lineNum"> 1557 </span><span class="lineCov"> 956 : if (is_diff) {</span>
|
|
<span class="lineNum"> 1558 </span><span class="lineCov"> 10 : printf("remove %s\n", fmt_term(disk, slink->sub, esc_buffer));</span>
|
|
<span class="lineNum"> 1559 </span> : }
|
|
<span class="lineNum"> 1560 </span> :
|
|
<span class="lineNum"> 1561 </span><span class="lineCov"> 956 : scan_link_remove(scan, slink);</span>
|
|
<span class="lineNum"> 1562 </span> : }
|
|
<span class="lineNum"> 1563 </span> : }
|
|
<span class="lineNum"> 1564 </span> :
|
|
<span class="lineNum"> 1565 </span> : /* check for removed dirs */
|
|
<span class="lineNum"> 1566 </span><span class="lineCov"> 575 : node = disk->dirlist;</span>
|
|
<span class="lineNum"> 1567 </span><span class="lineCov"> 1401 : while (node) {</span>
|
|
<span class="lineNum"> 1568 </span><span class="lineCov"> 251 : struct snapraid_dir* dir = node->data;</span>
|
|
<span class="lineNum"> 1569 </span> :
|
|
<span class="lineNum"> 1570 </span> : /* next node */
|
|
<span class="lineNum"> 1571 </span><span class="lineCov"> 251 : node = node->next;</span>
|
|
<span class="lineNum"> 1572 </span> :
|
|
<span class="lineNum"> 1573 </span> : /* remove if not present */
|
|
<span class="lineNum"> 1574 </span><span class="lineCov"> 251 : if (!dir_flag_has(dir, FILE_IS_PRESENT)) {</span>
|
|
<span class="lineNum"> 1575 </span><span class="lineCov"> 2 : scan_emptydir_remove(scan, dir);</span>
|
|
<span class="lineNum"> 1576 </span> : }
|
|
<span class="lineNum"> 1577 </span> : }
|
|
<span class="lineNum"> 1578 </span> :
|
|
<span class="lineNum"> 1579 </span> : /* sort the files before inserting them */
|
|
<span class="lineNum"> 1580 </span> : /* we use a stable sort to ensure that if the reported physical offset/inode */
|
|
<span class="lineNum"> 1581 </span> : /* are always 0, we keep at least the directory order */
|
|
<span class="lineNum"> 1582 </span><span class="lineCov"> 575 : switch (state->opt.force_order) {</span>
|
|
<span class="lineNum"> 1583 </span> : case SORT_PHYSICAL :
|
|
<span class="lineNum"> 1584 </span><span class="lineCov"> 12 : tommy_list_sort(&scan->file_insert_list, file_physical_compare);</span>
|
|
<span class="lineNum"> 1585 </span><span class="lineCov"> 12 : break;</span>
|
|
<span class="lineNum"> 1586 </span> : case SORT_INODE :
|
|
<span class="lineNum"> 1587 </span><span class="lineNoCov"> 0 : tommy_list_sort(&scan->file_insert_list, file_inode_compare);</span>
|
|
<span class="lineNum"> 1588 </span><span class="lineNoCov"> 0 : break;</span>
|
|
<span class="lineNum"> 1589 </span> : case SORT_ALPHA :
|
|
<span class="lineNum"> 1590 </span><span class="lineCov"> 563 : tommy_list_sort(&scan->file_insert_list, file_path_compare);</span>
|
|
<span class="lineNum"> 1591 </span><span class="lineCov"> 563 : break;</span>
|
|
<span class="lineNum"> 1592 </span> : case SORT_DIR :
|
|
<span class="lineNum"> 1593 </span> : /* already in order */
|
|
<span class="lineNum"> 1594 </span><span class="lineNoCov"> 0 : break;</span>
|
|
<span class="lineNum"> 1595 </span> : }
|
|
<span class="lineNum"> 1596 </span> :
|
|
<span class="lineNum"> 1597 </span> : /* insert all the new files, we insert them only after the deletion */
|
|
<span class="lineNum"> 1598 </span> : /* to reuse the just freed space */
|
|
<span class="lineNum"> 1599 </span> : /* also check if the physical offset reported are fakes or not */
|
|
<span class="lineNum"> 1600 </span><span class="lineCov"> 575 : node = scan->file_insert_list;</span>
|
|
<span class="lineNum"> 1601 </span><span class="lineCov"> 575 : phy_count = 0;</span>
|
|
<span class="lineNum"> 1602 </span><span class="lineCov"> 575 : phy_dup = 0;</span>
|
|
<span class="lineNum"> 1603 </span><span class="lineCov"> 575 : phy_last = FILEPHY_UNREAD_OFFSET;</span>
|
|
<span class="lineNum"> 1604 </span><span class="lineCov"> 575 : phy_file_last = 0;</span>
|
|
<span class="lineNum"> 1605 </span><span class="lineCov"> 103031 : while (node) {</span>
|
|
<span class="lineNum"> 1606 </span><span class="lineCov"> 101881 : struct snapraid_file* file = node->data;</span>
|
|
<span class="lineNum"> 1607 </span> :
|
|
<span class="lineNum"> 1608 </span> : /* if the file is not empty, count duplicate physical offsets */
|
|
<span class="lineNum"> 1609 </span><span class="lineCov"> 101881 : if (state->opt.force_order == SORT_PHYSICAL && file->size != 0) {</span>
|
|
<span class="lineNum"> 1610 </span><span class="lineCov"> 11418 : if (phy_file_last != 0 && file->physical == phy_last</span>
|
|
<span class="lineNum"> 1611 </span> : /* files without offset are expected to have duplicates */
|
|
<span class="lineNum"> 1612 </span><span class="lineNoCov"> 0 : && phy_last != FILEPHY_WITHOUT_OFFSET</span>
|
|
<span class="lineNum"> 1613 </span> : ) {
|
|
<span class="lineNum"> 1614 </span> : /* if verbose, print the list of duplicates real offsets */
|
|
<span class="lineNum"> 1615 </span> : /* other cases are for offsets not supported, so we don't need to report them file by file */
|
|
<span class="lineNum"> 1616 </span><span class="lineNoCov"> 0 : if (phy_last >= FILEPHY_REAL_OFFSET) {</span>
|
|
<span class="lineNum"> 1617 </span><span class="lineNoCov"> 0 : log_fatal("WARNING! Files '%s%s' and '%s%s' have the same physical offset %" PRId64 ".\n", disk->dir, phy_file_last->sub, disk->dir, file->sub, phy_last);</span>
|
|
<span class="lineNum"> 1618 </span> : }
|
|
<span class="lineNum"> 1619 </span><span class="lineNoCov"> 0 : ++phy_dup;</span>
|
|
<span class="lineNum"> 1620 </span> : }
|
|
<span class="lineNum"> 1621 </span><span class="lineCov"> 11418 : phy_file_last = file;</span>
|
|
<span class="lineNum"> 1622 </span><span class="lineCov"> 11418 : phy_last = file->physical;</span>
|
|
<span class="lineNum"> 1623 </span><span class="lineCov"> 11418 : ++phy_count;</span>
|
|
<span class="lineNum"> 1624 </span> : }
|
|
<span class="lineNum"> 1625 </span> :
|
|
<span class="lineNum"> 1626 </span> : /* next node */
|
|
<span class="lineNum"> 1627 </span><span class="lineCov"> 101881 : node = node->next;</span>
|
|
<span class="lineNum"> 1628 </span> :
|
|
<span class="lineNum"> 1629 </span> : /* insert in the parity */
|
|
<span class="lineNum"> 1630 </span><span class="lineCov"> 101881 : scan_file_allocate(scan, file);</span>
|
|
<span class="lineNum"> 1631 </span> : }
|
|
<span class="lineNum"> 1632 </span> :
|
|
<span class="lineNum"> 1633 </span> : /* mark the disk without reliable physical offset if it has duplicates */
|
|
<span class="lineNum"> 1634 </span> : /* here it should never happen because we already sorted out hardlinks */
|
|
<span class="lineNum"> 1635 </span><span class="lineCov"> 575 : if (state->opt.force_order == SORT_PHYSICAL && phy_dup > 0) {</span>
|
|
<span class="lineNum"> 1636 </span><span class="lineNoCov"> 0 : disk->has_unreliable_physical = 1;</span>
|
|
<span class="lineNum"> 1637 </span> : }
|
|
<span class="lineNum"> 1638 </span> :
|
|
<span class="lineNum"> 1639 </span> : /* insert all the new links */
|
|
<span class="lineNum"> 1640 </span><span class="lineCov"> 575 : node = scan->link_insert_list;</span>
|
|
<span class="lineNum"> 1641 </span><span class="lineCov"> 3607 : while (node) {</span>
|
|
<span class="lineNum"> 1642 </span><span class="lineCov"> 2457 : struct snapraid_link* slink = node->data;</span>
|
|
<span class="lineNum"> 1643 </span> :
|
|
<span class="lineNum"> 1644 </span> : /* next node */
|
|
<span class="lineNum"> 1645 </span><span class="lineCov"> 2457 : node = node->next;</span>
|
|
<span class="lineNum"> 1646 </span> :
|
|
<span class="lineNum"> 1647 </span> : /* insert it */
|
|
<span class="lineNum"> 1648 </span><span class="lineCov"> 2457 : scan_link_insert(scan, slink);</span>
|
|
<span class="lineNum"> 1649 </span> : }
|
|
<span class="lineNum"> 1650 </span> :
|
|
<span class="lineNum"> 1651 </span> : /* insert all the new dirs */
|
|
<span class="lineNum"> 1652 </span><span class="lineCov"> 575 : node = scan->dir_insert_list;</span>
|
|
<span class="lineNum"> 1653 </span><span class="lineCov"> 1160 : while (node) {</span>
|
|
<span class="lineNum"> 1654 </span><span class="lineCov"> 10 : struct snapraid_dir* dir = node->data;</span>
|
|
<span class="lineNum"> 1655 </span> :
|
|
<span class="lineNum"> 1656 </span> : /* next node */
|
|
<span class="lineNum"> 1657 </span><span class="lineCov"> 10 : node = node->next;</span>
|
|
<span class="lineNum"> 1658 </span> :
|
|
<span class="lineNum"> 1659 </span> : /* insert it */
|
|
<span class="lineNum"> 1660 </span><span class="lineCov"> 10 : scan_emptydir_insert(scan, dir);</span>
|
|
<span class="lineNum"> 1661 </span> : }
|
|
<span class="lineNum"> 1662 </span> : }
|
|
<span class="lineNum"> 1663 </span> :
|
|
<span class="lineNum"> 1664 </span> : /* check for disks where all the previously existing files where removed */
|
|
<span class="lineNum"> 1665 </span><span class="lineCov"> 96 : if (!state->opt.force_empty) {</span>
|
|
<span class="lineNum"> 1666 </span><span class="lineCov"> 90 : int all_missing = 0;</span>
|
|
<span class="lineNum"> 1667 </span><span class="lineCov"> 90 : int all_rewritten = 0;</span>
|
|
<span class="lineNum"> 1668 </span><span class="lineCov"> 90 : done = 0;</span>
|
|
<span class="lineNum"> 1669 </span><span class="lineCov"> 629 : for (i = state->disklist, j = scanlist; i != 0; i = i->next, j = j->next) {</span>
|
|
<span class="lineNum"> 1670 </span><span class="lineCov"> 539 : struct snapraid_disk* disk = i->data;</span>
|
|
<span class="lineNum"> 1671 </span><span class="lineCov"> 539 : struct snapraid_scan* scan = j->data;</span>
|
|
<span class="lineNum"> 1672 </span> :
|
|
<span class="lineNum"> 1673 </span><span class="lineCov"> 539 : if (scan->count_equal == 0</span>
|
|
<span class="lineNum"> 1674 </span><span class="lineCov"> 74 : && scan->count_move == 0</span>
|
|
<span class="lineNum"> 1675 </span><span class="lineCov"> 74 : && scan->count_restore == 0</span>
|
|
<span class="lineNum"> 1676 </span><span class="lineCov"> 74 : && (scan->count_remove != 0 || scan->count_change != 0)</span>
|
|
<span class="lineNum"> 1677 </span> : ) {
|
|
<span class="lineNum"> 1678 </span><span class="lineCov"> 1 : if (!done) {</span>
|
|
<span class="lineNum"> 1679 </span><span class="lineCov"> 1 : done = 1;</span>
|
|
<span class="lineNum"> 1680 </span><span class="lineCov"> 1 : log_fatal("WARNING! All the files previously present in disk '%s' at dir '%s'", disk->name, disk->dir);</span>
|
|
<span class="lineNum"> 1681 </span> : } else {
|
|
<span class="lineNum"> 1682 </span><span class="lineNoCov"> 0 : log_fatal(", disk '%s' at dir '%s'", disk->name, disk->dir);</span>
|
|
<span class="lineNum"> 1683 </span> : }
|
|
<span class="lineNum"> 1684 </span> :
|
|
<span class="lineNum"> 1685 </span> : /* detect the special condition of all files missing */
|
|
<span class="lineNum"> 1686 </span><span class="lineCov"> 1 : if (scan->count_change == 0)</span>
|
|
<span class="lineNum"> 1687 </span><span class="lineCov"> 1 : all_missing = 1;</span>
|
|
<span class="lineNum"> 1688 </span> :
|
|
<span class="lineNum"> 1689 </span> : /* detect the special condition of all files rewritten */
|
|
<span class="lineNum"> 1690 </span><span class="lineCov"> 1 : if (scan->count_remove == 0)</span>
|
|
<span class="lineNum"> 1691 </span><span class="lineNoCov"> 0 : all_rewritten = 1;</span>
|
|
<span class="lineNum"> 1692 </span> : }
|
|
<span class="lineNum"> 1693 </span> : }
|
|
<span class="lineNum"> 1694 </span><span class="lineCov"> 90 : if (done) {</span>
|
|
<span class="lineNum"> 1695 </span><span class="lineCov"> 1 : log_fatal("\nare now missing or rewritten!\n");</span>
|
|
<span class="lineNum"> 1696 </span><span class="lineCov"> 1 : if (all_rewritten) {</span>
|
|
<span class="lineNum"> 1697 </span><span class="lineNoCov"> 0 : log_fatal("This could happen when restoring a disk with a backup\n");</span>
|
|
<span class="lineNum"> 1698 </span><span class="lineNoCov"> 0 : log_fatal("program that is not setting correctly the timestamps.\n");</span>
|
|
<span class="lineNum"> 1699 </span> : }
|
|
<span class="lineNum"> 1700 </span><span class="lineCov"> 1 : if (all_missing) {</span>
|
|
<span class="lineNum"> 1701 </span><span class="lineCov"> 1 : log_fatal("This could happen when some disks are not mounted\n");</span>
|
|
<span class="lineNum"> 1702 </span><span class="lineCov"> 1 : log_fatal("in the expected directory.\n");</span>
|
|
<span class="lineNum"> 1703 </span> : }
|
|
<span class="lineNum"> 1704 </span><span class="lineCov"> 1 : if (!is_diff) {</span>
|
|
<span class="lineNum"> 1705 </span><span class="lineCov"> 1 : log_fatal("If you want to '%s' anyway, use 'snapraid --force-empty %s'.\n", state->command, state->command);</span>
|
|
<span class="lineNum"> 1706 </span><span class="lineCov"> 1 : exit(EXIT_FAILURE);</span>
|
|
<span class="lineNum"> 1707 </span> : }
|
|
<span class="lineNum"> 1708 </span> : }
|
|
<span class="lineNum"> 1709 </span> : }
|
|
<span class="lineNum"> 1710 </span> :
|
|
<span class="lineNum"> 1711 </span> : /* check for disks without the physical offset support */
|
|
<span class="lineNum"> 1712 </span><span class="lineCov"> 95 : if (state->opt.force_order == SORT_PHYSICAL) {</span>
|
|
<span class="lineNum"> 1713 </span><span class="lineCov"> 2 : done = 0;</span>
|
|
<span class="lineNum"> 1714 </span><span class="lineCov"> 14 : for (i = state->disklist; i != 0; i = i->next) {</span>
|
|
<span class="lineNum"> 1715 </span><span class="lineCov"> 12 : struct snapraid_disk* disk = i->data;</span>
|
|
<span class="lineNum"> 1716 </span> :
|
|
<span class="lineNum"> 1717 </span><span class="lineCov"> 12 : if (disk->has_unreliable_physical) {</span>
|
|
<span class="lineNum"> 1718 </span><span class="lineNoCov"> 0 : if (!done) {</span>
|
|
<span class="lineNum"> 1719 </span><span class="lineNoCov"> 0 : done = 1;</span>
|
|
<span class="lineNum"> 1720 </span><span class="lineNoCov"> 0 : log_fatal("WARNING! Physical offsets not supported for disk '%s'", disk->name);</span>
|
|
<span class="lineNum"> 1721 </span> : } else {
|
|
<span class="lineNum"> 1722 </span><span class="lineNoCov"> 0 : log_fatal(", '%s'", disk->name);</span>
|
|
<span class="lineNum"> 1723 </span> : }
|
|
<span class="lineNum"> 1724 </span> : }
|
|
<span class="lineNum"> 1725 </span> : }
|
|
<span class="lineNum"> 1726 </span><span class="lineCov"> 2 : if (done) {</span>
|
|
<span class="lineNum"> 1727 </span><span class="lineNoCov"> 0 : log_fatal(". Files order won't be optimal.\n");</span>
|
|
<span class="lineNum"> 1728 </span> : }
|
|
<span class="lineNum"> 1729 </span> : }
|
|
<span class="lineNum"> 1730 </span> :
|
|
<span class="lineNum"> 1731 </span> : /* check for disks without persistent inodes */
|
|
<span class="lineNum"> 1732 </span><span class="lineCov"> 95 : done = 0;</span>
|
|
<span class="lineNum"> 1733 </span><span class="lineCov"> 664 : for (i = state->disklist; i != 0; i = i->next) {</span>
|
|
<span class="lineNum"> 1734 </span><span class="lineCov"> 569 : struct snapraid_disk* disk = i->data;</span>
|
|
<span class="lineNum"> 1735 </span> :
|
|
<span class="lineNum"> 1736 </span><span class="lineCov"> 569 : if (disk->has_volatile_inodes) {</span>
|
|
<span class="lineNum"> 1737 </span><span class="lineNoCov"> 0 : if (!done) {</span>
|
|
<span class="lineNum"> 1738 </span><span class="lineNoCov"> 0 : done = 1;</span>
|
|
<span class="lineNum"> 1739 </span><span class="lineNoCov"> 0 : log_fatal("WARNING! Inodes are not persistent for disks: '%s'", disk->name);</span>
|
|
<span class="lineNum"> 1740 </span> : } else {
|
|
<span class="lineNum"> 1741 </span><span class="lineNoCov"> 0 : log_fatal(", '%s'", disk->name);</span>
|
|
<span class="lineNum"> 1742 </span> : }
|
|
<span class="lineNum"> 1743 </span> : }
|
|
<span class="lineNum"> 1744 </span> : }
|
|
<span class="lineNum"> 1745 </span><span class="lineCov"> 95 : if (done) {</span>
|
|
<span class="lineNum"> 1746 </span><span class="lineNoCov"> 0 : log_fatal(". Not using inodes to detect move operations.\n");</span>
|
|
<span class="lineNum"> 1747 </span> : }
|
|
<span class="lineNum"> 1748 </span> :
|
|
<span class="lineNum"> 1749 </span> : /* check for disks with changed UUID */
|
|
<span class="lineNum"> 1750 </span><span class="lineCov"> 95 : done = 0;</span>
|
|
<span class="lineNum"> 1751 </span><span class="lineCov"> 664 : for (i = state->disklist; i != 0; i = i->next) {</span>
|
|
<span class="lineNum"> 1752 </span><span class="lineCov"> 569 : struct snapraid_disk* disk = i->data;</span>
|
|
<span class="lineNum"> 1753 </span> :
|
|
<span class="lineNum"> 1754 </span> : /* don't print the message if the UUID changed because before */
|
|
<span class="lineNum"> 1755 </span> : /* it was no set. */
|
|
<span class="lineNum"> 1756 </span> : /* this is the normal condition for an empty disk because it */
|
|
<span class="lineNum"> 1757 </span> : /* isn't stored */
|
|
<span class="lineNum"> 1758 </span><span class="lineCov"> 569 : if (disk->has_different_uuid && !disk->had_empty_uuid) {</span>
|
|
<span class="lineNum"> 1759 </span><span class="lineCov"> 4 : if (!done) {</span>
|
|
<span class="lineNum"> 1760 </span><span class="lineCov"> 2 : done = 1;</span>
|
|
<span class="lineNum"> 1761 </span><span class="lineCov"> 2 : log_fatal("WARNING! UUID is changed for disks: '%s'", disk->name);</span>
|
|
<span class="lineNum"> 1762 </span> : } else {
|
|
<span class="lineNum"> 1763 </span><span class="lineCov"> 2 : log_fatal(", '%s'", disk->name);</span>
|
|
<span class="lineNum"> 1764 </span> : }
|
|
<span class="lineNum"> 1765 </span> : }
|
|
<span class="lineNum"> 1766 </span> : }
|
|
<span class="lineNum"> 1767 </span><span class="lineCov"> 95 : if (done) {</span>
|
|
<span class="lineNum"> 1768 </span><span class="lineCov"> 2 : log_fatal(". Not using inodes to detect move operations.\n");</span>
|
|
<span class="lineNum"> 1769 </span> : }
|
|
<span class="lineNum"> 1770 </span> :
|
|
<span class="lineNum"> 1771 </span> : /* check for disks with unsupported UUID */
|
|
<span class="lineNum"> 1772 </span><span class="lineCov"> 95 : done = 0;</span>
|
|
<span class="lineNum"> 1773 </span><span class="lineCov"> 664 : for (i = state->disklist; i != 0; i = i->next) {</span>
|
|
<span class="lineNum"> 1774 </span><span class="lineCov"> 569 : struct snapraid_disk* disk = i->data;</span>
|
|
<span class="lineNum"> 1775 </span> :
|
|
<span class="lineNum"> 1776 </span><span class="lineCov"> 569 : if (disk->has_unsupported_uuid) {</span>
|
|
<span class="lineNum"> 1777 </span><span class="lineNoCov"> 0 : if (!done) {</span>
|
|
<span class="lineNum"> 1778 </span><span class="lineNoCov"> 0 : done = 1;</span>
|
|
<span class="lineNum"> 1779 </span><span class="lineNoCov"> 0 : log_fatal("WARNING! UUID is unsupported for disks: '%s'", disk->name);</span>
|
|
<span class="lineNum"> 1780 </span> : } else {
|
|
<span class="lineNum"> 1781 </span><span class="lineNoCov"> 0 : log_fatal(", '%s'", disk->name);</span>
|
|
<span class="lineNum"> 1782 </span> : }
|
|
<span class="lineNum"> 1783 </span> : }
|
|
<span class="lineNum"> 1784 </span> : }
|
|
<span class="lineNum"> 1785 </span><span class="lineCov"> 95 : if (done) {</span>
|
|
<span class="lineNum"> 1786 </span><span class="lineNoCov"> 0 : log_fatal(". Not using inodes to detect move operations.\n");</span>
|
|
<span class="lineNum"> 1787 </span> : #if defined(_linux) && !HAVE_BLKID
|
|
<span class="lineNum"> 1788 </span> : log_fatal("The 'blkid' library is not linked in SnapRAID!\n");
|
|
<span class="lineNum"> 1789 </span> : log_fatal("Try rebuilding it after installing the libblkid-dev or libblkid-devel package.\n");
|
|
<span class="lineNum"> 1790 </span> : #endif
|
|
<span class="lineNum"> 1791 </span> : }
|
|
<span class="lineNum"> 1792 </span> :
|
|
<span class="lineNum"> 1793 </span><span class="lineCov"> 95 : total.count_equal = 0;</span>
|
|
<span class="lineNum"> 1794 </span><span class="lineCov"> 95 : total.count_move = 0;</span>
|
|
<span class="lineNum"> 1795 </span><span class="lineCov"> 95 : total.count_copy = 0;</span>
|
|
<span class="lineNum"> 1796 </span><span class="lineCov"> 95 : total.count_restore = 0;</span>
|
|
<span class="lineNum"> 1797 </span><span class="lineCov"> 95 : total.count_change = 0;</span>
|
|
<span class="lineNum"> 1798 </span><span class="lineCov"> 95 : total.count_remove = 0;</span>
|
|
<span class="lineNum"> 1799 </span><span class="lineCov"> 95 : total.count_insert = 0;</span>
|
|
<span class="lineNum"> 1800 </span> :
|
|
<span class="lineNum"> 1801 </span><span class="lineCov"> 664 : for (i = scanlist; i != 0; i = i->next) {</span>
|
|
<span class="lineNum"> 1802 </span><span class="lineCov"> 569 : struct snapraid_scan* scan = i->data;</span>
|
|
<span class="lineNum"> 1803 </span><span class="lineCov"> 569 : total.count_equal += scan->count_equal;</span>
|
|
<span class="lineNum"> 1804 </span><span class="lineCov"> 569 : total.count_move += scan->count_move;</span>
|
|
<span class="lineNum"> 1805 </span><span class="lineCov"> 569 : total.count_copy += scan->count_copy;</span>
|
|
<span class="lineNum"> 1806 </span><span class="lineCov"> 569 : total.count_restore += scan->count_restore;</span>
|
|
<span class="lineNum"> 1807 </span><span class="lineCov"> 569 : total.count_change += scan->count_change;</span>
|
|
<span class="lineNum"> 1808 </span><span class="lineCov"> 569 : total.count_remove += scan->count_remove;</span>
|
|
<span class="lineNum"> 1809 </span><span class="lineCov"> 569 : total.count_insert += scan->count_insert;</span>
|
|
<span class="lineNum"> 1810 </span> : }
|
|
<span class="lineNum"> 1811 </span> :
|
|
<span class="lineNum"> 1812 </span><span class="lineCov"> 95 : if (is_diff) {</span>
|
|
<span class="lineNum"> 1813 </span><span class="lineCov"> 8 : msg_status("\n");</span>
|
|
<span class="lineNum"> 1814 </span><span class="lineCov"> 8 : msg = msg_status;</span>
|
|
<span class="lineNum"> 1815 </span> : } else {
|
|
<span class="lineNum"> 1816 </span><span class="lineCov"> 87 : msg = msg_verbose;</span>
|
|
<span class="lineNum"> 1817 </span> : }
|
|
<span class="lineNum"> 1818 </span> :
|
|
<span class="lineNum"> 1819 </span><span class="lineCov"> 95 : msg("%8u equal\n", total.count_equal);</span>
|
|
<span class="lineNum"> 1820 </span><span class="lineCov"> 95 : msg("%8u added\n", total.count_insert);</span>
|
|
<span class="lineNum"> 1821 </span><span class="lineCov"> 95 : msg("%8u removed\n", total.count_remove);</span>
|
|
<span class="lineNum"> 1822 </span><span class="lineCov"> 95 : msg("%8u updated\n", total.count_change);</span>
|
|
<span class="lineNum"> 1823 </span><span class="lineCov"> 95 : msg("%8u moved\n", total.count_move);</span>
|
|
<span class="lineNum"> 1824 </span><span class="lineCov"> 95 : msg("%8u copied\n", total.count_copy);</span>
|
|
<span class="lineNum"> 1825 </span><span class="lineCov"> 95 : msg("%8u restored\n", total.count_restore);</span>
|
|
<span class="lineNum"> 1826 </span> :
|
|
<span class="lineNum"> 1827 </span><span class="lineCov"> 95 : log_tag("summary:equal:%u\n", total.count_equal);</span>
|
|
<span class="lineNum"> 1828 </span><span class="lineCov"> 95 : log_tag("summary:added:%u\n", total.count_insert);</span>
|
|
<span class="lineNum"> 1829 </span><span class="lineCov"> 95 : log_tag("summary:removed:%u\n", total.count_remove);</span>
|
|
<span class="lineNum"> 1830 </span><span class="lineCov"> 95 : log_tag("summary:updated:%u\n", total.count_change);</span>
|
|
<span class="lineNum"> 1831 </span><span class="lineCov"> 95 : log_tag("summary:moved:%u\n", total.count_move);</span>
|
|
<span class="lineNum"> 1832 </span><span class="lineCov"> 95 : log_tag("summary:copied:%u\n", total.count_copy);</span>
|
|
<span class="lineNum"> 1833 </span><span class="lineCov"> 95 : log_tag("summary:restored:%u\n", total.count_restore);</span>
|
|
<span class="lineNum"> 1834 </span> :
|
|
<span class="lineNum"> 1835 </span><span class="lineCov"> 284 : no_difference = !total.count_move && !total.count_copy && !total.count_restore</span>
|
|
<span class="lineNum"> 1836 </span><span class="lineCov"> 159 : && !total.count_change && !total.count_remove && !total.count_insert;</span>
|
|
<span class="lineNum"> 1837 </span> :
|
|
<span class="lineNum"> 1838 </span><span class="lineCov"> 95 : if (is_diff) {</span>
|
|
<span class="lineNum"> 1839 </span><span class="lineCov"> 8 : if (no_difference) {</span>
|
|
<span class="lineNum"> 1840 </span><span class="lineCov"> 2 : msg_status("No differences\n");</span>
|
|
<span class="lineNum"> 1841 </span> : } else {
|
|
<span class="lineNum"> 1842 </span><span class="lineCov"> 6 : msg_status("There are differences!\n");</span>
|
|
<span class="lineNum"> 1843 </span> : }
|
|
<span class="lineNum"> 1844 </span> : }
|
|
<span class="lineNum"> 1845 </span> :
|
|
<span class="lineNum"> 1846 </span><span class="lineCov"> 95 : if (no_difference) {</span>
|
|
<span class="lineNum"> 1847 </span><span class="lineCov"> 20 : log_tag("summary:exit:equal\n");</span>
|
|
<span class="lineNum"> 1848 </span> : } else {
|
|
<span class="lineNum"> 1849 </span><span class="lineCov"> 75 : log_tag("summary:exit:diff\n");</span>
|
|
<span class="lineNum"> 1850 </span> : }
|
|
<span class="lineNum"> 1851 </span><span class="lineCov"> 95 : log_flush();</span>
|
|
<span class="lineNum"> 1852 </span> :
|
|
<span class="lineNum"> 1853 </span><span class="lineCov"> 95 : tommy_list_foreach(&scanlist, (tommy_foreach_func*)free);</span>
|
|
<span class="lineNum"> 1854 </span> :
|
|
<span class="lineNum"> 1855 </span> : /* check the file-system on all disks */
|
|
<span class="lineNum"> 1856 </span><span class="lineCov"> 95 : state_fscheck(state, "after scan");</span>
|
|
<span class="lineNum"> 1857 </span> :
|
|
<span class="lineNum"> 1858 </span><span class="lineCov"> 95 : if (is_diff) {</span>
|
|
<span class="lineNum"> 1859 </span> : /* check for file difference */
|
|
<span class="lineNum"> 1860 </span><span class="lineCov"> 8 : if (!no_difference)</span>
|
|
<span class="lineNum"> 1861 </span><span class="lineCov"> 6 : return 1;</span>
|
|
<span class="lineNum"> 1862 </span> :
|
|
<span class="lineNum"> 1863 </span> : /* check also for incomplete "sync" */
|
|
<span class="lineNum"> 1864 </span><span class="lineCov"> 2 : if (parity_is_invalid(state))</span>
|
|
<span class="lineNum"> 1865 </span><span class="lineCov"> 1 : return 1;</span>
|
|
<span class="lineNum"> 1866 </span> : }
|
|
<span class="lineNum"> 1867 </span> :
|
|
<span class="lineNum"> 1868 </span><span class="lineCov"> 88 : return 0;</span>
|
|
<a name="1869"><span class="lineNum"> 1869 </span> : }</a>
|
|
<span class="lineNum"> 1870 </span> :
|
|
<span class="lineNum"> 1871 </span><span class="lineCov"> 8 : int state_diff(struct snapraid_state* state)</span>
|
|
<span class="lineNum"> 1872 </span> : {
|
|
<span class="lineNum"> 1873 </span><span class="lineCov"> 8 : return state_diffscan(state, 1);</span>
|
|
<a name="1874"><span class="lineNum"> 1874 </span> : }</a>
|
|
<span class="lineNum"> 1875 </span> :
|
|
<span class="lineNum"> 1876 </span><span class="lineCov"> 88 : void state_scan(struct snapraid_state* state)</span>
|
|
<span class="lineNum"> 1877 </span> : {
|
|
<span class="lineNum"> 1878 </span><span class="lineCov"> 88 : (void)state_diffscan(state, 0); /* ignore return value */</span>
|
|
<span class="lineNum"> 1879 </span><span class="lineCov"> 87 : }</span>
|
|
<span class="lineNum"> 1880 </span> :
|
|
</pre>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<br>
|
|
|
|
<table width="100%" border=0 cellspacing=0 cellpadding=0>
|
|
<tr><td class="ruler"><img src="../glass.png" width=3 height=3 alt=""></td></tr>
|
|
<tr><td class="versionInfo">Generated by: <a href="http://ltp.sourceforge.net/coverage/lcov.php" target="_parent">LCOV version 1.10</a></td></tr>
|
|
</table>
|
|
<br>
|
|
|
|
</body>
|
|
</html>
|