?? tapeinfo.c
字號:
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 + -