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 
uint32_t mode
Режим работы (0 - Обычный | 1 - Режим логирования)
Definition: bootscreen.c:23
size_t strlen(const char *str)
Возращает длину строки
Definition: string.c:88
void * memcpy(void *restrict destination, const void *restrict source, size_t n)
Копирование непересекающихся массивов используя SSE.
Definition: string.c:173
void perror(FILE *stream, char *s)
Выводит на экран ошибку с пользовательским сообщением
Definition: stdio.c:133
ssize_t fseek(FILE *stream, ssize_t offset, uint8_t whence)
Установка позиции в потоке данных относительно текущей позиции
Definition: stdio.c:315
void fclose(FILE *stream)
Закончить работу с файлом
Definition: stdio.c:213
uint32_t fmodecheck(const char *mode)
Получение режима работы (маски файла)
Definition: stdio.c:28
size_t fwrite(FILE *stream, size_t size, size_t count, const void *ptr)
Запись файла
Definition: stdio.c:381
void fcheckerror(FILE *stream)
Проверка файла на наличие ошибок при работе
Definition: stdio.c:98
uint32_t ferror(FILE *stream)
Получение кода ошибки
Definition: stdio.c:123
void rewind(FILE *stream)
Установка позиции потока в самое начало
Definition: stdio.c:362
FILE * fopen(const char *filename, const char *_mode)
Открывает файл
Definition: stdio.c:166
int ftell(FILE *stream)
Текущая позиция считывания в файле
Definition: stdio.c:287
int fsize(FILE *stream)
Получение размера файла в байтах
Definition: stdio.c:227
int fread(FILE *stream, size_t count, size_t size, void *buffer)
Чтение файла
Definition: stdio.c:250
Структура файла. Требуется для работы с VFS.
Definition: stdio.h:21