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

Generated by: LCOV version 1.10