LCOV - code coverage report
Current view: top level - src/server - list.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 115 154 74.7 %
Date: 2017-10-31 Functions: 10 11 90.9 %

          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(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             :                 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          50 : static void maybe_fake_directory(struct sbuf *mb)
      88             : {
      89          50 :         if(S_ISDIR(mb->statp.st_mode))
      90          50 :                 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          40 :                 maybe_fake_directory(mb);
     128             :         }
     129          22 :         else if(!strcmp(mb->path.buf, "/")
     130           2 :           && !strcmp(browsedir, "/"))
     131           2 :                 maybe_fake_directory(mb);
     132          20 :         else if(mb->path.cmd==CMD_DIRECTORY)
     133           8 :                 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 int send_backup_name_to_client(struct bu *bu)
     232             : {
     233          73 :         char msg[64]="";
     234         146 :         snprintf(msg, sizeof(msg), "%s%s",
     235             :                 bu->timestamp,
     236             :                 // Protocol2 backups are all deletable, so do not mention it.
     237          73 :                 protocol==PROTO_1
     238          38 :                 && (bu->flags & BU_DELETABLE)?" (deletable)":"");
     239          73 :         return asfd_write_wrapper_str(asfd, CMD_TIMESTAMP, msg);
     240             : }
     241             : 
     242          10 : static int list_all_backups(void)
     243             : {
     244          10 :         int found=0;
     245          25 :         struct bu *bu=NULL;
     246          24 :         for(bu=bu_list; bu; bu=bu->next)
     247             :         {
     248          15 :                 found=1;
     249          15 :                 if(send_backup_name_to_client(bu))
     250             :                         return -1;
     251             :         }
     252             :         return found;
     253             : }
     254             : 
     255          31 : static int list_contents_one(
     256             :         int list_server_callback(const char *fullpath))
     257             : {
     258          54 :         struct bu *bu=NULL;
     259          73 :         for(bu=bu_list; bu; bu=bu->next)
     260             :         {
     261          65 :                 if(!strcmp(bu->timestamp, backup)
     262          65 :                   || bu->bno==bno
     263          50 :                   || (*backup=='c' && (bu->flags & BU_CURRENT)))
     264             :                 {
     265          23 :                         if(cntr)
     266           0 :                                 cntr->bno=bu->bno;
     267          23 :                         if(send_backup_name_to_client(bu)
     268          22 :                           || list_server_callback(bu->path))
     269             :                                 return -1;
     270             :                         return 1;
     271             :                 }
     272             :         }
     273             :         return 0;
     274             : }
     275             : 
     276          15 : static int list_contents_many(
     277             :         int list_server_callback(const char *fullpath))
     278             : {
     279          15 :         int found=0;
     280          50 :         struct bu *bu=NULL;
     281          47 :         for(bu=bu_list; bu; bu=bu->next)
     282             :         {
     283          35 :                 found=1;
     284          35 :                 if(cntr)
     285           0 :                         cntr->bno=bu->bno;
     286          35 :                 if(send_backup_name_to_client(bu)
     287          34 :                   || list_server_callback(bu->path))
     288             :                         return -1;
     289             :         }
     290             :         return found;
     291             : }
     292             : 
     293             : #ifndef UTEST
     294             : static
     295             : #endif
     296          56 : int do_list_server_work(
     297             :         int list_server_callback(const char *fullpath))
     298             : {
     299          56 :         int ret=-1;
     300          56 :         int found=0;
     301             : 
     302             :         //logp("in do_list_server\n");
     303             : 
     304          56 :         if(write_status(CNTR_STATUS_LISTING, NULL, cntr))
     305             :                 goto end;
     306             : 
     307          56 :         switch(list_mode)
     308             :         {
     309             :                 case LIST_MODE_BACKUPS:
     310          10 :                         if((found=list_all_backups())<0)
     311             :                                 goto end;
     312             :                         break;
     313             :                 case LIST_MODE_CONTENTS_ONE:
     314          31 :                         if((found=list_contents_one(list_server_callback))<0)
     315             :                                 goto end;
     316             :                         break;
     317             :                 case LIST_MODE_CONTENTS_MANY:
     318          15 :                         if((found=list_contents_many(list_server_callback))<0)
     319             :                                 goto end;
     320             :                         break;
     321             :         }
     322             : 
     323          49 :         if(!found)
     324             :         {
     325          11 :                 if(list_mode==LIST_MODE_BACKUPS)
     326             :                 {
     327           3 :                         asfd_write_wrapper_str(asfd,
     328             :                                 CMD_MESSAGE, "no backups");
     329             :                         // Success.
     330             :                 }
     331             :                 else
     332             :                 {
     333           8 :                         asfd_write_wrapper_str(asfd,
     334             :                                 CMD_MESSAGE, "backup not found");
     335           8 :                         goto end;
     336             :                 }
     337             :         }
     338             : 
     339             :         ret=0;
     340             : end:
     341          56 :         bu_list_free(&bu_list);
     342          56 :         return ret;
     343             : }
     344             : 
     345           1 : int do_list_server(void)
     346             : {
     347           1 :         return do_list_server_work(list_manifest);
     348             : }

Generated by: LCOV version 1.10