"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 }