Line data Source code
1 : #include "burp.h"
2 : #include "base64.h"
3 : #include "cmd.h"
4 : #include "conf.h"
5 : #include "conffile.h"
6 : #include "client/main.h"
7 : #include "handy.h"
8 : #include "hexmap.h"
9 : #include "lock.h"
10 : #include "log.h"
11 : #include "strlist.h"
12 : #include "server/main.h"
13 : #include "server/protocol1/bedup.h"
14 : #include "server/protocol2/bsigs.h"
15 : #include "server/protocol2/bsparse.h"
16 : #include "server/protocol2/champ_chooser/champ_server.h"
17 :
18 0 : static void usage_server(void)
19 : {
20 : #ifndef HAVE_WIN32
21 0 : printf("\nThe configuration file specifies whether %s runs in server or client mode.\n", PACKAGE_TARNAME);
22 0 : printf("\nServer usage: %s [options]\n", progname());
23 0 : printf("\n");
24 0 : printf(" Options:\n");
25 0 : printf(" -a c Run as a stand-alone champion chooser.\n");
26 0 : printf(" -c <path> Path to conf file (default: %s).\n", config_default_path());
27 0 : printf(" -d <path> a single client in the status monitor.\n");
28 0 : printf(" -o <option> Override a given configuration option (you can use this flag several times).\n");
29 0 : printf(" -F Stay in the foreground.\n");
30 0 : printf(" -g Generate initial CA certificates and exit.\n");
31 0 : printf(" -h|-? Print this text and exit.\n");
32 0 : printf(" -i Print index of symbols and exit.\n");
33 0 : printf(" -n Do not fork any children (implies '-F').\n");
34 0 : printf(" -Q Do not log to stdout\n");
35 0 : printf(" -t Dry-run to test config file syntax.\n");
36 0 : printf(" -v Log to stdout.\n");
37 0 : printf(" -V Print version and exit.\n");
38 0 : printf("Options to use with '-a c':\n");
39 0 : printf(" -C <client> Run as if forked via a connection from this client.\n");
40 0 : printf("\n");
41 : #endif
42 0 : }
43 :
44 0 : static void usage_client(void)
45 : {
46 0 : printf("\nClient usage: %s [options]\n", progname());
47 0 : printf("\n");
48 0 : printf(" Options:\n");
49 0 : printf(" -a <action> The action can be one of the following.\n");
50 0 : printf(" b: backup\n");
51 0 : printf(" delete: delete\n");
52 0 : printf(" d: diff\n");
53 0 : printf(" e: estimate\n");
54 0 : printf(" l: list (this is the default when an action is not given)\n");
55 0 : printf(" L: long list\n");
56 0 : printf(" m: monitor interface\n");
57 0 : printf(" r: restore\n");
58 : #ifndef HAVE_WIN32
59 0 : printf(" s: status monitor (ncurses)\n");
60 0 : printf(" S: status monitor snapshot\n");
61 : #endif
62 0 : printf(" t: timed backup\n");
63 0 : printf(" T: check backup timer, but do not actually backup\n");
64 0 : printf(" v: verify\n");
65 0 : printf(" -b <number> Backup number (default: the most recent backup).\n");
66 0 : printf(" -c <path> Path to conf file (default: %s).\n", config_default_path());
67 0 : printf(" -d <directory> Directory to restore to, or directory to list.\n");
68 0 : printf(" -o <option> Override a given configuration option (you can use this flag several times).\n");
69 0 : printf(" -f Allow overwrite during restore.\n");
70 0 : printf(" -h|-? Print this text and exit.\n");
71 0 : printf(" -i Print index of symbols and exit.\n");
72 0 : printf(" -q <max secs> Randomised delay of starting a timed backup.\n");
73 0 : printf(" -Q Do not log to stdout\n");
74 0 : printf(" -r <regex> Specify a regular expression.\n");
75 0 : printf(" -s <number> Number of leading path components to strip during restore.\n");
76 0 : printf(" -t Dry-run to test config file syntax.\n");
77 0 : printf(" -v Log to stdout.\n");
78 0 : printf(" -V Print version and exit.\n");
79 : #ifdef HAVE_WIN32
80 : printf(" -x Do not use the Windows VSS API when restoring.\n");
81 : #else
82 0 : printf(" -x Strip Windows VSS data when restoring.\n");
83 0 : printf("Options to use with '-a S':\n");
84 0 : printf(" -C <client> Show a particular client.\n");
85 0 : printf(" -b <number> Show listable files in a particular backup (requires -C).\n");
86 0 : printf(" -d <path> Show a particular path in a backup (requires -C and -b).\n");
87 0 : printf(" -l <path> Log file for the status monitor.\n");
88 0 : printf(" -z <file> Dump a particular log file in a backup (requires -C and -b).\n");
89 : #endif
90 0 : printf("\n");
91 : #ifndef HAVE_WIN32
92 0 : printf(" See ");
93 : // Older versions of autoconf do not pick up PACKAGE_URL.
94 : #ifdef PACKAGE_URL
95 0 : printf("%s or ", PACKAGE_URL);
96 : #endif
97 0 : printf( "the man page ('man %s') for usage examples\n",
98 : PACKAGE_TARNAME);
99 0 : printf(" and additional configuration options.\n\n");
100 : #else
101 : printf(" See %s for usage examples and additional configuration\n",
102 : PACKAGE_TARNAME);
103 : printf(" options.\n\n");
104 : #endif
105 0 : }
106 :
107 0 : int reload(struct conf **confs, const char *conffile, bool firsttime)
108 : {
109 0 : if(!firsttime) logp("Reloading config\n");
110 :
111 0 : if(confs_init(confs)) return -1;
112 :
113 0 : if(conf_load_global_only(conffile, confs)) return -1;
114 :
115 0 : umask(get_mode_t(confs[OPT_UMASK]));
116 :
117 : // This will turn on syslogging which could not be turned on before
118 : // conf_load.
119 0 : log_fzp_set(NULL, confs);
120 :
121 : #ifndef HAVE_WIN32
122 0 : if(get_e_burp_mode(confs[OPT_BURP_MODE])==BURP_MODE_SERVER)
123 0 : setup_signals();
124 : #endif
125 :
126 : return 0;
127 : }
128 :
129 : static int replace_conf_str(struct conf *conf, const char *newval)
130 : {
131 0 : if(!newval) return 0;
132 0 : return set_string(conf, newval);
133 : }
134 :
135 : static void usage(void)
136 : {
137 0 : usage_server();
138 0 : usage_client();
139 : }
140 :
141 0 : static int parse_action(enum action *act, const char *optarg)
142 : {
143 0 : if(!strncmp(optarg, "backup", 1))
144 0 : *act=ACTION_BACKUP;
145 0 : else if(!strncmp(optarg, "timedbackup", 1))
146 0 : *act=ACTION_BACKUP_TIMED;
147 0 : else if(!strncmp(optarg, "Timercheck", 1))
148 0 : *act=ACTION_TIMER_CHECK;
149 0 : else if(!strncmp(optarg, "restore", 1))
150 0 : *act=ACTION_RESTORE;
151 0 : else if(!strncmp(optarg, "verify", 1))
152 0 : *act=ACTION_VERIFY;
153 0 : else if(!strncmp(optarg, "list", 1))
154 0 : *act=ACTION_LIST;
155 0 : else if(!strncmp(optarg, "List", 1))
156 0 : *act=ACTION_LIST_LONG;
157 0 : else if(!strncmp(optarg, "status", 1))
158 0 : *act=ACTION_STATUS;
159 0 : else if(!strncmp(optarg, "Status", 1))
160 0 : *act=ACTION_STATUS_SNAPSHOT;
161 0 : else if(!strncmp(optarg, "estimate", 1))
162 0 : *act=ACTION_ESTIMATE;
163 : // Make them spell 'delete' out fully so that it is less likely to be
164 : // used accidently.
165 0 : else if(!strncmp_w(optarg, "delete"))
166 0 : *act=ACTION_DELETE;
167 0 : else if(!strncmp(optarg, "champchooser", 1))
168 0 : *act=ACTION_CHAMP_CHOOSER;
169 0 : else if(!strncmp(optarg, "diff", 1))
170 0 : *act=ACTION_DIFF;
171 0 : else if(!strncmp(optarg, "Diff", 1))
172 0 : *act=ACTION_DIFF_LONG;
173 0 : else if(!strncmp(optarg, "monitor", 1))
174 0 : *act=ACTION_MONITOR;
175 : else
176 : {
177 : usage();
178 0 : return -1;
179 : }
180 : return 0;
181 : }
182 :
183 : #ifndef HAVE_WIN32
184 0 : static int run_champ_chooser(struct conf **confs)
185 : {
186 0 : const char *orig_client=get_string(confs[OPT_ORIG_CLIENT]);
187 0 : if(orig_client && *orig_client)
188 0 : return champ_chooser_server_standalone(confs);
189 0 : logp("No client name given for standalone champion chooser process.\n");
190 0 : logp("Try using the '-C' option.\n");
191 0 : return 1;
192 : }
193 :
194 0 : static int server_modes(enum action act,
195 : const char *conffile, struct lock *lock, int generate_ca_only,
196 : struct conf **confs)
197 : {
198 0 : switch(act)
199 : {
200 : case ACTION_CHAMP_CHOOSER:
201 : // We are running on the server machine, wanting to
202 : // be a standalone champion chooser process.
203 0 : return run_champ_chooser(confs);
204 : default:
205 0 : return server(confs, conffile, lock, generate_ca_only);
206 : }
207 : }
208 : #endif
209 :
210 0 : static void random_delay(struct conf **confs)
211 : {
212 : int delay;
213 0 : int randomise=get_int(confs[OPT_RANDOMISE]);
214 0 : if(!randomise) return;
215 0 : srand(getpid());
216 0 : delay=rand()%randomise;
217 0 : logp("Sleeping %d seconds\n", delay);
218 0 : sleep(delay);
219 : }
220 :
221 0 : static int run_test_confs(struct conf **confs, const char *client)
222 : {
223 0 : int ret=-1;
224 0 : struct conf **cconfs=NULL;
225 0 : if(!client)
226 : {
227 0 : confs_dump(confs, 0);
228 0 : ret=0;
229 0 : goto end;
230 : }
231 0 : if(!(cconfs=confs_alloc()))
232 : goto end;
233 0 : confs_init(cconfs);
234 0 : if(set_string(cconfs[OPT_CNAME], client)
235 0 : || set_string(cconfs[OPT_PEER_VERSION], PACKAGE_VERSION)
236 0 : || conf_load_clientconfdir(confs, cconfs))
237 : goto end;
238 0 : confs_dump(cconfs, CONF_FLAG_CC_OVERRIDE|CONF_FLAG_INCEXC);
239 :
240 : end:
241 0 : confs_free(&cconfs);
242 0 : return ret;
243 : }
244 :
245 0 : static struct lock *get_prog_lock(struct conf **confs)
246 : {
247 0 : struct lock *lock=NULL;
248 0 : const char *lockfile=confs_get_lockfile(confs);
249 0 : if(!(lock=lock_alloc_and_init(lockfile)))
250 : goto error;
251 0 : lock_get(lock);
252 0 : switch(lock->status)
253 : {
254 : case GET_LOCK_GOT:
255 : return lock;
256 : case GET_LOCK_NOT_GOT:
257 0 : logp("Could not get lockfile.\n");
258 0 : logp("Another process is probably running.\n");
259 0 : goto error;
260 : case GET_LOCK_ERROR:
261 : default:
262 0 : logp("Could not get lockfile.\n");
263 0 : logp("Maybe you do not have permissions to write to %s.\n", lockfile);
264 0 : goto error;
265 : }
266 : error:
267 0 : lock_free(&lock);
268 0 : return NULL;
269 : }
270 :
271 : #ifdef HAVE_WIN32
272 : #define main RealMain
273 : #endif
274 : #ifndef UTEST
275 : static
276 : #endif
277 0 : int real_main(int argc, char *argv[])
278 : {
279 0 : int ret=1;
280 0 : int option=0;
281 0 : int daemon=1;
282 0 : int forking=1;
283 0 : int strip=0;
284 0 : int randomise=0;
285 0 : struct lock *lock=NULL;
286 0 : struct conf **confs=NULL;
287 0 : int forceoverwrite=0;
288 0 : enum action act=ACTION_LIST;
289 0 : const char *backup=NULL;
290 0 : const char *backup2=NULL;
291 0 : char *restoreprefix=NULL;
292 0 : char *stripfrompath=NULL;
293 0 : const char *regex=NULL;
294 0 : const char *browsefile=NULL;
295 0 : char *browsedir=NULL;
296 0 : const char *conffile=config_default_path();
297 0 : const char *orig_client=NULL;
298 0 : const char *logfile=NULL;
299 : // The orig_client is the original client that the normal client
300 : // would like to restore from.
301 : #ifndef HAVE_WIN32
302 0 : int generate_ca_only=0;
303 : #endif
304 0 : int vss_restore=1;
305 0 : int test_confs=0;
306 : enum burp_mode mode;
307 0 : struct strlist *cli_overrides=NULL;
308 :
309 0 : log_init(argv[0]);
310 : #ifndef HAVE_WIN32
311 0 : if(!strcmp(prog, "bedup"))
312 0 : return run_bedup(argc, argv);
313 0 : if(!strcmp(prog, "bsigs"))
314 0 : return run_bsigs(argc, argv);
315 0 : if(!strcmp(prog, "bsparse"))
316 0 : return run_bsparse(argc, argv);
317 : #endif
318 :
319 0 : while((option=getopt(argc, argv, "a:b:c:C:d:o:fFghijl:nq:Qr:s:tvVxz:?"))!=-1)
320 : {
321 0 : switch(option)
322 : {
323 : case 'a':
324 0 : if(parse_action(&act, optarg)) goto end;
325 : break;
326 : case 'b':
327 : // The diff command may have two backups
328 : // specified.
329 0 : if(!backup2 && backup) backup2=optarg;
330 0 : if(!backup) backup=optarg;
331 : break;
332 : case 'c':
333 0 : conffile=optarg;
334 0 : break;
335 : case 'C':
336 0 : orig_client=optarg;
337 0 : break;
338 : case 'd':
339 0 : restoreprefix=optarg; // for restores
340 0 : browsedir=optarg; // for lists
341 0 : break;
342 : case 'f':
343 : forceoverwrite=1;
344 : break;
345 : case 'F':
346 0 : daemon=0;
347 0 : break;
348 : case 'g':
349 : #ifndef HAVE_WIN32
350 0 : generate_ca_only=1;
351 : #endif
352 0 : break;
353 : case 'i':
354 0 : cmd_print_all();
355 0 : ret=0;
356 0 : goto end;
357 : case 'l':
358 0 : logfile=optarg;
359 0 : break;
360 : case 'n':
361 0 : forking=0;
362 0 : break;
363 : case 'o':
364 0 : strlist_add(&cli_overrides, optarg, 0);
365 0 : break;
366 : case 'q':
367 0 : randomise=atoi(optarg);
368 0 : break;
369 : case 'Q':
370 0 : strlist_add(&cli_overrides, "progress_counter=0", 0);
371 0 : strlist_add(&cli_overrides, "stdout=0", 0);
372 0 : break;
373 : case 'r':
374 0 : regex=optarg;
375 0 : break;
376 : case 's':
377 0 : strip=atoi(optarg);
378 0 : break;
379 : case 'v':
380 0 : strlist_add(&cli_overrides, "stdout=1", 0);
381 0 : break;
382 : case 'V':
383 0 : printf("%s-%s\n", progname(), PACKAGE_VERSION);
384 0 : ret=0;
385 0 : goto end;
386 : case 'x':
387 0 : vss_restore=0;
388 0 : break;
389 : case 't':
390 0 : test_confs=1;
391 0 : break;
392 : case 'z':
393 0 : browsefile=optarg;
394 0 : break;
395 : case 'h':
396 : case '?':
397 : default:
398 : usage();
399 : goto end;
400 : }
401 : }
402 0 : if(optind<argc)
403 : {
404 : usage();
405 : goto end;
406 : }
407 :
408 0 : if(act==ACTION_MONITOR)
409 : {
410 : // Try to output everything in JSON.
411 0 : log_set_json(1);
412 : // Need to do this so that processes reading stdout get the
413 : // result of the printfs of logp straight away.
414 0 : setvbuf(stdout, NULL, _IONBF, 0);
415 : }
416 :
417 0 : conf_set_cli_overrides(cli_overrides);
418 0 : if(!(confs=confs_alloc()))
419 : goto end;
420 :
421 0 : if(reload(confs, conffile, 1))
422 : goto end;
423 :
424 : // Dry run to test config file syntax.
425 0 : if(test_confs)
426 : {
427 0 : ret=run_test_confs(confs, orig_client);
428 0 : goto end;
429 : }
430 :
431 0 : if(!backup) switch(act)
432 : {
433 : case ACTION_DELETE:
434 0 : logp("No backup specified for deletion.\n");
435 0 : goto end;
436 : case ACTION_RESTORE:
437 : case ACTION_VERIFY:
438 : case ACTION_DIFF:
439 : case ACTION_DIFF_LONG:
440 0 : logp("No backup specified. Using the most recent.\n");
441 0 : backup="0";
442 : default:
443 : break;
444 : }
445 0 : if(!backup2) switch(act)
446 : {
447 : case ACTION_DIFF:
448 : case ACTION_DIFF_LONG:
449 0 : logp("No second backup specified. Using file system scan.\n");
450 0 : backup2="n"; // For 'next'.
451 : default:
452 : break;
453 : }
454 :
455 : // The logfile option is only used for the status client stuff.
456 0 : if(logfile
457 0 : && (act!=ACTION_STATUS
458 0 : && act!=ACTION_STATUS_SNAPSHOT))
459 0 : logp("-l <logfile> option obsoleted\n");
460 :
461 0 : if(orig_client
462 0 : && *orig_client
463 0 : && set_string(confs[OPT_ORIG_CLIENT], orig_client))
464 : goto end;
465 :
466 : // The random delay needs to happen before the lock is got, otherwise
467 : // you would never be able to use burp by hand.
468 0 : if(randomise) set_int(confs[OPT_RANDOMISE], randomise);
469 0 : mode=get_e_burp_mode(confs[OPT_BURP_MODE]);
470 0 : if(mode==BURP_MODE_CLIENT
471 0 : && (act==ACTION_BACKUP_TIMED || act==ACTION_TIMER_CHECK))
472 0 : random_delay(confs);
473 :
474 0 : if(mode==BURP_MODE_SERVER)
475 : {
476 0 : switch(act)
477 : {
478 : case ACTION_CHAMP_CHOOSER:
479 : // Need to run without getting the lock.
480 : break;
481 : default:
482 0 : if(!(lock=get_prog_lock(confs)))
483 : goto end;
484 : break;
485 : }
486 : }
487 0 : else if(mode==BURP_MODE_CLIENT)
488 : {
489 0 : switch(act)
490 : {
491 : case ACTION_BACKUP:
492 : case ACTION_BACKUP_TIMED:
493 : case ACTION_TIMER_CHECK:
494 : // Need to get the lock.
495 0 : if(!(lock=get_prog_lock(confs)))
496 : goto end;
497 : break;
498 : default:
499 : break;
500 : }
501 : }
502 :
503 : // Change privileges after having got the lock, for convenience.
504 0 : if(chuser_and_or_chgrp(
505 0 : get_string(confs[OPT_USER]), get_string(confs[OPT_GROUP])))
506 : return -1;
507 :
508 0 : set_int(confs[OPT_OVERWRITE], forceoverwrite);
509 0 : set_int(confs[OPT_STRIP], strip);
510 0 : set_int(confs[OPT_FORK], forking);
511 0 : set_int(confs[OPT_DAEMON], daemon);
512 :
513 0 : strip_trailing_slashes(&restoreprefix);
514 0 : strip_trailing_slashes(&browsedir);
515 0 : if(replace_conf_str(confs[OPT_BACKUP], backup)
516 0 : || replace_conf_str(confs[OPT_BACKUP2], backup2)
517 0 : || replace_conf_str(confs[OPT_RESTOREPREFIX], restoreprefix)
518 0 : || replace_conf_str(confs[OPT_STRIP_FROM_PATH], stripfrompath)
519 0 : || replace_conf_str(confs[OPT_REGEX], regex)
520 0 : || replace_conf_str(confs[OPT_BROWSEFILE], browsefile)
521 0 : || replace_conf_str(confs[OPT_BROWSEDIR], browsedir)
522 0 : || replace_conf_str(confs[OPT_MONITOR_LOGFILE], logfile))
523 : goto end;
524 :
525 0 : base64_init();
526 0 : hexmap_init();
527 :
528 0 : if(mode==BURP_MODE_SERVER)
529 : {
530 : #ifdef HAVE_WIN32
531 : logp("Sorry, server mode is not implemented for Windows.\n");
532 : #else
533 0 : ret=server_modes(act,
534 : conffile, lock, generate_ca_only, confs);
535 : #endif
536 : }
537 : else
538 : {
539 0 : ret=client(confs, act, vss_restore);
540 : }
541 :
542 : end:
543 0 : lock_release(lock);
544 0 : lock_free(&lock);
545 0 : confs_free(&confs);
546 0 : strlists_free(&cli_overrides);
547 0 : return ret;
548 : }
549 :
550 : #ifndef UTEST
551 : int main(int argc, char *argv[])
552 : {
553 : return real_main(argc, argv);
554 : }
555 : #endif
|