ref: 258c23680f121b4681340e155a75e072531cc104
parent: f93ac9891008719a6c58f44a5a2b647d2af03284
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sat Dec 9 09:41:24 EST 2017
[lib/c] Add fopen(), fclose() and freopen() This is a preliminar work in these functions and they are not very well tested (you know, it means that I didn't execute them :P)
--- a/lib/c/include/stdio.h
+++ b/lib/c/include/stdio.h
@@ -27,6 +27,7 @@
#define _IOFBF (1 << 7)
#define _IOLBF (1 << 8)
#define _IONBF (1 << 9)
+#define _IOALLOC (1 <<10)
typedef struct {
int fd; /* file descriptor */
@@ -35,7 +36,7 @@
unsigned char *wp; /* write pointer */
unsigned char *lp; /* write pointer used when line-buffering */
size_t len; /* actual length of buffer */
- unsigned char flags;
+ unsigned short flags;
unsigned char unbuf[1]; /* tiny buffer for unbuffered io */
} FILE;
--- a/lib/c/src/Makefile
+++ b/lib/c/src/Makefile
@@ -10,7 +10,7 @@
fputs.o puts.o fread.o fwrite.o \
getc.o putc.o __putc.o __getc.o \
rewind.o fseek.o ferror.o feof.o clearerr.o \
- stdio.o \
+ fclose.o fopen.c freopen.c _fpopen.o stdio.o \
realloc.o calloc.o malloc.o \
assert.o strcpy.o strcmp.o strlen.o strchr.o \
strrchr.o strcat.o strncmp.o strncpy.o strncat.o strcoll.o \
--- /dev/null
+++ b/lib/c/src/_fpopen.c
@@ -1,0 +1,70 @@
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "syscall.h"
+#undef fopen
+
+FILE *
+_fpopen(const char * restrict fname,
+ const char * restrict mode,
+ FILE * restrict fp)
+{
+ int i, flags, fd, rw, bin;
+
+ flags = rw = bin = 0;
+
+ if (mode[0] == '\0)
+ goto einval;
+ if (mode[i = 1] == '+')
+ i++, rw = 1;
+ if (mode[i] == 'b')
+ i++, bin = 1;
+ if (mode[i] != '\0')
+ goto einval;
+
+ switch (mode[0]) {
+ case 'a':
+ flags |= O_APPEND | O_CREAT;
+ goto wrflags;
+ case 'w':
+ flags |= O_TRUNC | O_CREAT;
+ wrflags:
+ flags |= (rw) ? O_RDWR : O_WRONLY;
+ break;
+ case 'r':
+ flags = (rw) ? O_RDWR : O_RDONLY;
+ break;
+ default:
+ einval:
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if ((fd = _open(name, flags)) < 0)
+ return NULL;
+
+ if (fp->buf == NULL) {
+ if ((fp->buf = malloc(BUFSIZ)) == NULL) {
+ close(fd);
+ errno = ENOMEM;
+ return NULL;
+ }
+ fp->flags |= _IOALLOC;
+ }
+ fp->fd = fd;
+
+ if (!bin)
+ fp->flags |= _IOTEXT;
+
+ if (flags & O_RDWR)
+ fp->flags |= _IORW;
+ else if (flags & O_RDONLY)
+ fp->flags |= _IOREAD;
+ else
+ fp->flags |= _IOWRITE;
+
+ fp->lp = fp->rp = fp->wp = NULL;
+
+ return fp;
+}
--- /dev/null
+++ b/lib/c/src/fclose.c
@@ -1,0 +1,31 @@
+
+#include <stdio.h>
+#undef fclose
+
+int
+fclose(FILE *fp)
+{
+ int r = EOF;
+
+ if ((fp->flags & _IOSTRG) == 0 &&
+ fp->flags & (_IOWRITE | _IOREAD | _IOWR)) {
+ r = 0;
+ if (fflush(fp) == EOF)
+ r = EOF;
+ if (close(fp->fd) < 0)
+ r = EOF;
+ }
+
+ if (fp->flags & _IOALLOC) {
+ free(fp->buf);
+ fp->buf = NULL;
+ }
+
+ fp->flags &= ~(_IOWRITE | _IOREAD | _IOWR |
+ _IOERR | _IOEOF |
+ _IOALLOC |
+ _IOTXT |
+ _IOSTRG);
+
+ return r;
+}
--- /dev/null
+++ b/lib/c/src/fopen.c
@@ -1,0 +1,20 @@
+
+#include <errno.h>
+#include <stdio.h>
+#undef fopen
+
+FILE *
+fopen(const char * restrict name, const char * restrict mode)
+{
+ FILE *fp;
+
+ for (fp = __iob; fp < &__iob[FILE_MAX]; ++fp) {
+ if (fp->flags & (_IOREAD | _IOWRITE | _IORW) == 0)
+ break;
+ }
+ if (fp == &__iob[FILE_MAX]) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ return _fpopen(name, mode, fp);
+}
--- /dev/null
+++ b/lib/c/src/freopen.c
@@ -1,0 +1,12 @@
+
+#include <stdio.h>
+#undef freopen
+
+FILE *
+freopen(const char * restrict name, const char * restrict mode,
+ FILE * restrict fp)
+{
+ if (fclose(fp) == EOF)
+ return NULL;
+ return _fpopen(name, mode, fp);
+}