/* This function checks the label of a single tape, which may or may not * have been loaded by the changer. With the addition of char *dev, and *slot, * it has the same interface as taper_scan. slot should be the slot where * this tape is found, or NULL if no changer is in use. * Return value is the same as taper_scan. */ int scan_read_label( char *dev, char *slot, char *desired_label, char** label, char** timestamp, char** error_message) { Device * device; char *labelstr; DeviceStatusFlags device_status; char *new_label_errmsg; g_return_val_if_fail(dev != NULL, -1); if (*error_message == NULL) *error_message = stralloc(""); *label = *timestamp = NULL; device = device_open(dev); g_assert(device != NULL); if (device->status != DEVICE_STATUS_SUCCESS ) { *error_message = newvstrallocf(*error_message, _("%sError opening device %s: %s.\n"), *error_message, dev, device_error_or_status(device)); g_object_unref(device); amfree(*timestamp); amfree(*label); return -1; } if (!device_configure(device, TRUE)) { *error_message = newvstrallocf(*error_message, _("%sError configuring device %s: %s.\n"), *error_message, dev, device_error_or_status(device)); g_object_unref(device); amfree(*timestamp); amfree(*label); return -1; } device_status = device_read_label(device); if (device_status == DEVICE_STATUS_SUCCESS && device->volume_label != NULL) { *label = g_strdup(device->volume_label); *timestamp = strdup(device->volume_time); } else if (device_status & DEVICE_STATUS_VOLUME_UNLABELED) { if (!getconf_seen(CNF_LABEL_NEW_TAPES)) { *error_message = newvstrallocf(*error_message, _("%sFound an empty or non-amanda tape.\n"), *error_message); g_object_unref(device); return -1; } /* If we got a header, but the Device doesn't think it's labeled, then this * tape probably has some data on it, so refuse to automatically label it */ if (device->volume_header && device->volume_header->type != F_EMPTY) { *error_message = newvstrallocf(*error_message, _("%sFound a non-amanda tape; check and relabel it with 'amlabel -f'\n"), *error_message); g_object_unref(device); return -1; } g_object_unref(device); *label = find_brand_new_tape_label(&new_label_errmsg); if (*label != NULL) { *timestamp = stralloc("X"); *error_message = newvstrallocf(*error_message, _("%sFound an empty tape, will label it `%s'.\n"), *error_message, *label); return 3; } *error_message = newvstrallocf(*error_message, _("%s%s.\n"), *error_message, new_label_errmsg); return -1; } else { char * label_errstr; label_errstr = g_strdup_printf(_("Error reading label: %s.\n"), device_error_or_status(device)); *error_message = newvstralloc(*error_message, *error_message, label_errstr, NULL); g_free(label_errstr); return -1; } g_assert(*label != NULL && *timestamp != NULL); g_object_unref(device); *error_message = newvstrallocf(*error_message, _("%sread label `%s', date `%s'.\n"), *error_message, *label, *timestamp); /* Register this with the barcode database, even if its not ours. */ if (slot != NULL) { changer_label(slot, *label); } if (desired_label != NULL && strcmp(*label, desired_label) == 0) { /* Got desired label. */ return 1; } /* Is this actually an acceptable tape? */ labelstr = getconf_str(CNF_LABELSTR); if(!match(labelstr, *label)) { *error_message = newvstrallocf(*error_message, _("%slabel \"%s\" doesn't match \"%s\".\n"), *error_message, *label, labelstr); return -1; } else { tape_t *tp; if (strcmp(*timestamp, "X") == 0) { /* new, labeled tape. */ return 1; } tp = lookup_tapelabel(*label); if(tp == NULL) { *error_message = newvstrallocf(*error_message, _("%slabel \"%s\" matches labelstr but it is" " not listed in the tapelist file.\n"), *error_message, *label); return -1; } else if(tp != NULL && !reusable_tape(tp)) { *error_message = newvstrallocf(*error_message, _("%sTape with label %s is still active" " and cannot be overwritten.\n"), *error_message, *label); return -1; } } /* Yay! We got a good tape! */ return 2; }
char * find_brand_new_tape_label(char **errmsg) { char *format; char newlabel[AUTO_LABEL_MAX_LEN]; char tmpnum[30]; /* 64-bit integers can be 21 digists... */ char tmpfmt[16]; char *auto_pos = NULL; int i; ssize_t label_len, auto_len; tape_t *tp; *errmsg = NULL; if (!getconf_seen(CNF_LABEL_NEW_TAPES)) { return NULL; } format = getconf_str(CNF_LABEL_NEW_TAPES); memset(newlabel, 0, AUTO_LABEL_MAX_LEN); label_len = 0; auto_len = -1; /* Only find the first '%' */ while (*format != '\0') { if (label_len + 4 > AUTO_LABEL_MAX_LEN) { *errmsg = _("Auto label format is too long!"); return NULL; } if (*format == '\\') { /* Copy the next character. */ newlabel[label_len++] = format[1]; format += 2; } else if (*format == '%' && auto_len == -1) { /* This is the format specifier. */ auto_pos = newlabel + label_len; auto_len = 0; while (*format == '%' && label_len < AUTO_LABEL_MAX_LEN) { newlabel[label_len++] = '%'; auto_len ++; format ++; } } else { /* Just copy a character. */ newlabel[label_len++] = *(format++); } } /* Sometimes we copy the null, sometimes not. */ if (newlabel[label_len] != '\0') { newlabel[label_len++] = '\0'; } if (auto_pos == NULL) { *errmsg = _("Auto label template contains no '%%'!"); return NULL; } g_snprintf(tmpfmt, SIZEOF(tmpfmt), "%%0%zdd", (size_t)auto_len); for (i = 1; i < INT_MAX; i ++) { g_snprintf(tmpnum, SIZEOF(tmpnum), tmpfmt, i); if (strlen(tmpnum) != (size_t)auto_len) { *errmsg = _("All possible auto-labels used."); return NULL; } strncpy(auto_pos, tmpnum, (size_t)auto_len); tp = lookup_tapelabel(newlabel); if (tp == NULL) { /* Got it. Double-check that this is a labelstr match. */ if (!match(getconf_str(CNF_LABELSTR), newlabel)) { *errmsg = g_strdup_printf(_("New label %s does not match labelstr %s from amanda.conf"), newlabel, getconf_str(CNF_LABELSTR)); return NULL; } return stralloc(newlabel); } } /* Should not get here unless you have over two billion tapes. */ *errmsg = _("Taper internal error in find_brand_new_tape_label."); return 0; }
int main( int argc, char ** argv) { int i; time_t timer; char *lineread = NULL; struct sigaction act, oact; extern char *optarg; extern int optind; char *line = NULL; const security_driver_t *secdrv; char *req = NULL; int response_error; struct tm *tm; config_overrides_t *cfg_ovr; char *starting_hostname = NULL; /* * Configure program for internationalization: * 1) Only set the message locale for now. * 2) Set textdomain for all amanda related programs to "amanda" * We don't want to be forced to support dozens of message catalogs. */ setlocale(LC_MESSAGES, "C"); textdomain("amanda"); safe_fd(-1, 0); set_pname("amrecover"); /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); dbopen(DBG_SUBDIR_CLIENT); /* treat amrecover-specific command line options as the equivalent * -o command-line options to set configuration values */ cfg_ovr = new_config_overrides(argc/2); /* If the first argument is not an option flag, then we assume * it is a configuration name to match the syntax of the other * Amanda utilities. */ if (argc > 1 && argv[1][0] != '-') { add_config_override(cfg_ovr, "conf", argv[1]); /* remove that option from the command line */ argv[1] = argv[0]; argv++; argc--; } /* now parse regular command-line '-' options */ while ((i = getopt(argc, argv, "o:C:s:t:d:Uh:")) != EOF) { switch (i) { case 'C': add_config_override(cfg_ovr, "conf", optarg); break; case 's': add_config_override(cfg_ovr, "index_server", optarg); break; case 't': add_config_override(cfg_ovr, "tape_server", optarg); break; case 'd': add_config_override(cfg_ovr, "tapedev", optarg); break; case 'o': add_config_override_opt(cfg_ovr, optarg); break; case 'h': starting_hostname = g_strdup(optarg); break; case 'U': case '?': (void)g_printf(USAGE); return 0; } } if (optind != argc) { (void)g_fprintf(stderr, USAGE); exit(1); } /* load the base client configuration */ set_config_overrides(cfg_ovr); config_init(CONFIG_INIT_CLIENT, NULL); if (config_errors(NULL) >= CFGERR_WARNINGS) { config_print_errors(); if (config_errors(NULL) >= CFGERR_ERRORS) { g_critical(_("errors processing config file")); } } /* and now try to load the configuration named in that file */ config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY, getconf_str(CNF_CONF)); check_running_as(RUNNING_AS_ROOT); dbrename(get_config_name(), DBG_SUBDIR_CLIENT); our_features = am_init_feature_set(); our_features_string = am_feature_to_string(our_features); if (!starting_hostname) { starting_hostname = g_malloc(MAX_HOSTNAME_LENGTH+1); if (gethostname(starting_hostname, MAX_HOSTNAME_LENGTH) != 0) { error(_("cannot determine local host name\n")); /*NOTREACHED*/ } starting_hostname[MAX_HOSTNAME_LENGTH] = '\0'; } server_name = NULL; if (getconf_seen(CNF_INDEX_SERVER) == -2) { /* command line argument */ server_name = getconf_str(CNF_INDEX_SERVER); } if (!server_name) { server_name = getenv("AMANDA_SERVER"); if (server_name) { g_printf(_("Using index server from environment AMANDA_SERVER (%s)\n"), server_name); } } if (!server_name) { server_name = getconf_str(CNF_INDEX_SERVER); } if (!server_name) { error(_("No index server set")); /*NOTREACHED*/ } server_name = g_strdup(server_name); tape_server_name = NULL; if (getconf_seen(CNF_TAPE_SERVER) == -2) { /* command line argument */ tape_server_name = getconf_str(CNF_TAPE_SERVER); } if (!tape_server_name) { tape_server_name = getenv("AMANDA_TAPE_SERVER"); if (!tape_server_name) { tape_server_name = getenv("AMANDA_TAPESERVER"); if (tape_server_name) { g_printf(_("Using tape server from environment AMANDA_TAPESERVER (%s)\n"), tape_server_name); } } else { g_printf(_("Using tape server from environment AMANDA_TAPE_SERVER (%s)\n"), tape_server_name); } } if (!tape_server_name) { tape_server_name = getconf_str(CNF_TAPE_SERVER); } if (!tape_server_name) { error(_("No tape server set")); /*NOTREACHED*/ } tape_server_name = g_strdup(tape_server_name); amfree(tape_device_name); tape_device_name = getconf_str(CNF_TAPEDEV); if (!tape_device_name || strlen(tape_device_name) == 0 || !getconf_seen(CNF_TAPEDEV)) { tape_device_name = NULL; } else { tape_device_name = g_strdup(tape_device_name); } authopt = g_strdup(getconf_str(CNF_AUTH)); amfree(disk_name); amfree(mount_point); amfree(disk_path); dump_date[0] = '\0'; /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); /* set up signal handler */ act.sa_handler = sigint_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; if (sigaction(SIGINT, &act, &oact) != 0) { error(_("error setting signal handler: %s"), strerror(errno)); /*NOTREACHED*/ } proplist = g_hash_table_new_full(g_str_hash, g_str_equal, &g_free, &free_property_t); protocol_init(); /* We assume that amindexd support fe_amindexd_options_features */ /* and fe_amindexd_options_auth */ /* We should send a noop to really know */ req = g_strdup_printf("SERVICE amindexd\n" "OPTIONS features=%s;auth=%s;\n", our_features_string, authopt); secdrv = security_getdriver(authopt); if (secdrv == NULL) { error(_("no '%s' security driver available for host '%s'"), authopt, server_name); /*NOTREACHED*/ } protocol_sendreq(server_name, secdrv, generic_client_get_security_conf, req, STARTUP_TIMEOUT, amindexd_response, &response_error); amfree(req); protocol_run(); g_printf(_("AMRECOVER Version %s. Contacting server on %s ...\n"), VERSION, server_name); if(response_error != 0) { g_fprintf(stderr,"%s\n",errstr); exit(1); } /* get server's banner */ if (grab_reply(1) == -1) { aclose(server_socket); exit(1); } if (!server_happy()) { dbclose(); aclose(server_socket); exit(1); } /* try to get the features from the server */ { char *their_feature_string = NULL; indexsrv_features = NULL; line = g_strdup_printf("FEATURES %s", our_features_string); if(exchange(line) == 0) { their_feature_string = g_strdup(server_line+13); indexsrv_features = am_string_to_feature(their_feature_string); if (!indexsrv_features) g_printf(_("Bad feature string from server: %s"), their_feature_string); } if (!indexsrv_features) indexsrv_features = am_set_default_feature_set(); amfree(their_feature_string); amfree(line); } /* set the date of extraction to be today */ (void)time(&timer); tm = localtime(&timer); if (tm) strftime(dump_date, sizeof(dump_date), "%Y-%m-%d", tm); else error(_("BAD DATE")); g_printf(_("Setting restore date to today (%s)\n"), dump_date); line = g_strdup_printf("DATE %s", dump_date); if (converse(line) == -1) { aclose(server_socket); exit(1); } amfree(line); line = g_strdup_printf("SCNF %s", get_config_name()); if (converse(line) == -1) { aclose(server_socket); exit(1); } amfree(line); if (server_happy()) { /* set host we are restoring to this host by default */ amfree(dump_hostname); set_host(starting_hostname); if (dump_hostname) g_printf(_("Use the setdisk command to choose dump disk to recover\n")); else g_printf(_("Use the sethost command to choose a host to recover\n")); } quit_prog = 0; do { if ((lineread = readline("amrecover> ")) == NULL) { clearerr(stdin); putchar('\n'); break; } if (lineread[0] != '\0') { add_history(lineread); dbprintf(_("user command: '%s'\n"), lineread); process_line(lineread); /* act on line's content */ } amfree(lineread); } while (!quit_prog); dbclose(); aclose(server_socket); return 0; }
/* Link up the TaperSource with the Device, including retries etc. */ static void run_device_output(taper_state_t * taper_state, dump_info_t * dump_info) { GValue val; guint file_number; dump_info->current_part = 1; dump_info->total_time.tv_sec = 0; dump_info->total_time.tv_usec = 0; dump_info->total_bytes = 0; for (;;) { GTimeVal start_time, end_time, run_time; StreamingRequirement streaming_mode; queue_result_flags queue_result; CountingConsumerData consumer_data; dumpfile_t *this_header; size_t max_memory; this_header = munge_headers(dump_info); if (this_header == NULL) { char * qdiskname = quote_string(dump_info->diskname); char * errstr = taper_source_get_errmsg(dump_info->source); if (!errstr) errstr = "Failed reading dump header."; errstr = quote_string(errstr); putresult(FAILED, "%s INPUT-ERROR TAPE-GOOD %s \"\"\n", dump_info->handle, errstr); log_add(L_FAIL, "%s %s %s %d %s", dump_info->hostname, qdiskname, dump_info->timestamp, dump_info->level, errstr); amfree(qdiskname); amfree(errstr); return; } if (!find_and_label_new_tape(taper_state, dump_info)) { bail_no_volume(dump_info, taper_state->last_errmsg); dumpfile_free(this_header); return; } while (!device_start_file(taper_state->device, this_header)) { /* Close the device. */ device_finish(taper_state->device); g_object_unref(taper_state->device); taper_state->device = NULL; if (!find_and_label_new_tape(taper_state, dump_info)) { bail_no_volume(dump_info, taper_state->last_errmsg); dumpfile_free(this_header); return; } } dumpfile_free(this_header); bzero(&val, sizeof(val)); if (!device_property_get(taper_state->device, PROPERTY_STREAMING, &val) || !G_VALUE_HOLDS(&val, STREAMING_REQUIREMENT_TYPE)) { g_fprintf(stderr, "taper: Couldn't get streaming type!\n"); streaming_mode = STREAMING_REQUIREMENT_REQUIRED; } else { streaming_mode = g_value_get_enum(&val); } file_number = taper_state->device->file; consumer_data.next_consumer = device_write_consumer; consumer_data.next_consumer_data = taper_state->device; consumer_data.bytes_written = 0; g_get_current_time(&start_time); if (getconf_seen(CNF_DEVICE_OUTPUT_BUFFER_SIZE)) { max_memory = getconf_size(CNF_DEVICE_OUTPUT_BUFFER_SIZE); if (getconf_seen(CNF_TAPEBUFS)) { g_fprintf(stderr, "Configuration directives 'device_output_buffer_size' " "and \n" "'tapebufs' are incompatible; using former.\n"); } } else if (getconf_seen(CNF_TAPEBUFS)) { max_memory = getconf_int(CNF_TAPEBUFS) * taper_state->device->block_size; } else { /* Use default. */ max_memory = getconf_size(CNF_DEVICE_OUTPUT_BUFFER_SIZE); } queue_result = do_consumer_producer_queue_full (taper_source_producer, dump_info->source, counting_consumer, &consumer_data, taper_state->device->block_size, max_memory, streaming_mode); g_get_current_time(&end_time); run_time = timesub(end_time, start_time); /* The device_write_consumer leaves the file open, so close it now. */ if (!device_finish_file(taper_state->device)) { queue_result = queue_result | QUEUE_CONSUMER_ERROR; } if (!finish_part_attempt(taper_state, dump_info, queue_result, run_time, consumer_data.bytes_written)) { break; } } }
/* * This function should move the cleaning cartridge into the drive */ void clean_tape( int fd, char * tapedev, char * cnt_file, int drivenum, int cleancart, int maxclean, char * usagetime) { int counter; char *mailer; if (cleancart == -1 ){ return; } mailer = getconf_str(CNF_MAILER); /* Now we should increment the counter */ if (cnt_file != NULL){ counter = get_current_slot(cnt_file); counter++; if (counter>=maxclean){ /* Now we should inform the administrator */ char *mail_cmd; FILE *mailf; int mail_pipe_opened = 1; if (mailer && *mailer != '\0') { if (getconf_seen(CNF_MAILTO) && strlen(getconf_str(CNF_MAILTO)) > 0 && validate_mailto(getconf_str(CNF_MAILTO))) { mail_cmd = vstralloc(mailer, " -s", " \"", _("AMANDA PROBLEM: PLEASE FIX"), "\"", " ", getconf_str(CNF_MAILTO), NULL); if ((mailf = popen(mail_cmd, "w")) == NULL) { g_printf(_("Mail failed\n")); error(_("could not open pipe to \"%s\": %s"), mail_cmd, strerror(errno)); /*NOTREACHED*/ } } else { mail_pipe_opened = 0; mailf = stderr; g_fprintf(mailf, _("\nNo mail recipient specified, output redirected to stderr")); } } else { mail_pipe_opened = 0; mailf = stderr; g_fprintf(mailf, _("\nNo mailer specified; output redirected to stderr")); } g_fprintf(mailf, _("\nThe usage count of your cleaning tape in slot %d"), cleancart); g_fprintf(mailf,_("\nis more than %d. (cleanmax)"),maxclean); g_fprintf(mailf,_("\nTapedrive %s needs to be cleaned"),tapedev); g_fprintf(mailf,_("\nPlease insert a new cleaning tape and reset")); g_fprintf(mailf,_("\nthe countingfile %s"),cnt_file); if(mail_pipe_opened == 1 && pclose(mailf) != 0) { error(_("mail command failed: %s"), mail_cmd); /*NOTREACHED*/ } return; } put_current_slot(cnt_file,counter); } load(fd,drivenum,cleancart); if (drive_loaded(fd, drivenum)) unload(fd,drivenum,cleancart); unlink(usagetime); }