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->restore_list=prepend_s(sdirs->client, "restore_list")))
134 : return -1;
135 364 : if(manual_delete)
136 : {
137 0 : if(!(sdirs->deleteme=strdup_w(manual_delete, __func__)))
138 : return -1;
139 : }
140 : else
141 : {
142 364 : if(!(sdirs->deleteme=prepend_s(sdirs->client, "deleteme")))
143 : return -1;
144 : }
145 : return 0;
146 : }
147 :
148 : // Maybe should be in a protocol1 directory.
149 166 : static int do_protocol1_dirs(struct sdirs *sdirs, const char *cname,
150 : const char *manual_delete)
151 : {
152 166 : if(!(sdirs->clients=strdup_w(sdirs->base, __func__))
153 166 : || !(sdirs->client=prepend_s(sdirs->clients, cname))
154 166 : || do_common_dirs(sdirs, manual_delete)
155 166 : || !(sdirs->currentdata=prepend_s(sdirs->current, DATA_DIR))
156 166 : || !(sdirs->manifest=prepend_s(sdirs->working, "manifest.gz"))
157 166 : || !(sdirs->datadirtmp=prepend_s(sdirs->working, "data.tmp"))
158 166 : || !(sdirs->cmanifest=prepend_s(sdirs->current, "manifest.gz"))
159 166 : || !(sdirs->cincexc=prepend_s(sdirs->current, "incexc"))
160 166 : || !(sdirs->deltmppath=prepend_s(sdirs->working, "deltmppath")))
161 : return -1;
162 : // sdirs->rworking gets set later.
163 : // sdirs->treepath gets set later.
164 : // sdirs->relink gets set later.
165 : return 0;
166 : }
167 :
168 198 : static int do_protocol2_dirs(struct sdirs *sdirs,
169 : const char *cname, const char *dedup_group, const char *manual_delete)
170 : {
171 198 : if(!dedup_group)
172 : {
173 0 : logp("dedup_group unset in %s\n", __func__);
174 0 : return -1;
175 : }
176 198 : if(!(sdirs->dedup=prepend_s(sdirs->base, dedup_group))
177 198 : || !(sdirs->clients=prepend_s(sdirs->dedup, "clients"))
178 198 : || !(sdirs->client=prepend_s(sdirs->clients, cname))
179 198 : || !(sdirs->dindex=prepend_s(sdirs->client, "dindex"))
180 198 : || !(sdirs->dfiles=prepend_s(sdirs->client, "dfiles"))
181 198 : || do_common_dirs(sdirs, manual_delete)
182 198 : || !(sdirs->data=prepend_s(sdirs->dedup, DATA_DIR))
183 198 : || !(sdirs->cfiles=prepend_s(sdirs->data, "cfiles"))
184 198 : || !(sdirs->global_sparse=prepend_s(sdirs->data, "sparse"))
185 198 : || !(sdirs->champlock=prepend_s(sdirs->data, "cc.lock"))
186 198 : || !(sdirs->champsock=prepend_s(sdirs->data, "cc.sock"))
187 198 : || !(sdirs->champlog=prepend_s(sdirs->data, "cc.log"))
188 198 : || !(sdirs->champ_dindex_lock=prepend_s(sdirs->data, "dindex.lock"))
189 198 : || !(sdirs->manifest=prepend_s(sdirs->working, "manifest"))
190 198 : || !(sdirs->cmanifest=prepend_s(sdirs->current, "manifest")))
191 : return -1;
192 : // sdirs->rworking gets set later.
193 : // sdirs->rmanifest gets set later.
194 : return 0;
195 : }
196 :
197 45 : int sdirs_init_from_confs(struct sdirs *sdirs, struct conf **confs)
198 : {
199 45 : return sdirs_init(
200 : sdirs,
201 : get_protocol(confs),
202 45 : get_string(confs[OPT_DIRECTORY]),
203 45 : get_string(confs[OPT_CNAME]),
204 45 : get_string(confs[OPT_CLIENT_LOCKDIR]),
205 45 : get_string(confs[OPT_DEDUP_GROUP]),
206 45 : get_string(confs[OPT_MANUAL_DELETE])
207 : );
208 : }
209 :
210 364 : int sdirs_init(struct sdirs *sdirs, enum protocol protocol,
211 : const char *directory, const char *cname, const char *conf_lockdir,
212 : const char *dedup_group, const char *manual_delete)
213 : {
214 364 : if(!directory)
215 : {
216 0 : logp("directory unset in %s\n", __func__);
217 0 : goto error;
218 : }
219 :
220 364 : if(!(sdirs->base=strdup_w(directory, __func__)))
221 : goto error;
222 :
223 364 : sdirs->protocol=protocol;
224 :
225 364 : if(protocol==PROTO_1)
226 : {
227 166 : if(do_protocol1_dirs(sdirs, cname, manual_delete))
228 : goto error;
229 : }
230 : else
231 : {
232 198 : if(do_protocol2_dirs(sdirs, cname, dedup_group, manual_delete))
233 : goto error;
234 : }
235 :
236 364 : if(do_lock_dirs(sdirs, cname, conf_lockdir)) goto error;
237 :
238 : return 0;
239 : error:
240 : return -1;
241 : }
242 :
243 364 : void sdirs_free_content(struct sdirs *sdirs)
244 : {
245 364 : free_w(&sdirs->base);
246 364 : free_w(&sdirs->dedup);
247 364 : free_w(&sdirs->champlock);
248 364 : free_w(&sdirs->champsock);
249 364 : free_w(&sdirs->champlog);
250 364 : free_w(&sdirs->champ_dindex_lock);
251 364 : free_w(&sdirs->data);
252 364 : free_w(&sdirs->clients);
253 364 : free_w(&sdirs->client);
254 364 : free_w(&sdirs->created);
255 364 : free_w(&sdirs->command);
256 :
257 364 : free_w(&sdirs->working);
258 364 : free_w(&sdirs->rworking);
259 364 : free_w(&sdirs->finishing);
260 364 : free_w(&sdirs->current);
261 364 : free_w(&sdirs->currenttmp);
262 364 : free_w(&sdirs->deleteme);
263 364 : free_w(&sdirs->dindex);
264 364 : free_w(&sdirs->dfiles);
265 364 : free_w(&sdirs->cfiles);
266 364 : free_w(&sdirs->global_sparse);
267 :
268 364 : free_w(&sdirs->timestamp);
269 364 : free_w(&sdirs->changed);
270 364 : free_w(&sdirs->unchanged);
271 364 : free_w(&sdirs->manifest);
272 364 : free_w(&sdirs->rmanifest);
273 364 : free_w(&sdirs->cmanifest);
274 364 : free_w(&sdirs->phase1data);
275 :
276 364 : free_w(&sdirs->restore_list);
277 :
278 364 : free_w(&sdirs->lockdir);
279 364 : lock_free(&sdirs->lock_storage_for_write);
280 :
281 : // Protocol1 directories.
282 364 : free_w(&sdirs->currentdata);
283 364 : free_w(&sdirs->datadirtmp);
284 364 : free_w(&sdirs->cincexc);
285 364 : free_w(&sdirs->deltmppath);
286 364 : free_w(&sdirs->treepath);
287 364 : free_w(&sdirs->relink);
288 364 : }
289 :
290 403 : void sdirs_free(struct sdirs **sdirs)
291 : {
292 403 : if(!sdirs || !*sdirs) return;
293 363 : sdirs_free_content(*sdirs);
294 :
295 363 : free_v((void **)sdirs);
296 : }
|