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

Generated by: LCOV version 1.10