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 + -
显示快捷键?