2550 lines
95 KiB
C++
2550 lines
95 KiB
C++
//____________________________________________________________________________
|
|
//
|
|
// (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 <assert.h>
|
|
#include <time.h>
|
|
#include <string.h>
|
|
#include <wchar.h>
|
|
#include <stralign.h>
|
|
|
|
#include "stdafx.h"
|
|
#include "mtfapi.h"
|
|
|
|
static USHORT iCountMTFa = 0; // Count of existing objects
|
|
//
|
|
// Constructor
|
|
//
|
|
CMTFApi::CMTFApi(void)
|
|
{
|
|
m_uAlignmentFactor = 0;
|
|
|
|
m_iNumStrings = 0;
|
|
for (int i = 0; i < iNUMSTRINGS; ++i){
|
|
m_aszStrings[i] = 0;
|
|
}
|
|
|
|
iCountMTFa++;
|
|
}
|
|
|
|
//
|
|
// Destructor
|
|
//
|
|
CMTFApi::~CMTFApi()
|
|
{
|
|
ClearStrings();
|
|
|
|
iCountMTFa--;
|
|
}
|
|
|
|
|
|
/* ==================================================================================
|
|
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...
|
|
================================================================================= */
|
|
|
|
// - returns the size of a wchar_t string
|
|
// and returns zero for a null pointer
|
|
size_t CMTFApi::wstrsize(wchar_t *s)
|
|
{
|
|
if (s)
|
|
return wcslen(s) * sizeof(wchar_t);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
// - returns the size of a wchar_t unaligned string
|
|
// and returns zero for a null pointer
|
|
size_t CMTFApi::ua_wstrsize(wchar_t UNALIGNED *s)
|
|
{
|
|
if (s)
|
|
return ua_wcslen(s) * sizeof(wchar_t);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|
|
// - frees all allocated pointers in m_aszStrings and sets
|
|
// m_iNumStrings to zero
|
|
void CMTFApi::ClearStrings()
|
|
{
|
|
int i;
|
|
for (i = 0; i < iNUMSTRINGS; ++i)
|
|
{
|
|
if (m_aszStrings[i])
|
|
free(m_aszStrings[i]);
|
|
m_aszStrings[i] = 0;
|
|
}
|
|
|
|
m_iNumStrings = 0;
|
|
}
|
|
|
|
|
|
// - allocates a string in m_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!!!!!
|
|
wchar_t * CMTFApi::MakeString(wchar_t UNALIGNED * pString, size_t iSize)
|
|
{
|
|
size_t i;
|
|
if (m_iNumStrings >= iNUMSTRINGS) {
|
|
return NULL;
|
|
}
|
|
m_aszStrings[m_iNumStrings] = (wchar_t *)malloc(iSize + sizeof(wchar_t));
|
|
if (!m_aszStrings[m_iNumStrings])
|
|
return NULL;
|
|
|
|
for (i = 0; i < iSize / sizeof(wchar_t); ++i)
|
|
m_aszStrings[m_iNumStrings][i] = pString[i];
|
|
|
|
m_aszStrings[m_iNumStrings][i] = L'\0';
|
|
|
|
return m_aszStrings[m_iNumStrings++];
|
|
}
|
|
|
|
|
|
/* ==================================================================================
|
|
Other data structures
|
|
================================================================================= */
|
|
|
|
#pragma pack(1)
|
|
|
|
/***********************************************************************************
|
|
************************************************************************************
|
|
************************************************************************************
|
|
**** MTF On Tape Structures
|
|
************************************************************************************
|
|
************************************************************************************
|
|
***********************************************************************************/
|
|
|
|
/* ==================================================================================
|
|
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 CMTFApi::MTF_SetAlignmentFactor(UINT16 uAF)
|
|
{
|
|
// store the user's alignment factor in a private member
|
|
m_uAlignmentFactor = uAF;
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************
|
|
* MTF_GetAlignmentFactor()
|
|
* ** MTF API FUNCTION **
|
|
***********************************************************************************/
|
|
UINT16 CMTFApi::MTF_GetAlignmentFactor()
|
|
{
|
|
return m_uAlignmentFactor;
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************
|
|
* MTF_PadToNextAlignmentFactor()
|
|
* ** MTF API FUNCTION **
|
|
***********************************************************************************/
|
|
DWORD CMTFApi::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 CMTFApi::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 CMTFApi::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 CMTFApi::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 = (UINT16)iYear << 2 ;
|
|
sDateTime.dt_field[0] = ((UINT8 *)&temp)[1] ;
|
|
sDateTime.dt_field[1] = ((UINT8 *)&temp)[0] ;
|
|
|
|
temp = (UINT16)iMonth << 6 ;
|
|
sDateTime.dt_field[1] |= ((UINT8 *)&temp)[1] ;
|
|
sDateTime.dt_field[2] = ((UINT8 *)&temp)[0] ;
|
|
|
|
temp = (UINT16)iDay << 1 ;
|
|
sDateTime.dt_field[2] |= ((UINT8 *)&temp)[0] ;
|
|
|
|
temp = (UINT16)iHour << 4 ;
|
|
sDateTime.dt_field[2] |= ((UINT8 *)&temp)[1] ;
|
|
sDateTime.dt_field[3] = ((UINT8 *)&temp)[0] ;
|
|
|
|
temp = (UINT16)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 CMTFApi::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 CMTFApi::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 CMTFApi::MTF_CreateDateNull()
|
|
{
|
|
MTF_DATE_TIME sDateTime = {0};
|
|
|
|
return sDateTime;
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************
|
|
* MTF_CreateDateTimeFromFileTime()
|
|
* ** MTF API FUNCTION **
|
|
***********************************************************************************/
|
|
MTF_DATE_TIME CMTFApi::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 internal 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.
|
|
***********************************************************************************/
|
|
size_t CMTFApi::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!
|
|
***********************************************************************************/
|
|
size_t CMTFApi::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
|
|
*
|
|
***********************************************************************************/
|
|
UINT16 CMTFApi::CalcChecksum(
|
|
BYTE * pStartPtr,
|
|
int nNum )
|
|
{
|
|
UINT16 resultSoFar = 0;
|
|
UINT16 UNALIGNED *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
|
|
*
|
|
***********************************************************************************/
|
|
UINT32 CMTFApi::CalcChecksumOfStreamData(
|
|
BYTE * pStartPtr,
|
|
int nNum )
|
|
{
|
|
UINT32 resultSoFar = 0;
|
|
UINT32 UNALIGNED *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
|
|
size_t CMTFApi::MTF_DBLK_HDR_INFO_CalcAddDataSize(
|
|
MTF_DBLK_HDR_INFO *pSTDInfo
|
|
)
|
|
{
|
|
return pSTDInfo->uOSDataSize;
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************
|
|
* MTF_SetDblkHdrDefaults()
|
|
* ** MTF API FUNCTION **
|
|
***********************************************************************************/
|
|
void CMTFApi::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
|
|
*
|
|
***********************************************************************************/
|
|
void CMTFApi::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 = 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 CMTFApi::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 **
|
|
size_t CMTFApi::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 CMTFApi::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 CMTFApi::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 = (UINT16) (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(
|
|
(UINT8 *)(char *)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 CMTFApi::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 UNALIGNED *) (pBuffer + pTape->sTapeName.uOffset), pTape->sTapeName.uSize);
|
|
psTapeInfo->szTapeDescription = MakeString((wchar_t UNALIGNED *) (pBuffer + pTape->sTapeDescription.uOffset), pTape->sTapeDescription.uSize);
|
|
psTapeInfo->szTapePassword = MakeString((wchar_t UNALIGNED *) (pBuffer + pTape->sTapePassword.uOffset), pTape->sTapePassword.uSize);
|
|
psTapeInfo->szSoftwareName = MakeString((wchar_t UNALIGNED *) (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 **
|
|
size_t CMTFApi::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 CMTFApi::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 CMTFApi::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 = (UINT16) (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(
|
|
(UINT8 *)(char *)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 CMTFApi::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 UNALIGNED *) (pBuffer + psSSET->sDataSetName.uOffset), psSSET->sDataSetName.uSize);
|
|
psSSETInfo->szDataSetDescription = MakeString((wchar_t UNALIGNED *) (pBuffer + psSSET->sDataSetDescription.uOffset), psSSET->sDataSetDescription.uSize);
|
|
psSSETInfo->szDataSetPassword = MakeString((wchar_t UNALIGNED *) (pBuffer + psSSET->sDataSetPassword.uOffset), psSSET->sDataSetPassword.uSize);
|
|
psSSETInfo->szUserName = MakeString((wchar_t UNALIGNED *) (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 **
|
|
size_t CMTFApi::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 CMTFApi::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 CMTFApi::MTF_SetVOLBForDevice(MTF_DBLK_VOLB_INFO *pVOLBInfo, wchar_t *szDevice)
|
|
{
|
|
DWORD dwBufSize = MAX_COMPUTERNAME_LENGTH + 1;
|
|
wchar_t tempDeviceName[MTF_STRLEN+4];
|
|
|
|
wcscpy(m_szDeviceName, szDevice);
|
|
MTF_SetVOLBDefaults(pVOLBInfo); // initialize
|
|
|
|
// Determine the format and set the appropriate bit in the VOLB attributes.
|
|
if (*(m_szDeviceName+1) == L':') {
|
|
// drive letter w/colon format
|
|
pVOLBInfo->uVolumeAttributes |= MTF_VOLB_DEV_DRIVE;
|
|
}
|
|
else if (0 == wcsncmp( m_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, m_szDeviceName);
|
|
|
|
GetVolumeInformationW(tempDeviceName, m_szVolumeName, MTF_STRLEN, 0, 0, 0, 0, 0);
|
|
GetComputerNameW(m_szMachineName, &dwBufSize);
|
|
|
|
pVOLBInfo->szDeviceName = m_szDeviceName;
|
|
pVOLBInfo->szVolumeName = m_szVolumeName;
|
|
pVOLBInfo->szMachineName = m_szMachineName;
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************
|
|
* MTF_WriteVOLBDblk()
|
|
* ** MTF API FUNCTION **
|
|
***********************************************************************************/
|
|
DWORD CMTFApi::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 = (UINT16) (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(
|
|
(UINT8 *)(char *)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 CMTFApi::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 UNALIGNED *) (pBuffer + psVOLB->sDeviceName.uOffset), psVOLB->sDeviceName.uSize);
|
|
psVOLBInfo->szVolumeName = MakeString((wchar_t UNALIGNED *) (pBuffer + psVOLB->sVolumeName.uOffset), psVOLB->sVolumeName.uSize);
|
|
psVOLBInfo->szMachineName = MakeString((wchar_t UNALIGNED *) (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 **
|
|
size_t CMTFApi::MTF_DBLK_DIRB_INFO_CalcAddDataSize(MTF_DBLK_DIRB_INFO *pDIRBInfo)
|
|
{
|
|
return wstrsize(pDIRBInfo->szDirectoryName);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************
|
|
* MTF_SetDIRBDefaults()
|
|
* ** MTF API FUNCTION **
|
|
***********************************************************************************/
|
|
void CMTFApi::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 CMTFApi::MTF_SetDIRBFromFindData(
|
|
MTF_DBLK_DIRB_INFO *pDIRBInfo,
|
|
wchar_t *szDirectoryName,
|
|
WIN32_FIND_DATAW *pFindData
|
|
)
|
|
{
|
|
MTF_SetDIRBDefaults(pDIRBInfo); // initialize
|
|
|
|
if ( wcslen( szDirectoryName ) < MTF_STRLEN ) {
|
|
wcscpy(m_szDirectoryName, szDirectoryName);
|
|
pDIRBInfo->szDirectoryName = m_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 CMTFApi::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 = (UINT16) (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(
|
|
(UINT8 *)(char *)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 UNALIGNED *szDirectoryName = (wchar_t UNALIGNED *) (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 CMTFApi::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 **
|
|
size_t CMTFApi::MTF_DBLK_FILE_INFO_CalcAddDataSize(MTF_DBLK_FILE_INFO *pFILEInfo)
|
|
{
|
|
return wstrsize(pFILEInfo->szFileName);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************
|
|
* MTF_SetFILEDefaults()
|
|
* ** MTF API FUNCTION **
|
|
***********************************************************************************/
|
|
void CMTFApi::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 CMTFApi::MTF_SetFILEFromFindData(MTF_DBLK_FILE_INFO *pFILEInfo, WIN32_FIND_DATAW *pFindData)
|
|
{
|
|
time_t tTime;
|
|
time(&tTime);
|
|
|
|
MTF_SetFILEDefaults(pFILEInfo); // initialize
|
|
|
|
wcscpy(m_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 = m_szFileName;
|
|
|
|
pFILEInfo->uDisplaySize = MTF_CreateUINT64(pFindData->nFileSizeLow, pFindData->nFileSizeHigh);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************
|
|
* MTF_WriteFILEDblk()
|
|
* ** MTF API FUNCTION **
|
|
***********************************************************************************/
|
|
DWORD CMTFApi::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 = (UINT16) (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(
|
|
(UINT8 *)(char *)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 CMTFApi::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 UNALIGNED *) (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 CMTFApi::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 CMTFApi::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 = (UINT16) (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(
|
|
(UINT8 *)(char *)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 CMTFApi::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 CMTFApi::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 = (UINT16) (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(
|
|
(UINT8 *)(char *)MTF_ID_ESPB,
|
|
uOffsetToFirstStream,
|
|
psHdrInfo,
|
|
pBuffer,
|
|
0);
|
|
|
|
if (pnSizeUsed)
|
|
*pnSizeUsed = uOffsetToFirstStream;
|
|
|
|
return MTF_ERROR_NONE;
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************
|
|
* MTF_ReadESPBDblk()
|
|
* ** MTF API FUNCTION **
|
|
***********************************************************************************/
|
|
DWORD CMTFApi::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 CMTFApi::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 CMTFApi::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 = (UINT16) (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(
|
|
(UINT8 *)(char *)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 CMTFApi::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 CMTFApi::MTF_SetEOTMDefaults(MTF_DBLK_EOTM_INFO *pEOTMInfo)
|
|
{
|
|
pEOTMInfo->uLastESETPBA = 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************
|
|
* MTF_WriteEOTMDblk()
|
|
* ** MTF API FUNCTION **
|
|
***********************************************************************************/
|
|
DWORD CMTFApi::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 = (UINT16) (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(
|
|
(UINT8 *)(char *)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 CMTFApi::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 CMTFApi::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 CMTFApi::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 CMTFApi::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 = (UINT16) (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(
|
|
(UINT8 *)(char *)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 CMTFApi::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 CMTFApi::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 CMTFApi::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 CMTFApi::MTF_SetStreamIdFromSTREAM(
|
|
WIN32_STREAM_ID *pStreamId,
|
|
MTF_STREAM_INFO *pSTREAMInfo,
|
|
size_t nIDHeaderSize
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(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 CMTFApi::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 CMTFApi::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 UNALIGNED *szDirectoryName = (wchar_t UNALIGNED *) (pBuffer + nBufUsed);
|
|
|
|
iLen = ua_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 CMTFApi::MTF_ReadStreamHeader(MTF_STREAM_INFO *psStreamInfo,
|
|
BYTE *pBuffer)
|
|
|
|
{
|
|
*psStreamInfo = *((MTF_STREAM_INFO *) pBuffer);
|
|
return MTF_ERROR_NONE;
|
|
}
|
|
|
|
|
|
|
|
|