xref: /aosp_15_r20/external/deqp/framework/delibs/deutil/deFile.c (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Utility Library
3  * ----------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  *//*!
20  * \file
21  * \brief File abstraction.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "deFile.h"
25 #include "deMemory.h"
26 
27 #if (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_ANDROID) || \
28     (DE_OS == DE_OS_SYMBIAN) || (DE_OS == DE_OS_QNX) || (DE_OS == DE_OS_FUCHSIA)
29 
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <errno.h>
35 
36 struct deFile_s
37 {
38     int fd;
39 };
40 
deFileExists(const char * filename)41 bool deFileExists(const char *filename)
42 {
43     struct stat st;
44     int result = stat(filename, &st);
45     return result == 0;
46 }
47 
deDeleteFile(const char * filename)48 bool deDeleteFile(const char *filename)
49 {
50     return unlink(filename) == 0;
51 }
52 
deFile_createFromHandle(uintptr_t handle)53 deFile *deFile_createFromHandle(uintptr_t handle)
54 {
55     int fd       = (int)handle;
56     deFile *file = (deFile *)deCalloc(sizeof(deFile));
57     if (!file)
58     {
59         close(fd);
60         return file;
61     }
62 
63     file->fd = fd;
64     return file;
65 }
66 
mapOpenMode(deFileMode mode)67 static int mapOpenMode(deFileMode mode)
68 {
69     int flag = 0;
70 
71     /* Read, write or read and write access is required. */
72     DE_ASSERT((mode & DE_FILEMODE_READ) != 0 || ((mode & DE_FILEMODE_WRITE) != 0));
73 
74     /* Create, open or create and open mode is required. */
75     DE_ASSERT((mode & DE_FILEMODE_OPEN) != 0 || ((mode & DE_FILEMODE_CREATE) != 0));
76 
77     /* Require write when using create. */
78     DE_ASSERT(!(mode & DE_FILEMODE_CREATE) || (mode & DE_FILEMODE_WRITE));
79 
80     /* Require write and open when using truncate */
81     DE_ASSERT(!(mode & DE_FILEMODE_TRUNCATE) || ((mode & DE_FILEMODE_WRITE) && (mode & DE_FILEMODE_OPEN)));
82 
83     if (mode & DE_FILEMODE_READ)
84         flag |= O_RDONLY;
85 
86     if (mode & DE_FILEMODE_WRITE)
87         flag |= O_WRONLY;
88 
89     if (mode & DE_FILEMODE_TRUNCATE)
90         flag |= O_TRUNC;
91 
92     if (mode & DE_FILEMODE_CREATE)
93         flag |= O_CREAT;
94 
95     if (!(mode & DE_FILEMODE_OPEN))
96         flag |= O_EXCL;
97 
98     return flag;
99 }
100 
deFile_create(const char * filename,uint32_t mode)101 deFile *deFile_create(const char *filename, uint32_t mode)
102 {
103     int fd = open(filename, mapOpenMode(mode), 0777);
104     if (fd >= 0)
105         return deFile_createFromHandle((uintptr_t)fd);
106     else
107         return DE_NULL;
108 }
109 
deFile_destroy(deFile * file)110 void deFile_destroy(deFile *file)
111 {
112     close(file->fd);
113     deFree(file);
114 }
115 
deFile_setFlags(deFile * file,uint32_t flags)116 bool deFile_setFlags(deFile *file, uint32_t flags)
117 {
118     /* Non-blocking. */
119     {
120         int oldFlags = fcntl(file->fd, F_GETFL, 0);
121         int newFlags = (flags & DE_FILE_NONBLOCKING) ? (oldFlags | O_NONBLOCK) : (oldFlags & ~O_NONBLOCK);
122         if (fcntl(file->fd, F_SETFL, newFlags) != 0)
123             return false;
124     }
125 
126     /* Close on exec. */
127     {
128         int oldFlags = fcntl(file->fd, F_GETFD, 0);
129         int newFlags = (flags & DE_FILE_CLOSE_ON_EXEC) ? (oldFlags | FD_CLOEXEC) : (oldFlags & ~FD_CLOEXEC);
130         if (fcntl(file->fd, F_SETFD, newFlags) != 0)
131             return false;
132     }
133 
134     return true;
135 }
136 
mapSeekPosition(deFilePosition position)137 static int mapSeekPosition(deFilePosition position)
138 {
139     switch (position)
140     {
141     case DE_FILEPOSITION_BEGIN:
142         return SEEK_SET;
143     case DE_FILEPOSITION_END:
144         return SEEK_END;
145     case DE_FILEPOSITION_CURRENT:
146         return SEEK_CUR;
147     default:
148         DE_ASSERT(false);
149         return 0;
150     }
151 }
152 
deFile_seek(deFile * file,deFilePosition base,int64_t offset)153 bool deFile_seek(deFile *file, deFilePosition base, int64_t offset)
154 {
155     return lseek(file->fd, (off_t)offset, mapSeekPosition(base)) >= 0;
156 }
157 
deFile_getPosition(const deFile * file)158 int64_t deFile_getPosition(const deFile *file)
159 {
160     return lseek(file->fd, 0, SEEK_CUR);
161 }
162 
deFile_getSize(const deFile * file)163 int64_t deFile_getSize(const deFile *file)
164 {
165     int64_t size   = 0;
166     int64_t curPos = lseek(file->fd, 0, SEEK_CUR);
167 
168     if (curPos < 0)
169         return -1;
170 
171     size = lseek(file->fd, 0, SEEK_END);
172 
173     if (size < 0)
174         return -1;
175 
176     lseek(file->fd, (off_t)curPos, SEEK_SET);
177 
178     return size;
179 }
180 
mapReadWriteResult(int64_t numBytes)181 static deFileResult mapReadWriteResult(int64_t numBytes)
182 {
183     if (numBytes > 0)
184         return DE_FILERESULT_SUCCESS;
185     else if (numBytes == 0)
186         return DE_FILERESULT_END_OF_FILE;
187     else
188         return errno == EAGAIN ? DE_FILERESULT_WOULD_BLOCK : DE_FILERESULT_ERROR;
189 }
190 
deFile_read(deFile * file,void * buf,int64_t bufSize,int64_t * numReadPtr)191 deFileResult deFile_read(deFile *file, void *buf, int64_t bufSize, int64_t *numReadPtr)
192 {
193     int64_t numRead = read(file->fd, buf, (size_t)bufSize);
194 
195     if (numReadPtr)
196         *numReadPtr = numRead;
197 
198     return mapReadWriteResult(numRead);
199 }
200 
deFile_write(deFile * file,const void * buf,int64_t bufSize,int64_t * numWrittenPtr)201 deFileResult deFile_write(deFile *file, const void *buf, int64_t bufSize, int64_t *numWrittenPtr)
202 {
203     int64_t numWritten = write(file->fd, buf, (size_t)bufSize);
204 
205     if (numWrittenPtr)
206         *numWrittenPtr = numWritten;
207 
208     return mapReadWriteResult(numWritten);
209 }
210 
211 #elif (DE_OS == DE_OS_WIN32)
212 
213 #define VC_EXTRALEAN
214 #define WIN32_LEAN_AND_MEAN
215 #include <windows.h>
216 
217 struct deFile_s
218 {
219     HANDLE handle;
220 };
221 
deFileExists(const char * filename)222 bool deFileExists(const char *filename)
223 {
224     return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES;
225 }
226 
deDeleteFile(const char * filename)227 bool deDeleteFile(const char *filename)
228 {
229     return DeleteFile(filename) == TRUE;
230 }
231 
deFile_createFromHandle(uintptr_t handle)232 deFile *deFile_createFromHandle(uintptr_t handle)
233 {
234     deFile *file = (deFile *)deCalloc(sizeof(deFile));
235     if (!file)
236     {
237         CloseHandle((HANDLE)handle);
238         return file;
239     }
240 
241     file->handle = (HANDLE)handle;
242     return file;
243 }
244 
deFile_create(const char * filename,uint32_t mode)245 deFile *deFile_create(const char *filename, uint32_t mode)
246 {
247     DWORD access  = 0;
248     DWORD create  = OPEN_EXISTING;
249     HANDLE handle = DE_NULL;
250 
251     /* Read, write or read and write access is required. */
252     DE_ASSERT((mode & DE_FILEMODE_READ) != 0 || ((mode & DE_FILEMODE_WRITE) != 0));
253 
254     /* Create, open or create and open mode is required. */
255     DE_ASSERT((mode & DE_FILEMODE_OPEN) != 0 || ((mode & DE_FILEMODE_CREATE) != 0));
256 
257     /* Require write when using create. */
258     DE_ASSERT(!(mode & DE_FILEMODE_CREATE) || (mode & DE_FILEMODE_WRITE));
259 
260     /* Require write and open when using truncate */
261     DE_ASSERT(!(mode & DE_FILEMODE_TRUNCATE) || ((mode & DE_FILEMODE_WRITE) && (mode & DE_FILEMODE_OPEN)));
262 
263     if (mode & DE_FILEMODE_READ)
264         access |= GENERIC_READ;
265 
266     if (mode & DE_FILEMODE_WRITE)
267         access |= GENERIC_WRITE;
268 
269     if ((mode & DE_FILEMODE_TRUNCATE))
270     {
271         if ((mode & DE_FILEMODE_CREATE) && (mode & DE_FILEMODE_OPEN))
272             create = CREATE_ALWAYS;
273         else if (mode & DE_FILEMODE_OPEN)
274             create = TRUNCATE_EXISTING;
275         else
276             DE_ASSERT(false);
277     }
278     else
279     {
280         if ((mode & DE_FILEMODE_CREATE) && (mode & DE_FILEMODE_OPEN))
281             create = OPEN_ALWAYS;
282         else if (mode & DE_FILEMODE_CREATE)
283             create = CREATE_NEW;
284         else if (mode & DE_FILEMODE_OPEN)
285             create = OPEN_EXISTING;
286         else
287             DE_ASSERT(false);
288     }
289 
290     handle = CreateFile(filename, access, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, DE_NULL, create,
291                         FILE_ATTRIBUTE_NORMAL, DE_NULL);
292     if (handle == INVALID_HANDLE_VALUE)
293         return DE_NULL;
294 
295     return deFile_createFromHandle((uintptr_t)handle);
296 }
297 
deFile_destroy(deFile * file)298 void deFile_destroy(deFile *file)
299 {
300     CloseHandle(file->handle);
301     deFree(file);
302 }
303 
deFile_setFlags(deFile * file,uint32_t flags)304 bool deFile_setFlags(deFile *file, uint32_t flags)
305 {
306     /* Non-blocking. */
307     if (flags & DE_FILE_NONBLOCKING)
308         return false; /* Not supported. */
309 
310     /* Close on exec. */
311     if (!SetHandleInformation(file->handle, HANDLE_FLAG_INHERIT,
312                               (flags & DE_FILE_CLOSE_ON_EXEC) ? HANDLE_FLAG_INHERIT : 0))
313         return false;
314 
315     return true;
316 }
317 
deFile_seek(deFile * file,deFilePosition base,int64_t offset)318 bool deFile_seek(deFile *file, deFilePosition base, int64_t offset)
319 {
320     DWORD method  = 0;
321     LONG lowBits  = (LONG)(offset & 0xFFFFFFFFll);
322     LONG highBits = (LONG)((offset >> 32) & 0xFFFFFFFFll);
323 
324     switch (base)
325     {
326     case DE_FILEPOSITION_BEGIN:
327         method = FILE_BEGIN;
328         break;
329     case DE_FILEPOSITION_END:
330         method = FILE_END;
331         break;
332     case DE_FILEPOSITION_CURRENT:
333         method = FILE_CURRENT;
334         break;
335     default:
336         DE_ASSERT(false);
337         return false;
338     }
339 
340     return SetFilePointer(file->handle, lowBits, &highBits, method) != INVALID_SET_FILE_POINTER;
341 }
342 
deFile_getPosition(const deFile * file)343 int64_t deFile_getPosition(const deFile *file)
344 {
345     LONG highBits = 0;
346     LONG lowBits  = SetFilePointer(file->handle, 0, &highBits, FILE_CURRENT);
347 
348     return (int64_t)(((uint64_t)highBits << 32) | (uint64_t)lowBits);
349 }
350 
deFile_getSize(const deFile * file)351 int64_t deFile_getSize(const deFile *file)
352 {
353     DWORD highBits = 0;
354     DWORD lowBits  = GetFileSize(file->handle, &highBits);
355 
356     return (int64_t)(((uint64_t)highBits << 32) | (uint64_t)lowBits);
357 }
358 
mapReadWriteResult(BOOL retVal,DWORD numBytes)359 static deFileResult mapReadWriteResult(BOOL retVal, DWORD numBytes)
360 {
361     if (retVal && numBytes > 0)
362         return DE_FILERESULT_SUCCESS;
363     else if (retVal && numBytes == 0)
364         return DE_FILERESULT_END_OF_FILE;
365     else
366     {
367         DWORD error = GetLastError();
368 
369         if (error == ERROR_HANDLE_EOF)
370             return DE_FILERESULT_END_OF_FILE;
371         else
372             return DE_FILERESULT_ERROR;
373     }
374 }
375 
deFile_read(deFile * file,void * buf,int64_t bufSize,int64_t * numReadPtr)376 deFileResult deFile_read(deFile *file, void *buf, int64_t bufSize, int64_t *numReadPtr)
377 {
378     DWORD bufSize32 = (DWORD)bufSize;
379     DWORD numRead32 = 0;
380     BOOL result;
381 
382     /* \todo [2011-10-03 pyry] 64-bit IO. */
383     DE_ASSERT((int64_t)bufSize32 == bufSize);
384 
385     result = ReadFile(file->handle, buf, bufSize32, &numRead32, DE_NULL);
386 
387     if (numReadPtr)
388         *numReadPtr = (int64_t)numRead32;
389 
390     return mapReadWriteResult(result, numRead32);
391 }
392 
deFile_write(deFile * file,const void * buf,int64_t bufSize,int64_t * numWrittenPtr)393 deFileResult deFile_write(deFile *file, const void *buf, int64_t bufSize, int64_t *numWrittenPtr)
394 {
395     DWORD bufSize32    = (DWORD)bufSize;
396     DWORD numWritten32 = 0;
397     BOOL result;
398 
399     /* \todo [2011-10-03 pyry] 64-bit IO. */
400     DE_ASSERT((int64_t)bufSize32 == bufSize);
401 
402     result = WriteFile(file->handle, buf, bufSize32, &numWritten32, DE_NULL);
403 
404     if (numWrittenPtr)
405         *numWrittenPtr = (int64_t)numWritten32;
406 
407     return mapReadWriteResult(result, numWritten32);
408 }
409 
410 #else
411 #error Implement deFile for your OS.
412 #endif
413