reactos/sdk/tools/cabman/CCFDATAStorage.cxx

230 lines
4.2 KiB
C++

/*
* PROJECT: ReactOS cabinet manager
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: CCFDATAStorage class implementation
* COPYRIGHT: Copyright 2017 Casper S. Hornstrup (chorns@users.sourceforge.net)
* Copyright 2017 Colin Finck <mail@colinfinck.de>
* Copyright 2018 Dmitry Bagdanov <dimbo_job@mail.ru>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#if !defined(_WIN32)
#include <dirent.h>
#endif
#include "CCFDATAStorage.h"
#include "raw.h"
#include "mszip.h"
#if !defined(CAB_READ_ONLY)
/**
* @name CCFDATAStorage class
* @implemented
*
* Default constructor
*/
CCFDATAStorage::CCFDATAStorage()
{
FileHandle = NULL;
}
/**
* @name CCFDATAStorage class
* @implemented
*
* Default destructor
*/
CCFDATAStorage::~CCFDATAStorage()
{
ASSERT(FileHandle == NULL);
}
/**
* @name CCFDATAStorage class
* @implemented
*
* Creates the file
*
* @return
* Status of operation
*/
ULONG CCFDATAStorage::Create()
{
#if defined(_WIN32)
char TmpName[PATH_MAX];
char *pName;
int length;
if (tmpnam(TmpName) == NULL)
return CAB_STATUS_CANNOT_CREATE;
/* Append 'tmp' if the file name ends with a dot */
length = strlen(TmpName);
if (length > 0 && TmpName[length - 1] == '.')
strcat(TmpName, "tmp");
/* Skip a leading slash or backslash */
pName = TmpName;
if (*pName == '/' || *pName == '\\')
pName++;
strcpy(FullName, pName);
FileHandle = fopen(FullName, "w+b");
if (FileHandle == NULL)
return CAB_STATUS_CANNOT_CREATE;
#else
if ((FileHandle = tmpfile()) == NULL)
return CAB_STATUS_CANNOT_CREATE;
#endif
return CAB_STATUS_SUCCESS;
}
/**
* @name CCFDATAStorage class
* @implemented
*
* Destroys the file
*
* @return
* Status of operation
*/
ULONG CCFDATAStorage::Destroy()
{
ASSERT(FileHandle != NULL);
fclose(FileHandle);
FileHandle = NULL;
#if defined(_WIN32)
remove(FullName);
#endif
return CAB_STATUS_SUCCESS;
}
/**
* @name CCFDATAStorage class
* @implemented
*
* Truncate the scratch file to zero bytes
*
* @return
* Status of operation
*/
ULONG CCFDATAStorage::Truncate()
{
fclose(FileHandle);
#if defined(_WIN32)
FileHandle = fopen(FullName, "w+b");
#else
FileHandle = tmpfile();
#endif
if (FileHandle == NULL)
{
DPRINT(MID_TRACE, ("ERROR '%i'.\n", errno));
return CAB_STATUS_FAILURE;
}
return CAB_STATUS_SUCCESS;
}
/**
* @name CCFDATAStorage class
* @implemented
*
* Returns current position in file
*
* @return
* Current position
*/
ULONG CCFDATAStorage::Position()
{
return (ULONG)ftell(FileHandle);
}
/**
* @name CCFDATAStorage class
* @implemented
*
* Seeks to an absolute position
*
* @param Position
* Absolute position to seek to
*
* @return
* Status of operation
*/
ULONG CCFDATAStorage::Seek(LONG Position)
{
if (fseek(FileHandle, (off_t)Position, SEEK_SET) != 0)
return CAB_STATUS_FAILURE;
else
return CAB_STATUS_SUCCESS;
}
/**
* @name CCFDATAStorage class
* @implemented
*
* Reads a CFDATA block from the file
*
* @param Data
* Pointer to CFDATA block for the buffer
*
* @param Buffer
* Pointer to buffer to store data read
*
* @param BytesRead
* Pointer to buffer to write number of bytes read
*
* @return
* Status of operation
*/
ULONG CCFDATAStorage::ReadBlock(PCFDATA Data, void* Buffer, PULONG BytesRead)
{
*BytesRead = fread(Buffer, 1, Data->CompSize, FileHandle);
if (*BytesRead != Data->CompSize)
return CAB_STATUS_CANNOT_READ;
return CAB_STATUS_SUCCESS;
}
/**
* @name CCFDATAStorage class
* @implemented
*
* Writes a CFDATA block to the file
*
* @param Data
* Pointer to CFDATA block for the buffer
*
* @param Buffer
* Pointer to buffer with data to write
*
* @param BytesWritten
* Pointer to buffer to write number of bytes written
*
* @return
* Status of operation
*/
ULONG CCFDATAStorage::WriteBlock(PCFDATA Data, void* Buffer, PULONG BytesWritten)
{
*BytesWritten = fwrite(Buffer, 1, Data->CompSize, FileHandle);
if (*BytesWritten != Data->CompSize)
return CAB_STATUS_CANNOT_WRITE;
return CAB_STATUS_SUCCESS;
}
#endif /* CAB_READ_ONLY */