SayoriOS 0.3.3

stdio.c
См. документацию.
1
10 #include "io/ports.h"
11 #include "mem/vmm.h"
12 #include <lib/stdio.h>
13 #include <fs/fsm.h>
14 #include <fs/nvfs.h>
15 #include <io/tty.h>
16
17 bool stdio_debug = true;
18
19
28 uint32_t fmodecheck(const char* mode){
29 ON_NULLPTR(mode, {
30 qemu_log("Mode is nullptr!");
31 return 0;
32 });
33
34 uint32_t fmode = 0;
35 if (mode[0] == 'w') {
36 if (mode[1] == 'x') { // wx
37 fmode = O_WRITE | O_CREATE;
38 } else if (mode[1] == 'b') {
39 if (mode[2] == 'x') { // wbx
40 fmode = O_WRITE | O_CREATE;
41 } else if (mode[2] == '+') {
42 if (mode[3] == 'x') { // wb+x
43 fmode = O_WRITE | O_READ | O_CREATE;
44 } else { // wb+
45 fmode = O_WRITE | O_READ | O_CREATE | O_TRUNC;
46 }
47 } else { // wb
48 fmode = O_WRITE | O_CREATE | O_TRUNC;
49 }
50 } else if (mode[1] == '+') {
51 if (mode[2] == 'x') { // w+x
52 fmode = O_WRITE | O_READ | O_CREATE;
53 } else if (mode[2] == 'b') {
54 if (mode[3] == 'x') { // w+bx
55 fmode = O_WRITE | O_READ | O_CREATE;
56 } else { // w+b
57 fmode = O_WRITE | O_READ | O_CREATE | O_TRUNC;
58 }
59 } else { // w+
60 fmode = O_WRITE | O_READ | O_CREATE | O_TRUNC;
61 }
62 } else { // w
63 fmode = O_WRITE | O_CREATE | O_TRUNC;
64 }
65 } else if (mode[0] == 'r') {
66 if (mode[1] == 'b') {
67 if (mode[2] == '+') { // rb+
68 fmode = O_READ | O_WRITE;
69 } else { // rb
70 fmode = O_READ;
71 }
72 } else if (mode[1] == '+') { // r+ r+b
73 fmode = O_READ | O_WRITE;
74 } else { // r
75 fmode = O_READ;
76 }
77 } else if (mode[0] == 'a') {
78 if (mode[1] == 'b') {
79 if (mode[2] == '+') { // ab+
80 fmode = O_WRITE | O_READ | O_APPEND | O_CREATE;
81 } else { // ab
82 fmode = O_WRITE | O_APPEND | O_CREATE;
83 }
84 } else if (mode[1] == '+') { // a+ a+b
85 fmode = O_WRITE | O_READ | O_APPEND | O_CREATE;
86 } else { // a
87 fmode = O_WRITE | O_APPEND | O_CREATE;
88 }
89 }
90 return fmode;
91 }
92
98 void fcheckerror(FILE* stream){
99 ON_NULLPTR(stream, {
100 qemu_log("stream is nullptr!");
101 return;
102 });
103
104 FSM_FILE finfo = nvfs_info(stream->path);
105 if (finfo.Ready == 0){
106 stream->err = STDIO_ERR_NO_FOUND;
107 } else if (stream->fmode == 0){
108 stream->err = STDIO_ERR_MODE_ERROR;
109 } else if (stream->size <= 0){
110 stream->err = STDIO_ERR_SIZE;
111 } else if (stream->open == 0){
112 stream->err = STDIO_ERR_NO_OPEN;
113 }
114 }
115
123 uint32_t ferror(FILE* stream){
124 return stream->err;
125 }
126
133 void perror(FILE* stream,char* s){
134 switch(stream->err){
135 case STDIO_ERR_NO_FOUND:{
136 tty_printf("%s: %s\n",s, "File no found");
137 break;
138 }
139 case STDIO_ERR_MODE_ERROR:{
140 tty_printf("%s: %s\n",s, "Unknown operating mode");
141 break;
142 }
143 case STDIO_ERR_SIZE:{
144 tty_printf("%s: %s\n",s, "The file size has a non-standard value.");
145 break;
146 }
147 case STDIO_ERR_NO_OPEN:{
148 tty_printf("%s: %s\n",s, "The file has not been opened for work.");
149 break;
150 }
151 default: {
152 tty_printf("%s: %s\n",s, "Unknown");
153 break;
154 }
155 }
156 }
157
166 FILE* fopen(const char* filename, const char* _mode){
167 uint32_t freal_mode = fmodecheck(_mode);
168
169 return fopen_binmode(filename, freal_mode);
170 }
171
172 FILE* fopen_binmode(const char* filename, size_t mode) {
173 ON_NULLPTR(filename, {
174 qemu_log("Filename is nullptr!");
175 return NULL;
176 });
177
178 qemu_log("Open file");
179 qemu_log("|- Name: '%s'", filename);
180 qemu_log("|- Mode: '%x'", mode);
181
182 FILE* file = kcalloc(sizeof(FILE), 1);
183 // Получаем тип открытого файла
184 FSM_FILE finfo = nvfs_info(filename);
185 if (finfo.Ready == 0 || mode == 0) {
186 //kfree(file);
187 qemu_err("Failed to open file: %s (Exists: %d; FMODE: %d)",
188 filename,
189 finfo.Ready,
190 mode);
191 return 0;
192 }
193
194 file->open = 1; // Файл успешно открыт
195 file->fmode = mode; // Режим работы с файлом
196 file->size = finfo.Size; // Размер файла
197 file->path = kcalloc(strlen(filename) + 1, 1); // Полный путь к файлу
198 file->pos = 0; // Установка указателя в самое начало
199 file->err = 0; // Ошибок в работе нет
200
201 memcpy(file->path, filename, strlen(filename));
202
203 qemu_ok("File opened!");
204
205 return file;
206 }
207
213 void fclose(FILE* stream){
214 if(stream) {
215 kfree(stream->path);
216 kfree(stream);
217 }
218 }
219
227 int fsize(FILE* stream){
228 ON_NULLPTR(stream, {
229 return -1;
230 });
231
232 if (!stream->open || stream->size <= 0 || stream->fmode == 0){
233 fcheckerror(stream);
234 return -1;
235 } else {
236 return stream->size;
237 }
238 }
239
250 int fread(FILE* stream, size_t count, size_t size, void* buffer){
251 ON_NULLPTR(stream, {
252 return -1;
253 });
254
255 ON_NULLPTR(buffer, {
256 return -1;
257 });
258
259 if (stdio_debug) {
260 qemu_log("Params '%s': count=%d, size=%d, toread=%d, seek=%d", stream->path, count, size, count*size, stream->pos);
261 }
262
263 FSM_FILE finfo = nvfs_info(stream->path);
264
265 if (!stream->open || finfo.Ready == 0 || stream->size <= 0 || stream->fmode == 0){
266 // Удалось ли открыть файл, существует ли файл, размер файла больше нуля и указан правильный режим для работы с файлом
267 fcheckerror(stream);
268 return -1;
269 }
270
271 size_t res = nvfs_read(stream->path, stream->pos, size*count, buffer);
272
273 if(res > 0) {
274 stream->pos += size*count;
275 }
276
277 return res;
278 }
279
287 int ftell(FILE* stream) {
288 ON_NULLPTR(stream, {
289 return -1;
290 });
291
292 if (!stream->open
293 || stream->size < 0
294 || stream->fmode == 0
295 ) {
296 qemu_err("ftell(): invalid stream (open: %d; size: %d; mode: %x)", stream->open, stream->size, stream->fmode);
297 fcheckerror(stream);
298 return -1;
299 }
300
301 qemu_warn("Position is: %d", stream->pos);
302
303 return (int)stream->pos;
304 }
305
315 ssize_t fseek(FILE* stream, ssize_t offset, uint8_t whence){
316 qemu_log("fseek() call\n");
317 ON_NULLPTR(stream, {
318 return -1;
319 });
320
321 qemu_log("Stream is not null");
322 if (!stream->open || stream->size == 0 || stream->fmode == 0){
323 fcheckerror(stream);
324 qemu_err("Seek error: Open: %d; Size: %d; Mode: %x", stream->open, stream->size, stream->fmode);
325 return -1;
326 }
327 qemu_log("Stream is valid");
328
329 size_t lsk = 0;
330
331 if (whence == SEEK_CUR) {
332 lsk = stream->pos;
333 } else if (whence == SEEK_END) {
334 lsk = stream->size;
335 } else if (whence == SEEK_SET) {
336 //lsk = 0;
337 if(offset >= 0 && offset <= stream->size) {
338 stream->pos = offset;
339 qemu_log("Whence = SET; Value = %d", offset);
340 return 0;
341 } else {
342 qemu_err("Invalid offset (whence = 0x0): %x", offset);
343 }
344 } else {
345 qemu_err("Invalid whence: %d", whence);
346 return -1;
347 }
348
349 qemu_warn("Offset: %d; Shifting by: %d; Whence = %x", offset, lsk, whence);
350 if (lsk + offset > 0 && stream->size >= lsk+offset){
351 stream->pos = lsk + offset;
352 }
353
354 return 0;
355 }
356
362 void rewind(FILE* stream){
363 ON_NULLPTR(stream, {
364 return;
365 });
366
367 if (!stream->open || stream->size <= 0 || stream->fmode == 0){
368 fcheckerror(stream);
369 }
370 stream->pos = 0;
371 }
372
381 size_t fwrite(FILE *stream, size_t size, size_t count, const void *ptr) {
382 ON_NULLPTR(stream, {
383 qemu_log("stream is nullptr!");
384 return 0;
385 });
386
387 // FSM_FILE finfo = nvfs_info(stream->path);
388
389 if(stream->pos + (size * count) > stream->size) {
390 qemu_warn("Out of bounds write!");
391
392 // TODO: Filesystem should handle this situation and allocate needed space.
393
394 // WARNING: Workaround
395 stream->size = stream->pos + (size * count);
396 }
397
398 size_t res = nvfs_write(stream->path, stream->pos, size*count, ptr);
399
400 if(res > 0)
401 stream->pos += size*count;
402
403 return -1;
404 }
405
406
mode
uint32_t mode
Режим работы (0 - Обычный | 1 - Режим логирования)
Definition: bootscreen.c:23
strlen
size_t strlen(const char *str)
Возращает длину строки
Definition: string.c:88
memcpy
void * memcpy(void *restrict destination, const void *restrict source, size_t n)
Копирование непересекающихся массивов используя SSE.
Definition: string.c:173
perror
void perror(FILE *stream, char *s)
Выводит на экран ошибку с пользовательским сообщением
Definition: stdio.c:133
fseek
ssize_t fseek(FILE *stream, ssize_t offset, uint8_t whence)
Установка позиции в потоке данных относительно текущей позиции
Definition: stdio.c:315
fclose
void fclose(FILE *stream)
Закончить работу с файлом
Definition: stdio.c:213
fmodecheck
uint32_t fmodecheck(const char *mode)
Получение режима работы (маски файла)
Definition: stdio.c:28
fwrite
size_t fwrite(FILE *stream, size_t size, size_t count, const void *ptr)
Запись файла
Definition: stdio.c:381
fcheckerror
void fcheckerror(FILE *stream)
Проверка файла на наличие ошибок при работе
Definition: stdio.c:98
ferror
uint32_t ferror(FILE *stream)
Получение кода ошибки
Definition: stdio.c:123
rewind
void rewind(FILE *stream)
Установка позиции потока в самое начало
Definition: stdio.c:362
fopen
FILE * fopen(const char *filename, const char *_mode)
Открывает файл
Definition: stdio.c:166
ftell
int ftell(FILE *stream)
Текущая позиция считывания в файле
Definition: stdio.c:287
fsize
int fsize(FILE *stream)
Получение размера файла в байтах
Definition: stdio.c:227
fread
int fread(FILE *stream, size_t count, size_t size, void *buffer)
Чтение файла
Definition: stdio.c:250
FILE
Структура файла. Требуется для работы с VFS.
Definition: stdio.h:21