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

Generated by: LCOV version 1.10