"Fossies" - the Fresh Open Source Software Archive

Member "smbnetfs-0.6.3/src/smbitem.c" (1 Mar 2019, 18775 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 "smbitem.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.6.1_vs_0.6.2.

    1 #include "config.h"
    2 #include <stdlib.h>
    3 #include <string.h>
    4 #include <pthread.h>
    5 #include "common.h"
    6 #include "smbitem.h"
    7 
    8 struct trees{
    9     struct smbitem  *samba;
   10     struct smbitem  *user;
   11 };
   12 
   13 static struct trees trees           = { NULL, NULL };
   14 static pthread_mutex_t m_smbitem        = PTHREAD_MUTEX_INITIALIZER;
   15 
   16 static struct smbitem* smbitem_new_host(const char *name, int is_hidden){
   17     struct smbitem  *item;
   18 
   19     item = malloc(sizeof(struct smbitem) + strlen(name) + 1);
   20     if (item == NULL) return NULL;
   21 
   22     memset(item, 0 , sizeof(struct smbitem));
   23     item->ref_count = 1;
   24     item->name = (char *) (item + 1);
   25     strcpy(item->name, name);
   26     item->type = SMBITEM_HOST;
   27     item->touch_time = time(NULL);
   28     item->is_hidden = is_hidden;
   29     return item;
   30 }
   31 
   32 static struct smbitem* smbitem_new_group(const char *name){
   33     struct smbitem  *item;
   34 
   35     item = malloc(sizeof(struct smbitem) + strlen(name) + 1);
   36     if (item == NULL) return NULL;
   37 
   38     memset(item, 0 , sizeof(struct smbitem));
   39     item->ref_count = 1;
   40     item->name = (char *) (item + 1);
   41     strcpy(item->name, name);
   42     item->type = SMBITEM_GROUP;
   43     item->touch_time = time(NULL);
   44     return item;
   45 }
   46 
   47 static struct smbitem* smbitem_new_link(const char *name, const char *linkpath){
   48     struct smbitem  *item;
   49 
   50     item = (struct smbitem*) malloc(sizeof(struct smbitem) +
   51     strlen(name) + strlen(linkpath) + 2);
   52     if (item == NULL) return NULL;
   53 
   54     memset(item, 0 , sizeof(struct smbitem));
   55     item->ref_count = 1;
   56     item->name = (char *) (item + 1);
   57     strcpy(item->name, name);
   58     item->type = SMBITEM_LINK;
   59     item->touch_time = time(NULL);
   60     item->linkpath = item->name + strlen(name) + 1;
   61     strcpy(item->linkpath, linkpath);
   62     return item;
   63 }
   64 
   65 static inline void smbitem_delete_item(struct smbitem *item){
   66     free(item);
   67 }
   68 
   69 static inline void smbitem_aquire_item(struct smbitem *item){
   70     item->ref_count++;
   71 }
   72 
   73 static void smbitem_release_item(struct smbitem *item){
   74     item->ref_count--;
   75     if (item->ref_count == 0){
   76     switch(item->type){
   77         case SMBITEM_HOST:
   78         if (item->parent_group != NULL)
   79             smbitem_release_item(item->parent_group);
   80         break;
   81 
   82         case SMBITEM_GROUP:
   83         if (item->childs != NULL){
   84             int     i;
   85 
   86             for(i = 0; i < item->child_cnt; i++)
   87             smbitem_release_item(item->childs[i]);
   88             free(item->childs);
   89         }
   90         break;
   91 
   92         case SMBITEM_LINK:
   93         break;
   94 
   95         default:
   96         DPRINTF(0, "ERROR: item '%s' is damaged\n", item->name);
   97         return;
   98     }
   99     smbitem_delete_item(item);
  100     }
  101 }
  102 
  103 static void smbitem_delete_obsolete_items(struct smbitem *group, time_t threshold){
  104     int     i;
  105 
  106     for(i = group->child_cnt - 1; i >= 0; i--){
  107     if (group->childs[i]->type == SMBITEM_GROUP){
  108         smbitem_delete_obsolete_items(group->childs[i], threshold);
  109     }
  110     if (group->childs[i]->touch_time < threshold){
  111         smbitem_release_item(group->childs[i]);
  112         if (i != group->child_cnt - 1){
  113         memmove(&group->childs[i],
  114             &group->childs[i + 1],
  115             (group->child_cnt - i - 1) * sizeof(struct smbitem *));
  116         }
  117         group->child_cnt--;
  118     }
  119     }
  120 }
  121 
  122 /*
  123  * This function search for an item in specified SMBNetFS group,
  124  * group items MUST be sorted alphabetically, so we can bisect.
  125  * 'first' is the search starting position (usually zero)
  126  *
  127  * return:
  128  *   a) item position, if item with specified name was found
  129  *   b) negative value -(pos+1), if item was not found,
  130  *      where 'pos' is the position to insert the new element
  131  */
  132 static int smbitem_find_in_group_wl(struct smbitem *group, const char *name,
  133                 size_t name_len, int first){
  134     int last = group->child_cnt - 1;
  135 
  136     while(first <= last){
  137     int i       = (first + last) >> 1;
  138     int result  = strncasecmp(group->childs[i]->name, name, name_len);
  139 
  140     if ((result == 0) &&
  141         (group->childs[i]->name[name_len] == '\0')) return i;
  142     if (result < 0) first = i + 1;
  143     else last = i - 1;
  144     }
  145     return -(first + 1);
  146 }
  147 
  148 static inline int smbitem_find_in_group(struct smbitem *group, const char *name, int first){
  149     return smbitem_find_in_group_wl(group, name, strlen(name), first);
  150 }
  151 
  152 /*
  153  * This function insert an element to specified SMBNetFS group,
  154  * insert position MUST be obtained with smbitem_find_in_group().
  155  *
  156  * return:
  157  *   a) zero, if no errors
  158  *   b) (-1), if insertion failed
  159  */
  160 static int smbitem_insert_to_group(struct smbitem *group, struct smbitem *item, int pos){
  161     if ((pos > group->child_cnt) || (pos < 0)) return -1;
  162 
  163     if (group->max_child_cnt == group->child_cnt){
  164     struct smbitem  **new_childs;
  165     int     new_max_cnt;
  166 
  167     new_max_cnt = (group->max_child_cnt == 0) ?
  168             64 : 2 * group->max_child_cnt;
  169     new_childs = realloc(group->childs,
  170             new_max_cnt * sizeof(struct smbitem *));
  171     if (new_childs == NULL) return -1;
  172 
  173     group->max_child_cnt = new_max_cnt;
  174     group->childs = new_childs;
  175     }
  176 
  177     if (pos < group->child_cnt){
  178     memmove(&group->childs[pos + 1],
  179         &group->childs[pos],
  180         (group->child_cnt - pos) * sizeof(struct smbitem *));
  181     }
  182     group->childs[pos] = item;
  183     group->child_cnt++;
  184     group->touch_time = time(NULL);
  185     return 0;
  186 }
  187 
  188 int smbitem_init(void){
  189     int     result = -1;
  190 
  191     pthread_mutex_lock(&m_smbitem);
  192     if ((trees.samba  = smbitem_new_group("/")) == NULL) goto error;
  193     if ((trees.user   = smbitem_new_group("/")) == NULL){
  194         smbitem_release_item(trees.samba);
  195         trees.samba = NULL;
  196         goto error;
  197     }
  198     result = 0;
  199       error:
  200     pthread_mutex_unlock(&m_smbitem);
  201     return result;
  202 }
  203 
  204 void smbitem_done(void){
  205     pthread_mutex_lock(&m_smbitem);
  206     smbitem_release_item(trees.samba);
  207     smbitem_release_item(trees.user);
  208     trees.samba = trees.user = NULL;
  209     pthread_mutex_unlock(&m_smbitem);
  210 }
  211 
  212 int smbitem_mkgroup(const char *path, enum smbitem_tree_t tree){
  213     int         pos, result;
  214     struct smbitem  *dir;
  215 
  216     DPRINTF(6, "path=%s, tree=%d\n", path, tree);
  217 
  218     dir = (tree == SMBITEM_SAMBA_TREE) ? trees.samba : trees.user;
  219 
  220     if ((path == NULL) || (*path == '\0') ||
  221     (strchr(path, '/') != NULL) ||
  222     (strcmp(path, ".")  == 0) ||
  223     (strcmp(path, "..") == 0)) return -1;
  224 
  225     result = -1;
  226     pthread_mutex_lock(&m_smbitem);
  227     pos = smbitem_find_in_group(dir, path, 0);
  228     if (pos >= 0){
  229         if (dir->childs[pos]->type == SMBITEM_GROUP){
  230         /* group already exist, touch it */
  231         dir->childs[pos]->touch_time = time(NULL);
  232         }else{
  233         /* replace founded item with a new group */
  234         struct smbitem *item = smbitem_new_group(path);
  235         if (item == NULL) goto error;
  236 
  237         smbitem_release_item(dir->childs[pos]);
  238         dir->childs[pos] = item;
  239         }
  240     }else{
  241         /* create new group and add it to a directory */
  242         struct smbitem *item = smbitem_new_group(path);
  243         if (item == NULL) goto error;
  244         if (smbitem_insert_to_group(dir, item, -(pos + 1)) != 0){
  245         smbitem_release_item(item);
  246         goto error;
  247         }
  248     }
  249     dir->touch_time = time(NULL);
  250     result = 0;
  251       error:
  252     pthread_mutex_unlock(&m_smbitem);
  253     return result;
  254 }
  255 
  256 int smbitem_mkhost(const char *path, const char *group,
  257         int is_hidden, enum smbitem_tree_t tree){
  258 
  259     int         pos, result;
  260     struct smbitem  *dir, *item, *parent_group;
  261 
  262     DPRINTF(6, "path=%s, group=%s, is_hidden=%d, tree=%d\n",
  263     path, group, is_hidden, tree);
  264 
  265     dir = (tree == SMBITEM_SAMBA_TREE) ? trees.samba : trees.user;
  266 
  267     if ((path == NULL) || (*path == '\0') ||
  268     (strchr(path, '/') != NULL) ||
  269     (strcmp(path, ".")  == 0) ||
  270     (strcmp(path, "..") == 0)) return -1;
  271 
  272     if (group != NULL){
  273     if ((strchr(group, '/') != NULL) ||
  274         (strcmp(group, ".")  == 0) ||
  275         (strcmp(group, "..") == 0)) return -1;
  276     }
  277 
  278     result = -1;
  279     pthread_mutex_lock(&m_smbitem);
  280     if (group != NULL){
  281         pos = smbitem_find_in_group(dir, group, 0);
  282         if ((pos < 0) || (dir->childs[pos]->type != SMBITEM_GROUP)){
  283         DPRINTF(5, "ERROR: group '%s' was not found\n", group);
  284         goto error;
  285         }
  286         parent_group = dir->childs[pos];
  287     }else parent_group = NULL;
  288 
  289     pos = smbitem_find_in_group(dir, path, 0);
  290     if (pos >= 0){
  291         if (dir->childs[pos]->type == SMBITEM_HOST){
  292         /* host already exist, update it */
  293         item = dir->childs[pos];
  294         if ((item->parent_group != NULL) &&
  295             (item->parent_group != parent_group)){
  296 
  297             smbitem_release_item(item->parent_group);
  298             item->parent_group = NULL;
  299         }
  300         item->is_hidden = is_hidden;
  301         item->touch_time = time(NULL);
  302         }else{
  303         /* replace founded item with a new host */
  304         item = smbitem_new_host(path, is_hidden);
  305         if (item == NULL) goto error;
  306 
  307         smbitem_release_item(dir->childs[pos]);
  308         dir->childs[pos] = item;
  309         }
  310     }else{
  311         /* create new host and add it to a directory */
  312         item = smbitem_new_host(path, is_hidden);
  313         if (item == NULL) goto error;
  314         if (smbitem_insert_to_group(dir, item, -(pos + 1)) != 0){
  315         smbitem_release_item(item);
  316         goto error;
  317         }
  318     }
  319     if (parent_group != NULL){
  320         smbitem_aquire_item(parent_group);
  321         parent_group->touch_time = time(NULL);
  322         item->parent_group = parent_group;
  323     }
  324     dir->touch_time = time(NULL);
  325     result = 0;
  326       error:
  327     pthread_mutex_unlock(&m_smbitem);
  328     return result;
  329 }
  330 
  331 int smbitem_mklink(const char *path, const char *linkpath, enum smbitem_tree_t tree){
  332     int         pos, result;
  333     size_t      dirname_len;
  334     const char      *tmp, *dirname;
  335     struct smbitem  *dir;
  336 
  337     DPRINTF(6, "path=%s, linkpath=%s, tree=%d\n", path, linkpath, tree);
  338 
  339     dir = (tree == SMBITEM_SAMBA_TREE) ? trees.samba : trees.user;
  340 
  341     if ((linkpath == NULL) || (*linkpath == '\0')) return -1;
  342     if ((path == NULL) || (*path == '\0')) return -1;
  343 
  344     if ((tmp = strchr(path, '/')) != NULL){
  345     dirname = path;
  346     dirname_len = tmp - path;
  347     path = tmp + 1;
  348     }else{
  349     dirname = NULL;
  350     dirname_len = 0;
  351     }
  352 
  353     if ((*path == '\0') ||
  354     (strchr(path, '/') != NULL) ||
  355     (strcmp(path, ".")  == 0) ||
  356     (strcmp(path, "..") == 0)){
  357 
  358     return -1;
  359     }
  360 
  361     result = -1;
  362     pthread_mutex_lock(&m_smbitem);
  363     if (dirname != NULL){
  364         pos = smbitem_find_in_group_wl(dir, dirname, dirname_len, 0);
  365         if ((pos < 0) || (dir->childs[pos]->type != SMBITEM_GROUP)){
  366         DPRINTF(5, "ERROR: group '%.*s' was not found\n",
  367             (int) dirname_len, dirname);
  368         goto error;
  369         }
  370         dir = dir->childs[pos];
  371     }
  372 
  373     pos = smbitem_find_in_group(dir, path, 0);
  374     if (pos >= 0){
  375         if ((dir->childs[pos]->type == SMBITEM_LINK) &&
  376         (strcmp(dir->childs[pos]->linkpath, linkpath) == 0)){
  377 
  378         /* link already exist, update it */
  379         dir->childs[pos]->touch_time = time(NULL);
  380         }else{
  381         /* replace founded item with a new link */
  382         struct smbitem *item = smbitem_new_link(path, linkpath);
  383         if (item == NULL) goto error;
  384 
  385         smbitem_release_item(dir->childs[pos]);
  386         dir->childs[pos] = item;
  387         }
  388     }else{
  389         /* create new link and add it to a directory */
  390         struct smbitem *item = smbitem_new_link(path, linkpath);
  391         if (item == NULL) goto error;
  392         if (smbitem_insert_to_group(dir, item, -(pos + 1)) != 0){
  393         smbitem_release_item(item);
  394         goto error;
  395         }
  396     }
  397     dir->touch_time = time(NULL);
  398     result = 0;
  399       error:
  400     pthread_mutex_unlock(&m_smbitem);
  401     return result;
  402 }
  403 
  404 struct smbitem * smbitem_get_samba_groups(void){
  405     int         i;
  406     struct smbitem  *dir;
  407 
  408     dir = NULL;
  409     pthread_mutex_lock(&m_smbitem);
  410     /* create new group */
  411     dir = smbitem_new_group("/");
  412     if (dir == NULL) goto end;
  413 
  414     /* add samba groups only */
  415     for(i = 0; i < trees.samba->child_cnt; i++){
  416         if (trees.samba->childs[i]->type != SMBITEM_GROUP) continue;
  417         if (smbitem_insert_to_group(dir,
  418             trees.samba->childs[i], dir->child_cnt) != 0) goto error;
  419         smbitem_aquire_item(trees.samba->childs[i]);
  420     }
  421     goto end;
  422 
  423       error:
  424         if (dir != NULL) smbitem_release_item(dir);
  425         dir = NULL;
  426       end:
  427     pthread_mutex_unlock(&m_smbitem);
  428     return dir;
  429 }
  430 
  431 struct smbitem * smbitem_getdir(const char *path){
  432     int         i, pos;
  433     struct smbitem  *dir_user, *dir_samba, *dir;
  434 
  435     if ((path == NULL) ||
  436     (strchr(path, '/') != NULL) ||
  437     (strcmp(path, ".")  == 0) ||
  438     (strcmp(path, "..") == 0)) return NULL;
  439 
  440     dir = NULL;
  441     pthread_mutex_lock(&m_smbitem);
  442     if (*path != '\0'){
  443         /* find dir in user configured tree */
  444         dir_user = NULL;
  445         pos = smbitem_find_in_group(trees.user, path, 0);
  446         if (pos >= 0){
  447         if (trees.user->childs[pos]->type == SMBITEM_GROUP){
  448             dir_user = trees.user->childs[pos];
  449         }else{
  450             DPRINTF(5, "ERROR: '%s' is not a group\n", path);
  451             goto error;
  452         }
  453         }
  454 
  455         /* find dir in samba scanned tree */
  456         dir_samba = NULL;
  457         pos = smbitem_find_in_group(trees.samba, path, 0);
  458         if (pos >= 0){
  459         if (trees.samba->childs[pos]->type == SMBITEM_GROUP){
  460             dir_samba = trees.samba->childs[pos];
  461         }else if (dir_user == NULL){
  462             DPRINTF(5, "ERROR: '%s' is not a group\n", path);
  463             goto error;
  464         }
  465         }
  466     }else{
  467         dir_user = trees.user;
  468         dir_samba = trees.samba;
  469     }
  470 
  471     /* create new group */
  472     dir = smbitem_new_group(path);
  473     if (dir == NULL) goto error;
  474 
  475     /* copy contents of dir_user to dir */
  476     if ((dir_user != NULL) && (dir_user->child_cnt > 0)){
  477         dir->childs = malloc(dir_user->max_child_cnt * sizeof(struct smbitem *));
  478         if (dir->childs == NULL) goto error;
  479 
  480         dir->max_child_cnt = dir_user->max_child_cnt;
  481         dir->child_cnt = dir_user->child_cnt;
  482         memcpy(dir->childs, dir_user->childs,
  483         dir_user->child_cnt * sizeof(struct smbitem *));
  484 
  485         for(i = 0; i < dir_user->child_cnt; i++)
  486         smbitem_aquire_item(dir->childs[i]);
  487     }
  488 
  489     /* merge with dir_samba */
  490     if ((dir_samba != NULL) && (dir_samba->child_cnt > 0)){
  491         pos = 0;
  492         for(i = 0; i < dir_samba->child_cnt; i++){
  493         pos = smbitem_find_in_group(dir, dir_samba->childs[i]->name, pos);
  494         if (pos < 0){
  495             pos = -(pos + 1);
  496             if (smbitem_insert_to_group(dir, dir_samba->childs[i], pos) != 0)
  497             goto error;
  498             smbitem_aquire_item(dir_samba->childs[i]);
  499         }
  500         pos++;
  501         }
  502     }
  503     goto end;
  504 
  505       error:
  506         if (dir != NULL) smbitem_release_item(dir);
  507         dir = NULL;
  508       end:
  509     pthread_mutex_unlock(&m_smbitem);
  510     return dir;
  511 }
  512 
  513 void smbitem_release_dir(struct smbitem *item){
  514     if (item->type != SMBITEM_GROUP){
  515     DPRINTF(5, "ERROR: item is not a group\n");
  516     return;
  517     }
  518     pthread_mutex_lock(&m_smbitem);
  519     smbitem_release_item(item);
  520     pthread_mutex_unlock(&m_smbitem);
  521 }
  522 
  523 void smbitem_delete_obsolete(time_t threshold, enum smbitem_tree_t tree){
  524     struct smbitem  *dir;
  525 
  526     DPRINTF(6, "threshold=%d, tree=%d\n", (int)threshold, tree);
  527 
  528     dir = (tree == SMBITEM_SAMBA_TREE) ? trees.samba : trees.user;
  529 
  530     pthread_mutex_lock(&m_smbitem);
  531     smbitem_delete_obsolete_items(dir, threshold);
  532     pthread_mutex_unlock(&m_smbitem);
  533 }
  534 
  535 static inline const char * smbitem_get_path_end(const char *path){
  536     const char *next = strchr(path, '/');
  537     return (next != NULL) ? next : path + strlen(path);
  538 }
  539 
  540 enum smbitem_path_t smbitem_what_is(const char *path){
  541     int         pos;
  542     struct smbitem  *dir, *tmp_dir;
  543     const char      *next;
  544 
  545     if (path == NULL) return SMBITEM_UNKNOWN;
  546 
  547     DPRINTF(6, "path=%s\n", path);
  548 
  549     while(*path == '/') path++;
  550     if (*path == '\0') return SMBITEM_SMBNETFS_DIR;
  551     next = smbitem_get_path_end(path);
  552 
  553     if ((dir = smbitem_getdir("")) == NULL) return SMBITEM_UNKNOWN;
  554 
  555     if ((pos = smbitem_find_in_group_wl(dir, path, next - path, 0)) >= 0){
  556     switch(dir->childs[pos]->type){
  557         case SMBITEM_HOST:
  558         goto smbitem_host;
  559 
  560         case SMBITEM_GROUP:
  561         while(*next == '/') next++;
  562         if (*next == '\0') goto smbitem_smbnetfs_dir;
  563 
  564         tmp_dir = smbitem_getdir(dir->childs[pos]->name);
  565         if (tmp_dir == NULL) goto error;
  566 
  567         smbitem_release_dir(dir);
  568         dir = tmp_dir;
  569         path = next;
  570         next = smbitem_get_path_end(next);
  571 
  572         pos = smbitem_find_in_group_wl(dir, path, next - path, 0);
  573         if (pos < 0) goto error;
  574         if (dir->childs[pos]->type != SMBITEM_LINK) goto error;
  575 
  576         case SMBITEM_LINK:
  577         goto smbitem_smbnetfs_link;
  578 
  579         default:
  580         goto error;
  581     }
  582     }
  583 
  584   smbitem_host:
  585     smbitem_release_dir(dir);
  586 
  587     while(*next == '/') next++;
  588     if (*next == '\0') return SMBITEM_SMB_NAME;
  589     next = smbitem_get_path_end(next);
  590 
  591     while(*next == '/') next++;
  592     if (*next == '\0') return SMBITEM_SMB_SHARE;
  593     return SMBITEM_SMB_SHARE_ITEM;
  594 
  595   smbitem_smbnetfs_dir:
  596     if (*next != '\0') goto error;
  597     smbitem_release_dir(dir);
  598     return SMBITEM_SMBNETFS_DIR;
  599 
  600   smbitem_smbnetfs_link:
  601     if (*next != '\0') goto error;
  602     smbitem_release_dir(dir);
  603     return SMBITEM_SMBNETFS_LINK;
  604 
  605   error:
  606     smbitem_release_dir(dir);
  607     return SMBITEM_UNKNOWN;
  608 }
  609 
  610 int smbitem_is_name_exist(const char *name){
  611     int         pos;
  612 
  613     if ((name == NULL) || (*name == '\0')) return 0;
  614     pthread_mutex_lock(&m_smbitem);
  615     /* find dir in user configured tree */
  616     pos = smbitem_find_in_group(trees.user, name, 0);
  617     if (pos < 0){
  618         /* find dir in samba scanned tree */
  619         pos = smbitem_find_in_group(trees.samba, name, 0);
  620     }
  621     pthread_mutex_unlock(&m_smbitem);
  622     return (pos >= 0);
  623 }
  624 
  625 int smbitem_readlink(const char *path, char *buf, size_t size){
  626     int         pos;
  627     struct smbitem  *dir, *tmp_dir;
  628     const char      *next;
  629 
  630     if (path == NULL) return -1;
  631 
  632     DPRINTF(6, "path=%s\n", path);
  633 
  634     while(*path == '/') path++;
  635     if (*path == '\0') return -1;
  636     next = smbitem_get_path_end(path);
  637 
  638     if ((dir = smbitem_getdir("")) == NULL) return -1;
  639 
  640     if ((pos = smbitem_find_in_group_wl(dir, path, next - path, 0)) >= 0){
  641     switch(dir->childs[pos]->type){
  642         case SMBITEM_GROUP:
  643         while(*next == '/') next++;
  644         if (*next == '\0') goto error;
  645 
  646         tmp_dir = smbitem_getdir(dir->childs[pos]->name);
  647         if (tmp_dir == NULL) goto error;
  648 
  649         smbitem_release_dir(dir);
  650         dir = tmp_dir;
  651         path = next;
  652         next = smbitem_get_path_end(next);
  653 
  654         pos = smbitem_find_in_group_wl(dir, path, next - path, 0);
  655         if (pos < 0) goto error;
  656         if (dir->childs[pos]->type != SMBITEM_LINK) goto error;
  657         /* FALLTHRU */
  658 
  659         case SMBITEM_LINK:
  660         if (*next != '\0') goto error;
  661         strncpy(buf, dir->childs[pos]->linkpath, size);
  662         buf[size - 1] = '\0';
  663         smbitem_release_dir(dir);
  664         return 0;
  665 
  666         default:
  667         goto error;
  668     }
  669     }
  670 
  671   error:
  672     smbitem_release_dir(dir);
  673     return -1;
  674 }
  675 
  676 int smbitem_get_group(const char *host, char *buf, size_t size){
  677     int         pos, result;
  678     struct smbitem  *item;
  679 
  680     if (host == NULL) return -1;
  681 
  682     DPRINTF(6, "host=%s\n", host);
  683 
  684     while(*host == '/') host++;
  685     if (*host == '\0') return -1;
  686     if ((strcmp(host, ".") == 0) || (strcmp(host, "..") == 0)) return -1;
  687 
  688     result = -1;
  689     pthread_mutex_lock(&m_smbitem);
  690     item = trees.user;
  691     if ((pos = smbitem_find_in_group(item, host, 0)) >= 0) goto ok;
  692     item = trees.samba;
  693     if ((pos = smbitem_find_in_group(item, host, 0)) <  0) goto end;
  694 
  695       ok:
  696     item = item->childs[pos];
  697     if (item->type != SMBITEM_HOST) goto end;
  698     if (item->parent_group == NULL) goto end;
  699 
  700     item = item->parent_group;
  701     strncpy(buf, item->name, size);
  702     buf[size - 1] = '\0';
  703     result = 0;
  704 
  705       end:
  706     pthread_mutex_unlock(&m_smbitem);
  707     return result;
  708 }