LCOV - code coverage report
Current view: top level - src/server - list.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 131 184 71.2 %
Date: 2015-11-30 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          48 : 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          48 :         asfd=a;
      44          48 :         cntr=c;
      45          48 :         protocol=p;
      46          48 :         backup=backup_str;
      47          48 :         browsedir=browsedir_str;
      48          48 :         if(bu_get_list(s, &bu_list))
      49           2 :                 goto error;
      50          46 :         if(regex_str
      51           9 :           && *regex_str
      52          55 :           && !(regex=regex_compile(regex_str)))
      53             :         {
      54           1 :                 char msg[256]="";
      55             :                 snprintf(msg, sizeof(msg), "unable to compile regex: %s\n",
      56           1 :                         regex_str);
      57           1 :                 log_and_send(asfd, msg);
      58           1 :                 goto error;
      59             :         }
      60          45 :         list_mode=LIST_MODE_BACKUPS;
      61          45 :         if(regex)
      62           8 :                 list_mode=LIST_MODE_CONTENTS_MANY;
      63          45 :         if(backup && *backup)
      64             :         {
      65          36 :                 if((bno=strtoul(backup, NULL, 10))>0)
      66          17 :                         list_mode=LIST_MODE_CONTENTS_ONE;
      67          19 :                 else if(*backup=='c')
      68           6 :                         list_mode=LIST_MODE_CONTENTS_ONE;
      69          13 :                 else if(*backup=='a')
      70           9 :                         list_mode=LIST_MODE_CONTENTS_MANY;
      71             :                 else
      72           4 :                         list_mode=LIST_MODE_CONTENTS_ONE;
      73             :         }
      74          45 :         return 0;
      75             : error:
      76           3 :         list_server_free();
      77           3 :         return -1;
      78             : }
      79             : 
      80          51 : void list_server_free(void)
      81             : {
      82          51 :         bu_list_free(&bu_list);
      83          51 :         regex_free(&regex);
      84          51 : }
      85             : 
      86          50 : static void maybe_fake_directory(struct sbuf *mb)
      87             : {
      88          50 :         if(S_ISDIR(mb->statp.st_mode))
      89          52 :                 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          12 :                         return 0;
     106          30 :                 cp+=bdlen;
     107          30 :                 if(browsedir[bdlen-1]!='/')
     108             :                 {
     109          24 :                         if(*cp!='\0')
     110             :                         {
     111          20 :                                 if(*cp!='/')
     112           2 :                                         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           1 :                 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           0 :                 goto error;
     150          40 :         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, __func__);
     172           0 :                 goto error;
     173             :         }
     174             : 
     175           0 :         if(browsedir) bdlen=strlen(browsedir);
     176             : 
     177             :         while(1)
     178             :         {
     179           0 :                 int show=0;
     180           0 :                 sbuf_free_content(sb);
     181             : 
     182           0 :                 switch(manio_read(manio, sb))
     183             :                 {
     184           0 :                         case 0: break;
     185           0 :                         case 1: if(browsedir && *browsedir && !last_bd_match)
     186             :                                         asfd_write_wrapper_str(asfd,
     187             :                                                 CMD_ERROR,
     188           0 :                                                 "directory not found");
     189           0 :                                 goto end; // Finished OK.
     190           0 :                         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           0 :                         goto error;
     200             : 
     201           0 :                 if(browsedir)
     202             :                 {
     203             :                         int r;
     204           0 :                         if((r=check_browsedir(browsedir,
     205           0 :                                 sb, bdlen, &last_bd_match))<0)
     206           0 :                                         goto error;
     207           0 :                         if(!r) continue;
     208           0 :                         show++;
     209             :                 }
     210             :                 else
     211             :                 {
     212           0 :                         if(!regex || regex_check(regex, sb->path.buf))
     213           0 :                                 show++;
     214             :                 }
     215           0 :                 if(show)
     216             :                 {
     217           0 :                         if(asfd_write_wrapper(asfd, &sb->attr)
     218           0 :                           || asfd_write_wrapper(asfd, &sb->path))
     219           0 :                                 goto error;
     220           0 :                         if(sbuf_is_link(sb)
     221           0 :                           && asfd_write_wrapper(asfd, &sb->link))
     222           0 :                                 goto error;
     223             :                 }
     224             :         }
     225             : 
     226             : error:
     227           0 :         ret=-1;
     228             : end:
     229           0 :         sbuf_free(&sb);
     230           0 :         free_w(&manifest_dir);
     231           0 :         manio_close(&manio);
     232           0 :         free_w(&last_bd_match);
     233           0 :         return ret;
     234             : }
     235             : 
     236          57 : static int send_backup_name_to_client(struct bu *bu)
     237             : {
     238          57 :         char msg[64]="";
     239             :         snprintf(msg, sizeof(msg), "%s%s",
     240             :                 bu->timestamp,
     241             :                 // Protocol2 backups are all deletable, so do not mention it.
     242          57 :                 protocol==PROTO_1
     243          57 :                 && (bu->flags & BU_DELETABLE)?" (deletable)":"");
     244          57 :         return asfd_write_wrapper_str(asfd, CMD_TIMESTAMP, msg);
     245             : }
     246             : 
     247           7 : static int list_all_backups(void)
     248             : {
     249           7 :         int found=0;
     250           7 :         struct bu *bu=NULL;
     251          21 :         for(bu=bu_list; bu; bu=bu->next)
     252             :         {
     253          15 :                 found=1;
     254          15 :                 if(send_backup_name_to_client(bu))
     255           1 :                         return -1;
     256             :         }
     257           6 :         return found;
     258             : }
     259             : 
     260          27 : static int list_contents_one(
     261             :         int list_server_callback(const char *fullpath))
     262             : {
     263          27 :         struct bu *bu=NULL;
     264          65 :         for(bu=bu_list; bu; bu=bu->next)
     265             :         {
     266          57 :                 if(!strcmp(bu->timestamp, backup)
     267          57 :                   || bu->bno==bno
     268          44 :                   || (*backup=='c' && (bu->flags & BU_CURRENT)))
     269             :                 {
     270          38 :                         if(send_backup_name_to_client(bu)
     271          19 :                           || list_server_callback(bu->path))
     272           3 :                                 return -1;
     273          16 :                         return 1;
     274             :                 }
     275             :         }
     276           8 :         return 0;
     277             : }
     278             : 
     279          11 : static int list_contents_many(
     280             :         int list_server_callback(const char *fullpath))
     281             : {
     282          11 :         int found=0;
     283          11 :         struct bu *bu=NULL;
     284          31 :         for(bu=bu_list; bu; bu=bu->next)
     285             :         {
     286          23 :                 found=1;
     287          46 :                 if(send_backup_name_to_client(bu)
     288          23 :                   || list_server_callback(bu->path))
     289           3 :                         return -1;
     290             :         }
     291           8 :         return found;
     292             : }
     293             : 
     294             : #ifndef UTEST
     295             : static
     296             : #endif
     297          45 : int do_list_server_work(
     298             :         int list_server_callback(const char *fullpath))
     299             : {
     300          45 :         int ret=-1;
     301          45 :         int found=0;
     302             : 
     303             :         //logp("in do_list_server\n");
     304             : 
     305          45 :         if(write_status(CNTR_STATUS_LISTING, NULL, cntr))
     306           0 :                 goto end;
     307             : 
     308          45 :         switch(list_mode)
     309             :         {
     310             :                 case LIST_MODE_BACKUPS:
     311           7 :                         if((found=list_all_backups())<0)
     312           1 :                                 goto end;
     313           6 :                         break;
     314             :                 case LIST_MODE_CONTENTS_ONE:
     315          27 :                         if((found=list_contents_one(list_server_callback))<0)
     316           3 :                                 goto end;
     317          24 :                         break;
     318             :                 case LIST_MODE_CONTENTS_MANY:
     319          11 :                         if((found=list_contents_many(list_server_callback))<0)
     320           3 :                                 goto end;
     321           8 :                         break;
     322             :         }
     323             : 
     324          38 :         if(!found)
     325             :         {
     326           8 :                 asfd_write_wrapper_str(asfd, CMD_ERROR, "backup not found");
     327           8 :                 goto end;
     328             :         }
     329             : 
     330          30 :         ret=0;
     331             : end:
     332          45 :         bu_list_free(&bu_list);
     333          45 :         return ret;
     334             : }
     335             : 
     336           0 : int do_list_server(void)
     337             : {
     338           0 :         return do_list_server_work(list_manifest);
     339             : }

Generated by: LCOV version 1.10