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