summaryrefslogtreecommitdiff
path: root/src/stdio
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2019-02-28 14:52:54 -0500
committerJakob Kaivo <jkk@ung.org>2019-02-28 14:52:54 -0500
commit5e7c2c33880fc104b28043c25087624ebd4dc122 (patch)
tree6a7f0f532def6b3bad1f2599faa780d021bb5e47 /src/stdio
parent494102538374ba5149dc319326c1c8f0c1873fc9 (diff)
attempt to use guaranteed space before allocating a new file
Diffstat (limited to 'src/stdio')
-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;
}