X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Ftaper.c;h=d5b72af25578559da2f06619a78911551d6060ce;hb=fb2bd066c2f8b34addafe48d62550e3033a59431;hp=4b54430c2ee4add5766afc24ae42360d268eebba;hpb=a6127998ee6dcab6bb034f6ca985b07804a86f9a;p=debian%2Famanda diff --git a/server-src/taper.c b/server-src/taper.c index 4b54430..d5b72af 100644 --- a/server-src/taper.c +++ b/server-src/taper.c @@ -394,6 +394,39 @@ static gboolean check_volume_changed(Device * device, return FALSE; } +static void +update_tapelist( + taper_state_t *state) +{ + char *tapelist_name = NULL; + char *tapelist_name_old = NULL; + + tapelist_name = config_dir_relative(getconf_str(CNF_TAPELIST)); + if (state->cur_tape == 0) { + tapelist_name_old = stralloc2(tapelist_name, ".yesterday"); + } else { + char cur_str[NUM_STR_SIZE]; + g_snprintf(cur_str, SIZEOF(cur_str), "%d", state->cur_tape - 1); + tapelist_name_old = vstralloc(tapelist_name, + ".today.", cur_str, NULL); + } + + if (write_tapelist(tapelist_name_old)) { + error("could not write tapelist: %s", strerror(errno)); + /*NOTREACHED*/ + } + amfree(tapelist_name_old); + + remove_tapelabel(state->device->volume_label); + add_tapelabel(state->driver_start_time, + state->device->volume_label); + if (write_tapelist(tapelist_name)) { + error("could not write tapelist: %s", strerror(errno)); + /*NOTREACHED*/ + } + amfree(tapelist_name); +} + /* Find and label a new tape, if one is not already open. Returns TRUE * if a tape could be written. */ static gboolean find_and_label_new_tape(taper_state_t * state, @@ -410,10 +443,11 @@ static gboolean find_and_label_new_tape(taper_state_t * state, } static gboolean label_new_tape(taper_state_t * state, dump_info_t * dump_info) { - char *tapelist_name; - char *tapelist_name_old; - char * old_volume_name; - char * old_volume_time; + char *old_volume_name = NULL; + char *old_volume_time = NULL; + tape_search_request_t request; + gboolean search_result; + ReadLabelStatusFlags status; /* If we got here, it means that we have found a tape to label and * have gotten permission from the driver to write it. But we @@ -422,104 +456,54 @@ static gboolean label_new_tape(taper_state_t * state, dump_info_t * dump_info) { state->device = device_open(state->next_tape_device); amfree(state->next_tape_device); - if (state->device == NULL) { - amfree(state->next_tape_label); - return FALSE; - } - + if (state->device == NULL) + goto skip_volume; + device_set_startup_properties_from_config(state->device); - device_read_label(state->device); + + /* if we have an error, and are sure it isn't just an unlabeled volume, + * then skip this volume */ + status = device_read_label(state->device); + if ((status & ~READ_LABEL_STATUS_VOLUME_UNLABELED) && + !(status & READ_LABEL_STATUS_VOLUME_UNLABELED)) + goto skip_volume; + old_volume_name = g_strdup(state->device->volume_label); old_volume_time = g_strdup(state->device->volume_time); - + if (!device_start(state->device, ACCESS_WRITE, state->next_tape_label, state->driver_start_time)) { gboolean tape_used; + /* Something broke, see if we can tell if the volume was erased or * not. */ g_fprintf(stderr, "taper: Error writing label %s to device %s.\n", state->next_tape_label, state->device->device_name); - device_finish(state->device); - device_read_label(state->device); + + if (!device_finish(state->device)) + goto request_new_volume; + + /* This time, if we can't read the label, assume we've overwritten + * the volume or otherwise corrupted it */ + status = device_read_label(state->device); + if ((status & ~READ_LABEL_STATUS_VOLUME_UNLABELED) && + !(status & READ_LABEL_STATUS_VOLUME_UNLABELED)) + goto request_new_volume; + tape_used = check_volume_changed(state->device, old_volume_name, old_volume_time); - g_object_unref(state->device); - state->device = NULL; - amfree(state->next_tape_label); - /* If the volume was written, we tell the driver and then immediately - * try again. */ if (tape_used) { - putresult(NEW_TAPE, "%s %s\n", dump_info->handle, - state->device->volume_label); - if (old_volume_name) { - log_add(L_WARNING, "Problem writing label to volume %s, " - "volume may be erased.\n", old_volume_name); - } else { - log_add(L_WARNING, "Problem writing label %s to new volume, " - "volume may be erased.\n", state->next_tape_label); - } - amfree(old_volume_name); - amfree(old_volume_time); - return find_and_label_new_tape(state, dump_info); + goto request_new_volume; } else { - /* Otherwise, we grab a new tape without talking to the driver - * again. */ - tape_search_request_t request; - gboolean search_result; - if (old_volume_name) { - log_add(L_WARNING, "Problem writing label to volume %s, " - "old volume data intact\n", old_volume_name); - } else { - log_add(L_WARNING, "Problem writing label %s to new volume, " - "old volume data intact\n", state->next_tape_label); - } - amfree(old_volume_name); - amfree(old_volume_time); - request.state = state; - request.prolong = TRUE; - request.errmsg = NULL; - search_result = GPOINTER_TO_INT(tape_search_thread(&request)); - if (search_result) { - amfree(request.errmsg); - return label_new_tape(state, dump_info); - } else { - /* Problem finding a new tape! */ - log_taper_scan_errmsg(request.errmsg); - putresult(NO_NEW_TAPE, "%s\n", dump_info->handle); - return FALSE; - } + goto skip_volume; } - } else { - amfree(old_volume_name); - amfree(old_volume_time); } + amfree(old_volume_name); + amfree(old_volume_time); amfree(state->next_tape_label); - tapelist_name = config_dir_relative(getconf_str(CNF_TAPELIST)); - if (state->cur_tape == 0) { - tapelist_name_old = stralloc2(tapelist_name, ".yesterday"); - } else { - char cur_str[NUM_STR_SIZE]; - g_snprintf(cur_str, SIZEOF(cur_str), "%d", state->cur_tape - 1); - tapelist_name_old = vstralloc(tapelist_name, - ".today.", cur_str, NULL); - } - - if (write_tapelist(tapelist_name_old)) { - error("could not write tapelist: %s", strerror(errno)); - /*NOTREACHED*/ - } - amfree(tapelist_name_old); - - remove_tapelabel(state->device->volume_label); - add_tapelabel(state->driver_start_time, - state->device->volume_label); - if (write_tapelist(tapelist_name)) { - error("could not write tapelist: %s", strerror(errno)); - /*NOTREACHED*/ - } - amfree(tapelist_name); + update_tapelist(state); state->cur_tape++; log_add(L_START, "datestamp %s label %s tape %d", @@ -529,6 +513,66 @@ static gboolean label_new_tape(taper_state_t * state, dump_info_t * dump_info) { state->device->volume_label); return TRUE; + +request_new_volume: + /* Tell the driver we overwrote this volume, even if it was empty, and request + * a new volume. */ + if (state->device) { + g_object_unref(state->device); + state->device = NULL; + } + + putresult(NEW_TAPE, "%s %s\n", dump_info->handle, + state->next_tape_label); + if (old_volume_name) { + log_add(L_WARNING, "Problem writing label '%s' to volume %s, " + "volume may be erased.\n", + state->next_tape_label, old_volume_name); + } else { + log_add(L_WARNING, "Problem writing label '%s' to new volume, " + "volume may be erased.\n", state->next_tape_label); + } + + amfree(state->next_tape_label); + amfree(old_volume_name); + amfree(old_volume_time); + + return find_and_label_new_tape(state, dump_info); + +skip_volume: + /* grab a new volume without talking to the driver again -- we do this if we're + * confident we didn't overwrite the last tape we got. */ + if (state->device) { + g_object_unref(state->device); + state->device = NULL; + } + + if (old_volume_name) { + log_add(L_WARNING, "Problem writing label '%s' to volume '%s', " + "old volume data intact\n", + state->next_tape_label, old_volume_name); + } else { + log_add(L_WARNING, "Problem writing label '%s' to new volume, " + "old volume data intact\n", state->next_tape_label); + } + + amfree(state->next_tape_label); + amfree(old_volume_name); + amfree(old_volume_time); + + request.state = state; + request.prolong = TRUE; + request.errmsg = NULL; + search_result = GPOINTER_TO_INT(tape_search_thread(&request)); + if (search_result) { + amfree(request.errmsg); + return label_new_tape(state, dump_info); + } else { + /* Problem finding a new tape! */ + log_taper_scan_errmsg(request.errmsg); + putresult(NO_NEW_TAPE, "%s\n", dump_info->handle); + return FALSE; + } } /* Find out if the dump is PARTIAL or not, and set the proper driver