smbnetfs  0.6.3
About: SMBNetFS is a Linux/FreeBSD filesystem that allow you to use samba/microsoft network in the same manner as the network neighborhood in Microsoft Windows.
  Fossies Dox: smbnetfs-0.6.3.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

stat_workaround.c
Go to the documentation of this file.
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 
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 
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 
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 
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 
49 static pthread_mutex_t m_stat_workaround = PTHREAD_MUTEX_INITIALIZER;
50 
51 
53  DPRINTF(7, "new_status=%s\n", new_status ? "true" : "false");
54  pthread_mutex_lock(&m_stat_workaround);
56  pthread_mutex_unlock(&m_stat_workaround);
57  return 1;
58 }
59 
61  if (depth < -1) return 0;
62  DPRINTF(7, "depth=%d\n", depth);
63  pthread_mutex_lock(&m_stat_workaround);
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",
75 
77 
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);
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 
101  int result;
102 
103  pthread_mutex_lock(&m_stat_workaround);
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 
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;
135 
136  refresh_item:
137  exception->touch_time = time(NULL);
138  return 1;
139 }
140 
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 
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 
173  int result;
174 
175  pthread_mutex_lock(&m_stat_workaround);
177  pthread_mutex_unlock(&m_stat_workaround);
178  return result;
179 }
180 
182  struct stat_workaround_predefined *elem;
183 
184  pthread_mutex_lock(&m_stat_workaround);
186  for(elem = stat_workaround_predefined_list; elem->name != NULL; elem++)
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 */
205  exception = list_entry(elem, struct stat_workaround_exception, entries);
206  elem = elem->next;
207 
208  if (exception->touch_time < threshold){
210  free(exception);
211  }
212  }
213 
214  /* check matching with workaround list */
217  workaround = list_entry(elem, struct stat_workaround, entries);
218  elem = elem->next;
219 
220  if (workaround->touch_time < threshold){
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 */
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 */
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 }
#define DPRINTF(level, fmt, args...)
Definition: common.h:47
static int is_valid_list_elem(LIST *list, LIST *elem)
Definition: list.h:88
static LIST * first_list_elem(LIST *list)
Definition: list.h:16
static void add_to_list_back(LIST *list, LIST *elem)
Definition: list.h:34
#define list_entry(ptr, type, member)
Definition: list.h:11
#define STATIC_LIST_INITIALIZER(list)
Definition: list.h:14
static void insert_to_list_before(LIST *list, LIST *elem, LIST *new_elem)
Definition: list.h:56
static void remove_from_list(LIST *list, LIST *elem)
Definition: list.h:77
static int stat_workaround_check_path(const char *path, int min_depth)
static int stat_workaround_default_depth
void stat_workaround_add_default_entries(void)
int stat_workaround_add_exception(const char *path)
int stat_workaround_add_name(const char *name, int case_sensitive, int depth)
static int stat_workaround_add_exception_internal(const char *path)
static int stat_workaround_add_exception_internal_low(const char *path, size_t len, int depth)
static struct stat_workaround_predefined stat_workaround_predefined_list[]
static int stat_workaround_default_entries
static LIST stat_workaround_list
static int stat_workaround_add_name_internal(const char *name, int case_sensitive, int depth)
int stat_workaround_enable_default_entries(int new_status)
static pthread_mutex_t m_stat_workaround
static LIST stat_workaround_exception_list
int stat_workaround_set_default_depth(int depth)
int stat_workaround_is_name_ignored(const char *path)
void stat_workaround_delete_obsolete(time_t threshold)
Definition: list.h:6
struct __LIST * next
Definition: list.h:7