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

Generated by: LCOV version 1.13