1 /*
2  * HLLib
3  * Copyright (C) 2006-2010 Ryan Gregg
4 
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later
9  * version.
10  */
11 
12 #include "HLLib.h"
13 #include "FileStream.h"
14 
15 using namespace HLLib;
16 using namespace HLLib::Streams;
17 
18 #ifdef _WIN32
CFileStream(const hlChar * lpFileName)19 CFileStream::CFileStream(const hlChar *lpFileName) : hFile(0), uiMode(HL_MODE_INVALID)
20 #else
21 CFileStream::CFileStream(const hlChar *lpFileName) : iFile(-1), uiMode(HL_MODE_INVALID)
22 #endif
23 {
24 	this->lpFileName = new hlChar[strlen(lpFileName) + 1];
25 	strcpy(this->lpFileName, lpFileName);
26 }
27 
~CFileStream()28 CFileStream::~CFileStream()
29 {
30 	this->Close();
31 
32 	delete []this->lpFileName;
33 }
34 
GetType() const35 HLStreamType CFileStream::GetType() const
36 {
37 	return HL_STREAM_FILE;
38 }
39 
GetFileName() const40 const hlChar *CFileStream::GetFileName() const
41 {
42 	return this->lpFileName;
43 }
44 
GetOpened() const45 hlBool CFileStream::GetOpened() const
46 {
47 #ifdef _WIN32
48 	return this->hFile != 0;
49 #else
50 	return this->iFile >= 0;
51 #endif
52 }
53 
GetMode() const54 hlUInt CFileStream::GetMode() const
55 {
56 	return this->uiMode;
57 }
58 
Open(hlUInt uiMode)59 hlBool CFileStream::Open(hlUInt uiMode)
60 {
61 	this->Close();
62 
63 #ifdef _WIN32
64 	DWORD dwDesiredAccess = ((uiMode & HL_MODE_READ) ? GENERIC_READ : 0) | ((uiMode & HL_MODE_WRITE) ? GENERIC_WRITE : 0);
65 	DWORD dwShareMode = (uiMode & HL_MODE_VOLATILE) ? FILE_SHARE_READ | FILE_SHARE_WRITE : ((uiMode & HL_MODE_READ) && !(uiMode & HL_MODE_WRITE) ? FILE_SHARE_READ : 0);
66 	DWORD dwCreationDisposition = (uiMode & HL_MODE_WRITE) && (uiMode & HL_MODE_CREATE) ? (bOverwriteFiles ? CREATE_ALWAYS : CREATE_NEW) : ((uiMode & HL_MODE_READ) || (uiMode & HL_MODE_WRITE) ? OPEN_EXISTING : 0);
67 
68 	if(dwDesiredAccess == 0 || dwCreationDisposition == 0)
69 	{
70 		LastError.SetErrorMessageFormated("Invalid open mode (%#.8x).", uiMode);
71 
72 		return hlFalse;
73 	}
74 
75 	this->hFile = CreateFile(this->lpFileName, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
76 
77 	if(this->hFile == INVALID_HANDLE_VALUE)
78 	{
79 		LastError.SetSystemErrorMessage("Error opening file.");
80 
81 		this->hFile = 0;
82 		return hlFalse;
83 	}
84 #else
85 	hlInt iMode;
86 
87 	if((uiMode & HL_MODE_READ) && (uiMode & HL_MODE_WRITE))
88 	{
89 		iMode = O_RDWR;
90 	}
91 	else if(uiMode & HL_MODE_READ)
92 	{
93 		iMode = O_RDONLY;
94 	}
95 	else if(uiMode & HL_MODE_WRITE)
96 	{
97 		iMode = O_WRONLY;
98 	}
99 
100 	if((uiMode & HL_MODE_WRITE) && (uiMode & HL_MODE_CREATE))
101 	{
102 		iMode |= bOverwriteFiles ? O_CREAT | O_TRUNC : O_CREAT | O_EXCL;
103 	}
104 
105 	if((uiMode & (HL_MODE_READ | HL_MODE_WRITE)) == 0)
106 	{
107 		LastError.SetErrorMessageFormated("Invalid open mode (%#.8x).", uiMode);
108 
109 		return hlFalse;
110 	}
111 
112 	this->iFile = open(this->lpFileName, iMode | O_BINARY | O_RANDOM, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
113 
114 	if(this->iFile < 0)
115 	{
116 		LastError.SetSystemErrorMessage("Error opening file.");
117 
118 		this->iFile = -1;
119 		return hlFalse;
120 	}
121 #endif
122 
123 	this->uiMode = uiMode;
124 
125 	return hlTrue;
126 }
127 
Close()128 hlVoid CFileStream::Close()
129 {
130 	if(this->GetOpened())
131 	{
132 #ifdef _WIN32
133 		CloseHandle(this->hFile);
134 		this->hFile = 0;
135 #else
136 		close(this->iFile);
137 		this->iFile = -1;
138 #endif
139 
140 		this->uiMode = HL_MODE_INVALID;
141 	}
142 }
143 
GetStreamSize() const144 hlULongLong CFileStream::GetStreamSize() const
145 {
146 	if(!this->GetOpened())
147 	{
148 		return 0;
149 	}
150 
151 #ifdef _WIN32
152 	LARGE_INTEGER liFileSize;
153 	return GetFileSizeEx(this->hFile, &liFileSize) ? static_cast<hlULongLong>(liFileSize.QuadPart) : 0;
154 #else
155 	struct stat Stat;
156 
157 	return fstat(this->iFile, &Stat) < 0 ? 0 : Stat.st_size;
158 #endif
159 }
160 
GetStreamPointer() const161 hlULongLong CFileStream::GetStreamPointer() const
162 {
163 	if(!this->GetOpened())
164 	{
165 		return 0;
166 	}
167 
168 #ifdef _WIN32
169 	LARGE_INTEGER liOffset;
170 	liOffset.QuadPart = 0;
171 
172 	LARGE_INTEGER liPointer;
173 	return SetFilePointerEx(this->hFile, liOffset, &liPointer, FILE_CURRENT) ? static_cast<hlULongLong>(liPointer.QuadPart) : 0;
174 #else
175 	 return (hlUInt)lseek(this->iFile, 0, SEEK_CUR);
176 #endif
177 }
178 
Seek(hlLongLong iOffset,HLSeekMode eSeekMode)179 hlULongLong CFileStream::Seek(hlLongLong iOffset, HLSeekMode eSeekMode)
180 {
181 	if(!this->GetOpened())
182 	{
183 		return 0;
184 	}
185 
186 #ifdef _WIN32
187 	DWORD dwMode = FILE_BEGIN;
188 	switch(eSeekMode)
189 	{
190 	/*case HL_SEEK_BEGINNING:
191 		dwMode = FILE_BEGIN;
192 		break;*/
193 	case HL_SEEK_CURRENT:
194 		dwMode = FILE_CURRENT;
195 		break;
196 	case HL_SEEK_END:
197 		dwMode = FILE_END;
198 		break;
199 	}
200 
201 	LARGE_INTEGER liOffset;
202 	liOffset.QuadPart = iOffset;
203 
204 	LARGE_INTEGER liPointer;
205 	return SetFilePointerEx(this->hFile, liOffset, &liPointer, dwMode) ? static_cast<hlULongLong>(liPointer.QuadPart) : 0;
206 #else
207 	hlInt iMode = SEEK_SET;
208 	switch(eSeekMode)
209 	{
210 	/*case HL_SEEK_BEGINNING:
211 		iMode = SEEK_SET;
212 		break;*/
213 	case HL_SEEK_CURRENT:
214 		iMode = SEEK_CUR;
215 		break;
216 	case HL_SEEK_END:
217 		iMode = SEEK_END;
218 		break;
219 	}
220 
221 	return (hlUInt)lseek(this->iFile, iOffset, iMode);
222 #endif
223 }
224 
Read(hlChar & cChar)225 hlBool CFileStream::Read(hlChar &cChar)
226 {
227 	if(!this->GetOpened())
228 	{
229 		return hlFalse;
230 	}
231 
232 	if((this->uiMode & HL_MODE_READ) == 0)
233 	{
234 		LastError.SetErrorMessage("Stream not in read mode.");
235 		return hlFalse;
236 	}
237 
238 #ifdef _WIN32
239 	hlULong ulBytesRead = 0;
240 
241 	if(!ReadFile(this->hFile, &cChar, 1, &ulBytesRead, NULL))
242 	{
243 		LastError.SetSystemErrorMessage("ReadFile() failed.");
244 	}
245 
246 	return ulBytesRead == 1;
247 #else
248 	hlInt iBytesRead = read(this->iFile, &cChar, 1);
249 
250 	if(iBytesRead < 0)
251 	{
252 		LastError.SetSystemErrorMessage("read() failed.");
253 	}
254 
255 	return iBytesRead == 1;
256 #endif
257 }
258 
Read(hlVoid * lpData,hlUInt uiBytes)259 hlUInt CFileStream::Read(hlVoid *lpData, hlUInt uiBytes)
260 {
261 	if(!this->GetOpened())
262 	{
263 		return 0;
264 	}
265 
266 	if((this->uiMode & HL_MODE_READ) == 0)
267 	{
268 		LastError.SetErrorMessage("Stream not in read mode.");
269 		return 0;
270 	}
271 
272 #ifdef _WIN32
273 	hlULong ulBytesRead = 0;
274 
275 	if(!ReadFile(this->hFile, lpData, uiBytes, &ulBytesRead, NULL))
276 	{
277 		LastError.SetSystemErrorMessage("ReadFile() failed.");
278 	}
279 
280 	return (hlUInt)ulBytesRead;
281 #else
282 	hlInt iBytesRead = read(this->iFile, lpData, uiBytes);
283 
284 	if(iBytesRead < 0)
285 	{
286 		LastError.SetSystemErrorMessage("read() failed.");
287 	}
288 
289 	return (hlUInt)iBytesRead;
290 #endif
291 }
292 
Write(hlChar cChar)293 hlBool CFileStream::Write(hlChar cChar)
294 {
295 	if(!this->GetOpened())
296 	{
297 		return hlFalse;
298 	}
299 
300 	if((this->uiMode & HL_MODE_WRITE) == 0)
301 	{
302 		LastError.SetErrorMessage("Stream not in write mode.");
303 		return hlFalse;
304 	}
305 
306 #ifdef _WIN32
307 	hlULong ulBytesWritten = 0;
308 
309 	if(!WriteFile(this->hFile, &cChar, 1, &ulBytesWritten, NULL))
310 	{
311 		LastError.SetSystemErrorMessage("WriteFile() failed.");
312 	}
313 
314 	return ulBytesWritten == 1;
315 #else
316 	hlInt iBytesWritten = write(this->iFile, &cChar, 1);
317 
318 	if(iBytesWritten < 0)
319 	{
320 		LastError.SetSystemErrorMessage("write() failed.");
321 	}
322 
323 	return iBytesWritten == 1;
324 #endif
325 }
326 
Write(const hlVoid * lpData,hlUInt uiBytes)327 hlUInt CFileStream::Write(const hlVoid *lpData, hlUInt uiBytes)
328 {
329 	if(!this->GetOpened())
330 	{
331 		return 0;
332 	}
333 
334 	if((this->uiMode & HL_MODE_WRITE) == 0)
335 	{
336 		LastError.SetErrorMessage("Stream not in write mode.");
337 		return 0;
338 	}
339 
340 #ifdef _WIN32
341 	hlULong ulBytesWritten = 0;
342 
343 	if(!WriteFile(this->hFile, lpData, uiBytes, &ulBytesWritten, NULL))
344 	{
345 		LastError.SetSystemErrorMessage("WriteFile() failed.");
346 	}
347 
348 	return (hlUInt)ulBytesWritten;
349 #else
350 	hlInt iBytesWritten = write(this->iFile, lpData, uiBytes);
351 
352 	if(iBytesWritten < 0)
353 	{
354 		LastError.SetSystemErrorMessage("write() failed.");
355 	}
356 
357 	return (hlUInt)iBytesWritten;
358 #endif
359 }
360