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