]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/dird.c
ebl Fix small bug about RecyclePool that is not updated at
[bacula/bacula] / bacula / src / dird / dird.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU 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    General Public License for more details.
17
18    You should have received a copy of the GNU 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    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *
30  *   Bacula Director daemon -- this is the main program
31  *
32  *     Kern Sibbald, March MM
33  *
34  *   Version $Id$
35  */
36
37 #include "bacula.h"
38 #include "dird.h"
39
40 #ifdef HAVE_PYTHON
41
42 #undef _POSIX_C_SOURCE
43 #include <Python.h>
44
45 #include "lib/pythonlib.h"
46
47 /* Imported Functions */
48 extern PyObject *job_getattr(PyObject *self, char *attrname);
49 extern int job_setattr(PyObject *self, char *attrname, PyObject *value);
50
51 #endif /* HAVE_PYTHON */
52
53 /* Forward referenced subroutines */
54 void terminate_dird(int sig);
55 static bool check_resources();
56 static bool check_catalog();
57 static void dir_sql_query(JCR *jcr, const char *cmd);
58   
59 /* Exported subroutines */
60 extern "C" void reload_config(int sig);
61 extern void invalidate_schedules();
62 extern bool parse_dir_config(CONFIG *config, const char *configfile, int exit_code);
63
64 /* Imported subroutines */
65 JCR *wait_for_next_job(char *runjob);
66 void term_scheduler();
67 void term_ua_server();
68 void start_UA_server(dlist *addrs);
69 void init_job_server(int max_workers);
70 void term_job_server();
71 void store_jobtype(LEX *lc, RES_ITEM *item, int index, int pass);
72 void store_level(LEX *lc, RES_ITEM *item, int index, int pass);
73 void store_replace(LEX *lc, RES_ITEM *item, int index, int pass);
74 void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass);
75 void init_device_resources();
76
77 static char *runjob = NULL;
78 static int background = 1;
79 static void init_reload(void);
80 static CONFIG *config;
81  
82 /* Globals Exported */
83 DIRRES *director;                     /* Director resource */
84 int FDConnectTimeout;
85 int SDConnectTimeout;
86 char *configfile = NULL;
87 void *start_heap;
88
89 /* Globals Imported */
90 extern RES_ITEM job_items[];
91 #if defined(_MSC_VER)
92 extern "C" { // work around visual compiler mangling variables
93    extern URES res_all;
94 }
95 #else
96 extern URES res_all;
97 #endif
98
99 #define CONFIG_FILE "bacula-dir.conf" /* default configuration file */
100
101 static void usage()
102 {
103    fprintf(stderr, _(
104 PROG_COPYRIGHT
105 "\nVersion: %s (%s)\n\n"
106 "Usage: dird [-f -s] [-c config_file] [-d debug_level] [config_file]\n"
107 "       -c <file>   set configuration file to file\n"
108 "       -d <nn>     set debug level to <nn>\n"
109 "       -dt         print timestamp in debug output\n"
110 "       -f          run in foreground (for debugging)\n"
111 "       -g          groupid\n"
112 "       -r <job>    run <job> now\n"
113 "       -s          no signals\n"
114 "       -t          test - read configuration and exit\n"
115 "       -u          userid\n"
116 "       -v          verbose user messages\n"
117 "       -?          print this message.\n"
118 "\n"), 2000, VERSION, BDATE);
119
120    exit(1);
121 }
122
123
124 /*********************************************************************
125  *
126  *         Main Bacula Server program
127  *
128  */
129 #if defined(HAVE_WIN32)
130 /* For Win32 main() is in src/win32 code ... */
131 #define main BaculaMain
132 #endif
133
134 int main (int argc, char *argv[])
135 {
136    int ch;
137    JCR *jcr;
138    bool no_signals = false;
139    bool test_config = false;
140    char *uid = NULL;
141    char *gid = NULL;
142 #ifdef HAVE_PYTHON
143    init_python_interpreter_args python_args;
144 #endif /* HAVE_PYTHON */
145
146    start_heap = sbrk(0);
147    setlocale(LC_ALL, "");
148    bindtextdomain("bacula", LOCALEDIR);
149    textdomain("bacula");
150
151    init_stack_dump();
152    my_name_is(argc, argv, "bacula-dir");
153    init_msg(NULL, NULL);              /* initialize message handler */
154    init_reload();
155    daemon_start_time = time(NULL);
156
157    console_command = run_console_command;
158
159    while ((ch = getopt(argc, argv, "c:d:fg:r:stu:v?")) != -1) {
160       switch (ch) {
161       case 'c':                    /* specify config file */
162          if (configfile != NULL) {
163             free(configfile);
164          }
165          configfile = bstrdup(optarg);
166          break;
167
168       case 'd':                    /* set debug level */
169          if (*optarg == 't') {
170             dbg_timestamp = true;
171          } else {
172             debug_level = atoi(optarg);
173             if (debug_level <= 0) {
174                debug_level = 1;
175             }
176          }
177          Dmsg1(10, "Debug level = %d\n", debug_level);
178          break;
179
180       case 'f':                    /* run in foreground */
181          background = FALSE;
182          break;
183
184       case 'g':                    /* set group id */
185          gid = optarg;
186          break;
187
188       case 'r':                    /* run job */
189          if (runjob != NULL) {
190             free(runjob);
191          }
192          if (optarg) {
193             runjob = bstrdup(optarg);
194          }
195          break;
196
197       case 's':                    /* turn off signals */
198          no_signals = true;
199          break;
200
201       case 't':                    /* test config */
202          test_config = true;
203          break;
204
205       case 'u':                    /* set uid */
206          uid = optarg;
207          break;
208
209       case 'v':                    /* verbose */
210          verbose++;
211          break;
212
213       case '?':
214       default:
215          usage();
216
217       }
218    }
219    argc -= optind;
220    argv += optind;
221
222    if (!no_signals) {
223       init_signals(terminate_dird);
224    }
225
226    if (argc) {
227       if (configfile != NULL) {
228          free(configfile);
229       }
230       configfile = bstrdup(*argv);
231       argc--;
232       argv++;
233    }
234    if (argc) {
235       usage();
236    }
237
238    if (configfile == NULL) {
239       configfile = bstrdup(CONFIG_FILE);
240    }
241
242    config = new_config_parser();
243    parse_dir_config(config, configfile, M_ERROR_TERM);
244
245    if (init_crypto() != 0) {
246       Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Cryptography library initialization failed.\n"));
247    }
248
249    if (!check_resources()) {
250       Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile);
251    }
252
253    if (!test_config) {                /* we don't need to do this block in test mode */
254       if (background) {
255          daemon_start();
256          init_stack_dump();              /* grab new pid */
257       }
258    
259       /* Create pid must come after we are a daemon -- so we have our final pid */
260       create_pid_file(director->pid_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
261       read_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
262    }
263
264    load_dir_plugins(director->plugin_directory);
265
266    drop(uid, gid);                    /* reduce privileges if requested */
267
268    if (!check_catalog()) {
269       Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile);
270    }
271
272    if (test_config) {
273       terminate_dird(0);
274    }
275
276    my_name_is(0, NULL, director->name());    /* set user defined name */
277
278    /* Plug database interface for library routines */
279    p_sql_query = (sql_query)dir_sql_query;
280    p_sql_escape = (sql_escape)db_escape_string;
281
282    FDConnectTimeout = (int)director->FDConnectTimeout;
283    SDConnectTimeout = (int)director->SDConnectTimeout;
284
285 #if !defined(HAVE_WIN32)
286    signal(SIGHUP, reload_config);
287 #endif
288
289    init_console_msg(working_directory);
290
291 #ifdef HAVE_PYTHON
292    python_args.progname = director->name();
293    python_args.scriptdir = director->scripts_directory;
294    python_args.modulename = "DirStartUp";
295    python_args.configfile = configfile;
296    python_args.workingdir = director->working_directory;
297    python_args.job_getattr = job_getattr;
298    python_args.job_setattr = job_setattr;
299
300    init_python_interpreter(&python_args);
301 #endif /* HAVE_PYTHON */
302
303    set_jcr_in_tsd(INVALID_JCR);
304    set_thread_concurrency(director->MaxConcurrentJobs * 2 +
305       4 /* UA */ + 4 /* sched+watchdog+jobsvr+misc */);
306
307    Dmsg0(200, "Start UA server\n");
308    start_UA_server(director->DIRaddrs);
309
310    start_watchdog();                  /* start network watchdog thread */
311
312    init_jcr_subsystem();              /* start JCR watchdogs etc. */
313
314    init_job_server(director->MaxConcurrentJobs);
315
316    dbg_jcr_add_hook(_dbg_print_db); /* used to debug B_DB connexion after fatal signal */
317
318 //   init_device_resources();
319
320    Dmsg0(200, "wait for next job\n");
321    /* Main loop -- call scheduler to get next job to run */
322    while ( (jcr = wait_for_next_job(runjob)) ) {
323       run_job(jcr);                   /* run job */
324       free_jcr(jcr);                  /* release jcr */
325       set_jcr_in_tsd(INVALID_JCR);
326       if (runjob) {                   /* command line, run a single job? */
327          break;                       /* yes, terminate */
328       }
329    }
330
331    terminate_dird(0);
332
333    return 0;
334 }
335
336 /*
337  * This allows the message handler to operate on the database
338  *   by using a pointer to this function. The pointer is
339  *   needed because the other daemons do not have access
340  *   to the database.  If the pointer is
341  *   not defined (other daemons), then writing the database
342  *   is disabled. 
343  */
344 static void dir_sql_query(JCR *jcr, const char *cmd)
345 {
346    if (!jcr || !jcr->db) {
347       return;
348    }
349    db_sql_query(jcr->db, cmd, NULL, NULL);
350 }
351
352 /* Cleanup and then exit */
353 void terminate_dird(int sig)
354 {
355    static bool already_here = false;
356
357    if (already_here) {                /* avoid recursive temination problems */
358       bmicrosleep(2, 0);              /* yield */
359       exit(1);
360    }
361    already_here = true;
362    debug_level = 0;                   /* turn off debug */
363    stop_watchdog();
364    generate_daemon_event(NULL, "Exit");
365    unload_plugins();
366    write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
367    delete_pid_file(director->pid_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
368    term_scheduler();
369    term_job_server();
370    if (runjob) {
371       free(runjob);
372    }
373    if (configfile != NULL) {
374       free(configfile);
375    }
376    if (debug_level > 5) {
377       print_memory_pool_stats();
378    }
379    if (config) {
380       config->free_resources();
381       free(config);
382       config = NULL;
383    }
384    term_ua_server();
385    term_msg();                        /* terminate message handler */
386    cleanup_crypto();
387    close_memory_pool();               /* release free memory in pool */
388    lmgr_cleanup_main();
389    sm_dump(false);
390    exit(sig);
391 }
392
393 struct RELOAD_TABLE {
394    int job_count;
395    RES **res_table;
396 };
397
398 static const int max_reloads = 32;
399 static RELOAD_TABLE reload_table[max_reloads];
400
401 static void init_reload(void)
402 {
403    for (int i=0; i < max_reloads; i++) {
404       reload_table[i].job_count = 0;
405       reload_table[i].res_table = NULL;
406    }
407 }
408
409 static void free_saved_resources(int table)
410 {
411    int num = r_last - r_first + 1;
412    RES **res_tab = reload_table[table].res_table;
413    if (!res_tab) {
414       Dmsg1(100, "res_tab for table %d already released.\n", table);
415       return;
416    }
417    Dmsg1(100, "Freeing resources for table %d\n", table);
418    for (int j=0; j<num; j++) {
419       free_resource(res_tab[j], r_first + j);
420    }
421    free(res_tab);
422    reload_table[table].job_count = 0;
423    reload_table[table].res_table = NULL;
424 }
425
426 /*
427  * Called here at the end of every job that was
428  * hooked decrementing the active job_count. When
429  * it goes to zero, no one is using the associated
430  * resource table, so free it.
431  */
432 static void reload_job_end_cb(JCR *jcr, void *ctx)
433 {
434    int reload_id = (int)((long int)ctx);
435    Dmsg3(100, "reload job_end JobId=%d table=%d cnt=%d\n", jcr->JobId,
436       reload_id, reload_table[reload_id].job_count);
437    lock_jobs();
438    LockRes();
439    if (--reload_table[reload_id].job_count <= 0) {
440       free_saved_resources(reload_id);
441    }
442    UnlockRes();
443    unlock_jobs();
444 }
445
446 static int find_free_reload_table_entry()
447 {
448    int table = -1;
449    for (int i=0; i < max_reloads; i++) {
450       if (reload_table[i].res_table == NULL) {
451          table = i;
452          break;
453       }
454    }
455    return table;
456 }
457
458 /*
459  * If we get here, we have received a SIGHUP, which means to
460  *    reread our configuration file.
461  *
462  * The algorithm used is as follows: we count how many jobs are
463  *   running and mark the running jobs to make a callback on
464  *   exiting. The old config is saved with the reload table
465  *   id in a reload table. The new config file is read. Now, as
466  *   each job exits, it calls back to the reload_job_end_cb(), which
467  *   decrements the count of open jobs for the given reload table.
468  *   When the count goes to zero, we release those resources.
469  *   This allows us to have pointers into the resource table (from
470  *   jobs), and once they exit and all the pointers are released, we
471  *   release the old table. Note, if no new jobs are running since the
472  *   last reload, then the old resources will be immediately release.
473  *   A console is considered a job because it may have pointers to
474  *   resources, but a SYSTEM job is not since it *should* not have any
475  *   permanent pointers to jobs.
476  */
477 extern "C"
478 void reload_config(int sig)
479 {
480    static bool already_here = false;
481 #if !defined(HAVE_WIN32)
482    sigset_t set;
483 #endif
484    JCR *jcr;
485    int njobs = 0;                     /* number of running jobs */
486    int table, rtable;
487    bool ok;       
488
489    if (already_here) {
490       abort();                        /* Oops, recursion -> die */
491    }
492    already_here = true;
493
494 #if !defined(HAVE_WIN32)
495    sigemptyset(&set);
496    sigaddset(&set, SIGHUP);
497    sigprocmask(SIG_BLOCK, &set, NULL);
498 #endif
499
500    lock_jobs();
501    LockRes();
502
503    table = find_free_reload_table_entry();
504    if (table < 0) {
505       Jmsg(NULL, M_ERROR, 0, _("Too many open reload requests. Request ignored.\n"));
506       goto bail_out;
507    }
508
509    Dmsg1(100, "Reload_config njobs=%d\n", njobs);
510    reload_table[table].res_table = config->save_resources();
511    Dmsg1(100, "Saved old config in table %d\n", table);
512
513    ok = parse_dir_config(config, configfile, M_ERROR);
514
515    Dmsg0(100, "Reloaded config file\n");
516    if (!ok || !check_resources() || !check_catalog()) {
517       rtable = find_free_reload_table_entry();    /* save new, bad table */
518       if (rtable < 0) {
519          Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile);
520          Jmsg(NULL, M_ERROR_TERM, 0, _("Out of reload table entries. Giving up.\n"));
521       } else {
522          Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile);
523          Jmsg(NULL, M_ERROR, 0, _("Resetting previous configuration.\n"));
524       }
525       reload_table[rtable].res_table = config->save_resources();
526       /* Now restore old resoure values */
527       int num = r_last - r_first + 1;
528       RES **res_tab = reload_table[table].res_table;
529       for (int i=0; i<num; i++) {
530          res_head[i] = res_tab[i];
531       }
532       table = rtable;                 /* release new, bad, saved table below */
533    } else {
534       invalidate_schedules();
535       /*
536        * Hook all active jobs so that they release this table
537        */
538       foreach_jcr(jcr) {
539          if (jcr->get_JobType() != JT_SYSTEM) {
540             reload_table[table].job_count++;
541             job_end_push(jcr, reload_job_end_cb, (void *)((long int)table));
542             njobs++;
543          }
544       }
545       endeach_jcr(jcr);
546    }
547
548    /* Reset globals */
549    set_working_directory(director->working_directory);
550    FDConnectTimeout = director->FDConnectTimeout;
551    SDConnectTimeout = director->SDConnectTimeout;
552    Dmsg0(10, "Director's configuration file reread.\n");
553
554    /* Now release saved resources, if no jobs using the resources */
555    if (njobs == 0) {
556       free_saved_resources(table);
557    }
558
559 bail_out:
560    UnlockRes();
561    unlock_jobs();
562 #if !defined(HAVE_WIN32)
563    sigprocmask(SIG_UNBLOCK, &set, NULL);
564    signal(SIGHUP, reload_config);
565 #endif
566    already_here = false;
567 }
568
569 /*
570  * Make a quick check to see that we have all the
571  * resources needed.
572  *
573  *  **** FIXME **** this routine could be a lot more
574  *   intelligent and comprehensive.
575  */
576 static bool check_resources()
577 {
578    bool OK = true;
579    JOB *job;
580    bool need_tls;
581
582    LockRes();
583
584    job = (JOB *)GetNextRes(R_JOB, NULL);
585    director = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
586    if (!director) {
587       Jmsg(NULL, M_FATAL, 0, _("No Director resource defined in %s\n"
588 "Without that I don't know who I am :-(\n"), configfile);
589       OK = false;
590    } else {
591       set_working_directory(director->working_directory);
592       if (!director->messages) {       /* If message resource not specified */
593          director->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
594          if (!director->messages) {
595             Jmsg(NULL, M_FATAL, 0, _("No Messages resource defined in %s\n"), configfile);
596             OK = false;
597          }
598       }
599       if (GetNextRes(R_DIRECTOR, (RES *)director) != NULL) {
600          Jmsg(NULL, M_FATAL, 0, _("Only one Director resource permitted in %s\n"),
601             configfile);
602          OK = false;
603       }
604       /* tls_require implies tls_enable */
605       if (director->tls_require) {
606          if (have_tls) {
607             director->tls_enable = true;
608          } else {
609             Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
610             OK = false;
611          }
612       }
613
614       need_tls = director->tls_enable || director->tls_authenticate;
615
616       if (!director->tls_certfile && need_tls) {
617          Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Director \"%s\" in %s.\n"),
618             director->name(), configfile);
619          OK = false;
620       }
621
622       if (!director->tls_keyfile && need_tls) {
623          Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Director \"%s\" in %s.\n"),
624             director->name(), configfile);
625          OK = false;
626       }
627
628       if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && 
629            need_tls && director->tls_verify_peer) {
630          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\" or \"TLS CA"
631               " Certificate Dir\" are defined for Director \"%s\" in %s."
632               " At least one CA certificate store is required"
633               " when using \"TLS Verify Peer\".\n"),
634               director->name(), configfile);
635          OK = false;
636       }
637
638       /* If everything is well, attempt to initialize our per-resource TLS context */
639       if (OK && (need_tls || director->tls_require)) {
640          /* Initialize TLS context:
641           * Args: CA certfile, CA certdir, Certfile, Keyfile,
642           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
643          director->tls_ctx = new_tls_context(director->tls_ca_certfile,
644             director->tls_ca_certdir, director->tls_certfile,
645             director->tls_keyfile, NULL, NULL, director->tls_dhfile,
646             director->tls_verify_peer);
647          
648          if (!director->tls_ctx) {
649             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Director \"%s\" in %s.\n"),
650                  director->name(), configfile);
651             OK = false;
652          }
653       }
654    }
655
656    if (!job) {
657       Jmsg(NULL, M_FATAL, 0, _("No Job records defined in %s\n"), configfile);
658       OK = false;
659    }
660    foreach_res(job, R_JOB) {
661       int i;
662
663       if (job->jobdefs) {
664          /* Handle Storage alists specifically */
665          JOB *jobdefs = job->jobdefs;
666          if (jobdefs->storage && !job->storage) {
667             STORE *st;
668             job->storage = New(alist(10, not_owned_by_alist));
669             foreach_alist(st, jobdefs->storage) {
670                job->storage->append(st);
671             }
672          }
673          /* Handle RunScripts alists specifically */
674          if (jobdefs->RunScripts) {
675             RUNSCRIPT *rs, *elt;
676             
677             if (!job->RunScripts) {
678                job->RunScripts = New(alist(10, not_owned_by_alist));
679             }
680            
681             foreach_alist(rs, jobdefs->RunScripts) {
682                elt = copy_runscript(rs);
683                job->RunScripts->append(elt); /* we have to free it */
684             }
685          }
686
687          /* Transfer default items from JobDefs Resource */
688          for (i=0; job_items[i].name; i++) {
689             char **def_svalue, **svalue;  /* string value */
690             uint32_t *def_ivalue, *ivalue;     /* integer value */
691             bool *def_bvalue, *bvalue;    /* bool value */
692             int64_t *def_lvalue, *lvalue; /* 64 bit values */
693             uint32_t offset;
694
695             Dmsg4(1400, "Job \"%s\", field \"%s\" bit=%d def=%d\n",
696                 job->name(), job_items[i].name,
697                 bit_is_set(i, job->hdr.item_present),
698                 bit_is_set(i, job->jobdefs->hdr.item_present));
699
700             if (!bit_is_set(i, job->hdr.item_present) &&
701                  bit_is_set(i, job->jobdefs->hdr.item_present)) {
702                Dmsg2(400, "Job \"%s\", field \"%s\": getting default.\n",
703                  job->name(), job_items[i].name);
704                offset = (char *)(job_items[i].value) - (char *)&res_all;
705                /*
706                 * Handle strings and directory strings
707                 */
708                if (job_items[i].handler == store_str ||
709                    job_items[i].handler == store_dir) {
710                   def_svalue = (char **)((char *)(job->jobdefs) + offset);
711                   Dmsg5(400, "Job \"%s\", field \"%s\" def_svalue=%s item %d offset=%u\n",
712                        job->name(), job_items[i].name, *def_svalue, i, offset);
713                   svalue = (char **)((char *)job + offset);
714                   if (*svalue) {
715                      Pmsg1(000, _("Hey something is wrong. p=0x%lu\n"), *svalue);
716                   }
717                   *svalue = bstrdup(*def_svalue);
718                   set_bit(i, job->hdr.item_present);
719                /*
720                 * Handle resources
721                 */
722                } else if (job_items[i].handler == store_res) {
723                   def_svalue = (char **)((char *)(job->jobdefs) + offset);
724                   Dmsg4(400, "Job \"%s\", field \"%s\" item %d offset=%u\n",
725                        job->name(), job_items[i].name, i, offset);
726                   svalue = (char **)((char *)job + offset);
727                   if (*svalue) {
728                      Pmsg1(000, _("Hey something is wrong. p=0x%lu\n"), *svalue);
729                   }
730                   *svalue = *def_svalue;
731                   set_bit(i, job->hdr.item_present);
732                /*
733                 * Handle alist resources
734                 */
735                } else if (job_items[i].handler == store_alist_res) {
736                   if (bit_is_set(i, job->jobdefs->hdr.item_present)) {
737                      set_bit(i, job->hdr.item_present);
738                   }
739                /*
740                 * Handle integer fields
741                 *    Note, our store_bit does not handle bitmaped fields
742                 */
743                } else if (job_items[i].handler == store_bit     ||
744                           job_items[i].handler == store_pint32  ||
745                           job_items[i].handler == store_jobtype ||
746                           job_items[i].handler == store_level   ||
747                           job_items[i].handler == store_int32   ||
748                           job_items[i].handler == store_migtype ||
749                           job_items[i].handler == store_replace) {
750                   def_ivalue = (uint32_t *)((char *)(job->jobdefs) + offset);
751                   Dmsg5(400, "Job \"%s\", field \"%s\" def_ivalue=%d item %d offset=%u\n",
752                        job->name(), job_items[i].name, *def_ivalue, i, offset);
753                   ivalue = (uint32_t *)((char *)job + offset);
754                   *ivalue = *def_ivalue;
755                   set_bit(i, job->hdr.item_present);
756                /*
757                 * Handle 64 bit integer fields
758                 */
759                } else if (job_items[i].handler == store_time   ||
760                           job_items[i].handler == store_size   ||
761                           job_items[i].handler == store_int64) {
762                   def_lvalue = (int64_t *)((char *)(job->jobdefs) + offset);
763                   Dmsg5(400, "Job \"%s\", field \"%s\" def_lvalue=%" lld " item %d offset=%u\n",
764                        job->name(), job_items[i].name, *def_lvalue, i, offset);
765                   lvalue = (int64_t *)((char *)job + offset);
766                   *lvalue = *def_lvalue;
767                   set_bit(i, job->hdr.item_present);
768                /*
769                 * Handle bool fields
770                 */
771                } else if (job_items[i].handler == store_bool) {
772                   def_bvalue = (bool *)((char *)(job->jobdefs) + offset);
773                   Dmsg5(400, "Job \"%s\", field \"%s\" def_bvalue=%d item %d offset=%u\n",
774                        job->name(), job_items[i].name, *def_bvalue, i, offset);
775                   bvalue = (bool *)((char *)job + offset);
776                   *bvalue = *def_bvalue;
777                   set_bit(i, job->hdr.item_present);
778                }
779             }
780          }
781       }
782       /*
783        * Ensure that all required items are present
784        */
785       for (i=0; job_items[i].name; i++) {
786          if (job_items[i].flags & ITEM_REQUIRED) {
787                if (!bit_is_set(i, job->hdr.item_present)) {
788                   Jmsg(NULL, M_ERROR_TERM, 0, _("\"%s\" directive in Job \"%s\" resource is required, but not found.\n"),
789                     job_items[i].name, job->name());
790                   OK = false;
791                 }
792          }
793          /* If this triggers, take a look at lib/parse_conf.h */
794          if (i >= MAX_RES_ITEMS) {
795             Emsg0(M_ERROR_TERM, 0, _("Too many items in Job resource\n"));
796          }
797       }
798       if (!job->storage && !job->pool->storage) {
799          Jmsg(NULL, M_FATAL, 0, _("No storage specified in Job \"%s\" nor in Pool.\n"),
800             job->name());
801          OK = false;
802       }
803    } /* End loop over Job res */
804
805
806    /* Loop over Consoles */
807    CONRES *cons;
808    foreach_res(cons, R_CONSOLE) {
809       /* tls_require implies tls_enable */
810       if (cons->tls_require) {
811          if (have_tls) {
812             cons->tls_enable = true;
813          } else {
814             Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
815             OK = false;
816             continue;
817          }
818       }
819
820       need_tls = cons->tls_enable || cons->tls_authenticate;
821       
822       if (!cons->tls_certfile && need_tls) {
823          Jmsg(NULL, M_FATAL, 0, _("\"TLS Certificate\" file not defined for Console \"%s\" in %s.\n"),
824             cons->name(), configfile);
825          OK = false;
826       }
827
828       if (!cons->tls_keyfile && need_tls) {
829          Jmsg(NULL, M_FATAL, 0, _("\"TLS Key\" file not defined for Console \"%s\" in %s.\n"),
830             cons->name(), configfile);
831          OK = false;
832       }
833
834       if ((!cons->tls_ca_certfile && !cons->tls_ca_certdir) 
835             && need_tls && cons->tls_verify_peer) {
836          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\" or \"TLS CA"
837             " Certificate Dir\" are defined for Console \"%s\" in %s."
838             " At least one CA certificate store is required"
839             " when using \"TLS Verify Peer\".\n"),
840             cons->name(), configfile);
841          OK = false;
842       }
843       /* If everything is well, attempt to initialize our per-resource TLS context */
844       if (OK && (need_tls || cons->tls_require)) {
845          /* Initialize TLS context:
846           * Args: CA certfile, CA certdir, Certfile, Keyfile,
847           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
848          cons->tls_ctx = new_tls_context(cons->tls_ca_certfile,
849             cons->tls_ca_certdir, cons->tls_certfile,
850             cons->tls_keyfile, NULL, NULL, cons->tls_dhfile, cons->tls_verify_peer);
851          
852          if (!cons->tls_ctx) {
853             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
854                cons->name(), configfile);
855             OK = false;
856          }
857       }
858
859    }
860
861    /* Loop over Clients */
862    CLIENT *client;
863    foreach_res(client, R_CLIENT) {
864       /* tls_require implies tls_enable */
865       if (client->tls_require) {
866          if (have_tls) {
867             client->tls_enable = true;
868          } else {
869             Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
870             OK = false;
871             continue;
872          }
873       }
874       need_tls = client->tls_enable || client->tls_authenticate;
875       if ((!client->tls_ca_certfile && !client->tls_ca_certdir) && need_tls) {
876          Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
877             " or \"TLS CA Certificate Dir\" are defined for File daemon \"%s\" in %s.\n"),
878             client->name(), configfile);
879          OK = false;
880       }
881
882       /* If everything is well, attempt to initialize our per-resource TLS context */
883       if (OK && (need_tls || client->tls_require)) {
884          /* Initialize TLS context:
885           * Args: CA certfile, CA certdir, Certfile, Keyfile,
886           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
887          client->tls_ctx = new_tls_context(client->tls_ca_certfile,
888             client->tls_ca_certdir, client->tls_certfile,
889             client->tls_keyfile, NULL, NULL, NULL,
890             true);
891          
892          if (!client->tls_ctx) {
893             Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
894                client->name(), configfile);
895             OK = false;
896          }
897       }
898    }
899
900    UnlockRes();
901    if (OK) {
902       close_msg(NULL);                /* close temp message handler */
903       init_msg(NULL, director->messages); /* open daemon message handler */
904    }
905    return OK;
906 }
907
908 static bool check_catalog()
909 {
910    bool OK = true;
911    bool need_tls;
912
913    /* Loop over databases */
914    CAT *catalog;
915    foreach_res(catalog, R_CATALOG) {
916       B_DB *db;
917       /*
918        * Make sure we can open catalog, otherwise print a warning
919        * message because the server is probably not running.
920        */
921       db = db_init(NULL, catalog->db_driver, catalog->db_name, catalog->db_user,
922                          catalog->db_password, catalog->db_address,
923                          catalog->db_port, catalog->db_socket,
924                          catalog->mult_db_connections);
925       if (!db || !db_open_database(NULL, db)) {
926          Pmsg2(000, _("Could not open Catalog \"%s\", database \"%s\".\n"),
927               catalog->name(), catalog->db_name);
928          Jmsg(NULL, M_FATAL, 0, _("Could not open Catalog \"%s\", database \"%s\".\n"),
929               catalog->name(), catalog->db_name);
930          if (db) {
931             Jmsg(NULL, M_FATAL, 0, _("%s"), db_strerror(db));
932             Pmsg1(000, "%s", db_strerror(db));
933             db_close_database(NULL, db);
934          }
935          OK = false;
936          continue;
937       }
938
939       /* Loop over all pools, defining/updating them in each database */
940       POOL *pool;
941       foreach_res(pool, R_POOL) {
942          /*
943           * If the Pool has a catalog resource create the pool only
944           *   in that catalog.
945           */
946          if (!pool->catalog || pool->catalog == catalog) {
947             create_pool(NULL, db, pool, POOL_OP_UPDATE);  /* update request */
948          }
949       }
950
951       /* Once they are created, we can loop over them again, updating
952        * references (RecyclePool)
953        */
954       foreach_res(pool, R_POOL) {
955          /*
956           * If the Pool has a catalog resource update the pool only
957           *   in that catalog.
958           */
959          if (!pool->catalog || pool->catalog == catalog) {
960             update_pool_recyclepool(NULL, db, pool);
961          }
962       }
963
964       STORE *store;
965       foreach_res(store, R_STORAGE) {
966          STORAGE_DBR sr;
967          MEDIATYPE_DBR mr;
968          if (store->media_type) {
969             bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
970             mr.ReadOnly = 0;
971             db_create_mediatype_record(NULL, db, &mr);
972          } else {
973             mr.MediaTypeId = 0;
974          }
975          bstrncpy(sr.Name, store->name(), sizeof(sr.Name));
976          sr.AutoChanger = store->autochanger;
977          db_create_storage_record(NULL, db, &sr);
978          store->StorageId = sr.StorageId;   /* set storage Id */
979          if (!sr.created) {                 /* if not created, update it */
980             sr.AutoChanger = store->autochanger;
981             db_update_storage_record(NULL, db, &sr);
982          }
983
984          /* tls_require implies tls_enable */
985          if (store->tls_require) {
986             if (have_tls) {
987                store->tls_enable = true;
988             } else {
989                Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
990                OK = false;
991             }
992          } 
993
994          need_tls = store->tls_enable || store->tls_authenticate;
995
996          if ((!store->tls_ca_certfile && !store->tls_ca_certdir) && need_tls) {
997             Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
998                  " or \"TLS CA Certificate Dir\" are defined for Storage \"%s\" in %s.\n"),
999                  store->name(), configfile);
1000             OK = false;
1001          }
1002
1003          /* If everything is well, attempt to initialize our per-resource TLS context */
1004          if (OK && (need_tls || store->tls_require)) {
1005            /* Initialize TLS context:
1006             * Args: CA certfile, CA certdir, Certfile, Keyfile,
1007             * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
1008             store->tls_ctx = new_tls_context(store->tls_ca_certfile,
1009                store->tls_ca_certdir, store->tls_certfile,
1010                store->tls_keyfile, NULL, NULL, NULL, true);
1011          
1012             if (!store->tls_ctx) {
1013                Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Storage \"%s\" in %s.\n"),
1014                     store->name(), configfile);
1015                OK = false;
1016             }
1017          }
1018       }
1019
1020       /* Loop over all counters, defining them in each database */
1021       /* Set default value in all counters */
1022       COUNTER *counter;
1023       foreach_res(counter, R_COUNTER) {
1024          /* Write to catalog? */
1025          if (!counter->created && counter->Catalog == catalog) {
1026             COUNTER_DBR cr;
1027             bstrncpy(cr.Counter, counter->name(), sizeof(cr.Counter));
1028             cr.MinValue = counter->MinValue;
1029             cr.MaxValue = counter->MaxValue;
1030             cr.CurrentValue = counter->MinValue;
1031             if (counter->WrapCounter) {
1032                bstrncpy(cr.WrapCounter, counter->WrapCounter->name(), sizeof(cr.WrapCounter));
1033             } else {
1034                cr.WrapCounter[0] = 0;  /* empty string */
1035             }
1036             if (db_create_counter_record(NULL, db, &cr)) {
1037                counter->CurrentValue = cr.CurrentValue;
1038                counter->created = true;
1039                Dmsg2(100, "Create counter %s val=%d\n", counter->name(), counter->CurrentValue);
1040             }
1041          }
1042          if (!counter->created) {
1043             counter->CurrentValue = counter->MinValue;  /* default value */
1044          }
1045       }
1046       db_close_database(NULL, db);
1047    }
1048    /* Set type in global for debugging */
1049    set_db_type(db_get_type());
1050    return OK;
1051 }