summaryrefslogtreecommitdiff
path: root/lib/libc/stdio/fopen.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/stdio/fopen.c')
-rw-r--r--lib/libc/stdio/fopen.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/lib/libc/stdio/fopen.c b/lib/libc/stdio/fopen.c
new file mode 100644
index 00000000..7d01fd38
--- /dev/null
+++ b/lib/libc/stdio/fopen.c
@@ -0,0 +1,56 @@
+#include <io.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libc.h>
+
+weak void __stdio_cleanup(void)
+{
+}
+
+FILE *fopen(const char *restrict pathname, const char *restrict mode)
+{
+ int fd, flags, _mode;
+ FILE *fp;
+
+ _mode = 0;
+ if (mode[0] == 'r') {
+ flags = O_RDONLY;
+ } else if (mode[0] == 'w') {
+ flags = O_WRONLY | O_CREAT | O_TRUNC;
+ } else if (mode[0] == 'a') {
+ flags = O_WRONLY | O_CREAT | O_APPEND;
+ _mode = 0666;
+ } else {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (strchr(mode, '+')) {
+ flags = (flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
+ }
+
+ if ((fd = open(pathname, flags, _mode)) < 0)
+ return NULL;
+
+ if ((fp = calloc(1, sizeof(FILE))) == NULL)
+ return NULL;
+
+ fp->fd = fd;
+ fp->buf_size = BUFSIZ;
+ fp->flags = flags;
+ fp->type = _IOLBF;
+ atomic_flag_clear(&fp->lock);
+ if ((fp->buf = malloc(BUFSIZ)) == NULL) {
+ close(fd);
+ free(fp);
+ return NULL;
+ }
+
+ __libc_fadd(fp);
+
+ return fp;
+}