LCOV - code coverage report
Current view: top level - src/server - list.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 111 150 74.0 %
Date: 2017-01-01 Functions: 9 11 81.8 %

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

Generated by: LCOV version 1.10