taperscan.c
来自「开源备份软件源码 AMANDA, the Advanced Marylan」· C语言 代码 · 共 586 行 · 第 1/2 页
C
586 行
/* * Copyright (c) 2005 Zmanda Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact information: Zmanda Inc, 505 N Mathlida Ave, Suite 120 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com *//* * $Id: taperscan.c,v 1.17 2006/07/12 12:28:19 martinea Exp $ * * This contains the implementation of the taper-scan algorithm, as it is * used by taper, amcheck, and amtape. See the header file taperscan.h for * interface information. */#include "amanda.h"#include "conffile.h"#include "changer.h"#include "tapefile.h"#include "device.h"#include "timestamp.h"#include "taperscan.h"struct taper_scan_tracker_s { GHashTable * scanned_slots;};int scan_read_label (char *dev, char * slot, char *wantlabel, char** label, char** timestamp, char**error_message);int changer_taper_scan (char *wantlabel, char** gotlabel, char** timestamp, char **tapedev, taper_scan_tracker_t * tracker, TaperscanOutputFunctor output_functor, void *output_data, TaperscanProlongFunctor prolong_functor, void *prolong_data);int scan_slot (void *data, int rc, char *slotstr, char *device);char *find_brand_new_tape_label (void);void FILE_taperscan_output_callback (void *data, char *msg);void CHAR_taperscan_output_callback (void *data, char *msg);/* NO GLOBALS PLEASE! *//* How does the taper scan algorithm work? Like this: * 1) If there is a barcode reader, and we have a recyclable tape, use the * reader to load the oldest tape. * 2) Otherwise, search through the changer until we find a new tape * or the oldest recyclable tape. * 3) If we couldn't find the oldest recyclable tape or a new tape, * but if in #2 we found *some* recyclable tape, use the oldest one we * found. * 4) At this point, we give up. *//* 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; ReadLabelStatusFlags label_status; g_return_val_if_fail(dev != NULL, -1); if (*error_message == NULL) *error_message = stralloc(""); *label = *timestamp = NULL; device = device_open(dev); if (device == NULL ) { *error_message = newvstrallocf(*error_message, _("%sError opening device %s.\n"), *error_message, dev); amfree(*timestamp); amfree(*label); return -1; } device_set_startup_properties_from_config(device); label_status = device_read_label(device); g_assert((device->volume_label != NULL) == (label_status == READ_LABEL_STATUS_SUCCESS)); if (device->volume_label != NULL) { *label = g_strdup(device->volume_label); *timestamp = strdup(device->volume_time); } else if (label_status & READ_LABEL_STATUS_VOLUME_UNLABELED) { g_object_unref(device); if (!getconf_seen(CNF_LABEL_NEW_TAPES)) { *error_message = newvstrallocf(*error_message, _("%sFound a non-amanda tape.\n"), *error_message); return -1; } *label = find_brand_new_tape_label(); if (*label != NULL) { *timestamp = stralloc("X"); *error_message = newvstrallocf(*error_message, _("%sFound a non-amanda tape, will label it `%s'.\n"), *error_message, *label); return 3; } *error_message = newvstrallocf(*error_message, _("%sFound a non-amanda tape, but have no labels left.\n"), *error_message); return -1; } else { char * label_errstr; char ** label_strv = g_flags_nick_to_strv(label_status, READ_LABEL_STATUS_FLAGS_TYPE); switch (g_strv_length(label_strv)) { case 0: label_errstr = g_strdup(_("Unknown error reading volume label.\n")); break; case 1: label_errstr = g_strdup_printf(_("Error reading volume label: %s\n"), *label_strv); break; default: { char * tmp_str = g_english_strjoinv(label_strv, "or"); label_errstr = g_strdup_printf(_("Error reading label: One of %s\n"), tmp_str); g_free(tmp_str); } } g_strfreev(label_strv); *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 overwriten.\n"), *error_message, *label); return -1; } } /* Yay! We got a good tape! */ return 2;}/* Interface is the same as taper_scan, with some additional bookkeeping. */typedef struct { char *wantlabel; char **gotlabel; char **timestamp; char **error_message; char **tapedev; char *slotstr; /* Best-choice slot number. */ char *first_labelstr_slot; int backwards; int tape_status; TaperscanOutputFunctor output_callback; void *output_data; TaperscanProlongFunctor prolong_callback; void * prolong_data; taper_scan_tracker_t * persistent;} changertrack_t;intscan_slot( void *data, int rc, char *slotstr, char *device){ int label_result; changertrack_t *ct = ((changertrack_t*)data); int result; if (ct->prolong_callback && !ct->prolong_callback(ct->prolong_data)) { return 1; } if (ct->persistent != NULL) { gpointer key; gpointer value; if (g_hash_table_lookup_extended(ct->persistent->scanned_slots, slotstr, &key, &value)) { /* We already returned this slot in a previous invocation, skip it now. */ return 0; } } if (*(ct->error_message) == NULL) *(ct->error_message) = stralloc(""); switch (rc) { default: *(ct->error_message) = newvstrallocf(*(ct->error_message), _("%sfatal changer error: slot %s: %s\n"), *(ct->error_message), slotstr, changer_resultstr); result = 1; break; case 1: *(ct->error_message) = newvstrallocf(*(ct->error_message), _("%schanger error: slot %s: %s\n"), *(ct->error_message), slotstr, changer_resultstr); result = 0; break; case 0: *(ct->error_message) = newvstrallocf(*(ct->error_message), _("slot %s:"), slotstr); amfree(*ct->gotlabel); amfree(*ct->timestamp); label_result = scan_read_label(device, slotstr, ct->wantlabel, ct->gotlabel, ct->timestamp, ct->error_message);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?