LCOV - code coverage report
Current view: top level - src/server - bu_get.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 135 143 94.4 %
Date: 2015-11-30 Functions: 9 9 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             : 
      11         731 : static int get_link(const char *dir, const char *lnk, char real[], size_t r)
      12             : {
      13         731 :         ssize_t len=0;
      14         731 :         char *tmp=NULL;
      15         731 :         if(!(tmp=prepend_s(dir, lnk)))
      16           0 :                 return -1;
      17         731 :         if((len=readlink(tmp, real, r-1))<0) len=0;
      18         731 :         real[len]='\0';
      19         731 :         free_w(&tmp);
      20         731 :         return 0;
      21             : }
      22             : 
      23        5205 : static void have_backup_file_name(struct bu *bu,
      24             :         const char *file, uint32_t bit)
      25             : {
      26             :         struct stat statp;
      27             :         static char path[256]="";
      28        5205 :         snprintf(path, sizeof(path), "%s/%s", bu->path, file);
      29       10410 :         if(lstat(path, &statp)) return;
      30         120 :         bu->flags|=bit;
      31             : }
      32             : 
      33        2118 : static void have_backup_file_name_w(struct bu *bu,
      34             :         const char *file, uint32_t bit)
      35             : {
      36             :         char compressed[32];
      37        2118 :         snprintf(compressed, sizeof(compressed), "%s.gz", file);
      38        2118 :         have_backup_file_name(bu, file, bit);
      39        2118 :         have_backup_file_name(bu, compressed, bit);
      40        2118 : }
      41             : 
      42        1133 : static int maybe_add_ent(const char *dir, const char *d_name,
      43             :         struct bu **bu_list, uint16_t flags, struct cstat *include_working)
      44             : {
      45        1133 :         int ret=-1;
      46        1133 :         char buf[32]="";
      47             :         struct stat statp;
      48        1133 :         char *fullpath=NULL;
      49        1133 :         char *timestamp=NULL;
      50        1133 :         char *timestampstr=NULL;
      51        1133 :         char *hlinkedpath=NULL;
      52        1133 :         char *basename=NULL;
      53        1133 :         struct bu *bu=NULL;
      54             : 
      55        3399 :         if(!(basename=prepend("", d_name))
      56        1133 :          || !(fullpath=prepend_s(dir, basename))
      57        1133 :          || !(timestamp=prepend_s(fullpath, "timestamp"))
      58        3399 :          || !(hlinkedpath=prepend_s(fullpath, "hardlinked")))
      59           0 :                 goto error;
      60             : 
      61        3399 :         if((!lstat(fullpath, &statp) && !S_ISDIR(statp.st_mode))
      62        1133 :           || lstat(timestamp, &statp) || !S_ISREG(statp.st_mode)
      63        1133 :           || timestamp_read(timestamp, buf, sizeof(buf))
      64             :         // A bit of paranoia to protect against loading directories moved
      65             :         // aside as if they were real storage directories.
      66        2266 :           || strncmp(buf, d_name, 8))
      67             :         {
      68           2 :                 ret=0; // For resilience.
      69           2 :                 goto error;
      70             :         }
      71             : 
      72        1131 :         free_w(&timestamp);
      73             : 
      74        1131 :         if(!(timestampstr=strdup_w(buf, __func__)))
      75           0 :                 goto error;
      76             : 
      77        1131 :         if(!lstat(hlinkedpath, &statp)) flags|=BU_HARDLINKED;
      78             : 
      79        1131 :         if(!(bu=bu_alloc())
      80        1131 :           || bu_init(bu, fullpath, basename, timestampstr, flags))
      81           0 :                 goto error;
      82             : 
      83        1131 :         if(*bu_list) bu->next=*bu_list;
      84        1131 :         *bu_list=bu;
      85        1131 :         have_backup_file_name_w(bu, "manifest", BU_MANIFEST);
      86        1131 :         if(include_working)
      87             :         {
      88         329 :                 have_backup_file_name_w(bu, "log", BU_LOG_BACKUP);
      89         329 :                 have_backup_file_name_w(bu, "restorelog", BU_LOG_RESTORE);
      90         329 :                 have_backup_file_name_w(bu, "verifylog", BU_LOG_VERIFY);
      91             :                 // Hack to include option for live counters.
      92         329 :                 if(include_working->run_status==RUN_STATUS_RUNNING)
      93             :                 {
      94          24 :                         switch(include_working->cntr->cntr_status)
      95             :                         {
      96             :                                 case CNTR_STATUS_SCANNING:
      97             :                                 case CNTR_STATUS_BACKUP:
      98             :                                 case CNTR_STATUS_MERGING:
      99             :                                 case CNTR_STATUS_SHUFFLING:
     100           6 :                                         bu->flags|=BU_STATS_BACKUP;
     101           6 :                                         break;
     102             :                                 case CNTR_STATUS_VERIFYING:
     103           6 :                                         bu->flags|=BU_STATS_VERIFY;
     104           6 :                                         break;
     105             :                                 case CNTR_STATUS_RESTORING:
     106           6 :                                         bu->flags|=BU_STATS_RESTORE;
     107           6 :                                         break;
     108             :                                 default:
     109           6 :                                         break;
     110             :                         }
     111             :                 }
     112         329 :                 if(!(bu->flags & BU_STATS_BACKUP))
     113         323 :                   have_backup_file_name(bu, "backup_stats", BU_STATS_BACKUP);
     114         329 :                 if(!(bu->flags & BU_STATS_RESTORE))
     115         323 :                   have_backup_file_name(bu, "restore_stats", BU_STATS_RESTORE);
     116         329 :                 if(!(bu->flags & BU_STATS_VERIFY))
     117         323 :                   have_backup_file_name(bu, "verify_stats", BU_STATS_VERIFY);
     118             :         }
     119             : 
     120        1131 :         free_w(&hlinkedpath);
     121        1131 :         return 0;
     122             : error:
     123           2 :         free_w(&basename);
     124           2 :         free_w(&fullpath);
     125           2 :         free_w(&timestamp);
     126           2 :         free_w(&timestampstr);
     127           2 :         free_w(&hlinkedpath);
     128           2 :         return ret;
     129             : }
     130             : 
     131         241 : static void setup_indices(struct bu *bu_list)
     132             : {
     133             :         int i;
     134         241 :         int tr=0;
     135         241 :         struct bu *bu=NULL;
     136         241 :         struct bu *last=NULL;
     137             : 
     138         241 :         i=1;
     139        1364 :         for(bu=bu_list; bu; bu=bu->next)
     140             :         {
     141             :                 // Enumerate the position of each entry.
     142        1123 :                 bu->index=i++;
     143             : 
     144             :                 // Backups that come after hardlinked backups are deletable.
     145        1123 :                 if((bu->flags & BU_HARDLINKED) && bu->next)
     146         214 :                         bu->next->flags|=BU_DELETABLE;
     147             : 
     148             :                 // Also set up reverse linkage.
     149        1123 :                 bu->prev=last;
     150        1123 :                 last=bu;
     151             :         }
     152             : 
     153             :         // The oldest backup is deletable.
     154         241 :         if(bu_list) bu_list->flags|=BU_DELETABLE;
     155             : 
     156         241 :         if(last)
     157             :         {
     158             : 
     159         239 :                 if((tr=last->bno))
     160             :                 {
     161             :                         // Transpose bnos so that the oldest bno is set to 1.
     162        1362 :                         for(bu=bu_list; bu; bu=bu->next)
     163        1123 :                                 bu->trbno=tr-bu->bno+1;
     164             :                 }
     165             :         }
     166         241 : }
     167             : 
     168         244 : static int do_bu_get_list(struct sdirs *sdirs,
     169             :         struct bu **bu_list, struct cstat *include_working)
     170             : {
     171         244 :         int i=0;
     172         244 :         int n=0;
     173         244 :         int ret=-1;
     174         244 :         char realwork[32]="";
     175         244 :         char realfinishing[32]="";
     176         244 :         char realcurrent[32]="";
     177         244 :         struct dirent **dp=NULL;
     178         244 :         const char *dir=NULL;
     179         244 :         uint16_t flags=0;
     180             :         struct stat statp;
     181             : 
     182         244 :         if(!sdirs)
     183             :         {
     184           3 :                 logp("%s() called with NULL sdirs\n");
     185           3 :                 goto end;
     186             :         }
     187             : 
     188         241 :         dir=sdirs->client;
     189             : 
     190         482 :         if(get_link(dir, "working", realwork, sizeof(realwork))
     191         241 :           || get_link(dir, "finishing", realfinishing, sizeof(realfinishing))
     192         482 :           || get_link(dir, "current", realcurrent, sizeof(realcurrent)))
     193           0 :                 goto end;
     194             : 
     195         482 :         if(!stat(dir, &statp)
     196         241 :           && entries_in_directory_alphasort_rev(dir, &dp, &n, 1 /* atime */))
     197             :         {
     198           0 :                 logp("scandir failed in %s: %s\n", __func__, strerror(errno));
     199           0 :                 goto end;
     200             :         }
     201        1631 :         for(i=0; i<n; i++)
     202             :         {
     203             :                 // Each storage directory starts with a digit. The 'deleteme'
     204             :                 // directory does not. This check avoids loading 'deleteme'
     205             :                 // as a storage directory.
     206        1390 :                 if(!isdigit(dp[i]->d_name[0]))
     207         261 :                         continue;
     208        1129 :                 flags=0;
     209        1129 :                 if(!strcmp(dp[i]->d_name, realcurrent))
     210             :                 {
     211         239 :                         flags|=BU_CURRENT;
     212             :                 }
     213         890 :                 else if(!strcmp(dp[i]->d_name, realwork))
     214             :                 {
     215           9 :                         if(!include_working) continue;
     216           7 :                         flags|=BU_WORKING;
     217             :                 }
     218         881 :                 else if(!strcmp(dp[i]->d_name, realfinishing))
     219             :                 {
     220           9 :                         if(!include_working) continue;
     221           7 :                         flags|=BU_FINISHING;
     222             :                 }
     223        2250 :                 if(maybe_add_ent(dir, dp[i]->d_name, bu_list, flags,
     224        2250 :                         include_working)) goto end;
     225             :         }
     226             : 
     227         241 :         setup_indices(*bu_list);
     228             : 
     229         241 :         ret=0;
     230             : end:
     231         244 :         if(dp)
     232             :         {
     233         239 :                 for(i=0; i<n; i++) free_v((void **)&dp[i]);
     234         239 :                 free_v((void **)&dp);
     235             :         }
     236         244 :         return ret;
     237             : }
     238             : 
     239         160 : int bu_get_list(struct sdirs *sdirs, struct bu **bu_list)
     240             : {
     241         160 :         return do_bu_get_list(sdirs, bu_list, NULL);
     242             : }
     243             : 
     244          84 : int bu_get_list_with_working(struct sdirs *sdirs, struct bu **bu_list,
     245             :         struct cstat *cstat)
     246             : {
     247          84 :         return do_bu_get_list(sdirs, bu_list, cstat);
     248             : }
     249             : 
     250           8 : int bu_get_current(struct sdirs *sdirs, struct bu **bu_list)
     251             : {
     252           8 :         char real[32]="";
     253             :         // FIX THIS: should not need to specify "current".
     254           8 :         if(get_link(sdirs->client, "current", real, sizeof(real)))
     255           0 :                 return -1;
     256           8 :         return maybe_add_ent(sdirs->client, real, bu_list, BU_CURRENT, NULL);
     257             : }

Generated by: LCOV version 1.10