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

📄 scsi-chio.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
字号:
/* *	$Id: scsi-chio.c,v 1.14 2006/05/25 01:47:07 johnfranks Exp $ * *	scsi-chio.c -- library routines to handle the changer *			support for chio based systems * *	Author: Eric Schnoebelen, eric@cirr.com *	based on work by: Larry Pyeatt,  pyeatt@cs.colostate.edu  *	Copyright: 1997, 1998 Eric Schnoebelen * *	Patch: Michael Enkelis, michaele@mxim.com) */#include "config.h"#include "amanda.h"#include <sys/types.h>#include <sys/ioctl.h>#include <sys/mtio.h>/* This include comes with Gerd Knor's SCSI media changer driver. * If you are porting to another system, this is the file that defines * ioctl calls for the changer.  You will have to track it down yourself * and possibly change all the ioctl() calls in this program.   */#if defined(HAVE_LINUX_CHIO_H)#  include <linux/chio.h>#else# if defined(HAVE_CHIO_H)#   include <chio.h># else /* HAVE_SYS_CHIO_H must be defined */#   include <sys/chio.h># endif	/* HAVE_CHIO_H */#endif  /* HAVE_LINUX_CHIO_H */char *modname = "@(#)" __FILE__ 		": SCSI support library for the chio(2) interface @(#)";/* * cache the general changer information, for faster access elsewhere */static struct changer_params changer_info;static int changer_info_init = 0;int GetCurrentSlot(int fd, int drive);int GetDeviceStatus (char *tapedev);int OpenDevice (char *tapedev);int CloseDevice (char *device, int DeviceFD);int Tape_Ready1 ( char *tapedev , int wait);int isempty(int fd, int slot);int find_empty(int fd, int start, int count);int get_clean_state(char *tapedev);int get_slot_count(int fd);int get_drive_count(int fd);int eject_tape(char *tapedev);int drive_loaded(int fd, int drivenum);int unload(int fd, int drive, int slot);int load(int fd, int drive, int slot);static int get_changer_info(int fd){int rc = 0;    if ( !changer_info_init ) {	rc = ioctl(fd, CHIOGPARAMS, &changer_info);	changer_info_init++;    }    return (rc);}/* Get the number of the first free slot * return > 0 number of empty slot * return = 0 no slot free * return < 0 error */int GetCurrentSlot(int fd, int drive){    struct changer_element_status  ces;    int slot;    int i, rc;    (void)drive;    get_changer_info(fd);    ces.ces_type = CHET_ST;    ces.ces_data = malloc(changer_info.cp_nslots);    rc = ioctl(fd, CHIOGSTATUS, &ces);    if (rc) {	dbprintf(_("changer status query failed: 0x%x %s\n"), rc, strerror(errno));	return -1;    }    for (slot = 0; slot < changer_info.cp_nslots; slot++)    {    	i = ces.ces_data[slot] & CESTATUS_FULL;    	dbprintf(_("\tGetCurrentSlot slot %d = %d\n"), slot, i);    	if (!i)            return(slot);    }    return -1;}int get_clean_state(char *tapedev){int rc;#if defined(BUILTIN)    rc = 0;#else#define GMT_CLN(x)	((x) & 0x00008000)    rc = ( GMT_CLN(GetDeviceStatus(tapedev)) );#endif	/* BUILTIN */    return rc;}int eject_tape(char *tapedev)/* This function ejects the tape from the drive */{int mtfd;struct mtop mt_com;    if ( (mtfd = OpenDevice(tapedev) ) < 0) {        dbprintf(_("eject_tape : failed\n"));        perror(tapedev);        exit(2);    }    mt_com.mt_op = MTOFFL;    mt_com.mt_count = 1;    if (ioctl(mtfd, MTIOCTOP, (char *)&mt_com) < 0) {/*    If the drive already ejected the tape due an error, or because it    was a cleaning tape, threre can be an error, which we should ignore        perror(tapedev);       exit(2);*/    }    return(CloseDevice(tapedev, mtfd));}/*  * this routine checks a specified slot to see if it is empty  */int isempty(int fd, int slot){struct changer_element_status  ces;int                            i,rc;int type=CHET_ST;    get_changer_info(fd);    ces.ces_type = type;    ces.ces_data = malloc(changer_info.cp_nslots);    rc = ioctl(fd, CHIOGSTATUS, &ces);    if (rc) {	dbprintf(_("changer status query failed: 0x%x %s\n"), rc,strerror(errno));	return -1;    }    i = ces.ces_data[slot] & CESTATUS_FULL;    free(ces.ces_data);    return !i;}/* * find the first empty slot  */int find_empty(int fd, int start, int count){struct changer_element_status  ces;int                            i,rc;int type=CHET_ST;    (void)start;    (void)count;    get_changer_info(fd);    ces.ces_type = type;    ces.ces_data = malloc(changer_info.cp_nslots);    rc = ioctl(fd,CHIOGSTATUS,&ces);    if (rc) {	dbprintf(_("changer status query failed: 0x%x %s\n"), rc, strerror(errno));	return -1;    }    i = 0;     while ((i < changer_info.cp_nslots)&&(ces.ces_data[i] & CESTATUS_FULL))	i++;    free(ces.ces_data);    return i;}/* * returns one if there is a tape loaded in the drive  */int drive_loaded(int fd, int drivenum){struct changer_element_status  ces;int                            i,rc;int type=CHET_DT;    get_changer_info(fd);    ces.ces_type = type;    ces.ces_data = malloc(changer_info.cp_ndrives);    rc = ioctl(fd, CHIOGSTATUS, &ces);    if (rc) {	dbprintf(_("drive status query failed: 0x%x %s\n"), rc, strerror(errno));	return -1;    }    i = (ces.ces_data[drivenum] & CESTATUS_FULL);    free(ces.ces_data);    return i;}/* * unloads the drive, putting the tape in the specified slot  */int unload(int fd, int drive, int slot){struct changer_move  move;int rc;    dbprintf(_("unload : fd = %d, drive = %d, slot =%d\n"),fd, drive, slot);    move.cm_fromtype = CHET_DT;    move.cm_fromunit = drive;    move.cm_totype = CHET_ST;    move.cm_tounit = slot;    move.cm_flags = 0;    rc = ioctl(fd, CHIOMOVE, &move);    if (rc){	dbprintf(_("drive unload failed (MOVE): 0x%x %s\n"), rc, strerror(errno));	return(-2);    }    return 0;}/* * moves tape from the specified slot into the drive  */int load(int fd, int drive, int slot){struct changer_move  move;int rc;    dbprintf(_("load : fd = %d, drive = %d, slot =%d\n"),fd, drive, slot);    move.cm_fromtype = CHET_ST;    move.cm_fromunit = slot;    move.cm_totype = CHET_DT;    move.cm_tounit = drive;    move.cm_flags = 0;    rc = ioctl(fd,CHIOMOVE,&move);    if (rc){	dbprintf(_("drive load failed (MOVE): 0x%x %s\n"), rc, strerror(errno));	return(-2);    }    return(0);}int get_slot_count(int fd){ int rc;    rc = get_changer_info(fd);    if (rc) {        dbprintf(_("slot count query failed: 0x%x %s\n"), rc, strerror(errno));        return -1;    }    return changer_info.cp_nslots;}int get_drive_count(int fd){ int rc;    rc = get_changer_info(fd);    if (rc) {        dbprintf(_("drive count query failed: 0x%x %s\n"), rc, strerror(errno));        return -1;    }    return changer_info.cp_ndrives;}/* This function should ask the drive if it is ready */int Tape_Ready1 ( char *tapedev , int wait)#if defined(BUILTIN){  FILE *out=NULL;  int cnt=0;    while ((cnt < wait) && (NULL==(out=fopen(tapedev,"w+")))){    cnt++;    sleep(1);  }  if (out != NULL)    fclose(out);  return 0;}#else{  int cnt=0;  dbprintf(_("Tape_Ready1 : wait for BOT : max %d seconds\n"),wait);  /* loop on status BOT */  while ((cnt < wait)) {    if ( GMT_BOT(GetDeviceStatus(tapedev)) ) {     break;    }    /* dbprintf(("Tape_Ready1 : cnt %d\n",cnt)); */    cnt++;    sleep(1);  }  if (cnt >= wait) {   dbprintf(_("Tape_Ready1 : BOT not found : %d seconds\n"),cnt);   return(-1);  } else {   dbprintf(_("Tape_Ready1 : BOT : %d seconds\n"),cnt);  return 0;  }}#endif	/* BUILTIN */int GetDeviceStatus (char *tapedev){  struct mtget status;  int mtfd, rc;  mtfd = OpenDevice(tapedev);  ioctl (mtfd, MTIOCGET, (char *)&status);  CloseDevice(tapedev, mtfd);  rc = status.mt_gstat;  return rc;}int OpenDevice (char *tapedev){  int DeviceFD;  DeviceFD = open(tapedev, O_RDWR);  return DeviceFD;}int CloseDevice (char *device, int DeviceFD){   int rc;   dbprintf(_("CloseDevice(%s)\n"), device);   rc = close(DeviceFD);   return rc;}/* * Local variables: * indent-tabs-mode: nil * c-default-style: gnu * End: */

⌨️ 快捷键说明

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