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 : }
|