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