LCOV - code coverage report
Current view: top level - src/server - bu_get.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 117 119 98.3 %
Date: 2019-09-01 10:44:57 Functions: 8 8 100.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../alloc.h"
       3             : #include "../bu.h"
       4             : #include "../fsops.h"
       5             : #include "../log.h"
       6             : #include "../prepend.h"
       7             : #include "sdirs.h"
       8             : #include "timestamp.h"
       9             : #include "bu_get.h"
      10             : 
      11             : static int get_link(const char *dir, const char *lnk, char real[], size_t r)
      12             : {
      13         866 :         return readlink_w_in_dir(dir, lnk, real, r);
      14             : }
      15             : 
      16        6489 : static void have_backup_file_name(struct bu *bu,
      17             :         const char *file, uint32_t bit)
      18             : {
      19             :         struct stat statp;
      20             :         static char path[256]="";
      21        6489 :         snprintf(path, sizeof(path), "%s/%s", bu->path, file);
      22       12842 :         if(lstat(path, &statp)) return;
      23         136 :         bu->flags|=bit;
      24             : }
      25             : 
      26        2562 : static void have_backup_file_name_w(struct bu *bu,
      27             :         const char *file, uint32_t bit)
      28             : {
      29             :         char compressed[32];
      30        2562 :         snprintf(compressed, sizeof(compressed), "%s.gz", file);
      31        2562 :         have_backup_file_name(bu, file, bit);
      32        2562 :         have_backup_file_name(bu, compressed, bit);
      33        2562 : }
      34             : 
      35        1199 : static int maybe_add_ent(const char *dir, const char *d_name,
      36             :         struct bu **bu_list, uint16_t flags,
      37             :         int include_working)
      38             : {
      39        1199 :         int ret=-1;
      40        1199 :         char buf[38]="";
      41             :         struct stat statp;
      42        1199 :         char *fullpath=NULL;
      43        1199 :         char *timestamp=NULL;
      44        1199 :         char *timestampstr=NULL;
      45        1199 :         char *hlinkedpath=NULL;
      46        1199 :         char *basename=NULL;
      47        1199 :         struct bu *bu=NULL;
      48             : 
      49        1199 :         if(!(basename=prepend("", d_name))
      50        1199 :          || !(fullpath=prepend_s(dir, basename))
      51        1199 :          || !(timestamp=prepend_s(fullpath, "timestamp"))
      52        1199 :          || !(hlinkedpath=prepend_s(fullpath, "hardlinked")))
      53             :                 goto error;
      54             : 
      55        2398 :         if((!lstat(fullpath, &statp) && !S_ISDIR(statp.st_mode))
      56        2398 :           || lstat(timestamp, &statp) || !S_ISREG(statp.st_mode)
      57        1199 :           || timestamp_read(timestamp, buf, sizeof(buf))
      58             :         // A bit of paranoia to protect against loading directories moved
      59             :         // aside as if they were real storage directories.
      60        1199 :           || strncmp(buf, d_name, 8))
      61             :         {
      62             :                 ret=0; // For resilience.
      63             :                 goto error;
      64             :         }
      65             : 
      66        1197 :         free_w(&timestamp);
      67             : 
      68        1197 :         if(!(timestampstr=strdup_w(buf, __func__)))
      69             :                 goto error;
      70             : 
      71        2394 :         if(!lstat(hlinkedpath, &statp)) flags|=BU_HARDLINKED;
      72             : 
      73        1197 :         if(!(bu=bu_alloc())
      74        1197 :           || bu_init(bu, fullpath, basename, timestampstr, flags))
      75             :                 goto error;
      76             : 
      77        1197 :         if(*bu_list) bu->next=*bu_list;
      78        1197 :         *bu_list=bu;
      79        1197 :         have_backup_file_name_w(bu, "manifest", BU_MANIFEST);
      80        1197 :         if(include_working)
      81             :         {
      82         455 :                 have_backup_file_name_w(bu, "log", BU_LOG_BACKUP);
      83         455 :                 have_backup_file_name_w(bu, "restorelog", BU_LOG_RESTORE);
      84         455 :                 have_backup_file_name_w(bu, "verifylog", BU_LOG_VERIFY);
      85         455 :                 if(!(bu->flags & BU_STATS_BACKUP))
      86         455 :                   have_backup_file_name(bu, "backup_stats", BU_STATS_BACKUP);
      87         455 :                 if(!(bu->flags & BU_STATS_RESTORE))
      88         455 :                   have_backup_file_name(bu, "restore_stats", BU_STATS_RESTORE);
      89         455 :                 if(!(bu->flags & BU_STATS_VERIFY))
      90         455 :                   have_backup_file_name(bu, "verify_stats", BU_STATS_VERIFY);
      91             :         }
      92             : 
      93        1197 :         free_w(&hlinkedpath);
      94        1197 :         return 0;
      95             : error:
      96           2 :         free_w(&basename);
      97           2 :         free_w(&fullpath);
      98           2 :         free_w(&timestamp);
      99           2 :         free_w(&timestampstr);
     100           2 :         free_w(&hlinkedpath);
     101           2 :         return ret;
     102             : }
     103             : 
     104         286 : static void setup_indices(struct bu *bu_list, enum protocol protocol)
     105             : {
     106             :         int i;
     107         286 :         int tr=0;
     108         286 :         struct bu *bu=NULL;
     109         286 :         struct bu *last=NULL;
     110             : 
     111         286 :         i=1;
     112        1475 :         for(bu=bu_list; bu; bu=bu->next)
     113             :         {
     114             :                 // Enumerate the position of each entry.
     115        1189 :                 bu->index=i++;
     116             : 
     117        1189 :                 if(protocol==PROTO_2)
     118             :                 {
     119             :                         // All PROTO_2 backups are deletable.
     120         553 :                         bu->flags|=BU_DELETABLE;
     121             :                 }
     122             :                 else
     123             :                 {
     124             :                         // Backups that come after hardlinked backups are
     125             :                         // deletable.
     126         636 :                         if((bu->flags & BU_HARDLINKED) && bu->next)
     127         111 :                                 bu->next->flags|=BU_DELETABLE;
     128             :                 }
     129             : 
     130             :                 // Also set up reverse linkage.
     131        1189 :                 bu->prev=last;
     132        1189 :                 last=bu;
     133             :         }
     134             : 
     135             :         // The oldest backup is deletable.
     136         286 :         if(bu_list) bu_list->flags|=BU_DELETABLE;
     137             : 
     138         286 :         if(last)
     139             :         {
     140             : 
     141         276 :                 if((tr=last->bno))
     142             :                 {
     143             :                         // Transpose bnos so that the oldest bno is set to 1.
     144        1189 :                         for(bu=bu_list; bu; bu=bu->next)
     145        1189 :                                 bu->trbno=tr-bu->bno+1;
     146             :                 }
     147             :         }
     148         286 : }
     149             : 
     150         287 : static int do_bu_get_list(struct sdirs *sdirs,
     151             :         struct bu **bu_list, int include_working)
     152             : {
     153         287 :         int i=0;
     154         287 :         int n=0;
     155         287 :         int ret=-1;
     156         287 :         char realwork[38]="";
     157         287 :         char realfinishing[38]="";
     158         287 :         char realcurrent[38]="";
     159         287 :         struct dirent **dp=NULL;
     160         287 :         const char *dir=NULL;
     161         287 :         uint16_t flags=0;
     162             :         struct stat statp;
     163             : 
     164         287 :         if(!sdirs)
     165             :         {
     166           1 :                 logp("%s() called with NULL sdirs\n", __func__);
     167           1 :                 goto end;
     168             :         }
     169             : 
     170         286 :         dir=sdirs->client;
     171             : 
     172         286 :         if(get_link(dir, "working", realwork, sizeof(realwork))
     173         286 :           || get_link(dir, "finishing", realfinishing, sizeof(realfinishing))
     174         286 :           || get_link(dir, "current", realcurrent, sizeof(realcurrent)))
     175             :                 goto end;
     176             : 
     177         286 :         if(!stat(dir, &statp)
     178         286 :           && (n=scandir(dir, &dp, filter_dot, alphasort))<0)
     179             :         {
     180           0 :                 logp("scandir failed in %s: %s\n", __func__, strerror(errno));
     181           0 :                 goto end;
     182             :         }
     183         286 :         i=n;
     184        2080 :         while(i--)
     185             :         {
     186             :                 // Each storage directory starts with a digit. The 'deleteme'
     187             :                 // directory does not. This check avoids loading 'deleteme'
     188             :                 // as a storage directory.
     189        1508 :                 if(!isdigit(dp[i]->d_name[0]))
     190         313 :                         continue;
     191        1195 :                 flags=0;
     192        1195 :                 if(!strcmp(dp[i]->d_name, realcurrent))
     193             :                 {
     194             :                         flags|=BU_CURRENT;
     195             :                 }
     196         919 :                 else if(!strcmp(dp[i]->d_name, realwork))
     197             :                 {
     198           9 :                         if(!include_working) continue;
     199             :                         flags|=BU_WORKING;
     200             :                 }
     201         910 :                 else if(!strcmp(dp[i]->d_name, realfinishing))
     202             :                 {
     203           9 :                         if(!include_working) continue;
     204             :                         flags|=BU_FINISHING;
     205             :                 }
     206        1191 :                 if(maybe_add_ent(dir, dp[i]->d_name, bu_list, flags,
     207             :                         include_working)) goto end;
     208             :         }
     209             : 
     210         286 :         setup_indices(*bu_list, sdirs->protocol);
     211             : 
     212         286 :         ret=0;
     213             : end:
     214         287 :         if(dp)
     215             :         {
     216        1508 :                 for(i=0; i<n; i++)
     217        1508 :                         free(dp[i]);
     218         282 :                 free(dp);
     219             :         }
     220         287 :         return ret;
     221             : }
     222             : 
     223         148 : int bu_get_list(struct sdirs *sdirs, struct bu **bu_list)
     224             : {
     225         148 :         return do_bu_get_list(sdirs, bu_list, 0/*include_working*/);
     226             : }
     227             : 
     228         139 : int bu_get_list_with_working(struct sdirs *sdirs, struct bu **bu_list)
     229             : {
     230         139 :         return do_bu_get_list(sdirs, bu_list, 1/*include_working*/);
     231             : }
     232             : 
     233           8 : int bu_get_current(struct sdirs *sdirs, struct bu **bu_list)
     234             : {
     235           8 :         char real[38]="";
     236             :         // FIX THIS: should not need to specify "current".
     237          16 :         if(get_link(sdirs->client, "current", real, sizeof(real)))
     238             :                 return -1;
     239           8 :         return maybe_add_ent(sdirs->client, real, bu_list, BU_CURRENT,
     240             :                 0/*include_working*/);
     241             : }

Generated by: LCOV version 1.13