Line data Source code
1 : #include "../../burp.h"
2 : #include "../../attribs.h"
3 : #include "../../base64.h"
4 : #include "../../conffile.h"
5 : #include "../../cstat.h"
6 : #include "../../fsops.h"
7 : #include "../../fzp.h"
8 : #include "../../handy.h"
9 : #include "../../hexmap.h"
10 : #include "../../iobuf.h"
11 : #include "../../lock.h"
12 : #include "../../log.h"
13 : #include "../../strlist.h"
14 : #include "../../protocol2/blk.h"
15 : #include "../bu_get.h"
16 : #include "../protocol2/backup_phase4.h"
17 : #include "../sdirs.h"
18 : #include "bsigs.h"
19 : #include "clist.h"
20 : #include "champ_chooser/champ_chooser.h"
21 : #include "sparse_min.h"
22 :
23 : static struct lock *sparse_lock=NULL;
24 : static struct cstat *clist=NULL;
25 :
26 3 : static int usage(void)
27 : {
28 3 : logfmt("\nUsage: %s [options] <path to dedup_group>\n", prog);
29 3 : logfmt("\n");
30 3 : logfmt(" Options:\n");
31 3 : logfmt(" -c <path> Path to config file (default: %s).\n",
32 : config_default_path());
33 3 : logfmt("\n");
34 3 : return 1;
35 : }
36 :
37 1 : static void release_locks(struct cstat *clist)
38 : {
39 : struct cstat *c;
40 : struct sdirs *s;
41 4 : for(c=clist; c; c=c->next)
42 : {
43 3 : s=(struct sdirs *)c->sdirs;
44 3 : if(!s) continue;
45 3 : lock_release(s->lock_storage_for_write);
46 3 : logp("released: %s\n", c->name);
47 : }
48 1 : lock_release(sparse_lock);
49 1 : lock_free(&sparse_lock);
50 1 : logp("released: sparse index\n");
51 1 : }
52 :
53 0 : static void sighandler(__attribute__ ((unused)) int signum)
54 : {
55 0 : release_locks(clist);
56 0 : exit(1);
57 : }
58 :
59 1 : static struct sdirs *get_sdirs(struct conf **conf)
60 : {
61 1 : struct sdirs *sdirs=NULL;
62 1 : if(!(sdirs=sdirs_alloc())
63 1 : || sdirs_init_from_confs(sdirs, conf))
64 0 : sdirs_free(&sdirs);
65 1 : return sdirs;
66 : }
67 :
68 1 : static int parse_directory(const char *arg,
69 : char **directory, char **dedup_group)
70 : {
71 : char *cp;
72 1 : if(!(*directory=strdup_w(arg, __func__)))
73 : goto error;
74 1 : strip_trailing_slashes(directory);
75 1 : if(!(cp=strrchr(*directory, '/')))
76 : {
77 0 : logp("Could not parse directory '%s'\n", *directory);
78 0 : goto error;
79 : }
80 1 : *cp='\0';
81 1 : if(!(*dedup_group=strdup_w(cp+1, __func__)))
82 : goto error;
83 1 : if(!*directory || !*dedup_group)
84 : goto error;
85 : return 0;
86 : error:
87 0 : free_w(directory);
88 0 : free_w(dedup_group);
89 0 : return -1;
90 : }
91 :
92 1 : static struct conf **load_conf(const char *configfile,
93 : const char *directory, const char *dedup_group)
94 : {
95 1 : struct conf **conf=NULL;
96 1 : if(!(conf=confs_alloc())
97 1 : || confs_init(conf)
98 1 : || conf_load_global_only(configfile, conf)
99 1 : || set_string(conf[OPT_CNAME], "fake")
100 1 : || set_string(conf[OPT_DIRECTORY], directory)
101 1 : || set_string(conf[OPT_DEDUP_GROUP], dedup_group)
102 1 : || set_protocol(conf, PROTO_2))
103 0 : confs_free(&conf);
104 1 : return conf;
105 : }
106 :
107 1 : static void setup_sighandler(void)
108 : {
109 1 : signal(SIGABRT, &sighandler);
110 1 : signal(SIGTERM, &sighandler);
111 1 : signal(SIGINT, &sighandler);
112 1 : }
113 :
114 1 : static int get_sparse_lock(const char *sparse)
115 : {
116 1 : if(!(sparse_lock=try_to_get_sparse_lock(sparse)))
117 : {
118 0 : logp("Could not get sparse lock\n");
119 0 : return -1;
120 : }
121 : return 0;
122 : }
123 :
124 1 : static int get_client_locks(struct cstat *clist)
125 : {
126 : struct cstat *c;
127 : struct sdirs *s;
128 8 : for(c=clist; c; c=c->next)
129 : {
130 3 : s=(struct sdirs *)c->sdirs;
131 3 : if(mkpath(&s->lock_storage_for_write->path, s->lockdir))
132 : {
133 0 : logp("problem with lock directory: %s\n", s->lockdir);
134 0 : return -1;
135 : }
136 :
137 3 : lock_get(s->lock_storage_for_write);
138 3 : switch(s->lock_storage_for_write->status)
139 : {
140 : case GET_LOCK_GOT:
141 3 : logp("locked: %s\n", c->name);
142 : break;
143 : case GET_LOCK_NOT_GOT:
144 0 : logp("Unable to get lock for client %s\n",
145 : c->name);
146 0 : return -1;
147 : case GET_LOCK_ERROR:
148 : default:
149 0 : logp("Problem with lock file: %s\n",
150 : s->lock_storage_for_write->path);
151 0 : return -1;
152 : }
153 : }
154 : return 0;
155 : }
156 :
157 3 : static int merge_in_client_sparse_indexes(struct cstat *c,
158 : const char *global_sparse)
159 : {
160 3 : int ret=-1;
161 3 : char *sparse=NULL;
162 3 : struct bu *b=NULL;
163 3 : struct bu *bu_list=NULL;
164 3 : struct sdirs *s=(struct sdirs *)c->sdirs;
165 :
166 3 : if(bu_get_list(s, &bu_list))
167 : goto end;
168 12 : for(b=bu_list; b; b=b->next)
169 : {
170 9 : free_w(&sparse);
171 9 : if(!(sparse=prepend_s(b->path, "manifest/sparse")))
172 : goto end;
173 9 : logp("merge: %s\n", sparse);
174 9 : if(merge_into_global_sparse(sparse,
175 : global_sparse, sparse_lock))
176 : goto end;
177 : }
178 : ret=0;
179 : end:
180 3 : bu_list_free(&bu_list);
181 3 : free_w(&sparse);
182 3 : return ret;
183 : }
184 :
185 1 : static int merge_in_all_sparse_indexes(const char *global_sparse)
186 : {
187 : struct cstat *c;
188 :
189 1 : if(!is_reg_lstat(global_sparse)
190 0 : && unlink(global_sparse))
191 : {
192 0 : logp("Could not delete %s: %s\n",
193 0 : global_sparse, strerror(errno));
194 0 : return -1;
195 : }
196 :
197 4 : for(c=clist; c; c=c->next)
198 3 : if(merge_in_client_sparse_indexes(c, global_sparse))
199 : return -1;
200 : return 0;
201 : }
202 :
203 5 : int run_bsparse(int argc, char *argv[])
204 : {
205 5 : int ret=1;
206 : int option;
207 5 : char *directory=NULL;
208 5 : char *dedup_group=NULL;
209 5 : const char *configfile=NULL;
210 5 : struct sdirs *sdirs=NULL;
211 5 : struct conf **conf=NULL;
212 :
213 5 : base64_init();
214 5 : configfile=config_default_path();
215 :
216 11 : while((option=getopt(argc, argv, "c:Vh?"))!=-1)
217 : {
218 4 : switch(option)
219 : {
220 : case 'c':
221 1 : configfile=optarg;
222 1 : break;
223 : case 'V':
224 1 : logfmt("%s-%s\n", prog, PACKAGE_VERSION);
225 1 : return 0;
226 : case 'h':
227 : case '?':
228 2 : return usage();
229 : }
230 : }
231 :
232 2 : if(optind>=argc || optind<argc-1)
233 1 : return usage();
234 :
235 1 : if(parse_directory(argv[optind], &directory, &dedup_group))
236 : goto end;
237 :
238 1 : logp("config file: %s\n", configfile);
239 1 : logp("directory: %s\n", directory);
240 1 : logp("dedup_group: %s\n", dedup_group);
241 :
242 1 : if(!(conf=load_conf(configfile, directory, dedup_group))
243 1 : || !(sdirs=get_sdirs(conf)))
244 : goto end;
245 :
246 1 : logp("clients: %s\n", sdirs->clients);
247 1 : logp("sparse file: %s\n", sdirs->global_sparse);
248 :
249 1 : setup_sighandler();
250 :
251 1 : if(get_sparse_lock(sdirs->global_sparse))
252 : goto end;
253 :
254 1 : if(get_client_list(&clist, sdirs->clients, conf))
255 : {
256 0 : logp("Did not find any client directories\n");
257 0 : goto end;
258 : }
259 :
260 1 : if(get_client_locks(clist))
261 : goto end;
262 :
263 1 : if(merge_in_all_sparse_indexes(sdirs->global_sparse))
264 : goto end;
265 :
266 1 : if(sparse_minimise(conf, sdirs->global_sparse, sparse_lock, clist))
267 : goto end;
268 :
269 1 : ret=0;
270 : end:
271 1 : release_locks(clist);
272 1 : sdirs_free(&sdirs);
273 1 : free_w(&directory);
274 1 : free_w(&dedup_group);
275 1 : confs_free(&conf);
276 1 : clist_free(&clist);
277 1 : return ret;
278 : }
|