mtx.c
来自「通用SCSI设备备份/读写程序」· C语言 代码 · 共 779 行 · 第 1/2 页
C
779 行
(ElementStatus->StorageElementFull[StorageElementNumber] ? "Full " : "Empty")); if (ElementStatus->PrimaryVolumeTag[StorageElementNumber][0]) { printf(":VolumeTag=%s",ElementStatus->PrimaryVolumeTag[StorageElementNumber]); } if (ElementStatus->AlternateVolumeTag[StorageElementNumber][0]) { printf(":AlternateVolumeTag=%s",ElementStatus->AlternateVolumeTag[StorageElementNumber]); } putchar('\n'); } #ifdef VMS VMS_DefineStatusSymbols();#endif}void Move(int src, int dest) { RequestSense_T *result; /* from MoveMedium */ result=MoveMedium(MediumChangerFD,src,dest,ElementStatus,inquiry_info,&SCSI_Flags); if (result) /* we have an error! */ { if (result->AdditionalSenseCode == 0x3B && result->AdditionalSenseCodeQualifier == 0x0E) FatalError("source Element Address %d is Empty\n", src); if (result->AdditionalSenseCode == 0x3B && result->AdditionalSenseCodeQualifier == 0x0D) FatalError("destination Element Address %d is Already Full\n", dest); if (result->AdditionalSenseCode == 0x30 && result->AdditionalSenseCodeQualifier == 0x03) FatalError("Cleaning Cartridge Installed and Ejected\n"); PrintRequestSense(result); FatalError("MOVE MEDIUM from Element Address %d to %d Failed\n", src,dest); }} /* okay, now for the Load, Unload, etc. logic: */static void Load(void) { int src, dest; /* okay, check src, dest: arg1=src, arg2=dest */ if (arg1 < 1) { FatalError("No source specified\n"); } if (arg2 < 0) { arg2 = 0; /* default to 1st drive :-( */ } arg1--; /* we use zero-based arrays, sigh, not 1 base like some lusers */ /* check for filehandle: */ if (!device_opened) { FatalError("No Media Changer Device Specified\n"); } /* okay, we should be there: */ if (arg1 < 0 || arg1 >= ElementStatus->StorageElementCount) { FatalError( "illegal <storage-element-number> argument '%s' to 'load' command\n", arg1+1); } if (arg2 < 0 || arg2 >= ElementStatus->DataTransferElementCount) { FatalError( "illegal <drive-number> argument '%s' to 'load' command\n", arg2); } if (ElementStatus->DataTransferElementFull[arg2]) { FatalError("Drive %d Full (Storage Element %d loaded)\n",arg2, ElementStatus->DataTransferElementSourceStorageElementNumber[arg2]+1); } /* Now look up the actual devices: */ dest=ElementStatus->DataTransferElementAddress[arg2]; src=ElementStatus->StorageElementAddress[arg1]; Move(src,dest); /* load it into the particular slot, if possible! */ /* now set the status for further command son this line... */ ElementStatus->StorageElementFull[arg1] = false; ElementStatus->DataTransferElementFull[arg2] = true; return; /* and done! */}static void Transfer(void) { int src,dest; if (arg1 < 1 ) { FatalError("No source specified\n"); } if (arg2 < 1) { FatalError("No destination specified\n"); } if (arg1 > ElementStatus->StorageElementCount) { FatalError("Invalid source\n"); } if (arg2 > ElementStatus->StorageElementCount) { FatalError("Invalid destination\n"); } /* okay, that's done... */ src=ElementStatus->StorageElementAddress[arg1-1]; dest=ElementStatus->StorageElementAddress[arg2-1]; Move(src,dest);}static void Eepos(void) { if (arg1 < 0 || arg1 > 3) { FatalError("eepos equires argument between 0 and 3.\n"); } SCSI_Flags.eepos=arg1;}static void Unload(void) { int src,dest; /* the actual SCSI-level numbers */ if (arg2 < 0) { arg2 = 0; /* default to 1st drive :-( */ } /* check for filehandle: */ if (!device_opened) { FatalError("No Media Changer Device Specified\n"); } /* okay, we should be there: */ if (arg1 < 0) { arg1 = ElementStatus->DataTransferElementSourceStorageElementNumber[arg2]; if (arg1 < 0) { FatalError("No Source for tape in drive %d!\n"); } } else { arg1--; /* go from bogus 1-base to zero-base */ } if (arg1 >= ElementStatus->StorageElementCount) { FatalError( "illegal <storage-element-number> argument '%s' to 'unload' command\n", arg1+1); } if (arg2 < 0 || arg2 >= ElementStatus->DataTransferElementCount) { FatalError( "illegal <drive-number> argument '%s' to 'unload' command\n", arg2); } if (ElementStatus->DataTransferElementFull[arg2] < 0 ) { FatalError("Data Transfer Element %d is Empty\n", arg2); } /* Now see if something already lives where we wanna go... */ if (ElementStatus->StorageElementFull[arg1]) { FatalError("Storage Element %d is Already Full\n", arg1+1); } /* okay, now to get src, dest: */ src=ElementStatus->DataTransferElementAddress[arg2]; if (arg1 >=0) { dest=ElementStatus->StorageElementAddress[arg1]; } else { dest=ElementStatus->DataTransferElementSourceStorageElementNumber[arg2]; } if (dest < 0) { /* we STILL don't know, sigh... */ FatalError("Do not know which slot to unload tape into!\n"); } fprintf(stderr, "Unloading Data Transfer Element into Storage Element %d...", arg1+1); fflush(stderr); /* make it real-time :-( */ Move(src,dest); fprintf(stderr, "done\n"); ElementStatus->StorageElementFull[arg1] = true; ElementStatus->DataTransferElementFull[arg2] = false;}/***************************************************************** ** ARGUMENT PARSING SUBROUTINES: Parse arguments, dispatch. *****************************************************************//* *** * int get_arg(idx): * * If we have an actual argument at the index position indicated (i.e. we * have not gone off the edge of the world), we return * its number. If we don't, or it's not a numeric argument, * we return -1. Note that 'get_arg' is kind of misleading, we only accept * numeric arguments, not any other kind. */int get_arg(int idx) { char *arg; int retval=-1; if (idx >= argc) return -1; /* sorry! */ arg=argv[idx]; if (*arg < '0' || *arg > '9') { return -1; /* sorry! */ } retval=atoi(arg); return retval;}/* open_device() -- set the 'fh' variable.... */void open_device(void) { if (device_opened) { SCSI_CloseDevice("Unknown",MediumChangerFD); /* close it, sigh... new device now! */ } MediumChangerFD = SCSI_OpenDevice(device); device_opened=1; /* SCSI_OpenDevice does an exit() if not. */} /* we see if we've got a file open. If not, we open one :-(. Then * we execute the actual command. Or not :-(. */ void execute_command(struct command_table_struct *command) { RequestSense_T RequestSense; if ((device==NULL) && command->need_device) { /* try to get it from TAPE environment variable... */ device=getenv("CHANGER"); if (device==NULL) { device=getenv("TAPE"); if (device==NULL) { device="/dev/changer"; /* Usage(); */ } } open_device(); } if (!ElementStatus && command->need_status) { inquiry_info=RequestInquiry(MediumChangerFD,&RequestSense); if (!inquiry_info) { PrintRequestSense(&RequestSense); FatalError("INQUIRY command Failed\n"); } ElementStatus = ReadElementStatus(MediumChangerFD,&RequestSense,inquiry_info,&SCSI_Flags); if (!ElementStatus) { PrintRequestSense(&RequestSense); FatalError("READ ELEMENT STATUS Command Failed\n"); } } /* okay, now to execute the command... */ command->command();}/* parse_args(): * Basically, we are parsing argv/argc. We can have multiple commands * on a line now, such as "unload 3 0 load 4 0" to unload one tape and * load in another tape into drive 0, and we execute these commands one * at a time as we come to them. If we don't have a -f at the start, we * barf. If we leave out a drive #, we default to drive 0 (the first drive * in the cabinet). */ int parse_args(void) { int i,cmd_tbl_idx; struct command_table_struct *command; i=1; while (i<argc) { if (strcmp(argv[i],"-f") == 0) { i++; if (i>=argc) { Usage(); } device=argv[i++]; open_device(); /* open the device and do a status scan on it... */ } else { cmd_tbl_idx=0; command=&command_table[0]; /* default to the first command... */ command=&command_table[cmd_tbl_idx]; while (command->name) { if (!strcmp(command->name,argv[i])) { /* we have a match... */ break; } /* otherwise we don't have a match... */ cmd_tbl_idx++; command=&command_table[cmd_tbl_idx]; } /* if it's not a command, exit.... */ if (!command->name) { Usage(); } i++; /* go to the next argument, if possible... */ /* see if we need to gather arguments, though! */ if (command->num_args == 0) { execute_command(command); /* execute_command handles 'stuff' */ } else { arg1=get_arg(i); /* checks i... */ if (arg1 != -1) { i++; /* next! */ } if (command->num_args==2 && arg1 != -1) { arg2=get_arg(i); if (arg2 != -1) { i++; } } execute_command(command); } arg1=-1; arg2=-1; } } return 0; /* should never get here. */}int main(int ArgCount, char *ArgVector[], char *Environment[]){#ifdef VMS RequestSense_T RequestSense;#endif /* save these where we can get at them elsewhere... */ argc=ArgCount; argv=ArgVector; argv0=argv[0]; parse_args(); /* also executes them as it sees them, sigh. */#ifndef VMS if (device) SCSI_CloseDevice(device, MediumChangerFD); return 0;#else if (device) { ElementStatus = ReadElementStatus(MediumChangerFD,&RequestSense); if (!ElementStatus) { PrintRequestSense(&RequestSense); FatalError("READ ELEMENT STATUS Command Failed\n"); } VMS_DefineStatusSymbols(); SCSI_CloseDevice(device, MediumChangerFD); } return SS$_NORMAL;#endif}/* *$Log: mtx.c,v $ *Revision 1.2.2.1 2001/11/06 21:20:40 elgreen *Hopefully a fix to the problem with the 0 return for open in crontabs * *Revision 1.2 2001/06/09 17:26:26 elgreen *Added 'nobarcode' command to mtx (to skip the initial request asking for *barcodes for mtx status purposes). * *Revision 1.1.1.1 2001/06/05 17:10:22 elgreen *Initial import into SourceForge * *Revision 1.15 2001/04/18 16:32:59 eric *Cleaned up all -Wall messages. * *Revision 1.14 2001/04/18 16:08:08 eric *after re-arranging & fixing bugs * *Revision 1.13 2001/03/06 01:37:05 eric *Solaris changes * *Revision 1.12 2001/01/24 22:04:08 eric *added /dev/changer as default file name. * *Revision 1.11 2001/01/15 22:21:06 eric *added autoconf stuff. * *Revision 1.10 2000/11/30 20:37:17 eric *Added quicky 'erase' command because I needed blank tapes and Linux *only does long erases. (Not documented on purpose, because of rather *bizarre interactions with the native tape driver if you don't know *what you are doing). * *Revision 1.9 2000/11/28 01:10:50 eric *Fixed syntax error in mtx.c... * *Revision 1.8 2000/10/28 00:10:35 eric *Fixed stupid typo * *Revision 1.7 2000/10/27 23:36:57 eric *make mtx inventory return an error code if the inventory fails, so that *we can wait for inventory to be completed at system startup * * */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?