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

Generated by: LCOV version 1.10