[CABMAN] Do not use tmpfile() because it does not work well on Windows XP
[reactos.git] / sdk / tools / cabman / CCFDATAStorage.cxx
1 /*
2 * PROJECT: ReactOS cabinet manager
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: CCFDATAStorage class implementation for Linux/Unix
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 "cabinet.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 char TmpName[MAX_PATH];
59 char *pName;
60 int length;
61
62 if (tmpnam(TmpName) == NULL)
63 return CAB_STATUS_CANNOT_CREATE;
64
65 /* Append 'tmp' if the file name ends with a dot */
66 length = strlen(TmpName);
67 if (length > 0 && TmpName[length - 1] == '.')
68 strcat(TmpName, "tmp");
69
70 /* Skip a leading slash or backslash */
71 pName = TmpName;
72 if (*pName == '/' || *pName == '\\')
73 pName++;
74
75 strcpy(FullName, pName);
76
77 FileHandle = fopen(FullName, "w+b");
78 if (FileHandle == NULL)
79 return CAB_STATUS_CANNOT_CREATE;
80
81 return CAB_STATUS_SUCCESS;
82 }
83
84 /**
85 * @name CCFDATAStorage class
86 * @implemented
87 *
88 * Destroys the file
89 *
90 * @return
91 * Status of operation
92 */
93 ULONG CCFDATAStorage::Destroy()
94 {
95 ASSERT(FileHandle != NULL);
96
97 fclose(FileHandle);
98
99 FileHandle = NULL;
100
101 remove(FullName);
102
103 return CAB_STATUS_SUCCESS;
104 }
105
106 /**
107 * @name CCFDATAStorage class
108 * @implemented
109 *
110 * Truncate the scratch file to zero bytes
111 *
112 * @return
113 * Status of operation
114 */
115 ULONG CCFDATAStorage::Truncate()
116 {
117 fclose(FileHandle);
118 FileHandle = fopen(FullName, "w+b");
119 if (FileHandle == NULL)
120 {
121 DPRINT(MID_TRACE, ("ERROR '%i'.\n", errno));
122 return CAB_STATUS_FAILURE;
123 }
124
125 return CAB_STATUS_SUCCESS;
126 }
127
128 /**
129 * @name CCFDATAStorage class
130 * @implemented
131 *
132 * Returns current position in file
133 *
134 * @return
135 * Current position
136 */
137 ULONG CCFDATAStorage::Position()
138 {
139 return (ULONG)ftell(FileHandle);
140 }
141
142
143 /**
144 * @name CCFDATAStorage class
145 * @implemented
146 *
147 * Seeks to an absolute position
148 *
149 * @param Position
150 * Absolute position to seek to
151 *
152 * @return
153 * Status of operation
154 */
155 ULONG CCFDATAStorage::Seek(LONG Position)
156 {
157 if (fseek(FileHandle, (off_t)Position, SEEK_SET) != 0)
158 return CAB_STATUS_FAILURE;
159 else
160 return CAB_STATUS_SUCCESS;
161 }
162
163
164 /**
165 * @name CCFDATAStorage class
166 * @implemented
167 *
168 * Reads a CFDATA block from the file
169 *
170 * @param Data
171 * Pointer to CFDATA block for the buffer
172 *
173 * @param Buffer
174 * Pointer to buffer to store data read
175 *
176 * @param BytesRead
177 * Pointer to buffer to write number of bytes read
178 *
179 * @return
180 * Status of operation
181 */
182 ULONG CCFDATAStorage::ReadBlock(PCFDATA Data, void* Buffer, PULONG BytesRead)
183 {
184 *BytesRead = fread(Buffer, 1, Data->CompSize, FileHandle);
185 if (*BytesRead != Data->CompSize)
186 return CAB_STATUS_CANNOT_READ;
187
188 return CAB_STATUS_SUCCESS;
189 }
190
191
192 /**
193 * @name CCFDATAStorage class
194 * @implemented
195 *
196 * Writes a CFDATA block to the file
197 *
198 * @param Data
199 * Pointer to CFDATA block for the buffer
200 *
201 * @param Buffer
202 * Pointer to buffer with data to write
203 *
204 * @param BytesWritten
205 * Pointer to buffer to write number of bytes written
206 *
207 * @return
208 * Status of operation
209 */
210 ULONG CCFDATAStorage::WriteBlock(PCFDATA Data, void* Buffer, PULONG BytesWritten)
211 {
212 *BytesWritten = fwrite(Buffer, 1, Data->CompSize, FileHandle);
213 if (*BytesWritten != Data->CompSize)
214 return CAB_STATUS_CANNOT_WRITE;
215
216 return CAB_STATUS_SUCCESS;
217 }
218
219
220 #endif /* CAB_READ_ONLY */