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