util/tests: Use define instead of VLA
[mesa.git] / src / util / os_file.c
1 /*
2 * Copyright 2019 Intel Corporation
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include "os_file.h"
7
8 #include <errno.h>
9 #include <stdlib.h>
10
11 #if defined(__linux__)
12
13 #include <fcntl.h>
14 #include <sys/stat.h>
15 #include <unistd.h>
16
17
18 static ssize_t
19 readN(int fd, char *buf, size_t len)
20 {
21 int err = -ENODATA;
22 size_t total = 0;
23 do {
24 ssize_t ret = read(fd, buf + total, len - total);
25
26 if (ret < 0)
27 ret = -errno;
28
29 if (ret == -EINTR || ret == -EAGAIN)
30 continue;
31
32 if (ret <= 0)
33 break;
34
35 total += ret;
36 } while (total != len);
37
38 return total ? total : err;
39 }
40
41 static char *
42 read_grow(int fd)
43 {
44 size_t len = 64;
45
46 char *buf = malloc(len);
47 if (!buf) {
48 close(fd);
49 errno = -ENOMEM;
50 return NULL;
51 }
52
53 ssize_t read;
54 size_t offset = 0, remaining = len - 1;
55 while ((read = readN(fd, buf + offset, remaining)) == remaining) {
56 char *newbuf = realloc(buf, 2 * len);
57 if (!newbuf) {
58 free(buf);
59 close(fd);
60 errno = -ENOMEM;
61 return NULL;
62 }
63
64 buf = newbuf;
65 len *= 2;
66 offset += read;
67 remaining = len - offset - 1;
68 }
69
70 close(fd);
71
72 if (read > 0)
73 offset += read;
74
75 buf[offset] = '\0';
76
77 return buf;
78 }
79
80 char *
81 os_read_file(const char *filename)
82 {
83 size_t len = 0;
84
85 int fd = open(filename, O_RDONLY);
86 if (fd == -1) {
87 /* errno set by open() */
88 return NULL;
89 }
90
91 struct stat stat;
92 if (fstat(fd, &stat) == 0)
93 len = stat.st_size;
94
95 if (!len)
96 return read_grow(fd);
97
98 /* add NULL terminator */
99 len++;
100
101 char *buf = malloc(len);
102 if (!buf) {
103 close(fd);
104 errno = -ENOMEM;
105 return NULL;
106 }
107
108 ssize_t read = readN(fd, buf, len - 1);
109
110 close(fd);
111
112 if (read == -1)
113 return NULL;
114
115 buf[read] = '\0';
116
117 return buf;
118 }
119
120 #else
121
122 char *
123 os_read_file(const char *filename)
124 {
125 errno = -ENOSYS;
126 return NULL;
127 }
128
129 #endif