LCOV - code coverage report
Current view: top level - src/server - bu_get.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 129 131 98.5 %
Date: 2016-05-01 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         845 : static int get_link(const char *dir, const char *lnk, char real[], size_t r)
      12             : {
      13         845 :         ssize_t len=0;
      14         845 :         char *tmp=NULL;
      15         845 :         if(!(tmp=prepend_s(dir, lnk)))
      16             :                 return -1;
      17        1690 :         if((len=readlink(tmp, real, r-1))<0) len=0;
      18         845 :         real[len]='\0';
      19         845 :         free_w(&tmp);
      20         845 :         return 0;
      21             : }
      22             : 
      23        5327 : 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        5327 :         snprintf(path, sizeof(path), "%s/%s", bu->path, file);
      29       10529 :         if(lstat(path, &statp)) return;
      30         125 :         bu->flags|=bit;
      31             : }
      32             : 
      33        6537 : static void have_backup_file_name_w(struct bu *bu,
      34             :         const char *file, uint32_t bit)
      35             : {
      36             :         char compressed[32];
      37             :         snprintf(compressed, sizeof(compressed), "%s.gz", file);
      38        2179 :         have_backup_file_name(bu, file, bit);
      39        2179 :         have_backup_file_name(bu, compressed, bit);
      40        2179 : }
      41             : 
      42        1194 : 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        1194 :         int ret=-1;
      46        1194 :         char buf[32]="";
      47             :         struct stat statp;
      48        1194 :         char *fullpath=NULL;
      49        1194 :         char *timestamp=NULL;
      50        1194 :         char *timestampstr=NULL;
      51        1194 :         char *hlinkedpath=NULL;
      52        1194 :         char *basename=NULL;
      53        2163 :         struct bu *bu=NULL;
      54             : 
      55        2388 :         if(!(basename=prepend("", d_name))
      56        1194 :          || !(fullpath=prepend_s(dir, basename))
      57        1194 :          || !(timestamp=prepend_s(fullpath, "timestamp"))
      58        2388 :          || !(hlinkedpath=prepend_s(fullpath, "hardlinked")))
      59             :                 goto error;
      60             : 
      61        3582 :         if((!lstat(fullpath, &statp) && !S_ISDIR(statp.st_mode))
      62        2388 :           || lstat(timestamp, &statp) || !S_ISREG(statp.st_mode)
      63        1194 :           || 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        2388 :           || strncmp(buf, d_name, 8))
      67             :         {
      68             :                 ret=0; // For resilience.
      69             :                 goto error;
      70             :         }
      71             : 
      72        1192 :         free_w(&timestamp);
      73             : 
      74        1192 :         if(!(timestampstr=strdup_w(buf, __func__)))
      75             :                 goto error;
      76             : 
      77        2384 :         if(!lstat(hlinkedpath, &statp)) flags|=BU_HARDLINKED;
      78             : 
      79        1192 :         if(!(bu=bu_alloc())
      80        1192 :           || bu_init(bu, fullpath, basename, timestampstr, flags))
      81             :                 goto error;
      82             : 
      83        1192 :         if(*bu_list) bu->next=*bu_list;
      84        1192 :         *bu_list=bu;
      85        1192 :         have_backup_file_name_w(bu, "manifest", BU_MANIFEST);
      86        1192 :         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             :                                         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        1192 :         free_w(&hlinkedpath);
     121        1192 :         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         279 : static void setup_indices(struct bu *bu_list, enum protocol protocol)
     132             : {
     133             :         int i;
     134         279 :         int tr=0;
     135         279 :         struct bu *bu=NULL;
     136         279 :         struct bu *last=NULL;
     137             : 
     138         279 :         i=1;
     139        1463 :         for(bu=bu_list; bu; bu=bu->next)
     140             :         {
     141             :                 // Enumerate the position of each entry.
     142        1184 :                 bu->index=i++;
     143             : 
     144        1184 :                 if(protocol==PROTO_2)
     145             :                 {
     146             :                         // All PROTO_2 backups are deletable.
     147         545 :                         bu->flags|=BU_DELETABLE;
     148             :                 }
     149             :                 else
     150             :                 {
     151             :                         // Backups that come after hardlinked backups are
     152             :                         // deletable.
     153         639 :                         if((bu->flags & BU_HARDLINKED) && bu->next)
     154         111 :                                 bu->next->flags|=BU_DELETABLE;
     155             :                 }
     156             : 
     157             :                 // Also set up reverse linkage.
     158        1184 :                 bu->prev=last;
     159        1184 :                 last=bu;
     160             :         }
     161             : 
     162             :         // The oldest backup is deletable.
     163         279 :         if(bu_list) bu_list->flags|=BU_DELETABLE;
     164             : 
     165         279 :         if(last)
     166             :         {
     167             : 
     168         273 :                 if((tr=last->bno))
     169             :                 {
     170             :                         // Transpose bnos so that the oldest bno is set to 1.
     171        1184 :                         for(bu=bu_list; bu; bu=bu->next)
     172        1184 :                                 bu->trbno=tr-bu->bno+1;
     173             :                 }
     174             :         }
     175         279 : }
     176             : 
     177         280 : static int do_bu_get_list(struct sdirs *sdirs,
     178             :         struct bu **bu_list, struct cstat *include_working)
     179             : {
     180         280 :         int i=0;
     181         280 :         int n=0;
     182         280 :         int ret=-1;
     183         280 :         char realwork[32]="";
     184         280 :         char realfinishing[32]="";
     185         280 :         char realcurrent[32]="";
     186         280 :         struct dirent **dp=NULL;
     187         280 :         const char *dir=NULL;
     188         280 :         uint16_t flags=0;
     189             :         struct stat statp;
     190             : 
     191         280 :         if(!sdirs)
     192             :         {
     193           1 :                 logp("%s() called with NULL sdirs\n", __func__);
     194           1 :                 goto end;
     195             :         }
     196             : 
     197         279 :         dir=sdirs->client;
     198             : 
     199         558 :         if(get_link(dir, "working", realwork, sizeof(realwork))
     200         279 :           || get_link(dir, "finishing", realfinishing, sizeof(realfinishing))
     201         558 :           || get_link(dir, "current", realcurrent, sizeof(realcurrent)))
     202             :                 goto end;
     203             : 
     204         279 :         if(!stat(dir, &statp)
     205         279 :           && entries_in_directory_alphasort_rev(dir, &dp, &n, 1 /* atime */))
     206             :         {
     207           0 :                 logp("scandir failed in %s: %s\n", __func__, strerror(errno));
     208           0 :                 goto end;
     209             :         }
     210        1485 :         for(i=0; i<n; i++)
     211             :         {
     212             :                 // Each storage directory starts with a digit. The 'deleteme'
     213             :                 // directory does not. This check avoids loading 'deleteme'
     214             :                 // as a storage directory.
     215        1485 :                 if(!isdigit(dp[i]->d_name[0]))
     216             :                         continue;
     217        1190 :                 flags=0;
     218        1190 :                 if(!strcmp(dp[i]->d_name, realcurrent))
     219             :                 {
     220             :                         flags|=BU_CURRENT;
     221             :                 }
     222         917 :                 else if(!strcmp(dp[i]->d_name, realwork))
     223             :                 {
     224           9 :                         if(!include_working) continue;
     225             :                         flags|=BU_WORKING;
     226             :                 }
     227         908 :                 else if(!strcmp(dp[i]->d_name, realfinishing))
     228             :                 {
     229           9 :                         if(!include_working) continue;
     230             :                         flags|=BU_FINISHING;
     231             :                 }
     232        1186 :                 if(maybe_add_ent(dir, dp[i]->d_name, bu_list, flags,
     233        1186 :                         include_working)) goto end;
     234             :         }
     235             : 
     236         279 :         setup_indices(*bu_list, sdirs->protocol);
     237             : 
     238         279 :         ret=0;
     239             : end:
     240         280 :         if(dp)
     241             :         {
     242        1485 :                 for(i=0; i<n; i++) free_v((void **)&dp[i]);
     243         273 :                 free_v((void **)&dp);
     244             :         }
     245         280 :         return ret;
     246             : }
     247             : 
     248         196 : int bu_get_list(struct sdirs *sdirs, struct bu **bu_list)
     249             : {
     250         196 :         return do_bu_get_list(sdirs, bu_list, NULL);
     251             : }
     252             : 
     253          84 : int bu_get_list_with_working(struct sdirs *sdirs, struct bu **bu_list,
     254             :         struct cstat *cstat)
     255             : {
     256          84 :         return do_bu_get_list(sdirs, bu_list, cstat);
     257             : }
     258             : 
     259           8 : int bu_get_current(struct sdirs *sdirs, struct bu **bu_list)
     260             : {
     261           8 :         char real[32]="";
     262             :         // FIX THIS: should not need to specify "current".
     263           8 :         if(get_link(sdirs->client, "current", real, sizeof(real)))
     264             :                 return -1;
     265           8 :         return maybe_add_ent(sdirs->client, real, bu_list, BU_CURRENT, NULL);
     266             : }

Generated by: LCOV version 1.10