summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/stdio/fopen.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/src/stdio/fopen.c b/src/stdio/fopen.c
index 5a0d5eae..1b415969 100644
--- a/src/stdio/fopen.c
+++ b/src/stdio/fopen.c
@@ -5,24 +5,44 @@
/** open a file stream **/
FILE * fopen(const char * restrict filename, const char * restrict mode)
{
- FILE *f = calloc(1, sizeof(*f));
- f->fd = -1;
- if (freopen(filename, mode, f) == NULL) {
- free(f);
- return NULL;
+ struct __FILE *base = __libc(FILE_STREAMS);
+ struct __FILE *f = base;
+
+ /* find the next available stream */
+ while (f->next != NULL) {
+ f = f->next;
+ }
+
+ /* use a stream from the guaranteed space if possible */
+ /* otherwise, allocate a new stream */
+ if (f < base + FOPEN_MAX) {
+ f->next = f + 1;
+ } else {
+ f->next = malloc(sizeof(*f->next));
}
- if (__libc(FILE_STREAMS)) {
- f->prev = __libc(FILE_STREAMS);
- f->prev->next = f;
+ /* if we had to allocate, but that failed, we're out of memory */
+ if (f->next == NULL) {
+ return NULL;
}
- /* __libc(FILE_STREAMS) = f; */
+ /* open the new stream */
+ f->next->prev = f;
+ f = f->next;
+ f->fd = -1;
+ if (freopen(filename, mode, f) == NULL) {
+ if (f < base + FOPEN_MAX) {
+ } else {
+ free(f);
+ }
+ return NULL;
+ }
/*
RETURN_SUCCESS(a pointer to the new file stream);
RETURN_FAILURE(CONSTANT(NULL));
*/
+
return f;
}