From: Tulio A M Mendes Date: Thu, 12 Feb 2026 03:07:11 +0000 (-0300) Subject: feat: ulibc stdio.h buffered I/O (FILE, fopen/fclose/fread/fwrite/fflush/fgetc/fgets... X-Git-Url: https://projects.tadryanom.me/sitemap.xml?a=commitdiff_plain;h=7600e8fe6861fc7fc74144ed39055b8ebd3ef2b2;p=AdrOS.git feat: ulibc stdio.h buffered I/O (FILE, fopen/fclose/fread/fwrite/fflush/fgetc/fgets/fputc/fputs/fprintf/vfprintf/feof/ferror, stdin/stdout/stderr) --- diff --git a/user/ulibc/include/stdio.h b/user/ulibc/include/stdio.h index b1cddf4..bfeaafd 100644 --- a/user/ulibc/include/stdio.h +++ b/user/ulibc/include/stdio.h @@ -4,6 +4,41 @@ #include #include +#define BUFSIZ 256 +#define EOF (-1) +#define FOPEN_MAX 16 + +#define _STDIO_READ 0x01 +#define _STDIO_WRITE 0x02 +#define _STDIO_EOF 0x04 +#define _STDIO_ERR 0x08 + +typedef struct _FILE { + int fd; + int flags; + char buf[BUFSIZ]; + int buf_pos; + int buf_len; +} FILE; + +extern FILE* stdin; +extern FILE* stdout; +extern FILE* stderr; + +FILE* fopen(const char* path, const char* mode); +int fclose(FILE* fp); +size_t fread(void* ptr, size_t size, size_t nmemb, FILE* fp); +size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* fp); +int fflush(FILE* fp); +int fgetc(FILE* fp); +char* fgets(char* s, int size, FILE* fp); +int fputc(int c, FILE* fp); +int fputs(const char* s, FILE* fp); +int feof(FILE* fp); +int ferror(FILE* fp); +int fprintf(FILE* fp, const char* fmt, ...) __attribute__((format(printf, 2, 3))); +int vfprintf(FILE* fp, const char* fmt, va_list ap); + int putchar(int c); int puts(const char* s); int printf(const char* fmt, ...) __attribute__((format(printf, 1, 2))); diff --git a/user/ulibc/src/stdio.c b/user/ulibc/src/stdio.c index a01bc01..2dbf69f 100644 --- a/user/ulibc/src/stdio.c +++ b/user/ulibc/src/stdio.c @@ -3,6 +3,159 @@ #include "string.h" #include +static FILE _stdin_file = { .fd = 0, .flags = _STDIO_READ }; +static FILE _stdout_file = { .fd = 1, .flags = _STDIO_WRITE }; +static FILE _stderr_file = { .fd = 2, .flags = _STDIO_WRITE }; + +FILE* stdin = &_stdin_file; +FILE* stdout = &_stdout_file; +FILE* stderr = &_stderr_file; + +static FILE _file_pool[FOPEN_MAX]; +static int _file_pool_used[FOPEN_MAX]; + +FILE* fopen(const char* path, const char* mode) { + int flags = 0; + int stdio_flags = 0; + if (mode[0] == 'r') { + flags = 0; /* O_RDONLY */ + stdio_flags = _STDIO_READ; + } else if (mode[0] == 'w') { + flags = 1 | 0x40 | 0x200; /* O_WRONLY | O_CREAT | O_TRUNC */ + stdio_flags = _STDIO_WRITE; + } else if (mode[0] == 'a') { + flags = 1 | 0x40 | 0x400; /* O_WRONLY | O_CREAT | O_APPEND */ + stdio_flags = _STDIO_WRITE; + } else { + return (FILE*)0; + } + int fd = open(path, flags); + if (fd < 0) return (FILE*)0; + for (int i = 0; i < FOPEN_MAX; i++) { + if (!_file_pool_used[i]) { + _file_pool_used[i] = 1; + _file_pool[i].fd = fd; + _file_pool[i].flags = stdio_flags; + _file_pool[i].buf_pos = 0; + _file_pool[i].buf_len = 0; + return &_file_pool[i]; + } + } + close(fd); + return (FILE*)0; +} + +int fflush(FILE* fp) { + if (!fp) return EOF; + if ((fp->flags & _STDIO_WRITE) && fp->buf_pos > 0) { + write(fp->fd, fp->buf, (size_t)fp->buf_pos); + fp->buf_pos = 0; + } + return 0; +} + +int fclose(FILE* fp) { + if (!fp) return EOF; + fflush(fp); + int rc = close(fp->fd); + for (int i = 0; i < FOPEN_MAX; i++) { + if (&_file_pool[i] == fp) { _file_pool_used[i] = 0; break; } + } + return rc; +} + +size_t fread(void* ptr, size_t size, size_t nmemb, FILE* fp) { + if (!fp || !ptr || size == 0 || nmemb == 0) return 0; + size_t total = size * nmemb; + size_t done = 0; + char* dst = (char*)ptr; + while (done < total) { + if (fp->buf_pos >= fp->buf_len) { + int r = read(fp->fd, fp->buf, BUFSIZ); + if (r <= 0) { fp->flags |= _STDIO_EOF; break; } + fp->buf_pos = 0; + fp->buf_len = r; + } + int avail = fp->buf_len - fp->buf_pos; + int want = (int)(total - done); + int chunk = avail < want ? avail : want; + memcpy(dst + done, fp->buf + fp->buf_pos, (size_t)chunk); + fp->buf_pos += chunk; + done += (size_t)chunk; + } + return done / size; +} + +size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* fp) { + if (!fp || !ptr || size == 0 || nmemb == 0) return 0; + size_t total = size * nmemb; + const char* src = (const char*)ptr; + size_t done = 0; + while (done < total) { + int space = BUFSIZ - fp->buf_pos; + int want = (int)(total - done); + int chunk = space < want ? space : want; + memcpy(fp->buf + fp->buf_pos, src + done, (size_t)chunk); + fp->buf_pos += chunk; + done += (size_t)chunk; + if (fp->buf_pos >= BUFSIZ) fflush(fp); + } + return done / size; +} + +int fgetc(FILE* fp) { + unsigned char c; + if (fread(&c, 1, 1, fp) != 1) return EOF; + return (int)c; +} + +char* fgets(char* s, int size, FILE* fp) { + if (!s || size <= 0 || !fp) return (char*)0; + int i = 0; + while (i < size - 1) { + int c = fgetc(fp); + if (c == EOF) { if (i == 0) return (char*)0; break; } + s[i++] = (char)c; + if (c == '\n') break; + } + s[i] = '\0'; + return s; +} + +int fputc(int c, FILE* fp) { + unsigned char ch = (unsigned char)c; + if (fwrite(&ch, 1, 1, fp) != 1) return EOF; + return (int)ch; +} + +int fputs(const char* s, FILE* fp) { + size_t len = strlen(s); + if (fwrite(s, 1, len, fp) != len) return EOF; + return 0; +} + +int feof(FILE* fp) { return fp ? (fp->flags & _STDIO_EOF) : 0; } +int ferror(FILE* fp) { return fp ? (fp->flags & _STDIO_ERR) : 0; } + +int vfprintf(FILE* fp, const char* fmt, va_list ap) { + char buf[1024]; + int n = vsnprintf(buf, sizeof(buf), fmt, ap); + if (n > 0) { + int w = n; + if (w > (int)(sizeof(buf) - 1)) w = (int)(sizeof(buf) - 1); + fwrite(buf, 1, (size_t)w, fp); + } + return n; +} + +int fprintf(FILE* fp, const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + int r = vfprintf(fp, fmt, ap); + va_end(ap); + return r; +} + int putchar(int c) { char ch = (char)c; write(STDOUT_FILENO, &ch, 1);