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

📄 tapeinfo.c

📁 通用SCSI设备备份/读写程序
💻 C
📖 第 1 页 / 共 2 页
字号:
    printf("BlockSize: %d\n", blocklen);    /* This doesn't seem to do anything useful on my Tandberg so I     * am taking it out -- elg     */     /* Put out the # Blocks */    /* blocklen=((int)input_buffer[5]<<16)+ */    /*      ((int)input_buffer[6]<<8)+ */    /*      input_buffer[7]; */    /* printf("Num Blocks:  %d\n", blocklen); */  }  /* First skip past any header.... */  tmp=input_buffer+4+input_buffer[3];  /* now find out real length of page... */  pagelen=tmp[1]+2;  retval=xmalloc(pagelen);  /* and copy our data to the new page. */  for (i=0;i<pagelen;i++) {    retval[i]=tmp[i];  }  /* okay, free our input buffer: */  free(input_buffer);  return retval;}#define DCE_MASK 0x80#define DCC_MASK 0x40#define DDE_MASK 0x80static void ReportCompressionPage(DEVICE_TYPE fd) {  /* actually ignore a bad sense reading, like might happen if the tape   * drive does not support the mode sense compression page.    */  RequestSense_T RequestSense;  unsigned char *compression_page;  compression_page=mode_sense(fd,0x0f,16,&RequestSense);  if (!compression_page) {    return;  /* sorry! */  }  /* Okay, we now have the compression page. Now print stuff from it: */  printf("DataCompEnabled: %s\n", (compression_page[2]&DCE_MASK)? "yes" : "no");  printf("DataCompCapable: %s\n", (compression_page[2]&DCC_MASK)? "yes" : "no");  printf("DataDeCompEnabled: %s\n", (compression_page[3]&DDE_MASK)? "yes" : "no");  printf("CompType: 0x%x\n",	 (compression_page[4]<<24)+(compression_page[5]<<16)+(compression_page[6]<<8)+compression_page[7]);  printf("DeCompType: 0x%x\n",	(compression_page[8]<<24)+ (compression_page[9]<<16)+(compression_page[10]<<8)+compression_page[11]);  free(compression_page);  return;}  /* Now for the device configuration mode page: */static void ReportConfigPage(DEVICE_TYPE fd) {  RequestSense_T RequestSense;  unsigned char *config_page;    config_page=mode_sense(fd,0x10,16,&RequestSense);  if (!config_page) return;  /* Now to print the stuff: */  printf("ActivePartition: %d\n",config_page[3]);  /* The following does NOT work accurately on any tape drive I know of... */  /*  printf("DevConfigComp: %s\n", config_page[14] ? "yes" : "no"); */  printf("EarlyWarningSize: %d\n",	 (config_page[11]<<16)+(config_page[12]<<8)+config_page[13]);  return;}/* *************************************** * Medium Partition Page: *  * The problem here, as we oh so graphically demonstrated during debugging * of the Linux 'st' driver :-), is that there are actually *TWO* formats for * the Medium Partition Page: There is the "long" format, where there is a * partition size word for each partition on the page, and there is a "short" * format, beloved of DAT drives, which only has a partition size word for * partition #1 (and no partition size word for partition #0, and no * provisions for any more partitions). So we must look at the size and * # of partitions defined to know what to report as what.  * ********************************************/static void ReportPartitionPage(DEVICE_TYPE fd) {  RequestSense_T RequestSense;  unsigned char *partition_page;  int num_parts,max_parts;  int i;  partition_page=mode_sense(fd,0x11,255,&RequestSense);  if (!partition_page) return;  /* Okay, now we have either old format or new format: */  num_parts=partition_page[3];  max_parts=partition_page[2];  printf("NumPartitions:%d\n",num_parts);  printf("MaxPartitions:%d\n",max_parts);  if (!num_parts) {  /* if no additional partitions, then ... */     free(partition_page);    return;  }    /* we know we have at least one partition if we got here. Check the   * page size field. If it is 8 or below, then we are the old format....   */#ifdef DEBUG_PARTITION  fprintf(stderr,"partition_page[1]=%d\n",partition_page[1]);  fflush(stderr);#endif  if (partition_page[1]==8) {    /* old-style! */    printf("Partition1:%d\n",(partition_page[8]<<8)+partition_page[9]);  } else {    /* new-style! */    for (i=0;i<=max_parts;i++) {#ifdef DEBUG_PARTITION          fprintf(stderr,"partition%d:[%d]%d [%d]%d\n",i,8+i*2,	      partition_page[8+i*2]<<8, 9+i*2,partition_page[9+i*2]);      fflush(stderr);#endif      printf("Partition%d:%d\n",i,	     (partition_page[8+i*2]<<8)+partition_page[9+i*2]);    }  }  free(partition_page);  return;}static void ReportSerialNumber(DEVICE_TYPE fd) {  /* actually ignore a bad sense reading, like might happen if the     tape drive does not support the inquiry page 0x80.   */  RequestSense_T sense;  CDB_T CDB;#define WILD_SER_SIZE 30  unsigned char buffer[WILD_SER_SIZE]; /* just wildly overestimate serial# length! */  int i,lim;  char *bufptr;     CDB[0]=0x12;  /* INQUIRY */  CDB[1]= 1;     /* EVPD = 1 */  CDB[2]=0x80;   /* The serial # page, hopefully. */  CDB[3]=0  ; /* reserved */  CDB[4]=WILD_SER_SIZE;  CDB[5]=0;  if (SCSI_ExecuteCommand(fd, Input, &CDB, 6,			  &buffer, sizeof(buffer), &sense) != 0)  {    /* PrintRequestSense(&sense); */ /* zap debugging output :-) */    /* printf("No Serial Number: None\n"); */    return;   }    /* okay, we have something in our buffer. Byte 3 should be the length of     the sernum field, and bytes 4 onward are the serial #. */    lim=(int)buffer[3];  bufptr= &(buffer[4]);    printf("SerialNumber: '");  for (i=0;i<lim;i++) {    putchar(*bufptr++);  }  printf("'\n");  return ; /* done! */}    /*  Read Block Limits! */void ReportBlockLimits(DEVICE_TYPE fd) {  RequestSense_T sense;  CDB_T CDB;  unsigned char buffer[6];  CDB[0]=0x05;  /* READ_BLOCK_LIMITS */  CDB[1]=0;  CDB[2]=0;  CDB[3]=0;  /* 1-5 all unused. */  CDB[4]=0;  CDB[5]=0;   slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));  if (SCSI_ExecuteCommand(fd,Input,&CDB,6,buffer,6,&sense)!=0){    return;  }    /* okay, but if we did get a result, print it: */  printf("MinBlock:%d\n",	 (buffer[4]<<8)+buffer[5]);  printf("MaxBlock:%d\n",	 (buffer[1]<<16)+(buffer[2]<<8)+buffer[3]);  return;}  /* Do a READ_POSITION. This may not be always valid, but (shrug). */void ReadPosition(DEVICE_TYPE fd) {  RequestSense_T sense;  CDB_T CDB;  unsigned char buffer[20];  unsigned int position;  CDB[0]=0x34;  /* READ_POSITION */  CDB[1]=0;  CDB[2]=0;  CDB[3]=0;  /* 1-9 all unused. */  CDB[4]=0;  CDB[5]=0;   CDB[6]=0;  CDB[7]=0;  CDB[8]=0;  CDB[9]=0;  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));  /* set the timeout: */  SCSI_Set_Timeout(2); /* set timeout to 2 seconds! */  /* if we don't get a result (e.g. we issue this to a disk drive), punt. */  if (SCSI_ExecuteCommand(fd,Input,&CDB,10,buffer,20,&sense)!=0){    return;  }    SCSI_Default_Timeout(); /* reset it to 5 minutes, sigh! */  /* okay, but if we did get a result, print it: */#define RBL_BOP 0x80#define RBL_EOP 0x40#define RBL_BCU 0x20#define RBL_BYCU  0x10#define RBL_R1 0x08#define RBL_BPU 0x04#define RBL_PERR 0x02  /* If we have BOP, go ahead and print that. */  if (buffer[0]&RBL_BOP) {    printf("BOP: yes\n");  }  /* if we have valid data, print it: */  if (buffer[0]&RBL_BPU) {    printf("Block Position: -1");  } else {        position= (unsigned int) (((unsigned int)buffer[4]<<24) +			      ((unsigned int)buffer[5]<<16) + 			      ((unsigned int)buffer[6]<<8) + buffer[7]);    printf("Block Position: %d\n",position);  }  return;}/* Test unit ready: This will tell us whether the tape drive * is currently ready to read or write. */int TestUnitReady(DEVICE_TYPE fd) {  RequestSense_T sense;  CDB_T CDB;  unsigned char buffer[6];  CDB[0]=0x00;  /* TEST_UNIT_READY */  CDB[1]=0;  CDB[2]=0;  CDB[3]=0;  /* 1-5 all unused. */  CDB[4]=0;  CDB[5]=0;   slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));  if (SCSI_ExecuteCommand(fd,Input,&CDB,6,buffer,0,&sense)!=0){    printf("Ready: no\n");    return 0;  }    printf("Ready: yes\n");  return 1;}/* We write a filemarks of 0 before going to grab position, in order * to insure that data in the buffer is not a problem.  */int WriteFileMarks(DEVICE_TYPE fd,int count) {  RequestSense_T sense;  CDB_T CDB;  unsigned char buffer[6];  CDB[0]=0x10;  /* WRITE_FILE_MARKS */  CDB[1]=0;  CDB[2]=(count >> 16) & 0xff;  CDB[3]=(count >>8) & 0xff;  CDB[4]=count & 0xff;  CDB[5]=0;   /* we really don't care if this command works or not, sigh.  */  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));  if (SCSI_ExecuteCommand(fd,Input,&CDB,6,buffer,0,&sense)!=0){    return 1;  }  return 0;}/* This will get the SCSI ID and LUN of the target device, if such * is available from the OS. Currently only Linux supports this, * but other drivers could, if someone wants to write a  * SCSI_GetIDLun function for them.  */#ifdef HAVE_GET_ID_LUNstatic void ReportIDLun(DEVICE_TYPE fd) {  scsi_id_t *scsi_id;  scsi_id=SCSI_GetIDLun(fd);  printf("SCSI ID: %d\nSCSI LUN: %d\n",scsi_id->id,scsi_id->lun);}#endif/* we only have one argument: "-f <device>". */int main(int argc, char **argv) {  DEVICE_TYPE fd;  char *filename;  argv0=argv[0];    if (argc != 3) {    fprintf(stderr,"argc=%d",argc);    usage();  }  if (strcmp(argv[1],"-f")!=0) {    usage();  }  filename=argv[2];    fd=SCSI_OpenDevice(filename);    /* Now to call the various routines: */  ReportInquiry(fd);  ReportSerialNumber(fd);  ReportTapeAlert(fd);  /* ReportConfigPage(fd);  */  /* ReportPartitionPage(fd); */  ReportBlockLimits(fd); #ifdef HAVE_GET_ID_LUN  ReportIDLun(fd);#endif  /* okay, we should only report position if the unit is ready :-(. */  if (TestUnitReady(fd)) {    ReportCompressionPage(fd);     ReadPosition(fd);   }  exit(0);}      

⌨️ 快捷键说明

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