1 /*-------------------------------------------------------------------------
2 * drawElements Utility Library
3 * ----------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief File abstraction.
22 *//*--------------------------------------------------------------------*/
27 #if (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_SYMBIAN) || (DE_OS == DE_OS_QNX)
29 #include <sys/types.h>
40 deBool deFileExists (const char* filename)
43 int result = stat(filename, &st);
47 deBool deDeleteFile (const char* filename)
49 return unlink(filename) == 0;
52 deFile* deFile_createFromHandle (deUintptr handle)
55 deFile* file = (deFile*)deCalloc(sizeof(deFile));
66 static int mapOpenMode (deFileMode mode)
70 /* Read, write or read and write access is required. */
71 DE_ASSERT((mode & DE_FILEMODE_READ) != 0 || ((mode & DE_FILEMODE_WRITE) != 0));
73 /* Create, open or create and open mode is required. */
74 DE_ASSERT((mode & DE_FILEMODE_OPEN) != 0 || ((mode & DE_FILEMODE_CREATE) != 0));
76 /* Require write when using create. */
77 DE_ASSERT(!(mode & DE_FILEMODE_CREATE) || (mode & DE_FILEMODE_WRITE));
79 /* Require write and open when using truncate */
80 DE_ASSERT(!(mode & DE_FILEMODE_TRUNCATE) || ((mode & DE_FILEMODE_WRITE) && (mode & DE_FILEMODE_OPEN)));
82 if (mode & DE_FILEMODE_READ)
85 if (mode & DE_FILEMODE_WRITE)
88 if (mode & DE_FILEMODE_TRUNCATE)
91 if (mode & DE_FILEMODE_CREATE)
94 if (!(mode & DE_FILEMODE_OPEN))
100 deFile* deFile_create (const char* filename, deUint32 mode)
102 int fd = open(filename, mapOpenMode(mode), 0777);
104 return deFile_createFromHandle((deUintptr)fd);
109 void deFile_destroy (deFile* file)
115 deBool deFile_setFlags (deFile* file, deUint32 flags)
119 int oldFlags = fcntl(file->fd, F_GETFL, 0);
120 int newFlags = (flags & DE_FILE_NONBLOCKING) ? (oldFlags | O_NONBLOCK) : (oldFlags & ~O_NONBLOCK);
121 if (fcntl(file->fd, F_SETFL, newFlags) != 0)
127 int oldFlags = fcntl(file->fd, F_GETFD, 0);
128 int newFlags = (flags & DE_FILE_CLOSE_ON_EXEC) ? (oldFlags | FD_CLOEXEC) : (oldFlags & ~FD_CLOEXEC);
129 if (fcntl(file->fd, F_SETFD, newFlags) != 0)
136 static int mapSeekPosition (deFilePosition position)
140 case DE_FILEPOSITION_BEGIN: return SEEK_SET;
141 case DE_FILEPOSITION_END: return SEEK_END;
142 case DE_FILEPOSITION_CURRENT: return SEEK_CUR;
149 deBool deFile_seek (deFile* file, deFilePosition base, deInt64 offset)
151 return lseek(file->fd, (off_t)offset, mapSeekPosition(base)) >= 0;
154 deInt64 deFile_getPosition (const deFile* file)
156 return lseek(file->fd, 0, SEEK_CUR);
159 deInt64 deFile_getSize (const deFile* file)
162 deInt64 curPos = lseek(file->fd, 0, SEEK_CUR);
167 size = lseek(file->fd, 0, SEEK_END);
172 lseek(file->fd, (off_t)curPos, SEEK_SET);
177 static deFileResult mapReadWriteResult (deInt64 numBytes)
180 return DE_FILERESULT_SUCCESS;
181 else if (numBytes == 0)
182 return DE_FILERESULT_END_OF_FILE;
184 return errno == EAGAIN ? DE_FILERESULT_WOULD_BLOCK : DE_FILERESULT_ERROR;
187 deFileResult deFile_read (deFile* file, void* buf, deInt64 bufSize, deInt64* numReadPtr)
189 deInt64 numRead = read(file->fd, buf, (size_t)bufSize);
192 *numReadPtr = numRead;
194 return mapReadWriteResult(numRead);
197 deFileResult deFile_write (deFile* file, const void* buf, deInt64 bufSize, deInt64* numWrittenPtr)
199 deInt64 numWritten = write(file->fd, buf, (size_t)bufSize);
202 *numWrittenPtr = numWritten;
204 return mapReadWriteResult(numWritten);
207 #elif (DE_OS == DE_OS_WIN32)
210 #define WIN32_LEAN_AND_MEAN
218 deBool deFileExists (const char* filename)
220 return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES;
223 deBool deDeleteFile (const char* filename)
225 return DeleteFile(filename) == TRUE;
228 deFile* deFile_createFromHandle (deUintptr handle)
230 deFile* file = (deFile*)deCalloc(sizeof(deFile));
233 CloseHandle((HANDLE)handle);
237 file->handle = (HANDLE)handle;
241 deFile* deFile_create (const char* filename, deUint32 mode)
244 DWORD create = OPEN_EXISTING;
245 HANDLE handle = DE_NULL;
247 /* Read, write or read and write access is required. */
248 DE_ASSERT((mode & DE_FILEMODE_READ) != 0 || ((mode & DE_FILEMODE_WRITE) != 0));
250 /* Create, open or create and open mode is required. */
251 DE_ASSERT((mode & DE_FILEMODE_OPEN) != 0 || ((mode & DE_FILEMODE_CREATE) != 0));
253 /* Require write when using create. */
254 DE_ASSERT(!(mode & DE_FILEMODE_CREATE) || (mode & DE_FILEMODE_WRITE));
256 /* Require write and open when using truncate */
257 DE_ASSERT(!(mode & DE_FILEMODE_TRUNCATE) || ((mode & DE_FILEMODE_WRITE) && (mode & DE_FILEMODE_OPEN)));
260 if (mode & DE_FILEMODE_READ)
261 access |= GENERIC_READ;
263 if (mode & DE_FILEMODE_WRITE)
264 access |= GENERIC_WRITE;
266 if ((mode & DE_FILEMODE_TRUNCATE))
268 if ((mode & DE_FILEMODE_CREATE) && (mode & DE_FILEMODE_OPEN))
269 create = CREATE_ALWAYS;
270 else if (mode & DE_FILEMODE_OPEN)
271 create = TRUNCATE_EXISTING;
277 if ((mode & DE_FILEMODE_CREATE) && (mode & DE_FILEMODE_OPEN))
278 create = OPEN_ALWAYS;
279 else if (mode & DE_FILEMODE_CREATE)
281 else if (mode & DE_FILEMODE_OPEN)
282 create = OPEN_EXISTING;
287 handle = CreateFile(filename, access, FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, DE_NULL, create, FILE_ATTRIBUTE_NORMAL, DE_NULL);
288 if (handle == INVALID_HANDLE_VALUE)
291 return deFile_createFromHandle((deUintptr)handle);
294 void deFile_destroy (deFile* file)
296 CloseHandle(file->handle);
300 deBool deFile_setFlags (deFile* file, deUint32 flags)
303 if (flags & DE_FILE_NONBLOCKING)
304 return DE_FALSE; /* Not supported. */
307 if (!SetHandleInformation(file->handle, HANDLE_FLAG_INHERIT, (flags & DE_FILE_CLOSE_ON_EXEC) ? HANDLE_FLAG_INHERIT : 0))
313 deBool deFile_seek (deFile* file, deFilePosition base, deInt64 offset)
316 LONG lowBits = (LONG)(offset & 0xFFFFFFFFll);
317 LONG highBits = (LONG)((offset >> 32) & 0xFFFFFFFFll);
321 case DE_FILEPOSITION_BEGIN: method = FILE_BEGIN; break;
322 case DE_FILEPOSITION_END: method = FILE_END; break;
323 case DE_FILEPOSITION_CURRENT: method = FILE_CURRENT; break;
329 return SetFilePointer(file->handle, lowBits, &highBits, method) != INVALID_SET_FILE_POINTER;
332 deInt64 deFile_getPosition (const deFile* file)
335 LONG lowBits = SetFilePointer(file->handle, 0, &highBits, FILE_CURRENT);
337 return (deInt64)(((deUint64)highBits << 32) | (deUint64)lowBits);
340 deInt64 deFile_getSize (const deFile* file)
343 DWORD lowBits = GetFileSize(file->handle, &highBits);
345 return (deInt64)(((deUint64)highBits << 32) | (deUint64)lowBits);
348 static deFileResult mapReadWriteResult (BOOL retVal, DWORD numBytes)
350 if (retVal && numBytes > 0)
351 return DE_FILERESULT_SUCCESS;
352 else if (retVal && numBytes == 0)
353 return DE_FILERESULT_END_OF_FILE;
356 DWORD error = GetLastError();
358 if (error == ERROR_HANDLE_EOF)
359 return DE_FILERESULT_END_OF_FILE;
361 return DE_FILERESULT_ERROR;
365 deFileResult deFile_read (deFile* file, void* buf, deInt64 bufSize, deInt64* numReadPtr)
367 DWORD bufSize32 = (DWORD)bufSize;
371 /* \todo [2011-10-03 pyry] 64-bit IO. */
372 DE_ASSERT((deInt64)bufSize32 == bufSize);
374 result = ReadFile(file->handle, buf, bufSize32, &numRead32, DE_NULL);
377 *numReadPtr = (deInt64)numRead32;
379 return mapReadWriteResult(result, numRead32);
382 deFileResult deFile_write (deFile* file, const void* buf, deInt64 bufSize, deInt64* numWrittenPtr)
384 DWORD bufSize32 = (DWORD)bufSize;
385 DWORD numWritten32 = 0;
388 /* \todo [2011-10-03 pyry] 64-bit IO. */
389 DE_ASSERT((deInt64)bufSize32 == bufSize);
391 result = WriteFile(file->handle, buf, bufSize32, &numWritten32, DE_NULL);
394 *numWrittenPtr = (deInt64)numWritten32;
396 return mapReadWriteResult(result, numWritten32);
400 # error Implement deFile for your OS.