/* * Start watchdog thread * * Returns: 0 on success * errno on failure */ int start_watchdog(void) { int stat; watchdog_t *dummy = NULL; int errstat; if (wd_is_init) { return 0; } Dmsg0(800, "Initialising NicB-hacked watchdog thread\n"); watchdog_time = time(NULL); if ((errstat=rwl_init(&lock)) != 0) { berrno be; Jmsg1(NULL, M_ABORT, 0, _("Unable to initialize watchdog lock. ERR=%s\n"), be.bstrerror(errstat)); } wd_queue = New(dlist(dummy, &dummy->link)); wd_inactive = New(dlist(dummy, &dummy->link)); wd_is_init = true; if ((stat = pthread_create(&wd_tid, NULL, watchdog_thread, NULL)) != 0) { return stat; } return 0; }
/* * Initialized the main volume list. Note, we are using a recursive lock. */ void init_vol_list_lock() { int errstat; if ((errstat=rwl_init(&vol_list_lock, PRIO_SD_VOL_LIST)) != 0) { berrno be; Emsg1(M_ABORT, 0, _("Unable to initialize volume list lock. ERR=%s\n"), be.bstrerror(errstat)); } }
bool CONFIG::parse_config() { static bool first = true; int errstat; POOL_MEM config_path; if (first && (errstat = rwl_init(&m_res_lock)) != 0) { berrno be; Jmsg1(NULL, M_ABORT, 0, _("Unable to initialize resource lock. ERR=%s\n"), be.bstrerror(errstat)); } first = false; if (!find_config_path(config_path)) { Jmsg0(NULL, M_ERROR_TERM, 0, _("Failed to find config filename.\n")); } m_used_config_path = bstrdup(config_path.c_str()); Dmsg1(100, "config file = %s\n", m_used_config_path); return parse_config_file(config_path.c_str(), NULL, m_scan_error, m_scan_warning, m_err_type); }
bool CONFIG::parse_config() { LEX *lc = NULL; int token, i, pass; int res_type = 0; enum parse_state state = p_none; RES_ITEM *items = NULL; int level = 0; static bool first = true; int errstat; const char *cf = m_cf; LEX_ERROR_HANDLER *scan_error = m_scan_error; int err_type = m_err_type; if (first && (errstat=rwl_init(&res_lock)) != 0) { berrno be; Jmsg1(NULL, M_ABORT, 0, _("Unable to initialize resource lock. ERR=%s\n"), be.bstrerror(errstat)); } first = false; char *full_path = (char *)alloca(MAX_PATH + 1); if (!find_config_file(cf, full_path, MAX_PATH +1)) { Jmsg0(NULL, M_ABORT, 0, _("Config filename too long.\n")); } cf = full_path; /* Make two passes. The first builds the name symbol table, * and the second picks up the items. */ Dmsg0(900, "Enter parse_config()\n"); for (pass=1; pass <= 2; pass++) { Dmsg1(900, "parse_config pass %d\n", pass); if ((lc = lex_open_file(lc, cf, scan_error)) == NULL) { berrno be; /* We must create a lex packet to print the error */ lc = (LEX *)malloc(sizeof(LEX)); memset(lc, 0, sizeof(LEX)); if (scan_error) { lc->scan_error = scan_error; } else { lex_set_default_error_handler(lc); } lex_set_error_handler_error_type(lc, err_type) ; bstrncpy(lc->str, cf, sizeof(lc->str)); lc->fname = lc->str; scan_err2(lc, _("Cannot open config file \"%s\": %s\n"), lc->str, be.bstrerror()); free(lc); return 0; } lex_set_error_handler_error_type(lc, err_type) ; while ((token=lex_get_token(lc, T_ALL)) != T_EOF) { Dmsg3(900, "parse state=%d pass=%d got token=%s\n", state, pass, lex_tok_to_str(token)); switch (state) { case p_none: if (token == T_EOL) { break; } else if (token == T_UTF8_BOM) { /* We can assume the file is UTF-8 as we have seen a UTF-8 BOM */ break; } else if (token == T_UTF16_BOM) { scan_err0(lc, _("Currently we cannot handle UTF-16 source files. " "Please convert the conf file to UTF-8\n")); return 0; } else if (token != T_IDENTIFIER) { scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str); return 0; } for (i=0; resources[i].name; i++) { if (strcasecmp(resources[i].name, lc->str) == 0) { items = resources[i].items; if (!items) { break; } state = p_resource; res_type = resources[i].rcode; init_resource(this, res_type, items, pass); break; } } if (state == p_none) { scan_err1(lc, _("expected resource name, got: %s"), lc->str); return 0; } break; case p_resource: switch (token) { case T_BOB: level++; break; case T_IDENTIFIER: if (level != 1) { scan_err1(lc, _("not in resource definition: %s"), lc->str); return 0; } for (i=0; items[i].name; i++) { if (strcasecmp(items[i].name, lc->str) == 0) { /* If the ITEM_NO_EQUALS flag is set we do NOT * scan for = after the keyword */ if (!(items[i].flags & ITEM_NO_EQUALS)) { token = lex_get_token(lc, T_SKIP_EOL); Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token)); if (token != T_EQUALS) { scan_err1(lc, _("expected an equals, got: %s"), lc->str); return 0; } } Dmsg1(800, "calling handler for %s\n", items[i].name); /* Call item handler */ items[i].handler(lc, &items[i], i, pass); i = -1; break; } } if (i >= 0) { Dmsg2(900, "level=%d id=%s\n", level, lc->str); Dmsg1(900, "Keyword = %s\n", lc->str); scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n" "Perhaps you left the trailing brace off of the previous resource."), lc->str); return 0; } break; case T_EOB: level--; state = p_none; Dmsg0(900, "T_EOB => define new resource\n"); if (res_all.hdr.name == NULL) { scan_err0(lc, _("Name not specified for resource")); return 0; } save_resource(res_type, items, pass); /* save resource */ break; case T_EOL: break; default: scan_err2(lc, _("unexpected token %d %s in resource definition"), token, lex_tok_to_str(token)); return 0; } break; default: scan_err1(lc, _("Unknown parser state %d\n"), state); return 0; } } if (state != p_none) { scan_err0(lc, _("End of conf file reached with unclosed resource.")); return 0; } if (debug_level >= 900 && pass == 2) { int i; for (i=m_r_first; i<=m_r_last; i++) { dump_resource(i, m_res_head[i-m_r_first], prtmsg, NULL); } } lc = lex_close_file(lc); } Dmsg0(900, "Leave parse_config()\n"); return 1; }
DEVICE *m_init_dev(JCR *jcr, DEVRES *device) { struct stat statp; int errstat; DCR *dcr = NULL; DEVICE *dev = NULL; uint32_t max_bs; /* If no device type specified, try to guess */ if (!device->dev_type) { /* Check that device is available */ if (stat(device->device_name, &statp) < 0) { berrno be; Jmsg2(jcr, M_ERROR, 0, _("Unable to stat device %s: ERR=%s\n"), device->device_name, be.bstrerror()); return NULL; } if (S_ISDIR(statp.st_mode)) { device->dev_type = B_FILE_DEV; } else if (S_ISCHR(statp.st_mode)) { device->dev_type = B_TAPE_DEV; } else if (S_ISFIFO(statp.st_mode)) { device->dev_type = B_FIFO_DEV; #ifdef USE_VTAPE /* must set DeviceType = Vtape * in normal mode, autodetection is disabled */ } else if (S_ISREG(statp.st_mode)) { device->dev_type = B_VTAPE_DEV; #endif } else if (!(device->cap_bits & CAP_REQMOUNT)) { Jmsg2(jcr, M_ERROR, 0, _("%s is an unknown device type. Must be tape or directory\n" " or have RequiresMount=yes for DVD. st_mode=%x\n"), device->device_name, statp.st_mode); return NULL; } else { device->dev_type = B_DVD_DEV; } if (strcmp(device->device_name, "/dev/null") == 0) { device->dev_type = B_NULL_DEV; } } switch (device->dev_type) { case B_DVD_DEV: Jmsg0(jcr, M_FATAL, 0, _("DVD support is now deprecated.\n")); return NULL; case B_VTAPE_DEV: dev = New(vtape); break; #ifdef USE_FTP case B_FTP_DEV: dev = New(ftp_device); break; #endif case B_TAPE_DEV: dev = New(tape_dev); break; case B_FILE_DEV: case B_FIFO_DEV: case B_NULL_DEV: dev = New(file_dev); break; default: return NULL; } dev->clear_slot(); /* unknown */ /* Copy user supplied device parameters from Resource */ dev->dev_name = get_memory(strlen(device->device_name)+1); pm_strcpy(dev->dev_name, device->device_name); dev->prt_name = get_memory(strlen(device->device_name) + strlen(device->hdr.name) + 20); /* We edit "Resource-name" (physical-name) */ Mmsg(dev->prt_name, "\"%s\" (%s)", device->hdr.name, device->device_name); Dmsg1(400, "Allocate dev=%s\n", dev->print_name()); dev->capabilities = device->cap_bits; dev->min_free_space = device->min_free_space; dev->min_block_size = device->min_block_size; dev->max_block_size = device->max_block_size; dev->max_volume_size = device->max_volume_size; dev->max_file_size = device->max_file_size; dev->max_concurrent_jobs = device->max_concurrent_jobs; dev->volume_capacity = device->volume_capacity; dev->max_rewind_wait = device->max_rewind_wait; dev->max_open_wait = device->max_open_wait; dev->vol_poll_interval = device->vol_poll_interval; dev->max_spool_size = device->max_spool_size; dev->drive_index = device->drive_index; dev->enabled = device->enabled; dev->autoselect = device->autoselect; dev->read_only = device->read_only; dev->dev_type = device->dev_type; dev->device = device; if (dev->is_tape()) { /* No parts on tapes */ dev->max_part_size = 0; } else { dev->max_part_size = device->max_part_size; } /* Sanity check */ if (dev->vol_poll_interval && dev->vol_poll_interval < 60) { dev->vol_poll_interval = 60; } if (!device->dev) { /* The first time we create a DEVICE from the DEVRES, we keep a pointer * to the DEVICE accessible from the DEVRES. */ device->dev = dev; } if (dev->is_fifo()) { dev->capabilities |= CAP_STREAM; /* set stream device */ } /* If the device requires mount : * - Check that the mount point is available * - Check that (un)mount commands are defined */ if (dev->is_file() && dev->requires_mount()) { if (!device->mount_point || stat(device->mount_point, &statp) < 0) { berrno be; dev->dev_errno = errno; Jmsg2(jcr, M_ERROR_TERM, 0, _("Unable to stat mount point %s: ERR=%s\n"), device->mount_point, be.bstrerror()); } if (!device->mount_command || !device->unmount_command) { Jmsg0(jcr, M_ERROR_TERM, 0, _("Mount and unmount commands must defined for a device which requires mount.\n")); } } /* Keep the device ID in the DEVICE struct to identify the hardware */ if (dev->is_file() && stat(dev->archive_name(), &statp) == 0) { dev->devno = statp.st_dev; } /* Sanity check */ if (dev->max_block_size == 0) { max_bs = DEFAULT_BLOCK_SIZE; } else { max_bs = dev->max_block_size; } if (dev->min_block_size > max_bs) { Jmsg(jcr, M_ERROR_TERM, 0, _("Min block size > max on device %s\n"), dev->print_name()); } if (dev->max_block_size > 4096000) { Jmsg3(jcr, M_ERROR, 0, _("Block size %u on device %s is too large, using default %u\n"), dev->max_block_size, dev->print_name(), DEFAULT_BLOCK_SIZE); dev->max_block_size = 0; } if (dev->max_block_size % TAPE_BSIZE != 0) { Jmsg3(jcr, M_WARNING, 0, _("Max block size %u not multiple of device %s block size=%d.\n"), dev->max_block_size, dev->print_name(), TAPE_BSIZE); } if (dev->max_volume_size != 0 && dev->max_volume_size < (dev->max_block_size << 4)) { Jmsg(jcr, M_ERROR_TERM, 0, _("Max Vol Size < 8 * Max Block Size for device %s\n"), dev->print_name()); } dev->errmsg = get_pool_memory(PM_EMSG); *dev->errmsg = 0; if ((errstat = dev->init_mutex()) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } if ((errstat = pthread_cond_init(&dev->wait, NULL)) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } if ((errstat = pthread_cond_init(&dev->wait_next_vol, NULL)) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } if ((errstat = pthread_mutex_init(&dev->spool_mutex, NULL)) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init spool mutex: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } if ((errstat = dev->init_acquire_mutex()) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init acquire mutex: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } if ((errstat = dev->init_read_acquire_mutex()) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init read acquire mutex: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } if ((errstat = dev->init_volcat_mutex()) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init volcat mutex: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } if ((errstat = dev->init_dcrs_mutex()) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init dcrs mutex: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } dev->set_mutex_priorities(); #ifdef xxx if ((errstat = rwl_init(&dev->lock)) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } #endif dev->clear_opened(); dev->attached_dcrs = New(dlist(dcr, &dcr->dev_link)); Dmsg2(100, "init_dev: tape=%d dev_name=%s\n", dev->is_tape(), dev->dev_name); dev->initiated = true; return dev; }
static inline DEVICE *m_init_dev(JCR *jcr, DEVRES *device, bool new_init) { struct stat statp; int errstat; DCR *dcr = NULL; DEVICE *dev = NULL; uint32_t max_bs; Dmsg1(400, "max_block_size in device res is %u\n", device->max_block_size); /* * If no device type specified, try to guess */ if (!device->dev_type) { /* * Check that device is available */ if (stat(device->device_name, &statp) < 0) { berrno be; Jmsg2(jcr, M_ERROR, 0, _("Unable to stat device %s: ERR=%s\n"), device->device_name, be.bstrerror()); return NULL; } if (S_ISDIR(statp.st_mode)) { device->dev_type = B_FILE_DEV; } else if (S_ISCHR(statp.st_mode)) { device->dev_type = B_TAPE_DEV; } else if (S_ISFIFO(statp.st_mode)) { device->dev_type = B_FIFO_DEV; } else if (!bit_is_set(CAP_REQMOUNT, device->cap_bits)) { Jmsg2(jcr, M_ERROR, 0, _("%s is an unknown device type. Must be tape or directory, st_mode=%x\n"), device->device_name, statp.st_mode); return NULL; } } /* * See what type of device is wanted. */ switch (device->dev_type) { /* * When using dynamic loading use the init_backend_dev() function * for any type of device not being of the type file. */ #ifndef HAVE_DYNAMIC_SD_BACKENDS #ifdef HAVE_GFAPI case B_GFAPI_DEV: dev = New(gfapi_device); break; #endif #ifdef HAVE_OBJECTSTORE case B_OBJECT_STORE_DEV: dev = New(object_store_device); break; #endif #ifdef HAVE_RADOS case B_RADOS_DEV: dev = New(rados_device); break; #endif #ifdef HAVE_CEPHFS case B_CEPHFS_DEV: dev = New(cephfs_device); break; #endif #ifdef HAVE_ELASTO case B_ELASTO_DEV: dev = New(elasto_device); break; #endif #ifdef HAVE_WIN32 case B_TAPE_DEV: dev = New(win32_tape_device); break; case B_FIFO_DEV: dev = New(win32_fifo_device); break; #else case B_TAPE_DEV: dev = New(unix_tape_device); break; case B_FIFO_DEV: dev = New(unix_fifo_device); break; #endif #endif /* HAVE_DYNAMIC_SD_BACKENDS */ #ifdef HAVE_WIN32 case B_FILE_DEV: dev = New(win32_file_device); break; #else case B_FILE_DEV: dev = New(unix_file_device); break; #endif default: #ifdef HAVE_DYNAMIC_SD_BACKENDS dev = init_backend_dev(jcr, device->dev_type); #endif break; } if (!dev) { Jmsg2(jcr, M_ERROR, 0, _("%s has an unknown device type %d\n"), device->device_name, device->dev_type); return NULL; } dev->clear_slot(); /* unknown */ /* * Copy user supplied device parameters from Resource */ dev->dev_name = get_memory(strlen(device->device_name) + 1); pm_strcpy(dev->dev_name, device->device_name); if (device->device_options) { dev->dev_options = get_memory(strlen(device->device_options) + 1); pm_strcpy(dev->dev_options, device->device_options); } dev->prt_name = get_memory(strlen(device->device_name) + strlen(device->name()) + 20); /* * We edit "Resource-name" (physical-name) */ Mmsg(dev->prt_name, "\"%s\" (%s)", device->name(), device->device_name); Dmsg1(400, "Allocate dev=%s\n", dev->print_name()); copy_bits(CAP_MAX, device->cap_bits, dev->capabilities); /* * current block sizes */ dev->min_block_size = device->min_block_size; dev->max_block_size = device->max_block_size; dev->max_volume_size = device->max_volume_size; dev->max_file_size = device->max_file_size; dev->max_concurrent_jobs = device->max_concurrent_jobs; dev->volume_capacity = device->volume_capacity; dev->max_rewind_wait = device->max_rewind_wait; dev->max_open_wait = device->max_open_wait; dev->max_open_vols = device->max_open_vols; dev->vol_poll_interval = device->vol_poll_interval; dev->max_spool_size = device->max_spool_size; dev->drive = device->drive; dev->drive_index = device->drive_index; dev->autoselect = device->autoselect; dev->norewindonclose = device->norewindonclose; dev->dev_type = device->dev_type; dev->device = device; /* * Sanity check */ if (dev->vol_poll_interval && dev->vol_poll_interval < 60) { dev->vol_poll_interval = 60; } device->dev = dev; if (dev->is_fifo()) { dev->set_cap(CAP_STREAM); /* set stream device */ } /* * If the device requires mount : * - Check that the mount point is available * - Check that (un)mount commands are defined */ if (dev->is_file() && dev->requires_mount()) { if (!device->mount_point || stat(device->mount_point, &statp) < 0) { berrno be; dev->dev_errno = errno; Jmsg2(jcr, M_ERROR_TERM, 0, _("Unable to stat mount point %s: ERR=%s\n"), device->mount_point, be.bstrerror()); } if (!device->mount_command || !device->unmount_command) { Jmsg0(jcr, M_ERROR_TERM, 0, _("Mount and unmount commands must defined for a device which requires mount.\n")); } } /* * Sanity check */ if (dev->max_block_size == 0) { max_bs = DEFAULT_BLOCK_SIZE; } else { max_bs = dev->max_block_size; } if (dev->min_block_size > max_bs) { Jmsg(jcr, M_ERROR_TERM, 0, _("Min block size > max on device %s\n"), dev->print_name()); } if (dev->max_block_size > MAX_BLOCK_LENGTH) { Jmsg3(jcr, M_ERROR, 0, _("Block size %u on device %s is too large, using default %u\n"), dev->max_block_size, dev->print_name(), DEFAULT_BLOCK_SIZE); dev->max_block_size = 0; } if (dev->max_block_size % TAPE_BSIZE != 0) { Jmsg3(jcr, M_WARNING, 0, _("Max block size %u not multiple of device %s block size=%d.\n"), dev->max_block_size, dev->print_name(), TAPE_BSIZE); } if (dev->max_volume_size != 0 && dev->max_volume_size < (dev->max_block_size << 4)) { Jmsg(jcr, M_ERROR_TERM, 0, _("Max Vol Size < 8 * Max Block Size for device %s\n"), dev->print_name()); } dev->errmsg = get_pool_memory(PM_EMSG); *dev->errmsg = 0; if ((errstat = dev->init_mutex()) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } if ((errstat = pthread_cond_init(&dev->wait, NULL)) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } if ((errstat = pthread_cond_init(&dev->wait_next_vol, NULL)) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } if ((errstat = pthread_mutex_init(&dev->spool_mutex, NULL)) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init spool mutex: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } if ((errstat = dev->init_acquire_mutex()) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init acquire mutex: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } if ((errstat = dev->init_read_acquire_mutex()) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init read acquire mutex: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } dev->set_mutex_priorities(); #ifdef xxx if ((errstat = rwl_init(&dev->lock)) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(errstat)); Jmsg0(jcr, M_ERROR_TERM, 0, dev->errmsg); } #endif dev->clear_opened(); dev->attached_dcrs = New(dlist(dcr, &dcr->dev_link)); Dmsg2(100, "init_dev: tape=%d dev_name=%s\n", dev->is_tape(), dev->dev_name); dev->initiated = true; Dmsg3(100, "dev=%s dev_max_bs=%u max_bs=%u\n", dev->dev_name, dev->device->max_block_size, dev->max_block_size); return dev; }