📄 scsi-changer-driver.c
字号:
/* * Print the scsi-changer-driver version */voidChangerDriverVersion(void){ DebugPrint(DEBUG_ERROR, SECTION_INFO, "scsi-changer-driver: %s\n",rcsid); SCSI_OS_Version();}/* * Try to generate an template which can be used as an example for the config file * */voidPrintConf(void){ extern OpenFiles_T *pDev; int count; char *cwd; g_printf(_("# Please replace every ??? with the correct parameter.\n")); g_printf(_("# It is not possible to guess everything :-)\n")); g_printf(_("# Remove the line if the option is not needed.")); g_printf(_("# Example: cleanmax if you have no cleaning tape")); g_printf(_("#\n")); g_printf(_( "number_configs 1 # Number of configs, you can have more than 1 config\n" " # if you have for example more than one drive, or you\n" " # to split your lib to use different dump levels\n" " #\n")); g_printf(_( "emubarcode 1 # If you drive has no barcode reader this will try\n" " # keep an inventory of your tapes to find them faster\n" " #\n")); g_printf(_( "havebarcode 0 # Set this to 1 if you have a library with a\n" " # barcode reader\n" " #\n")); g_printf(_( "debuglevel 0:0 # For debuging, see the docs /docs/TAPE-CHANGER\n" " #\n")); g_printf(_( "eject ??? # set this to 1 if your drive needs an eject before move\n" " #\n")); g_printf(_( "sleep ??? # How long to wait after an eject command before moving\n" " # the tape\n" " #\n")); for (count = 0; count < CHG_MAXDEV ; count++) { if (pDev[count].dev) { if (pDev[count].inquiry != NULL && pDev[count].inquiry->type == TYPE_CHANGER) { g_printf(_("changerdev %s # This is the device to communicate with the robot\n"), pDev[count].dev); break; } } } /* * Did we reach the end of the list ? * If no we found an changer and now we try to * get the element status for the count of slots */ if (count < CHG_MAXDEV) { pDev[count].functions->function_status(count, 1); } else { g_printf(_("changerdev ??? # Ups nothing found. Please check the docs\n")); } g_printf(_( " #\n")); g_printf(_( " # Here now comes the config for the first tape\n")); g_printf(_( "config 0 # This value is the one which is used in the amanda\n" " # config file to tell the chg-scsi programm which tape\n" " # and which slots to use\n" " #\n")); g_printf(_( "cleancart ??? # The slot where the cleaning tape is located\n" " # remove it if you have no cleaning tape\n" " #\n")); g_printf(_( "drivenum 0 # Which tape drive to use if there are more than one drive\n" " #\n")); g_printf(_( "dev ??? # Which is the raw device to read/write data from the tape\n" " # It is important to use the non rewinding tape, like\n" " # /dev/nrst0 on linux, /dev/nrsa0 on BSD ....\n" " #\n")); /* * OK now lets see if we have an direct SCSI channel * to the tape * If not thats not a problem */ for (count = 0; count < CHG_MAXDEV; count++) { if (pDev[count].dev) { if (pDev[count].inquiry != NULL && pDev[count].inquiry->type == TYPE_TAPE) { g_printf(_( "scsitapedev %s # This is the device to communicate with the tape\n" " # to get some device stats, not so important, and\n" " # if you run into problems delete it completely\n" " #\n"), pDev[count].dev); break; } } } if (STE != 0) { g_printf(_( "startuse 0 # Which is the first slot to use\n" " #\n")); g_printf(_( "enduse %zu # Which is the last slot to use.\n"), STE); } else { g_printf(_( "startuse ??? # Which is the first slot to use\n" " #\n")); g_printf(_( "enduse ??? # Which is the last slot to use.\n")); } g_printf(_( " # Decrement this value by 1 if you have a\n" " # cleaning tape in the last slot\n" " #\n")); if ((cwd = getcwd(NULL, 0)) == NULL) { cwd = _("<unknown>"); } g_printf(_("statfile %s/tape0-slot #\n"),cwd); g_printf(_("cleanfile %s/tape0-clean #\n"), cwd); g_printf(_("usagecount %s/tape0-totaltime #\n"), cwd); g_printf(_("tapestatus %s/tape0-tapestatus #\n"), cwd); g_printf(_("labelfile %s/labelfile #\n"), cwd);}/* * Try to create a list of tapes and labels which are in the current * magazin. The drive must be empty !! * * labelfile -> file name of the db * drive -> which drive should we use * eject -> the tape device needs an eject before move * start -> start at slot start * stop -> stop at slot stop * clean -> if we have an cleaning tape than this is the slot number of it * * return * 0 -> fail * 1 -> successfull * * ToDo: * Check if the tape/changer is ready for the next move * If an tape is loaded unload it and do initialize element status to * get all labels if an bar code reader is installed */voidInventory( char * labelfile, int drive, int eject, int start, int stop, int clean){ extern OpenFiles_T *pDev; size_t x; static int inv_done = 0; /* Inventory function called ?, marker to disable recursion */ MBC_T *pbarcoderes; /* Here we will pass the parameter to MapBarCode and get the result */ (void)start; /* Quiet unused parameter warning */ (void)stop; /* Quiet unused parameter warning */ DebugPrint(DEBUG_INFO,SECTION_MAP_BARCODE, _("##### START Inventory\n")); pbarcoderes = alloc(SIZEOF(MBC_T)); memset(pbarcoderes, 0 , SIZEOF(MBC_T)); if (inv_done != 0) { DebugPrint(DEBUG_INFO,SECTION_MAP_BARCODE, _("##### STOP inv_done -> %d Inventory\n"),inv_done); free(pbarcoderes); return; /*NOTREACHED*/ } inv_done = 1; barcode = BarCode(INDEX_CHANGER); pbarcoderes->action = RESET_VALID; MapBarCode(labelfile,pbarcoderes); /* * Check if an tape is loaded, if yes unload it * and do an INIT ELEMENT STATUS */ if (pDTE[0].status == 'F') { if (eject) { (void)eject_tape("", eject); } (void)unload(INDEX_TAPE, 0, 0); } GenericResetStatus(INDEX_CHANGER); for (x = 0; x < STE; x++) { if (x == (size_t)clean) { continue; } /* * Load the tape, on error try the next * error could be an empty slot for example */ if (load(INDEX_CHANGER, drive, x ) != 0) { DebugPrint(DEBUG_ERROR,SECTION_MAP_BARCODE, _("Load drive(%d) from(%d) failed\n"), drive, x); continue; } /* * Wait until the tape is ready */ Tape_Ready(INDEX_TAPECTL, 60); SCSI_CloseDevice(INDEX_TAPE); if ((chgscsi_result = (char *)tape_rdlabel(pDev[INDEX_TAPE].dev, &chgscsi_datestamp, &chgscsi_label)) == NULL) { pbarcoderes->action = UPDATE_SLOT; strncpy(pbarcoderes->data.voltag, chgscsi_label, SIZEOF(pbarcoderes->data.voltag)); pbarcoderes->data.slot = x; pbarcoderes->data.from = 0; pbarcoderes->data.LoadCount = 1; if (BarCode(INDEX_CHANGER) == 1) { strncpy(pbarcoderes->data.barcode, pDTE[drive].VolTag, SIZEOF(pbarcoderes->data.barcode)); MapBarCode(labelfile, pbarcoderes); } else { MapBarCode(labelfile, pbarcoderes); } } else { DebugPrint(DEBUG_ERROR,SECTION_MAP_BARCODE, _("Read label failed\n")); } if (eject) { (void)eject_tape("", eject); } (void)unload(INDEX_TAPE, drive, x); } DebugPrint(DEBUG_INFO,SECTION_MAP_BARCODE, _("##### STOP Inventory\n")); free(pbarcoderes);}/* * Check if the slot ist empty * slot -> slot number to check */intisempty( int fd, int slot){ extern OpenFiles_T *pDev; DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### START isempty\n")); if (ElementStatusValid == 0) { if ( pDev[fd].functions->function_status(fd, 1) != 0) { DebugPrint(DEBUG_ERROR,SECTION_TAPE,_("##### STOP isempty [-1]\n")); return(-1); /*NOTREACHED*/ } } if (pSTE[slot].status == 'E') { DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### STOP isempty [1]\n")); return(1); /*NOTREACHED*/ } DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### STOP isempty [0]\n")); return(0);}intget_clean_state( char *tapedev){ extern OpenFiles_T *pDev; /* Return 1 if cleaning is needed */ int ret; DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### START get_clean_state\n")); if (pDev[INDEX_TAPECTL].SCSI == 0) { DebugPrint(DEBUG_ERROR,SECTION_TAPE,_("##### STOP get_clean_state [-1]\n")); return(-1); /*NOTREACHED*/ } ret=pDev[INDEX_TAPECTL].functions->function_clean(tapedev); DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### STOP get_clean_state [%d]\n"), ret); return(ret);}/* * eject the tape * The parameter tapedev is not used. * Type describes if we should force the SCSI eject if available * normal eject is done with the ioctl *//* This function ejects the tape from the drive */inteject_tape( char * tapedev, int type){ extern OpenFiles_T *pDev; int ret; DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### START eject_tape %s\n"),tapedev); if (pDev[INDEX_TAPECTL].functions == NULL) return(-1); /* * Try to read the label */ if (pDev[INDEX_TAPE].avail == 1 && (changer->emubarcode == 1 || BarCode(INDEX_CHANGER))) { if (pDev[INDEX_TAPECTL].SCSI == 1 && pDev[INDEX_TAPECTL].avail) { DebugPrint(DEBUG_INFO,SECTION_TAPE,"##### eject_tape rewind\n"); pDev[INDEX_TAPECTL].functions->function_rewind(INDEX_TAPECTL); } else { DebugPrint(DEBUG_INFO,SECTION_TAPE,"##### eject_tape rewind2\n"); pDev[INDEX_TAPE].functions->function_rewind(INDEX_TAPE); } if (pDev[INDEX_TAPE].devopen == 1) { DebugPrint(DEBUG_INFO,SECTION_TAPE,"##### eject_tape close\n"); SCSI_CloseDevice(INDEX_TAPE); } DebugPrint(DEBUG_INFO,SECTION_TAPE,"##### tape_eject tape_rdlabel\n"); chgscsi_result = (char *)tape_rdlabel(pDev[INDEX_TAPE].dev, &chgscsi_datestamp, &chgscsi_label); } if (pDev[INDEX_TAPECTL].SCSI == 1 && pDev[INDEX_TAPECTL].avail == 1 && type == 1) { DebugPrint(DEBUG_INFO,SECTION_TAPE,"##### tape_eject eject\n"); ret=pDev[INDEX_TAPECTL].functions->function_eject(tapedev, type); DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### STOP (SCSI)eject_tape [%d]\n"), ret); return(ret); /*NOTREACHED*/ } if (pDev[INDEX_TAPE].avail == 1) { ret=Tape_Ioctl(INDEX_TAPE, IOCTL_EJECT); DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### STOP (ioctl)eject_tape [%d]\n"), ret); return(ret); /*NOTREACHED*/ } DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### STOP eject_tape [-1]\n")); return(-1);}/* Find an empty slot, starting at start, ending at start+count */intfind_empty( int fd, int start, int count){ extern OpenFiles_T *pDev; size_t x; size_t end; DebugPrint(DEBUG_INFO,SECTION_ELEMENT,_("###### START find_empty\n")); if (ElementStatusValid == 0) { if ( pDev[fd].functions->function_status(fd , 1) != 0) { DebugPrint(DEBUG_ERROR,SECTION_ELEMENT, _("###### END find_empty [-1]\n")); return((ssize_t)-1); /*NOTREACHED*/ } } if (count == 0) { end = STE; } else { end = start + count; } if (end > STE) { end = STE; } DebugPrint(DEBUG_INFO, SECTION_ELEMENT, _("start at %zu, end at %zu\n"), (size_t)start, (size_t)end); for (x = start; x < end; x++) { if (pSTE[x].status == 'E') { DebugPrint(DEBUG_INFO,SECTION_ELEMENT, _("###### END find_empty [%lu]\n"), x); return((ssize_t)x); /*NOTREACHED*/ } } DebugPrint(DEBUG_ERROR,SECTION_ELEMENT,_("###### END find_empty [-1]\n")); return((ssize_t)-1);}/* * See if the tape is loaded based on the information we * got back from the ReadElementStatus * return values * -1 -> Error (Fatal) * 0 -> drive is empty * 1 -> drive is loaded */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -