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 177 : struct sdirs *sdirs_alloc(void)
14 : {
15 177 : return (struct sdirs *)calloc_w(1, sizeof(struct sdirs), __func__);
16 : }
17 :
18 177 : static int do_lock_dirs(struct sdirs *sdirs,
19 : const char *cname, const char *conf_lockdir)
20 : {
21 177 : int ret=-1;
22 177 : char *lockbase=NULL;
23 177 : char *lockfile=NULL;
24 177 : 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 176 : if(!(sdirs->lockdir=strdup_w(sdirs->client, __func__))
33 176 : || !(lockbase=strdup_w(sdirs->client, __func__)))
34 : goto end;
35 : }
36 177 : if(!(lockfile=prepend_s(lockbase, "lockfile"))
37 177 : || !(sdirs->lock_storage_for_write=lock_alloc_and_init(lockfile)))
38 : goto end;
39 177 : ret=0;
40 : end:
41 177 : free_w(&lockbase);
42 177 : free_w(&lockfile);
43 177 : return ret;
44 : }
45 :
46 : static int free_prepend_s(char **dst, const char *a, const char *b)
47 : {
48 26 : free_w(dst);
49 26 : return !(*dst=prepend_s(a, b));
50 : }
51 :
52 2 : int sdirs_get_real_manifest(struct sdirs *sdirs)
53 : {
54 4 : return free_prepend_s(&sdirs->rmanifest,
55 2 : sdirs->rworking, "manifest.gz");
56 : }
57 :
58 6 : int sdirs_get_real_working_from_symlink(struct sdirs *sdirs)
59 : {
60 6 : char real[256]="";
61 6 : 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 12 : if(free_prepend_s(&sdirs->rworking, sdirs->client, real)
68 12 : || free_prepend_s(&sdirs->treepath,
69 : sdirs->rworking, DATA_DIR "/" TREE_DIR)
70 12 : || free_prepend_s(&sdirs->relink, sdirs->rworking, RELINK_DIR))
71 : return -1;
72 : return 0;
73 : }
74 :
75 2 : int sdirs_create_real_working(
76 : struct sdirs *sdirs,
77 : uint64_t bno,
78 : const char *timestamp_format
79 : ) {
80 2 : char tstmp[64]="";
81 2 : char fname[64]="";
82 :
83 2 : if(build_path_w(sdirs->working))
84 : return -1;
85 2 : if(timestamp_get_new(bno,
86 : tstmp, sizeof(tstmp), fname, sizeof(fname), timestamp_format)
87 4 : || free_prepend_s(&sdirs->rworking, sdirs->client, fname)
88 4 : || free_prepend_s(&sdirs->treepath,
89 : sdirs->rworking, DATA_DIR "/" TREE_DIR)
90 4 : || 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 2 : 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 2 : 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 2 : 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 177 : static int do_common_dirs(struct sdirs *sdirs, const char *manual_delete)
122 : {
123 177 : if(!(sdirs->created=prepend_s(sdirs->client, ".created"))
124 177 : || !(sdirs->command=prepend_s(sdirs->client, ".command"))
125 177 : || !(sdirs->working=prepend_s(sdirs->client, "working"))
126 177 : || !(sdirs->finishing=prepend_s(sdirs->client, "finishing"))
127 177 : || !(sdirs->current=prepend_s(sdirs->client, "current"))
128 177 : || !(sdirs->currenttmp=prepend_s(sdirs->client, "current.tmp"))
129 177 : || !(sdirs->timestamp=prepend_s(sdirs->working, "timestamp"))
130 177 : || !(sdirs->phase1data=prepend_s(sdirs->working, "phase1.gz"))
131 177 : || !(sdirs->changed=prepend_s(sdirs->working, "changed"))
132 177 : || !(sdirs->unchanged=prepend_s(sdirs->working, "unchanged"))
133 177 : || !(sdirs->counters_d=prepend_s(sdirs->working, "counters_d"))
134 177 : || !(sdirs->counters_n=prepend_s(sdirs->working, "counters_n"))
135 177 : || !(sdirs->restore_list=prepend_s(sdirs->client, "restore_list")))
136 : return -1;
137 177 : if(manual_delete)
138 : {
139 0 : if(!(sdirs->deleteme=strdup_w(manual_delete, __func__)))
140 : return -1;
141 : }
142 : else
143 : {
144 177 : if(!(sdirs->deleteme=prepend_s(sdirs->client, "deleteme")))
145 : return -1;
146 : }
147 : return 0;
148 : }
149 :
150 : // Maybe should be in a protocol1 directory.
151 177 : static int do_protocol1_dirs(struct sdirs *sdirs, const char *cname,
152 : const char *manual_delete)
153 : {
154 177 : if(!(sdirs->clients=strdup_w(sdirs->base, __func__))
155 177 : || !(sdirs->client=prepend_s(sdirs->clients, cname))
156 177 : || do_common_dirs(sdirs, manual_delete)
157 177 : || !(sdirs->currentdata=prepend_s(sdirs->current, DATA_DIR))
158 177 : || !(sdirs->manifest=prepend_s(sdirs->working, "manifest.gz"))
159 177 : || !(sdirs->datadirtmp=prepend_s(sdirs->working, "data.tmp"))
160 177 : || !(sdirs->cmanifest=prepend_s(sdirs->current, "manifest.gz"))
161 177 : || !(sdirs->cincexc=prepend_s(sdirs->current, "incexc"))
162 177 : || !(sdirs->deltmppath=prepend_s(sdirs->working, "deltmppath")))
163 : return -1;
164 : // sdirs->rworking gets set later.
165 : // sdirs->treepath gets set later.
166 : // sdirs->relink gets set later.
167 : return 0;
168 : }
169 :
170 25 : int sdirs_init_from_confs_plus_cname(
171 : struct sdirs *sdirs,
172 : struct conf **confs,
173 : const char *cname
174 : ) {
175 25 : return sdirs_init(
176 : sdirs,
177 25 : get_string(confs[OPT_DIRECTORY]),
178 : cname,
179 25 : get_string(confs[OPT_CLIENT_LOCKDIR]),
180 25 : get_string(confs[OPT_DEDUP_GROUP]),
181 25 : get_string(confs[OPT_MANUAL_DELETE])
182 : );
183 : }
184 :
185 25 : int sdirs_init_from_confs(
186 : struct sdirs *sdirs,
187 : struct conf **confs
188 : ) {
189 25 : return sdirs_init_from_confs_plus_cname(
190 : sdirs,
191 : confs,
192 25 : get_string(confs[OPT_CNAME])
193 : );
194 : }
195 :
196 177 : int sdirs_init(struct sdirs *sdirs,
197 : const char *directory, const char *cname, const char *conf_lockdir,
198 : const char *dedup_group, const char *manual_delete)
199 : {
200 177 : if(!directory)
201 : {
202 0 : logp("directory unset in %s\n", __func__);
203 0 : goto error;
204 : }
205 :
206 177 : if(!(sdirs->base=strdup_w(directory, __func__)))
207 : goto error;
208 :
209 177 : if(do_protocol1_dirs(sdirs, cname, manual_delete))
210 : goto error;
211 :
212 177 : if(do_lock_dirs(sdirs, cname, conf_lockdir)) goto error;
213 :
214 : return 0;
215 : error:
216 : return -1;
217 : }
218 :
219 178 : void sdirs_free_content(struct sdirs *sdirs)
220 : {
221 178 : free_w(&sdirs->base);
222 178 : free_w(&sdirs->dedup);
223 178 : free_w(&sdirs->champlock);
224 178 : free_w(&sdirs->champsock);
225 178 : free_w(&sdirs->champlog);
226 178 : free_w(&sdirs->champ_dindex_lock);
227 178 : free_w(&sdirs->data);
228 178 : free_w(&sdirs->clients);
229 178 : free_w(&sdirs->client);
230 178 : free_w(&sdirs->created);
231 178 : free_w(&sdirs->command);
232 :
233 178 : free_w(&sdirs->working);
234 178 : free_w(&sdirs->rworking);
235 178 : free_w(&sdirs->finishing);
236 178 : free_w(&sdirs->current);
237 178 : free_w(&sdirs->currenttmp);
238 178 : free_w(&sdirs->deleteme);
239 178 : free_w(&sdirs->dindex);
240 178 : free_w(&sdirs->dfiles);
241 178 : free_w(&sdirs->cfiles);
242 :
243 178 : free_w(&sdirs->timestamp);
244 178 : free_w(&sdirs->changed);
245 178 : free_w(&sdirs->unchanged);
246 178 : free_w(&sdirs->counters_d);
247 178 : free_w(&sdirs->counters_n);
248 178 : free_w(&sdirs->manifest);
249 178 : free_w(&sdirs->rmanifest);
250 178 : free_w(&sdirs->cmanifest);
251 178 : free_w(&sdirs->phase1data);
252 :
253 178 : free_w(&sdirs->restore_list);
254 :
255 178 : free_w(&sdirs->lockdir);
256 178 : lock_free(&sdirs->lock_storage_for_write);
257 :
258 : // Protocol1 directories.
259 178 : free_w(&sdirs->currentdata);
260 178 : free_w(&sdirs->datadirtmp);
261 178 : free_w(&sdirs->cincexc);
262 178 : free_w(&sdirs->deltmppath);
263 178 : free_w(&sdirs->treepath);
264 178 : free_w(&sdirs->relink);
265 178 : }
266 :
267 214 : void sdirs_free(struct sdirs **sdirs)
268 : {
269 214 : if(!sdirs || !*sdirs) return;
270 177 : sdirs_free_content(*sdirs);
271 :
272 177 : free_v((void **)sdirs);
273 : }
|