NT4/private/windows/rover/filesync/core/db.c
2020-09-30 17:12:29 +02:00

473 lines
9.5 KiB
C

/*
* db.c - Twin database module.
*/
/* Headers
**********/
#include "project.h"
#pragma hdrstop
#include "stub.h"
/* Constants
************/
/* database header magic id string */
#define MAGIC_HEADER "DDSH\x02\x05\x01\x14"
/* length of MAGIC_HEADER (no null terminator) */
#define MAGIC_HEADER_LEN (8)
/* Types
********/
typedef struct _dbheader
{
BYTE rgbyteMagic[MAGIC_HEADER_LEN];
DWORD dwcbHeaderLen;
DWORD dwMajorVer;
DWORD dwMinorVer;
}
DBHEADER;
DECLARE_STANDARD_TYPES(DBHEADER);
/***************************** Private Functions *****************************/
/* Module Prototypes
********************/
PRIVATE_CODE TWINRESULT WriteDBHeader(HCACHEDFILE, PDBHEADER);
PRIVATE_CODE TWINRESULT ReadDBHeader(HCACHEDFILE, PDBHEADER);
PRIVATE_CODE TWINRESULT CheckDBHeader(PCDBHEADER);
PRIVATE_CODE TWINRESULT WriteTwinInfo(HCACHEDFILE, HBRFCASE);
PRIVATE_CODE TWINRESULT ReadTwinInfo(HCACHEDFILE, HBRFCASE, PCDBVERSION);
#ifdef VSTF
PRIVATE_CODE BOOL IsValidPCDBHEADER(PCDBHEADER);
#endif
/*
** WriteDBHeader()
**
**
**
** Arguments:
**
** Returns: TWINRESULT
**
** Side Effects: none
*/
PRIVATE_CODE TWINRESULT WriteDBHeader(HCACHEDFILE hcf, PDBHEADER pdbh)
{
TWINRESULT tr;
ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
ASSERT(IS_VALID_STRUCT_PTR(pdbh, CDBHEADER));
if (WriteToCachedFile(hcf, (PCVOID)pdbh, sizeof(*pdbh), NULL))
tr = TR_SUCCESS;
else
tr = TR_BRIEFCASE_WRITE_FAILED;
return(tr);
}
/*
** ReadDBHeader()
**
**
**
** Arguments:
**
** Returns: TWINRESULT
**
** Side Effects: none
*/
PRIVATE_CODE TWINRESULT ReadDBHeader(HCACHEDFILE hcf, PDBHEADER pdbh)
{
TWINRESULT tr;
DWORD dwcbRead;
ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
ASSERT(IS_VALID_WRITE_PTR(pdbh, DBHEADER));
if (ReadFromCachedFile(hcf, pdbh, sizeof(*pdbh), &dwcbRead) &&
dwcbRead == sizeof(*pdbh))
tr = CheckDBHeader(pdbh);
else
tr = TR_CORRUPT_BRIEFCASE;
return(tr);
}
/*
** CheckDBHeader()
**
**
**
** Arguments:
**
** Returns: TWINRESULT
**
** Side Effects: none
*/
PRIVATE_CODE TWINRESULT CheckDBHeader(PCDBHEADER pcdbh)
{
TWINRESULT tr = TR_CORRUPT_BRIEFCASE;
ASSERT(IS_VALID_READ_PTR(pcdbh, CDBHEADER));
if (MyMemComp(pcdbh->rgbyteMagic, MAGIC_HEADER, MAGIC_HEADER_LEN) == CR_EQUAL)
{
/* Treat older databases as corrupt. Support M8 databases. */
if (pcdbh->dwMajorVer == HEADER_MAJOR_VER &&
(pcdbh->dwMinorVer == HEADER_MINOR_VER || pcdbh->dwMinorVer == HEADER_M8_MINOR_VER))
{
if (pcdbh->dwcbHeaderLen == sizeof(*pcdbh))
tr = TR_SUCCESS;
}
else if (pcdbh->dwMajorVer > HEADER_MAJOR_VER ||
(pcdbh->dwMajorVer == HEADER_MAJOR_VER &&
pcdbh->dwMinorVer > HEADER_MINOR_VER))
{
tr = TR_NEWER_BRIEFCASE;
WARNING_OUT((TEXT("CheckDBHeader(): Newer database version %lu.%lu."),
pcdbh->dwMajorVer,
pcdbh->dwMinorVer));
}
else
{
tr = TR_CORRUPT_BRIEFCASE;
WARNING_OUT((TEXT("CheckDBHeader(): Treating old database version %lu.%lu as corrupt. Current database version is %lu.%lu."),
pcdbh->dwMajorVer,
pcdbh->dwMinorVer,
(DWORD)HEADER_MAJOR_VER,
(DWORD)HEADER_MINOR_VER));
}
}
return(tr);
}
/*
** WriteTwinInfo()
**
**
**
** Arguments:
**
** Returns: TWINRESULT
**
** Side Effects: none
*/
PRIVATE_CODE TWINRESULT WriteTwinInfo(HCACHEDFILE hcf, HBRFCASE hbr)
{
TWINRESULT tr = TR_BRIEFCASE_WRITE_FAILED;
ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
ASSERT(IS_VALID_HANDLE(hbr, BRFCASE));
tr = WritePathList(hcf, GetBriefcasePathList(hbr));
if (tr == TR_SUCCESS)
{
tr = WriteBriefcaseInfo(hcf, hbr);
if (tr == TR_SUCCESS)
{
tr = WriteStringTable(hcf, GetBriefcaseNameStringTable(hbr));
if (tr == TR_SUCCESS)
{
tr = WriteTwinFamilies(hcf, GetBriefcaseTwinFamilyPtrArray(hbr));
if (tr == TR_SUCCESS)
tr = WriteFolderPairList(hcf, GetBriefcaseFolderPairPtrArray(hbr));
}
}
}
return(tr);
}
/*
** ReadTwinInfo()
**
**
**
** Arguments:
**
** Returns: TWINRESULT
**
** Side Effects: none
*/
PRIVATE_CODE TWINRESULT ReadTwinInfo(HCACHEDFILE hcf, HBRFCASE hbr,
PCDBVERSION pcdbver)
{
TWINRESULT tr;
HHANDLETRANS hhtPathTrans;
ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
ASSERT(IS_VALID_READ_PTR(pcdbver, DBVERSION));
ASSERT(IS_VALID_HANDLE(hbr, BRFCASE));
tr = ReadPathList(hcf, GetBriefcasePathList(hbr), &hhtPathTrans);
if (tr == TR_SUCCESS)
{
tr = ReadBriefcaseInfo(hcf, hbr, hhtPathTrans);
if (tr == TR_SUCCESS)
{
HHANDLETRANS hhtNameTrans;
tr = ReadStringTable(hcf, GetBriefcaseNameStringTable(hbr), &hhtNameTrans);
if (tr == TR_SUCCESS)
{
tr = ReadTwinFamilies(hcf, hbr, pcdbver, hhtPathTrans, hhtNameTrans);
if (tr == TR_SUCCESS)
tr = ReadFolderPairList(hcf, hbr, hhtPathTrans, hhtNameTrans);
DestroyHandleTranslator(hhtNameTrans);
}
}
DestroyHandleTranslator(hhtPathTrans);
}
return(tr);
}
#ifdef VSTF
/*
** IsValidPCDBHEADER()
**
**
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
PRIVATE_CODE BOOL IsValidPCDBHEADER(PCDBHEADER pcdbh)
{
BOOL bResult;
if (IS_VALID_READ_PTR(pcdbh, CDBHEADER) &&
EVAL(MyMemComp(pcdbh->rgbyteMagic, MAGIC_HEADER, MAGIC_HEADER_LEN) == CR_EQUAL) &&
EVAL(pcdbh->dwcbHeaderLen == sizeof(*pcdbh)) &&
EVAL(pcdbh->dwMajorVer == HEADER_MAJOR_VER) &&
EVAL(pcdbh->dwMinorVer == HEADER_MINOR_VER || pcdbh->dwMinorVer == HEADER_M8_MINOR_VER))
bResult = TRUE;
else
bResult = FALSE;
return(bResult);
}
#endif
/****************************** Public Functions *****************************/
/*
** WriteTwinDatabase()
**
**
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
PUBLIC_CODE TWINRESULT WriteTwinDatabase(HCACHEDFILE hcf, HBRFCASE hbr)
{
TWINRESULT tr;
ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
ASSERT(IS_VALID_HANDLE(hbr, BRFCASE));
if (! SeekInCachedFile(hcf, 0, FILE_BEGIN))
{
DBHEADER dbh;
/* Set up database header. */
CopyMemory(dbh.rgbyteMagic, MAGIC_HEADER, MAGIC_HEADER_LEN);
dbh.dwcbHeaderLen = sizeof(dbh);
dbh.dwMajorVer = HEADER_MAJOR_VER;
dbh.dwMinorVer = HEADER_MINOR_VER;
tr = WriteDBHeader(hcf, &dbh);
if (tr == TR_SUCCESS)
{
TRACE_OUT((TEXT("WriteTwinDatabase(): Wrote database header version %lu.%lu."),
dbh.dwMajorVer,
dbh.dwMinorVer));
tr = WriteTwinInfo(hcf, hbr);
if (tr == TR_SUCCESS && ! SetEndOfCachedFile(hcf))
tr = TR_BRIEFCASE_WRITE_FAILED;
}
}
else
tr = TR_BRIEFCASE_WRITE_FAILED;
return(tr);
}
/*
** ReadTwinDatabase()
**
**
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
PUBLIC_CODE TWINRESULT ReadTwinDatabase(HBRFCASE hbr, HCACHEDFILE hcf)
{
TWINRESULT tr;
ASSERT(IS_VALID_HANDLE(hbr, BRFCASE));
ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
if (! SeekInCachedFile(hcf, 0, FILE_BEGIN))
{
DBHEADER dbh;
tr = ReadDBHeader(hcf, &dbh);
if (tr == TR_SUCCESS)
{
TRACE_OUT((TEXT("ReadTwinDatabase(): Read database header version %lu.%lu."),
dbh.dwMajorVer,
dbh.dwMinorVer));
tr = ReadTwinInfo(hcf, hbr, (PCDBVERSION)&dbh.dwMajorVer);
if (tr == TR_SUCCESS)
ASSERT(GetCachedFilePointerPosition(hcf) == GetCachedFileSize(hcf));
}
}
else
tr = TR_BRIEFCASE_READ_FAILED;
return(tr);
}
/*
** WriteDBSegmentHeader()
**
**
**
** Arguments:
**
** Returns: TWINRESULT
**
** Side Effects: none
*/
PUBLIC_CODE TWINRESULT WriteDBSegmentHeader(HCACHEDFILE hcf,
LONG lcbDBSegmentHeaderOffset,
PCVOID pcvSegmentHeader,
UINT ucbSegmentHeaderLen)
{
TWINRESULT tr;
DWORD dwcbStartOffset;
ASSERT(IS_VALID_HANDLE(hcf, CACHEDFILE));
ASSERT(lcbDBSegmentHeaderOffset >= 0);
ASSERT(ucbSegmentHeaderLen > 0);
ASSERT(IS_VALID_READ_BUFFER_PTR(pcvSegmentHeader, BYTE, ucbSegmentHeaderLen));
dwcbStartOffset = GetCachedFilePointerPosition(hcf);
if (dwcbStartOffset != INVALID_SEEK_POSITION &&
SeekInCachedFile(hcf, lcbDBSegmentHeaderOffset, SEEK_SET) != INVALID_SEEK_POSITION &&
WriteToCachedFile(hcf, pcvSegmentHeader, ucbSegmentHeaderLen, NULL) &&
SeekInCachedFile(hcf, dwcbStartOffset, SEEK_SET) != INVALID_SEEK_POSITION)
tr = TR_SUCCESS;
else
tr = TR_BRIEFCASE_WRITE_FAILED;
return(tr);
}
/*
** TranslateFCRESULTToTWINRESULT()
**
**
**
** Arguments:
**
** Returns:
**
** Side Effects: none
*/
PUBLIC_CODE TWINRESULT TranslateFCRESULTToTWINRESULT(FCRESULT fcr)
{
TWINRESULT tr;
switch (fcr)
{
case FCR_SUCCESS:
tr = TR_SUCCESS;
break;
case FCR_OUT_OF_MEMORY:
tr = TR_OUT_OF_MEMORY;
break;
case FCR_OPEN_FAILED:
tr = TR_BRIEFCASE_OPEN_FAILED;
break;
case FCR_CREATE_FAILED:
tr = TR_BRIEFCASE_OPEN_FAILED;
break;
case FCR_WRITE_FAILED:
tr = TR_BRIEFCASE_WRITE_FAILED;
break;
default:
ASSERT(fcr == FCR_FILE_LOCKED);
tr = TR_BRIEFCASE_LOCKED;
break;
}
return(tr);
}