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

📄 chg-scsi-chio.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  $Id: chg-scsi-chio.c,v 1.12 2006/07/25 18:18:46 martinea Exp $ * *  chg-scsi-chio.c -- generic SCSI changer driver * *  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"int Tape_Ready1 ( char *tapedev , int wait);char *tapestatfile = NULL;/*----------------------------------------------------------------------------*/typedef enum{  NUMDRIVE,EJECT,SLEEP,CLEANMAX,DRIVE,START,END,CLEAN,DEVICE,STATFILE,CLEANFILE,DRIVENUM,    CHANGERDEV,USAGECOUNT,SCSITAPEDEV, TAPESTATFILE    } token_t;typedef struct {  char *word;  token_t token;} tokentable_t;tokentable_t t_table[]={  { "number_configs",	NUMDRIVE},  { "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},  { NULL,		-1 }};changer_t *changer;void	init_changer_struct(changer_t *chg, size_t number_of_config);void	dump_changer_struct(changer_t *chg);void	free_changer_struct(changer_t **changer);void	parse_line(char *linebuffer,int *token,char **value);int	read_config(char *configfile, changer_t *chg);int	get_current_slot(char *count_file);void	put_current_slot(char *count_file,int slot);void	usage(char *argv[]);int	get_relative_target(int fd,int nslots,char *parameter,int loaded,                         char *changer_file,int slot_offset,int maxslot);int	is_positive_number(char *tmp);int	ask_clean(char *tapedev);void	clean_tape(int fd,char *tapedev,char *cnt_file, int drivenum,                 int cleancart, int maxclean,char *usagetime);int	main(int argc, char *argv[]);/* * Initialize data structures with default values*/voidinit_changer_struct(    changer_t *	chg,    size_t	number_of_config){  size_t i;   memset(chg, 0, SIZEOF(*chg));  chg->number_of_configs = number_of_config;  chg->eject = 1;  chg->sleep = 0;  chg->cleanmax = 0;  chg->device = NULL;  chg->conf = alloc(SIZEOF(config_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(_("Tapes need sleep: %lld seconds\n"), (long long)chg->sleep);  dbprintf(_("Clean cycles    : %d\n"), chg->cleanmax);  dbprintf(_("Changer device  : %s\n"), chg->device);  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].scsitapedev != NULL)      dbprintf(_("  SCSI Tape dev : %s\n"), chg->conf[i].scsitapedev);    else      dbprintf(_("  SCSI Tape dev : 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;  assert(changer != NULL);  assert(*changer != NULL);  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");  }  return;}/* * This function reads the specified configfile and fills the structure*/intread_config(    char *	configfile,    changer_t *	chg){  size_t numconf;  FILE *file;  int init_flag = 0;  size_t drivenum=0;  char *linebuffer;  int token;  char *value;  numconf = 1;  /* At least one configuration is assumed */  /* If there are more, it should be the first entry in the configurationfile */  if (NULL==(file=fopen(configfile,"r"))){    return (-1);  }  while (NULL != (linebuffer = agets(file))) {      if (linebuffer[0] == '\0') {	amfree(linebuffer);	continue;      }      parse_line(linebuffer,&token,&value);      if (token != -1){        if (0==init_flag) {          if (token != NUMDRIVE){            init_changer_struct(chg, numconf);          } else {            numconf = atoi(value);            init_changer_struct(chg, numconf);          }          init_flag=1;        }        switch (token){        case NUMDRIVE: if ((size_t)atoi(value) != numconf)          g_fprintf(stderr,_("Error: number_drives at wrong place, should be "                  "first in file\n"));        break;        case EJECT:          chg->eject = atoi(value);          break;        case SLEEP:          chg->sleep = atoi(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 CLEANMAX:          chg->cleanmax = atoi(value);          break;        case DRIVE:          drivenum = atoi(value);          if(drivenum >= numconf){            g_fprintf(stderr,_("Error: drive must be less than number_drives\n"));          }          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){            chg->conf[drivenum].timefile = stralloc(value);          } else {            g_fprintf(stderr,_("Error: drive is not less than number_drives"                    " usagecount ignored\n"));          }          break;        default:          g_fprintf(stderr,_("Error: Unknown token\n"));          break;        }      }    amfree(linebuffer);  }  amfree(linebuffer);  fclose(file);  return 0;}/*----------------------------------------------------------------------------*//*  The tape drive does not have an idea of current slot so *  we use a file to store the current slot.  It is not ideal *  but it gets the job done   */int get_current_slot(char *count_file){  FILE *inf;  int retval;  if ((inf=fopen(count_file,"r")) == NULL) {    g_fprintf(stderr, _("%s: unable to open current slot file (%s)\n"),            get_pname(), count_file);    return 0;  }  if (fscanf(inf, "%d", &retval) != 1) {    g_fprintf(stderr, _("%s: unable to read current slot file (%s)\n"),            get_pname(), count_file);    retval = 0;  }  fclose(inf);  return retval;}void put_current_slot(char *count_file,int slot){  FILE *inf;  if ((inf=fopen(count_file,"w")) == NULL) {    g_fprintf(stderr, _("%s: unable to open current slot file (%s)\n"),            get_pname(), count_file);    exit(2);  }  g_fprintf(inf, "%d\n", slot);  fclose(inf);}/* ----------------------------------------------------------------------    This stuff deals with parsing the command line */typedef struct com_arg{  char *str;  int command_code;  int takesparam;} argument;typedef struct com_stru{  int command_code;  char *parameter;} command;void	parse_args(int argc, char *argv[], command *rval);/* major command line args */#define COMCOUNT 5#define COM_SLOT 0#define COM_INFO 1#define COM_RESET 2#define COM_EJECT 3#define COM_CLEAN 4argument argdefs[]={{"-slot",COM_SLOT,1},                    {"-info",COM_INFO,0},                    {"-reset",COM_RESET,0},                    {"-eject",COM_EJECT,0},                    {"-clean",COM_CLEAN,0}};/* minor command line args */#define SLOTCOUNT 5#define SLOT_CUR 0#define SLOT_NEXT 1#define SLOT_PREV 2#define SLOT_FIRST 3#define SLOT_LAST 4argument slotdefs[]={{"current",SLOT_CUR,0},                     {"next",SLOT_NEXT,0},                     {"prev",SLOT_PREV,0},                     {"first",SLOT_FIRST,0},                     {"last",SLOT_LAST,0}};int is_positive_number(char *tmp) /* is the string a valid positive int? */{  int i=0;  if ((tmp==NULL)||(tmp[0]==0))    return 0;  while ((tmp[i]>='0')&&(tmp[i]<='9')&&(tmp[i]!=0))    i++;  if (tmp[i]==0)    return 1;  else    return 0;}

⌨️ 快捷键说明

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