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

📄 mtxl.c

📁 通用SCSI设备备份/读写程序
💻 C
📖 第 1 页 / 共 3 页
字号:
#endif     dest++;  }  dest=0; /* null-terminate, sigh. */ }/* This #%!@# routine has more parameters than I can count! */unsigned char *SendElementStatusRequest(DEVICE_TYPE MediumChangerFD,					RequestSense_T *RequestSense,					Inquiry_T *inquiry_info, 					SCSI_Flags_T *flags,					int ElementStart,					int NumElements,					int NumBytes					) {  CDB_T CDB;  boolean is_attached = false;  unsigned char *DataBuffer; /* size of data... */#ifdef HAVE_GET_ID_LUN  scsi_id_t *scsi_id;#endif  if ((inquiry_info->MChngr) && (inquiry_info->PeripheralDeviceType != MEDIUM_CHANGER_TYPE)) {    is_attached=true;  }  if (flags->no_attached) { /* override, sigh */     is_attached=false;  }  DataBuffer=(unsigned char *) xmalloc(NumBytes+1);  slow_bzero((char *)RequestSense,sizeof(RequestSense_T));#ifdef HAVE_GET_ID_LUN  scsi_id = SCSI_GetIDLun(MediumChangerFD);#endif  CDB[0] = 0xB8;		/* READ ELEMENT STATUS */  if (is_attached) {    CDB[0] = 0xB4;  /* whoops, READ_ELEMENT_STATUS_ATTACHED! */   }#ifdef HAVE_GET_ID_LUN  CDB[1] = (scsi_id->lun << 5) | ((flags->no_barcodes) ? 0 : 0x10) | flags->elementtype;  /* Lun + VolTag + Type code */  free(scsi_id);#else  CDB[1] = ((flags->no_barcodes) ? 0 : 0x10) | flags->elementtype;		/* Element Type Code = 0, VolTag = 1 */#endif  CDB[2] = (ElementStart >> 8) & 0xff;	/* Starting Element Address MSB */  CDB[3] = ElementStart & 0xff;		/* Starting Element Address LSB */  CDB[4]= (NumElements >> 8) & 0xff;	  /* Number Of Elements MSB */  CDB[5]= NumElements & 0xff ;        /* Number of elements LSB */  /*  CDB[5]=127; */ /* test */#ifdef DEBUG  fprintf(stderr,"CDB[5]=%d\n" , CDB[5]);#endif  CDB[6] = 0;			/* Reserved */  CDB[7]= (NumBytes >> 16) & 0xff; /* allocation length MSB */  CDB[8]= (NumBytes >> 8) & 0xff;  CDB[9]= NumBytes & 0xff;   /* allocation length LSB */  CDB[10] = 0;			/* Reserved */  CDB[11] = 0;			/* Control */#ifdef DEBUG_BARCODE  {    int i;    fprintf(stderr,"CDB= ");    for (i=0;i<12;i++) {      fprintf(stderr,"%x ",CDB[i]);    }    fprintf(stderr,"\n");    fflush(stderr);  }#endif  if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 12,			  DataBuffer,NumBytes, RequestSense) != 0){    /* okay, first see if we have sense key of 'illegal request',       additional sense code of '24', additional sense qualfier of        '0', and field in error of '4'. This means that we issued a request       w/bar code reader and did not have one, thus must re-issue the request       w/out barcode :-(.    */        /* Okay, most autochangers and tape libraries set a sense key here if     * they do not have a bar code reader. For some reason, the ADIC DAT     * uses a different sense key? Let's retry w/o bar codes for *ALL*     * sense keys, sigh sigh sigh.      */        if ( RequestSense->SenseKey > 1 ) {      /* we issued a code requesting bar codes, there is no bar code reader? */      /* clear out our sense buffer first... */      slow_bzero((char *)RequestSense,sizeof(RequestSense_T));      CDB[1] &= ~0x10; /* clear bar code flag! */#ifdef DEBUG_BARCODE      {	int i;	fprintf(stderr,"CDB= ");	for (i=0;i<12;i++) {	  fprintf(stderr,"%x ",CDB[i]);	}	fprintf(stderr,"\n");	fflush(stderr);      }#endif            if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 12,			      DataBuffer, NumBytes, RequestSense) != 0){	free(DataBuffer);	return NULL;      }    } else {      free(DataBuffer);      return NULL;    }  }#ifdef DEBUG_BARCODE  /* print a bunch of extra debug data :-(.  */  PrintRequestSense(RequestSense); /* see what it sez :-(. */  {    int i;    fprintf(stderr,"Data:");    for (i=0;i<40;i++) {      fprint(stderr,"%02x ",DataBuffer[i]);    }    fprintf(stderr,"\n");  }#endif    return DataBuffer; /* we succeeded! */}/******************* ParseElementStatus ***********************************//* This does the actual grunt work of parsing element status data. It fills * in appropriate pieces of its input data. It may be called multiple times * while we are gathering element status. */static void ParseElementStatus(int *EmptyStorageElementAddress,			       int *EmptyStorageElementCount,			       unsigned char *DataBuffer,			       ElementStatus_T *ElementStatus,			       ElementModeSense_T *mode_sense			       )   {        unsigned char *DataPointer=DataBuffer;    TransportElementDescriptor_T TEBuf;    TransportElementDescriptor_T *TransportElementDescriptor;    ElementStatusDataHeader_T *ElementStatusDataHeader;    Element2StatusPage_T *ElementStatusPage;    Element2StatusPage_T ESBuf;    int ElementCount;    int TransportElementDescriptorLength;    int BytesAvailable;         ElementStatusDataHeader = (ElementStatusDataHeader_T *) DataBuffer;      ElementStatusDataHeader = (ElementStatusDataHeader_T *) DataPointer;  DataPointer += sizeof(ElementStatusDataHeader_T);  ElementCount =    BigEndian16(ElementStatusDataHeader->NumberOfElementsAvailable);#ifdef DEBUG      fprintf(stderr,"ElementCount=%d\n",ElementCount);      fflush(stderr);#endif  while (ElementCount > 0)    {#ifdef DEBUG      int got_element_num=0;            fprintf(stderr,"Working on element # %d Element Count %d\n",got_element_num,ElementCount);      got_element_num++;#endif      memcpy(&ESBuf, DataPointer, sizeof(ElementStatusPage_T));      ElementStatusPage = &ESBuf;      DataPointer += sizeof(ElementStatusPage_T);      TransportElementDescriptorLength =	BigEndian16(ElementStatusPage->ElementDescriptorLength);      if (TransportElementDescriptorLength <	  sizeof(TransportElementDescriptorShort_T)) {	/* Foo, Storage Element Descriptors can be 4 bytes?! */	if ( (ElementStatusPage->ElementTypeCode != MediumTransportElement &&	      ElementStatusPage->ElementTypeCode != StorageElement &&	      ElementStatusPage->ElementTypeCode != ImportExportElement ) ||	     TransportElementDescriptorLength < 4) {#ifdef DEBUG	  fprintf(stderr,"boom! ElementTypeCode=%d\n",ElementStatusPage->ElementTypeCode);#endif	  FatalError("Transport Element Descriptor Length too short: %d\n",TransportElementDescriptorLength);	} 	      }#ifdef DEBUG      fprintf(stderr,"Transport Element Descriptor Length=%d\n",TransportElementDescriptorLength);#endif      BytesAvailable =	BigEndian24(ElementStatusPage->ByteCountOfDescriptorDataAvailable);      if (BytesAvailable <= 0) {	      ElementCount--;      }      while (BytesAvailable > 0)	{	  /* TransportElementDescriptor =	     (TransportElementDescriptor_T *) DataPointer; */          memcpy(&TEBuf, DataPointer, 			(TransportElementDescriptorLength <= sizeof(TEBuf)) ?				TransportElementDescriptorLength  :				sizeof(TEBuf));          TransportElementDescriptor = &TEBuf;	  DataPointer += TransportElementDescriptorLength;	  BytesAvailable -= TransportElementDescriptorLength;	  ElementCount--;	  switch (ElementStatusPage->ElementTypeCode)	    {	    case MediumTransportElement:	      ElementStatus->TransportElementAddress = BigEndian16(TransportElementDescriptor->ElementAddress);#ifdef DEBUG	      fprintf(stderr,"TransportElementAddress=%d\n",ElementStatus->TransportElementAddress); #endif	      break;	      /* we treat ImportExport elements as if they were normal	       * storage elements now, sigh...	       */	    case ImportExportElement:	      ElementStatus->ImportExportCount++;#ifdef DEBUG	      fprintf(stderr,"ImportExportElement=%d\n",ElementStatus->StorageElementCount);#endif	      ElementStatus->StorageElementIsImportExport[ElementStatus->StorageElementCount] = 1;	      /* WARNING: DO *NOT* PUT A 'break' STATEMENT HERE, it is supposed	       * to run on into the case for a Storage Element! 	       */	    case StorageElement:#ifdef DEBUG	      fprintf(stderr,"StorageElementCount=%d  ElementAddress = %d ",ElementStatus->StorageElementCount,BigEndian16(TransportElementDescriptor->ElementAddress));#endif	      ElementStatus->StorageElementAddress[ElementStatus->StorageElementCount] =		BigEndian16(TransportElementDescriptor->ElementAddress);	      ElementStatus->StorageElementFull[ElementStatus->StorageElementCount] =		TransportElementDescriptor->Full;#ifdef DEBUG	      fprintf(stderr,"TransportElement->Full = %d\n",TransportElementDescriptor->Full);#endif	      if (!TransportElementDescriptor->Full)		{		  EmptyStorageElementAddress[(*EmptyStorageElementCount)++] =		    ElementStatus->StorageElementCount; /* slot idx. */		    /*   ElementStatus->StorageElementAddress[ElementStatus->StorageElementCount]; */		}	      if ( (TransportElementDescriptorLength >  11) && 		   (ElementStatusPage->VolBits & E2_AVOLTAG)) {		copy_barcode(TransportElementDescriptor->AlternateVolumeTag,			     ElementStatus->AlternateVolumeTag[ElementStatus->StorageElementCount]);	      } else {		ElementStatus->AlternateVolumeTag[ElementStatus->StorageElementCount][0]=0;  /* null string. */;	      } 	      if ( (TransportElementDescriptorLength > 11) && 		   (ElementStatusPage->VolBits & E2_PVOLTAG)) {		copy_barcode(TransportElementDescriptor->PrimaryVolumeTag,			     ElementStatus->PrimaryVolumeTag[ElementStatus->StorageElementCount]);	      } else {		ElementStatus->PrimaryVolumeTag[ElementStatus->StorageElementCount][0]=0; /* null string. */	      }	      	      ElementStatus->StorageElementCount++;	      /* Note that the original mtx had no check here for 		 buffer overflow, though some drives might mistakingly		 do one... 	      */ 	      if (ElementStatus->StorageElementCount > mode_sense->NumStorage) {		fprintf(stderr,"Warning:Too Many Storage Elements Reported (expected %d, now have %d\n",			mode_sense->NumStorage,			ElementStatus->StorageElementCount);		fflush(stderr);		return; /* we're done :-(. */	      }	      break;	    case DataTransferElement:	      /* tape drive not installed, go back to top of loop */	      /* if (TransportElementDescriptor->Except) continue ; */	      /* Note: This is for Exabyte tape libraries that improperly		 report that they have a 2nd tape drive when they don't. We		 could generalize this in an ideal world, but my attempt to		 do so failed with dual-drive Exabyte tape libraries that		 *DID* have the second drive. Sigh. 	      */	      /* No longer need this test due to code restructuring? */	      /* if (TransportElementDescriptor->AdditionalSenseCode==0x83 && 		  TransportElementDescriptor->AdditionalSenseCodeQualifier==0x04) 		continue;	      */ 	      /* generalize it. Does it work? Let's try it! */	      /* No, dammit, following does not work on dual-drive Exabyte		 'cause if a tape is in the drive, it sets the AdditionalSense		  code to something (sigh).	      */	      /* if (TransportElementDescriptor->AdditionalSenseCode!=0)		continue;	      */ 	      		  	      ElementStatus->DataTransferElementAddress[ElementStatus->DataTransferElementCount] =		BigEndian16(TransportElementDescriptor->ElementAddress);	      ElementStatus->DataTransferElementFull[ElementStatus->DataTransferElementCount] = 		TransportElementDescriptor->Full;	      ElementStatus->DataTransferElementSourceStorageElementNumber[ElementStatus->DataTransferElementCount] =		BigEndian16(TransportElementDescriptor			    ->SourceStorageElementAddress);	      if (ElementStatus->DataTransferElementCount >= mode_sense->NumDataTransfer) {		FatalError("Too many Data Transfer Elements Reported\n");	      }	      if (ElementStatusPage->VolBits & E2_PVOLTAG) {		copy_barcode(TransportElementDescriptor->PrimaryVolumeTag,			     ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount]);	      } else {		ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */	      }	      if (ElementStatusPage->VolBits & E2_AVOLTAG) {		copy_barcode(TransportElementDescriptor->AlternateVolumeTag,			     ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount]);	      } else {		ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */	      }	      ElementStatus->DataTransferElementCount++;	      /* 0 actually is a usable element address */	      /* if (DataTransferElementAddress == 0) */	      /*	FatalError( */	      /*  "illegal Data Transfer Element Address %d reported\n", */	      /* DataTransferElementAddress); */	      break;	    default:	      FatalError("illegal Element Type Code %d reported\n",			 ElementStatusPage->ElementTypeCode);	    }	}    }}/********************* Real ReadElementStatus ********************* *//* * We no longer do the funky trick to figure out ALLOCATION_LENGTH. * Instead, we use the SCSI Generic command rather than SEND_SCSI_COMMAND * under Linux, which gets around the @#%@ 4k buffer size in Linux.  * We still have the restriction that Linux cuts off the last two * bytes of the SENSE DATA (Q#@$%@#$^ Linux!). Which means that the * verbose widget won't work :-(.   * We now look for that "attached" bit in the inquiry_info to see whether * to use READ_ELEMENT_ATTACHED or plain old READ_ELEMENT. In addition, we * look at the device type in the inquiry_info to see whether it is a media * changer or tape device, and if it's a media changer device, we ignore the * attached bit (one beta tester found an old 4-tape DAT changer that set * the attached bit for both the tape device AND the media changer device). */ElementStatus_T *ReadElementStatus(DEVICE_TYPE MediumChangerFD, RequestSense_T *RequestSense, Inquiry_T *inquiry_info, SCSI_Flags_T *flags) {  ElementStatus_T *ElementStatus;    unsigned char *DataBuffer; /* size of data... */    int EmptyStorageElementCount=0;  int *EmptyStorageElementAddress; /* [MAX_STORAGE_ELEMENTS]; */    int empty_idx=0;  int invalid_sources=0;  boolean is_attached = false;  int i,j;    ElementModeSense_T *mode_sense = NULL;    if ((inquiry_info->MChngr) && (inquiry_info->PeripheralDeviceType != MEDIUM_CHANGER_TYPE)) {    is_attached=true;  }  if (flags->no_attached) { /* override, sigh */     is_attached=false;  }  if (!is_attached) {    mode_sense=ReadAssignmentPage(MediumChangerFD);  }  if (!mode_sense) {    mode_sense=(ElementModeSense_T *) xmalloc(sizeof(ElementModeSense_T));    mode_sense->NumMediumTransport=MAX_TRANSPORT_ELEMENTS;    mode_sense->NumStorage=MAX_STORAGE_ELEMENTS;    mode_sense->NumDataTransfer=MAX_TRANSFER_ELEMENTS;    mode_sense->MaxReadElementStatusData=  (sizeof(ElementStatusDataHeader_T)					    + 3 * sizeof(ElementStatusPage_T)					    + (MAX_STORAGE_ELEMENTS+MAX_TRANSFER_ELEMENTS+MAX_TRANSPORT_ELEMENTS)					    * sizeof(TransportElementDescriptor_T));        /* don't care about the others anyhow at the moment... */  }    ElementStatus=AllocateElementData(mode_sense);  /* Now to initialize it (sigh).  */  ElementStatus->StorageElementCount = 0;  ElementStatus->DataTransferElementCount=0;        /* first, allocate some empty storage stuff: Note that we pass this   * down to ParseElementStatus (sigh!)    */    EmptyStorageElementAddress=(int *)xzmalloc((mode_sense->NumStorage+1)*sizeof(int));  for (i=0;i<mode_sense->NumStorage;i++) {    EmptyStorageElementAddress[i]=-1;  }    /* Okay, now to send some requests for the various types of stuff: */  /* -----------STORAGE ELEMENTS---------------- */  /* Let's start with storage elements: */  for (i=0;i<mode_sense->NumDataTransfer;i++) {    /* initialize them to an illegal # so that we can fix later... */    ElementStatus->DataTransferElementSourceStorageElementNumber[i] = -1;   }  

⌨️ 快捷键说明

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