]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/stored.c
Complete port to Windows
[bacula/bacula] / bacula / src / stored / stored.c
1 /*
2  * Second generation Storage daemon.
3  *
4  * It accepts a number of simple commands from the File daemon
5  * and acts on them. When a request to append data is made,
6  * it opens a data channel and accepts data from the
7  * File daemon.
8  *
9  *   Version $Id$
10  *
11  */
12 /*
13    Copyright (C) 2000-2006 Kern Sibbald
14
15    This program is free software; you can redistribute it and/or
16    modify it under the terms of the GNU General Public License
17    version 2 as amended with additional clauses defined in the
18    file LICENSE in the main source directory.
19
20    This program is distributed in the hope that it will be useful,
21    but WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
23    the file LICENSE for additional details.
24
25  */
26
27 #include "bacula.h"
28 #include "stored.h"
29
30 /* Imported functions */
31
32
33 /* Forward referenced functions */
34 void terminate_stored(int sig);
35 static int check_resources();
36 static void cleanup_old_files();
37
38 extern "C" void *device_initialization(void *arg);
39
40 #define CONFIG_FILE "bacula-sd.conf"  /* Default config file */
41
42 /* Global variables exported */
43 char OK_msg[]   = "3000 OK\n";
44 char TERM_msg[] = "3999 Terminate\n";
45 STORES *me = NULL;                    /* our Global resource */
46 bool forge_on = false;                /* proceed inspite of I/O errors */
47 pthread_mutex_t device_release_mutex = PTHREAD_MUTEX_INITIALIZER;
48 pthread_cond_t wait_device_release = PTHREAD_COND_INITIALIZER;
49
50
51 static uint32_t VolSessionId = 0;
52 uint32_t VolSessionTime;
53 char *configfile = NULL;
54 bool init_done = false;
55
56 /* Global static variables */
57 static bool foreground = 0;
58 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
59 static workq_t dird_workq;            /* queue for processing connections */
60
61
62 static void usage()
63 {
64    fprintf(stderr, _(
65 "Copyright (C) 2000-2005 Kern Sibbald.\n"
66 "\nVersion: %s (%s)\n\n"
67 "Usage: stored [options] [-c config_file] [config_file]\n"
68 "        -c <file>   use <file> as configuration file\n"
69 "        -dnn        set debug level to nn\n"
70 "        -f          run in foreground (for debugging)\n"
71 "        -g <group>  set groupid to group\n"
72 "        -p          proceed despite I/O errors\n"
73 "        -s          no signals (for debugging)\n"
74 "        -t          test - read config and exit\n"
75 "        -u <user>   userid to <user>\n"
76 "        -v          verbose user messages\n"
77 "        -?          print this message.\n"
78 "\n"), VERSION, BDATE);
79    exit(1);
80 }
81
82 /*********************************************************************
83  *
84  *  Main Bacula Unix Storage Daemon
85  *
86  */
87 #if defined(HAVE_WIN32)
88 #define main BaculaMain
89 #endif
90
91 int main (int argc, char *argv[])
92 {
93    int ch;
94    bool no_signals = false;
95    bool test_config = false;
96    pthread_t thid;
97    char *uid = NULL;
98    char *gid = NULL;
99
100    setlocale(LC_ALL, "");
101    bindtextdomain("bacula", LOCALEDIR);
102    textdomain("bacula");
103
104    init_stack_dump();
105    my_name_is(argc, argv, "bacula-sd");
106    init_msg(NULL, NULL);
107    daemon_start_time = time(NULL);
108
109    /* Sanity checks */
110    if (TAPE_BSIZE % B_DEV_BSIZE != 0 || TAPE_BSIZE / B_DEV_BSIZE == 0) {
111       Emsg2(M_ABORT, 0, _("Tape block size (%d) not multiple of system size (%d)\n"),
112          TAPE_BSIZE, B_DEV_BSIZE);
113    }
114    if (TAPE_BSIZE != (1 << (ffs(TAPE_BSIZE)-1))) {
115       Emsg1(M_ABORT, 0, _("Tape block size (%d) is not a power of 2\n"), TAPE_BSIZE);
116    }
117
118    while ((ch = getopt(argc, argv, "c:d:fg:pstu:v?")) != -1) {
119       switch (ch) {
120       case 'c':                    /* configuration file */
121          if (configfile != NULL) {
122             free(configfile);
123          }
124          configfile = bstrdup(optarg);
125          break;
126
127       case 'd':                    /* debug level */
128          debug_level = atoi(optarg);
129          if (debug_level <= 0) {
130             debug_level = 1;
131          }
132          break;
133
134       case 'f':                    /* run in foreground */
135          foreground = true;
136          break;
137
138       case 'g':                    /* set group id */
139          gid = optarg;
140          break;
141
142       case 'p':                    /* proceed in spite of I/O errors */
143          forge_on = true;
144          break;
145
146       case 's':                    /* no signals */
147          no_signals = true;
148          break;
149
150       case 't':
151          test_config = true;
152          break;
153
154       case 'u':                    /* set uid */
155          uid = optarg;
156          break;
157
158       case 'v':                    /* verbose */
159          verbose++;
160          break;
161
162       case '?':
163       default:
164          usage();
165          break;
166       }
167    }
168    argc -= optind;
169    argv += optind;
170
171    if (argc) {
172       if (configfile != NULL) {
173          free(configfile);
174       }
175       configfile = bstrdup(*argv);
176       argc--;
177       argv++;
178    }
179    if (argc)
180       usage();
181
182    if (!no_signals) {
183       init_signals(terminate_stored);
184    }
185
186    if (configfile == NULL) {
187       configfile = bstrdup(CONFIG_FILE);
188    }
189
190    parse_config(configfile);
191
192    if (init_crypto() != 0) {
193       Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Cryptography library initialization failed.\n"));
194    }
195
196    if (!check_resources()) {
197       Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile);
198    }
199
200    init_reservations_lock();
201
202    if (test_config) {
203       terminate_stored(0);
204    }
205
206    my_name_is(0, (char **)NULL, me->hdr.name);     /* Set our real name */
207
208    if (!foreground) {
209       daemon_start();                 /* become daemon */
210       init_stack_dump();              /* pick up new pid */
211    }
212
213    create_pid_file(me->pid_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
214    read_state_file(me->working_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
215
216    drop(uid, gid);
217
218    cleanup_old_files();
219
220
221    /* Ensure that Volume Session Time and Id are both
222     * set and are both non-zero.
223     */
224    VolSessionTime = (uint32_t)daemon_start_time;
225    if (VolSessionTime == 0) { /* paranoid */
226       Jmsg0(NULL, M_ABORT, 0, _("Volume Session Time is ZERO!\n"));
227    }
228
229    init_python_interpreter(me->hdr.name, me->scripts_directory, "SDStartUp");
230
231    /* Make sure on Solaris we can run concurrent, watch dog + servers + misc */
232    set_thread_concurrency(me->max_concurrent_jobs * 2 + 4);
233
234     /*
235      * Start the device allocation thread
236      */
237    create_volume_list();              /* do before device_init */
238    if (pthread_create(&thid, NULL, device_initialization, NULL) != 0) {
239       Emsg1(M_ABORT, 0, _("Unable to create thread. ERR=%s\n"), strerror(errno));
240    }
241
242    start_watchdog();                  /* start watchdog thread */
243    init_jcr_subsystem();              /* start JCR watchdogs etc. */
244
245    /* Single server used for Director and File daemon */
246    bnet_thread_server(me->sdaddrs, me->max_concurrent_jobs * 2 + 1,
247                       &dird_workq, handle_connection_request);
248    exit(1);                           /* to keep compiler quiet */
249 }
250
251 /* Return a new Session Id */
252 uint32_t newVolSessionId()
253 {
254    uint32_t Id;
255
256    P(mutex);
257    VolSessionId++;
258    Id = VolSessionId;
259    V(mutex);
260    return Id;
261 }
262
263 /* Check Configuration file for necessary info */
264 static int check_resources()
265 {
266    bool OK = true;
267
268
269    me = (STORES *)GetNextRes(R_STORAGE, NULL);
270    if (!me) {
271       Jmsg1(NULL, M_ERROR, 0, _("No Storage resource defined in %s. Cannot continue.\n"),
272          configfile);
273       OK = false;
274    }
275
276    if (GetNextRes(R_STORAGE, (RES *)me) != NULL) {
277       Jmsg1(NULL, M_ERROR, 0, _("Only one Storage resource permitted in %s\n"),
278          configfile);
279       OK = false;
280    }
281    if (GetNextRes(R_DIRECTOR, NULL) == NULL) {
282       Jmsg1(NULL, M_ERROR, 0, _("No Director resource defined in %s. Cannot continue.\n"),
283          configfile);
284       OK = false;
285    }
286    if (GetNextRes(R_DEVICE, NULL) == NULL){
287       Jmsg1(NULL, M_ERROR, 0, _("No Device resource defined in %s. Cannot continue.\n"),
288            configfile);
289       OK = false;
290    }
291
292    if (!me->messages) {
293       me->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
294       if (!me->messages) {
295          Jmsg1(NULL, M_ERROR, 0, _("No Messages resource defined in %s. Cannot continue.\n"),
296             configfile);
297          OK = false;
298       }
299    }
300
301    if (!me->working_directory) {
302       Jmsg1(NULL, M_ERROR, 0, _("No Working Directory defined in %s. Cannot continue.\n"),
303          configfile);
304       OK = false;
305    }
306
307    DIRRES *director;
308    STORES *store;
309    foreach_res(store, R_STORAGE) { 
310       /* tls_require implies tls_enable */
311       if (store->tls_require) {
312          if (have_tls) {
313             store->tls_enable = true;
314          } else {
315             Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
316             OK = false;
317             continue;
318          }
319       }
320
321       if (!store->tls_certfile && store->tls_enable) {
322          Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Storage \"%s\" in %s.\n"),
323               store->hdr.name, configfile);
324          OK = false;
325       }
326
327       if (!store->tls_keyfile && store->tls_enable) {
328          Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Storage \"%s\" in %s.\n"),
329               store->hdr.name, configfile);
330          OK = false;
331       }
332
333       if ((!store->tls_ca_certfile && !store->tls_ca_certdir) && store->tls_enable && store->tls_verify_peer) {
334          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
335               " or \"TLS CA Certificate Dir\" are defined for Storage \"%s\" in %s."
336               " At least one CA certificate store is required"
337               " when using \"TLS Verify Peer\".\n"),
338               store->hdr.name, configfile);
339          OK = false;
340       }
341
342       /* If everything is well, attempt to initialize our per-resource TLS context */
343       if (OK && (store->tls_enable || store->tls_require)) {
344          /* Initialize TLS context:
345           * Args: CA certfile, CA certdir, Certfile, Keyfile,
346           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
347          store->tls_ctx = new_tls_context(store->tls_ca_certfile,
348             store->tls_ca_certdir, store->tls_certfile,
349             store->tls_keyfile, NULL, NULL, store->tls_dhfile,
350             store->tls_verify_peer);
351
352          if (!store->tls_ctx) { 
353             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Storage \"%s\" in %s.\n"),
354                  store->hdr.name, configfile);
355             OK = false;
356          }
357       }
358    }
359
360    foreach_res(director, R_DIRECTOR) { 
361       /* tls_require implies tls_enable */
362       if (director->tls_require) {
363          director->tls_enable = true;
364       }
365
366       if (!director->tls_certfile && director->tls_enable) {
367          Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Director \"%s\" in %s.\n"),
368               director->hdr.name, configfile);
369          OK = false;
370       }
371
372       if (!director->tls_keyfile && director->tls_enable) {
373          Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Director \"%s\" in %s.\n"),
374               director->hdr.name, configfile);
375          OK = false;
376       }
377
378       if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && director->tls_enable && director->tls_verify_peer) {
379          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
380               " or \"TLS CA Certificate Dir\" are defined for Director \"%s\" in %s."
381               " At least one CA certificate store is required"
382               " when using \"TLS Verify Peer\".\n"),
383               director->hdr.name, configfile);
384          OK = false;
385       }
386
387       /* If everything is well, attempt to initialize our per-resource TLS context */
388       if (OK && (director->tls_enable || director->tls_require)) {
389          /* Initialize TLS context:
390           * Args: CA certfile, CA certdir, Certfile, Keyfile,
391           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
392          director->tls_ctx = new_tls_context(director->tls_ca_certfile,
393             director->tls_ca_certdir, director->tls_certfile,
394             director->tls_keyfile, NULL, NULL, director->tls_dhfile,
395             director->tls_verify_peer);
396
397          if (!director->tls_ctx) { 
398             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Director \"%s\" in %s.\n"),
399                  director->hdr.name, configfile);
400             OK = false;
401          }
402       }
403    }
404
405    OK = init_autochangers();
406
407    
408    if (OK) {
409       close_msg(NULL);                   /* close temp message handler */
410       init_msg(NULL, me->messages);      /* open daemon message handler */
411       set_working_directory(me->working_directory);
412    }
413
414    return OK;
415 }
416
417 static void cleanup_old_files()
418 {
419    POOLMEM *cleanup = get_pool_memory(PM_MESSAGE);
420    int len = strlen(me->working_directory);
421    pm_strcpy(cleanup, "/bin/rm -f ");
422    pm_strcat(cleanup, me->working_directory);
423    if (len > 0 && me->working_directory[len-1] != '/') {
424       pm_strcat(cleanup, "/");
425    }
426    pm_strcat(cleanup, my_name);
427    pm_strcat(cleanup, "*.spool");
428    run_program(cleanup, 0, NULL);
429    free_pool_memory(cleanup);
430 }      
431
432
433 /*
434  * Here we attempt to init and open each device. This is done
435  *  once at startup in a separate thread.
436  */
437 extern "C"
438 void *device_initialization(void *arg)
439 {
440    DEVRES *device;
441    DCR *dcr;
442    JCR *jcr;
443    DEVICE *dev;
444
445    LockRes();
446
447    pthread_detach(pthread_self());
448    jcr = new_jcr(sizeof(JCR), stored_free_jcr);
449    jcr->JobType = JT_SYSTEM;
450    /* Initialize FD start condition variable */
451    int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
452    if (errstat != 0) {
453       Jmsg1(jcr, M_ABORT, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat));
454    }
455
456    foreach_res(device, R_DEVICE) {
457       Dmsg1(90, "calling init_dev %s\n", device->device_name);
458       dev = init_dev(NULL, device);
459       Dmsg1(10, "SD init done %s\n", device->device_name);
460       if (!dev) {
461          Jmsg1(NULL, M_ERROR, 0, _("Could not initialize %s\n"), device->device_name);
462          continue;
463       }
464
465       jcr->dcr = dcr = new_dcr(jcr, dev);
466       if (dev->is_autochanger()) {
467          /* If autochanger set slot in dev sturcture */
468          get_autochanger_loaded_slot(dcr);
469       }
470
471       if (device->cap_bits & CAP_ALWAYSOPEN) {
472          Dmsg1(20, "calling first_open_device %s\n", dev->print_name());
473          if (!first_open_device(dcr)) {
474             Jmsg1(NULL, M_ERROR, 0, _("Could not open device %s\n"), dev->print_name());
475             Dmsg1(20, "Could not open device %s\n", dev->print_name());
476             free_dcr(dcr);
477             jcr->dcr = NULL;
478             continue;
479          }
480       }
481       if (device->cap_bits & CAP_AUTOMOUNT && dev->is_open()) {
482          switch (read_dev_volume_label(dcr)) {
483          case VOL_OK:
484             memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
485             break;
486          default:
487             Jmsg1(NULL, M_WARNING, 0, _("Could not mount device %s\n"), dev->print_name());
488             break;
489          }
490       }
491       free_dcr(dcr);
492       jcr->dcr = NULL;
493    }
494    free_jcr(jcr); 
495    init_done = true;
496    UnlockRes();
497    return NULL;
498 }
499
500
501 /* Clean up and then exit */
502 void terminate_stored(int sig)
503 {
504    static bool in_here = false;
505    DEVRES *device;
506    JCR *jcr;
507
508    if (in_here) {                     /* prevent loops */
509       exit(1);
510    }
511    in_here = true;
512
513    if (sig == SIGTERM) {              /* normal shutdown request? */
514       /*
515        * This is a normal shutdown request. We wiffle through
516        *   all open jobs canceling them and trying to wake
517        *   them up so that they will report back the correct
518        *   volume status.
519        */
520       foreach_jcr(jcr) {
521          BSOCK *fd;
522          if (jcr->JobId == 0) {
523             free_jcr(jcr);
524             continue;                 /* ignore console */
525          }
526          set_jcr_job_status(jcr, JS_Canceled);
527          fd = jcr->file_bsock;
528          if (fd) {
529             fd->timed_out = true;
530             Dmsg1(100, "term_stored killing JobId=%d\n", jcr->JobId);
531             pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
532             /* ***FIXME*** wiffle through all dcrs */
533             if (jcr->dcr && jcr->dcr->dev && jcr->dcr->dev->dev_blocked) {
534                pthread_cond_broadcast(&jcr->dcr->dev->wait_next_vol);
535                pthread_cond_broadcast(&wait_device_release);
536             }
537             if (jcr->read_dcr && jcr->read_dcr->dev && jcr->read_dcr->dev->dev_blocked) {
538                pthread_cond_broadcast(&jcr->read_dcr->dev->wait_next_vol);
539                pthread_cond_broadcast(&wait_device_release);
540             }
541             bmicrosleep(0, 50000);
542          }
543          free_jcr(jcr);
544       }
545       bmicrosleep(0, 500000);         /* give them 1/2 sec to clean up */
546    }
547
548    write_state_file(me->working_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
549    delete_pid_file(me->pid_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
550
551    Dmsg1(200, "In terminate_stored() sig=%d\n", sig);
552
553    foreach_res(device, R_DEVICE) {
554       Dmsg1(10, "Term device %s\n", device->device_name);
555       if (device->dev) {
556          free_volume(device->dev);
557          device->dev->term();
558          device->dev = NULL;
559       } else {
560          Dmsg1(10, "No dev structure %s\n", device->device_name);
561       }
562    }
563
564    if (configfile) {
565       free(configfile);
566       configfile = NULL;
567    }
568    free_config_resources();
569
570    if (debug_level > 10) {
571       print_memory_pool_stats();
572    }
573    term_reservations_lock();
574    term_msg();
575    stop_watchdog();
576    cleanup_crypto();
577    free_volume_list();
578    close_memory_pool();
579
580    sm_dump(false);                    /* dump orphaned buffers */
581    exit(sig);
582 }