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