Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/coreutils/src/gnulib/lib/fts-cycle.c |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /* Detect cycles in file tree walks. | - | ||||||||||||||||||
2 | - | |||||||||||||||||||
3 | Copyright (C) 2003-2006, 2009-2018 Free Software Foundation, Inc. | - | ||||||||||||||||||
4 | - | |||||||||||||||||||
5 | Written by Jim Meyering. | - | ||||||||||||||||||
6 | - | |||||||||||||||||||
7 | This program is free software: you can redistribute it and/or modify | - | ||||||||||||||||||
8 | it under the terms of the GNU General Public License as published by | - | ||||||||||||||||||
9 | the Free Software Foundation; either version 3 of the License, or | - | ||||||||||||||||||
10 | (at your option) any later version. | - | ||||||||||||||||||
11 | - | |||||||||||||||||||
12 | This program is distributed in the hope that it will be useful, | - | ||||||||||||||||||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | - | ||||||||||||||||||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | - | ||||||||||||||||||
15 | GNU General Public License for more details. | - | ||||||||||||||||||
16 | - | |||||||||||||||||||
17 | You should have received a copy of the GNU General Public License | - | ||||||||||||||||||
18 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ | - | ||||||||||||||||||
19 | - | |||||||||||||||||||
20 | #include "cycle-check.h" | - | ||||||||||||||||||
21 | #include "hash.h" | - | ||||||||||||||||||
22 | - | |||||||||||||||||||
23 | /* Use each of these to map a device/inode pair to an FTSENT. */ | - | ||||||||||||||||||
24 | struct Active_dir | - | ||||||||||||||||||
25 | { | - | ||||||||||||||||||
26 | dev_t dev; | - | ||||||||||||||||||
27 | ino_t ino; | - | ||||||||||||||||||
28 | FTSENT *fts_ent; | - | ||||||||||||||||||
29 | }; | - | ||||||||||||||||||
30 | - | |||||||||||||||||||
31 | static bool | - | ||||||||||||||||||
32 | AD_compare (void const *x, void const *y) | - | ||||||||||||||||||
33 | { | - | ||||||||||||||||||
34 | struct Active_dir const *ax = x; | - | ||||||||||||||||||
35 | struct Active_dir const *ay = y; | - | ||||||||||||||||||
36 | return ax->ino == ay->ino executed 1431 times by 3 tests: return ax->ino == ay->ino && ax->dev == ay->dev; Executed by:
| 1431 | ||||||||||||||||||
37 | && ax->dev == ay->dev; executed 1431 times by 3 tests: return ax->ino == ay->ino && ax->dev == ay->dev; Executed by:
| 1431 | ||||||||||||||||||
38 | } | - | ||||||||||||||||||
39 | - | |||||||||||||||||||
40 | static size_t | - | ||||||||||||||||||
41 | AD_hash (void const *x, size_t table_size) | - | ||||||||||||||||||
42 | { | - | ||||||||||||||||||
43 | struct Active_dir const *ax = x; | - | ||||||||||||||||||
44 | return (uintmax_t) ax->ino % table_size; executed 2858 times by 3 tests: return (uintmax_t) ax->ino % table_size; Executed by:
| 2858 | ||||||||||||||||||
45 | } | - | ||||||||||||||||||
46 | - | |||||||||||||||||||
47 | /* Set up the cycle-detection machinery. */ | - | ||||||||||||||||||
48 | - | |||||||||||||||||||
49 | static bool | - | ||||||||||||||||||
50 | setup_dir (FTS *fts) | - | ||||||||||||||||||
51 | { | - | ||||||||||||||||||
52 | if (fts->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL))
| 530-14208 | ||||||||||||||||||
53 | { | - | ||||||||||||||||||
54 | enum { HT_INITIAL_SIZE = 31 }; | - | ||||||||||||||||||
55 | fts->fts_cycle.ht = hash_initialize (HT_INITIAL_SIZE, NULL, AD_hash, | - | ||||||||||||||||||
56 | AD_compare, free); | - | ||||||||||||||||||
57 | if (! fts->fts_cycle.ht)
| 0-530 | ||||||||||||||||||
58 | return false; never executed: return 0 ; | 0 | ||||||||||||||||||
59 | } executed 530 times by 3 tests: end of block Executed by:
| 530 | ||||||||||||||||||
60 | else | - | ||||||||||||||||||
61 | { | - | ||||||||||||||||||
62 | fts->fts_cycle.state = malloc (sizeof *fts->fts_cycle.state); | - | ||||||||||||||||||
63 | if (! fts->fts_cycle.state)
| 0-14208 | ||||||||||||||||||
64 | return false; never executed: return 0 ; | 0 | ||||||||||||||||||
65 | cycle_check_init (fts->fts_cycle.state); | - | ||||||||||||||||||
66 | } executed 14208 times by 6 tests: end of block Executed by:
| 14208 | ||||||||||||||||||
67 | - | |||||||||||||||||||
68 | return true; executed 14738 times by 6 tests: return 1 ; Executed by:
| 14738 | ||||||||||||||||||
69 | } | - | ||||||||||||||||||
70 | - | |||||||||||||||||||
71 | /* Enter a directory during a file tree walk. */ | - | ||||||||||||||||||
72 | - | |||||||||||||||||||
73 | static bool | - | ||||||||||||||||||
74 | enter_dir (FTS *fts, FTSENT *ent) | - | ||||||||||||||||||
75 | { | - | ||||||||||||||||||
76 | if (fts->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL))
| 1389-100755 | ||||||||||||||||||
77 | { | - | ||||||||||||||||||
78 | struct stat const *st = ent->fts_statp; | - | ||||||||||||||||||
79 | struct Active_dir *ad = malloc (sizeof *ad); | - | ||||||||||||||||||
80 | struct Active_dir *ad_from_table; | - | ||||||||||||||||||
81 | - | |||||||||||||||||||
82 | if (!ad)
| 0-1389 | ||||||||||||||||||
83 | return false; never executed: return 0 ; | 0 | ||||||||||||||||||
84 | - | |||||||||||||||||||
85 | ad->dev = st->st_dev; | - | ||||||||||||||||||
86 | ad->ino = st->st_ino; | - | ||||||||||||||||||
87 | ad->fts_ent = ent; | - | ||||||||||||||||||
88 | - | |||||||||||||||||||
89 | /* See if we've already encountered this directory. | - | ||||||||||||||||||
90 | This can happen when following symlinks as well as | - | ||||||||||||||||||
91 | with a corrupted directory hierarchy. */ | - | ||||||||||||||||||
92 | ad_from_table = hash_insert (fts->fts_cycle.ht, ad); | - | ||||||||||||||||||
93 | - | |||||||||||||||||||
94 | if (ad_from_table != ad)
| 2-1387 | ||||||||||||||||||
95 | { | - | ||||||||||||||||||
96 | free (ad); | - | ||||||||||||||||||
97 | if (!ad_from_table)
| 0-2 | ||||||||||||||||||
98 | return false; never executed: return 0 ; | 0 | ||||||||||||||||||
99 | - | |||||||||||||||||||
100 | /* There was an entry with matching dev/inode already in the table. | - | ||||||||||||||||||
101 | Record the fact that we've found a cycle. */ | - | ||||||||||||||||||
102 | ent->fts_cycle = ad_from_table->fts_ent; | - | ||||||||||||||||||
103 | ent->fts_info = FTS_DC; | - | ||||||||||||||||||
104 | } executed 2 times by 1 test: end of block Executed by:
| 2 | ||||||||||||||||||
105 | } executed 1389 times by 3 tests: end of block Executed by:
| 1389 | ||||||||||||||||||
106 | else | - | ||||||||||||||||||
107 | { | - | ||||||||||||||||||
108 | if (cycle_check (fts->fts_cycle.state, ent->fts_statp))
| 0-100755 | ||||||||||||||||||
109 | { | - | ||||||||||||||||||
110 | /* FIXME: setting fts_cycle like this isn't proper. | - | ||||||||||||||||||
111 | To do what the documentation requires, we'd have to | - | ||||||||||||||||||
112 | go around the cycle again and find the right entry. | - | ||||||||||||||||||
113 | But no callers in coreutils use the fts_cycle member. */ | - | ||||||||||||||||||
114 | ent->fts_cycle = ent; | - | ||||||||||||||||||
115 | ent->fts_info = FTS_DC; | - | ||||||||||||||||||
116 | } never executed: end of block | 0 | ||||||||||||||||||
117 | } executed 100755 times by 6 tests: end of block Executed by:
| 100755 | ||||||||||||||||||
118 | - | |||||||||||||||||||
119 | return true; executed 102144 times by 6 tests: return 1 ; Executed by:
| 102144 | ||||||||||||||||||
120 | } | - | ||||||||||||||||||
121 | - | |||||||||||||||||||
122 | /* Leave a directory during a file tree walk. */ | - | ||||||||||||||||||
123 | - | |||||||||||||||||||
124 | static void | - | ||||||||||||||||||
125 | leave_dir (FTS *fts, FTSENT *ent) | - | ||||||||||||||||||
126 | { | - | ||||||||||||||||||
127 | struct stat const *st = ent->fts_statp; | - | ||||||||||||||||||
128 | if (fts->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL))
| 1387-100750 | ||||||||||||||||||
129 | { | - | ||||||||||||||||||
130 | struct Active_dir obj; | - | ||||||||||||||||||
131 | void *found; | - | ||||||||||||||||||
132 | obj.dev = st->st_dev; | - | ||||||||||||||||||
133 | obj.ino = st->st_ino; | - | ||||||||||||||||||
134 | found = hash_delete (fts->fts_cycle.ht, &obj); | - | ||||||||||||||||||
135 | if (!found)
| 0-1387 | ||||||||||||||||||
136 | abort (); never executed: abort (); | 0 | ||||||||||||||||||
137 | free (found); | - | ||||||||||||||||||
138 | } executed 1387 times by 3 tests: end of block Executed by:
| 1387 | ||||||||||||||||||
139 | else | - | ||||||||||||||||||
140 | { | - | ||||||||||||||||||
141 | FTSENT *parent = ent->fts_parent; | - | ||||||||||||||||||
142 | if (parent != NULL && 0 <= parent->fts_level)
| 0-100750 | ||||||||||||||||||
143 | CYCLE_CHECK_REFLECT_CHDIR_UP (fts->fts_cycle.state, never executed: abort (); executed 1632 times by 5 tests: end of block Executed by:
executed 95861 times by 5 tests: end of block Executed by:
| 0-95861 | ||||||||||||||||||
144 | *(parent->fts_statp), *st); | - | ||||||||||||||||||
145 | } executed 100750 times by 6 tests: end of block Executed by:
| 100750 | ||||||||||||||||||
146 | } | - | ||||||||||||||||||
147 | - | |||||||||||||||||||
148 | /* Free any memory used for cycle detection. */ | - | ||||||||||||||||||
149 | - | |||||||||||||||||||
150 | static void | - | ||||||||||||||||||
151 | free_dir (FTS *sp) | - | ||||||||||||||||||
152 | { | - | ||||||||||||||||||
153 | if (sp->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL))
| 530-14208 | ||||||||||||||||||
154 | { | - | ||||||||||||||||||
155 | if (sp->fts_cycle.ht)
| 0-530 | ||||||||||||||||||
156 | hash_free (sp->fts_cycle.ht); executed 530 times by 3 tests: hash_free (sp->fts_cycle.ht); Executed by:
| 530 | ||||||||||||||||||
157 | } executed 530 times by 3 tests: end of block Executed by:
| 530 | ||||||||||||||||||
158 | else | - | ||||||||||||||||||
159 | free (sp->fts_cycle.state); executed 14208 times by 6 tests: free (sp->fts_cycle.state); Executed by:
| 14208 | ||||||||||||||||||
160 | } | - | ||||||||||||||||||
Source code | Switch to Preprocessed file |