LCOV - code coverage report
Current view: top level - src/server - list.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 117 158 74.1 %
Date: 2019-03-30 01:11:57 Functions: 9 10 90.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../alloc.h"
       3             : #include "../asfd.h"
       4             : #include "../async.h"
       5             : #include "../attribs.h"
       6             : #include "../bu.h"
       7             : #include "../cmd.h"
       8             : #include "../cntr.h"
       9             : #include "../cstat.h"
      10             : #include "../log.h"
      11             : #include "../prepend.h"
      12             : #include "../regexp.h"
      13             : #include "bu_get.h"
      14             : #include "child.h"
      15             : #include "list.h"
      16             : #include "manio.h"
      17             : 
      18             : enum list_mode
      19             : {
      20             :         LIST_MODE_BACKUPS=0,
      21             :         LIST_MODE_CONTENTS_ONE,
      22             :         LIST_MODE_CONTENTS_MANY,
      23             : };
      24             : 
      25             : static struct asfd *asfd;
      26             : static struct cntr *cntr;
      27             : static enum protocol protocol;
      28             : static const char *backup;
      29             : static regex_t *regex=NULL;
      30             : static const char *browsedir;
      31             : static struct bu *bu_list=NULL;
      32             : static enum list_mode list_mode;
      33             : static unsigned long bno=0;
      34             : 
      35          57 : int list_server_init(
      36             :         struct asfd *a,
      37             :         struct sdirs *s,
      38             :         struct cntr *c,
      39             :         enum protocol p,
      40             :         const char *backup_str,
      41             :         const char *regex_str,
      42             :         const char *browsedir_str)
      43             : {
      44          57 :         asfd=a;
      45          57 :         cntr=c;
      46          57 :         protocol=p;
      47          57 :         backup=backup_str;
      48          57 :         browsedir=browsedir_str;
      49          57 :         if(bu_get_list_with_working(s, &bu_list))
      50             :                 goto error;
      51          57 :         if(regex_str
      52           9 :           && *regex_str
      53           9 :           && !(regex=regex_compile(regex_str)))
      54             :         {
      55           1 :                 char msg[256]="";
      56           1 :                 snprintf(msg, sizeof(msg), "unable to compile regex: %s\n",
      57             :                         regex_str);
      58           1 :                 log_and_send(asfd, msg);
      59             :                 goto error;
      60             :         }
      61          56 :         list_mode=LIST_MODE_BACKUPS;
      62          56 :         if(regex || browsedir)
      63          16 :                 list_mode=LIST_MODE_CONTENTS_MANY;
      64          56 :         if(backup && *backup)
      65             :         {
      66          42 :                 if((bno=strtoul(backup, NULL, 10))>0)
      67          19 :                         list_mode=LIST_MODE_CONTENTS_ONE;
      68          23 :                 else if(*backup=='c')
      69           8 :                         list_mode=LIST_MODE_CONTENTS_ONE;
      70          15 :                 else if(*backup=='a')
      71          11 :                         list_mode=LIST_MODE_CONTENTS_MANY;
      72             :                 else
      73           4 :                         list_mode=LIST_MODE_CONTENTS_ONE;
      74             :         }
      75             :         return 0;
      76             : error:
      77             :         list_server_free();
      78           1 :         return -1;
      79             : }
      80             : 
      81          57 : void list_server_free(void)
      82             : {
      83          58 :         bu_list_free(&bu_list);
      84          58 :         regex_free(&regex);
      85          57 : }
      86             : 
      87             : static void maybe_fake_directory(struct sbuf *mb)
      88             : {
      89          50 :         if(S_ISDIR(mb->statp.st_mode))
      90             :                 return;
      91             :         // We are faking a directory entry.
      92             :         // Make sure the directory bit is set.
      93          48 :         mb->statp.st_mode &= ~(S_IFMT);
      94          48 :         mb->statp.st_mode |= S_IFDIR;
      95          48 :         attribs_encode(mb);
      96             : }
      97             : 
      98          77 : int check_browsedir(const char *browsedir,
      99             :         struct sbuf *mb, size_t bdlen, char **last_bd_match)
     100             : {
     101          77 :         char *cp=mb->path.buf;
     102          77 :         char *copy=NULL;
     103          77 :         if(bdlen>0)
     104             :         {
     105          42 :                 if(strncmp(browsedir, cp, bdlen))
     106             :                         return 0;
     107          30 :                 cp+=bdlen;
     108          30 :                 if(browsedir[bdlen-1]!='/')
     109             :                 {
     110          24 :                         if(*cp!='\0')
     111             :                         {
     112          20 :                                 if(*cp!='/')
     113             :                                         return 0;
     114          18 :                                 cp++;
     115             :                         }
     116             :                 }
     117             :         }
     118          63 :         if(*cp=='\0')
     119           8 :                 cp=(char *)".";
     120          63 :         if(!(copy=strdup_w(cp, __func__)))
     121             :                 goto error;
     122          62 :         if((cp=strchr(copy, '/')))
     123             :         {
     124          40 :                 if(bdlen==0) cp++;
     125          40 :                 *cp='\0';
     126             : 
     127             :                 maybe_fake_directory(mb);
     128             :         }
     129          22 :         else if(!strcmp(mb->path.buf, "/")
     130           2 :           && !strcmp(browsedir, "/"))
     131             :                 maybe_fake_directory(mb);
     132          20 :         else if(mb->path.cmd==CMD_DIRECTORY)
     133             :                 maybe_fake_directory(mb);
     134             : 
     135             :         // Strip off possible trailing slash.
     136          62 :         if((cp=strrchr(copy, '/')) && cp>copy)
     137          14 :                 *cp='\0';
     138             : 
     139          62 :         if(*last_bd_match
     140          50 :           && !strcmp(*last_bd_match, copy))
     141             :         {
     142             :                 // Got a duplicate match.
     143          22 :                 free_w(&copy);
     144          22 :                 return 0;
     145             :         }
     146          40 :         free_w(&mb->path.buf);
     147          40 :         mb->path.buf=copy;
     148          40 :         free_w(last_bd_match);
     149          40 :         if(!(*last_bd_match=strdup_w(copy, __func__)))
     150             :                 goto error;
     151             :         return 1;
     152             : error:
     153           1 :         free_w(&copy);
     154           1 :         log_out_of_memory(__func__);
     155           1 :         return -1;
     156             : }
     157             : 
     158           0 : static int list_manifest(const char *fullpath)
     159             : {
     160           0 :         int ret=0;
     161           0 :         struct sbuf *sb=NULL;
     162           0 :         struct manio *manio=NULL;
     163           0 :         char *manifest_dir=NULL;
     164           0 :         char *last_bd_match=NULL;
     165           0 :         size_t bdlen=0;
     166             : 
     167           0 :         if(!(manifest_dir=prepend_s(fullpath,
     168           0 :                 protocol==PROTO_1?"manifest.gz":"manifest"))
     169           0 :           || !(manio=manio_open(manifest_dir, "rb", protocol))
     170           0 :           || !(sb=sbuf_alloc(protocol)))
     171             :         {
     172           0 :                 log_and_send_oom(asfd);
     173           0 :                 goto error;
     174             :         }
     175             : 
     176           0 :         if(browsedir) bdlen=strlen(browsedir);
     177             : 
     178             :         while(1)
     179             :         {
     180           0 :                 sbuf_free_content(sb);
     181             : 
     182           0 :                 switch(manio_read(manio, sb))
     183             :                 {
     184             :                         case 0: break;
     185           0 :                         case 1: if(browsedir && *browsedir && !last_bd_match)
     186           0 :                                         asfd_write_wrapper_str(asfd,
     187             :                                                 CMD_ERROR,
     188             :                                                 "directory not found");
     189             :                                 goto end; // Finished OK.
     190             :                         default: goto error;
     191             :                 }
     192             : 
     193           0 :                 if(protocol==PROTO_2 && sb->endfile.buf)
     194           0 :                         continue;
     195           0 :                 if(sbuf_is_metadata(sb))
     196           0 :                         continue;
     197             : 
     198           0 :                 if(write_status(CNTR_STATUS_LISTING, sb->path.buf, cntr))
     199             :                         goto error;
     200             : 
     201           0 :                 if(browsedir)
     202             :                 {
     203             :                         int r;
     204           0 :                         if((r=check_browsedir(browsedir,
     205             :                                 sb, bdlen, &last_bd_match))<0)
     206             :                                         goto error;
     207           0 :                         if(!r) continue;
     208             :                 }
     209             : 
     210           0 :                 if(regex && !regex_check(regex, sb->path.buf))
     211           0 :                         continue;
     212             : 
     213           0 :                 if(asfd_write_wrapper(asfd, &sb->attr)
     214           0 :                   || asfd_write_wrapper(asfd, &sb->path))
     215             :                         goto error;
     216           0 :                 if(sbuf_is_link(sb)
     217           0 :                   && asfd_write_wrapper(asfd, &sb->link))
     218             :                         goto error;
     219             :         }
     220             : 
     221             : error:
     222             :         ret=-1;
     223             : end:
     224           0 :         sbuf_free(&sb);
     225           0 :         free_w(&manifest_dir);
     226           0 :         manio_close(&manio);
     227           0 :         free_w(&last_bd_match);
     228           0 :         return ret;
     229             : }
     230             : 
     231          73 : static char *get_extradesc(struct bu *bu)
     232             : {
     233          73 :         if(bu->flags & BU_WORKING)
     234           0 :                 return strdup_w(" (working)", __func__);
     235          73 :         else if(bu->flags & BU_FINISHING)
     236           0 :                 return strdup_w(" (finishing)", __func__);
     237             :         // Protocol2 backups are all deletable, so do not mention it.
     238          73 :         else if(bu->flags & BU_DELETABLE && protocol==1)
     239          19 :                 return strdup_w(" (deletable)", __func__);
     240          54 :         return strdup_w("", __func__);
     241             : }
     242             : 
     243          73 : static int send_backup_name_to_client(struct bu *bu)
     244             : {
     245             :         int ret;
     246          73 :         char msg[64]="";
     247             :         char *extradesc;
     248          73 :         if(!(extradesc=get_extradesc(bu)))
     249             :                 return -1;
     250          73 :         snprintf(msg, sizeof(msg), "%s%s", bu->timestamp, extradesc);
     251          73 :         ret=asfd_write_wrapper_str(asfd, CMD_TIMESTAMP, msg);
     252          73 :         free_w(&extradesc);
     253          73 :         return ret;
     254             : }
     255             : 
     256             : static int list_all_backups(void)
     257             : {
     258          10 :         int found=0;
     259          10 :         struct bu *bu=NULL;
     260          24 :         for(bu=bu_list; bu; bu=bu->next)
     261             :         {
     262          15 :                 found=1;
     263          15 :                 if(send_backup_name_to_client(bu))
     264             :                         return -1;
     265             :         }
     266             :         return found;
     267             : }
     268             : 
     269          31 : static int list_contents_one(
     270             :         int list_server_callback(const char *fullpath))
     271             : {
     272          31 :         struct bu *bu=NULL;
     273          73 :         for(bu=bu_list; bu; bu=bu->next)
     274             :         {
     275          65 :                 if(!strcmp(bu->timestamp, backup)
     276          65 :                   || bu->bno==bno
     277          50 :                   || (*backup=='c' && (bu->flags & BU_CURRENT)))
     278             :                 {
     279          23 :                         if(cntr)
     280           0 :                                 cntr->bno=bu->bno;
     281          23 :                         if(send_backup_name_to_client(bu)
     282          22 :                           || list_server_callback(bu->path))
     283             :                                 return -1;
     284             :                         return 1;
     285             :                 }
     286             :         }
     287             :         return 0;
     288             : }
     289             : 
     290          15 : static int list_contents_many(
     291             :         int list_server_callback(const char *fullpath))
     292             : {
     293          15 :         int found=0;
     294          15 :         struct bu *bu=NULL;
     295          47 :         for(bu=bu_list; bu; bu=bu->next)
     296             :         {
     297          35 :                 found=1;
     298          35 :                 if(cntr)
     299           0 :                         cntr->bno=bu->bno;
     300          35 :                 if(send_backup_name_to_client(bu)
     301          34 :                   || list_server_callback(bu->path))
     302             :                         return -1;
     303             :         }
     304             :         return found;
     305             : }
     306             : 
     307             : #ifndef UTEST
     308             : static
     309             : #endif
     310          56 : int do_list_server_work(
     311             :         int list_server_callback(const char *fullpath))
     312             : {
     313          56 :         int ret=-1;
     314          56 :         int found=0;
     315             : 
     316             :         //logp("in do_list_server\n");
     317             : 
     318          56 :         if(write_status(CNTR_STATUS_LISTING, NULL, cntr))
     319             :                 goto end;
     320             : 
     321          56 :         switch(list_mode)
     322             :         {
     323             :                 case LIST_MODE_BACKUPS:
     324          10 :                         if((found=list_all_backups())<0)
     325             :                                 goto end;
     326             :                         break;
     327             :                 case LIST_MODE_CONTENTS_ONE:
     328          31 :                         if((found=list_contents_one(list_server_callback))<0)
     329             :                                 goto end;
     330             :                         break;
     331             :                 case LIST_MODE_CONTENTS_MANY:
     332          15 :                         if((found=list_contents_many(list_server_callback))<0)
     333             :                                 goto end;
     334             :                         break;
     335             :         }
     336             : 
     337          49 :         if(!found)
     338             :         {
     339          11 :                 if(list_mode==LIST_MODE_BACKUPS)
     340             :                 {
     341           3 :                         asfd_write_wrapper_str(asfd,
     342             :                                 CMD_MESSAGE, "no backups");
     343             :                         // Success.
     344             :                 }
     345             :                 else
     346             :                 {
     347           8 :                         asfd_write_wrapper_str(asfd,
     348             :                                 CMD_MESSAGE, "backup not found");
     349           8 :                         goto end;
     350             :                 }
     351             :         }
     352             : 
     353             :         ret=0;
     354             : end:
     355          56 :         bu_list_free(&bu_list);
     356          56 :         return ret;
     357             : }
     358             : 
     359           1 : int do_list_server(void)
     360             : {
     361           1 :         return do_list_server_work(list_manifest);
     362             : }

Generated by: LCOV version 1.13