1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
5 Copyright (C) 2011-2012 Planets Communications B.V.
6 Copyright (C) 2013-2020 Bareos GmbH & Co. KG
7
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
11 in the file LICENSE.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, USA.
22 */
23 /*
24 * Kern Sibbald, MM
25 */
26 /**
27 * @file
28 * Second generation Storage daemon.
29 *
30 * It accepts a number of simple commands from the File daemon
31 * and acts on them. When a request to append data is made,
32 * it opens a data channel and accepts data from the
33 * File daemon.
34 */
35
36 #include "include/bareos.h"
37 #include "stored/stored.h"
38 #include "lib/crypto_cache.h"
39 #include "stored/acquire.h"
40 #include "stored/autochanger.h"
41 #include "stored/bsr.h"
42 #include "stored/device.h"
43 #include "stored/jcr_private.h"
44 #include "stored/job.h"
45 #include "stored/label.h"
46 #include "stored/ndmp_tape.h"
47 #include "stored/sd_backends.h"
48 #include "stored/sd_stats.h"
49 #include "stored/socket_server.h"
50 #include "stored/stored_globals.h"
51 #include "stored/wait.h"
52 #include "lib/berrno.h"
53 #include "lib/bsock.h"
54 #include "lib/bnet_network_dump.h"
55 #include "lib/daemon.h"
56 #include "lib/bsignal.h"
57 #include "lib/parse_conf.h"
58 #include "lib/thread_specific_data.h"
59 #include "lib/util.h"
60 #include "lib/watchdog.h"
61 #include "include/jcr.h"
62
63
64 namespace storagedaemon {
65 extern bool ParseSdConfig(const char* configfile, int exit_code);
66 }
67
68 using namespace storagedaemon;
69
70 /* Imported functions */
71 extern void PrintMessage(void* sock, const char* fmt, ...);
72
73 /* Forward referenced functions */
74 namespace storagedaemon {
75 #if !defined(HAVE_WIN32)
76 static
77 #endif
78 void
79 TerminateStored(int sig);
80 } // namespace storagedaemon
81 static int CheckResources();
82 static void CleanUpOldFiles();
83
84 extern "C" void* device_initialization(void* arg);
85
86 /* Global static variables */
87 static bool foreground = 0;
88
usage()89 static void usage()
90 {
91 kBareosVersionStrings.PrintCopyrightWithFsfAndPlanets(stderr, 2000);
92 fprintf(
93 stderr,
94 _("Usage: bareos-sd [options]\n"
95 " -c <path> use <path> as configuration file or directory\n"
96 " -d <nn> set debug level to <nn>\n"
97 " -dt print timestamp in debug output\n"
98 " -f run in foreground (for debugging)\n"
99 " -g <group> run as group <group>\n"
100 " -m print kaboom output (for debugging)\n"
101 " -p proceed despite I/O errors\n"
102 " -s no signals (for debugging)\n"
103 " -t test - read configuration and exit\n"
104 " -u <user> run as user <user>\n"
105 " -v verbose user messages\n"
106 " -xc print configuration and exit\n"
107 " -xs print configuration file schema in JSON format "
108 "and exit\n"
109 " -? print this message.\n"
110 "\n"));
111 exit(1);
112 }
113
114 /*********************************************************************
115 *
116 * Main Bareos Storage Daemon
117 *
118 */
119 #if defined(HAVE_WIN32)
120 #define main BareosMain
121 #endif
122
main(int argc,char * argv[])123 int main(int argc, char* argv[])
124 {
125 int ch;
126 bool no_signals = false;
127 bool test_config = false;
128 bool export_config = false;
129 bool export_config_schema = false;
130 pthread_t thid;
131 char* uid = NULL;
132 char* gid = NULL;
133
134 setlocale(LC_ALL, "");
135 tzset();
136 bindtextdomain("bareos", LOCALEDIR);
137 textdomain("bareos");
138
139 InitStackDump();
140 MyNameIs(argc, argv, "bareos-sd");
141 InitMsg(NULL, NULL);
142 daemon_start_time = time(NULL);
143
144 /*
145 * Sanity checks
146 */
147 if (TAPE_BSIZE % B_DEV_BSIZE != 0 || TAPE_BSIZE / B_DEV_BSIZE == 0) {
148 Emsg2(M_ABORT, 0,
149 _("Tape block size (%d) not multiple of system size (%d)\n"),
150 TAPE_BSIZE, B_DEV_BSIZE);
151 }
152 if (TAPE_BSIZE != (1 << (ffs(TAPE_BSIZE) - 1))) {
153 Emsg1(M_ABORT, 0, _("Tape block size (%d) is not a power of 2\n"),
154 TAPE_BSIZE);
155 }
156
157 while ((ch = getopt(argc, argv, "c:d:fg:mpstu:vx:z:?")) != -1) {
158 switch (ch) {
159 case 'c': /* configuration file */
160 if (configfile != NULL) { free(configfile); }
161 configfile = strdup(optarg);
162 break;
163
164 case 'd': /* debug level */
165 if (*optarg == 't') {
166 dbg_timestamp = true;
167 } else {
168 debug_level = atoi(optarg);
169 if (debug_level <= 0) { debug_level = 1; }
170 }
171 break;
172
173 case 'f': /* run in foreground */
174 foreground = true;
175 break;
176
177 case 'g': /* set group id */
178 gid = optarg;
179 break;
180
181 case 'm': /* print kaboom output */
182 prt_kaboom = true;
183 break;
184
185 case 'p': /* proceed in spite of I/O errors */
186 forge_on = true;
187 break;
188
189 case 's': /* no signals */
190 no_signals = true;
191 break;
192
193 case 't':
194 test_config = true;
195 break;
196
197 case 'u': /* set uid */
198 uid = optarg;
199 break;
200
201 case 'v': /* verbose */
202 verbose++;
203 break;
204
205 case 'x': /* export configuration/schema and exit */
206 if (*optarg == 's') {
207 export_config_schema = true;
208 } else if (*optarg == 'c') {
209 export_config = true;
210 } else {
211 usage();
212 }
213 break;
214
215 case 'z': /* switch network debugging on */
216 if (!BnetDump::EvaluateCommandLineArgs(optarg)) { exit(1); }
217 break;
218
219 case '?':
220 default:
221 usage();
222 break;
223 }
224 }
225 argc -= optind;
226 argv += optind;
227
228 if (!no_signals) { InitSignals(TerminateStored); }
229
230 if (argc) {
231 if (configfile != NULL) { free(configfile); }
232 configfile = strdup(*argv);
233 argc--;
234 argv++;
235 }
236 if (argc) { usage(); }
237
238 /*
239 * See if we want to drop privs.
240 */
241 if (geteuid() == 0) { drop(uid, gid, false); }
242
243 if (export_config_schema) {
244 PoolMem buffer;
245
246 my_config = InitSdConfig(configfile, M_ERROR_TERM);
247 PrintConfigSchemaJson(buffer);
248 printf("%s\n", buffer.c_str());
249 goto bail_out;
250 }
251
252 my_config = InitSdConfig(configfile, M_ERROR_TERM);
253 ParseSdConfig(configfile, M_ERROR_TERM);
254
255 if (export_config) {
256 my_config->DumpResources(PrintMessage, NULL);
257 goto bail_out;
258 }
259
260 if (!foreground && !test_config) {
261 daemon_start(); /* become daemon */
262 InitStackDump(); /* pick up new pid */
263 }
264
265 if (InitCrypto() != 0) {
266 Jmsg((JobControlRecord*)NULL, M_ERROR_TERM, 0,
267 _("Cryptography library initialization failed.\n"));
268 }
269
270 if (!CheckResources()) {
271 Jmsg((JobControlRecord*)NULL, M_ERROR_TERM, 0,
272 _("Please correct the configuration in %s\n"),
273 my_config->get_base_config_path().c_str());
274 }
275
276 InitReservationsLock();
277
278 if (test_config) { TerminateStored(0); }
279
280 MyNameIs(0, (char**)NULL, me->resource_name_); /* Set our real name */
281
282 CreatePidFile(me->pid_directory, "bareos-sd",
283 GetFirstPortHostOrder(me->SDaddrs));
284 ReadStateFile(me->working_directory, "bareos-sd",
285 GetFirstPortHostOrder(me->SDaddrs));
286 ReadCryptoCache(me->working_directory, "bareos-sd",
287 GetFirstPortHostOrder(me->SDaddrs));
288
289 SetJcrInThreadSpecificData(nullptr);
290
291 /*
292 * Make sure on Solaris we can run concurrent, watch dog + servers + misc
293 */
294 SetThreadConcurrency(me->MaxConcurrentJobs * 2 + 4);
295
296 LoadSdPlugins(me->plugin_directory, me->plugin_names);
297
298 CleanUpOldFiles();
299
300 /* Ensure that Volume Session Time and Id are both
301 * set and are both non-zero.
302 */
303 vol_session_time = (uint32_t)daemon_start_time;
304 if (vol_session_time == 0) { /* paranoid */
305 Jmsg0(NULL, M_ABORT, 0, _("Volume Session Time is ZERO!\n"));
306 }
307
308 /*
309 * Start the device allocation thread
310 */
311 CreateVolumeLists(); /* do before device_init */
312 if (pthread_create(&thid, NULL, device_initialization, NULL) != 0) {
313 BErrNo be;
314 Emsg1(M_ABORT, 0, _("Unable to create thread. ERR=%s\n"), be.bstrerror());
315 }
316
317 InitJcrChain();
318 StartWatchdog(); /* start watchdog thread */
319 if (me->jcr_watchdog_time) {
320 InitJcrSubsystem(
321 me->jcr_watchdog_time); /* start JobControlRecord watchdogs etc. */
322 }
323
324 StartStatisticsThread();
325
326 #if HAVE_NDMP
327 /*
328 * Separate thread that handles NDMP connections
329 */
330 if (me->ndmp_enable) {
331 StartNdmpThreadServer(me->NDMPaddrs, me->MaxConnections);
332 }
333 #endif
334
335 /*
336 * Single server used for Director/Storage and File daemon
337 */
338 StartSocketServer(me->SDaddrs);
339
340 /* to keep compiler quiet */
341 TerminateStored(0);
342
343 bail_out:
344 return 0;
345 }
346
347 /* Check Configuration file for necessary info */
CheckResources()348 static int CheckResources()
349 {
350 bool OK = true;
351 const std::string& configfile = my_config->get_base_config_path();
352
353 if (my_config->GetNextRes(R_STORAGE, (BareosResource*)me) != NULL) {
354 Jmsg1(NULL, M_ERROR, 0, _("Only one Storage resource permitted in %s\n"),
355 configfile.c_str());
356 OK = false;
357 }
358
359 if (my_config->GetNextRes(R_DIRECTOR, NULL) == NULL) {
360 Jmsg1(NULL, M_ERROR, 0,
361 _("No Director resource defined in %s. Cannot continue.\n"),
362 configfile.c_str());
363 OK = false;
364 }
365
366 if (my_config->GetNextRes(R_DEVICE, NULL) == NULL) {
367 Jmsg1(NULL, M_ERROR, 0,
368 _("No Device resource defined in %s. Cannot continue.\n"),
369 configfile.c_str());
370 OK = false;
371 }
372
373 /*
374 * Sanity check.
375 */
376 if (me->MaxConnections < ((2 * me->MaxConcurrentJobs) + 2)) {
377 me->MaxConnections = (2 * me->MaxConcurrentJobs) + 2;
378 }
379
380 if (!me->messages) {
381 me->messages = (MessagesResource*)my_config->GetNextRes(R_MSGS, NULL);
382 if (!me->messages) {
383 Jmsg1(NULL, M_ERROR, 0,
384 _("No Messages resource defined in %s. Cannot continue.\n"),
385 configfile.c_str());
386 OK = false;
387 }
388 }
389
390 if (!me->working_directory) {
391 Jmsg1(NULL, M_ERROR, 0,
392 _("No Working Directory defined in %s. Cannot continue.\n"),
393 configfile.c_str());
394 OK = false;
395 }
396
397 StorageResource* store = me;
398 if (store->IsTlsConfigured()) {
399 if (!have_tls) {
400 Jmsg(NULL, M_FATAL, 0, _("TLS required but not compiled into Bareos.\n"));
401 OK = false;
402 }
403 }
404
405 DeviceResource* device;
406 foreach_res (device, R_DEVICE) {
407 if (device->drive_crypto_enabled && BitIsSet(CAP_LABEL, device->cap_bits)) {
408 Jmsg(NULL, M_FATAL, 0,
409 _("LabelMedia enabled is incompatible with tape crypto on Device "
410 "\"%s\" in %s.\n"),
411 device->resource_name_, configfile.c_str());
412 OK = false;
413 }
414 }
415
416 if (OK) { OK = InitAutochangers(); }
417
418 if (OK) {
419 CloseMsg(NULL); /* close temp message handler */
420 InitMsg(NULL, me->messages); /* open daemon message handler */
421 SetWorkingDirectory(me->working_directory);
422 if (me->secure_erase_cmdline) {
423 SetSecureEraseCmdline(me->secure_erase_cmdline);
424 }
425 if (me->log_timestamp_format) {
426 SetLogTimestampFormat(me->log_timestamp_format);
427 }
428 }
429
430 return OK;
431 }
432
433 /**
434 * Remove old .spool files written by me from the working directory.
435 */
CleanUpOldFiles()436 static void CleanUpOldFiles()
437 {
438 DIR* dp;
439 struct dirent* result;
440 #ifdef USE_READDIR_R
441 struct dirent* entry;
442 #endif
443 int rc, name_max;
444 int my_name_len = strlen(my_name);
445 int len = strlen(me->working_directory);
446 POOLMEM* cleanup = GetPoolMemory(PM_MESSAGE);
447 POOLMEM* basename = GetPoolMemory(PM_MESSAGE);
448 regex_t preg1{};
449 char prbuf[500];
450 BErrNo be;
451
452 /* Look for .spool files but don't allow spaces */
453 const char* pat1 = "^[^ ]+\\.spool$";
454
455 /* Setup working directory prefix */
456 PmStrcpy(basename, me->working_directory);
457 if (len > 0 && !IsPathSeparator(me->working_directory[len - 1])) {
458 PmStrcat(basename, "/");
459 }
460
461 /* Compile regex expressions */
462 rc = regcomp(&preg1, pat1, REG_EXTENDED);
463 if (rc != 0) {
464 regerror(rc, &preg1, prbuf, sizeof(prbuf));
465 Pmsg2(000, _("Could not compile regex pattern \"%s\" ERR=%s\n"), pat1,
466 prbuf);
467 goto get_out2;
468 }
469
470 name_max = pathconf(".", _PC_NAME_MAX);
471 if (name_max < 1024) { name_max = 1024; }
472
473 if (!(dp = opendir(me->working_directory))) {
474 BErrNo be;
475 Pmsg2(000, "Failed to open working dir %s for cleanup: ERR=%s\n",
476 me->working_directory, be.bstrerror());
477 goto get_out1;
478 }
479
480 #ifdef USE_READDIR_R
481 entry = (struct dirent*)malloc(sizeof(struct dirent) + name_max + 1000);
482 while (1) {
483 if ((Readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
484 #else
485 while (1) {
486 result = readdir(dp);
487 if (result == NULL) {
488 #endif
489 break;
490 }
491
492 /* Exclude any name with ., .., not my_name or containing a space */
493 if (strcmp(result->d_name, ".") == 0 || strcmp(result->d_name, "..") == 0 ||
494 strncmp(result->d_name, my_name, my_name_len) != 0) {
495 Dmsg1(500, "Skipped: %s\n", result->d_name);
496 continue;
497 }
498
499 /* Unlink files that match regex */
500 if (regexec(&preg1, result->d_name, 0, NULL, 0) == 0) {
501 PmStrcpy(cleanup, basename);
502 PmStrcat(cleanup, result->d_name);
503 Dmsg1(500, "Unlink: %s\n", cleanup);
504 SecureErase(NULL, cleanup);
505 }
506 }
507 #ifdef USE_READDIR_R
508 free(entry);
509 #endif
510 closedir(dp);
511
512 get_out1:
513 regfree(&preg1);
514 get_out2:
515 FreePoolMemory(cleanup);
516 FreePoolMemory(basename);
517 }
518
519
520 /**
521 * Here we attempt to init and open each device. This is done once at startup in
522 * a separate thread.
523 */
524 extern "C" void* device_initialization(void* arg)
525 {
526 DeviceResource* device;
527 DeviceControlRecord* dcr;
528 JobControlRecord* jcr;
529 Device* dev;
530 int errstat;
531
532 LockRes(my_config);
533
534 pthread_detach(pthread_self());
535 jcr = NewStoredJcr();
536 NewPlugins(jcr); /* instantiate plugins */
537 jcr->setJobType(JT_SYSTEM);
538
539 /*
540 * Initialize job start condition variable
541 */
542 errstat = pthread_cond_init(&jcr->impl->job_start_wait, NULL);
543 if (errstat != 0) {
544 BErrNo be;
545 Jmsg1(jcr, M_ABORT, 0,
546 _("Unable to init job start cond variable: ERR=%s\n"),
547 be.bstrerror(errstat));
548 }
549
550 /*
551 * Initialize job end condition variable
552 */
553 errstat = pthread_cond_init(&jcr->impl->job_end_wait, NULL);
554 if (errstat != 0) {
555 BErrNo be;
556 Jmsg1(jcr, M_ABORT, 0,
557 _("Unable to init job endstart cond variable: ERR=%s\n"),
558 be.bstrerror(errstat));
559 }
560
561 foreach_res (device, R_DEVICE) {
562 Dmsg1(90, "calling InitDev %s\n", device->device_name);
563 dev = InitDev(NULL, device);
564 Dmsg1(10, "SD init done %s\n", device->device_name);
565 if (!dev) {
566 Jmsg1(NULL, M_ERROR, 0, _("Could not initialize %s\n"),
567 device->device_name);
568 continue;
569 }
570
571 dcr = new StorageDaemonDeviceControlRecord;
572 jcr->impl->dcr = dcr;
573 SetupNewDcrDevice(jcr, dcr, dev, NULL);
574 jcr->impl->dcr->SetWillWrite();
575 GeneratePluginEvent(jcr, bsdEventDeviceInit, dcr);
576 if (dev->IsAutochanger()) {
577 /*
578 * If autochanger set slot in dev structure
579 */
580 GetAutochangerLoadedSlot(dcr);
581 }
582
583 if (BitIsSet(CAP_ALWAYSOPEN, device->cap_bits)) {
584 Dmsg1(20, "calling FirstOpenDevice %s\n", dev->print_name());
585 if (!FirstOpenDevice(dcr)) {
586 Jmsg1(NULL, M_ERROR, 0, _("Could not open device %s\n"),
587 dev->print_name());
588 Dmsg1(20, "Could not open device %s\n", dev->print_name());
589 FreeDeviceControlRecord(dcr);
590 jcr->impl->dcr = NULL;
591 continue;
592 }
593 }
594
595 if (BitIsSet(CAP_AUTOMOUNT, device->cap_bits) && dev->IsOpen()) {
596 switch (ReadDevVolumeLabel(dcr)) {
597 case VOL_OK:
598 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
599 VolumeUnused(dcr); /* mark volume "released" */
600 break;
601 default:
602 Jmsg1(NULL, M_WARNING, 0, _("Could not mount device %s\n"),
603 dev->print_name());
604 break;
605 }
606 }
607 FreeDeviceControlRecord(dcr);
608 jcr->impl->dcr = NULL;
609 }
610 FreeJcr(jcr);
611 init_done = true;
612 UnlockRes(my_config);
613 return NULL;
614 }
615
616 /**
617 * Clean up and then exit
618 */
619 namespace storagedaemon {
620
621 #if !defined(HAVE_WIN32)
622 static
623 #endif
624 void
625 TerminateStored(int sig)
626 {
627 static bool in_here = false;
628 DeviceResource* device;
629 JobControlRecord* jcr;
630
631 if (in_here) { /* prevent loops */
632 Bmicrosleep(2, 0); /* yield */
633 exit(1);
634 }
635 in_here = true;
636 debug_level = 0; /* turn off any debug */
637 StopStatisticsThread();
638 #if HAVE_NDMP
639 if (me->ndmp_enable) { StopNdmpThreadServer(); }
640 #endif
641 StopSocketServer();
642
643 StopWatchdog();
644
645 if (sig == SIGTERM) { /* normal shutdown request? */
646 /*
647 * This is a normal shutdown request. We wiffle through
648 * all open jobs canceling them and trying to wake
649 * them up so that they will report back the correct
650 * volume status.
651 */
652 foreach_jcr (jcr) {
653 BareosSocket* fd;
654 if (jcr->JobId == 0) { continue; /* ignore console */ }
655 jcr->setJobStatus(JS_Canceled);
656 fd = jcr->file_bsock;
657 if (fd) {
658 fd->SetTimedOut();
659 jcr->MyThreadSendSignal(TIMEOUT_SIGNAL);
660 Dmsg1(100, "term_stored killing JobId=%d\n", jcr->JobId);
661 /* ***FIXME*** wiffle through all dcrs */
662 if (jcr->impl->dcr && jcr->impl->dcr->dev &&
663 jcr->impl->dcr->dev->blocked()) {
664 pthread_cond_broadcast(&jcr->impl->dcr->dev->wait_next_vol);
665 Dmsg1(100, "JobId=%u broadcast wait_device_release\n",
666 (uint32_t)jcr->JobId);
667 ReleaseDeviceCond();
668 }
669 if (jcr->impl->read_dcr && jcr->impl->read_dcr->dev &&
670 jcr->impl->read_dcr->dev->blocked()) {
671 pthread_cond_broadcast(&jcr->impl->read_dcr->dev->wait_next_vol);
672 Dmsg1(100, "JobId=%u broadcast wait_device_release\n",
673 (uint32_t)jcr->JobId);
674 ReleaseDeviceCond();
675 }
676 Bmicrosleep(0, 50000);
677 }
678 FreeJcr(jcr);
679 }
680 Bmicrosleep(0, 500000); /* give them 1/2 sec to clean up */
681 }
682
683 WriteStateFile(me->working_directory, "bareos-sd",
684 GetFirstPortHostOrder(me->SDaddrs));
685 DeletePidFile(me->pid_directory, "bareos-sd",
686 GetFirstPortHostOrder(me->SDaddrs));
687
688 Dmsg1(200, "In TerminateStored() sig=%d\n", sig);
689
690 UnloadSdPlugins();
691 FlushCryptoCache();
692 FreeVolumeLists();
693
694 foreach_res (device, R_DEVICE) {
695 Dmsg1(10, "Term device %s\n", device->device_name);
696 if (device->dev) {
697 device->dev->ClearVolhdr();
698 device->dev->term();
699 device->dev = NULL;
700 } else {
701 Dmsg1(10, "No dev structure %s\n", device->device_name);
702 }
703 }
704
705 #if defined(HAVE_DYNAMIC_SD_BACKENDS)
706 DevFlushBackends();
707 #endif
708
709 if (configfile) {
710 free(configfile);
711 configfile = NULL;
712 }
713 if (my_config) {
714 delete my_config;
715 my_config = NULL;
716 }
717
718 if (debug_level > 10) { PrintMemoryPoolStats(); }
719 TermMsg();
720 CleanupCrypto();
721 TermReservationsLock();
722 CloseMemoryPool();
723
724 exit(sig);
725 }
726
727 } /* namespace storagedaemon */
728