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 */
CCFDATAStorage()31 CCFDATAStorage::CCFDATAStorage()
32 {
33 FileHandle = NULL;
34 }
35
36 /**
37 * @name CCFDATAStorage class
38 * @implemented
39 *
40 * Default destructor
41 */
~CCFDATAStorage()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 */
Create()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 */
Destroy()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 */
Truncate()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 */
Position()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 */
Seek(LONG Position)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 */
ReadBlock(PCFDATA Data,void * Buffer,PULONG BytesRead)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 */
WriteBlock(PCFDATA Data,void * Buffer,PULONG BytesWritten)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