This source file includes following definitions.
- AD_compare
- AD_hash
- setup_dir
- enter_dir
- leave_dir
- free_dir
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include "cycle-check.h"
21 #include "hash.h"
22
23
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
37 && ax->dev == ay->dev;
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;
45 }
46
47
48
49 static bool
50 setup_dir (FTS *fts)
51 {
52 if (fts->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL))
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)
58 return false;
59 }
60 else
61 {
62 fts->fts_cycle.state = malloc (sizeof *fts->fts_cycle.state);
63 if (! fts->fts_cycle.state)
64 return false;
65 cycle_check_init (fts->fts_cycle.state);
66 }
67
68 return true;
69 }
70
71
72
73 static bool
74 enter_dir (FTS *fts, FTSENT *ent)
75 {
76 if (fts->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL))
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)
83 return false;
84
85 ad->dev = st->st_dev;
86 ad->ino = st->st_ino;
87 ad->fts_ent = ent;
88
89
90
91
92 ad_from_table = hash_insert (fts->fts_cycle.ht, ad);
93
94 if (ad_from_table != ad)
95 {
96 free (ad);
97 if (!ad_from_table)
98 return false;
99
100
101
102 ent->fts_cycle = ad_from_table->fts_ent;
103 ent->fts_info = FTS_DC;
104 }
105 }
106 else
107 {
108 if (cycle_check (fts->fts_cycle.state, ent->fts_statp))
109 {
110
111
112
113
114 ent->fts_cycle = ent;
115 ent->fts_info = FTS_DC;
116 }
117 }
118
119 return true;
120 }
121
122
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))
129 {
130 struct Active_dir obj;
131 void *found;
132 obj.dev = st->st_dev;
133 obj.ino = st->st_ino;
134 found = hash_remove (fts->fts_cycle.ht, &obj);
135 if (!found)
136 abort ();
137 free (found);
138 }
139 else
140 {
141 FTSENT *parent = ent->fts_parent;
142 if (parent != NULL && 0 <= parent->fts_level)
143 CYCLE_CHECK_REFLECT_CHDIR_UP (fts->fts_cycle.state,
144 *(parent->fts_statp), *st);
145 }
146 }
147
148
149
150 static void
151 free_dir (FTS *sp)
152 {
153 if (sp->fts_options & (FTS_TIGHT_CYCLE_CHECK | FTS_LOGICAL))
154 {
155 if (sp->fts_cycle.ht)
156 hash_free (sp->fts_cycle.ht);
157 }
158 else
159 free (sp->fts_cycle.state);
160 }