**FREE //===================================================================== // // Media Definition Parser // // Parses TAPE0200 data returned by QSRRTVMD. // //===================================================================== ctl-opt option(*srcstmt:*nodebugio) nomain; /COPY './meddfn_h.rpgle' /COPY './meddfnap_h.rpgle' //===================================================================== // // Prototype // //===================================================================== dcl-pr MD_ParseRetrieveBuffer; ReceiverBuffer char(32767) const options(*varsize); MediaDefinition likeds(MD_MediaDefinition_T); Error likeds(MD_Error_T); end-pr; //===================================================================== // // MD_ParseRetrieveBuffer // // Parses a retrieved TAPE0200 buffer. // // Supported: // // - TAPE0200 Header // - Device Definitions // - Media File Definitions // - Volume Identifier Arrays // // Parser errors are returned in Error. // //===================================================================== dcl-proc MD_ParseRetrieveBuffer export; dcl-pi *n; ReceiverBuffer char(32767) const options(*varsize); MediaDefinition likeds(MD_MediaDefinition_T); Error likeds(MD_Error_T); end-pi; //================================================================== // TAPE0200 structures //================================================================== dcl-ds Header likeds(MD_Tape0200Header_T); dcl-ds Device likeds(MD_Tape0200DeviceDefinition_T); dcl-ds MediaFile likeds(MD_Tape0200MediaFileDefinition_T); //================================================================== // Working variables //================================================================== dcl-s ReceiverLength int(10); dcl-s DeviceOffset int(10); dcl-s MediaOffset int(10); dcl-s VolumeOffset int(10); dcl-s DeviceIndex int(10); dcl-s MediaIndex int(10); dcl-s VolumeIndex int(10); dcl-s RequiredLength int(10); //================================================================== // Initialize //================================================================== clear MediaDefinition; clear Error; ReceiverLength = %len(ReceiverBuffer); //================================================================== // Receiver buffer //================================================================== if ReceiverLength < %size(Header); Error.HasError = *on; Error.MessageID = 'MDF2005'; Error.MessageData = *blanks; return; endif; //================================================================== // TAPE0200 Header //================================================================== Header = %subst( ReceiverBuffer : 1 : %size(Header)); //================================================================== // Validate Header //================================================================== if Header.LengthOfHeader <> %size(Header); Error.HasError = *on; Error.MessageID = 'MDF2001'; Error.MessageData = *blanks; return; endif; if Header.NumberOfDeviceDefinitions < 1 or Header.NumberOfDeviceDefinitions > MD_MaxDeviceDefinitions; Error.HasError = *on; Error.MessageID = 'MDF2001'; Error.MessageData = *blanks; return; endif; if Header.OffsetToFirstDeviceDefinition < %size(Header) or Header.OffsetToFirstDeviceDefinition > ReceiverLength - %size(Device); Error.HasError = *on; Error.MessageID = 'MDF2001'; Error.MessageData = *blanks; return; endif; if Header.DeviceAllocation <> MD_DeviceAllocateAll and Header.DeviceAllocation <> MD_DeviceAllocateOne and Header.DeviceAllocation <> MD_DeviceAllocateMinimum; Error.HasError = *on; Error.MessageID = 'MDF2001'; Error.MessageData = *blanks; return; endif; if Header.SaveFormat <> MD_SaveFormatAuto and Header.SaveFormat <> MD_SaveFormatSerial and Header.SaveFormat <> MD_SaveFormatParallel; Error.HasError = *on; Error.MessageID = 'MDF2001'; Error.MessageData = *blanks; return; endif; if Header.MaximumParallelDeviceResources < 0 or Header.MinimumParallelDeviceResources < 0 or Header.MinimumParallelDeviceResources > Header.MaximumParallelDeviceResources; Error.HasError = *on; Error.MessageID = 'MDF2001'; Error.MessageData = *blanks; return; endif; //================================================================== // Header -> Media Definition //================================================================== MediaDefinition.MaximumParallelResources = Header.MaximumParallelDeviceResources; MediaDefinition.MinimumParallelResources = Header.MinimumParallelDeviceResources; MediaDefinition.NumberOfDevices = Header.NumberOfDeviceDefinitions; MediaDefinition.DeviceAllocation = Header.DeviceAllocation; MediaDefinition.SaveFormat = Header.SaveFormat; //================================================================== // Device Definitions //================================================================== DeviceOffset = Header.OffsetToFirstDeviceDefinition; for DeviceIndex = 1 to Header.NumberOfDeviceDefinitions; //=============================================================== // Validate Device Offset //=============================================================== if DeviceOffset < 0 or DeviceOffset > ReceiverLength - %size(Device); Error.HasError = *on; Error.MessageID = 'MDF2002'; Error.MessageData = *blanks; return; endif; //=============================================================== // Read Device Definition //=============================================================== Device = %subst( ReceiverBuffer : DeviceOffset + 1 : %size(Device)); //=============================================================== // Validate Device Definition //=============================================================== if Device.LengthOfDeviceDefinition <> %size(Device); Error.HasError = *on; Error.MessageID = 'MDF2002'; Error.MessageData = *blanks; return; endif; if Device.NumberOfMediaFileDefinitions < 1 or Device.NumberOfMediaFileDefinitions > MD_MaxMediaDefinitions; Error.HasError = *on; Error.MessageID = 'MDF2002'; Error.MessageData = *blanks; return; endif; if %trim(Device.DeviceName) = ''; Error.HasError = *on; Error.MessageID = 'MDF2002'; Error.MessageData = *blanks; return; endif; if Device.OffsetToFirstMediaFileDefinition < %size(Device); Error.HasError = *on; Error.MessageID = 'MDF2002'; Error.MessageData = *blanks; return; endif; //=============================================================== // Device -> Media Definition //=============================================================== MediaDefinition.Device(DeviceIndex).DeviceName = Device.DeviceName; MediaDefinition.Device(DeviceIndex).NumberOfMediaFiles = Device.NumberOfMediaFileDefinitions; //=============================================================== // Media Files //=============================================================== MediaOffset = DeviceOffset + Device.OffsetToFirstMediaFileDefinition; for MediaIndex = 1 to Device.NumberOfMediaFileDefinitions; //============================================================ // Validate Media Offset //============================================================ if MediaOffset < 0 or MediaOffset > ReceiverLength - %size(MediaFile); Error.HasError = *on; Error.MessageID = 'MDF2003'; Error.MessageData = *blanks; return; endif; //============================================================ // Read Media File Definition //============================================================ MediaFile = %subst( ReceiverBuffer : MediaOffset + 1 : %size(MediaFile)); //============================================================ // Validate Media File Definition //============================================================ if MediaFile.LengthOfMediaFileDefinition <> %size(MediaFile); Error.HasError = *on; Error.MessageID = 'MDF2003'; Error.MessageData = *blanks; return; endif; if MediaFile.NumberOfVolumeIdentifiers < 0 or MediaFile.NumberOfVolumeIdentifiers > MD_MaxVolumeIdentifiers; Error.HasError = *on; Error.MessageID = 'MDF2003'; Error.MessageData = *blanks; return; endif; if MediaFile.NumberOfVolumeIdentifiers = 0; if MediaFile.OffsetToVolumeIdentifierArray <> 0 or MediaFile.LengthOfVolumeIdentifier <> 0 or MediaFile.StartingVolumeArrayElement <> 0; Error.HasError = *on; Error.MessageID = 'MDF2004'; Error.MessageData = *blanks; return; endif; else; if MediaFile.OffsetToVolumeIdentifierArray <= 0 or MediaFile.LengthOfVolumeIdentifier <> MD_VOLUME_ID_LENGTH or MediaFile.StartingVolumeArrayElement < 1; Error.HasError = *on; Error.MessageID = 'MDF2004'; Error.MessageData = *blanks; return; endif; RequiredLength = MediaFile.NumberOfVolumeIdentifiers * MediaFile.LengthOfVolumeIdentifier; if MediaFile.OffsetToVolumeIdentifierArray > ReceiverLength - RequiredLength or MediaFile.OffsetToVolumeIdentifierArray < MediaOffset + %size(MediaFile); Error.HasError = *on; Error.MessageID = 'MDF2004'; Error.MessageData = *blanks; return; endif; endif; //============================================================ // Media File -> Media Definition //============================================================ MediaDefinition.Device(DeviceIndex) .MediaFile(MediaIndex) .SequenceNumber = MediaFile.SequenceNumber; MediaDefinition.Device(DeviceIndex) .MediaFile(MediaIndex) .StartingPositionInFile = MediaFile.StartingPositionInFile; MediaDefinition.Device(DeviceIndex) .MediaFile(MediaIndex) .NumberOfVolumeIdentifiers = MediaFile.NumberOfVolumeIdentifiers; //============================================================ // Volume Identifier Array //============================================================ if MediaFile.NumberOfVolumeIdentifiers > 0; VolumeOffset = MediaFile.OffsetToVolumeIdentifierArray; for VolumeIndex = 1 to MediaFile.NumberOfVolumeIdentifiers; MediaDefinition.Device(DeviceIndex) .MediaFile(MediaIndex) .VolumeIdentifier(VolumeIndex) .VolumeIdentifier = %subst( ReceiverBuffer : VolumeOffset + ((VolumeIndex - 1) * MediaFile.LengthOfVolumeIdentifier) + 1 : MediaFile.LengthOfVolumeIdentifier); endfor; endif; //============================================================ // Next Media File //============================================================ if MediaIndex < Device.NumberOfMediaFileDefinitions; if MediaFile.OffsetToNextMediaFileDefinition <= MediaOffset or MediaFile.OffsetToNextMediaFileDefinition > ReceiverLength - %size(MediaFile); Error.HasError = *on; Error.MessageID = 'MDF2003'; Error.MessageData = *blanks; return; endif; MediaOffset = MediaFile.OffsetToNextMediaFileDefinition; else; if MediaFile.OffsetToNextMediaFileDefinition <> 0; Error.HasError = *on; Error.MessageID = 'MDF2003'; Error.MessageData = *blanks; return; endif; endif; endfor; //================================================================ // Next Device //================================================================ if DeviceIndex < Header.NumberOfDeviceDefinitions; if Device.OffsetToNextDeviceDefinition <= DeviceOffset or Device.OffsetToNextDeviceDefinition > ReceiverLength - %size(Device); Error.HasError = *on; Error.MessageID = 'MDF2002'; Error.MessageData = *blanks; return; endif; DeviceOffset = Device.OffsetToNextDeviceDefinition; else; if Device.OffsetToNextDeviceDefinition <> 0; Error.HasError = *on; Error.MessageID = 'MDF2002'; Error.MessageData = *blanks; return; endif; endif; endfor; end-proc;