//____________________________________________________________________________ // // (C) Copyright Seagate Software, Inc. 1994-1996 // © 1998 Seagate Software, Inc. All rights reserved. // // All Rights Reserved Worldwide. // //____________________________________________________________________________ // // FILE NAME : mtf_api.c // // DESCRIPTION : mtf api implementation // // CREATED: 6/20/95 // //____________________________________________________________________________ // // $Revision: 1.35 $ // $Date: 02 Feb 1995 15:47:04 $ // $Modtime: 02 Feb 1995 15:37:38 $ // //____________________________________________________________________________ // *****************************************************************************/ #include #include #include #include #include "mtf_api.h" /*********************************************************************************** ************************************************************************************ ************************************************************************************ **** MTF API Static Data Structures and Housekeeping ************************************************************************************ ************************************************************************************ ***********************************************************************************/ // see below static UINT16 s_uAlignmentFactor = 0; static size_t Align(size_t uSize, size_t uAlignment); // when the api formats it's own strings (i.e. file names from the WIN32_FIND_DATA, // we need to keep those strings somewhere so we can set the pointers to them in // the info structs. #define STRLEN 256 static wchar_t s_szDeviceName[STRLEN]; static wchar_t s_szVolumeName[STRLEN]; static wchar_t s_szMachineName[MAX_COMPUTERNAME_LENGTH+1]; static wchar_t s_szDirectoryName[STRLEN]; static wchar_t s_szFileName[STRLEN]; /* ================================================================================== String Management When reading blocks, the strings are not null terminated -- we would like to pull them out and deliver them back in the ####_INFO structures in a civilized (null terminated) way. Thus, just set up an array of malloc'ec strings. Each call that uses strings should first call "ClearStrings" -- strings returned to the user will only be good up until the next call... ================================================================================= */ #define iNUMSTRINGS 5 static wchar_t *s_aszStrings[iNUMSTRINGS] = {0}; // we keep an array of pointers to allocated strings // this managed by ClearStrings() and MakeString() static int s_iNumStrings = 0; // the number of strings currently allocated // - returns the size of a wchar_t string // and returns zero for a null pointer static size_t wstrsize(wchar_t *s) { if (s) return wcslen(s) * sizeof(wchar_t); else return 0; } // - frees all allocated pointers in s_aszStrings and sets // s_iNumStrings to zero static void ClearStrings() { int i; for (i = 0; i < iNUMSTRINGS; ++i) { if (s_aszStrings[i]) free(s_aszStrings[i]); s_aszStrings[i] = 0; } s_iNumStrings = 0; } // - allocates a string in s_aszStrings that is a copy of pString // (pString need not be null terminated) // (note -- iSize is the size of the string in bytes -- not the length!!!!! static wchar_t * MakeString(wchar_t * pString, size_t iSize) { size_t i; assert(s_iNumStrings < iNUMSTRINGS); s_aszStrings[s_iNumStrings] = malloc(iSize + sizeof(wchar_t)); if (!s_aszStrings[s_iNumStrings]) return NULL; for (i = 0; i < iSize / sizeof(wchar_t); ++i) s_aszStrings[s_iNumStrings][i] = pString[i]; s_aszStrings[s_iNumStrings][i] = L'\0'; return s_aszStrings[s_iNumStrings++]; } /* ================================================================================== Other static data structures ================================================================================= */ #pragma pack(1) /*********************************************************************************** ************************************************************************************ ************************************************************************************ **** MTF On Tape Structures ************************************************************************************ ************************************************************************************ ***********************************************************************************/ /* ================================================================================== Tape Address ================================================================================== */ typedef struct { UINT16 uSize; /* Size of the data */ UINT16 uOffset; /* Offset to the data */ } MTF_TAPE_ADDRESS; /* ================================================================================== Common DBLK Header - The common dblk header exactly as it appears on tape in the head of the dblks ================================================================================== */ typedef struct { UINT8 acBlockType[4]; /* 00h Unique identifier, see above */ UINT32 uBlockAttributes; /* 04h Common attributes for this block */ UINT16 uOffsetToFirstStream; /* 08h Offset to data associated with this */ /* DBLK, or offset to next DBLK or */ /* filemark if there is no associated */ /* data. */ UINT8 uOSID; /* 0Ah Machine/OS id where written, low byte */ UINT8 uOSVersion; /* 0Bh Machine/OS id where written, high byte */ UINT64 uDisplayableSize; /* 0Ch Displayable data size */ UINT64 uFormatLogicalAddress; /* 14h Logical blk address relative to SSET */ UINT16 uReservedForMBC; /* 1Ch Reserved for Media Based Catalog */ UINT16 uSoftwareCompression; /* 1Eh Software Compression Algorithm ***/ UINT8 acReserved1[4]; /* 20h reserved */ UINT32 uControlBlockId; /* 24h Used for error recovery */ UINT8 acReserved2[4]; /* 28h reserved */ MTF_TAPE_ADDRESS sOSSpecificData; /* 2Ch Size and offset of OS specific stuff */ UINT8 uStringType; /* 30h ASCII, Unicode, etc. */ UINT8 uReserved3; /* 31h for alignment purposes */ UINT16 uHeaderCheckSum; /* 32h Checksum of the block header. The */ /* algorithm is: XOR each word preceeding */ /* this one and store the result here. */ /* (When the checksum is verified the */ /* 'block_type' is also checked for a */ /* non-zero value. */ } MTF_DBLK_HDR; /* ================================================================================== DBLK TAPE Header - The TAPE DBLK, exactly as it appears on tape, including the common DBLK header (MTF_DBLK_HDR) ================================================================================== */ typedef struct { /* MTF_DBLK_TAPE */ MTF_DBLK_HDR sBlockHeader; UINT32 uTapeFamilyId; UINT32 uTapeAttributes; UINT16 uTapeSequenceNumber; UINT16 uPasswordEncryptionAlgorithm; UINT16 uSoftFilemarkBlockSize; /* Or ECC Algorithm */ UINT16 uTapeCatalogType; MTF_TAPE_ADDRESS sTapeName; MTF_TAPE_ADDRESS sTapeDescription; MTF_TAPE_ADDRESS sTapePassword; MTF_TAPE_ADDRESS sSoftware_name; UINT16 uAlignmentFactor; UINT16 uSoftwareVendorId; MTF_DATE_TIME sTapeDate; UINT8 uMTFMajorVersion; } MTF_DBLK_TAPE; /* ================================================================================== Start of Set DBLK (SSET) - The SSET DBLK, exactly as it appears on tape, including the common DBLK header (MTF_DBLK_HDR) ================================================================================== */ typedef struct { MTF_DBLK_HDR sBlockHeader; UINT32 uSSETAttributes; UINT16 uPasswordEncryptionAlgorithm; UINT16 uDataEncryptionAlgorithm; /* Or Software Compression Algorithm ***/ UINT16 uSoftwareVendorId; UINT16 uDataSetNumber; MTF_TAPE_ADDRESS sDataSetName; MTF_TAPE_ADDRESS sDataSetDescription; MTF_TAPE_ADDRESS sDataSetPassword; MTF_TAPE_ADDRESS sUserName; UINT64 uPhysicalBlockAddress; MTF_DATE_TIME sMediaWriteDate; UINT8 uSoftwareVerMjr; UINT8 uSoftwareVerMnr; UINT8 uTimeZone; UINT8 uMTFMinorVer; UINT8 uTapeCatalogVersion; } MTF_DBLK_SSET; /* ================================================================================== Volume DBLK (VOLB) - The VOLB DBLK, exactly as it appears on tape, including the common DBLK header (MTF_DBLK_HDR) ================================================================================== */ typedef struct { MTF_DBLK_HDR sBlockHeader; UINT32 uVolumeAttributes; MTF_TAPE_ADDRESS sDeviceName; MTF_TAPE_ADDRESS sVolumeName; MTF_TAPE_ADDRESS sMachineName; MTF_DATE_TIME sMediaWriteDate; } MTF_DBLK_VOLB; /* ================================================================================== Directory DBLK (DIRB) - The DIRB DBLK, exactly as it appears on tape, including the common DBLK header (MTF_DBLK_HDR) ================================================================================== */ typedef struct { MTF_DBLK_HDR sBlockHeader; UINT32 uDirectoryAttributes; MTF_DATE_TIME sLastModificationDate; MTF_DATE_TIME sCreationDate; MTF_DATE_TIME sBackupDate; MTF_DATE_TIME sLastAccessDate; UINT32 uDirectoryId; MTF_TAPE_ADDRESS sDirectoryName; } MTF_DBLK_DIRB; /* ================================================================================== Directory DBLK (FILE) - The FILE DBLK, exactly as it appears on tape, including the common DBLK header (MTF_DBLK_HDR) ================================================================================== */ typedef struct { MTF_DBLK_HDR sBlockHeader; UINT32 uFileAttributes; MTF_DATE_TIME sLastModificationDate; MTF_DATE_TIME sCreationDate; MTF_DATE_TIME sBackupDate; MTF_DATE_TIME sLastAccessDate; UINT32 uDirectoryId; UINT32 uFileId; MTF_TAPE_ADDRESS sFileName; } MTF_DBLK_FILE; #pragma pack() /* ================================================================================== Corrupt File DBLK (CFIL) - use MTF_DBLK_CFIL_INFO -- same structure ================================================================================== */ typedef MTF_DBLK_CFIL_INFO MTF_DBLK_CFIL; /* ================================================================================== End of Set Pad Block (ESPB) ================================================================================== */ // consists only of header /* ================================================================================== End of Set Block (ESET) - use MTF_DBLK_ESET_INFO -- same structure ================================================================================== */ typedef MTF_DBLK_ESET_INFO MTF_DBLK_ESET; /* ================================================================================== End of Set Block (EOTM) - use MTF_DBLK_EOTM_INFO -- same structure ================================================================================== */ typedef MTF_DBLK_EOTM_INFO MTF_DBLK_EOTM; /* ================================================================================== Soft Filemark (SFMB) - use MTF_DBLK_SFMB_INFO -- same structure ================================================================================== */ typedef MTF_DBLK_SFMB_INFO MTF_DBLK_SFMB; /* ================================================================================== StreamHeader - use MTF_STREAM_INFO -- same structure ================================================================================== */ typedef MTF_STREAM_INFO MTF_STREAM; /*********************************************************************************** ************************************************************************************ ************************************************************************************ **** MTF Misc Data Types ************************************************************************************ ************************************************************************************ ***********************************************************************************/ /* ================================================================================== Alignment Factor ================================================================================== */ /*********************************************************************************** * MTF_SetAlignmentFactor() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetAlignmentFactor(UINT16 uAF) { // store the user's alignment factor in a static variable s_uAlignmentFactor = uAF; } /*********************************************************************************** * MTF_GetAlignmentFactor() * ** MTF API FUNCTION ** ***********************************************************************************/ UINT16 MTF_GetAlignmentFactor() { // make sure an alignment factor was stored, // and return it assert(s_uAlignmentFactor != 0); return s_uAlignmentFactor; } /*********************************************************************************** * MTF_PadToNextAlignmentFactor() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_PadToNextAlignmentFactor( BYTE *pBuffer, size_t nBufUsed, size_t nBufferSize, size_t *pnSizeUsed) { size_t i; size_t nAlignment; MTF_STREAM_INFO sStream; // figure out what the next alignment value is and then pad out the user's buffer // with an SPAD, making sure the buffer is big enough nAlignment = Align(nBufUsed + sizeof(MTF_STREAM_INFO), MTF_GetAlignmentFactor()); *pnSizeUsed = nAlignment; if (nBufferSize < nAlignment) return MTF_ERROR_BUFFER_TOO_SMALL; MTF_SetSTREAMDefaults(&sStream, "SPAD"); sStream.uStreamLength = MTF_CreateUINT64(nAlignment - nBufUsed - sizeof(MTF_STREAM_INFO), 0); MTF_WriteStreamHeader(&sStream, pBuffer + nBufUsed, nBufferSize - nBufUsed, 0); for (i = nBufUsed + sizeof(MTF_STREAM_INFO); i < nAlignment; ++i) pBuffer[i] = 0; return MTF_ERROR_NONE; } /*********************************************************************************** * MTF_PadToNextPhysicalBlockBoundary() - (bmd) * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_PadToNextPhysicalBlockBoundary( BYTE *pBuffer, size_t nBlockSize, size_t nBufUsed, size_t nBufferSize, size_t *pnSizeUsed) { size_t i; size_t nAlignment; MTF_STREAM_INFO sStream; // figure out what the next alignment value is and then pad out the user's buffer // with an SPAD, making sure the buffer is big enough nAlignment = Align(nBufUsed + sizeof(MTF_STREAM_INFO), nBlockSize); *pnSizeUsed = nAlignment; if (nBufferSize < nAlignment) return MTF_ERROR_BUFFER_TOO_SMALL; MTF_SetSTREAMDefaults(&sStream, "SPAD"); sStream.uStreamLength = MTF_CreateUINT64(nAlignment - nBufUsed - sizeof(MTF_STREAM_INFO), 0); MTF_WriteStreamHeader(&sStream, pBuffer + nBufUsed, nBufferSize - nBufUsed, 0); for (i = nBufUsed + sizeof(MTF_STREAM_INFO); i < nAlignment; ++i) pBuffer[i] = 0; return MTF_ERROR_NONE; } /*********************************************************************************** * MTF_CreateUINT64() * ** MTF API FUNCTION ** ***********************************************************************************/ UINT64 MTF_CreateUINT64(UINT32 uLSB, UINT32 uMSB) { UINT64 uRet; uRet = (UINT64) uMSB << 32; uRet += uLSB; return uRet; } /* ================================================================================== Compressed date structure for storing dates in minimal space on tape: BYTE 0 BYTE 1 BYTE 2 BYTE 3 BYTE 4 76543210 76543210 76543210 76543210 76543210 yyyyyyyy yyyyyymm mmdddddh hhhhmmmm mmssssss 33333333 33222222 22221111 11111100 00000000 98765432 10987654 32109876 54321098 76543210 ================================================================================== */ /*********************************************************************************** * MTF_CreateDateTime() * ** MTF API FUNCTION ** ***********************************************************************************/ MTF_DATE_TIME MTF_CreateDateTime( int iYear, int iMonth, int iDay, int iHour, int iMinute, int iSecond ) { MTF_DATE_TIME sDateTime = {0}; UINT16 temp ; // pack the date time structure with the arguments as per the diagram above temp = iYear << 2 ; sDateTime.dt_field[0] = ((UINT8 *)&temp)[1] ; sDateTime.dt_field[1] = ((UINT8 *)&temp)[0] ; temp = iMonth << 6 ; sDateTime.dt_field[1] |= ((UINT8 *)&temp)[1] ; sDateTime.dt_field[2] = ((UINT8 *)&temp)[0] ; temp = iDay << 1 ; sDateTime.dt_field[2] |= ((UINT8 *)&temp)[0] ; temp = iHour << 4 ; sDateTime.dt_field[2] |= ((UINT8 *)&temp)[1] ; sDateTime.dt_field[3] = ((UINT8 *)&temp)[0] ; temp = iMinute << 6 ; sDateTime.dt_field[3] |= ((UINT8 *)&temp)[1] ; sDateTime.dt_field[4] = ((UINT8 *)&temp)[0] ; temp = (UINT16)iSecond ; sDateTime.dt_field[4] |= ((UINT8 *)&temp)[0] ; return sDateTime; } /*********************************************************************************** * MTF_CreateDateTimeFromTM() * ** MTF API FUNCTION ** ***********************************************************************************/ MTF_DATE_TIME MTF_CreateDateTimeFromTM( struct tm *pT ) { // translate call to MTF_CreateDateTime return MTF_CreateDateTime(pT->tm_year + 1900, pT->tm_mon + 1, pT->tm_mday, pT->tm_hour, pT->tm_min, pT->tm_sec); } /*********************************************************************************** * MTF_CreateDateTimeToTM() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_CreateDateTimeToTM( MTF_DATE_TIME *pDT, struct tm *pT ) { UINT8 temp[2] ; // unpack the MTF_DATE_TIME structure and store the results temp[0] = pDT->dt_field[1] ; temp[1] = pDT->dt_field[0] ; pT->tm_year = *((UINT16 *)temp) >> 2 ; temp[0] = pDT->dt_field[2] ; temp[1] = pDT->dt_field[1] ; pT->tm_mon = (*((UINT16 *)temp) >> 6) & 0x000F ; pT->tm_mday = (*((UINT16 *)temp) >> 1) & 0x001F ; temp[0] = pDT->dt_field[3] ; temp[1] = pDT->dt_field[2] ; pT->tm_hour = (*((UINT16 *)temp) >> 4) & 0x001F ; temp[0] = pDT->dt_field[4] ; temp[1] = pDT->dt_field[3] ; pT->tm_min = (*((UINT16 *)temp) >> 6) & 0x003F ; pT->tm_sec = *((UINT16 *)temp) & 0x003F ; } /*********************************************************************************** * MTF_CreateDateNull() * ** MTF API FUNCTION ** ***********************************************************************************/ MTF_DATE_TIME MTF_CreateDateNull() { MTF_DATE_TIME sDateTime = {0}; return sDateTime; } /*********************************************************************************** * MTF_CreateDateTimeFromFileTime() * ** MTF API FUNCTION ** ***********************************************************************************/ MTF_DATE_TIME MTF_CreateDateTimeFromFileTime( FILETIME sFileTime ) { SYSTEMTIME sSystemTime; FileTimeToSystemTime(&sFileTime, &sSystemTime); return MTF_CreateDateTime(sSystemTime.wYear, sSystemTime.wMonth, sSystemTime.wDay, sSystemTime.wHour, sSystemTime.wMinute, sSystemTime.wSecond); } /*********************************************************************************** ************************************************************************************ **** MTF static HELPER FUNCITONS ************************************************************************************ ***********************************************************************************/ /*********************************************************************************** * StringToTapeAddress() * * Description: Used by the MTF_Write#### functions below. Given a Buffer, an * MTF_TAPE_ADDRESS struct and the current end of the string storage * area in the buffer, this function appends the string to the string * storage area, fills in the MTF_TAPE_ADDRESS struct indicating where * the string was stored and returns the new end of the string storage * area accounting for the added string. ***********************************************************************************/ static size_t StringToTapeAddress( MTF_TAPE_ADDRESS *pAd, // the mtf tape address structure to fill BYTE *pBuffer, // the buffer that is being filled wchar_t *str, // the string to store MTF style in the buffer size_t uCurrentStorageOffset // the next available point in the buffer for string storage ) { // if we have a string, // - put the size and offset in the MTF_TAPE_ADDRESS structure and then copy // the string to the pBuffer at the uCurrentStorageOffset'th byte // otherwise // - put a zero size and offset in the MTF_TAPE_ADDRESS struct. // return the new end of the string storage area if (str) { pAd->uSize = (UINT16)wstrsize(str); pAd->uOffset = (UINT16)uCurrentStorageOffset; memcpy(pBuffer + uCurrentStorageOffset, str, pAd->uSize); uCurrentStorageOffset += pAd->uSize; } else { pAd->uSize = 0; pAd->uOffset = 0; } return uCurrentStorageOffset; } /*********************************************************************************** * Align() * * Description: Given uSize and an alignment factor, retuns the value * of the uSize+ pad, where pad is the value necesary to * get to the next alignment factor. * * Returns uSize + pad -- not just pad! ***********************************************************************************/ static size_t Align( size_t uSize, size_t uAlignment) { if (uSize % uAlignment) return uSize - (uSize % uAlignment) + uAlignment; else return uSize; } /*********************************************************************************** * CalcChecksum() * * Description: returns the 16bit XOR sum of the nNum bytes starting at the UINT16 * pointed to by pStartPtr * ***********************************************************************************/ static UINT16 CalcChecksum( BYTE * pStartPtr, int nNum ) { UINT16 resultSoFar = 0; UINT16 *pCur = (UINT16 *) pStartPtr; while( nNum-- ) resultSoFar ^= *pCur++ ; return( resultSoFar ) ; } /*********************************************************************************** * CalcChecksumOfStreamData() - (bmd) * * Description: returns the 32bit XOR sum of the nNum bytes starting at the UINT64 * pointed to by pStartPtr * ***********************************************************************************/ static UINT32 CalcChecksumOfStreamData( BYTE * pStartPtr, int nNum ) { UINT32 resultSoFar = 0; UINT32 *pCur = (UINT32 *) pStartPtr; while( nNum-- ) resultSoFar ^= *pCur++ ; return( resultSoFar ) ; } /*********************************************************************************** ************************************************************************************ ************************************************************************************ **** MTF API STRUCTURE FUNCTIONS ************************************************************************************ ************************************************************************************ ***********************************************************************************/ /* ================================================================================== ===================================================================================== Common DBLK: MTF_DBLK_HDR_INFO ===================================================================================== ================================================================================== */ // Calculates the room that will be taken up in the DBLK by strings and OS specific data static size_t MTF_DBLK_HDR_INFO_CalcAddDataSize( MTF_DBLK_HDR_INFO *pSTDInfo ) { return pSTDInfo->uOSDataSize; } /*********************************************************************************** * MTF_SetDblkHdrDefaults() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetDblkHdrDefaults( MTF_DBLK_HDR_INFO * pStdInfo ) { int i; for (i = 0; i < 5; ++i) pStdInfo->acBlockType[i] = 0; pStdInfo->uBlockAttributes = 0; pStdInfo->uOSID = 0; pStdInfo->uOSVersion = 0; pStdInfo->uDisplayableSize = 0; pStdInfo->uFormatLogicalAddress = 0; pStdInfo->uReservedForMBC = 0; pStdInfo->uSoftwareCompression = MTF_COMPRESS_NONE; pStdInfo->uControlBlockId = 0; pStdInfo->pvOSData = 0; pStdInfo->uOSDataSize = 0; pStdInfo->uStringType = MTF_STRING_UNICODE_STR; } /*********************************************************************************** * MTF_WriteDblkHdrToBuffer() * * Description: called by the MTF_Write#####() functions to format the common block * header to the buffer * - this also calculates the header check sum and fills it in * * Pre: - *puCurrentStorageOffset is the offset at where string and OS Data storage will * begin in the buffer * - the size of the buffer has been checked and can hold any info written to it * * Post: - *puCurrentStorageOffset is updated to reflect any added strings or storage * ***********************************************************************************/ static void MTF_WriteDblkHdrToBuffer( UINT8 acID[4], // four byte header id to write UINT16 uOffsetToFirstStream, // the size of the DBLK for which this will be a header MTF_DBLK_HDR_INFO *psHdrInfo, // the header info struct to use (filled in by client) BYTE *pBuffer, // the buffer to format to size_t *puCurrentStorage) // the point in the buffer where string and os data stroage begins // (this will be updated upon return to reflect added data to storage) { MTF_DBLK_HDR *pHDR = 0; UINT16 uCurrentStorageOffset = 0; int i; // - if no *puCurrentStorage, we assume storage starts at // the end of the on tape MTF_DBLK_HDR structure if (puCurrentStorage) uCurrentStorageOffset = (UINT16)*puCurrentStorage; else uCurrentStorageOffset = (UINT16)sizeof(MTF_DBLK_HDR); pHDR = (MTF_DBLK_HDR *) pBuffer; // write in the four byte DBLK ID for (i = 0; i < 4; ++i) pHDR->acBlockType[i] = acID[i]; pHDR->uBlockAttributes = psHdrInfo->uBlockAttributes; pHDR->uOffsetToFirstStream = uOffsetToFirstStream; pHDR->uOSID = psHdrInfo->uOSID; pHDR->uOSVersion = psHdrInfo->uOSVersion; pHDR->uDisplayableSize = psHdrInfo->uDisplayableSize; pHDR->uFormatLogicalAddress = psHdrInfo->uFormatLogicalAddress; pHDR->uReservedForMBC = 0; // must be zero in backup set pHDR->uSoftwareCompression = psHdrInfo->uSoftwareCompression; pHDR->uControlBlockId = psHdrInfo->uControlBlockId; pHDR->sOSSpecificData.uSize = psHdrInfo->uOSDataSize; // write out the os specific data at the current storage offset and update it if (psHdrInfo->uOSDataSize) { pHDR->sOSSpecificData.uOffset = uCurrentStorageOffset; memcpy(pBuffer + uCurrentStorageOffset, psHdrInfo->pvOSData, psHdrInfo->uOSDataSize); uCurrentStorageOffset += psHdrInfo->uOSDataSize; } else { pHDR->sOSSpecificData.uOffset = 0; pHDR->sOSSpecificData.uSize = 0; } pHDR->uStringType = psHdrInfo->uStringType; pHDR->uHeaderCheckSum = CalcChecksum(pBuffer, sizeof(MTF_DBLK_HDR) / sizeof(UINT16) - 1); if (puCurrentStorage) *puCurrentStorage = uCurrentStorageOffset; } void MTF_DBLK_HDR_INFO_ReadFromBuffer( MTF_DBLK_HDR_INFO *psHdrInfo, BYTE *pBuffer) { MTF_DBLK_HDR *pHDR = 0; size_t uCurrentStorageOffset = 0; int i; pHDR = (MTF_DBLK_HDR *) pBuffer; for (i = 0; i < 4; ++i) psHdrInfo->acBlockType[i] = pHDR->acBlockType[i]; psHdrInfo->acBlockType[4] = 0; psHdrInfo->uOffsetToFirstStream = pHDR->uOffsetToFirstStream; psHdrInfo->uBlockAttributes = pHDR->uBlockAttributes ; psHdrInfo->uOSID = pHDR->uOSID; psHdrInfo->uOSVersion = pHDR->uOSVersion; psHdrInfo->uDisplayableSize = pHDR->uDisplayableSize; psHdrInfo->uFormatLogicalAddress= pHDR->uFormatLogicalAddress; psHdrInfo->uSoftwareCompression = pHDR->uSoftwareCompression; psHdrInfo->uControlBlockId = pHDR->uControlBlockId; psHdrInfo->uOSDataSize = pHDR->sOSSpecificData.uSize; psHdrInfo->pvOSData = (pBuffer + pHDR->sOSSpecificData.uOffset); psHdrInfo->uStringType = pHDR->uStringType; psHdrInfo->uHeaderCheckSum = pHDR->uHeaderCheckSum; } /* ================================================================================== ===================================================================================== TAPE DBLK: MTF_DBLK_TAPE_INFO ===================================================================================== ================================================================================== */ // Calculates the room that will be taken up in the DBLK by strings and OS specific data // **NOT INCLUDING THE COMMON DBLK HEADER additional info ** static size_t MTF_DBLK_TAPE_INFO_CalcAddDataSize( MTF_DBLK_TAPE_INFO *pTapeInfo ) { return wstrsize(pTapeInfo->szTapeName) + wstrsize(pTapeInfo->szTapeDescription) + wstrsize(pTapeInfo->szTapePassword) + wstrsize(pTapeInfo->szSoftwareName); } /*********************************************************************************** * MTF_SetTAPEDefaults() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetTAPEDefaults( MTF_DBLK_TAPE_INFO *pTapeInfo ) { time_t tTime; time(&tTime); pTapeInfo->uTapeFamilyId = 0; pTapeInfo->uTapeAttributes = 0; pTapeInfo->uTapeSequenceNumber = 0; pTapeInfo->uPasswordEncryptionAlgorithm = MTF_PW_ENCRYPT_NONE; pTapeInfo->uSoftFilemarkBlockSize = 0; pTapeInfo->uTapeCatalogType = MTF_OTC_NONE; // MTF_OTC_TYPE pTapeInfo->szTapeName = 0 ; pTapeInfo->szTapeDescription = 0 ; pTapeInfo->szTapePassword = 0; pTapeInfo->szSoftwareName = 0; pTapeInfo->uAlignmentFactor = MTF_GetAlignmentFactor(); pTapeInfo->uSoftwareVendorId = 0; pTapeInfo->sTapeDate = MTF_CreateDateTimeFromTM(gmtime(&tTime)); pTapeInfo->uMTFMajorVersion = MTF_FORMAT_VER_MAJOR; } /*********************************************************************************** * MTF_WriteTAPEDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_WriteTAPEDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_TAPE_INFO *psTapeInfo, BYTE *pBuffer, size_t nBufferSize, size_t *pnSizeUsed) { UINT16 uOffsetToFirstStream; // // Figure the size of the entire DBLK & make sure we have room // uOffsetToFirstStream = sizeof(MTF_DBLK_TAPE) + MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo) + MTF_DBLK_TAPE_INFO_CalcAddDataSize(psTapeInfo); uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4); if (nBufferSize < uOffsetToFirstStream) { if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; return MTF_ERROR_BUFFER_TOO_SMALL; } memset(pBuffer, 0, uOffsetToFirstStream); // // write the header and then fill in the stuff from this info struct // { MTF_DBLK_TAPE *pTape = 0; size_t uCurrentStorageOffset = 0; uCurrentStorageOffset = sizeof(MTF_DBLK_TAPE); MTF_WriteDblkHdrToBuffer( MTF_ID_TAPE, uOffsetToFirstStream, psHdrInfo, pBuffer, &uCurrentStorageOffset); pTape = (MTF_DBLK_TAPE *) pBuffer; pTape->uTapeFamilyId = psTapeInfo->uTapeFamilyId; pTape->uTapeAttributes = psTapeInfo->uTapeAttributes; pTape->uTapeSequenceNumber = psTapeInfo->uTapeSequenceNumber; pTape->uPasswordEncryptionAlgorithm = psTapeInfo->uPasswordEncryptionAlgorithm; pTape->uSoftFilemarkBlockSize = psTapeInfo->uSoftFilemarkBlockSize; pTape->uTapeCatalogType = psTapeInfo->uTapeCatalogType; uCurrentStorageOffset = StringToTapeAddress(&pTape->sTapeName, pBuffer, psTapeInfo->szTapeName, uCurrentStorageOffset); uCurrentStorageOffset = StringToTapeAddress(&pTape->sTapeDescription, pBuffer, psTapeInfo->szTapeDescription, uCurrentStorageOffset); uCurrentStorageOffset = StringToTapeAddress(&pTape->sTapePassword, pBuffer, psTapeInfo->szTapePassword, uCurrentStorageOffset); uCurrentStorageOffset = StringToTapeAddress(&pTape->sSoftware_name, pBuffer, psTapeInfo->szSoftwareName, uCurrentStorageOffset); pTape->uAlignmentFactor = psTapeInfo->uAlignmentFactor; pTape->uSoftwareVendorId = psTapeInfo->uSoftwareVendorId; pTape->sTapeDate = psTapeInfo->sTapeDate; pTape->uMTFMajorVersion = psTapeInfo->uMTFMajorVersion; if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; } return MTF_ERROR_NONE; } /*********************************************************************************** * MTF_ReadTAPEDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_ReadTAPEDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_TAPE_INFO *psTapeInfo, BYTE *pBuffer) { MTF_DBLK_TAPE *pTape = 0; ClearStrings(); MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer); pTape = (MTF_DBLK_TAPE *) pBuffer; psTapeInfo->uTapeFamilyId = pTape->uTapeFamilyId; psTapeInfo->uTapeAttributes = pTape->uTapeAttributes; psTapeInfo->uTapeSequenceNumber = pTape->uTapeSequenceNumber; psTapeInfo->uPasswordEncryptionAlgorithm = pTape->uPasswordEncryptionAlgorithm; psTapeInfo->uSoftFilemarkBlockSize = pTape->uSoftFilemarkBlockSize; psTapeInfo->uTapeCatalogType = pTape->uTapeCatalogType; psTapeInfo->uAlignmentFactor = pTape->uAlignmentFactor; psTapeInfo->uSoftwareVendorId = pTape->uSoftwareVendorId; psTapeInfo->sTapeDate = pTape->sTapeDate; psTapeInfo->uMTFMajorVersion = pTape->uMTFMajorVersion; psTapeInfo->szTapeName = MakeString((wchar_t *) (pBuffer + pTape->sTapeName.uOffset), pTape->sTapeName.uSize); psTapeInfo->szTapeDescription = MakeString((wchar_t *) (pBuffer + pTape->sTapeDescription.uOffset), pTape->sTapeDescription.uSize); psTapeInfo->szTapePassword = MakeString((wchar_t *) (pBuffer + pTape->sTapePassword.uOffset), pTape->sTapePassword.uSize); psTapeInfo->szSoftwareName = MakeString((wchar_t *) (pBuffer + pTape->sSoftware_name.uOffset), pTape->sSoftware_name.uSize); if ( !psTapeInfo->szTapeName || !psTapeInfo->szTapeDescription || !psTapeInfo->szTapePassword || !psTapeInfo->szSoftwareName) return MTF_OUT_OF_MEMORY; return MTF_ERROR_NONE; } /* ================================================================================== ===================================================================================== SSET DBLK: MTF_DBLK_SSET_INFO ===================================================================================== ================================================================================== */ // Calculates the room that will be taken up in the DBLK by strings and OS specific data // **NOT INCLUDING THE COMMON DBLK HEADER additional info ** static size_t MTF_DBLK_SSET_INFO_CalcAddDataSize( MTF_DBLK_SSET_INFO *pSSETInfo ) { return wstrsize(pSSETInfo->szDataSetName) + wstrsize(pSSETInfo->szDataSetDescription) + wstrsize(pSSETInfo->szDataSetPassword) + wstrsize(pSSETInfo->szUserName); } /*********************************************************************************** * MTF_SetSSETDefaults() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetSSETDefaults( MTF_DBLK_SSET_INFO *pSSETInfo ) { time_t tTime; time(&tTime); pSSETInfo->uSSETAttributes = 0; pSSETInfo->uPasswordEncryptionAlgorithm = MTF_PW_ENCRYPT_NONE; pSSETInfo->uDataEncryptionAlgorithm = MTF_DATA_ENCRYPT_NONE; pSSETInfo->uSoftwareVendorId = 0; pSSETInfo->uDataSetNumber = 0; pSSETInfo->szDataSetName = 0 ; pSSETInfo->szDataSetDescription = 0 ; pSSETInfo->szDataSetPassword = 0 ; pSSETInfo->szUserName = 0 ; pSSETInfo->uPhysicalBlockAddress = 0; pSSETInfo->sMediaWriteDate = MTF_CreateDateTimeFromTM(gmtime(&tTime)); pSSETInfo->uSoftwareVerMjr = 0; pSSETInfo->uSoftwareVerMnr = 0; pSSETInfo->uTimeZone = MTF_LOCAL_TZ; pSSETInfo->uMTFMinorVer = MTF_FORMAT_VER_MINOR; pSSETInfo->uTapeCatalogVersion = MTF_OTC_NONE; // MTF_OTC_VERSION } /*********************************************************************************** * MTF_WriteSSETDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_WriteSSETDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_SSET_INFO *psSSETInfo, BYTE *pBuffer, size_t nBufferSize, size_t *pnSizeUsed) { UINT16 uOffsetToFirstStream; // // Figure the size of the entire DBLK & make sure we have room // uOffsetToFirstStream = sizeof(MTF_DBLK_SSET) + MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo) + MTF_DBLK_SSET_INFO_CalcAddDataSize(psSSETInfo); uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4); if (nBufferSize < uOffsetToFirstStream) { if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; return MTF_ERROR_BUFFER_TOO_SMALL; } memset(pBuffer, 0, uOffsetToFirstStream); { MTF_DBLK_SSET *psSSET = 0; size_t uCurrentStorageOffset = 0; uCurrentStorageOffset = sizeof(MTF_DBLK_SSET); MTF_WriteDblkHdrToBuffer( MTF_ID_SSET, uOffsetToFirstStream, psHdrInfo, pBuffer, &uCurrentStorageOffset); psSSET = (MTF_DBLK_SSET *) pBuffer; psSSET->uSSETAttributes = psSSETInfo->uSSETAttributes; psSSET->uPasswordEncryptionAlgorithm = psSSETInfo->uPasswordEncryptionAlgorithm; psSSET->uDataEncryptionAlgorithm = psSSETInfo->uDataEncryptionAlgorithm; psSSET->uSoftwareVendorId = psSSETInfo->uSoftwareVendorId; psSSET->uDataSetNumber = psSSETInfo->uDataSetNumber; uCurrentStorageOffset = StringToTapeAddress(&psSSET->sDataSetName, pBuffer, psSSETInfo->szDataSetName, uCurrentStorageOffset); uCurrentStorageOffset = StringToTapeAddress(&psSSET->sDataSetDescription, pBuffer, psSSETInfo->szDataSetDescription, uCurrentStorageOffset); uCurrentStorageOffset = StringToTapeAddress(&psSSET->sDataSetPassword, pBuffer, psSSETInfo->szDataSetPassword, uCurrentStorageOffset); uCurrentStorageOffset = StringToTapeAddress(&psSSET->sUserName, pBuffer, psSSETInfo->szUserName, uCurrentStorageOffset); psSSET->uPhysicalBlockAddress = psSSETInfo->uPhysicalBlockAddress; psSSET->sMediaWriteDate = psSSETInfo->sMediaWriteDate; psSSET->uSoftwareVerMjr = psSSETInfo->uSoftwareVerMjr; psSSET->uSoftwareVerMnr = psSSETInfo->uSoftwareVerMnr; psSSET->uTimeZone = psSSETInfo->uTimeZone; psSSET->uMTFMinorVer = psSSETInfo->uMTFMinorVer; psSSET->uTapeCatalogVersion = psSSETInfo->uTapeCatalogVersion; if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; } return MTF_ERROR_NONE; } /*********************************************************************************** * MTF_ReadSSETDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_ReadSSETDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_SSET_INFO *psSSETInfo, BYTE *pBuffer) { MTF_DBLK_SSET *psSSET = 0; ClearStrings(); MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer); psSSET = (MTF_DBLK_SSET *) pBuffer; psSSETInfo->uSSETAttributes = psSSET->uSSETAttributes; psSSETInfo->uPasswordEncryptionAlgorithm = psSSET->uPasswordEncryptionAlgorithm; psSSETInfo->uDataEncryptionAlgorithm = psSSET->uDataEncryptionAlgorithm; psSSETInfo->uSoftwareVendorId = psSSET->uSoftwareVendorId; psSSETInfo->uDataSetNumber = psSSET->uDataSetNumber; psSSETInfo->uPhysicalBlockAddress = psSSET->uPhysicalBlockAddress; psSSETInfo->sMediaWriteDate = psSSET->sMediaWriteDate; psSSETInfo->uSoftwareVerMjr = psSSET->uSoftwareVerMjr; psSSETInfo->uSoftwareVerMnr = psSSET->uSoftwareVerMnr; psSSETInfo->uTimeZone = psSSET->uTimeZone; psSSETInfo->uMTFMinorVer = psSSET->uMTFMinorVer; psSSETInfo->uTapeCatalogVersion = psSSET->uTapeCatalogVersion; psSSETInfo->szDataSetName = MakeString((wchar_t *) (pBuffer + psSSET->sDataSetName.uOffset), psSSET->sDataSetName.uSize); psSSETInfo->szDataSetDescription = MakeString((wchar_t *) (pBuffer + psSSET->sDataSetDescription.uOffset), psSSET->sDataSetDescription.uSize); psSSETInfo->szDataSetPassword = MakeString((wchar_t *) (pBuffer + psSSET->sDataSetPassword.uOffset), psSSET->sDataSetPassword.uSize); psSSETInfo->szUserName = MakeString((wchar_t *) (pBuffer + psSSET->sUserName.uOffset), psSSET->sUserName.uSize); if ( !psSSETInfo->szDataSetName || !psSSETInfo->szDataSetDescription || !psSSETInfo->szDataSetPassword || !psSSETInfo->szUserName ) return MTF_OUT_OF_MEMORY; return MTF_ERROR_NONE; } /* ================================================================================== ===================================================================================== VOLB DBLK: MTF_DBLK_VOLB_INFO ===================================================================================== ================================================================================== */ // Calculates the room that will be taken up in the DBLK by strings and OS specific data // **NOT INCLUDING THE COMMON DBLK HEADER additional info ** static size_t MTF_DBLK_VOLB_INFO_CalcAddDataSize( MTF_DBLK_VOLB_INFO *pVOLBInfo ) { return wstrsize(pVOLBInfo->szDeviceName) + wstrsize(pVOLBInfo->szVolumeName) + wstrsize(pVOLBInfo->szMachineName); } /*********************************************************************************** * MTF_SetVOLBDefaults() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetVOLBDefaults(MTF_DBLK_VOLB_INFO *pVOLBInfo) { time_t tTime; time(&tTime); pVOLBInfo->uVolumeAttributes = 0; pVOLBInfo->szDeviceName = 0 ; pVOLBInfo->szVolumeName = 0 ; pVOLBInfo->szMachineName = 0 ; pVOLBInfo->sMediaWriteDate = MTF_CreateDateTimeFromTM(gmtime(&tTime));; } /*********************************************************************************** * MTF_SetVOLBForDevice() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetVOLBForDevice(MTF_DBLK_VOLB_INFO *pVOLBInfo, wchar_t *szDevice) { int nBufSize = MAX_COMPUTERNAME_LENGTH + 1; wchar_t tempDeviceName[STRLEN+4]; wcscpy(s_szDeviceName, szDevice); MTF_SetVOLBDefaults(pVOLBInfo); // initialize // Determine the format and set the appropriate bit in the VOLB attributes. if (*(s_szDeviceName+1) == L':') { // drive letter w/colon format pVOLBInfo->uVolumeAttributes |= MTF_VOLB_DEV_DRIVE; } else if (0 == wcsncmp( s_szDeviceName, L"UNC", 3 )) { // UNC format pVOLBInfo->uVolumeAttributes |= MTF_VOLB_DEV_UNC; } else { // operating system specific format pVOLBInfo->uVolumeAttributes |= MTF_VOLB_DEV_OS_SPEC; } // need to prepend \\?\ for the GetVolumeInformation call wcscpy(tempDeviceName, L"\\\\?\\"); wcscat(tempDeviceName, s_szDeviceName); GetVolumeInformationW(tempDeviceName, s_szVolumeName, STRLEN, 0, 0, 0, 0, 0); GetComputerNameW(s_szMachineName, &nBufSize); pVOLBInfo->szDeviceName = s_szDeviceName; pVOLBInfo->szVolumeName = s_szVolumeName; pVOLBInfo->szMachineName = s_szMachineName; } /*********************************************************************************** * MTF_WriteVOLBDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_WriteVOLBDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_VOLB_INFO *psVOLBInfo, BYTE *pBuffer, size_t nBufferSize, size_t *pnSizeUsed) { UINT16 uOffsetToFirstStream; // // Figure the size of the entire DBLK & make sure we have room // uOffsetToFirstStream = sizeof(MTF_DBLK_VOLB) + MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo) + MTF_DBLK_VOLB_INFO_CalcAddDataSize(psVOLBInfo); uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4); if (nBufferSize < uOffsetToFirstStream) { if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; return MTF_ERROR_BUFFER_TOO_SMALL; } memset(pBuffer, 0, uOffsetToFirstStream); { MTF_DBLK_VOLB *psVOLB = 0; size_t uCurrentStorageOffset = 0; uCurrentStorageOffset = sizeof(MTF_DBLK_VOLB); MTF_WriteDblkHdrToBuffer( MTF_ID_VOLB, uOffsetToFirstStream, psHdrInfo, pBuffer, &uCurrentStorageOffset); psVOLB = (MTF_DBLK_VOLB *) pBuffer; psVOLB->uVolumeAttributes = psVOLBInfo->uVolumeAttributes; uCurrentStorageOffset = StringToTapeAddress(&psVOLB->sDeviceName, pBuffer, psVOLBInfo->szDeviceName, uCurrentStorageOffset); uCurrentStorageOffset = StringToTapeAddress(&psVOLB->sVolumeName, pBuffer, psVOLBInfo->szVolumeName, uCurrentStorageOffset); uCurrentStorageOffset = StringToTapeAddress(&psVOLB->sMachineName, pBuffer, psVOLBInfo->szMachineName, uCurrentStorageOffset); psVOLB->sMediaWriteDate = psVOLBInfo->sMediaWriteDate; if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; } return MTF_ERROR_NONE; } /*********************************************************************************** * MTF_ReadVOLBDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_ReadVOLBDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_VOLB_INFO *psVOLBInfo, BYTE *pBuffer) { MTF_DBLK_VOLB *psVOLB = 0; ClearStrings(); MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer); psVOLB = (MTF_DBLK_VOLB *) pBuffer; psVOLBInfo->uVolumeAttributes = psVOLB->uVolumeAttributes; psVOLBInfo->sMediaWriteDate = psVOLB->sMediaWriteDate; psVOLBInfo->szDeviceName = MakeString((wchar_t *) (pBuffer + psVOLB->sDeviceName.uOffset), psVOLB->sDeviceName.uSize); psVOLBInfo->szVolumeName = MakeString((wchar_t *) (pBuffer + psVOLB->sVolumeName.uOffset), psVOLB->sVolumeName.uSize); psVOLBInfo->szMachineName = MakeString((wchar_t *) (pBuffer + psVOLB->sMachineName.uOffset), psVOLB->sMachineName.uSize); if ( !psVOLBInfo->szDeviceName || !psVOLBInfo->szVolumeName || !psVOLBInfo->szMachineName ) return MTF_OUT_OF_MEMORY; return MTF_ERROR_NONE; } /* ================================================================================== ===================================================================================== DIRB DBLK: MTF_DBLK_DIRB_INFO ===================================================================================== ================================================================================== */ // Calculates the room that will be taken up in the DBLK by strings and OS specific data // **NOT INCLUDING THE COMMON DBLK HEADER additional info ** static size_t MTF_DBLK_DIRB_INFO_CalcAddDataSize(MTF_DBLK_DIRB_INFO *pDIRBInfo) { return wstrsize(pDIRBInfo->szDirectoryName); } /*********************************************************************************** * MTF_SetDIRBDefaults() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetDIRBDefaults( MTF_DBLK_DIRB_INFO *pDIRBInfo ) { pDIRBInfo->uDirectoryAttributes = 0; pDIRBInfo->sLastModificationDate = MTF_CreateDateNull(); pDIRBInfo->sCreationDate = MTF_CreateDateNull(); pDIRBInfo->sBackupDate = MTF_CreateDateNull(); pDIRBInfo->sLastAccessDate = MTF_CreateDateNull(); pDIRBInfo->uDirectoryId = 0; pDIRBInfo->szDirectoryName = 0 ; } /*********************************************************************************** * MTF_SetDIRBFromFindData() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetDIRBFromFindData( MTF_DBLK_DIRB_INFO *pDIRBInfo, wchar_t *szDirectoryName, WIN32_FIND_DATAW *pFindData ) { MTF_SetDIRBDefaults(pDIRBInfo); // initialize if ( wcslen( szDirectoryName ) < STRLEN ) { wcscpy(s_szDirectoryName, szDirectoryName); pDIRBInfo->szDirectoryName = s_szDirectoryName; } else { pDIRBInfo->uDirectoryAttributes |= MTF_DIRB_PATH_IN_STREAM; pDIRBInfo->szDirectoryName = 0; } if (pFindData) { pDIRBInfo->uDirectoryAttributes |= pFindData->dwFileAttributes & FILE_ATTRIBUTE_READONLY ? MTF_DIRB_READ_ONLY : 0 | pFindData->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ? MTF_DIRB_HIDDEN : 0 | pFindData->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ? MTF_DIRB_SYSTEM : 0 | pFindData->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE ? MTF_DIRB_MODIFIED : 0; pDIRBInfo->sLastModificationDate = MTF_CreateDateTimeFromFileTime(pFindData->ftLastWriteTime); pDIRBInfo->sCreationDate = MTF_CreateDateTimeFromFileTime(pFindData->ftCreationTime); pDIRBInfo->sLastAccessDate = MTF_CreateDateTimeFromFileTime(pFindData->ftLastAccessTime); } pDIRBInfo->uDirectoryId = 0; } /*********************************************************************************** * MTF_WriteDIRBDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_WriteDIRBDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_DIRB_INFO *psDIRBInfo, BYTE *pBuffer, size_t nBufferSize, size_t *pnSizeUsed) { UINT16 uOffsetToFirstStream; // // Figure the size of the entire DBLK & make sure we have room // uOffsetToFirstStream = sizeof(MTF_DBLK_DIRB) + MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo) + MTF_DBLK_DIRB_INFO_CalcAddDataSize(psDIRBInfo); uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4); if (nBufferSize < uOffsetToFirstStream) { if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; return MTF_ERROR_BUFFER_TOO_SMALL; } memset(pBuffer, 0, uOffsetToFirstStream); { MTF_DBLK_DIRB *psDIRB = 0; size_t uCurrentStorageOffset = 0; uCurrentStorageOffset = sizeof(MTF_DBLK_DIRB); MTF_WriteDblkHdrToBuffer( MTF_ID_DIRB, uOffsetToFirstStream, psHdrInfo, pBuffer, &uCurrentStorageOffset); psDIRB = (MTF_DBLK_DIRB *) pBuffer; psDIRB->uDirectoryAttributes = psDIRBInfo->uDirectoryAttributes; psDIRB->sLastModificationDate = psDIRBInfo->sLastModificationDate; psDIRB->sCreationDate = psDIRBInfo->sCreationDate; psDIRB->sBackupDate = psDIRBInfo->sBackupDate; psDIRB->sLastAccessDate = psDIRBInfo->sLastAccessDate; psDIRB->uDirectoryId = psDIRBInfo->uDirectoryId; // // here, we need to turn the slashes (L'\\') to zeros (L'\0')in the directory name string... // { int i, iLen; wchar_t *szDirectoryName = (wchar_t *) (pBuffer + uCurrentStorageOffset); uCurrentStorageOffset = StringToTapeAddress(&psDIRB->sDirectoryName, pBuffer, psDIRBInfo->szDirectoryName, uCurrentStorageOffset); iLen = wstrsize(psDIRBInfo->szDirectoryName); for (i = 0; i < iLen; ++i) if (szDirectoryName[i] == L'\\') szDirectoryName[i] = L'\0'; } if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; } return MTF_ERROR_NONE; } /*********************************************************************************** * MTF_ReadDIRBDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_ReadDIRBDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_DIRB_INFO *psDIRBInfo, BYTE *pBuffer) { MTF_DBLK_DIRB *psDIRB = 0; ClearStrings(); MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer); psDIRB = (MTF_DBLK_DIRB *) pBuffer; psDIRBInfo->uDirectoryAttributes = psDIRB->uDirectoryAttributes; psDIRBInfo->sLastModificationDate = psDIRB->sLastModificationDate; psDIRBInfo->sCreationDate = psDIRB->sCreationDate; psDIRBInfo->sBackupDate = psDIRB->sBackupDate; psDIRBInfo->sLastAccessDate = psDIRB->sLastAccessDate; psDIRBInfo->uDirectoryId = psDIRB->uDirectoryId; psDIRBInfo->szDirectoryName = NULL; // // we need to turn the zeros in the directory name back to slashes // (there are no terminating \0's in the string -- all \0's are really \\'s // { wchar_t *pTmpBuffer; int i; pTmpBuffer = (wchar_t *) malloc(psDIRB->sDirectoryName.uSize); if (pTmpBuffer) { memmove(pTmpBuffer, pBuffer + psDIRB->sDirectoryName.uOffset, psDIRB->sDirectoryName.uSize); for (i = 0; i < psDIRB->sDirectoryName.uSize; ++i) if (pTmpBuffer[i] == L'\0') pTmpBuffer[i] = L'\\'; psDIRBInfo->szDirectoryName = MakeString(pTmpBuffer, psDIRB->sDirectoryName.uSize); free(pTmpBuffer); } } if ( !psDIRBInfo->szDirectoryName ) return MTF_OUT_OF_MEMORY; return MTF_ERROR_NONE; } /* ================================================================================== ===================================================================================== FILE DBLK: MTF_DBLK_FILE_INFO ===================================================================================== ================================================================================== */ // Calculates the room that will be taken up in the DBLK by strings and OS specific data // **NOT INCLUDING THE COMMON DBLK HEADER additional info ** static size_t MTF_DBLK_FILE_INFO_CalcAddDataSize(MTF_DBLK_FILE_INFO *pFILEInfo) { return wstrsize(pFILEInfo->szFileName); } /*********************************************************************************** * MTF_SetFILEDefaults() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetFILEDefaults(MTF_DBLK_FILE_INFO *pFILEInfo) { pFILEInfo->uFileAttributes = 0; pFILEInfo->sLastModificationDate = MTF_CreateDateNull(); pFILEInfo->sCreationDate = MTF_CreateDateNull(); pFILEInfo->sBackupDate = MTF_CreateDateNull(); pFILEInfo->sLastAccessDate = MTF_CreateDateNull(); pFILEInfo->uDirectoryId = 0; pFILEInfo->uFileId = 0; pFILEInfo->szFileName = 0; } /*********************************************************************************** * MTF_SetFILEFromFindData() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetFILEFromFindData(MTF_DBLK_FILE_INFO *pFILEInfo, WIN32_FIND_DATAW *pFindData) { time_t tTime; time(&tTime); MTF_SetFILEDefaults(pFILEInfo); // initialize wcscpy(s_szFileName, pFindData->cFileName); pFILEInfo->uFileAttributes = (pFindData->dwFileAttributes & FILE_ATTRIBUTE_READONLY ? MTF_FILE_READ_ONLY : 0) | (pFindData->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ? MTF_FILE_HIDDEN : 0) | (pFindData->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ? MTF_FILE_SYSTEM : 0) | (pFindData->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE ? MTF_FILE_MODIFIED : 0) ; pFILEInfo->sLastModificationDate = MTF_CreateDateTimeFromFileTime(pFindData->ftLastWriteTime); pFILEInfo->sCreationDate = MTF_CreateDateTimeFromFileTime(pFindData->ftCreationTime); pFILEInfo->sLastAccessDate = MTF_CreateDateTimeFromFileTime(pFindData->ftLastAccessTime); pFILEInfo->uDirectoryId = 0; pFILEInfo->uFileId = 0; pFILEInfo->szFileName = s_szFileName; pFILEInfo->uDisplaySize = MTF_CreateUINT64(pFindData->nFileSizeLow, pFindData->nFileSizeHigh); } /*********************************************************************************** * MTF_WriteFILEDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_WriteFILEDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_FILE_INFO *psFILEInfo, BYTE *pBuffer, size_t nBufferSize, size_t *pnSizeUsed) { UINT16 uOffsetToFirstStream; // // Figure the size of the entire DBLK & make sure we have room // uOffsetToFirstStream = sizeof(MTF_DBLK_FILE) + MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo) + MTF_DBLK_FILE_INFO_CalcAddDataSize(psFILEInfo); uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4); if (nBufferSize < uOffsetToFirstStream) { if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; return MTF_ERROR_BUFFER_TOO_SMALL; } memset(pBuffer, 0, uOffsetToFirstStream); { MTF_DBLK_FILE *psFILE = 0; size_t uCurrentStorageOffset = 0; uCurrentStorageOffset = sizeof(MTF_DBLK_FILE); psHdrInfo->uDisplayableSize = psFILEInfo->uDisplaySize; MTF_WriteDblkHdrToBuffer( MTF_ID_FILE, uOffsetToFirstStream, psHdrInfo, pBuffer, &uCurrentStorageOffset); psFILE = (MTF_DBLK_FILE *) pBuffer; psFILE->uFileAttributes = psFILEInfo->uFileAttributes; psFILE->sLastModificationDate = psFILEInfo->sLastModificationDate; psFILE->sCreationDate = psFILEInfo->sCreationDate; psFILE->sBackupDate = psFILEInfo->sBackupDate; psFILE->sLastAccessDate = psFILEInfo->sLastAccessDate; psFILE->uDirectoryId = psFILEInfo->uDirectoryId; psFILE->uFileId = psFILEInfo->uFileId; uCurrentStorageOffset = StringToTapeAddress(&psFILE->sFileName, pBuffer, psFILEInfo->szFileName, uCurrentStorageOffset); if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; } return MTF_ERROR_NONE; } /*********************************************************************************** * MTF_ReadFILEDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_ReadFILEDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_FILE_INFO *psFILEInfo, BYTE *pBuffer) { MTF_DBLK_FILE *psFILE = 0; ClearStrings(); MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer); psFILE = (MTF_DBLK_FILE *) pBuffer; psFILEInfo->uFileAttributes = psFILE->uFileAttributes; psFILEInfo->sLastModificationDate = psFILE->sLastModificationDate; psFILEInfo->sCreationDate = psFILE->sCreationDate; psFILEInfo->sBackupDate = psFILE->sBackupDate; psFILEInfo->sLastAccessDate = psFILE->sLastAccessDate; psFILEInfo->uDirectoryId = psFILE->uDirectoryId; psFILEInfo->uFileId = psFILE->uFileId; psFILEInfo->szFileName = MakeString((wchar_t *) (pBuffer + psFILE->sFileName.uOffset), psFILE->sFileName.uSize); if ( !psFILEInfo->szFileName ) return MTF_OUT_OF_MEMORY; return MTF_ERROR_NONE; } /* ================================================================================== ===================================================================================== CFIL DBLK: MTF_DBLK_CFIL_INFO ===================================================================================== ================================================================================== */ /*********************************************************************************** * MTF_SetCFILDefaults() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetCFILDefaults( MTF_DBLK_CFIL_INFO *pCFILInfo ) { pCFILInfo->uCFileAttributes = MTF_CFIL_UNREADABLE_BLK; pCFILInfo->uDirectoryId = 0; pCFILInfo->uFileId = 0; pCFILInfo->uStreamOffset = 0; pCFILInfo->uCorruptStreamNumber = 0; } /*********************************************************************************** * MTF_WriteCFILDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_WriteCFILDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_CFIL_INFO *psCFILInfo, BYTE *pBuffer, size_t nBufferSize, size_t *pnSizeUsed) { UINT16 uOffsetToFirstStream; // // Figure the size of the entire DBLK & make sure we have room // uOffsetToFirstStream = sizeof(MTF_DBLK_HDR) + sizeof(MTF_DBLK_CFIL) + MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo); uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4); if (nBufferSize < uOffsetToFirstStream) { if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; return MTF_ERROR_BUFFER_TOO_SMALL; } memset(pBuffer, 0, uOffsetToFirstStream); { MTF_DBLK_CFIL_INFO *psCFIL = 0; size_t uCurrentStorageOffset = 0; uCurrentStorageOffset = sizeof(MTF_DBLK_HDR) + sizeof(MTF_DBLK_CFIL); MTF_WriteDblkHdrToBuffer( MTF_ID_CFIL, uOffsetToFirstStream, psHdrInfo, pBuffer, &uCurrentStorageOffset); psCFIL = (MTF_DBLK_CFIL_INFO *) (pBuffer + sizeof(MTF_DBLK_HDR)); *psCFIL = *psCFILInfo; if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; } return MTF_ERROR_NONE; } /*********************************************************************************** * MTF_ReadCFILDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_ReadCFILDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_CFIL_INFO *psCFILInfo, BYTE *pBuffer) { MTF_DBLK_CFIL *psCFIL = 0; ClearStrings(); MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer); psCFIL = (MTF_DBLK_CFIL_INFO *) (pBuffer + sizeof(MTF_DBLK_HDR)); *psCFILInfo = *psCFIL; return MTF_ERROR_NONE; } /* ================================================================================== ===================================================================================== ESPB DBLK ===================================================================================== ================================================================================== */ /*********************************************************************************** * MTF_WriteESPBDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_WriteESPBDblk( MTF_DBLK_HDR_INFO *psHdrInfo, BYTE *pBuffer, size_t nBufferSize, size_t *pnSizeUsed) { UINT16 uOffsetToFirstStream; // // Figure the size of the entire DBLK & make sure we have room // uOffsetToFirstStream = sizeof(MTF_DBLK_HDR) + MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo); uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4); if (nBufferSize < uOffsetToFirstStream) { if (pnSizeUsed) { *pnSizeUsed = uOffsetToFirstStream; } return MTF_ERROR_BUFFER_TOO_SMALL; } memset(pBuffer, 0, uOffsetToFirstStream); MTF_WriteDblkHdrToBuffer( MTF_ID_ESPB, uOffsetToFirstStream, psHdrInfo, pBuffer, 0); if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; return MTF_ERROR_NONE; } /*********************************************************************************** * MTF_ReadESPBDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_ReadESPBDblk( MTF_DBLK_HDR_INFO *psHdrInfo, BYTE *pBuffer) { MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer); return MTF_ERROR_NONE; } /* ================================================================================== ===================================================================================== End of Set DBLK (ESET) ===================================================================================== ================================================================================== */ /*********************************************************************************** * MTF_SetESETDefaults() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetESETDefaults(MTF_DBLK_ESET_INFO *pESETInfo) { time_t tTime; time(&tTime); pESETInfo->uESETAttributes = 0; pESETInfo->uNumberOfCorrupFiles = 0; pESETInfo->uSetMapPBA = 0; pESETInfo->uFileDetailPBA = 0; pESETInfo->uFDDTapeSequenceNumber = 0; pESETInfo->uDataSetNumber = 0; pESETInfo->sMediaWriteDate = MTF_CreateDateTimeFromTM(gmtime(&tTime)); } /*********************************************************************************** * MTF_WriteESETDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_WriteESETDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_ESET_INFO *psESETInfo, BYTE *pBuffer, size_t nBufferSize, size_t *pnSizeUsed) { UINT16 uOffsetToFirstStream; // // Figure the size of the entire DBLK & make sure we have room // uOffsetToFirstStream = sizeof(MTF_DBLK_ESET) + sizeof(MTF_DBLK_HDR) + MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo); uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4); if (nBufferSize < uOffsetToFirstStream) { if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; return MTF_ERROR_BUFFER_TOO_SMALL; } memset(pBuffer, 0, uOffsetToFirstStream); { MTF_DBLK_ESET_INFO *psESET = 0; size_t uCurrentStorageOffset = 0; uCurrentStorageOffset = sizeof(MTF_DBLK_ESET) + sizeof(MTF_DBLK_HDR); MTF_WriteDblkHdrToBuffer( MTF_ID_ESET, uOffsetToFirstStream, psHdrInfo, pBuffer, &uCurrentStorageOffset); psESET = (MTF_DBLK_ESET_INFO *) (pBuffer + sizeof(MTF_DBLK_HDR)); *psESET = *psESETInfo; if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; } return MTF_ERROR_NONE; } /*********************************************************************************** * MTF_ReadESETDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_ReadESETDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_ESET_INFO *psESETInfo, BYTE *pBuffer) { MTF_DBLK_ESET *psESET = 0; ClearStrings(); MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer); psESET = (MTF_DBLK_ESET_INFO *) (pBuffer + sizeof(MTF_DBLK_HDR)); *psESETInfo = *psESET; return MTF_ERROR_NONE; } /* ================================================================================== ===================================================================================== End of Set DBLK (EOTM) ===================================================================================== ================================================================================== */ /*********************************************************************************** * MTF_SetEOTMDefaults() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetEOTMDefaults(MTF_DBLK_EOTM_INFO *pEOTMInfo) { pEOTMInfo->uLastESETPBA = 0; } /*********************************************************************************** * MTF_WriteEOTMDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_WriteEOTMDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_EOTM_INFO *psEOTMInfo, BYTE *pBuffer, size_t nBufferSize, size_t *pnSizeUsed) { UINT16 uOffsetToFirstStream; // // Figure the size of the entire DBLK & make sure we have room // uOffsetToFirstStream = sizeof(MTF_DBLK_EOTM_INFO) + sizeof(MTF_DBLK_HDR) + MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo); uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4); if (nBufferSize < uOffsetToFirstStream) { if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; return MTF_ERROR_BUFFER_TOO_SMALL; } memset(pBuffer, 0, uOffsetToFirstStream); { MTF_DBLK_EOTM_INFO *psEOTM = 0; size_t uCurrentStorageOffset = 0; uCurrentStorageOffset = sizeof(MTF_DBLK_HDR) + sizeof(MTF_DBLK_EOTM); MTF_WriteDblkHdrToBuffer( MTF_ID_EOTM, uOffsetToFirstStream, psHdrInfo, pBuffer, &uCurrentStorageOffset); psEOTM = (MTF_DBLK_EOTM_INFO *) (pBuffer + sizeof(MTF_DBLK_HDR)); *psEOTM = *psEOTMInfo; if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; } return MTF_ERROR_NONE; } /*********************************************************************************** * MTF_ReadEOTMDblk() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_ReadEOTMDblk( MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_EOTM_INFO *psEOTMInfo, BYTE *pBuffer) { MTF_DBLK_EOTM *psEOTM = 0; ClearStrings(); MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer); psEOTM = (MTF_DBLK_EOTM_INFO *) (pBuffer + sizeof(MTF_DBLK_HDR)); *psEOTMInfo = *psEOTM; return MTF_ERROR_NONE; } /* ================================================================================== ===================================================================================== Soft Filemark (SFMB) ===================================================================================== ================================================================================== */ /*********************************************************************************** * MTF_CreateSFMB() - (bmd) * ** MTF API FUNCTION ** ***********************************************************************************/ size_t MTF_GetMaxSoftFilemarkEntries(size_t nBlockSize) { size_t n; if (0 == nBlockSize || nBlockSize % 512) { return 0; } // The SFMB fills the entire block. // Calculate the total number of entries that fit within a block // such that MTF_DBLK_HDR + MTF_DBLK_SFMB + (n-1 elements) < nBlockSize n = (nBlockSize - sizeof(MTF_DBLK_HDR) - sizeof(MTF_DBLK_SFMB) + sizeof(UINT32))/sizeof(UINT32); return n; } /*********************************************************************************** * MTF_InsertSoftFilemark() - (bmd) * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_InsertSoftFilemark(MTF_DBLK_SFMB_INFO *psSoftInfo, UINT32 pba) { size_t n; size_t bytesToShift; // We insert a filemark entry by shifting all the entries down. The one closest BOM // eventually drop out of the array. if (psSoftInfo) { n = psSoftInfo->uNumberOfFilemarkEntries; bytesToShift = psSoftInfo->uFilemarkEntriesUsed * sizeof(UINT32); // So we don't overwrite memory. bytesToShift -= (psSoftInfo->uFilemarkEntriesUsed < psSoftInfo->uNumberOfFilemarkEntries) ? 0 : sizeof(UINT32); memmove(&psSoftInfo->uFilemarkArray[1], &psSoftInfo->uFilemarkArray[0], bytesToShift); psSoftInfo->uFilemarkArray[0] = pba; if (psSoftInfo->uFilemarkEntriesUsed < psSoftInfo->uNumberOfFilemarkEntries) { psSoftInfo->uFilemarkEntriesUsed++; } } } /*********************************************************************************** * MTF_WriteSFMBDblk() - (bmd) * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_WriteSFMBDblk(MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_SFMB_INFO *psSoftInfo, BYTE *pBuffer, size_t nBufferSize, size_t *pnSizeUsed) { UINT16 uOffsetToFirstStream; size_t sizeOfSFMB; if (NULL == psHdrInfo || NULL == psSoftInfo || NULL == pBuffer || NULL == pnSizeUsed || 0 == nBufferSize) { return ERROR_INVALID_PARAMETER; } // Code assumes sizeof(MTF_DBLK_SFMB_INFO) == sizeof(MTF_DBLK_SFMB) if (sizeof(MTF_DBLK_SFMB_INFO) != sizeof(MTF_DBLK_SFMB)) { return ERROR_INVALID_FUNCTION; } // // Figure the size of the entire DBLK & make sure we have room // sizeOfSFMB = sizeof(MTF_DBLK_SFMB) + (psSoftInfo->uNumberOfFilemarkEntries-1)*sizeof(UINT32); uOffsetToFirstStream = sizeOfSFMB + sizeof(MTF_DBLK_HDR) + MTF_DBLK_HDR_INFO_CalcAddDataSize(psHdrInfo); uOffsetToFirstStream = (UINT16)Align(uOffsetToFirstStream, 4); if (nBufferSize < uOffsetToFirstStream) { if (pnSizeUsed) *pnSizeUsed = uOffsetToFirstStream; return MTF_ERROR_BUFFER_TOO_SMALL; } memset(pBuffer, 0, uOffsetToFirstStream); { MTF_DBLK_SFMB_INFO *psSFMB = 0; size_t uCurrentStorageOffset = 0; uCurrentStorageOffset = sizeof(MTF_DBLK_HDR) + sizeOfSFMB; MTF_WriteDblkHdrToBuffer( MTF_ID_SFMB, uOffsetToFirstStream, psHdrInfo, pBuffer, &uCurrentStorageOffset); psSFMB = (MTF_DBLK_SFMB *) (pBuffer + sizeof(MTF_DBLK_HDR)); // Need a deep copy since MTF_DBLK_SFMB_INFO holds a placeholder for the array. memcpy(psSFMB, psSoftInfo, sizeOfSFMB); if (pnSizeUsed) { *pnSizeUsed = uOffsetToFirstStream; } } return MTF_ERROR_NONE; } /*********************************************************************************** * MTF_ReadSFMBDblk() - (bmd) * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_ReadSFMBDblk(MTF_DBLK_HDR_INFO *psHdrInfo, MTF_DBLK_SFMB_INFO *psSoftInfo, BYTE *pBuffer) { MTF_DBLK_SFMB *psSFMB = 0; size_t sizeOfSFMB; if (NULL == psHdrInfo || NULL == psSoftInfo || NULL == pBuffer) { return ERROR_INVALID_PARAMETER; } // Code assumes sizeof(MTF_DBLK_SFMB_INFO) == sizeof(MTF_DBLK_SFMB) if (sizeof(MTF_DBLK_SFMB_INFO) != sizeof(MTF_DBLK_SFMB)) { return ERROR_INVALID_FUNCTION; } ClearStrings(); MTF_DBLK_HDR_INFO_ReadFromBuffer(psHdrInfo, pBuffer); psSFMB = (MTF_DBLK_SFMB *) (pBuffer + sizeof(MTF_DBLK_HDR)); // Need a deep copy since MTF_DBLK_SFMB_INFO holds a placeholder for the array. sizeOfSFMB = sizeof(MTF_DBLK_SFMB) + (psSFMB->uNumberOfFilemarkEntries-1)*sizeof(UINT32); memcpy(psSoftInfo, psSFMB, sizeOfSFMB); return MTF_ERROR_NONE; } /* ================================================================================== ===================================================================================== STREAM HEADER ===================================================================================== ================================================================================== */ /*********************************************************************************** * MTF_SetSTREAMDefaults() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetSTREAMDefaults(MTF_STREAM_INFO *pSTREAMInfo, char *szId) { memcpy(pSTREAMInfo->acStreamId, szId, 4); pSTREAMInfo->uStreamFileSystemAttributes = 0; pSTREAMInfo->uStreamTapeFormatAttributes = 0; pSTREAMInfo->uStreamLength = 0; pSTREAMInfo->uDataEncryptionAlgorithm = 0; pSTREAMInfo->uDataCompressionAlgorithm = 0; pSTREAMInfo->uCheckSum = 0; } /*********************************************************************************** * MTF_SetSTREAMFromStreamId() * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetSTREAMFromStreamId( MTF_STREAM_INFO *pSTREAMInfo, WIN32_STREAM_ID *pStreamId, size_t nIDHeaderSize ) { // From Steve DeVos, Seagate: // > BACKUP_INVALID and BACKUP_LINK will never be returned from BackupRead. // > // > -Steve // // TODO: MTF_NT_ENCRYPTED_STREAM "NTED"; These retrieved by NT Encyption APIs // TODO: MTF_NT_QUOTA_STREAM "NTQU"; These retrieved by NT Quota APIs MTF_SetSTREAMDefaults(pSTREAMInfo, "UNKN"); if (pStreamId->dwStreamId == BACKUP_DATA) memcpy(pSTREAMInfo->acStreamId, "STAN", 4); else if (pStreamId->dwStreamId == BACKUP_EA_DATA) memcpy(pSTREAMInfo->acStreamId, "NTEA", 4); else if (pStreamId->dwStreamId == BACKUP_SECURITY_DATA) memcpy(pSTREAMInfo->acStreamId, "NACL", 4); else if (pStreamId->dwStreamId == BACKUP_ALTERNATE_DATA) memcpy(pSTREAMInfo->acStreamId, "ADAT", 4); else if (pStreamId->dwStreamId == BACKUP_OBJECT_ID) memcpy(pSTREAMInfo->acStreamId, "NTOI", 4); else if (pStreamId->dwStreamId == BACKUP_REPARSE_DATA) memcpy(pSTREAMInfo->acStreamId, "NTRP", 4); else if (pStreamId->dwStreamId == BACKUP_SPARSE_BLOCK) memcpy(pSTREAMInfo->acStreamId, "SPAR", 4); else { pSTREAMInfo->uStreamFileSystemAttributes |= MTF_STREAM_IS_NON_PORTABLE; } if (pStreamId->dwStreamAttributes & STREAM_MODIFIED_WHEN_READ) pSTREAMInfo->uStreamFileSystemAttributes |= MTF_STREAM_MODIFIED_BY_READ; if (pStreamId->dwStreamAttributes & STREAM_CONTAINS_SECURITY) pSTREAMInfo->uStreamFileSystemAttributes |= MTF_STREAM_CONTAINS_SECURITY; if (pStreamId->dwStreamAttributes & STREAM_SPARSE_ATTRIBUTE) pSTREAMInfo->uStreamFileSystemAttributes |= MTF_STREAM_IS_SPARSE; pSTREAMInfo->uStreamTapeFormatAttributes = 0; pSTREAMInfo->uStreamLength = MTF_CreateUINT64(pStreamId->Size.LowPart, pStreamId->Size.HighPart) + nIDHeaderSize; pSTREAMInfo->uDataEncryptionAlgorithm = 0; pSTREAMInfo->uDataCompressionAlgorithm = 0; pSTREAMInfo->uCheckSum = 0; } /*********************************************************************************** * MTF_SetStreamIdFromSTREAM() - (bmd) * ** MTF API FUNCTION ** ***********************************************************************************/ void MTF_SetStreamIdFromSTREAM( WIN32_STREAM_ID *pStreamId, MTF_STREAM_INFO *pSTREAMInfo, size_t nIDHeaderSize ) { memset( pStreamId, 0, sizeof( WIN32_STREAM_ID ) ); if (0 == memcmp(pSTREAMInfo->acStreamId, "STAN", 4)) pStreamId->dwStreamId = BACKUP_DATA; else if (0 == memcmp(pSTREAMInfo->acStreamId, "NTEA", 4)) pStreamId->dwStreamId = BACKUP_EA_DATA; else if (0 == memcmp(pSTREAMInfo->acStreamId, "NACL", 4)) pStreamId->dwStreamId = BACKUP_SECURITY_DATA; else if (0 == memcmp(pSTREAMInfo->acStreamId, "ADAT", 4)) pStreamId->dwStreamId = BACKUP_ALTERNATE_DATA; else if (0 == memcmp(pSTREAMInfo->acStreamId, "NTOI", 4)) pStreamId->dwStreamId = BACKUP_OBJECT_ID; else if (0 == memcmp(pSTREAMInfo->acStreamId, "NTRP", 4)) pStreamId->dwStreamId = BACKUP_REPARSE_DATA; else if (0 == memcmp(pSTREAMInfo->acStreamId, "SPAR", 4)) pStreamId->dwStreamId = BACKUP_SPARSE_BLOCK; else { pStreamId->dwStreamId = BACKUP_INVALID; } pStreamId->dwStreamAttributes = STREAM_NORMAL_ATTRIBUTE; if (pSTREAMInfo->uStreamFileSystemAttributes & MTF_STREAM_MODIFIED_BY_READ) pStreamId->dwStreamAttributes |= STREAM_MODIFIED_WHEN_READ; if (pSTREAMInfo->uStreamFileSystemAttributes & MTF_STREAM_CONTAINS_SECURITY) pStreamId->dwStreamAttributes |= STREAM_CONTAINS_SECURITY; if (pSTREAMInfo->uStreamFileSystemAttributes & MTF_STREAM_IS_SPARSE) pStreamId->dwStreamAttributes |= STREAM_SPARSE_ATTRIBUTE; // TODO: Handle named data streams (size of name and in MTF stream) // ? How do I know ? pStreamId->Size.LowPart = (DWORD)((pSTREAMInfo->uStreamLength << 32) >>32); pStreamId->Size.HighPart = (DWORD)(pSTREAMInfo->uStreamLength >> 32); } /*********************************************************************************** * MTF_WriteStreamHeader() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_WriteStreamHeader(MTF_STREAM_INFO *psStreamInfo, BYTE *pBuffer, size_t nBufferSize, size_t *pnSizeUsed) { psStreamInfo->uCheckSum = CalcChecksum((BYTE *) psStreamInfo, sizeof(MTF_STREAM_INFO) / sizeof(UINT16) - 1); if (nBufferSize < sizeof(MTF_STREAM_INFO)) { if (pnSizeUsed) *pnSizeUsed = sizeof(MTF_STREAM_INFO); return MTF_ERROR_BUFFER_TOO_SMALL; } memset(pBuffer, 0, sizeof(MTF_STREAM_INFO)); *((MTF_STREAM_INFO *) pBuffer) = *psStreamInfo; if (pnSizeUsed) *pnSizeUsed = sizeof(MTF_STREAM_INFO); return MTF_ERROR_NONE; } /*********************************************************************************** * MTF_WriteNameStream() - (bmd) * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_WriteNameStream( char *szType, wchar_t *szName, BYTE *pBuffer, size_t nBufferSize, size_t *pnSizeUsed) { MTF_STREAM_INFO sStream; UINT16 uOffsetToCSUMStream; UINT16 uOffsetToNextStream; size_t nBufUsed; UINT16 nameSize; UINT32 nameChecksum; // // Figure the size of the entire Name stream including trailing CSUM and make sure we have room. // nameSize = (UINT16)wstrsize(szName); // including terminating '\0' uOffsetToCSUMStream = sizeof(MTF_STREAM_INFO) + nameSize; uOffsetToCSUMStream = (UINT16)Align(uOffsetToCSUMStream, 4); uOffsetToNextStream = uOffsetToCSUMStream; uOffsetToNextStream += sizeof(MTF_STREAM_INFO) + 4; // includes 4 byte CSUM data uOffsetToNextStream = (UINT16)Align(uOffsetToNextStream, 4); if (nBufferSize < uOffsetToNextStream) { return MTF_ERROR_BUFFER_TOO_SMALL; } memset(pBuffer, 0, uOffsetToNextStream); MTF_SetSTREAMDefaults(&sStream, szType); sStream.uStreamLength = nameSize; sStream.uStreamTapeFormatAttributes |= MTF_STREAM_CHECKSUMED; MTF_WriteStreamHeader(&sStream, pBuffer, nBufferSize, &nBufUsed); memcpy(pBuffer + nBufUsed, szName, nameSize); if ( 0 == memcmp(sStream.acStreamId, "PNAM", 4) ) { // // here, we need to turn the slashes (L'\\') to zeros (L'\0')in the directory name string... // int i, iLen; wchar_t *szDirectoryName = (wchar_t *) (pBuffer + nBufUsed); iLen = wstrsize(szDirectoryName); for (i = 0; i < iLen; ++i) if (szDirectoryName[i] == L'\\') szDirectoryName[i] = L'\0'; } // For Name streams, we always tack on a CSUM nameChecksum = CalcChecksumOfStreamData(pBuffer + nBufUsed, nameSize / sizeof(UINT32) + 1); MTF_SetSTREAMDefaults(&sStream, MTF_CHECKSUM_STREAM); sStream.uStreamLength = sizeof(nameChecksum); MTF_WriteStreamHeader(&sStream, pBuffer + uOffsetToCSUMStream, nBufferSize, &nBufUsed); memcpy(pBuffer + uOffsetToCSUMStream + nBufUsed, &nameChecksum, sizeof(nameChecksum)); if (pnSizeUsed) *pnSizeUsed = uOffsetToNextStream; return MTF_ERROR_NONE; } /*********************************************************************************** * MTF_ReadStreamHeader() * ** MTF API FUNCTION ** ***********************************************************************************/ DWORD MTF_ReadStreamHeader(MTF_STREAM_INFO *psStreamInfo, BYTE *pBuffer) { *psStreamInfo = *((MTF_STREAM_INFO *) pBuffer); return MTF_ERROR_NONE; }