LCOV - code coverage report
Current view: top level - src/server/protocol2/champ_chooser - dindex.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 53 141 37.6 %
Date: 2016-03-31 Functions: 2 5 40.0 %

          Line data    Source code
       1             : #include "../../../burp.h"
       2             : #include "../../../alloc.h"
       3             : #include "../../../fsops.h"
       4             : #include "../../../hexmap.h"
       5             : #include "../../../log.h"
       6             : #include "../../../prepend.h"
       7             : #include "../../../protocol2/blk.h"
       8             : #include "../../../sbuf.h"
       9             : #include "../../../strlist.h"
      10             : #include "../../sdirs.h"
      11             : #include "../backup_phase4.h"
      12             : 
      13           0 : static int backup_in_progress(const char *fullpath)
      14             : {
      15           0 :         int ret=-1;
      16             :         struct stat statp;
      17           0 :         char *working=NULL;
      18           0 :         char *finishing=NULL;
      19             : 
      20           0 :         if(!(working=prepend_s(fullpath, "working"))
      21           0 :           || !(finishing=prepend_s(fullpath, "finishing")))
      22             :                 goto end;
      23             : 
      24           0 :         if(!lstat(working, &statp)
      25           0 :           || !lstat(finishing, &statp))
      26             :         {
      27             :                 logp("%s looks like it has a backup in progress.\n",
      28           0 :                                 fullpath);
      29           0 :                 logp("Give up clean up attempt.\n");
      30           0 :                 ret=1;
      31           0 :                 goto end;
      32             :         }
      33             :         ret=0;
      34             : end:
      35           0 :         free_w(&working);
      36           0 :         free_w(&finishing);
      37           0 :         return ret;
      38             : }
      39             : 
      40           0 : static int get_dfiles_to_merge(struct sdirs *sdirs, struct strlist **s)
      41             : {
      42           0 :         int i=0;
      43           0 :         int n=0;
      44           0 :         int ret=-1;
      45             :         struct stat statp;
      46           0 :         char *fullpath=NULL;
      47           0 :         char *dfiles=NULL;
      48           0 :         struct dirent **dir=NULL;
      49             : 
      50           0 :         logp("Attempting to clean up unused data files %s\n", sdirs->clients);
      51             : 
      52           0 :         if(entries_in_directory_no_sort(sdirs->clients, &dir, &n, 1 /*atime*/))
      53             :         {
      54             :                 logp("scandir failed for %s in %s: %s\n",
      55           0 :                         sdirs->clients, __func__, strerror(errno));
      56             :                 goto end;
      57             :         }
      58           0 :         for(i=0; i<n; i++)
      59             :         {
      60           0 :                 free_w(&fullpath);
      61           0 :                 if(!(fullpath=prepend_s(sdirs->clients, dir[i]->d_name)))
      62             :                         goto end;
      63           0 :                 switch(is_dir(fullpath, dir[i]))
      64             :                 {
      65             :                         case 0: continue;
      66             :                         case 1: break;
      67             :                         default: logp("is_dir(%s): %s\n",
      68           0 :                                         fullpath, strerror(errno));
      69             :                                 goto end;
      70             :                 }
      71             : 
      72           0 :                 if(strcmp(sdirs->client, fullpath))
      73             :                 {
      74           0 :                         switch(backup_in_progress(fullpath))
      75             :                         {
      76             :                                 case 0: break;
      77           0 :                                 case 1: ret=0;
      78             :                                 default: goto end;
      79             :                         }
      80             :                 }
      81             : 
      82           0 :                 free_w(&dfiles);
      83           0 :                 if(!(dfiles=prepend_s(fullpath, "dfiles"))
      84           0 :                   || lstat(dfiles, &statp))
      85             :                         continue;
      86             : 
      87             :                 // Have a good entry. Add it to the list.
      88           0 :                 if(strlist_add(s, dfiles, 0))
      89             :                         goto end;
      90             :         }
      91             : 
      92             :         ret=0;
      93             : end:
      94           0 :         free_w(&fullpath);
      95           0 :         free_w(&dfiles);
      96           0 :         if(dir)
      97             :         {
      98           0 :                 for(i=0; i<n; i++) free_v((void **)&dir[i]);
      99           0 :                 free_v((void **)&dir);
     100             :         }
     101           0 :         return ret;
     102             : }
     103             : 
     104           2 : static int do_unlink(struct blk *oblk, const char *datadir)
     105             : {
     106           2 :         int ret=-1;
     107           2 :         char *fullpath=NULL;
     108           2 :         char *savepath=uint64_to_savepathstr(oblk->savepath);
     109           2 :         if(!(fullpath=prepend_s(datadir, savepath)))
     110             :                 goto end;
     111           2 :         errno=0;
     112           2 :         if(unlink(fullpath) && errno!=ENOENT)
     113             :         {
     114           0 :                 logp("Could not unlink %s: %s\n", fullpath, strerror(errno));
     115             :                 goto end;
     116             :         }
     117           2 :         logp("Deleted %s\n", savepath);
     118           2 :         ret=0;
     119             : end:
     120           2 :         free_w(&fullpath);
     121           2 :         return ret;
     122             : }
     123             : 
     124             : #ifndef UTEST
     125             : static
     126             : #endif
     127           6 : int compare_dindexes_and_unlink_datafiles(const char *dindex_old,
     128             :         const char *dindex_new, const char *datadir)
     129             : {
     130           6 :         int ret=-1;
     131           6 :         struct fzp *nzp=NULL;
     132           6 :         struct fzp *ozp=NULL;
     133             :         struct iobuf nbuf;
     134             :         struct iobuf obuf;
     135             :         struct blk nblk;
     136             :         struct blk oblk;
     137             : 
     138           6 :         iobuf_init(&nbuf);
     139           6 :         iobuf_init(&obuf);
     140             :         memset(&nblk, 0, sizeof(struct blk));
     141             :         memset(&oblk, 0, sizeof(struct blk));
     142             :         
     143          12 :         if(!(nzp=fzp_gzopen(dindex_new, "rb"))
     144           6 :           || !(ozp=fzp_gzopen(dindex_old, "rb")))
     145             :                 goto end;
     146             : 
     147          22 :         while(nzp || ozp)
     148             :         {
     149          17 :                 if(nzp
     150          16 :                   && !nbuf.buf)
     151             :                 {
     152          15 :                         switch(iobuf_fill_from_fzp(&nbuf, nzp))
     153             :                         {
     154           5 :                                 case 1: fzp_close(&nzp);
     155           5 :                                         break;
     156          10 :                                 case 0: if(nbuf.cmd!=CMD_SAVE_PATH)
     157             :                                         {
     158             :                                                 logp("unknown cmd in %s: %c\n",
     159           0 :                                                         __func__, nbuf.cmd);
     160           0 :                                                 goto end;
     161             :                                         }
     162          10 :                                         if(blk_set_from_iobuf_savepath(&nblk,
     163          10 :                                                 &nbuf)) goto end;
     164             :                                         break;
     165             :                                 default: goto end; // Error;
     166             :                         }
     167             :                 }
     168             : 
     169          17 :                 if(ozp
     170          17 :                   && !obuf.buf)
     171             :                 {
     172          16 :                         switch(iobuf_fill_from_fzp(&obuf, ozp))
     173             :                         {
     174           6 :                                 case 1: fzp_close(&ozp);
     175           6 :                                         break;
     176          10 :                                 case 0: if(obuf.cmd!=CMD_SAVE_PATH)
     177             :                                         {
     178             :                                                 logp("unknown cmd in %s: %c\n",
     179           0 :                                                         __func__, obuf.cmd);
     180           0 :                                                 goto end;
     181             :                                         }
     182          10 :                                         if(blk_set_from_iobuf_savepath(&oblk,
     183          10 :                                                 &obuf)) goto end;
     184             :                                         break;
     185             :                                 default: goto end; // Error;
     186             :                         }
     187             :                 }
     188             : 
     189          17 :                 if(nbuf.buf && !obuf.buf)
     190             :                 {
     191             :                         // No more from the old file. Time to stop.
     192             :                         break;
     193             :                 }
     194          16 :                 else if(!nbuf.buf && obuf.buf)
     195             :                 {
     196             :                         // No more in the new file. Delete old entry.
     197           1 :                         if(do_unlink(&oblk, datadir))
     198             :                                 goto end;
     199           1 :                         iobuf_free_content(&obuf);
     200             :                 }
     201          15 :                 else if(!nbuf.buf && !obuf.buf)
     202             :                 {
     203             :                         continue;
     204             :                 }
     205          10 :                 else if(nblk.savepath==oblk.savepath)
     206             :                 {
     207             :                         // Same, free both and continue;
     208           8 :                         iobuf_free_content(&nbuf);
     209           8 :                         iobuf_free_content(&obuf);
     210             :                 }
     211           2 :                 else if(nblk.savepath<oblk.savepath)
     212             :                 {
     213             :                         // Only in the new file.
     214           1 :                         iobuf_free_content(&nbuf);
     215             :                 }
     216             :                 else
     217             :                 {
     218             :                         // Only in the old file.
     219           1 :                         if(do_unlink(&oblk, datadir))
     220             :                                 goto end;
     221           1 :                         iobuf_free_content(&obuf);
     222             :                 }
     223             :         }
     224             : 
     225             : 
     226             :         ret=0;
     227             : end:
     228           6 :         iobuf_free_content(&nbuf);
     229           6 :         iobuf_free_content(&obuf);
     230           6 :         fzp_close(&nzp);
     231           6 :         fzp_close(&ozp);
     232           6 :         return ret;
     233             : }
     234             : 
     235           0 : int delete_unused_data_files(struct sdirs *sdirs)
     236             : {
     237           0 :         int ret=-1;
     238           0 :         uint64_t fcount=0;
     239             :         char hfile[32];
     240           0 :         char *tmpdir=NULL;
     241           0 :         char *hlinks=NULL;
     242           0 :         char *fullpath=NULL;
     243           0 :         char *dindex_new=NULL;
     244           0 :         char *dindex_old=NULL;
     245           0 :         struct strlist *s=NULL;
     246           0 :         struct strlist *slist=NULL;
     247             :         struct stat statp;
     248             : 
     249           0 :         if(get_dfiles_to_merge(sdirs, &slist)
     250           0 :           || !(dindex_old=prepend_s(sdirs->data, "dindex"))
     251           0 :           || !(tmpdir=prepend_s(sdirs->data, "dindex.new"))
     252           0 :           || !(hlinks=prepend_s(tmpdir, "hlinks"))
     253           0 :           || recursive_delete(tmpdir)
     254           0 :           || mkdir(tmpdir, 0777)
     255           0 :           || mkdir(hlinks, 0777))
     256             :                 goto end;
     257             : 
     258           0 :         for(s=slist; s; s=s->next)
     259             :         {
     260           0 :                 snprintf(hfile, sizeof(hfile), "%08"PRIX64, fcount++);
     261           0 :                 free_w(&fullpath);
     262           0 :                 if(!(fullpath=prepend_s(hlinks, hfile)))
     263             :                         goto end;
     264           0 :                 if(link(s->path, fullpath))
     265             :                 {
     266             :                         logp("Could not hardlink %s to %s: %s\n",
     267           0 :                                 fullpath, s->path, strerror(errno));
     268           0 :                         goto end;
     269             :                 }
     270             :         }
     271             : 
     272           0 :         if(!(dindex_new=prepend_s(tmpdir, "dindex")))
     273             :                 goto end;
     274             : 
     275           0 :         if(merge_files_in_dir(dindex_new,
     276           0 :                 tmpdir, "hlinks", fcount, merge_dindexes))
     277             :                         goto end;
     278             : 
     279           0 :         if(!lstat(dindex_new, &statp))
     280             :         {
     281           0 :                 if(!lstat(dindex_old, &statp)
     282           0 :                   && compare_dindexes_and_unlink_datafiles(dindex_old,
     283           0 :                         dindex_new, sdirs->data))
     284             :                                 goto end;
     285           0 :                 if(do_rename(dindex_new, dindex_old))
     286             :                         goto end;
     287             :         }
     288             : 
     289             :         ret=0;
     290             : end:
     291           0 :         strlists_free(&slist);
     292           0 :         if(tmpdir) recursive_delete(tmpdir);
     293           0 :         free_w(&fullpath);
     294           0 :         free_w(&hlinks);
     295           0 :         free_w(&tmpdir);
     296           0 :         free_w(&dindex_new);
     297           0 :         free_w(&dindex_old);
     298           0 :         return ret;
     299             : }

Generated by: LCOV version 1.10