LCOV - code coverage report
Current view: top level - src/server/monitor - cache.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 69 96 71.9 %
Date: 2022-12-03 01:09:05 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          63 : static void ent_free(struct ent **ent)
      22             : {
      23          63 :         if(!ent || !*ent) return;
      24          63 :         free_w(&(*ent)->name);
      25          63 :         free_w(&(*ent)->link);
      26          63 :         free_v((void **)&(*ent)->ents);
      27          63 :         free_v((void **)ent);
      28             : }
      29             : 
      30          63 : static struct ent *ent_alloc(const char *name, const char *link)
      31             : {
      32             :         struct ent *ent;
      33          63 :         if(!(ent=(struct ent *)calloc_w(1, sizeof(struct ent), __func__))
      34          63 :            || !(ent->name=strdup_w(name, __func__)) || !(ent->link=strdup_w(link? link:"", __func__)))
      35             :                 goto error;
      36          63 :         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          62 : static int ent_add_to_list(struct ent *ent,
      51             :         struct sbuf *sb, const char *ent_name)
      52             : {
      53          62 :         struct ent *enew=NULL;
      54          62 :         if(!(ent->ents=(struct ent **)realloc_w(ent->ents,
      55          62 :                 (ent->count+1)*sizeof(struct ent *), __func__))
      56          62 :            || !(enew=ent_alloc(ent_name, sb->link.buf)))
      57             :         {
      58           0 :                 log_out_of_memory(__func__);
      59             :                 return -1;
      60             :         }
      61          62 :         memcpy(&enew->statp, &sb->statp, sizeof(struct stat));
      62          62 :         ent->ents[ent->count]=enew;
      63          62 :         ent->count++;
      64             :         return 0;
      65             : }
      66             : 
      67          64 : static void ents_free(struct ent *ent)
      68             : {
      69          64 :         int i=0;
      70          64 :         if(!ent) return;
      71          62 :         for(i=0; i<ent->count; i++)
      72          62 :                 ents_free(ent->ents[i]);
      73          63 :         ent_free(&ent);
      74             : }
      75             : 
      76           1 : void cache_free(void)
      77             : {
      78           2 :         free_w(&cached_client);
      79           2 :         ents_free(root);
      80           1 : }
      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             :         cache_free();
     110             : 
     111           1 :         if(!(root=ent_alloc("",""))) goto end;
     112             : 
     113             :         while(1)
     114             :         {
     115          21 :                 sbuf_free_content(sb);
     116          21 :                 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          40 :                 if(sb->path.cmd!=CMD_DIRECTORY
     124          20 :                   && sb->path.cmd!=CMD_FILE
     125           7 :                   && sb->path.cmd!=CMD_ENC_FILE
     126           5 :                   && sb->path.cmd!=CMD_EFS_FILE
     127           5 :                   && sb->path.cmd!=CMD_SPECIAL
     128           3 :                   && !cmd_is_link(sb->path.cmd))
     129           0 :                         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          20 :                 if((tok=strtok(sb->path.buf, "/"))) do
     142             :                 {
     143          89 :                         if(point->count>0)
     144             :                         {
     145          46 :                                 p=point->ents[point->count-1];
     146          46 :                                 if(!strcmp(tok, p->name))
     147             :                                 {
     148          27 :                                         point=p;
     149          27 :                                         continue;
     150             :                                 }
     151             :                         }
     152             : 
     153          62 :                         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          42 :                                 sb->statp.st_mode&=S_IFDIR;
     161             :                         }
     162          62 :                         if(ent_add_to_list(point, sb, tok)) goto end;
     163          62 :                         point=point->ents[point->count-1];
     164          89 :                 } 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_entry(ent->name, ent->link, &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           0 :         } 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.13