Cthulhu  0.2.10
Cthulhu compiler collection
file.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: LGPL-3.0-only
2 
3 #include "os/os.h"
4 #include "os_common.h"
5 
6 #include "base/panic.h"
7 #include "core/macros.h"
8 
9 #include <limits.h>
10 #include <stdio.h>
11 #include <errno.h>
12 #include <unistd.h>
13 
14 #include <sys/mman.h>
15 #include <sys/stat.h>
16 
17 static const char *get_access(os_access_t access)
18 {
19  switch (access)
20  {
21  case eOsAccessRead:
22  return "rb";
23 
24  case eOsAccessWrite:
25  case (eOsAccessRead | eOsAccessWrite):
26  return "w+b";
27 
28  case (eOsAccessWrite | eOsAccessTruncate):
29  case (eOsAccessRead | eOsAccessWrite | eOsAccessTruncate):
30  return "wb";
31 
32  default:
33  CT_NEVER("invalid access flags %s", os_access_string(access));
34  }
35 }
36 
38 os_error_t os_file_exists(const char *path)
39 {
40  CTASSERT(path != NULL);
41 
42  if (access(path, F_OK) == 0)
43  {
44  return eOsExists;
45  }
46 
47  return errno;
48 }
49 
51 {
52  return fopen(path, get_access(access));
53 }
54 
56 os_error_t os_tmpfile_open(os_file_t *file)
57 {
58  CTASSERT(file != NULL);
59 
60  FILE *fd = tmpfile();
61 
62  if (fd == NULL)
63  {
64  return errno;
65  }
66 
67  os_file_t result = {
68  .path = "<tmpfile>",
69  .impl = fd,
70  };
71 
72  *file = result;
73  return 0;
74 }
75 
77 {
78  return fclose(file) == 0;
79 }
80 
82 os_error_t os_file_read(os_file_t *file, void *buffer, size_t size, size_t *actual)
83 {
84  CTASSERT(file != NULL);
85  CTASSERT(buffer != NULL);
86  CTASSERT(size > 0);
87  CTASSERT(actual != NULL);
88 
89  size_t read = fread(buffer, 1, size, file->impl);
90 
91  if (read < size)
92  {
93  if (ferror(file->impl))
94  {
95  return errno;
96  }
97  }
98 
99  *actual = read;
100  return 0;
101 }
102 
103 STA_DECL
104 os_error_t os_file_write(os_file_t *file, const void *buffer, size_t size, size_t *actual)
105 {
106  CTASSERT(file != NULL);
107  CTASSERT(buffer != NULL);
108  CTASSERT(size > 0);
109  CTASSERT(actual != NULL);
110 
111  size_t written = fwrite(buffer, 1, size, file->impl);
112 
113  if (written < size)
114  {
115  if (ferror(file->impl))
116  {
117  return errno;
118  }
119  }
120 
121  *actual = written;
122  return errno;
123 }
124 
125 STA_DECL
126 os_error_t os_file_size(os_file_t *file, size_t *actual)
127 {
128  CTASSERT(file != NULL);
129  CTASSERT(actual != NULL);
130 
131  struct stat info;
132  int result = fstat(fileno(file->impl), &info);
133  if (result < 0)
134  {
135  return errno;
136  }
137 
138  *actual = info.st_size;
139  return 0;
140 }
141 
142 STA_DECL
143 os_error_t os_file_resize(os_file_t *file, size_t size)
144 {
145  CTASSERT(file != NULL);
146 
147  // save the current position
148  long pos = ftell(file->impl);
149  if (pos < 0)
150  return errno;
151 
152  int result = ftruncate(fileno(file->impl), size);
153  if (result < 0)
154  return errno;
155 
156  // restore the position
157  result = fseek(file->impl, pos, SEEK_SET);
158  if (result < 0)
159  return errno;
160 
161  return errno;
162 }
163 
164 STA_DECL
165 os_error_t os_file_seek(os_file_t *file, size_t offset, size_t *actual)
166 {
167  CTASSERT(file != NULL);
168  CTASSERT(offset < LONG_MAX);
169  CTASSERT(actual != NULL);
170 
171  int result = fseek(file->impl, (long)offset, SEEK_SET);
172  if (result < 0)
173  {
174  return errno;
175  }
176 
177  *actual = offset;
178  return errno;
179 }
180 
181 STA_DECL
182 os_error_t os_file_tell(os_file_t *file, size_t *actual)
183 {
184  CTASSERT(file != NULL);
185  CTASSERT(actual != NULL);
186 
187  long pos = ftell(file->impl);
188 
189  if (pos < 0)
190  {
191  return errno;
192  }
193 
194  *actual = pos;
195  return errno;
196 }
197 
198 static int get_mmap_prot(os_protect_t protect)
199 {
200  int result = PROT_NONE;
201 
202  if (protect & eOsProtectRead)
203  {
204  result |= PROT_READ;
205  }
206 
207  if (protect & eOsProtectWrite)
208  {
209  result |= PROT_WRITE;
210  }
211 
212  if (protect & eOsProtectExecute)
213  {
214  result |= PROT_EXEC;
215  }
216 
217  return result;
218 }
219 
220 CT_LOCAL void *impl_file_map(os_file_t *file, os_protect_t protect, size_t size, os_mapping_t *mapping)
221 {
222  CT_UNUSED(mapping);
223 
224  int prot = get_mmap_prot(protect);
225 
226  int fd = fileno(file->impl);
227  return mmap(NULL, size, prot, MAP_PRIVATE, fd, 0);
228 }
229 
231 {
232  if (munmap(map->view, map->size) != 0)
233  {
234  return errno;
235  }
236 
237  return 0;
238 }
CT_NODISCARD size_t size
Definition: scan.h:128
os_protect_t
file mapping memory protection
Definition: core.h:47
CT_NODISCARD CT_CONSTFN STA_RET_STRING CT_OS_API const char * os_access_string(os_access_t access)
get the string representation of a file access mode
Definition: os_common.c:32
os_access_t
file access mode
Definition: core.h:38
#define STA_DECL
sal2 annotation on function implementations to copy annotations from the declaration
#define CT_LOCAL
Definition: compiler.h:166
#define CT_UNUSED(x)
mark a variable as unused
Definition: macros.h:46
#define CT_NEVER(...)
assert that a code path is never reached
Definition: panic.h:136
#define CTASSERT(expr)
assert a condition, prints the condition as a message
Definition: panic.h:130
STA_DECL os_error_t os_file_resize(os_file_t *file, size_t size)
truncate/expand a file to a specific size
Definition: file.c:143
CT_LOCAL os_error_t impl_unmap(os_mapping_t *map)
Definition: file.c:230
STA_DECL os_error_t os_file_read(os_file_t *file, void *buffer, size_t size, size_t *actual)
Definition: file.c:82
STA_DECL os_error_t os_file_seek(os_file_t *file, size_t offset, size_t *actual)
Definition: file.c:165
STA_DECL os_error_t os_file_write(os_file_t *file, const void *buffer, size_t size, size_t *actual)
Definition: file.c:104
STA_DECL os_error_t os_file_size(os_file_t *file, size_t *actual)
Definition: file.c:126
STA_DECL os_error_t os_tmpfile_open(os_file_t *file)
Definition: file.c:56
STA_DECL os_error_t os_file_exists(const char *path)
check if a file exists
Definition: file.c:38
STA_DECL os_error_t os_file_tell(os_file_t *file, size_t *actual)
Definition: file.c:182
CT_LOCAL bool impl_file_close(os_file_impl_t file)
Definition: file.c:76
CT_LOCAL void * impl_file_map(os_file_t *file, os_protect_t protect, size_t size, os_mapping_t *mapping)
Definition: file.c:220
CT_LOCAL os_file_impl_t impl_file_open(const char *path, os_access_t access)
Definition: file.c:50
@ eOsExists
Definition: posix.h:26
FILE * os_file_impl_t
Definition: posix.h:11
a file handle
Definition: os.h:40
os_file_impl_t impl
Definition: os.h:45
const char * path
Definition: os.h:42
memory mapping handle
Definition: posix.h:18
size_t size
Definition: posix.h:20
void * view
Definition: posix.h:19