diff options
| author | Jakob Kaivo <jkk@ung.org> | 2019-02-28 14:52:54 -0500 |
|---|---|---|
| committer | Jakob Kaivo <jkk@ung.org> | 2019-02-28 14:52:54 -0500 |
| commit | 5e7c2c33880fc104b28043c25087624ebd4dc122 (patch) | |
| tree | 6a7f0f532def6b3bad1f2599faa780d021bb5e47 | |
| parent | 494102538374ba5149dc319326c1c8f0c1873fc9 (diff) | |
attempt to use guaranteed space before allocating a new file
| -rw-r--r-- | src/stdio/fopen.c | 38 |
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; } |
