@@ -12,23 +12,30 @@ static struct cache_def {
12
12
* Returns the length (on a path component basis) of the longest
13
13
* common prefix match of 'name' and the cached path string.
14
14
*/
15
- static inline int longest_match_lstat_cache (int len , const char * name )
15
+ static inline int longest_match_lstat_cache (int len , const char * name ,
16
+ int * previous_slash )
16
17
{
17
- int max_len , match_len = 0 , i = 0 ;
18
+ int max_len , match_len = 0 , match_len_prev = 0 , i = 0 ;
18
19
19
20
max_len = len < cache .len ? len : cache .len ;
20
21
while (i < max_len && name [i ] == cache .path [i ]) {
21
- if (name [i ] == '/' )
22
+ if (name [i ] == '/' ) {
23
+ match_len_prev = match_len ;
22
24
match_len = i ;
25
+ }
23
26
i ++ ;
24
27
}
25
28
/* Is the cached path string a substring of 'name'? */
26
- if (i == cache .len && cache .len < len && name [cache .len ] == '/' )
29
+ if (i == cache .len && cache .len < len && name [cache .len ] == '/' ) {
30
+ match_len_prev = match_len ;
27
31
match_len = cache .len ;
28
32
/* Is 'name' a substring of the cached path string? */
29
- else if ((i == len && len < cache .len && cache .path [len ] == '/' ) ||
30
- (i == len && len == cache .len ))
33
+ } else if ((i == len && len < cache .len && cache .path [len ] == '/' ) ||
34
+ (i == len && len == cache .len )) {
35
+ match_len_prev = match_len ;
31
36
match_len = len ;
37
+ }
38
+ * previous_slash = match_len_prev ;
32
39
return match_len ;
33
40
}
34
41
@@ -63,7 +70,7 @@ static inline void reset_lstat_cache(int track_flags, int prefix_len_stat_func)
63
70
static int lstat_cache (int len , const char * name ,
64
71
int track_flags , int prefix_len_stat_func )
65
72
{
66
- int match_len , last_slash , last_slash_dir ;
73
+ int match_len , last_slash , last_slash_dir , previous_slash ;
67
74
int match_flags , ret_flags , save_flags , max_len , ret ;
68
75
struct stat st ;
69
76
@@ -81,7 +88,8 @@ static int lstat_cache(int len, const char *name,
81
88
* Check to see if we have a match from the cache for
82
89
* the 2 "excluding" path types.
83
90
*/
84
- match_len = last_slash = longest_match_lstat_cache (len , name );
91
+ match_len = last_slash =
92
+ longest_match_lstat_cache (len , name , & previous_slash );
85
93
match_flags = cache .flags & track_flags & (FL_NOENT |FL_SYMLINK );
86
94
if (match_flags && match_len == cache .len )
87
95
return match_flags ;
@@ -167,6 +175,26 @@ static int lstat_cache(int len, const char *name,
167
175
return ret_flags ;
168
176
}
169
177
178
+ /*
179
+ * Invalidate the given 'name' from the cache, if 'name' matches
180
+ * completely with the cache.
181
+ */
182
+ void invalidate_lstat_cache (int len , const char * name )
183
+ {
184
+ int match_len , previous_slash ;
185
+
186
+ match_len = longest_match_lstat_cache (len , name , & previous_slash );
187
+ if (len == match_len ) {
188
+ if ((cache .track_flags & FL_DIR ) && previous_slash > 0 ) {
189
+ cache .path [previous_slash ] = '\0' ;
190
+ cache .len = previous_slash ;
191
+ cache .flags = FL_DIR ;
192
+ } else
193
+ reset_lstat_cache (cache .track_flags ,
194
+ cache .prefix_len_stat_func );
195
+ }
196
+ }
197
+
170
198
#define USE_ONLY_LSTAT 0
171
199
172
200
/*
0 commit comments