LCOV - code coverage report
Current view: top level - src/server - delete.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 110 115 95.7 %
Date: 2016-05-30 Functions: 7 7 100.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../alloc.h"
       3             : #include "../asfd.h"
       4             : #include "../bu.h"
       5             : #include "../cmd.h"
       6             : #include "../cntr.h"
       7             : #include "../fsops.h"
       8             : #include "../log.h"
       9             : #include "../prepend.h"
      10             : #include "../strlist.h"
      11             : #include "bu_get.h"
      12             : #include "child.h"
      13             : #include "sdirs.h"
      14             : #include "protocol2/backup_phase4.h"
      15             : 
      16          77 : static int do_rename_w(const char *a, const char *b,
      17             :         const char *cname, struct bu *bu)
      18             : {
      19          77 :         int ret=-1;
      20          77 :         char *target=NULL;
      21          77 :         char new_name[256]="";
      22          77 :         snprintf(new_name, sizeof(new_name), "%s-%s", cname, bu->basename);
      23         154 :         if(!(target=prepend_s(b, new_name))
      24          77 :           || build_path_w(target))
      25             :                 goto end;
      26          77 :         if(do_rename(a, target))
      27             :         {
      28           0 :                 logp("Error when trying to rename for delete %s\n", a);
      29             :                 goto end;
      30             :         }
      31             :         ret=0;
      32             : end:
      33          77 :         free_w(&target);
      34          77 :         return ret;
      35             : }
      36             : 
      37          77 : static int recursive_delete_w(struct sdirs *sdirs, struct bu *bu,
      38             :         const char *manual_delete)
      39             : {
      40          77 :         if(manual_delete) return 0;
      41          77 :         if(recursive_delete(sdirs->deleteme))
      42             :         {
      43           0 :                 logp("Error when trying to delete %s\n", bu->path);
      44             :                 return -1;
      45             :         }
      46             :         return 0;
      47             : }
      48             : 
      49             : // The failure conditions here are dealt with by the rubble cleaning code.
      50         154 : static int delete_backup(struct sdirs *sdirs, const char *cname, struct bu *bu,
      51             :         const char *manual_delete)
      52             : {
      53          77 :         logp("deleting %s backup %"PRId64"\n", cname, bu->bno);
      54             : 
      55          77 :         if(sdirs->global_sparse)
      56             :         {
      57          43 :                 const char *candidate_str=bu->path+strlen(sdirs->base)+1;
      58          43 :                 if(remove_from_global_sparse(
      59          43 :                         sdirs->global_sparse, candidate_str))
      60             :                                 return -1;
      61             :         }
      62             : 
      63          77 :         if(!bu->next && !bu->prev)
      64             :         {
      65             :                 // The current, and only, backup.
      66           4 :                 if(do_rename_w(bu->path, sdirs->deleteme, cname, bu))
      67             :                         return -1;
      68             :                 // If interrupted here, there will be a dangling 'current'
      69             :                 // symlink.
      70           2 :                 if(unlink(sdirs->current))
      71             :                 {
      72             :                         logp("unlink %s: %s\n",
      73           0 :                                 sdirs->current, strerror(errno));
      74           0 :                         return -1;
      75             :                 }
      76           2 :                 return recursive_delete_w(sdirs, bu, manual_delete);
      77             :         }
      78          75 :         if(!bu->next && bu->prev)
      79             :         {
      80             :                 // The current backup. There are other backups left.
      81             :                 // Need to point the symlink at the previous backup.
      82           3 :                 const char *target=NULL;
      83             :                 
      84           3 :                 target=bu->prev->basename;
      85           3 :                 unlink(sdirs->currenttmp);
      86           3 :                 if(do_symlink(target, sdirs->currenttmp))
      87             :                         return -1;
      88             :                 // If interrupted here, there is a currenttmp and a current
      89             :                 // symlink, and they both point to valid directories.
      90           6 :                 if(do_rename_w(bu->path, sdirs->deleteme, cname, bu))
      91             :                         return -1;
      92             :                 // If interrupted here, there is a currenttmp and a current
      93             :                 // symlink, and the current link is dangling.
      94           3 :                 if(do_rename(sdirs->currenttmp, sdirs->current))
      95             :                         return -1;
      96             :                 // If interrupted here, moving the symlink could have failed
      97             :                 // after current was deleted but before currenttmp was renamed.
      98           3 :                 if(recursive_delete_w(sdirs, bu, manual_delete))
      99             :                         return -1;
     100           3 :                 return 0;
     101             :         }
     102             : 
     103             :         // It is not the current backup.
     104         216 :         if(do_rename_w(bu->path, sdirs->deleteme, cname, bu)
     105          72 :           || recursive_delete_w(sdirs, bu, manual_delete))
     106             :                 return -1;
     107          72 :         return 0;
     108             : }
     109             : 
     110          64 : static int range_loop(struct sdirs *sdirs, const char *cname,
     111             :         struct strlist *keep, unsigned long rmin, struct bu *bu_list,
     112             :         struct bu *last, const char *manual_delete, int *deleted)
     113             : {
     114          64 :         struct bu *bu=NULL;
     115          64 :         unsigned long r=0;
     116          64 :         unsigned long rmax=0;
     117             : 
     118          64 :         rmax=rmin*keep->next->flag;
     119             : 
     120             :         // This is going over each range.
     121         152 :         for(r=rmax; r>rmin; r-=rmin)
     122             :         {
     123          88 :                 int count=0;
     124          88 :                 unsigned long s=r-rmin;
     125             : 
     126             :                 // Count the backups in the range.
     127         855 :                 for(bu=bu_list; bu; bu=bu->next)
     128         767 :                   if(s<bu->trbno && bu->trbno<=r)
     129         165 :                         count++;
     130             : 
     131             :                 // Want to leave one entry in each range.
     132          88 :                 if(count<=1) continue;
     133             : 
     134             :                 // Try to delete from the most recent in each
     135             :                 // so that hardlinked backups get taken out
     136             :                 // last.
     137             : 
     138         358 :                 for(bu=last; bu; bu=bu->prev)
     139             :                 {
     140         378 :                         if(s<bu->trbno
     141         172 :                           && bu->trbno<r
     142          80 :                           && (bu->flags & BU_DELETABLE))
     143             :                         {
     144          45 :                                 if(delete_backup(sdirs, cname, bu,
     145          45 :                                         manual_delete)) return -1;
     146          45 :                                 (*deleted)++;
     147          45 :                                 if(--count<=1) break;
     148             :                         }
     149             :                 }
     150             :         }
     151             : 
     152             :         return 0;
     153             : }
     154             : 
     155          57 : static int do_delete_backups(struct sdirs *sdirs, const char *cname,
     156             :         struct strlist *keep, struct bu *bu_list, const char *manual_delete)
     157             : {
     158          57 :         int ret=-1;
     159          57 :         int deleted=0;
     160          57 :         unsigned long m=1;
     161          57 :         struct bu *bu=NULL;
     162          57 :         struct bu *last=NULL;
     163          57 :         struct strlist *k=NULL;
     164             : 
     165             :         // Find the last entry in the list.
     166          57 :         for(bu=bu_list; bu; bu=bu->next) last=bu;
     167             : 
     168             :         // For each of the 'keep' values, generate ranges in which to keep
     169             :         // one backup.
     170         121 :         for(k=keep; k; k=k->next)
     171             :         {
     172         121 :                 unsigned long rmin=0;
     173         121 :                 rmin=m * k->flag;
     174             : 
     175         185 :                 if(k->next && range_loop(sdirs, cname,
     176          64 :                         k, rmin, bu_list, last, manual_delete, &deleted))
     177             :                                 goto end;
     178         121 :                 m=rmin;
     179             :         }
     180             : 
     181             :         // Remove the very oldest backups.
     182         202 :         for(bu=bu_list; bu; bu=bu->next) if(bu->trbno>m) break;
     183             : 
     184          26 :         for(; bu; bu=bu->prev)
     185             :         {
     186          26 :                 if(delete_backup(sdirs, cname, bu, manual_delete))
     187             :                         goto end;
     188          26 :                 deleted++;
     189             :         }
     190             : 
     191          57 :         ret=deleted;
     192             : end:
     193          57 :         return ret;
     194             : }
     195             : 
     196          24 : int delete_backups(struct sdirs *sdirs,
     197             :         const char *cname, struct strlist *keep, const char *manual_delete)
     198             : {
     199          24 :         int ret=-1;
     200          24 :         struct bu *bu_list=NULL;
     201             :         // Deleting a backup might mean that more become available to delete.
     202             :         // Keep trying to delete until we cannot delete any more.
     203             :         while(1)
     204             :         {
     205          57 :                 if(bu_get_list(sdirs, &bu_list)) goto end;
     206          57 :                 switch(do_delete_backups(sdirs, cname, keep, bu_list,
     207          57 :                         manual_delete))
     208             :                 {
     209             :                         case 0: ret=0; goto end;
     210           0 :                         case -1: ret=-1; goto end;
     211             :                         default: break;
     212             :                 }
     213          33 :                 bu_list_free(&bu_list);
     214             :         }
     215             : end:
     216          24 :         bu_list_free(&bu_list);
     217          57 :         return ret;
     218             : }
     219             : 
     220          12 : int do_delete_server(struct asfd *asfd,
     221             :         struct sdirs *sdirs, struct cntr *cntr,
     222             :         const char *cname, const char *backup, const char *manual_delete)
     223             : {
     224          12 :         int ret=-1;
     225          12 :         int found=0;
     226          12 :         unsigned long bno=0;
     227          12 :         struct bu *bu=NULL;
     228          12 :         struct bu *bu_list=NULL;
     229             : 
     230          12 :         logp("in do_delete\n");
     231             : 
     232          24 :         if(bu_get_list(sdirs, &bu_list)
     233          12 :           || write_status(CNTR_STATUS_DELETING, NULL, cntr))
     234             :                 goto end;
     235             : 
     236          12 :         if(backup && *backup) bno=strtoul(backup, NULL, 10);
     237             : 
     238          36 :         for(bu=bu_list; bu; bu=bu->next)
     239             :         {
     240          32 :                 if(!backup || !*backup) continue;
     241             :                 if(!found
     242          32 :                   && (!strcmp(bu->timestamp, backup)
     243          32 :                         || bu->bno==bno))
     244             :                 {
     245           8 :                         if(bu->flags & BU_DELETABLE)
     246             :                         {
     247           6 :                                 found=1;
     248          12 :                                 if(asfd->write_str(asfd, CMD_GEN, "ok")
     249          12 :                                   || delete_backup(sdirs, cname, bu,
     250           6 :                                         manual_delete))
     251             :                                                 goto end;
     252             :                         }
     253             :                         else
     254             :                         {
     255             :                                 asfd->write_str(asfd, CMD_ERROR,
     256           2 :                                         "backup not deletable");
     257           2 :                                 goto end;
     258             :                         }
     259             :                         break;
     260             :                 }
     261             :         }
     262             : 
     263          10 :         if(backup && *backup && !found)
     264             :         {
     265           4 :                 asfd->write_str(asfd, CMD_ERROR, "backup not found");
     266           4 :                 goto end;
     267             :         }
     268             : 
     269             :         ret=0;
     270             : end:
     271          12 :         bu_list_free(&bu_list);
     272          12 :         return ret;
     273             : }

Generated by: LCOV version 1.10