LCOV - code coverage report
Current view: top level - src/server - bu_get.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 115 117 98.3 %
Date: 2022-05-01 01:22:11 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         460 :         return readlink_w_in_dir(dir, lnk, real, r);
      14             : }
      15             : 
      16        3584 : 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        3584 :         snprintf(path, sizeof(path), "%s/%s", bu->path, file);
      22        7095 :         if(lstat(path, &statp)) return;
      23          73 :         bu->flags|=bit;
      24             : }
      25             : 
      26        1408 : static void have_backup_file_name_w(struct bu *bu,
      27             :         const char *file, uint32_t bit)
      28             : {
      29             :         char compressed[32];
      30        1408 :         snprintf(compressed, sizeof(compressed), "%s.gz", file);
      31        1408 :         have_backup_file_name(bu, file, bit);
      32        1408 :         have_backup_file_name(bu, compressed, bit);
      33        1408 : }
      34             : 
      35         641 : 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         641 :         int ret=-1;
      40         641 :         char buf[38]="";
      41             :         struct stat statp;
      42         641 :         char *fullpath=NULL;
      43         641 :         char *timestamp=NULL;
      44         641 :         char *timestampstr=NULL;
      45         641 :         char *hlinkedpath=NULL;
      46         641 :         char *basename=NULL;
      47         641 :         struct bu *bu=NULL;
      48             : 
      49         641 :         if(!(basename=prepend("", d_name))
      50         641 :          || !(fullpath=prepend_s(dir, basename))
      51         641 :          || !(timestamp=prepend_s(fullpath, "timestamp"))
      52         641 :          || !(hlinkedpath=prepend_s(fullpath, "hardlinked")))
      53             :                 goto error;
      54             : 
      55        1282 :         if((!lstat(fullpath, &statp) && !S_ISDIR(statp.st_mode))
      56        1282 :           || lstat(timestamp, &statp) || !S_ISREG(statp.st_mode)
      57         641 :           || 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         641 :           || strncmp(buf, d_name, 8))
      61             :         {
      62             :                 ret=0; // For resilience.
      63             :                 goto error;
      64             :         }
      65             : 
      66         640 :         free_w(&timestamp);
      67             : 
      68         640 :         if(!(timestampstr=strdup_w(buf, __func__)))
      69             :                 goto error;
      70             : 
      71        1280 :         if(!lstat(hlinkedpath, &statp)) flags|=BU_HARDLINKED;
      72             : 
      73         640 :         if(!(bu=bu_alloc())
      74         640 :           || bu_init(bu, fullpath, basename, timestampstr, flags))
      75             :                 goto error;
      76             : 
      77         640 :         if(*bu_list) bu->next=*bu_list;
      78         640 :         *bu_list=bu;
      79         640 :         have_backup_file_name_w(bu, "manifest", BU_MANIFEST);
      80         640 :         if(include_working)
      81             :         {
      82         256 :                 have_backup_file_name_w(bu, "log", BU_LOG_BACKUP);
      83         256 :                 have_backup_file_name_w(bu, "restorelog", BU_LOG_RESTORE);
      84         256 :                 have_backup_file_name_w(bu, "verifylog", BU_LOG_VERIFY);
      85         256 :                 if(!(bu->flags & BU_STATS_BACKUP))
      86         256 :                   have_backup_file_name(bu, "backup_stats", BU_STATS_BACKUP);
      87         256 :                 if(!(bu->flags & BU_STATS_RESTORE))
      88         256 :                   have_backup_file_name(bu, "restore_stats", BU_STATS_RESTORE);
      89         256 :                 if(!(bu->flags & BU_STATS_VERIFY))
      90         256 :                   have_backup_file_name(bu, "verify_stats", BU_STATS_VERIFY);
      91             :         }
      92             : 
      93         640 :         free_w(&hlinkedpath);
      94         640 :         return 0;
      95             : error:
      96           1 :         free_w(&basename);
      97           1 :         free_w(&fullpath);
      98           1 :         free_w(&timestamp);
      99           1 :         free_w(&timestampstr);
     100           1 :         free_w(&hlinkedpath);
     101           1 :         return ret;
     102             : }
     103             : 
     104         152 : static void setup_indices(struct bu *bu_list)
     105             : {
     106             :         int i;
     107         152 :         int tr=0;
     108         152 :         struct bu *bu=NULL;
     109         152 :         struct bu *last=NULL;
     110             : 
     111         152 :         i=1;
     112         788 :         for(bu=bu_list; bu; bu=bu->next)
     113             :         {
     114             :                 // Enumerate the position of each entry.
     115         636 :                 bu->index=i++;
     116             : 
     117             :                 // Backups that come after hardlinked backups are
     118             :                 // deletable.
     119         636 :                 if((bu->flags & BU_HARDLINKED) && bu->next)
     120         111 :                         bu->next->flags|=BU_DELETABLE;
     121             : 
     122             :                 // Also set up reverse linkage.
     123         636 :                 bu->prev=last;
     124         636 :                 last=bu;
     125             :         }
     126             : 
     127             :         // The oldest backup is deletable.
     128         152 :         if(bu_list) bu_list->flags|=BU_DELETABLE;
     129             : 
     130         152 :         if(last)
     131             :         {
     132             : 
     133         144 :                 if((tr=last->bno))
     134             :                 {
     135             :                         // Transpose bnos so that the oldest bno is set to 1.
     136         636 :                         for(bu=bu_list; bu; bu=bu->next)
     137         636 :                                 bu->trbno=tr-bu->bno+1;
     138             :                 }
     139             :         }
     140         152 : }
     141             : 
     142         153 : static int do_bu_get_list(struct sdirs *sdirs,
     143             :         struct bu **bu_list, int include_working)
     144             : {
     145         153 :         int i=0;
     146         153 :         int n=0;
     147         153 :         int ret=-1;
     148         153 :         char realwork[38]="";
     149         153 :         char realfinishing[38]="";
     150         153 :         char realcurrent[38]="";
     151         153 :         struct dirent **dp=NULL;
     152         153 :         const char *dir=NULL;
     153         153 :         uint16_t flags=0;
     154             :         struct stat statp;
     155             : 
     156         153 :         if(!sdirs)
     157             :         {
     158           1 :                 logp("%s() called with NULL sdirs\n", __func__);
     159           1 :                 goto end;
     160             :         }
     161             : 
     162         152 :         dir=sdirs->client;
     163             : 
     164         152 :         if(get_link(dir, "working", realwork, sizeof(realwork))
     165         152 :           || get_link(dir, "finishing", realfinishing, sizeof(realfinishing))
     166         152 :           || get_link(dir, "current", realcurrent, sizeof(realcurrent)))
     167             :                 goto end;
     168             : 
     169         152 :         if(!stat(dir, &statp)
     170         152 :           && (n=scandir(dir, &dp, filter_dot, alphasort))<0)
     171             :         {
     172           0 :                 logp("scandir failed in %s: %s\n", __func__, strerror(errno));
     173           0 :                 goto end;
     174             :         }
     175         152 :         i=n;
     176        1114 :         while(i--)
     177             :         {
     178             :                 // Each storage directory starts with a digit. The 'deleteme'
     179             :                 // directory does not. This check avoids loading 'deleteme'
     180             :                 // as a storage directory.
     181         810 :                 if(!isdigit(dp[i]->d_name[0]))
     182         171 :                         continue;
     183         639 :                 flags=0;
     184         639 :                 if(!strcmp(dp[i]->d_name, realcurrent))
     185             :                 {
     186             :                         flags|=BU_CURRENT;
     187             :                 }
     188         495 :                 else if(!strcmp(dp[i]->d_name, realwork))
     189             :                 {
     190           6 :                         if(!include_working) continue;
     191             :                         flags|=BU_WORKING;
     192             :                 }
     193         489 :                 else if(!strcmp(dp[i]->d_name, realfinishing))
     194             :                 {
     195           6 :                         if(!include_working) continue;
     196             :                         flags|=BU_FINISHING;
     197             :                 }
     198         637 :                 if(maybe_add_ent(dir, dp[i]->d_name, bu_list, flags,
     199             :                         include_working)) goto end;
     200             :         }
     201             : 
     202         152 :         setup_indices(*bu_list);
     203             : 
     204         152 :         ret=0;
     205             : end:
     206         153 :         if(dp)
     207             :         {
     208         810 :                 for(i=0; i<n; i++)
     209         810 :                         free(dp[i]);
     210         150 :                 free(dp);
     211             :         }
     212         153 :         return ret;
     213             : }
     214             : 
     215          73 : int bu_get_list(struct sdirs *sdirs, struct bu **bu_list)
     216             : {
     217          73 :         return do_bu_get_list(sdirs, bu_list, 0/*include_working*/);
     218             : }
     219             : 
     220          80 : int bu_get_list_with_working(struct sdirs *sdirs, struct bu **bu_list)
     221             : {
     222          80 :         return do_bu_get_list(sdirs, bu_list, 1/*include_working*/);
     223             : }
     224             : 
     225           4 : int bu_get_current(struct sdirs *sdirs, struct bu **bu_list)
     226             : {
     227           4 :         char real[38]="";
     228             :         // FIX THIS: should not need to specify "current".
     229           8 :         if(get_link(sdirs->client, "current", real, sizeof(real)))
     230             :                 return -1;
     231           4 :         return maybe_add_ent(sdirs->client, real, bu_list, BU_CURRENT,
     232             :                 0/*include_working*/);
     233             : }

Generated by: LCOV version 1.13