aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2012-05-10 15:02:16 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2012-05-10 15:02:16 -0700
commit54c51a9c23876b292231608d01b85ebbb2cc976c (patch)
tree7191c5ee0b33dc27764946c7bbb11a2f0098888e
parent26cebd536042c9ec00eb5cc44c83bd2079751426 (diff)
downloadklibc-54c51a9c23876b292231608d01b85ebbb2cc976c.tar.gz
[klibc] Restructure the FILE object to allow simple inlines
Restructure the FILE object so that functions which are simple accessors for the FILE object contents can get it from there, without unnecessarily exposing the internals. Furthermore, allocate the buffer and the file object in the same allocation; no need to have extra mallocs() for no reason. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--usr/include/stddef.h8
-rw-r--r--usr/include/stdio.h92
-rw-r--r--usr/klibc/Kbuild5
-rw-r--r--usr/klibc/fread2.c2
-rw-r--r--usr/klibc/fwrite2.c2
-rw-r--r--usr/klibc/stdio/fclose.c9
-rw-r--r--usr/klibc/stdio/feof.c5
-rw-r--r--usr/klibc/stdio/ferror.c5
-rw-r--r--usr/klibc/stdio/fflush.c44
-rw-r--r--usr/klibc/stdio/fileno.c5
-rw-r--r--usr/klibc/stdio/fread.c28
-rw-r--r--usr/klibc/stdio/fseek.c20
-rw-r--r--usr/klibc/stdio/ftell.c3
-rw-r--r--usr/klibc/stdio/fwrite.c42
-rw-r--r--usr/klibc/stdio/fxopen.c68
-rw-r--r--usr/klibc/stdio/openmode.c39
-rw-r--r--usr/klibc/stdio/stdioint.h22
-rw-r--r--usr/klibc/stdio/ungetc.c9
18 files changed, 247 insertions, 161 deletions
diff --git a/usr/include/stddef.h b/usr/include/stddef.h
index f1529a421cd26..338b0dd0ef7ef 100644
--- a/usr/include/stddef.h
+++ b/usr/include/stddef.h
@@ -21,4 +21,12 @@
#undef offsetof
#define offsetof(t,m) ((size_t)&((t *)0)->m)
+/*
+ * The container_of construct: if p is a pointer to member m of
+ * container class c, then return a pointer to the container of which
+ * *p is a member.
+ */
+#undef container_of
+#define container_of(p, c, m) ((c *)((char *)(p) - offsetof(c,m)))
+
#endif /* _STDDEF_H */
diff --git a/usr/include/stdio.h b/usr/include/stdio.h
index 17f93c43a1d4d..44f38a798a0ee 100644
--- a/usr/include/stdio.h
+++ b/usr/include/stdio.h
@@ -11,7 +11,12 @@
#include <stddef.h>
#include <unistd.h>
-struct _IO_file;
+struct _IO_file {
+ off_t _io_filepos; /* File position */
+ int _io_fileno; /* Underlying file descriptor */
+ _Bool _io_eof; /* End of file flag */
+ _Bool _io_error; /* Error flag */
+};
typedef struct _IO_file FILE;
#ifndef EOF
@@ -26,17 +31,24 @@ typedef struct _IO_file FILE;
#define SEEK_CUR 1
#define SEEK_END 2
+enum _IO_bufmode {
+ _IONBF,
+ _IOLBF,
+ _IOFBF
+};
+#define _IONBF _IONBF
+#define _IOLBF _IOLBF
+#define _IOFBF _IOFBF
+
/*
* Convert between a FILE * and a file descriptor.
*/
__extern FILE *stdin, *stdout, *stderr;
-__extern int fileno(FILE *);
__extern FILE *fopen(const char *, const char *);
__extern FILE *fdopen(int, const char *);
__extern int fclose(FILE *);
__extern int fseek(FILE *, off_t, int);
-__extern off_t ftell(FILE * __f);
__extern int fputs(const char *, FILE *);
__extern int puts(const char *);
__extern int fputc(int, FILE *);
@@ -51,23 +63,6 @@ __extern int getc_unlocked(FILE *);
#define getchar() fgetc(stdin)
__extern int ungetc(int, FILE *);
-__extern size_t _fread(void *, size_t, FILE *);
-__extern size_t _fwrite(const void *, size_t, FILE *);
-
-#ifndef __NO_FREAD_FWRITE_INLINES
-__extern_inline size_t
-fread(void *__p, size_t __s, size_t __n, FILE * __f)
-{
- return _fread(__p, __s * __n, __f) / __s;
-}
-
-__extern_inline size_t
-fwrite(const void *__p, size_t __s, size_t __n, FILE * __f)
-{
- return _fwrite(__p, __s * __n, __f) / __s;
-}
-#endif
-
__extern int printf(const char *, ...);
__extern int vprintf(const char *, va_list);
__extern int fprintf(FILE *, const char *, ...);
@@ -79,10 +74,6 @@ __extern int vsnprintf(char *, size_t n, const char *, va_list);
__extern int asprintf(char **, const char *, ...);
__extern int vasprintf(char **, const char *, va_list);
-__extern int ferror(FILE * );
-__extern int feof(FILE *);
-__extern int fflush(FILE *);
-
__extern int sscanf(const char *, const char *, ...);
__extern int vsscanf(const char *, const char *, va_list);
@@ -93,4 +84,57 @@ __extern int renameat(int, const char *, int, const char *);
__extern int remove(const char *);
+__extern size_t _fread(void *, size_t, FILE *);
+__extern size_t _fwrite(const void *, size_t, FILE *);
+__extern int fflush(FILE *);
+
+__extern size_t fread(void *, size_t, size_t, FILE *);
+__extern size_t fwrite(const void *, size_t, size_t, FILE *);
+
+__extern off_t ftell(FILE *__f);
+
+__extern int ferror(FILE * );
+__extern int feof(FILE *);
+__extern int fileno(FILE *);
+
+#ifndef __NO_STDIO_INLINES
+__extern_inline size_t
+fread(void *__p, size_t __s, size_t __n, FILE * __f)
+{
+ return _fread(__p, __s * __n, __f) / __s;
+}
+
+__extern_inline size_t
+fwrite(const void *__p, size_t __s, size_t __n, FILE * __f)
+{
+ return _fwrite(__p, __s * __n, __f) / __s;
+}
+
+__extern_inline off_t ftell(FILE *__f)
+{
+ return __f->_io_filepos;
+}
+
+__extern_inline int fileno(FILE *__f)
+{
+ return __f->_io_fileno;
+}
+
+__extern_inline int ferror(FILE *__f)
+{
+ return __f->_io_error;
+}
+
+__extern_inline int feof(FILE *__f)
+{
+ return __f->_io_eof;
+}
+
+__extern_inline void clearerr(FILE *__f)
+{
+ __f->_io_error = 0;
+ __f->_io_eof = 0;
+}
+#endif
+
#endif /* _STDIO_H */
diff --git a/usr/klibc/Kbuild b/usr/klibc/Kbuild
index ac1ce9e149031..96ff76aefa187 100644
--- a/usr/klibc/Kbuild
+++ b/usr/klibc/Kbuild
@@ -27,7 +27,7 @@ klib-y := vsnprintf.o snprintf.o vsprintf.o sprintf.o \
siglongjmp.o \
sigaction.o sigpending.o sigprocmask.o sigsuspend.o \
pselect.o ppoll.o \
- brk.o sbrk.o malloc.o realloc.o calloc.o \
+ brk.o sbrk.o malloc.o realloc.o zalloc.o calloc.o \
mmap.o shm_open.o shm_unlink.o \
memcpy.o memcmp.o memset.o memccpy.o memmem.o memswap.o \
memmove.o memchr.o memrchr.o bzero.o \
@@ -58,7 +58,8 @@ klib-y := vsnprintf.o snprintf.o vsprintf.o sprintf.o \
userdb/getgrgid.o userdb/getgrnam.o userdb/getpwnam.o \
userdb/getpwuid.o userdb/root_group.o userdb/root_user.o \
setmntent.o endmntent.o getmntent.o \
- stdio/fclose.o stdio/fopen.o stdio/fdopen.o stdio/fxopen.o \
+ stdio/fclose.o stdio/fopen.o stdio/fdopen.o \
+ stdio/openmode.o stdio/fxopen.o \
stdio/fread.o stdio/fwrite.o stdio/fflush.o \
stdio/fseek.o stdio/ftell.o stdio/fileno.o \
stdio/ungetc.o stdio/feof.o stdio/ferror.o
diff --git a/usr/klibc/fread2.c b/usr/klibc/fread2.c
index c9c6ed87c4dd4..7dca56b163313 100644
--- a/usr/klibc/fread2.c
+++ b/usr/klibc/fread2.c
@@ -4,7 +4,7 @@
* The actual fread() function as a non-inline
*/
-#define __NO_FREAD_FWRITE_INLINES
+#define __NO_STDIO_INLINES
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE * f)
diff --git a/usr/klibc/fwrite2.c b/usr/klibc/fwrite2.c
index b5ab0a45c1d19..cebc017c68b66 100644
--- a/usr/klibc/fwrite2.c
+++ b/usr/klibc/fwrite2.c
@@ -4,7 +4,7 @@
* The actual fwrite() function as a non-inline
*/
-#define __NO_FREAD_FWRITE_INLINES
+#define __NO_STDIO_INLINES
#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE * f)
diff --git a/usr/klibc/stdio/fclose.c b/usr/klibc/stdio/fclose.c
index 682385ebe29b9..288b1b8c66bb0 100644
--- a/usr/klibc/stdio/fclose.c
+++ b/usr/klibc/stdio/fclose.c
@@ -4,20 +4,19 @@
#include "stdioint.h"
-int fclose(FILE *f)
+int fclose(FILE *file)
{
+ struct _IO_file_pvt *f = stdio_pvt(file);
int rv;
- fflush(f);
+ fflush(file);
- rv = close(f->fd);
+ rv = close(f->pub._io_fileno);
/* Remove from linked list */
f->next->prev = f->prev;
f->prev->next = f->next;
- free(f->buf);
free(f);
-
return rv;
}
diff --git a/usr/klibc/stdio/feof.c b/usr/klibc/stdio/feof.c
index 23bf29fe3bdb1..6762c08e25366 100644
--- a/usr/klibc/stdio/feof.c
+++ b/usr/klibc/stdio/feof.c
@@ -1,6 +1,7 @@
+#define __NO_STDIO_INLINES
#include "stdioint.h"
-int feof(FILE *f)
+int feof(FILE *__f)
{
- return !!(f->flags & _IO_FILE_FLAG_EOF);
+ return __f->_io_eof;
}
diff --git a/usr/klibc/stdio/ferror.c b/usr/klibc/stdio/ferror.c
index 8fc6bb01e29aa..6b4502abc7758 100644
--- a/usr/klibc/stdio/ferror.c
+++ b/usr/klibc/stdio/ferror.c
@@ -1,6 +1,7 @@
+#define __NO_STDIO_INLINES
#include "stdioint.h"
-int ferror(FILE *f)
+int ferror(FILE *__f)
{
- return !!(f->flags & _IO_FILE_FLAG_ERR);
+ return __f->_io_error;
}
diff --git a/usr/klibc/stdio/fflush.c b/usr/klibc/stdio/fflush.c
index 8c78be4720eec..cade1f2a1028e 100644
--- a/usr/klibc/stdio/fflush.c
+++ b/usr/klibc/stdio/fflush.c
@@ -4,42 +4,50 @@
#include "stdioint.h"
-int fflush(FILE *f)
+int __fflush(struct _IO_file_pvt *f)
{
ssize_t rv;
char *p;
- if (!f) {
- int err = 0;
-
- for (f = __stdio_headnode.next; f != &__stdio_headnode;
- f = f->next)
- err |= fflush(f);
- return err;
- }
-
- if (!(f->flags & _IO_FILE_FLAG_WRITE))
+ if (!f->obytes)
return 0;
p = f->buf;
- while (f->bytes) {
- rv = write(f->fd, p, f->bytes);
+ while (f->obytes) {
+ rv = write(f->pub._io_fileno, p, f->obytes);
if (rv == -1) {
if (errno == EINTR || errno == EAGAIN)
continue;
- f->flags |= _IO_FILE_FLAG_ERR;
+ f->pub._io_error = true;
return EOF;
} else if (rv == 0) {
/* EOF on output? */
- f->flags |= _IO_FILE_FLAG_EOF;
+ f->pub._io_eof = true;
return EOF;
}
p += rv;
- f->bytes -= rv;
+ f->obytes -= rv;
}
- f->data = f->buf + _IO_UNGET_SLOP;
- f->flags &= ~_IO_FILE_FLAG_WRITE;
return 0;
}
+
+int fflush(FILE *file)
+{
+ struct _IO_file_pvt *f;
+
+ if (__likely(file)) {
+ f = stdio_pvt(file);
+ return __fflush(f);
+ } else {
+ int err = 0;
+
+ for (f = __stdio_headnode.next; f != &__stdio_headnode;
+ f = f->next)
+ err |= __fflush(f);
+ return err;
+ }
+}
+
+
diff --git a/usr/klibc/stdio/fileno.c b/usr/klibc/stdio/fileno.c
index f44ecf463c2e8..2750f2eb6c562 100644
--- a/usr/klibc/stdio/fileno.c
+++ b/usr/klibc/stdio/fileno.c
@@ -1,6 +1,7 @@
+#define __NO_STDIO_INLINES
#include "stdioint.h"
-int fileno(FILE *f)
+int fileno(FILE *__f)
{
- return f->fd;
+ return __f->_io_fileno;
}
diff --git a/usr/klibc/stdio/fread.c b/usr/klibc/stdio/fread.c
index dd27891cfe991..1cb8a0c4d8aa6 100644
--- a/usr/klibc/stdio/fread.c
+++ b/usr/klibc/stdio/fread.c
@@ -6,8 +6,9 @@
#include <string.h>
#include "stdioint.h"
-size_t _fread(void *buf, size_t count, FILE *f)
+size_t _fread(void *buf, size_t count, FILE *file)
{
+ struct _IO_file_pvt *f = stdio_pvt(file);
size_t bytes = 0;
size_t nb;
char *p = buf;
@@ -18,11 +19,11 @@ size_t _fread(void *buf, size_t count, FILE *f)
if (!count)
return 0;
- if (f->flags & _IO_FILE_FLAG_WRITE)
- fflush(f);
+ if (f->obytes) /* User error! */
+ __fflush(f);
while (count) {
- while (f->bytes == 0) {
+ while (f->ibytes == 0) {
/*
* The buffer is empty, we have to read
*/
@@ -36,14 +37,14 @@ size_t _fread(void *buf, size_t count, FILE *f)
nb = f->bufsiz;
}
- rv = read(f->fd, rdptr, nb);
+ rv = read(f->pub._io_fileno, rdptr, nb);
if (rv == -1) {
if (errno == EINTR || errno == EAGAIN)
continue;
- f->flags |= _IO_FILE_FLAG_ERR;
+ f->pub._io_error = true;
return bytes;
} else if (rv == 0) {
- f->flags |= _IO_FILE_FLAG_EOF;
+ f->pub._io_eof = true;
return bytes;
@@ -53,11 +54,10 @@ size_t _fread(void *buf, size_t count, FILE *f)
p += rv;
bytes += rv;
count -= rv;
- f->filepos += rv;
+ f->pub._io_filepos += rv;
} else {
- f->bytes = rv;
+ f->ibytes = rv;
f->data = rdptr;
- f->flags |= _IO_FILE_FLAG_READ;
}
if (!count)
@@ -65,7 +65,7 @@ size_t _fread(void *buf, size_t count, FILE *f)
}
/* If we get here, the buffer is non-empty */
- nb = f->bytes;
+ nb = f->ibytes;
nb = (count < nb) ? count : nb;
if (nb) {
memcpy(p, f->data, nb);
@@ -73,10 +73,8 @@ size_t _fread(void *buf, size_t count, FILE *f)
bytes += nb;
count -= nb;
f->data += nb;
- f->bytes -= nb;
- f->filepos += nb;
- if (!f->bytes)
- f->flags &= ~_IO_FILE_FLAG_READ;
+ f->ibytes -= nb;
+ f->pub._io_filepos += nb;
}
}
return bytes;
diff --git a/usr/klibc/stdio/fseek.c b/usr/klibc/stdio/fseek.c
index 1a2ced3eb4bd7..b437b346ac160 100644
--- a/usr/klibc/stdio/fseek.c
+++ b/usr/klibc/stdio/fseek.c
@@ -4,17 +4,25 @@
#include "stdioint.h"
-__extern int fseek(FILE *f, off_t where, int whence)
+__extern int fseek(FILE *file, off_t where, int whence)
{
+ struct _IO_file_pvt *f = stdio_pvt(file);
off_t rv;
- fflush(f);
+ if (f->obytes)
+ __fflush(f);
- rv = lseek(f->fd, where, whence);
+ if (whence == SEEK_CUR) {
+ where += f->pub._io_filepos;
+ whence = SEEK_SET;
+ }
+
+ rv = lseek(f->pub._io_fileno, where, whence);
if (rv != -1) {
- f->filepos = rv;
- f->bytes = 0;
- f->flags &= ~_IO_FILE_FLAG_READ;
+ f->pub._io_filepos = rv;
+ f->ibytes = 0;
+ f->obytes = 0;
+ f->data = f->buf + _IO_UNGET_SLOP;
return 0;
} else {
return -1;
diff --git a/usr/klibc/stdio/ftell.c b/usr/klibc/stdio/ftell.c
index 72cb5690e93ff..2dba32d48a056 100644
--- a/usr/klibc/stdio/ftell.c
+++ b/usr/klibc/stdio/ftell.c
@@ -1,6 +1,7 @@
+#define __NO_STDIO_INLINES
#include "stdioint.h"
off_t ftell(FILE *f)
{
- return f->filepos;
+ return f->_io_filepos;
}
diff --git a/usr/klibc/stdio/fwrite.c b/usr/klibc/stdio/fwrite.c
index 96dbd09a52f09..1782b97b5e145 100644
--- a/usr/klibc/stdio/fwrite.c
+++ b/usr/klibc/stdio/fwrite.c
@@ -5,7 +5,8 @@
#include <string.h>
#include "stdioint.h"
-static size_t fwrite_noflush(const void *buf, size_t count, FILE *f)
+static size_t fwrite_noflush(const void *buf, size_t count,
+ struct _IO_file_pvt *f)
{
size_t bytes = 0;
size_t nb;
@@ -13,53 +14,53 @@ static size_t fwrite_noflush(const void *buf, size_t count, FILE *f)
ssize_t rv;
while (count) {
- if (f->bytes == 0 && count >= f->bufsiz) {
+ if (f->obytes == 0 && count >= f->bufsiz) {
/*
* The buffer is empty and the write is large,
* so bypass the buffering entirely.
*/
- rv = write(f->fd, p, count);
+ rv = write(f->pub._io_fileno, p, count);
if (rv == -1) {
if (errno == EINTR || errno == EAGAIN)
continue;
- f->flags |= _IO_FILE_FLAG_ERR;
+ f->pub._io_error = true;
break;
} else if (rv == 0) {
/* EOF on output? */
- f->flags |= _IO_FILE_FLAG_EOF;
+ f->pub._io_eof = true;
break;
}
p += rv;
bytes += rv;
count -= rv;
- f->filepos += rv;
+ f->pub._io_filepos += rv;
} else {
- nb = f->bufsiz - f->bytes;
+ nb = f->bufsiz - f->obytes;
nb = (count < nb) ? count : nb;
if (nb) {
- memcpy(f->buf+f->bytes, p, nb);
+ memcpy(f->buf+f->obytes, p, nb);
p += nb;
- f->bytes += nb;
+ f->obytes += nb;
count -= nb;
bytes += nb;
- f->filepos += nb;
- f->flags |= _IO_FILE_FLAG_WRITE;
+ f->pub._io_filepos += nb;
}
if (!count)
break; /* Done... */
/* If we get here, the buffer must be full */
- if (fflush(f))
+ if (__fflush(f))
break;
}
}
return bytes;
}
-size_t _fwrite(const void *buf, size_t count, FILE *f)
+size_t _fwrite(const void *buf, size_t count, FILE *file)
{
+ struct _IO_file_pvt *f = stdio_pvt(file);
size_t bytes = 0;
size_t pf_len, pu_len;
const char *p = buf;
@@ -68,10 +69,13 @@ size_t _fwrite(const void *buf, size_t count, FILE *f)
and unflushed (pu) depending on buffering mode
and contents. */
- if (f->flags & _IO_FILE_FLAG_UNBUF) {
+ switch (f->bufmode) {
+ case _IONBF:
pf_len = 0;
pu_len = count;
- } else if (f->flags & _IO_FILE_FLAG_LINE_BUF) {
+ break;
+
+ case _IOLBF:
pf_len = count;
pu_len = 0;
@@ -79,15 +83,19 @@ size_t _fwrite(const void *buf, size_t count, FILE *f)
pf_len--;
pu_len++;
}
- } else {
+ break;
+
+ case _IOFBF:
+ default:
pf_len = 0;
pu_len = count;
+ break;
}
if (pf_len) {
bytes = fwrite_noflush(p, pf_len, f);
p += bytes;
- if (fflush(f) || bytes != pf_len)
+ if (__fflush(f) || bytes != pf_len)
return bytes;
}
diff --git a/usr/klibc/stdio/fxopen.c b/usr/klibc/stdio/fxopen.c
index 7e8608ffc5062..dcc45f11e9424 100644
--- a/usr/klibc/stdio/fxopen.c
+++ b/usr/klibc/stdio/fxopen.c
@@ -9,63 +9,29 @@
FILE *stdin, *stdout, *stderr;
/* Doubly-linked list of all stdio structures */
-struct _IO_file __stdio_headnode =
+struct _IO_file_pvt __stdio_headnode =
{
.prev = &__stdio_headnode,
.next = &__stdio_headnode,
};
-int __parse_open_mode(const char *mode)
+FILE *__fxopen(int fd, int flags, bool close_on_err)
{
- int rwflags = O_RDONLY;
- int crflags = 0;
- int eflag = 0;
+ struct _IO_file_pvt *f;
+ const size_t bufoffs =
+ (sizeof *f + 4*sizeof(void *) - 1) &
+ ~(4*sizeof(void *) - 1);
- while (*mode) {
- switch (*mode++) {
- case 'r':
- rwflags = O_RDONLY;
- crflags = 0;
- break;
- case 'w':
- rwflags = O_WRONLY;
- crflags = O_CREAT | O_TRUNC;
- break;
- case 'a':
- rwflags = O_WRONLY;
- crflags = O_CREAT | O_APPEND;
- break;
- case 'e':
- eflag = O_CLOEXEC;
- break;
- case '+':
- rwflags = O_RDWR;
- break;
- }
- }
-
- return rwflags | crflags | eflag;
-}
-
-FILE *__fxopen(int fd, int flags, int close_on_err)
-{
- FILE *f = NULL;
-
- f = malloc(sizeof *f);
+ f = zalloc(bufoffs + BUFSIZ + _IO_UNGET_SLOP);
if (!f)
goto err;
- f->fd = fd;
- f->filepos = lseek(fd, 0, SEEK_CUR);
-
- f->buf = malloc(BUFSIZ + _IO_UNGET_SLOP);
- if (!f->buf)
- goto err;
-
+ f->data = f->buf = (char *)f + bufoffs;
+ f->pub._io_fileno = fd;
+ f->pub._io_filepos = lseek(fd, 0, SEEK_CUR);
f->bufsiz = BUFSIZ;
f->data = f->buf + _IO_UNGET_SLOP;
- f->bytes = 0; /* No data in buffer */
- f->flags = isatty(fd) ? _IO_FILE_FLAG_LINE_BUF : 0;
+ f->bufmode = isatty(fd) ? _IOLBF : _IONBF;
/* Insert into linked list */
f->prev = &__stdio_headnode;
@@ -73,13 +39,11 @@ FILE *__fxopen(int fd, int flags, int close_on_err)
f->next->prev = f;
__stdio_headnode.next = f;
- return f;
+ return &f->pub;
err:
- if (f) {
- free(f->buf);
+ if (f)
free(f);
- }
if (close_on_err)
close(fd);
errno = ENOMEM;
@@ -89,11 +53,11 @@ err:
void __init_stdio(void)
{
stdin = __fxopen(0, O_RDONLY, 0);
- stdin->flags = _IO_FILE_FLAG_LINE_BUF;
+ stdio_pvt(stdin)->bufmode = _IOLBF;
stdout = __fxopen(1, O_WRONLY|O_TRUNC, 0);
- stdout->flags = _IO_FILE_FLAG_LINE_BUF;
+ stdio_pvt(stdout)->bufmode = _IOLBF;
stderr = __fxopen(2, O_WRONLY|O_TRUNC, 0);
- stderr->flags = _IO_FILE_FLAG_UNBUF;
+ stdio_pvt(stderr)->bufmode = _IONBF;
}
diff --git a/usr/klibc/stdio/openmode.c b/usr/klibc/stdio/openmode.c
new file mode 100644
index 0000000000000..c3503e450454b
--- /dev/null
+++ b/usr/klibc/stdio/openmode.c
@@ -0,0 +1,39 @@
+/*
+ * openmode.c
+ *
+ * Parse the mode argument to fopen() or fdopen()
+ */
+
+#include "stdioint.h"
+
+int __parse_open_mode(const char *mode)
+{
+ int rwflags = O_RDONLY;
+ int crflags = 0;
+ int eflag = 0;
+
+ while (*mode) {
+ switch (*mode++) {
+ case 'r':
+ rwflags = O_RDONLY;
+ crflags = 0;
+ break;
+ case 'w':
+ rwflags = O_WRONLY;
+ crflags = O_CREAT | O_TRUNC;
+ break;
+ case 'a':
+ rwflags = O_WRONLY;
+ crflags = O_CREAT | O_APPEND;
+ break;
+ case 'e':
+ eflag = O_CLOEXEC;
+ break;
+ case '+':
+ rwflags = O_RDWR;
+ break;
+ }
+ }
+
+ return rwflags | crflags | eflag;
+}
diff --git a/usr/klibc/stdio/stdioint.h b/usr/klibc/stdio/stdioint.h
index f57c589abf8a8..d0d87184967e0 100644
--- a/usr/klibc/stdio/stdioint.h
+++ b/usr/klibc/stdio/stdioint.h
@@ -9,22 +9,25 @@
#include <stdio.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
/* Actual FILE structure */
-struct _IO_file {
- struct _IO_file *prev, *next;
- off_t filepos; /* File position */
+struct _IO_file_pvt {
+ struct _IO_file pub; /* Data exported to inlines */
+ struct _IO_file_pvt *prev, *next;
char *buf; /* Buffer */
- char *data; /* Data in buffer */
- int bytes; /* Data bytes in buffer */
+ char *data; /* Location of input data in buffer */
+ int ibytes; /* Input data bytes in buffer */
+ int obytes; /* Output data bytes in buffer */
int bufsiz; /* Total size of buffer */
- int fd; /* Underlying file descriptor */
- int flags; /* Error, end of file */
+ enum _IO_bufmode bufmode; /* Type of buffering */
};
+#define stdio_pvt(x) container_of(x, struct _IO_file_pvt, pub)
+
enum _IO_file_flags {
_IO_FILE_FLAG_WRITE = 1, /* Buffer has write data */
_IO_FILE_FLAG_READ = 2, /* Buffer has read data */
@@ -37,9 +40,10 @@ enum _IO_file_flags {
/* Assign this much extra to the input buffer in case of ungetc() */
#define _IO_UNGET_SLOP 32
+__extern int __fflush(struct _IO_file_pvt *);
__extern int __parse_open_mode(const char *mode);
-__extern FILE *__fxopen(int fd, int flags, int close_on_err);
+__extern FILE *__fxopen(int fd, int flags, bool close_on_err);
-__extern struct _IO_file __stdio_headnode;
+__extern struct _IO_file_pvt __stdio_headnode;
#endif /* USR_KLIBC_STDIO_STDIOINT_H */
diff --git a/usr/klibc/stdio/ungetc.c b/usr/klibc/stdio/ungetc.c
index f8ed58dffa1aa..fe328ac593f7e 100644
--- a/usr/klibc/stdio/ungetc.c
+++ b/usr/klibc/stdio/ungetc.c
@@ -4,13 +4,14 @@
#include "stdioint.h"
-int ungetc(int c, FILE *f)
+int ungetc(int c, FILE *file)
{
- if (f->flags & _IO_FILE_FLAG_WRITE || f->data <= f->buf)
+ struct _IO_file_pvt *f = stdio_pvt(file);
+
+ if (f->obytes || f->data <= f->buf)
return EOF;
*(--f->data) = c;
- f->bytes++;
- f->flags |= _IO_FILE_FLAG_READ;
+ f->ibytes++;
return c;
}