"Fossies" - the Fresh Open Source Software Archive 
Member "smbnetfs-0.6.3/src/stat_workaround.c" (10 Jan 2015, 10028 Bytes) of package /linux/misc/smbnetfs-0.6.3.tar.bz2:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "stat_workaround.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
0.5.3b_vs_0.6.0.
1 #include "config.h"
2 #include <time.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <pthread.h>
6
7 #include "list.h"
8 #include "common.h"
9 #include "smbitem.h"
10 #include "stat_workaround.h"
11
12 struct stat_workaround_predefined{
13 int case_sensitive; // is predefined name case sensitive?
14 int depth; // name search depth
15 char *name; // predefined name to be workarounded
16 };
17
18 struct stat_workaround{
19 LIST entries;
20 time_t touch_time; // struct touch time
21 int case_sensitive; // is name case sensitive?
22 int depth; // name search depth
23 int len; // calculated from the name
24 char name[1]; // name to be workarounded
25 };
26
27 struct stat_workaround_exception{
28 LIST entries;
29 time_t touch_time; // struct touch time
30 int depth; // calculated from the path
31 int len; // calculated from the path
32 char path[1]; // exception path
33 };
34
35 static struct stat_workaround_predefined stat_workaround_predefined_list[] = {
36 { 1, 3, ".directory" },
37 { 1, 3, ".git" },
38 { 1, 3, "HEAD" },
39 { 0, 3, "desktop.ini" },
40 { 1, 1, "autorun.inf" },
41 { 1, 1, ".xdg-volume-info" },
42 { 0, 0, NULL }
43 };
44
45 static int stat_workaround_default_entries = 1;
46 static int stat_workaround_default_depth = 3;
47 static LIST stat_workaround_list = STATIC_LIST_INITIALIZER(stat_workaround_list);
48 static LIST stat_workaround_exception_list = STATIC_LIST_INITIALIZER(stat_workaround_exception_list);
49 static pthread_mutex_t m_stat_workaround = PTHREAD_MUTEX_INITIALIZER;
50
51
52 int stat_workaround_enable_default_entries(int new_status){
53 DPRINTF(7, "new_status=%s\n", new_status ? "true" : "false");
54 pthread_mutex_lock(&m_stat_workaround);
55 stat_workaround_default_entries = new_status;
56 pthread_mutex_unlock(&m_stat_workaround);
57 return 1;
58 }
59
60 int stat_workaround_set_default_depth(int depth){
61 if (depth < -1) return 0;
62 DPRINTF(7, "depth=%d\n", depth);
63 pthread_mutex_lock(&m_stat_workaround);
64 stat_workaround_default_depth = depth;
65 pthread_mutex_unlock(&m_stat_workaround);
66 return 1;
67 }
68
69 static int stat_workaround_add_name_internal(const char *name, int case_sensitive, int depth){
70 LIST *elem;
71 struct stat_workaround *workaround;
72
73 DPRINTF(6, "name=%s, case_sensitive=%d, depth=%d\n",
74 name, case_sensitive, depth);
75
76 if (depth < -1) depth = stat_workaround_default_depth;
77
78 elem = first_list_elem(&stat_workaround_list);
79 while(is_valid_list_elem(&stat_workaround_list, elem)){
80 workaround = list_entry(elem, struct stat_workaround, entries);
81 if (strcmp(workaround->name, name) == 0) goto refresh_item;
82 elem = elem->next;
83 }
84
85 workaround = malloc(sizeof(struct stat_workaround) + strlen(name));
86 if (workaround == NULL) return 0;
87
88 memset(workaround, 0, sizeof(struct stat_workaround) + strlen(name));
89 strcpy(workaround->name, name);
90 workaround->len = strlen(name);
91 add_to_list_back(&stat_workaround_list, &workaround->entries);
92
93 refresh_item:
94 workaround->touch_time = time(NULL);
95 workaround->depth = depth;
96 workaround->case_sensitive = case_sensitive;
97 return 1;
98 }
99
100 int stat_workaround_add_name(const char *name, int case_sensitive, int depth){
101 int result;
102
103 pthread_mutex_lock(&m_stat_workaround);
104 result = stat_workaround_add_name_internal(name, case_sensitive, depth);
105 pthread_mutex_unlock(&m_stat_workaround);
106 return result;
107 }
108
109 /********************************************************************
110 * WARNING: stat_workaround_exception_list is sorted alphabetically *
111 ********************************************************************/
112 static int stat_workaround_add_exception_internal_low(const char *path, size_t len, int depth){
113 LIST *elem;
114 struct stat_workaround_exception *exception;
115 int result = 1;
116
117 for(; (len > 0) && (path[len - 1] == '/'); len--);
118
119 elem = first_list_elem(&stat_workaround_exception_list);
120 while(is_valid_list_elem(&stat_workaround_exception_list, elem)){
121 exception = list_entry(elem, struct stat_workaround_exception, entries);
122 if ((result = strncmp(exception->path, path, len)) < 0) break;
123 if ((result == 0) && (exception->path[len] == '\0')) goto refresh_item;
124 elem = elem->next;
125 }
126
127 exception = malloc(sizeof(struct stat_workaround_exception) + len);
128 if (exception == NULL) return 0;
129
130 memset(exception, 0, sizeof(struct stat_workaround_exception) + len);
131 strncpy(exception->path, path, len);
132 exception->len = len;
133 exception->depth = depth;
134 insert_to_list_before(&stat_workaround_exception_list, elem, &exception->entries);
135
136 refresh_item:
137 exception->touch_time = time(NULL);
138 return 1;
139 }
140
141 static int stat_workaround_add_exception_internal(const char *path){
142 size_t pos;
143 int depth;
144
145 DPRINTF(6, "path=%s\n", path);
146
147 pos = 0;
148 depth = 0;
149 while(path[pos]){
150 while(path[pos] == '/') pos++;
151 if (path[pos] == '\0') break;
152 while((path[pos] != '/') && (path[pos] != '\0')) pos++;
153
154 if (!stat_workaround_add_exception_internal_low(path, pos, ++depth)) return 0;
155 }
156
157 int i = 0;
158 LIST *elem;
159 struct stat_workaround_exception *exception;
160
161 elem = first_list_elem(&stat_workaround_exception_list);
162 while(is_valid_list_elem(&stat_workaround_exception_list, elem)){
163 exception = list_entry(elem, struct stat_workaround_exception, entries);
164 DPRINTF(6, "%d: path=%s, len=%d, depth=%d\n",
165 i, exception->path, exception->len, exception->depth);
166 i++;
167 elem = elem->next;
168 }
169 return 1;
170 }
171
172 int stat_workaround_add_exception(const char *path){
173 int result;
174
175 pthread_mutex_lock(&m_stat_workaround);
176 result = stat_workaround_add_exception_internal(path);
177 pthread_mutex_unlock(&m_stat_workaround);
178 return result;
179 }
180
181 void stat_workaround_add_default_entries(void){
182 struct stat_workaround_predefined *elem;
183
184 pthread_mutex_lock(&m_stat_workaround);
185 if (stat_workaround_default_entries){
186 for(elem = stat_workaround_predefined_list; elem->name != NULL; elem++)
187 stat_workaround_add_name_internal(elem->name,
188 elem->case_sensitive, elem->depth);
189 }
190 pthread_mutex_unlock(&m_stat_workaround);
191 }
192
193 void stat_workaround_delete_obsolete(time_t threshold){
194 LIST *elem;
195 struct stat_workaround *workaround;
196 struct stat_workaround_exception *exception;
197
198 DPRINTF(6, "threshold=%d\n", (int)threshold);
199
200 pthread_mutex_lock(&m_stat_workaround);
201
202 /* check matching with exception list */
203 elem = first_list_elem(&stat_workaround_exception_list);
204 while(is_valid_list_elem(&stat_workaround_exception_list, elem)){
205 exception = list_entry(elem, struct stat_workaround_exception, entries);
206 elem = elem->next;
207
208 if (exception->touch_time < threshold){
209 remove_from_list(&stat_workaround_exception_list, &exception->entries);
210 free(exception);
211 }
212 }
213
214 /* check matching with workaround list */
215 elem = first_list_elem(&stat_workaround_list);
216 while(is_valid_list_elem(&stat_workaround_list, elem)){
217 workaround = list_entry(elem, struct stat_workaround, entries);
218 elem = elem->next;
219
220 if (workaround->touch_time < threshold){
221 remove_from_list(&stat_workaround_list, &workaround->entries);
222 free(workaround);
223 }
224 }
225
226 pthread_mutex_unlock(&m_stat_workaround);
227 }
228
229 static int stat_workaround_check_path(const char *path, int min_depth){
230 LIST *elem;
231 struct stat_workaround *workaround;
232 const char *path_start, *path_end;
233 ssize_t len;
234 int i;
235 int (*cmp_func)(const char *, const char *, size_t);
236
237 DPRINTF(7, "path=%s, min_depth=%d\n", path, min_depth);
238
239 /* check matching with workaround list */
240 elem = first_list_elem(&stat_workaround_list);
241 while(is_valid_list_elem(&stat_workaround_list, elem)){
242 workaround = list_entry(elem, struct stat_workaround, entries);
243 DPRINTF(7, "workaround->name=%s\n", workaround->name);
244
245 cmp_func = workaround->case_sensitive ? strncmp : strncasecmp;
246
247 path_start = path;
248 len = strlen(workaround->name);
249 for(i = min_depth; (i < workaround->depth) || (workaround->depth == -1); i++){
250 while(*path_start == '/') path_start++;
251 if (*path_start == '\0') break;
252
253 DPRINTF(7, "path_start=%s\n", path_start);
254 path_end = path_start;
255 while((*path_end != '/') && (*path_end != '\0')) path_end++;
256 if ((path_end - path_start == len) &&
257 (cmp_func(path_start, workaround->name, len) == 0)) return 1;
258
259 path_start = path_end;
260 }
261
262 elem = elem->next;
263 }
264 return 0;
265 }
266
267 int stat_workaround_is_name_ignored(const char *path){
268 LIST *elem;
269 struct stat_workaround_exception *exception;
270 ssize_t len, min_len;
271 int result, ret;
272
273 DPRINTF(7, "path=%s\n", path);
274
275 for(len = strlen(path); (len > 1) && (path[len - 1] == '/'); len--);
276
277 pthread_mutex_lock(&m_stat_workaround);
278
279 /* check matching with exception list */
280 elem = first_list_elem(&stat_workaround_exception_list);
281 while(is_valid_list_elem(&stat_workaround_exception_list, elem)){
282 exception = list_entry(elem, struct stat_workaround_exception, entries);
283
284 min_len = (len <= exception->len) ? len : exception->len;
285 ret = strncmp(exception->path, path, min_len);
286
287 DPRINTF(7, "exception->path=%s, min_len=%zd, ret=%d\n",
288 exception->path, min_len, ret);
289
290 if (ret == 0){
291 if (min_len == len){
292 if ((exception->path[len] == '/') || (exception->path[len] == '\0')){
293 /* path is a part of exception path, so do not ignore it */
294 result = 0;
295 goto end;
296 }
297 }else{
298 if (path[exception->len] == '/'){
299 /* path contain an exception path, so start */
300 /* scanning from exception->depth level */
301 result = stat_workaround_check_path(path + min_len, exception->depth);
302 goto end;
303 }
304 }
305 }
306
307 elem = elem->next;
308 }
309
310 // if (smbitem_is_name_exist(workaround->name)) continue;
311
312 /* scan the full path for a pattern */
313 result = stat_workaround_check_path(path, 0);
314
315 end:
316 pthread_mutex_unlock(&m_stat_workaround);
317
318 DPRINTF(7, "path=%s, result=%d\n", path, result);
319 return result;
320 }