Beispiel #1
0
/* 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;
}
Beispiel #2
0
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;
}
Beispiel #3
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;
}
Beispiel #4
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;
        }
    }
}
Beispiel #5
0
/*
 * 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);
}