LCOV - code coverage report
Current view: top level - src/server/protocol2 - bsparse.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 142 172 82.6 %
Date: 2018-12-11 11:12:16 Functions: 13 14 92.9 %

          Line data    Source code
       1             : #include "../../burp.h"
       2             : #include "../../attribs.h"
       3             : #include "../../base64.h"
       4             : #include "../../conffile.h"
       5             : #include "../../cstat.h"
       6             : #include "../../fsops.h"
       7             : #include "../../fzp.h"
       8             : #include "../../handy.h"
       9             : #include "../../hexmap.h"
      10             : #include "../../iobuf.h"
      11             : #include "../../lock.h"
      12             : #include "../../log.h"
      13             : #include "../../strlist.h"
      14             : #include "../../protocol2/blk.h"
      15             : #include "../bu_get.h"
      16             : #include "../protocol2/backup_phase4.h"
      17             : #include "../sdirs.h"
      18             : #include "bsigs.h"
      19             : #include "champ_chooser/champ_chooser.h"
      20             : 
      21             : static struct cstat *clist=NULL;
      22             : static struct lock *sparse_lock=NULL;
      23             : 
      24           3 : static int usage(void)
      25             : {
      26           3 :         logfmt("\nUsage: %s [options] <path to dedup_group>\n", prog);
      27           3 :         logfmt("\n");
      28           3 :         logfmt(" Options:\n");
      29           3 :         logfmt("  -c <path>  Path to config file (default: %s).\n",
      30             :                 config_default_path());
      31           3 :         logfmt("\n");
      32           3 :         return 1;
      33             : }
      34             : 
      35           1 : static void release_locks(void)
      36             : {
      37             :         struct cstat *c;
      38             :         struct sdirs *s;
      39           4 :         for(c=clist; c; c=c->next)
      40             :         {
      41           3 :                 s=(struct sdirs *)c->sdirs;
      42           3 :                 if(!s) continue;
      43           3 :                 lock_release(s->lock_storage_for_write);
      44           3 :                 logp("released: %s\n", c->name);
      45             :         }
      46           1 :         lock_release(sparse_lock);
      47           1 :         lock_free(&sparse_lock);
      48           1 :         logp("released: sparse index\n");
      49           1 : }
      50             : 
      51           0 : static void sighandler(__attribute__ ((unused)) int signum)
      52             : {
      53           0 :         release_locks();
      54           0 :         exit(1);
      55             : }
      56             : 
      57           1 : static struct sdirs *get_sdirs(struct conf **globalcs)
      58             : {
      59           1 :         struct sdirs *sdirs=NULL;
      60           1 :         if(!(sdirs=sdirs_alloc())
      61           1 :           || sdirs_init_from_confs(sdirs, globalcs))
      62           0 :                 sdirs_free(&sdirs);
      63           1 :         return sdirs;
      64             : }
      65             : 
      66           1 : static int parse_directory(const char *arg,
      67             :         char **directory, char **dedup_group)
      68             : {
      69             :         char *cp;
      70           1 :         if(!(*directory=strdup_w(arg, __func__)))
      71             :                 goto error;
      72           1 :         strip_trailing_slashes(directory);
      73           1 :         if(!(cp=strrchr(*directory, '/')))
      74             :         {
      75           0 :                 logp("Could not parse directory '%s'\n", *directory);
      76           0 :                 goto error;
      77             :         }
      78           1 :         *cp='\0';
      79           1 :         if(!(*dedup_group=strdup_w(cp+1, __func__)))
      80             :                 goto error;
      81           1 :         if(!*directory || !*dedup_group)
      82             :                 goto error;
      83             :         return 0;
      84             : error:
      85           0 :         free_w(directory);
      86           0 :         free_w(dedup_group);
      87           0 :         return -1;
      88             : }
      89             : 
      90           1 : static struct conf **load_conf(const char *configfile,
      91             :         const char *directory, const char *dedup_group)
      92             : {
      93           1 :         struct conf **globalcs=NULL;
      94           1 :         if(!(globalcs=confs_alloc())
      95           1 :           || confs_init(globalcs)
      96           1 :           || conf_load_global_only(configfile, globalcs)
      97           1 :           || set_string(globalcs[OPT_CNAME], "fake")
      98           1 :           || set_string(globalcs[OPT_DIRECTORY], directory)
      99           1 :           || set_string(globalcs[OPT_DEDUP_GROUP], dedup_group)
     100           1 :           || set_protocol(globalcs, PROTO_2))
     101           0 :                 confs_free(&globalcs);
     102           1 :         return globalcs;
     103             : }
     104             : 
     105           1 : static void setup_sighandler(void)
     106             : {
     107           1 :         signal(SIGABRT, &sighandler);
     108           1 :         signal(SIGTERM, &sighandler);
     109           1 :         signal(SIGINT, &sighandler);
     110           1 : }
     111             : 
     112           1 : static int get_sparse_lock(const char *sparse)
     113             : {
     114           1 :         if(!(sparse_lock=try_to_get_sparse_lock(sparse)))
     115             :         {
     116           0 :                 logp("Could not get sparse lock\n");
     117           0 :                 return -1;
     118             :         }
     119             :         return 0;
     120             : }
     121             : 
     122           1 : static int get_client_locks(void)
     123             : {
     124             :         struct cstat *c;
     125             :         struct sdirs *s;
     126           8 :         for(c=clist; c; c=c->next)
     127             :         {
     128           3 :                 s=(struct sdirs *)c->sdirs;
     129           3 :                 if(mkpath(&s->lock_storage_for_write->path, s->lockdir))
     130             :                 {
     131           0 :                         logp("problem with lock directory: %s\n", s->lockdir);
     132           0 :                         return -1;
     133             :                 }
     134             : 
     135           3 :                 lock_get(s->lock_storage_for_write);
     136           3 :                 switch(s->lock_storage_for_write->status)
     137             :                 {
     138             :                         case GET_LOCK_GOT:
     139           3 :                                 logp("locked: %s\n", c->name);
     140             :                                 break;
     141             :                         case GET_LOCK_NOT_GOT:
     142           0 :                                 logp("Unable to get lock for client %s\n",
     143             :                                         c->name);
     144           0 :                                 return -1;
     145             :                         case GET_LOCK_ERROR:
     146             :                         default:
     147           0 :                                 logp("Problem with lock file: %s\n",
     148             :                                         s->lock_storage_for_write->path);
     149           0 :                                 return -1;
     150             :                 }
     151             :         }
     152             :         return 0;
     153             : }
     154             : 
     155           1 : static struct cstat *get_client_list(const char *cdir, struct conf **globalcs)
     156             : {
     157           1 :         int i=0;
     158           1 :         int count=0;
     159           1 :         char *fullpath=NULL;
     160           1 :         char **clients=NULL;
     161           1 :         struct cstat *cnew=NULL;
     162           1 :         const char *clientconfdir=get_string(globalcs[OPT_CLIENTCONFDIR]);
     163           1 :         if(entries_in_directory_alphasort(cdir, &clients, &count, 1/*atime*/, 1/*follow_symlinks*/))
     164             :                 goto error;
     165           4 :         for(i=0; i<count; i++)
     166             :         {
     167           4 :                 free_w(&fullpath);
     168           4 :                 if(!(fullpath=prepend_s(cdir, clients[i])))
     169             :                         goto end;
     170           4 :                 switch(is_dir_lstat(fullpath))
     171             :                 {
     172           1 :                         case 0: continue;
     173             :                         case 1: break;
     174           0 :                         default: logp("is_dir(%s): %s\n",
     175           0 :                                  fullpath, strerror(errno));
     176           0 :                                         goto error;
     177             :                 }
     178             : 
     179           3 :                 if(set_string(globalcs[OPT_CNAME], clients[i]))
     180             :                         goto error;
     181             : 
     182             :                 // Have a good entry. Add it to the list.
     183           3 :                 if(!(cnew=cstat_alloc())
     184           3 :                   || !(cnew->sdirs=sdirs_alloc())
     185           3 :                   || (sdirs_init_from_confs((struct sdirs *)cnew->sdirs,
     186             :                         globalcs))
     187           3 :                   || cstat_init(cnew, clients[i], clientconfdir))
     188             :                         goto error;
     189           3 :                 cstat_add_to_list(&clist, cnew);
     190           3 :                 cnew=NULL;
     191             :         }
     192             :         goto end;
     193             : error:
     194           0 :         cstat_list_free(&clist);
     195             : end:
     196           4 :         for(i=0; i<count; i++)
     197           4 :                 free_w(&(clients[i]));
     198           1 :         free_v((void **)&clients);
     199           1 :         free_w(&fullpath);
     200           1 :         if(cnew)
     201             :         {
     202           0 :                 sdirs_free((struct sdirs **)&cnew->sdirs);
     203           0 :                 cstat_free(&cnew);
     204             :         }
     205           1 :         return clist;
     206             : }
     207             : 
     208           1 : static void clist_free(void)
     209             : {
     210             :         struct cstat *c;
     211           1 :         if(!clist)
     212             :                 return;
     213           3 :         for(c=clist; c; c=c->next)
     214           3 :                 sdirs_free((struct sdirs **)&c->sdirs);
     215           1 :         cstat_list_free(&clist);
     216             : }
     217             : 
     218           3 : static int merge_in_client_sparse_indexes(struct cstat *c,
     219             :         const char *global_sparse)
     220             : {
     221           3 :         int ret=-1;
     222           3 :         char *sparse=NULL;
     223           3 :         struct bu *b=NULL;
     224           3 :         struct bu *bu_list=NULL;
     225           3 :         struct sdirs *s=(struct sdirs *)c->sdirs;
     226             : 
     227           3 :         if(bu_get_list(s, &bu_list))
     228             :                 goto end;
     229          12 :         for(b=bu_list; b; b=b->next)
     230             :         {
     231           9 :                 free_w(&sparse);
     232           9 :                 if(!(sparse=prepend_s(b->path, "manifest/sparse")))
     233             :                         goto end;
     234           9 :                 logp("merge: %s\n", sparse);
     235           9 :                 if(merge_into_global_sparse(sparse,
     236             :                         global_sparse, sparse_lock))
     237             :                                 goto end;
     238             :         }
     239             :         ret=0;
     240             : end:
     241           3 :         bu_list_free(&bu_list);
     242           3 :         free_w(&sparse);
     243           3 :         return ret;
     244             : }
     245             : 
     246           1 : static int merge_in_all_sparse_indexes(const char *global_sparse)
     247             : {
     248             :         struct cstat *c;
     249             : 
     250           1 :         if(!is_reg_lstat(global_sparse)
     251           0 :           && unlink(global_sparse))
     252             :         {
     253           0 :                 logp("Could not delete %s: %s\n",
     254           0 :                         global_sparse, strerror(errno));
     255           0 :                 return -1;
     256             :         }
     257             : 
     258           4 :         for(c=clist; c; c=c->next)
     259           3 :                 if(merge_in_client_sparse_indexes(c, global_sparse))
     260             :                         return -1;
     261             :         return 0;
     262             : }
     263             : 
     264           5 : int run_bsparse(int argc, char *argv[])
     265             : {
     266           5 :         int ret=1;
     267             :         int option;
     268           5 :         char *directory=NULL;
     269           5 :         char *dedup_group=NULL;
     270           5 :         const char *configfile=NULL;
     271           5 :         struct sdirs *sdirs=NULL;
     272           5 :         struct conf **globalcs=NULL;
     273             : 
     274           5 :         base64_init();
     275           5 :         configfile=config_default_path();
     276             : 
     277          11 :         while((option=getopt(argc, argv, "c:Vh?"))!=-1)
     278             :         {
     279           4 :                 switch(option)
     280             :                 {
     281             :                         case 'c':
     282           1 :                                 configfile=optarg;
     283           1 :                                 break;
     284             :                         case 'V':
     285           1 :                                 logfmt("%s-%s\n", prog, PACKAGE_VERSION);
     286           1 :                                 return 0;
     287             :                         case 'h':
     288             :                         case '?':
     289           2 :                                 return usage();
     290             :                 }
     291             :         }
     292             : 
     293           2 :         if(optind>=argc || optind<argc-1)
     294           1 :                 return usage();
     295             : 
     296           1 :         if(parse_directory(argv[optind], &directory, &dedup_group))
     297             :                 goto end;
     298             : 
     299           1 :         logp("config file: %s\n", configfile);
     300           1 :         logp("directory: %s\n", directory);
     301           1 :         logp("dedup_group: %s\n", dedup_group);
     302             : 
     303           1 :         if(!(globalcs=load_conf(configfile, directory, dedup_group))
     304           1 :           || !(sdirs=get_sdirs(globalcs)))
     305             :                 goto end;
     306             : 
     307           1 :         logp("clients: %s\n", sdirs->clients);
     308           1 :         logp("sparse file: %s\n", sdirs->global_sparse);
     309             : 
     310           1 :         setup_sighandler();
     311             : 
     312           1 :         if(get_sparse_lock(sdirs->global_sparse))
     313             :                 goto end;
     314             : 
     315           1 :         if(!get_client_list(sdirs->clients, globalcs))
     316             :         {
     317           0 :                 logp("Did not find any client directories\n");
     318           0 :                 goto end;
     319             :         }
     320             : 
     321           1 :         if(get_client_locks())
     322             :                 goto end;
     323             : 
     324           1 :         if(merge_in_all_sparse_indexes(sdirs->global_sparse))
     325             :                 goto end;
     326             : 
     327           1 :         ret=0;
     328             : end:
     329           1 :         release_locks();
     330           1 :         sdirs_free(&sdirs);
     331           1 :         free_w(&directory);
     332           1 :         free_w(&dedup_group);
     333           1 :         confs_free(&globalcs);
     334           1 :         clist_free();
     335           1 :         return ret;
     336             : }

Generated by: LCOV version 1.13