static bool select_director(const char *director, DIRRES **ret_dir, CONRES **ret_cons) { int numcon=0, numdir=0; int i=0, item=0; BSOCK *UA_sock; DIRRES *dir = NULL; CONRES *cons = NULL; *ret_cons = NULL; *ret_dir = NULL; LockRes(); numdir = 0; foreach_res(dir, R_DIRECTOR) { numdir++; } numcon = 0; foreach_res(cons, R_CONSOLE) { numcon++; } UnlockRes(); if (numdir == 1) { /* No choose */ dir = (DIRRES *)GetNextRes(R_DIRECTOR, NULL); } if (director) { /* Command line choice overwrite the no choose option */ LockRes(); foreach_res(dir, R_DIRECTOR) { if (bstrcmp(dir->name(), director)) { break; } } UnlockRes(); if (!dir) { /* Can't find Director used as argument */ senditf(_("Can't find %s in Director list\n"), director); return 0; } } if (!dir) { /* prompt for director */ UA_sock = New(BSOCK_TCP); try_again: sendit(_("Available Directors:\n")); LockRes(); numdir = 0; foreach_res(dir, R_DIRECTOR) { senditf( _("%2d: %s at %s:%d\n"), 1+numdir++, dir->name(), dir->address, dir->DIRport); }
/* * Select a Storage resource from prompt list */ STORERES *select_storage_resource(UAContext *ua, bool autochanger_only) { STORERES *store; char name[MAX_NAME_LENGTH]; if (autochanger_only) { start_prompt(ua, _("The defined Autochanger Storage resources are:\n")); } else { start_prompt(ua, _("The defined Storage resources are:\n")); } LockRes(); foreach_res(store, R_STORAGE) { if (acl_access_ok(ua, Storage_ACL, store->name())) { if (autochanger_only && !store->autochanger) { continue; } else { add_prompt(ua, store->name()); } } } UnlockRes(); if (do_prompt(ua, _("Storage"), _("Select Storage resource"), name, sizeof(name)) < 0) { return NULL; } store = (STORERES *)GetResWithName(R_STORAGE, name); return store; }
static bool msgscmd(UAContext *ua, const char *cmd) { MSGSRES *msgs = NULL; LockRes(); foreach_res(msgs, R_MSGS) { ua->send_msg("%s\n", msgs->name()); }
/* * Can use an argument to filter on JobType * .jobs [type=B] */ bool dot_jobs_cmd(UAContext *ua, const char *cmd) { int pos; JOBRES *job; uint32_t type = 0; if ((pos = find_arg_with_value(ua, "type")) >= 0) { type = ua->argv[pos][0]; } LockRes(); ua->send->array_start("jobs"); foreach_res(job, R_JOB) { if (!type || type == job->JobType) { if (acl_access_ok(ua, Job_ACL, job->name())) { ua->send->object_start(); ua->send->object_key_value("name", job->name(), "%s\n"); ua->send->object_end(); } } } ua->send->array_end("jobs"); UnlockRes(); return true; }
/* * Make a quick check to see that we have all the * resources needed. */ static int check_resources() { int xOK = true; DIRRES *director; LockRes(); numdir = 0; foreach_res(director, R_DIRECTOR) { numdir++; /* tls_require implies tls_enable */ if (director->tls_require) { if (have_tls) { director->tls_enable = true; } else { Jmsg(NULL, M_FATAL, 0, wxString(_("TLS required but not configured in Bacula.\n")).mb_str(*wxConvCurrent)); xOK = false; continue; } } if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && director->tls_enable) { Jmsg(NULL, M_FATAL, 0, wxString(_("Neither \"TLS CA Certificate\" or \"TLS CA Certificate Dir\" are defined for Director \"%s\" in config file.\nAt least one CA certificate store is required.\n")).mb_str(*wxConvCurrent), director->hdr.name); xOK = false; } }
/* * Make a quick check to see that we have all the * resources needed. */ static int check_resources() { bool ok = true; DIRRES *director; int numdir; bool tls_needed; LockRes(); numdir = 0; foreach_res(director, R_DIRECTOR) { numdir++; /* tls_require implies tls_enable */ if (director->tls_require) { if (have_tls) { director->tls_enable = true; } else { Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n")); ok = false; continue; } } tls_needed = director->tls_enable || director->tls_authenticate; if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && tls_needed) { Emsg2(M_FATAL, 0, _("Neither \"TLS CA Certificate\"" " or \"TLS CA Certificate Dir\" are defined for Director \"%s\" in %s." " At least one CA certificate store is required.\n"), director->hdr.name, configfile); ok = false; } }
QStringList MonitorItemThread::createRes(const cl_opts& cl) { QStringList tabRefs; LockRes(my_config); int monitorItems = 0; MONITORRES *monitorRes; foreach_res(my_config, monitorRes, R_MONITOR) { monitorItems++; } if (monitorItems != 1) { Emsg2(M_ERROR_TERM, 0, _("Error: %d Monitor resources defined in %s. " "You must define one and only one Monitor resource.\n"), monitorItems, cl.configfile); } monitor = reinterpret_cast<MONITORRES*>(my_config->GetNextRes(R_MONITOR, (RES *)NULL)); int nitems = 0; DIRRES* dird; foreach_res(my_config, dird, R_DIRECTOR) { MonitorItem* item = new MonitorItem; item->setType(R_DIRECTOR); item->setResource(dird); item->setConnectTimeout(monitor->DIRConnectTimeout); item->connectToMainWindow(MainWindow::instance()); tabRefs.append(item->get_name()); items.append(item); nitems++; }
/* * Get a catalog resource from prompt list */ CATRES *get_catalog_resource(UAContext *ua) { CATRES *catalog = NULL; char name[MAX_NAME_LENGTH]; for (int i = 1; i < ua->argc; i++) { if (bstrcasecmp(ua->argk[i], NT_("catalog")) && ua->argv[i]) { if (acl_access_ok(ua, Catalog_ACL, ua->argv[i])) { catalog = (CATRES *)GetResWithName(R_CATALOG, ua->argv[i]); break; } } } if (ua->gui && !catalog) { LockRes(); catalog = (CATRES *)GetNextRes(R_CATALOG, NULL); UnlockRes(); if (!catalog) { ua->error_msg(_("Could not find a Catalog resource\n")); return NULL; } else if (!acl_access_ok(ua, Catalog_ACL, catalog->name())) { ua->error_msg(_("You must specify a \"use <catalog-name>\" command before continuing.\n")); return NULL; } return catalog; } if (!catalog) { start_prompt(ua, _("The defined Catalog resources are:\n")); LockRes(); foreach_res(catalog, R_CATALOG) { if (acl_access_ok(ua, Catalog_ACL, catalog->name())) { add_prompt(ua, catalog->name()); } } UnlockRes(); if (do_prompt(ua, _("Catalog"), _("Select Catalog resource"), name, sizeof(name)) < 0) { return NULL; } catalog = (CATRES *)GetResWithName(R_CATALOG, name); }
bool dot_msgs_cmd(UAContext *ua, const char *cmd) { MSGSRES *msgs = NULL; LockRes(); ua->send->array_start("messages"); foreach_res(msgs, R_MSGS) { ua->send->object_start(); ua->send->object_key_value("text", msgs->name(), "%s\n"); ua->send->object_end(); }
static bool catalogscmd(UAContext *ua, const char *cmd) { CATRES *cat; LockRes(); foreach_res(cat, R_CATALOG) { if (acl_access_ok(ua, Catalog_ACL, cat->name())) { ua->send_msg("%s\n", cat->name()); } } UnlockRes(); return true; }
static bool clientscmd(UAContext *ua, const char *cmd) { CLIENTRES *client; LockRes(); foreach_res(client, R_CLIENT) { if (acl_access_ok(ua, Client_ACL, client->name())) { ua->send_msg("%s\n", client->name()); } } UnlockRes(); return true; }
static bool filesetscmd(UAContext *ua, const char *cmd) { FILESETRES *fs; LockRes(); foreach_res(fs, R_FILESET) { if (acl_access_ok(ua, FileSet_ACL, fs->name())) { ua->send_msg("%s\n", fs->name()); } } UnlockRes(); return true; }
/* * Called here at the end of every job that was * hooked decrementing the active job_count. When * it goes to zero, no one is using the associated * resource table, so free it. */ static void reload_job_end_cb(JCR *jcr, void *ctx) { int reload_id = (int)((intptr_t)ctx); Dmsg3(100, "reload job_end JobId=%d table=%d cnt=%d\n", jcr->JobId, reload_id, reload_table[reload_id].job_count); lock_jobs(); LockRes(); if (--reload_table[reload_id].job_count <= 0) { free_saved_resources(reload_id); } UnlockRes(); unlock_jobs(); }
/* * Search for device resource that corresponds to * device name on command line (or default). * * Returns: NULL on failure * Device resource pointer on success */ static DEVRES *find_device_res(char *device_name, int read_access) { bool found = false; DEVRES *device; Dmsg0(900, "Enter find_device_res\n"); LockRes(my_config); foreach_res(my_config, device, R_DEVICE) { Dmsg2(900, "Compare %s and %s\n", device->device_name, device_name); if (bstrcmp(device->device_name, device_name)) { found = true; break; } }
/* * Return resource of type rcode that matches name */ RES *GetResWithName(int rcode, const char *name) { RES *res; int rindex = rcode - my_config->m_r_first; LockRes(); res = my_config->m_res_head[rindex]; while (res) { if (bstrcmp(res->name, name)) { break; } res = res->next; } UnlockRes(); return res; }
/* * Called here to do a special operation on a variable * op_ptr points to the special operation code (not EOS terminated) * arg_ptr points to argument to special op code * val_ptr points to the value string * out_ptr points to string to be returned */ static var_rc_t operate_var(var_t *var, void *my_ctx, const char *op_ptr, int op_len, const char *arg_ptr, int arg_len, const char *val_ptr, int val_len, char **out_ptr, int *out_len, int *out_size) { COUNTERRES *counter; POOL_MEM buf(PM_NAME); var_rc_t status = VAR_ERR_UNDEFINED_OPERATION; Dmsg0(100, "Enter operate_var\n"); if (!val_ptr) { *out_size = 0; return status; } if (op_len == 3 && bstrncmp(op_ptr, "inc", 3)) { buf.check_size(val_len + 1); pm_memcpy(buf, arg_ptr, val_len); (buf.c_str())[val_len] = 0; Dmsg1(100, "Arg=%s\n", buf.c_str()); pm_memcpy(buf, val_ptr, val_len); (buf.c_str())[val_len] = 0; Dmsg1(100, "Val=%s\n", buf.c_str()); LockRes(); for (counter = NULL; (counter = (COUNTERRES *)GetNextRes(R_COUNTER, (RES *)counter)); ) { if (bstrcmp(counter->name(), buf.c_str())) { Dmsg2(100, "counter=%s val=%s\n", counter->name(), buf.c_str()); break; } } UnlockRes(); return status; } *out_size = 0; return status; }
bool dot_filesets_cmd(UAContext *ua, const char *cmd) { FILESETRES *fs; LockRes(); ua->send->array_start("filesets"); foreach_res(fs, R_FILESET) { if (acl_access_ok(ua, FileSet_ACL, fs->name())) { ua->send->object_start(); ua->send->object_key_value("name", fs->name(), "%s\n"); ua->send->object_end(); } } ua->send->array_end("filesets"); UnlockRes(); return true; }
bool dot_jobdefs_cmd(UAContext *ua, const char *cmd) { JOBRES *jobdefs; LockRes(); ua->send->array_start("jobdefs"); foreach_res(jobdefs, R_JOBDEFS) { if (acl_access_ok(ua, Job_ACL, jobdefs->name())) { ua->send->object_start(); ua->send->object_key_value("name", jobdefs->name(), "%s\n"); ua->send->object_end(); } } ua->send->object_end("jobdefs"); UnlockRes(); return true; }
bool dot_catalogs_cmd(UAContext *ua, const char *cmd) { CATRES *cat; LockRes(); ua->send->array_start("catalogs"); foreach_res(cat, R_CATALOG) { if (acl_access_ok(ua, Catalog_ACL, cat->name())) { ua->send->object_start(); ua->send->object_key_value("name", cat->name(), "%s\n"); ua->send->object_end(); } } ua->send->array_end("catalogs"); UnlockRes(); return true; }
bool dot_clients_cmd(UAContext *ua, const char *cmd) { CLIENTRES *client; LockRes(); ua->send->array_start("clients"); foreach_res(client, R_CLIENT) { if (acl_access_ok(ua, Client_ACL, client->name())) { ua->send->object_start(); ua->send->object_key_value("name", client->name(), "%s\n"); ua->send->object_end(); } } ua->send->array_end("clients"); UnlockRes(); return true; }
/* * Can use an argument to filter on JobType * .jobs [type=B] */ static bool jobscmd(UAContext *ua, const char *cmd) { JOBRES *job; uint32_t type = 0; int pos; if ((pos = find_arg_with_value(ua, "type")) >= 0) { type = ua->argv[pos][0]; } LockRes(); foreach_res(job, R_JOB) { if (!type || type == job->JobType) { if (acl_access_ok(ua, Job_ACL, job->name())) { ua->send_msg("%s\n", job->name()); } } } UnlockRes(); return true; }
/* * Create a Job Control Record for a control "job", * filling in all the appropriate fields. */ JCR *new_control_jcr(const char *base_name, int job_type) { JCR *jcr; jcr = new_jcr(sizeof(JCR), dird_free_jcr); /* * The job and defaults are not really used, but * we set them up to ensure that everything is correctly * initialized. */ LockRes(); jcr->job = (JOB *)GetNextRes(R_JOB, NULL); set_jcr_defaults(jcr, jcr->job); UnlockRes(); jcr->sd_auth_key = bstrdup("dummy"); /* dummy Storage daemon key */ create_unique_job_name(jcr, base_name); jcr->sched_time = jcr->start_time; jcr->setJobType(job_type); jcr->setJobLevel(L_NONE); jcr->setJobStatus(JS_Running); jcr->JobId = 0; return jcr; }
/* * Select a FileSet resource from prompt list */ FILESETRES *select_fileset_resource(UAContext *ua) { FILESETRES *fs; char name[MAX_NAME_LENGTH]; start_prompt(ua, _("The defined FileSet resources are:\n")); LockRes(); foreach_res(fs, R_FILESET) { if (acl_access_ok(ua, FileSet_ACL, fs->name())) { add_prompt(ua, fs->name()); } } UnlockRes(); if (do_prompt(ua, _("FileSet"), _("Select FileSet resource"), name, sizeof(name)) < 0) { return NULL; } fs = (FILESETRES *)GetResWithName(R_FILESET, name); return fs; }
/* * Search counter variables */ static var_rc_t lookup_counter_var(var_t *ctx, void *my_ctx, const char *var_ptr, int var_len, int var_inc, int var_index, const char **val_ptr, int *val_len, int *val_size) { COUNTERRES *counter; POOL_MEM buf(PM_NAME); var_rc_t status = VAR_ERR_UNDEFINED_VARIABLE; buf.check_size(var_len + 1); pm_memcpy(buf, var_ptr, var_len); (buf.c_str())[var_len] = 0; LockRes(); for (counter = NULL; (counter = (COUNTERRES *)GetNextRes(R_COUNTER, (RES *)counter)); ) { if (bstrcmp(counter->name(), buf.c_str())) { Dmsg2(100, "Counter=%s val=%d\n", buf.c_str(), counter->CurrentValue); /* * -1 => return size of array */ if (var_index == -1) { Mmsg(buf, "%d", counter->CurrentValue); *val_len = Mmsg(buf, "%d", strlen(buf.c_str())); *val_ptr = bstrdup(buf.c_str()); *val_size = 0; /* don't try to free val_ptr */ return VAR_OK; } else { Mmsg(buf, "%d", counter->CurrentValue); *val_ptr = bstrdup(buf.c_str()); *val_len = strlen(buf.c_str()); *val_size = *val_len + 1; } if (var_inc) { /* increment the variable? */ if (counter->CurrentValue == counter->MaxValue) { counter->CurrentValue = counter->MinValue; } else { counter->CurrentValue++; } if (counter->Catalog) { /* update catalog if need be */ COUNTER_DBR cr; JCR *jcr = (JCR *)my_ctx; memset(&cr, 0, sizeof(cr)); bstrncpy(cr.Counter, counter->name(), sizeof(cr.Counter)); cr.MinValue = counter->MinValue; cr.MaxValue = counter->MaxValue; cr.CurrentValue = counter->CurrentValue; Dmsg1(100, "New value=%d\n", cr.CurrentValue); if (counter->WrapCounter) { bstrncpy(cr.WrapCounter, counter->WrapCounter->name(), sizeof(cr.WrapCounter)); } else { cr.WrapCounter[0] = 0; } if (!db_update_counter_record(jcr, jcr->db, &cr)) { Jmsg(jcr, M_ERROR, 0, _("Count not update counter %s: ERR=%s\n"), counter->name(), db_strerror(jcr->db)); } } } status = VAR_OK; break; } } UnlockRes(); return status; }
/** * Find all the requested files and send them * to the Storage daemon. * * Note, we normally carry on a one-way * conversation from this point on with the SD, simply blasting * data to him. To properly know what is going on, we * also run a "heartbeat" monitor which reads the socket and * reacts accordingly (at the moment it has nothing to do * except echo the heartbeat to the Director). */ bool blast_data_to_storage_daemon(JCR *jcr, char *addr, crypto_cipher_t cipher) { BSOCK *sd; bool ok = true; sd = jcr->store_bsock; jcr->setJobStatus(JS_Running); Dmsg1(300, "filed: opened data connection %d to stored\n", sd->m_fd); LockRes(); CLIENTRES *client = (CLIENTRES *)GetNextRes(R_CLIENT, NULL); UnlockRes(); uint32_t buf_size; if (client) { buf_size = client->max_network_buffer_size; } else { buf_size = 0; /* use default */ } if (!sd->set_buffer_size(buf_size, BNET_SETBUF_WRITE)) { jcr->setJobStatus(JS_ErrorTerminated); Jmsg(jcr, M_FATAL, 0, _("Cannot set buffer size FD->SD.\n")); return false; } jcr->buf_size = sd->msglen; if (!adjust_compression_buffers(jcr)) { return false; } if (!crypto_session_start(jcr, cipher)) { return false; } set_find_options((FF_PKT *)jcr->ff, jcr->incremental, jcr->mtime); /** * In accurate mode, we overload the find_one check function */ if (jcr->accurate) { set_find_changed_function((FF_PKT *)jcr->ff, accurate_check_file); } start_heartbeat_monitor(jcr); if (have_acl) { jcr->acl_data = (acl_data_t *)malloc(sizeof(acl_data_t)); memset(jcr->acl_data, 0, sizeof(acl_data_t)); jcr->acl_data->u.build = (acl_build_data_t *)malloc(sizeof(acl_build_data_t)); memset(jcr->acl_data->u.build, 0, sizeof(acl_build_data_t)); jcr->acl_data->u.build->content = get_pool_memory(PM_MESSAGE); } if (have_xattr) { jcr->xattr_data = (xattr_data_t *)malloc(sizeof(xattr_data_t)); memset(jcr->xattr_data, 0, sizeof(xattr_data_t)); jcr->xattr_data->u.build = (xattr_build_data_t *)malloc(sizeof(xattr_build_data_t)); memset(jcr->xattr_data->u.build, 0, sizeof(xattr_build_data_t)); jcr->xattr_data->u.build->content = get_pool_memory(PM_MESSAGE); } /** * Subroutine save_file() is called for each file */ if (!find_files(jcr, (FF_PKT *)jcr->ff, save_file, plugin_save)) { ok = false; /* error */ jcr->setJobStatus(JS_ErrorTerminated); } if (have_acl && jcr->acl_data->u.build->nr_errors > 0) { Jmsg(jcr, M_WARNING, 0, _("Encountered %ld acl errors while doing backup\n"), jcr->acl_data->u.build->nr_errors); } if (have_xattr && jcr->xattr_data->u.build->nr_errors > 0) { Jmsg(jcr, M_WARNING, 0, _("Encountered %ld xattr errors while doing backup\n"), jcr->xattr_data->u.build->nr_errors); } close_vss_backup_session(jcr); accurate_finish(jcr); /* send deleted or base file list to SD */ stop_heartbeat_monitor(jcr); sd->signal(BNET_EOD); /* end of sending data */ if (have_acl && jcr->acl_data) { free_pool_memory(jcr->acl_data->u.build->content); free(jcr->acl_data->u.build); free(jcr->acl_data); jcr->acl_data = NULL; } if (have_xattr && jcr->xattr_data) { free_pool_memory(jcr->xattr_data->u.build->content); free(jcr->xattr_data->u.build); free(jcr->xattr_data); jcr->xattr_data = NULL; } if (jcr->big_buf) { free(jcr->big_buf); jcr->big_buf = NULL; } cleanup_compression(jcr); crypto_session_end(jcr); Dmsg1(100, "end blast_data ok=%d\n", ok); return ok; }
void *device_initialization(void *arg) { DEVRES *device; DCR *dcr; JCR *jcr; DEVICE *dev; int errstat; LockRes(); pthread_detach(pthread_self()); jcr = new_jcr(sizeof(JCR), stored_free_jcr); new_plugins(jcr); /* instantiate plugins */ jcr->setJobType(JT_SYSTEM); /* * Initialize job start condition variable */ errstat = pthread_cond_init(&jcr->job_start_wait, NULL); if (errstat != 0) { berrno be; Jmsg1(jcr, M_ABORT, 0, _("Unable to init job start cond variable: ERR=%s\n"), be.bstrerror(errstat)); } /* * Initialize job end condition variable */ errstat = pthread_cond_init(&jcr->job_end_wait, NULL); if (errstat != 0) { berrno be; Jmsg1(jcr, M_ABORT, 0, _("Unable to init job endstart cond variable: ERR=%s\n"), be.bstrerror(errstat)); } foreach_res(device, R_DEVICE) { Dmsg1(90, "calling init_dev %s\n", device->device_name); dev = init_dev(NULL, device); Dmsg1(10, "SD init done %s\n", device->device_name); if (!dev) { Jmsg1(NULL, M_ERROR, 0, _("Could not initialize %s\n"), device->device_name); continue; } jcr->dcr = dcr = new_dcr(jcr, NULL, dev, NULL); generate_plugin_event(jcr, bsdEventDeviceInit, dcr); if (dev->is_autochanger()) { /* If autochanger set slot in dev structure */ get_autochanger_loaded_slot(dcr); } if (device->cap_bits & CAP_ALWAYSOPEN) { Dmsg1(20, "calling first_open_device %s\n", dev->print_name()); if (!first_open_device(dcr)) { Jmsg1(NULL, M_ERROR, 0, _("Could not open device %s\n"), dev->print_name()); Dmsg1(20, "Could not open device %s\n", dev->print_name()); free_dcr(dcr); jcr->dcr = NULL; continue; } } if (device->cap_bits & CAP_AUTOMOUNT && dev->is_open()) { switch (read_dev_volume_label(dcr)) { case VOL_OK: memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo)); volume_unused(dcr); /* mark volume "released" */ break; default: Jmsg1(NULL, M_WARNING, 0, _("Could not mount device %s\n"), dev->print_name()); break; } } free_dcr(dcr); jcr->dcr = NULL; }
/* * Verify attributes of the requested files on the Volume * */ void do_verify_volume(JCR *jcr) { BSOCK *sd, *dir; POOLMEM *fname; /* original file name */ POOLMEM *lname; /* link name */ int32_t stream; uint32_t size; uint32_t VolSessionId, VolSessionTime, file_index; uint32_t record_file_index; char digest[BASE64_SIZE(CRYPTO_DIGEST_MAX_SIZE)]; int type, stat; sd = jcr->store_bsock; if (!sd) { Jmsg(jcr, M_FATAL, 0, _("Storage command not issued before Verify.\n")); jcr->setJobStatus(JS_FatalError); return; } dir = jcr->dir_bsock; jcr->setJobStatus(JS_Running); LockRes(); CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL); UnlockRes(); uint32_t buf_size; if (client) { buf_size = client->max_network_buffer_size; } else { buf_size = 0; /* use default */ } if (!sd->set_buffer_size(buf_size, BNET_SETBUF_WRITE)) { jcr->setJobStatus(JS_FatalError); return; } jcr->buf_size = sd->msglen; fname = get_pool_memory(PM_FNAME); lname = get_pool_memory(PM_FNAME); /* * Get a record from the Storage daemon */ while (bget_msg(sd) >= 0 && !job_canceled(jcr)) { /* * First we expect a Stream Record Header */ if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index, &stream, &size) != 5) { Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg); goto bail_out; } Dmsg3(30, "Got hdr: FilInx=%d Stream=%d size=%d.\n", file_index, stream, size); /* * Now we expect the Stream Data */ if (bget_msg(sd) < 0) { Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), sd->bstrerror()); goto bail_out; } if (size != ((uint32_t)sd->msglen)) { Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size); goto bail_out; } Dmsg2(30, "Got stream data %s, len=%d\n", stream_to_ascii(stream), sd->msglen); /* File Attributes stream */ switch (stream) { case STREAM_UNIX_ATTRIBUTES: case STREAM_UNIX_ATTRIBUTES_EX: char *ap, *lp, *fp; Dmsg0(400, "Stream=Unix Attributes.\n"); if ((int)sizeof_pool_memory(fname) < sd->msglen) { fname = realloc_pool_memory(fname, sd->msglen + 1); } if ((int)sizeof_pool_memory(lname) < sd->msglen) { lname = realloc_pool_memory(lname, sd->msglen + 1); } *fname = 0; *lname = 0; /* * An Attributes record consists of: * File_index * Type (FT_types) * Filename * Attributes * Link name (if file linked i.e. FT_LNK) * Extended Attributes (if Win32) */ if (sscanf(sd->msg, "%d %d", &record_file_index, &type) != 2) { Jmsg(jcr, M_FATAL, 0, _("Error scanning record header: %s\n"), sd->msg); Dmsg0(0, "\nError scanning header\n"); goto bail_out; } Dmsg2(30, "Got Attr: FilInx=%d type=%d\n", record_file_index, type); ap = sd->msg; while (*ap++ != ' ') /* skip record file index */ ; while (*ap++ != ' ') /* skip type */ ; /* Save filename and position to attributes */ fp = fname; while (*ap != 0) { *fp++ = *ap++; /* copy filename to fname */ } *fp = *ap++; /* terminate filename & point to attribs */ Dmsg2(100, "File=%s Attr=%s\n", fname, ap); /* Skip to Link name */ if (type == FT_LNK || type == FT_LNKSAVED) { lp = ap; while (*lp++ != 0) { ; } pm_strcat(lname, lp); /* "save" link name */ } else { *lname = 0; } jcr->lock(); jcr->JobFiles++; jcr->num_files_examined++; pm_strcpy(jcr->last_fname, fname); /* last file examined */ jcr->unlock(); /* * Send file attributes to Director * File_index * Stream * Verify Options * Filename (full path) * Encoded attributes * Link name (if type==FT_LNK) * For a directory, link is the same as fname, but with trailing * slash. For a linked file, link is the link. */ /* Send file attributes to Director */ Dmsg2(200, "send ATTR inx=%d fname=%s\n", jcr->JobFiles, fname); if (type == FT_LNK || type == FT_LNKSAVED) { stat = dir->fsend("%d %d %s %s%c%s%c%s%c", jcr->JobFiles, STREAM_UNIX_ATTRIBUTES, "pinsug5", fname, 0, ap, 0, lname, 0); /* for a deleted record, we set fileindex=0 */ } else if (type == FT_DELETED) { stat = dir->fsend("%d %d %s %s%c%s%c%c", 0, STREAM_UNIX_ATTRIBUTES, "pinsug5", fname, 0, ap, 0, 0); } else { stat = dir->fsend("%d %d %s %s%c%s%c%c", jcr->JobFiles, STREAM_UNIX_ATTRIBUTES, "pinsug5", fname, 0, ap, 0, 0); } Dmsg2(200, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg); if (!stat) { Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), dir->bstrerror()); goto bail_out; } break; case STREAM_MD5_DIGEST: bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_MD5_SIZE, true); Dmsg2(400, "send inx=%d MD5=%s\n", jcr->JobFiles, digest); dir->fsend("%d %d %s *MD5-%d*", jcr->JobFiles, STREAM_MD5_DIGEST, digest, jcr->JobFiles); Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg); break; case STREAM_SHA1_DIGEST: bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA1_SIZE, true); Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, digest); dir->fsend("%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_DIGEST, digest, jcr->JobFiles); Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg); break; case STREAM_SHA256_DIGEST: bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA256_SIZE, true); Dmsg2(400, "send inx=%d SHA256=%s\n", jcr->JobFiles, digest); dir->fsend("%d %d %s *SHA256-%d*", jcr->JobFiles, STREAM_SHA256_DIGEST, digest, jcr->JobFiles); Dmsg2(20, "bfiled>bdird: SHA256 len=%d: msg=%s\n", dir->msglen, dir->msg); break; case STREAM_SHA512_DIGEST: bin_to_base64(digest, sizeof(digest), (char *)sd->msg, CRYPTO_DIGEST_SHA512_SIZE, true); Dmsg2(400, "send inx=%d SHA512=%s\n", jcr->JobFiles, digest); dir->fsend("%d %d %s *SHA512-%d*", jcr->JobFiles, STREAM_SHA512_DIGEST, digest, jcr->JobFiles); Dmsg2(20, "bfiled>bdird: SHA512 len=%d: msg=%s\n", dir->msglen, dir->msg); break; /* * Restore stream object is counted, but not restored here */ case STREAM_RESTORE_OBJECT: jcr->lock(); jcr->JobFiles++; jcr->num_files_examined++; jcr->unlock(); break; /* Ignore everything else */ default: break; } /* end switch */ } /* end while bnet_get */ jcr->setJobStatus(JS_Terminated); goto ok_out; bail_out: jcr->setJobStatus(JS_ErrorTerminated); ok_out: if (jcr->compress_buf) { free(jcr->compress_buf); jcr->compress_buf = NULL; } free_pool_memory(fname); free_pool_memory(lname); Dmsg2(050, "End Verify-Vol. Files=%d Bytes=%" lld "\n", jcr->JobFiles, jcr->JobBytes); }
int main (int argc, char *argv[]) { int i, ch; FILE *fd; char line[1000]; char *VolumeName = NULL; char *bsrName = NULL; char *DirectorName = NULL; bool ignore_label_errors = false; DIRRES *director = NULL; setlocale(LC_ALL, ""); bindtextdomain("bareos", LOCALEDIR); textdomain("bareos"); init_stack_dump(); lmgr_init_thread(); working_directory = "/tmp"; my_name_is(argc, argv, "bls"); init_msg(NULL, NULL); /* initialize message handler */ OSDependentInit(); ff = init_find_files(); while ((ch = getopt(argc, argv, "b:c:D:d:e:i:jkLpvV:?")) != -1) { switch (ch) { case 'b': bsrName = optarg; break; case 'c': /* specify config file */ if (configfile != NULL) { free(configfile); } configfile = bstrdup(optarg); break; case 'D': /* specify director name */ if (DirectorName != NULL) { free(DirectorName); } DirectorName = bstrdup(optarg); break; case 'd': /* debug level */ if (*optarg == 't') { dbg_timestamp = true; } else { debug_level = atoi(optarg); if (debug_level <= 0) { debug_level = 1; } } break; case 'e': /* exclude list */ if ((fd = fopen(optarg, "rb")) == NULL) { berrno be; Pmsg2(0, _("Could not open exclude file: %s, ERR=%s\n"), optarg, be.bstrerror()); exit(1); } while (fgets(line, sizeof(line), fd) != NULL) { strip_trailing_junk(line); Dmsg1(100, "add_exclude %s\n", line); add_fname_to_exclude_list(ff, line); } fclose(fd); break; case 'i': /* include list */ if ((fd = fopen(optarg, "rb")) == NULL) { berrno be; Pmsg2(0, _("Could not open include file: %s, ERR=%s\n"), optarg, be.bstrerror()); exit(1); } while (fgets(line, sizeof(line), fd) != NULL) { strip_trailing_junk(line); Dmsg1(100, "add_include %s\n", line); add_fname_to_include_list(ff, 0, line); } fclose(fd); break; case 'j': list_jobs = true; break; case 'k': list_blocks = true; break; case 'L': dump_label = true; break; case 'p': ignore_label_errors = true; forge_on = true; break; case 'v': verbose++; break; case 'V': /* Volume name */ VolumeName = optarg; break; case '?': default: usage(); } /* end switch */ } /* end while */ argc -= optind; argv += optind; if (!argc) { Pmsg0(0, _("No archive name specified\n")); usage(); } if (configfile == NULL) { configfile = bstrdup(CONFIG_FILE); } my_config = new_config_parser(); parse_sd_config(my_config, configfile, M_ERROR_TERM); LockRes(); me = (STORES *)GetNextRes(R_STORAGE, NULL); if (!me) { UnlockRes(); Emsg1(M_ERROR_TERM, 0, _("No Storage resource defined in %s. Cannot continue.\n"), configfile); } UnlockRes(); if (DirectorName) { foreach_res(director, R_DIRECTOR) { if (bstrcmp(director->hdr.name, DirectorName)) { break; } } if (!director) { Emsg2(M_ERROR_TERM, 0, _("No Director resource named %s defined in %s. Cannot continue.\n"), DirectorName, configfile); } } load_sd_plugins(me->plugin_directory, me->plugin_names); read_crypto_cache(me->working_directory, "bareos-sd", get_first_port_host_order(me->SDaddrs)); if (ff->included_files_list == NULL) { add_fname_to_include_list(ff, 0, "/"); } for (i=0; i < argc; i++) { if (bsrName) { bsr = parse_bsr(NULL, bsrName); } jcr = setup_jcr("bls", argv[i], bsr, director, VolumeName, 1); /* acquire for read */ if (!jcr) { exit(1); } jcr->ignore_label_errors = ignore_label_errors; dev = jcr->dcr->dev; if (!dev) { exit(1); } dcr = jcr->dcr; rec = new_record(); attr = new_attr(jcr); /* * Assume that we have already read the volume label. * If on second or subsequent volume, adjust buffer pointer */ if (dev->VolHdr.PrevVolumeName[0] != 0) { /* second volume */ Pmsg1(0, _("\n" "Warning, this Volume is a continuation of Volume %s\n"), dev->VolHdr.PrevVolumeName); } if (list_blocks) { do_blocks(argv[i]); } else if (list_jobs) { do_jobs(argv[i]); } else { do_ls(argv[i]); } do_close(jcr); } if (bsr) { free_bsr(bsr); } term_include_exclude_files(ff); term_find_files(ff); return 0; }
/* * Restore files */ bool restore_cmd(UAContext *ua, const char *cmd) { RESTORE_CTX rx; /* restore context */ POOL_MEM buf; JOBRES *job; int i; JCR *jcr = ua->jcr; char *escaped_bsr_name = NULL; char *escaped_where_name = NULL; char *strip_prefix, *add_prefix, *add_suffix, *regexp; strip_prefix = add_prefix = add_suffix = regexp = NULL; memset(&rx, 0, sizeof(rx)); rx.path = get_pool_memory(PM_FNAME); rx.fname = get_pool_memory(PM_FNAME); rx.JobIds = get_pool_memory(PM_FNAME); rx.JobIds[0] = 0; rx.BaseJobIds = get_pool_memory(PM_FNAME); rx.query = get_pool_memory(PM_FNAME); rx.bsr = new_bsr(); i = find_arg_with_value(ua, "comment"); if (i >= 0) { rx.comment = ua->argv[i]; if (!is_comment_legal(ua, rx.comment)) { goto bail_out; } } i = find_arg_with_value(ua, "backupformat"); if (i >= 0) { rx.backup_format = ua->argv[i]; } i = find_arg_with_value(ua, "where"); if (i >= 0) { rx.where = ua->argv[i]; } i = find_arg_with_value(ua, "replace"); if (i >= 0) { rx.replace = ua->argv[i]; } i = find_arg_with_value(ua, "pluginoptions"); if (i >= 0) { rx.plugin_options = ua->argv[i]; } i = find_arg_with_value(ua, "strip_prefix"); if (i >= 0) { strip_prefix = ua->argv[i]; } i = find_arg_with_value(ua, "add_prefix"); if (i >= 0) { add_prefix = ua->argv[i]; } i = find_arg_with_value(ua, "add_suffix"); if (i >= 0) { add_suffix = ua->argv[i]; } i = find_arg_with_value(ua, "regexwhere"); if (i >= 0) { rx.RegexWhere = ua->argv[i]; } if (strip_prefix || add_suffix || add_prefix) { int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix); regexp = (char *)bmalloc(len * sizeof(char)); bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix); rx.RegexWhere = regexp; } /* TODO: add acl for regexwhere ? */ if (rx.RegexWhere) { if (!acl_access_ok(ua, Where_ACL, rx.RegexWhere, true)) { ua->error_msg(_("\"RegexWhere\" specification not authorized.\n")); goto bail_out; } } if (rx.where) { if (!acl_access_ok(ua, Where_ACL, rx.where, true)) { ua->error_msg(_("\"where\" specification not authorized.\n")); goto bail_out; } } if (!open_client_db(ua, true)) { goto bail_out; } /* Ensure there is at least one Restore Job */ LockRes(); foreach_res(job, R_JOB) { if (job->JobType == JT_RESTORE) { if (!rx.restore_job) { rx.restore_job = job; } rx.restore_jobs++; } } UnlockRes(); if (!rx.restore_jobs) { ua->error_msg(_( "No Restore Job Resource found in bareos-dir.conf.\n" "You must create at least one before running this command.\n")); goto bail_out; } /* * Request user to select JobIds or files by various different methods * last 20 jobs, where File saved, most recent backup, ... * In the end, a list of files are pumped into * add_findex() */ switch (user_select_jobids_or_files(ua, &rx)) { case 0: /* error */ goto bail_out; case 1: /* selected by jobid */ get_and_display_basejobs(ua, &rx); if (!build_directory_tree(ua, &rx)) { ua->send_msg(_("Restore not done.\n")); goto bail_out; } break; case 2: /* selected by filename, no tree needed */ break; } if (rx.bsr->JobId) { char ed1[50]; if (!complete_bsr(ua, rx.bsr)) { /* find Vol, SessId, SessTime from JobIds */ ua->error_msg(_("Unable to construct a valid BSR. Cannot continue.\n")); goto bail_out; } if (!(rx.selected_files = write_bsr_file(ua, rx))) { ua->warning_msg(_("No files selected to be restored.\n")); goto bail_out; } display_bsr_info(ua, rx); /* display vols needed, etc */ if (rx.selected_files==1) { ua->info_msg(_("\n1 file selected to be restored.\n\n")); } else { ua->info_msg(_("\n%s files selected to be restored.\n\n"), edit_uint64_with_commas(rx.selected_files, ed1)); } } else { ua->warning_msg(_("No files selected to be restored.\n")); goto bail_out; } if (rx.restore_jobs == 1) { job = rx.restore_job; } else { job = get_restore_job(ua); } if (!job) { goto bail_out; } if (!get_client_name(ua, &rx)) { goto bail_out; } if (!rx.ClientName) { ua->error_msg(_("No Client resource found!\n")); goto bail_out; } if (!get_restore_client_name(ua, rx)) { goto bail_out; } escaped_bsr_name = escape_filename(jcr->RestoreBootstrap); Mmsg(ua->cmd, "run job=\"%s\" client=\"%s\" restoreclient=\"%s\" storage=\"%s\"" " bootstrap=\"%s\" files=%u catalog=\"%s\"", job->name(), rx.ClientName, rx.RestoreClientName, rx.store?rx.store->name():"", escaped_bsr_name ? escaped_bsr_name : jcr->RestoreBootstrap, rx.selected_files, ua->catalog->name()); /* * Build run command */ if (rx.backup_format) { Mmsg(buf, " backupformat=%s", rx.backup_format); pm_strcat(ua->cmd, buf); } pm_strcpy(buf, ""); if (rx.RegexWhere) { escaped_where_name = escape_filename(rx.RegexWhere); Mmsg(buf, " regexwhere=\"%s\"", escaped_where_name ? escaped_where_name : rx.RegexWhere); } else if (rx.where) { escaped_where_name = escape_filename(rx.where); Mmsg(buf," where=\"%s\"", escaped_where_name ? escaped_where_name : rx.where); } pm_strcat(ua->cmd, buf); if (rx.replace) { Mmsg(buf, " replace=%s", rx.replace); pm_strcat(ua->cmd, buf); } if (rx.plugin_options) { Mmsg(buf, " pluginoptions=%s", rx.plugin_options); pm_strcat(ua->cmd, buf); } if (rx.comment) { Mmsg(buf, " comment=\"%s\"", rx.comment); pm_strcat(ua->cmd, buf); } if (escaped_bsr_name != NULL) { bfree(escaped_bsr_name); } if (escaped_where_name != NULL) { bfree(escaped_where_name); } if (regexp) { bfree(regexp); } if (find_arg(ua, NT_("yes")) > 0) { pm_strcat(ua->cmd, " yes"); /* pass it on to the run command */ } Dmsg1(200, "Submitting: %s\n", ua->cmd); /* * Transfer jobids to jcr to for picking up restore objects */ jcr->JobIds = rx.JobIds; rx.JobIds = NULL; parse_ua_args(ua); run_cmd(ua, ua->cmd); free_rx(&rx); garbage_collect_memory(); /* release unused memory */ return true; bail_out: if (escaped_bsr_name != NULL) { bfree(escaped_bsr_name); } if (escaped_where_name != NULL) { bfree(escaped_where_name); } if (regexp) { bfree(regexp); } free_rx(&rx); garbage_collect_memory(); /* release unused memory */ return false; }
int main (int argc, char *argv[]) { int ch; FILE *fd; char line[1000]; bool got_inc = false; setlocale(LC_ALL, ""); bindtextdomain("bareos", LOCALEDIR); textdomain("bareos"); init_stack_dump(); lmgr_init_thread(); working_directory = "/tmp"; my_name_is(argc, argv, "bextract"); init_msg(NULL, NULL); /* setup message handler */ OSDependentInit(); ff = init_find_files(); binit(&bfd); while ((ch = getopt(argc, argv, "b:c:D:d:e:i:pvV:?")) != -1) { switch (ch) { case 'b': /* bootstrap file */ bsr = parse_bsr(NULL, optarg); // dump_bsr(bsr, true); break; case 'c': /* specify config file */ if (configfile != NULL) { free(configfile); } configfile = bstrdup(optarg); break; case 'D': /* specify director name */ if (DirectorName != NULL) { free(DirectorName); } DirectorName = bstrdup(optarg); break; case 'd': /* debug level */ if (*optarg == 't') { dbg_timestamp = true; } else { debug_level = atoi(optarg); if (debug_level <= 0) { debug_level = 1; } } break; case 'e': /* exclude list */ if ((fd = fopen(optarg, "rb")) == NULL) { berrno be; Pmsg2(0, _("Could not open exclude file: %s, ERR=%s\n"), optarg, be.bstrerror()); exit(1); } while (fgets(line, sizeof(line), fd) != NULL) { strip_trailing_junk(line); Dmsg1(900, "add_exclude %s\n", line); add_fname_to_exclude_list(ff, line); } fclose(fd); break; case 'i': /* include list */ if ((fd = fopen(optarg, "rb")) == NULL) { berrno be; Pmsg2(0, _("Could not open include file: %s, ERR=%s\n"), optarg, be.bstrerror()); exit(1); } while (fgets(line, sizeof(line), fd) != NULL) { strip_trailing_junk(line); Dmsg1(900, "add_include %s\n", line); add_fname_to_include_list(ff, 0, line); } fclose(fd); got_inc = true; break; case 'p': forge_on = true; break; case 'v': verbose++; break; case 'V': /* Volume name */ VolumeName = optarg; break; case '?': default: usage(); } /* end switch */ } /* end while */ argc -= optind; argv += optind; if (argc != 2) { Pmsg0(0, _("Wrong number of arguments: \n")); usage(); } if (configfile == NULL) { configfile = bstrdup(CONFIG_FILE); } config = new_config_parser(); parse_sd_config(config, configfile, M_ERROR_TERM); LockRes(); me = (STORES *)GetNextRes(R_STORAGE, NULL); if (!me) { UnlockRes(); Emsg1(M_ERROR_TERM, 0, _("No Storage resource defined in %s. Cannot continue.\n"), configfile); } UnlockRes(); if (DirectorName) { foreach_res(director, R_DIRECTOR) { if (bstrcmp(director->hdr.name, DirectorName)) { break; } } if (!director) { Emsg2(M_ERROR_TERM, 0, _("No Director resource named %s defined in %s. Cannot continue.\n"), DirectorName, configfile); } } load_sd_plugins(me->plugin_directory); read_crypto_cache(me->working_directory, "bareos-sd", get_first_port_host_order(me->sdaddrs)); if (!got_inc) { /* If no include file, */ add_fname_to_include_list(ff, 0, "/"); /* include everything */ } where = argv[1]; do_extract(argv[0]); if (bsr) { free_bsr(bsr); } if (prog_name_msg) { Pmsg1(000, _("%d Program Name and/or Program Data Stream records ignored.\n"), prog_name_msg); } if (win32_data_msg) { Pmsg1(000, _("%d Win32 data or Win32 gzip data stream records. Ignored.\n"), win32_data_msg); } term_include_exclude_files(ff); term_find_files(ff); return 0; }