⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chg-scsi.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 4 页
字号:
static char rcsid[] = "$Id: chg-scsi.c,v 1.52 2006/07/25 18:18:46 martinea Exp $";/* *  * *  chg-scsi.c -- generic SCSI changer driver * *  This program provides the framework to control *  SCSI changers. It is based on the original chg-scsi *  from Eric Schnoebelen <eric@cirr.com> (Original copyright below) *  The device dependent part is handled by scsi-changer-driver.c *  The SCSI OS interface is handled by scsi-ostype.c * *  Original copyrights: * *  This program provides a driver to control generic *  SCSI changers, no matter what platform.  The host/OS *  specific portions of the interface are implemented *  in libscsi.a, which contains a module for each host/OS. *  The actual interface for HP/UX is in scsi-hpux.c; *  chio is in scsi-chio.c, etc..  A prototype system *  dependent scsi interface file is in scsi-proto.c. * *  Copyright 1997, 1998 Eric Schnoebelen <eric@cirr.com> * * This module based upon seagate-changer, by Larry Pyeatt *                  <pyeatt@cs.colostate.edu> * * The original introductory comments follow: * * This program was written to control the Seagate/Conner/Archive * autoloading DAT drive.  This drive normally has 4 tape capacity * but can be expanded to 12 tapes with an optional tape cartridge. * This program may also work on onther drives.  Try it and let me * know of successes/failures. * * I have attempted to conform to the requirements for Amanda tape * changer interface.  There could be some bugs.   * * This program works for me under Linux with Gerd Knorr's  * <kraxel@cs.tu-berlin.de> SCSI media changer driver installed  * as a kernel module.  The kernel module is available at  * http://sunsite.unc.edu/pub/Linux/kernel/patches/scsi/scsi-changer* * Since the Linux media changer is based on NetBSD, this program * should also work for NetBSD, although I have not tried it. * It may be necessary to change the IOCTL calls to work on other * OS's.   * * (c) 1897 Larry Pyeatt,  pyeatt@cs.colostate.edu  * All Rights Reserved. *  * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation.  The author makes no representations about the * suitability of this software for any purpose.   It is provided "as is" * without express or implied warranty. * * Michael C. Povel 03.06.98 added ejetct_tape and sleep for external tape * devices, and changed some code to allow multiple drives to use their * own slots. Also added support for reserverd slots. * At the moment these parameters are hard coded and only tested under Linux *  */#include "config.h"#include "amanda.h"#include "conffile.h"#include "libscsi.h"#include "scsi-defs.h"#include "tapeio.h"char *tapestatfile = NULL;FILE *debug_file = NULL;/*  * So we have 3 devices, here will all the infos be stored after an * successfull open  */OpenFiles_T *pDev = NULL;/* Defined in scsi-changer-driver.c */extern int ElementStatusValid;extern ElementInfo_T *pMTE; /*Medium Transport Element */extern ElementInfo_T *pSTE; /*Storage Element */extern ElementInfo_T *pIEE; /*Import Export Element */extern ElementInfo_T *pDTE; /*Data Transfer Element */extern size_t MTE;             /*Counter for the above element types */extern size_t STE;extern size_t IEE;extern size_t DTE;int do_inventory = 0;     /* Set if load/unload functions thinks an inventory should be done */int clean_slot = -1;typedef enum{  NUMDRIVE,EJECT,SLEEP,CLEANMAX,DRIVE,START,END,CLEAN,DEVICE,STATFILE,CLEANFILE,DRIVENUM,    CHANGERDEV,USAGECOUNT,SCSITAPEDEV, TAPESTATFILE, LABELFILE, CHANGERIDENT,    TAPEIDENT, EMUBARCODE, HAVEBARCODE, DEBUGLEVEL, AUTOINV    } token_t;typedef struct {  char *word;  token_t token;} tokentable_t;tokentable_t t_table[] = {  { "number_configs",	NUMDRIVE},  { "autoinv",		AUTOINV},  { "eject",		EJECT},  { "sleep",		SLEEP},  { "cleanmax",		CLEANMAX},  { "config",		DRIVE},  { "startuse",		START},  { "enduse",		END},  { "cleancart",	CLEAN},  { "dev",		DEVICE},  { "statfile",		STATFILE},  { "cleanfile",	CLEANFILE},  { "drivenum",		DRIVENUM},  { "changerdev",	CHANGERDEV},  { "usagecount",	USAGECOUNT},  { "scsitapedev",	SCSITAPEDEV},  { "tapestatus",	TAPESTATFILE},  { "labelfile",	LABELFILE},  { "changerident",	CHANGERIDENT},  { "tapeident",	TAPEIDENT},  { "emubarcode",	EMUBARCODE},  { "havebarcode",	HAVEBARCODE},  { "debuglevel",	DEBUGLEVEL},  { NULL,		-1 }};changer_t *changer;int ask_clean(char *tapedev);int get_current_slot(char *count_file);int get_relative_target(int fd, int nslots, char *parameter,		int param_index, int loaded, char *slot_file,		int slot_offset, int maxslot);int is_positive_number(char *tmp);int MapBarCode(char *labelfile, MBC_T *result);int read_config(char *configfile, changer_t *chg);void clean_tape(int fd, char *tapedev, char *cnt_file, int drivenum,		int cleancart, int maxclean, char *usagetime);void dump_changer_struct(changer_t *chg);void free_changer_struct(changer_t **chg);void init_changer_struct(changer_t *chg, int number_of_config);void parse_line(char *linebuffer, int *token,char **value);void put_current_slot(char *count_file, int slot);void usage(char *argv[]);int main(int argc, char *argv[]);/* Initialize data structures with default values */voidinit_changer_struct(    changer_t *chg,    int number_of_config){  int i;   memset(chg, 0, SIZEOF(*chg));  chg->number_of_configs = number_of_config;  chg->eject = 1;  chg->conf = alloc(SIZEOF(config_t) * (size_t)number_of_config);  for (i=0; i < number_of_config; i++){    chg->conf[i].drivenum     = 0;    chg->conf[i].start        = -1;    chg->conf[i].end          = -1;    chg->conf[i].cleanslot    = -1;    chg->conf[i].device       = NULL;    chg->conf[i].slotfile     = NULL;    chg->conf[i].cleanfile    = NULL;    chg->conf[i].timefile     = NULL;    chg->conf[i].scsitapedev  = NULL;    chg->conf[i].tapestatfile = NULL;    chg->conf[i].changerident = NULL;    chg->conf[i].tapeident    = NULL;  }}/* Dump of information for debug */voiddump_changer_struct(    changer_t *chg){  int i;  dbprintf(_("Number of configurations: %d\n"), chg->number_of_configs);  dbprintf(_("Tapes need eject: %s\n"), (chg->eject>0 ? _("Yes") : _("No")));  	dbprintf (_("\traw: %d\n"),chg->eject);  dbprintf(_("Inv. auto update: %s\n"), (chg->autoinv>0 ? _("Yes") : _("No")));  dbprintf (_("\traw: %d\n"),chg->autoinv);  dbprintf(_("barcode reader  : %s\n"), (chg->havebarcode>0 ? _("Yes") : _("No")));  dbprintf (_("\traw: %d\n"),chg->havebarcode);  dbprintf(_("Emulate Barcode : %s\n"), (chg->emubarcode>0 ? _("Yes") : _("No")));  dbprintf (_("\traw: %d\n"),chg->emubarcode);  if (chg->debuglevel != NULL)     dbprintf(_("debug level     : %s\n"), chg->debuglevel);  dbprintf(_("Tapes need sleep: %ld seconds\n"), (long int)chg->sleep);  dbprintf(_("Clean cycles    : %d\n"), chg->cleanmax);  dbprintf(_("Changer device  : %s\n"), chg->device);  if (chg->labelfile != NULL)    dbprintf(_("Label file      : %s\n"), chg->labelfile);  for (i=0; i<chg->number_of_configs; i++){    dbprintf(_("Tape config Nr: %d\n"), i);    dbprintf(_("  Drive number  : %d\n"), chg->conf[i].drivenum);    dbprintf(_("  Start slot    : %d\n"), chg->conf[i].start);    dbprintf(_("  End slot      : %d\n"), chg->conf[i].end);    dbprintf(_("  Clean slot    : %d\n"), chg->conf[i].cleanslot);    if (chg->conf[i].device != NULL)      dbprintf(_("  Device name   : %s\n"), chg->conf[i].device);    else      dbprintf(_("  Device name   : none\n"));    if (chg->conf[i].changerident != NULL)      dbprintf(_("  changer ident : %s\n"), chg->conf[i].changerident);    else      dbprintf(_("  changer ident : none\n"));    if (chg->conf[i].scsitapedev != NULL)      dbprintf(_("  SCSI Tape dev : %s\n"), chg->conf[i].scsitapedev);    else      dbprintf(_("  SCSI Tape dev : none\n"));    if (chg->conf[i].tapeident != NULL)      dbprintf(_("  tape ident    : %s\n"), chg->conf[i].tapeident);    else      dbprintf(_("  tape ident    : none\n"));    if (chg->conf[i].tapestatfile != NULL)      dbprintf(_("  stat file     : %s\n"), chg->conf[i].tapestatfile);    else      dbprintf(_("  stat file     : none\n"));    if (chg->conf[i].slotfile != NULL)      dbprintf(_("  Slot file     : %s\n"), chg->conf[i].slotfile);    else      dbprintf(_("  Slot file     : none\n"));    if (chg->conf[i].cleanfile != NULL)      dbprintf(_("  Clean file    : %s\n"), chg->conf[i].cleanfile);    else      dbprintf(_("  Clean file    : none\n"));    if (chg->conf[i].timefile != NULL)      dbprintf(_("  Usage count   : %s\n"), chg->conf[i].timefile);    else      dbprintf(_("  Usage count   : none\n"));  }}/* Free all allocated memory */voidfree_changer_struct(    changer_t **changer){  changer_t *chg;  int i;  chg = *changer;  if (chg->device != NULL)    amfree(chg->device);  for (i = 0; i < chg->number_of_configs; i++){    if (chg->conf[i].device != NULL)      amfree(chg->conf[i].device);    if (chg->conf[i].slotfile != NULL)      amfree(chg->conf[i].slotfile);    if (chg->conf[i].cleanfile != NULL)      amfree(chg->conf[i].cleanfile);    if (chg->conf[i].timefile != NULL)      amfree(chg->conf[i].timefile);  }  if (chg->conf != NULL)    amfree(chg->conf);  chg->conf = NULL;  chg->device = NULL;  amfree(*changer);}/* This function parses a line, and returns a token and value */voidparse_line(    char *linebuffer,    int *token,    char **value){  char *tok;  int i;  int ready = 0;  *token = -1;  /* No Token found */  tok=strtok(linebuffer," \t\n");  while ((tok != NULL) && (tok[0]!='#')&&(ready==0)){    if (*token != -1){      *value=tok;      ready=1;    } else {      i=0;      while ((t_table[i].word != NULL)&&(*token==-1)){        if (0==strcasecmp(t_table[i].word,tok)){          *token=t_table[i].token;        }        i++;      }    }    tok=strtok(NULL," \t\n");  }}/* This function reads the specified configfile and fills the structure */intread_config(    char *configfile,    changer_t *chg){  int numconf;  FILE *file;  int init_flag = 0;  int drivenum=0;  char *linebuffer;  int token;  char *value;  char *p;  numconf = 1;  /* At least one configuration is assumed */  /* If there are more, it should be the first entry in the configurationfile */  assert(chg != NULL);  if ((file=fopen(configfile,"r")) == NULL) {    return (-1);  }  while ((NULL != (linebuffer = agets(file)))) {      if (linebuffer[0] == '\0') {	amfree(linebuffer);	continue;      }      parse_line(linebuffer, &token, &value);      if (token != -1){	if (value == NULL)	  value = "0";        if (init_flag == 0) {          if (token != NUMDRIVE){            init_changer_struct(chg, numconf);          } else {            numconf = atoi(value);	    if (numconf < 1 || numconf > 100) {		g_fprintf(stderr,_("numconf %d is bad\n"), numconf);		numconf = 1;	    }            init_changer_struct(chg, numconf);          }          init_flag=1;        }        switch (token) {        case NUMDRIVE: if (atoi(value) != numconf)          g_fprintf(stderr,_("Error: number_drives at wrong place, should be "                  "first in file\n"));        break;        case AUTOINV:          chg->autoinv = 1;          break;        case EMUBARCODE:          chg->emubarcode = 1;          break;        case DEBUGLEVEL:          chg->debuglevel = stralloc(value);          break;        case EJECT:          chg->eject = atoi(value);          break;        case HAVEBARCODE:          chg->havebarcode = atoi(value);          break;       case SLEEP:          chg->sleep = (unsigned)atoi(value);          break;        case LABELFILE:          chg->labelfile = stralloc(value);          break;        case CHANGERDEV:          chg->device = stralloc(value);          break;        case SCSITAPEDEV:          chg->conf[drivenum].scsitapedev = stralloc(value);          break;        case TAPESTATFILE:          chg->conf[drivenum].tapestatfile = stralloc(value);          break;        case CHANGERIDENT:          chg->conf[drivenum].changerident = stralloc(value);	  if (drivenum < 0 || drivenum > 100) {	    g_fprintf(stderr,_("drivenum %d is bad\n"), drivenum);	    drivenum = 0;	  }	  if (strcmp(chg->conf[drivenum].changerident,"generic_changer") != 0) {            p = chg->conf[drivenum].changerident;            while (*p != '\0')            {              if (*p == '_')              {                *p=' ';              }              p++;            }	  }          break;        case TAPEIDENT:          chg->conf[drivenum].tapeident = stralloc(value);          break;        case CLEANMAX:          chg->cleanmax = atoi(value);          break;        case DRIVE:          drivenum = atoi(value);          if (drivenum < 0) {            g_fprintf(stderr,_("Error: drive must be >= 0\n"));	    drivenum = 0;          } else if (drivenum >= numconf) {            g_fprintf(stderr,_("Error: drive must be less than number_drives\n"));	    drivenum = numconf;          }          break;        case DRIVENUM:          if (drivenum < numconf){            chg->conf[drivenum].drivenum = atoi(value);          } else {            g_fprintf(stderr,_("Error: drive is not less than number_drives"                    " drivenum ignored\n"));          }          break;        case START:          if (drivenum < numconf){            chg->conf[drivenum].start = atoi(value);          } else {            g_fprintf(stderr,_("Error: drive is not less than number_drives"                    " startuse ignored\n"));          }          break;        case END:          if (drivenum < numconf){            chg->conf[drivenum].end = atoi(value);          } else {            g_fprintf(stderr,_("Error: drive is not less than number_drives"                    " enduse ignored\n"));          }          break;        case CLEAN:          if (drivenum < numconf){            chg->conf[drivenum].cleanslot = atoi(value);          } else {            g_fprintf(stderr,_("Error: drive is not less than number_drives"                    " cleanslot ignored\n"));          }          break;        case DEVICE:          if (drivenum < numconf){            chg->conf[drivenum].device = stralloc(value);          } else {            g_fprintf(stderr,_("Error: drive is not less than number_drives"                    " device ignored\n"));          }          break;        case STATFILE:          if (drivenum < numconf){            chg->conf[drivenum].slotfile = stralloc(value);          } else {            g_fprintf(stderr,_("Error: drive is not less than number_drives"                    " slotfile ignored\n"));          }          break;        case CLEANFILE:          if (drivenum < numconf){            chg->conf[drivenum].cleanfile = stralloc(value);          } else {            g_fprintf(stderr,_("Error: drive is not less than number_drives"                    " cleanfile ignored\n"));          }          break;        case USAGECOUNT:          if (drivenum < numconf){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -