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

Generated by: LCOV version 1.13