/* * 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 * Copyright 2018 Dmitry Bagdanov */ #include #include #include #include #include #if !defined(_WIN32) #include #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 */