LCOV - code coverage report
Current view: top level - src/server - sdirs.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 143 160 89.4 %
Date: 2017-08-31 Functions: 13 13 100.0 %

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

Generated by: LCOV version 1.10