PatchworkOS
Loading...
Searching...
No Matches
file.c
Go to the documentation of this file.
1#include "file.h"
2
3#include <errno.h>
4#include <stddef.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <sys/io.h>
8
9static list_t files;
11
13{
14 if (mode == NULL)
15 {
16 return 0;
17 }
18
20
21 switch (mode[0])
22 {
23 case 'r':
24 {
26 }
27 break;
28 case 'w':
29 {
31 }
32 break;
33 case 'a':
34 {
36 }
37 break;
38 default:
39 {
40 return 0;
41 }
42 }
43
44 for (uint64_t i = 1; i < 4; i++)
45 {
46 switch (mode[i])
47 {
48 case '+':
49 {
50 if ((files & _FILE_RW) == _FILE_RW)
51 {
52 return 0;
53 }
54 files |= _FILE_RW;
55 }
56 break;
57 case 'b':
58 {
59 if (files & _FILE_BIN)
60 {
61 return 0;
62 }
64 }
65 break;
66 case '\0':
67 {
68 return files;
69 }
70 default:
71 {
72 return 0;
73 }
74 }
75 }
76
77 return 0;
78}
79
81{
82 FILE* stream = calloc(1, sizeof(FILE));
83 if (stream == NULL)
84 {
85 return NULL;
86 }
87
88 list_entry_init(&stream->entry);
89 return stream;
90}
91
92void _file_free(FILE* stream)
93{
94 if (stream != stdin && stream != stdout && stream != stderr)
95 {
96 free(stream);
97 }
98}
99
100uint64_t _file_init(FILE* stream, fd_t fd, _file_flags_t flags, void* buffer, uint64_t bufferSize)
101{
102 if (buffer == NULL)
103 {
104 void* oldBuf = stream->buf;
105 stream->buf = malloc(bufferSize);
106 if (stream->buf == NULL)
107 {
108 return ERR;
109 }
110 if (stream->flags & _FILE_OWNS_BUFFER)
111 {
112 free(oldBuf);
113 }
114 stream->flags = flags | _FILE_OWNS_BUFFER;
115 }
116 else
117 {
118 if (stream->flags & _FILE_OWNS_BUFFER)
119 {
120 free(stream->buf);
121 }
122 stream->buf = buffer;
123 stream->flags = flags;
124 }
125
126 stream->fd = fd;
127 stream->bufSize = bufferSize;
128 stream->bufIndex = 0;
129 stream->bufEnd = 0;
130 stream->pos.offset = 0;
131 stream->pos.status = 0;
132 stream->ungetIndex = 0;
133
134 if (mtx_init(&stream->mtx, mtx_recursive) != thrd_success)
135 {
136 if (stream->flags & _FILE_OWNS_BUFFER)
137 {
138 free(stream->buf);
139 }
140 return ERR;
141 }
142
143 return 0;
144}
145
146void _file_deinit(FILE* stream)
147{
148 if (stream->flags & _FILE_OWNS_BUFFER)
149 {
150 free(stream->buf);
151 }
152
153 close(stream->fd);
154
155 mtx_destroy(&stream->mtx);
156}
157
159{
160 if (!(stream->flags & _FILE_BIN))
161 {
162 // TODO: Text stream conversion here
163 }
164
165 uint64_t count = write(stream->fd, stream->buf, stream->bufIndex);
166 if (count == ERR)
167 {
168 stream->flags |= _FILE_ERROR;
169 return ERR;
170 }
171
172 stream->pos.offset += count;
173 stream->bufIndex = 0;
174 return 0;
175}
176
178{
179 uint64_t count = read(stream->fd, stream->buf, stream->bufSize);
180 if (count == ERR)
181 {
182 stream->flags |= _FILE_ERROR;
183 return ERR;
184 }
185 if (count == 0)
186 {
187 stream->flags |= _FILE_EOF;
188 return ERR;
189 }
190
191 if (!(stream->flags & _FILE_BIN))
192 {
193 /* TODO: Text stream conversion here */
194 }
195
196 stream->pos.offset += count;
197 stream->bufEnd = count;
198 stream->bufIndex = 0;
199 return 0;
200}
201
202uint64_t _file_seek(FILE* stream, int64_t offset, int whence)
203{
204 if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END)
205 {
206 errno = EINVAL;
207 return ERR;
208 }
209
210 uint64_t result = seek(stream->fd, offset, whence);
211
212 if (result == ERR)
213 {
214 return ERR;
215 }
216
217 stream->ungetIndex = 0;
218 stream->bufIndex = 0;
219 stream->bufEnd = 0;
220 stream->pos.offset = result;
221 return result;
222}
223
225{
226 if ((stream->bufIndex > stream->bufEnd) ||
228 !(stream->flags & (_FILE_READ | _FILE_RW)))
229 {
230 errno = EBADF;
231 stream->flags |= _FILE_ERROR;
232 return ERR;
233 }
234
235 stream->flags |= _FILE_READ | _FILE_BYTESTREAM;
236 return 0;
237}
238
240{
241 if ((stream->bufIndex < stream->bufEnd) || (stream->ungetIndex > 0) ||
243 !(stream->flags & (_FILE_WRITE | _FILE_APPEND | _FILE_RW)))
244 {
245 errno = EBADF;
246 stream->flags |= _FILE_ERROR;
247 return ERR;
248 }
249
251 return 0;
252}
253
254void _files_init(void)
255{
258 {
259 fprintf(stderr, "libstd: failed to initialize files mutex\n");
260 abort();
261 }
262}
263
265{
267 list_push(&files, &file->entry);
269}
270
272{
274 list_remove(&files, &file->entry);
276}
277
278void _files_close(void)
279{
281
282 FILE* temp;
283 FILE* stream;
284 LIST_FOR_EACH_SAFE(stream, temp, &files, entry)
285 {
286 fclose(stream);
287 }
288
290}
291
293{
294 uint64_t result = 0;
296
297 FILE* stream;
298 LIST_FOR_EACH(stream, &files, entry)
299 {
300 if (fflush(stream) == EOF)
301 {
302 result = ERR;
303 }
304 }
305
307
308 return result;
309}
#define SEEK_SET
Definition SEEK.h:4
#define SEEK_CUR
Definition SEEK.h:5
#define SEEK_END
Definition SEEK.h:6
#define EINVAL
Invalid argument.
Definition errno.h:142
#define errno
Error number variable.
Definition errno.h:27
#define EBADF
Bad file number.
Definition errno.h:77
uint64_t close(fd_t fd)
System call for closing files.
Definition close.c:9
uint64_t seek(fd_t fd, int64_t offset, seek_origin_t origin)
System call for changing the file offset.
Definition seek.c:9
uint64_t read(fd_t fd, void *buffer, uint64_t count)
System call for reading from files.
Definition read.c:9
uint64_t write(fd_t fd, const void *buffer, uint64_t count)
System call for writing to files.
Definition write.c:9
#define LIST_FOR_EACH(elem, list, member)
Iterates over a list.
Definition list.h:65
#define LIST_FOR_EACH_SAFE(elem, temp, list, member)
Safely iterates over a list, allowing for element removal during iteration.
Definition list.h:81
static void list_remove(list_t *list, list_entry_t *entry)
Removes a list entry from its current list.
Definition list.h:317
static void list_push(list_t *list, list_entry_t *entry)
Pushes an entry to the end of the list.
Definition list.h:345
static void list_entry_init(list_entry_t *entry)
Initializes a list entry.
Definition list.h:184
static void list_init(list_t *list)
Initializes a list.
Definition list.h:198
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
__UINT64_TYPE__ fd_t
A file descriptor.
Definition fd_t.h:12
uint64_t _file_prepare_read(FILE *stream)
Definition file.c:224
uint64_t _file_prepare_write(FILE *stream)
Definition file.c:239
uint64_t _files_flush(void)
Definition file.c:292
uint64_t _file_flush_buffer(FILE *stream)
Definition file.c:158
FILE * _file_new(void)
Definition file.c:80
void _files_close(void)
Definition file.c:278
void _files_push(FILE *file)
Definition file.c:264
void _file_free(FILE *stream)
Definition file.c:92
uint64_t _file_seek(FILE *stream, int64_t offset, int whence)
Definition file.c:202
static mtx_t filesMtx
Definition file.c:10
static list_t files
Definition file.c:9
_file_flags_t _file_flags_parse(const char *mode)
Definition file.c:12
uint64_t _file_init(FILE *stream, fd_t fd, _file_flags_t flags, void *buffer, uint64_t bufferSize)
Definition file.c:100
uint64_t _file_fill_buffer(FILE *stream)
Definition file.c:177
void _files_init(void)
Definition file.c:254
void _file_deinit(FILE *stream)
Definition file.c:146
void _files_remove(FILE *file)
Definition file.c:271
static dentry_t * file
Definition log_file.c:17
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
static atomic_long count
Definition main.c:9
_file_flags_t
Definition file.h:9
@ _FILE_EOF
Definition file.h:23
@ _FILE_READ
Definition file.h:10
@ _FILE_WIDESTREAM
Definition file.h:20
@ _FILE_WRITE
Definition file.h:11
@ _FILE_RW
Definition file.h:12
@ _FILE_OWNS_BUFFER
Definition file.h:15
@ _FILE_BIN
Definition file.h:14
@ _FILE_ERROR
Definition file.h:19
@ _FILE_APPEND
Definition file.h:13
@ _FILE_BYTESTREAM
Definition file.h:21
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__INT64_TYPE__ int64_t
Definition stdint.h:16
#define EOF
Definition stdio.h:25
_PUBLIC int fflush(FILE *stream)
Definition fflush.c:6
_PUBLIC int fclose(FILE *stream)
Definition fclose.c:7
FILE * stdout
Definition std_streams.c:17
FILE * stderr
Definition std_streams.c:18
FILE * stdin
Definition std_streams.c:16
_PUBLIC int fprintf(FILE *_RESTRICT stream, const char *_RESTRICT format,...)
Definition fprintf.c:5
_PUBLIC void * calloc(size_t nmemb, size_t size)
Definition calloc.c:6
_PUBLIC void * malloc(size_t size)
Definition malloc.c:5
_PUBLIC _NORETURN void abort(void)
Definition abort.c:7
_PUBLIC void free(void *ptr)
Definition free.c:11
Definition file.h:34
fpos_t pos
Definition file.h:41
fd_t fd
Definition file.h:36
uint8_t * buf
Definition file.h:37
list_entry_t entry
Definition file.h:35
uint64_t bufIndex
Definition file.h:39
uint64_t bufEnd
Definition file.h:40
uint64_t bufSize
Definition file.h:38
_file_flags_t flags
Definition file.h:44
mtx_t mtx
Definition file.h:45
uint64_t ungetIndex
Definition file.h:43
int status
Definition file.h:29
uint64_t offset
Definition file.h:28
A doubly linked list.
Definition list.h:51
_PUBLIC int mtx_lock(mtx_t *mtx)
Definition mtx_lock.c:11
_PUBLIC int mtx_init(mtx_t *mtx, int type)
Definition mtx_init.c:10
_PUBLIC int mtx_unlock(mtx_t *mtx)
Definition mtx_unlock.c:10
@ thrd_success
Definition threads.h:74
@ mtx_recursive
Definition threads.h:67
_PUBLIC void mtx_destroy(mtx_t *mtx)
Definition mtx_destroy.c:10