LCOV - code coverage report
Current view: top level - src/server/monitor - cache.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 67 92 72.8 %
Date: 2016-07-02 Functions: 7 9 77.8 %

          Line data    Source code
       1             : #include "../../burp.h"
       2             : #include "../../alloc.h"
       3             : #include "../../cmd.h"
       4             : #include "../../log.h"
       5             : #include "../../sbuf.h"
       6             : #include "../manio.h"
       7             : #include "json_output.h"
       8             : 
       9             : typedef struct ent ent_t;
      10             : 
      11             : struct ent
      12             : {
      13             :         char *name;
      14             :         int count;
      15             :         struct stat statp;
      16             :         struct ent **ents;
      17             : };
      18             : 
      19          62 : static void ent_free(struct ent **ent)
      20             : {
      21         124 :         if(!ent || !*ent) return;
      22          62 :         free_w(&(*ent)->name);
      23          62 :         free_v((void **)&(*ent)->ents);
      24          62 :         free_v((void **)ent);
      25             : }
      26             : 
      27          62 : static struct ent *ent_alloc(const char *name)
      28             : {
      29             :         struct ent *ent;
      30         124 :         if(!(ent=(struct ent *)calloc_w(1, sizeof(struct ent), __func__))
      31          62 :           || !(ent->name=strdup_w(name, __func__)))
      32             :                 goto error;
      33          62 :         return ent;
      34             : error:
      35           0 :         ent_free(&ent);
      36           0 :         return NULL;
      37             : }
      38             : 
      39             : // FIX THIS:
      40             : // For extra kicks, could make the config option allow multiple caches -
      41             : // eg, 'monitor_browse_cache=5', then rotate out the oldest one.
      42             : 
      43             : static struct ent *root=NULL;
      44             : static char *cached_client=NULL;
      45             : static unsigned long cached_bno=0;
      46             : 
      47          61 : static int ent_add_to_list(struct ent *ent,
      48             :         struct sbuf *sb, const char *ent_name)
      49             : {
      50          61 :         struct ent *enew=NULL;
      51          61 :         if(!(ent->ents=(struct ent **)realloc_w(ent->ents,
      52          61 :                 (ent->count+1)*sizeof(struct ent *), __func__))
      53          61 :           || !(enew=ent_alloc(ent_name)))
      54             :         {
      55           0 :                 log_out_of_memory(__func__);
      56             :                 return -1;
      57             :         }
      58          61 :         memcpy(&enew->statp, &sb->statp, sizeof(struct stat));
      59          61 :         ent->ents[ent->count]=enew;
      60          61 :         ent->count++;
      61             :         return 0;
      62             : }
      63             : 
      64          63 : static void ents_free(struct ent *ent)
      65             : {
      66          63 :         int i=0;
      67         126 :         if(!ent) return;
      68          61 :         for(i=0; i<ent->count; i++)
      69          61 :                 ents_free(ent->ents[i]);
      70          62 :         ent_free(&ent);
      71             : }
      72             : 
      73           2 : void cache_free(void)
      74             : {
      75           2 :         free_w(&cached_client);
      76           2 :         ents_free(root);
      77           2 : }
      78             : 
      79             : /*
      80             : static void cache_dump(struct ent *e, int *depth)
      81             : {
      82             :         int count;
      83             :         for(count=0; count<*depth; count++)
      84             :                 printf(" ");
      85             :         printf("'%s'\n", e->name);
      86             :         for(count=0; count<e->count; count++)
      87             :         {
      88             :                 (*depth)++;
      89             :                 cache_dump(e->ents[count], depth);
      90             :                 (*depth)--;
      91             :         }
      92             : }
      93             : */
      94             : 
      95           1 : int cache_load(struct manio *manio, struct sbuf *sb,
      96             :         const char *cname, unsigned long bno)
      97             : {
      98           1 :         int ret=-1;
      99           1 :         int ars=0;
     100             : //      int depth=0;
     101           1 :         char *tok=NULL;
     102           1 :         struct ent *point=NULL;
     103           1 :         struct ent *p=NULL;
     104             : 
     105             : //printf("in cache load\n");
     106           1 :         cache_free();
     107             : 
     108           1 :         if(!(root=ent_alloc(""))) goto end;
     109             : 
     110             :         while(1)
     111             :         {
     112          32 :                 sbuf_free_content(sb);
     113          32 :                 if((ars=manio_read(manio, sb)))
     114             :                 {
     115           1 :                         if(ars<0) goto end;
     116             :                         // ars==1 means it ended ok.
     117             :                         break;
     118             :                 }
     119             : 
     120          31 :                 if(manio->protocol==PROTO_2 && sb->endfile.buf)
     121             :                         continue;
     122             : 
     123          20 :                 if(sb->path.cmd!=CMD_DIRECTORY
     124          20 :                   && sb->path.cmd!=CMD_FILE
     125           6 :                   && sb->path.cmd!=CMD_ENC_FILE
     126           6 :                   && sb->path.cmd!=CMD_EFS_FILE
     127           6 :                   && sb->path.cmd!=CMD_SPECIAL
     128          22 :                   && !cmd_is_link(sb->path.cmd))
     129             :                         continue;
     130             : 
     131             :                 // Some messing around so that we can list '/'.
     132          20 :                 if(!*(root->name) && !strncmp(sb->path.buf, "/", 1))
     133             :                 {
     134           1 :                         memcpy(&root->statp, &sb->statp, sizeof(struct stat));
     135           1 :                         free_w(&root->name);
     136           1 :                         if(!(root->name=strdup_w("/", __func__)))
     137             :                                 goto end;
     138             :                 }
     139             : 
     140          20 :                 point=root;
     141          89 :                 if((tok=strtok(sb->path.buf, "/"))) do
     142             :                 {
     143          69 :                         if(point->count>0)
     144             :                         {
     145          27 :                                 p=point->ents[point->count-1];
     146          27 :                                 if(!strcmp(tok, p->name))
     147             :                                 {
     148             :                                         point=p;
     149             :                                         continue;
     150             :                                 }
     151             :                         }
     152             : 
     153          61 :                         if(sb->path.buf+sb->path.len!=tok+strlen(tok))
     154             :                         {
     155             :                                 // There is an entry in a directory where the
     156             :                                 // directory itself was not backed up.
     157             :                                 // We will make a fake entry for the directory,
     158             :                                 // and use the same stat data.
     159             :                                 // Make sure that we set the directory flag.
     160          41 :                                 sb->statp.st_mode&=S_IFDIR;
     161             :                         }
     162          61 :                         if(ent_add_to_list(point, sb, tok)) goto end;
     163          61 :                         point=point->ents[point->count-1];
     164             :                 } while((tok=strtok(NULL, "/")));
     165             :         }
     166             : 
     167           1 :         if(!(cached_client=strdup_w(cname, __func__)))
     168             :                 goto end;
     169           1 :         cached_bno=bno;
     170           1 :         ret=0;
     171             : //      cache_dump(root, &depth);
     172             : end:
     173           1 :         return ret;
     174             : }
     175             : 
     176           4 : int cache_loaded(const char *cname, unsigned long bno)
     177             : {
     178           4 :         if(cached_client
     179           2 :           && !strcmp(cname, cached_client)
     180           2 :           && cached_bno==bno)
     181             :                 return 1;
     182           3 :         return 0;
     183             : }
     184             : 
     185             : static int result_single(struct ent *ent)
     186             : {
     187             : //      printf("result: %s\n", ent->name);
     188           0 :         return json_from_statp(ent->name, &ent->statp);
     189             : }
     190             : 
     191           0 : static int result_list(struct ent *ent)
     192             : {
     193           0 :         int i=0;
     194             : //      printf("in results\n");
     195           0 :         for(i=0; i<ent->count; i++)
     196           0 :                 result_single(ent->ents[i]);
     197           0 :         return 0;
     198             : }
     199             : 
     200           0 : int cache_lookup(const char *browse)
     201             : {
     202           0 :         int i=0;
     203           0 :         int ret=-1;
     204           0 :         char *tok=NULL;
     205           0 :         char *copy=NULL;
     206           0 :         struct ent *point=root;
     207             : 
     208           0 :         if(!browse || !*browse)
     209             :         {
     210             :                 // The difference between the top level for Windows and the
     211             :                 // top level for non-Windows.
     212           0 :                 if(*(point->name)) ret=result_single(point);
     213           0 :                 else ret=result_list(point);
     214             :                 goto end;
     215             :         }
     216             : 
     217           0 :         if(!(copy=strdup_w(browse, __func__)))
     218             :                 goto end;
     219           0 :         if((tok=strtok(copy, "/"))) do
     220             :         {
     221             :                 // FIX THIS: Should do a binary search here, for monster speed
     222             :                 // increases when there are lots of files in a directory.
     223           0 :                 for(i=0; i<point->count; i++)
     224             :                 {
     225           0 :                         if(strcmp(tok, point->ents[i]->name)) continue;
     226             :                         point=point->ents[i];
     227             :                         break;
     228             :                 }
     229             :         } while((tok=strtok(NULL, "/")));
     230             : 
     231           0 :         ret=result_list(point);
     232             : end:
     233           0 :         free_w(&copy);
     234           0 :         return ret;
     235             : }

Generated by: LCOV version 1.10