shithub: scc

Download patch

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);
+}