LCOV - code coverage report
Current view: top level - src/server - bu_get.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 113 114 99.1 %
Date: 2017-09-30 Functions: 8 8 100.0 %

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

Generated by: LCOV version 1.10