LCOV - code coverage report
Current view: top level - src/server - sdirs.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 129 144 89.6 %
Date: 2017-01-01 Functions: 12 12 100.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "sdirs.h"
       3             : #include "../alloc.h"
       4             : #include "../conf.h"
       5             : #include "../fsops.h"
       6             : #include "../lock.h"
       7             : #include "../log.h"
       8             : #include "../prepend.h"
       9             : #include "timestamp.h"
      10             : 
      11         312 : struct sdirs *sdirs_alloc(void)
      12             : {
      13         312 :         return (struct sdirs *)calloc_w(1, sizeof(struct sdirs), __func__);
      14             : }
      15             : 
      16         313 : static int do_lock_dirs(struct sdirs *sdirs,
      17             :         const char *cname, const char *conf_lockdir)
      18             : {
      19         313 :         int ret=-1;
      20         313 :         char *lockbase=NULL;
      21         313 :         char *lockfile=NULL;
      22         313 :         if(conf_lockdir)
      23             :         {
      24           1 :                 if(!(sdirs->lockdir=strdup_w(conf_lockdir, __func__))
      25           1 :                   || !(lockbase=prepend_s(sdirs->lockdir, cname)))
      26             :                         goto end;
      27             :         }
      28             :         else
      29             :         {
      30         312 :                 if(!(sdirs->lockdir=strdup_w(sdirs->client, __func__))
      31         312 :                   || !(lockbase=strdup_w(sdirs->client, __func__)))
      32             :                         goto end;
      33             :         }
      34         313 :         if(!(lockfile=prepend_s(lockbase, "lockfile"))
      35         313 :           || !(sdirs->lock=lock_alloc_and_init(lockfile)))
      36             :                 goto end;
      37         313 :         ret=0;
      38             : end:
      39         313 :         free_w(&lockbase);
      40         313 :         free_w(&lockfile);
      41         313 :         return ret;
      42             : }
      43             : 
      44             : static int free_prepend_s(char **dst, const char *a, const char *b)
      45             : {
      46          23 :         free_w(dst);
      47          23 :         return !(*dst=prepend_s(a, b));
      48             : }
      49             : 
      50           5 : int sdirs_get_real_manifest(struct sdirs *sdirs, enum protocol protocol)
      51             : {
      52          15 :         return free_prepend_s(&sdirs->rmanifest,
      53           5 :                 sdirs->rworking, protocol==PROTO_1?"manifest.gz":"manifest");
      54             : }
      55             : 
      56           7 : int sdirs_get_real_working_from_symlink(struct sdirs *sdirs)
      57             : {
      58           7 :         char real[256]="";
      59           7 :         if(readlink_w(sdirs->working, real, sizeof(real))<0)
      60             :         {
      61           0 :                 logp("Could not readlink %s: %s\n",
      62           0 :                         sdirs->working, strerror(errno));
      63           0 :                 return -1;
      64             :         }
      65          14 :         if(free_prepend_s(&sdirs->rworking, sdirs->client, real)
      66          14 :           || free_prepend_s(&sdirs->treepath,
      67             :                 sdirs->rworking, DATA_DIR "/" TREE_DIR))
      68             :                         return -1;
      69             :         return 0;
      70             : }
      71             : 
      72           2 : int sdirs_create_real_working(struct sdirs *sdirs, const char *timestamp_format)
      73             : {
      74           2 :         char tstmp[64]="";
      75           2 :         char fname[64]="";
      76             : 
      77           2 :         if(build_path_w(sdirs->working)
      78           2 :           || timestamp_get_new(sdirs,
      79             :                 tstmp, sizeof(tstmp), fname, sizeof(fname), timestamp_format)
      80           4 :           || free_prepend_s(&sdirs->rworking, sdirs->client, fname)
      81           4 :           || free_prepend_s(&sdirs->treepath,
      82             :                 sdirs->rworking, DATA_DIR "/" TREE_DIR))
      83             :                         return -1;
      84             : 
      85             :         // Add the working symlink before creating the directory.
      86             :         // This is because bedup checks the working symlink before
      87             :         // going into a directory. If the directory got created first,
      88             :         // bedup might go into it in the moment before the symlink
      89             :         // gets added.
      90           2 :         if(do_symlink(fname, sdirs->working))
      91             :                 // relative link to the real work dir
      92             :         {
      93           0 :                 logp("could not point working symlink to: %s\n",
      94             :                         sdirs->rworking);
      95           0 :                 return -1;
      96             :         }
      97           2 :         if(mkdir(sdirs->rworking, 0777))
      98             :         {
      99           0 :                 logp("could not mkdir for next backup: %s\n", sdirs->rworking);
     100           0 :                 unlink(sdirs->working);
     101           0 :                 return -1;
     102             :         }
     103           2 :         if(timestamp_write(sdirs->timestamp, tstmp))
     104             :         {
     105           0 :                 logp("unable to write timestamp %s to %s\n",
     106             :                         tstmp, sdirs->timestamp);
     107           0 :                 return -1;
     108             :         }
     109             : 
     110             :         return 0;
     111             : }
     112             : 
     113         313 : static int do_common_dirs(struct sdirs *sdirs, const char *manual_delete)
     114             : {
     115         313 :         if(!(sdirs->working=prepend_s(sdirs->client, "working"))
     116         313 :           || !(sdirs->finishing=prepend_s(sdirs->client, "finishing"))
     117         313 :           || !(sdirs->current=prepend_s(sdirs->client, "current"))
     118         313 :           || !(sdirs->currenttmp=prepend_s(sdirs->client, "current.tmp"))
     119         313 :           || !(sdirs->timestamp=prepend_s(sdirs->working, "timestamp"))
     120         313 :           || !(sdirs->phase1data=prepend_s(sdirs->working, "phase1.gz"))
     121         313 :           || !(sdirs->changed=prepend_s(sdirs->working, "changed"))
     122         313 :           || !(sdirs->unchanged=prepend_s(sdirs->working, "unchanged")))
     123             :                 return -1;
     124         313 :         if(manual_delete)
     125             :         {
     126           0 :                 if(!(sdirs->deleteme=strdup_w(manual_delete, __func__)))
     127             :                         return -1;
     128             :         }
     129             :         else
     130             :         {
     131         313 :                 if(!(sdirs->deleteme=prepend_s(sdirs->client, "deleteme")))
     132             :                         return -1;
     133             :         }
     134             :         return 0;
     135             : }
     136             : 
     137             : // Maybe should be in a protocol1 directory.
     138         131 : static int do_protocol1_dirs(struct sdirs *sdirs, const char *cname,
     139             :         const char *manual_delete)
     140             : {
     141         131 :         if(!(sdirs->clients=strdup_w(sdirs->base, __func__))
     142         131 :           || !(sdirs->client=prepend_s(sdirs->clients, cname))
     143         131 :           || do_common_dirs(sdirs, manual_delete)
     144         131 :           || !(sdirs->currentdata=prepend_s(sdirs->current, DATA_DIR))
     145         131 :           || !(sdirs->manifest=prepend_s(sdirs->working, "manifest.gz"))
     146         131 :           || !(sdirs->datadirtmp=prepend_s(sdirs->working, "data.tmp"))
     147         131 :           || !(sdirs->cmanifest=prepend_s(sdirs->current, "manifest.gz"))
     148         131 :           || !(sdirs->cincexc=prepend_s(sdirs->current, "incexc"))
     149         131 :           || !(sdirs->deltmppath=prepend_s(sdirs->working, "deltmppath")))
     150             :                 return -1;
     151             :         // sdirs->rworking gets set later.
     152             :         // sdirs->treepath gets set later.
     153             :         return 0;
     154             : }
     155             : 
     156         182 : static int do_protocol2_dirs(struct sdirs *sdirs,
     157             :         const char *cname, const char *dedup_group, const char *manual_delete)
     158             : {
     159         182 :         if(!dedup_group)
     160             :         {
     161           0 :                 logp("dedup_group unset in %s\n", __func__);
     162           0 :                 return -1;
     163             :         }
     164         182 :         if(!(sdirs->dedup=prepend_s(sdirs->base, dedup_group))
     165         182 :           || !(sdirs->clients=prepend_s(sdirs->dedup, "clients"))
     166         182 :           || !(sdirs->client=prepend_s(sdirs->clients, cname))
     167         182 :           || !(sdirs->dindex=prepend_s(sdirs->client, "dindex"))
     168         182 :           || !(sdirs->dfiles=prepend_s(sdirs->client, "dfiles"))
     169         182 :           || do_common_dirs(sdirs, manual_delete)
     170         182 :           || !(sdirs->data=prepend_s(sdirs->dedup, DATA_DIR))
     171         182 :           || !(sdirs->cfiles=prepend_s(sdirs->data, "cfiles"))
     172         182 :           || !(sdirs->global_sparse=prepend_s(sdirs->data, "sparse"))
     173         182 :           || !(sdirs->champlock=prepend_s(sdirs->data, "cc.lock"))
     174         182 :           || !(sdirs->champsock=prepend_s(sdirs->data, "cc.sock"))
     175         182 :           || !(sdirs->champlog=prepend_s(sdirs->data, "cc.log"))
     176         182 :           || !(sdirs->champ_dindex_lock=prepend_s(sdirs->data, "dindex.lock"))
     177         182 :           || !(sdirs->manifest=prepend_s(sdirs->working, "manifest"))
     178         182 :           || !(sdirs->cmanifest=prepend_s(sdirs->current, "manifest")))
     179             :                 return -1;
     180             :         // sdirs->rworking gets set later.
     181             :         // sdirs->rmanifest gets set later.
     182             :         return 0;
     183             : }
     184             : 
     185          16 : int sdirs_init_from_confs(struct sdirs *sdirs, struct conf **confs)
     186             : {
     187          16 :         return sdirs_init(
     188             :                 sdirs,
     189             :                 get_protocol(confs),
     190          16 :                 get_string(confs[OPT_DIRECTORY]),
     191          16 :                 get_string(confs[OPT_CNAME]),
     192          16 :                 get_string(confs[OPT_CLIENT_LOCKDIR]),
     193          16 :                 get_string(confs[OPT_DEDUP_GROUP]),
     194          16 :                 get_string(confs[OPT_MANUAL_DELETE])
     195             :         );
     196             : }
     197             : 
     198         313 : int sdirs_init(struct sdirs *sdirs, enum protocol protocol,
     199             :         const char *directory, const char *cname, const char *conf_lockdir,
     200             :         const char *dedup_group, const char *manual_delete)
     201             : {
     202         313 :         if(!directory)
     203             :         {
     204           0 :                 logp("directory unset in %s\n", __func__);
     205           0 :                 goto error;
     206             :         }
     207             : 
     208         313 :         if(!(sdirs->base=strdup_w(directory, __func__)))
     209             :                 goto error;
     210             : 
     211         313 :         sdirs->protocol=protocol;
     212             : 
     213         313 :         if(protocol==PROTO_1)
     214             :         {
     215         131 :                 if(do_protocol1_dirs(sdirs, cname, manual_delete))
     216             :                         goto error;
     217             :         }
     218             :         else
     219             :         {
     220         182 :                 if(do_protocol2_dirs(sdirs, cname, dedup_group, manual_delete))
     221             :                         goto error;
     222             :         }
     223             : 
     224         313 :         if(do_lock_dirs(sdirs, cname, conf_lockdir)) goto error;
     225             : 
     226             :         return 0;
     227             : error:
     228             :         return -1;
     229             : }
     230             : 
     231         313 : void sdirs_free_content(struct sdirs *sdirs)
     232             : {
     233         313 :         free_w(&sdirs->base);
     234         313 :         free_w(&sdirs->dedup);
     235         313 :         free_w(&sdirs->champlock);
     236         313 :         free_w(&sdirs->champsock);
     237         313 :         free_w(&sdirs->champlog);
     238         313 :         free_w(&sdirs->champ_dindex_lock);
     239         313 :         free_w(&sdirs->data);
     240         313 :         free_w(&sdirs->clients);
     241         313 :         free_w(&sdirs->client);
     242             : 
     243         313 :         free_w(&sdirs->working);
     244         313 :         free_w(&sdirs->rworking);
     245         313 :         free_w(&sdirs->finishing);
     246         313 :         free_w(&sdirs->current);
     247         313 :         free_w(&sdirs->currenttmp);
     248         313 :         free_w(&sdirs->deleteme);
     249         313 :         free_w(&sdirs->dindex);
     250         313 :         free_w(&sdirs->dfiles);
     251         313 :         free_w(&sdirs->cfiles);
     252         313 :         free_w(&sdirs->global_sparse);
     253             : 
     254         313 :         free_w(&sdirs->timestamp);
     255         313 :         free_w(&sdirs->changed);
     256         313 :         free_w(&sdirs->unchanged);
     257         313 :         free_w(&sdirs->manifest);
     258         313 :         free_w(&sdirs->rmanifest);
     259         313 :         free_w(&sdirs->cmanifest);
     260         313 :         free_w(&sdirs->phase1data);
     261             : 
     262         313 :         free_w(&sdirs->lockdir);
     263         313 :         lock_free(&sdirs->lock);
     264             : 
     265             :         // Protocol1 directories.
     266         313 :         free_w(&sdirs->currentdata);
     267         313 :         free_w(&sdirs->datadirtmp);
     268         313 :         free_w(&sdirs->cincexc);
     269         313 :         free_w(&sdirs->deltmppath);
     270         313 :         free_w(&sdirs->treepath);
     271         313 : }
     272             : 
     273         351 : void sdirs_free(struct sdirs **sdirs)
     274             : {
     275         702 :         if(!sdirs || !*sdirs) return;
     276         312 :         sdirs_free_content(*sdirs);
     277             : 
     278         312 :         free_v((void **)sdirs);
     279             : }

Generated by: LCOV version 1.10