1 /* 2 * PROJECT: ReactOS cabinet manager 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: CCFDATAStorage class implementation 5 * COPYRIGHT: Copyright 2017 Casper S. Hornstrup (chorns@users.sourceforge.net) 6 * Copyright 2017 Colin Finck <mail@colinfinck.de> 7 * Copyright 2018 Dmitry Bagdanov <dimbo_job@mail.ru> 8 */ 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <sys/stat.h> 13 #include <sys/types.h> 14 15 #if !defined(_WIN32) 16 #include <dirent.h> 17 #endif 18 19 #include "CCFDATAStorage.h" 20 #include "raw.h" 21 #include "mszip.h" 22 23 #if !defined(CAB_READ_ONLY) 24 25 /** 26 * @name CCFDATAStorage class 27 * @implemented 28 * 29 * Default constructor 30 */ 31 CCFDATAStorage::CCFDATAStorage() 32 { 33 FileHandle = NULL; 34 } 35 36 /** 37 * @name CCFDATAStorage class 38 * @implemented 39 * 40 * Default destructor 41 */ 42 CCFDATAStorage::~CCFDATAStorage() 43 { 44 ASSERT(FileHandle == NULL); 45 } 46 47 /** 48 * @name CCFDATAStorage class 49 * @implemented 50 * 51 * Creates the file 52 * 53 * @return 54 * Status of operation 55 */ 56 ULONG CCFDATAStorage::Create() 57 { 58 #if defined(_WIN32) 59 char TmpName[PATH_MAX]; 60 char *pName; 61 int length; 62 63 if (tmpnam(TmpName) == NULL) 64 return CAB_STATUS_CANNOT_CREATE; 65 66 /* Append 'tmp' if the file name ends with a dot */ 67 length = strlen(TmpName); 68 if (length > 0 && TmpName[length - 1] == '.') 69 strcat(TmpName, "tmp"); 70 71 /* Skip a leading slash or backslash */ 72 pName = TmpName; 73 if (*pName == '/' || *pName == '\\') 74 pName++; 75 76 strcpy(FullName, pName); 77 78 FileHandle = fopen(FullName, "w+b"); 79 if (FileHandle == NULL) 80 return CAB_STATUS_CANNOT_CREATE; 81 #else 82 if ((FileHandle = tmpfile()) == NULL) 83 return CAB_STATUS_CANNOT_CREATE; 84 #endif 85 return CAB_STATUS_SUCCESS; 86 } 87 88 /** 89 * @name CCFDATAStorage class 90 * @implemented 91 * 92 * Destroys the file 93 * 94 * @return 95 * Status of operation 96 */ 97 ULONG CCFDATAStorage::Destroy() 98 { 99 ASSERT(FileHandle != NULL); 100 101 fclose(FileHandle); 102 103 FileHandle = NULL; 104 105 #if defined(_WIN32) 106 remove(FullName); 107 #endif 108 109 return CAB_STATUS_SUCCESS; 110 } 111 112 /** 113 * @name CCFDATAStorage class 114 * @implemented 115 * 116 * Truncate the scratch file to zero bytes 117 * 118 * @return 119 * Status of operation 120 */ 121 ULONG CCFDATAStorage::Truncate() 122 { 123 fclose(FileHandle); 124 #if defined(_WIN32) 125 FileHandle = fopen(FullName, "w+b"); 126 #else 127 FileHandle = tmpfile(); 128 #endif 129 if (FileHandle == NULL) 130 { 131 DPRINT(MID_TRACE, ("ERROR '%i'.\n", errno)); 132 return CAB_STATUS_FAILURE; 133 } 134 135 return CAB_STATUS_SUCCESS; 136 } 137 138 /** 139 * @name CCFDATAStorage class 140 * @implemented 141 * 142 * Returns current position in file 143 * 144 * @return 145 * Current position 146 */ 147 ULONG CCFDATAStorage::Position() 148 { 149 return (ULONG)ftell(FileHandle); 150 } 151 152 153 /** 154 * @name CCFDATAStorage class 155 * @implemented 156 * 157 * Seeks to an absolute position 158 * 159 * @param Position 160 * Absolute position to seek to 161 * 162 * @return 163 * Status of operation 164 */ 165 ULONG CCFDATAStorage::Seek(LONG Position) 166 { 167 if (fseek(FileHandle, (off_t)Position, SEEK_SET) != 0) 168 return CAB_STATUS_FAILURE; 169 else 170 return CAB_STATUS_SUCCESS; 171 } 172 173 174 /** 175 * @name CCFDATAStorage class 176 * @implemented 177 * 178 * Reads a CFDATA block from the file 179 * 180 * @param Data 181 * Pointer to CFDATA block for the buffer 182 * 183 * @param Buffer 184 * Pointer to buffer to store data read 185 * 186 * @param BytesRead 187 * Pointer to buffer to write number of bytes read 188 * 189 * @return 190 * Status of operation 191 */ 192 ULONG CCFDATAStorage::ReadBlock(PCFDATA Data, void* Buffer, PULONG BytesRead) 193 { 194 *BytesRead = fread(Buffer, 1, Data->CompSize, FileHandle); 195 if (*BytesRead != Data->CompSize) 196 return CAB_STATUS_CANNOT_READ; 197 198 return CAB_STATUS_SUCCESS; 199 } 200 201 202 /** 203 * @name CCFDATAStorage class 204 * @implemented 205 * 206 * Writes a CFDATA block to the file 207 * 208 * @param Data 209 * Pointer to CFDATA block for the buffer 210 * 211 * @param Buffer 212 * Pointer to buffer with data to write 213 * 214 * @param BytesWritten 215 * Pointer to buffer to write number of bytes written 216 * 217 * @return 218 * Status of operation 219 */ 220 ULONG CCFDATAStorage::WriteBlock(PCFDATA Data, void* Buffer, PULONG BytesWritten) 221 { 222 *BytesWritten = fwrite(Buffer, 1, Data->CompSize, FileHandle); 223 if (*BytesWritten != Data->CompSize) 224 return CAB_STATUS_CANNOT_WRITE; 225 226 return CAB_STATUS_SUCCESS; 227 } 228 229 230 #endif /* CAB_READ_ONLY */ 231