summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-11-23 14:59:26 +0100
committerAnton Kling <anton@kling.gg>2024-11-23 16:31:25 +0100
commit934c30d35a3ca0e0bf6cd8709d779e060e27f6d2 (patch)
treeb2d5df8919b7bf721b9901b56cccad3f3d1644e0
parent2dce92236b9fe0a9398287ac7c62f2f4e67d53b6 (diff)
libc: Add append to f(d)open and other fixes
-rw-r--r--userland/libc/Makefile6
-rw-r--r--userland/libc/include/stdio.h7
-rw-r--r--userland/libc/stdio/fclose.c4
-rw-r--r--userland/libc/stdio/fopen.c49
-rw-r--r--userland/libc/stdio/fwrite.c5
5 files changed, 35 insertions, 36 deletions
diff --git a/userland/libc/Makefile b/userland/libc/Makefile
index a41e8e4..0e56a4a 100644
--- a/userland/libc/Makefile
+++ b/userland/libc/Makefile
@@ -1,12 +1,12 @@
CC="i686-sb-gcc"
AR="i686-sb-ar"
AS="i686-sb-as"
-CFLAGS = -ggdb -ffreestanding -nostdlib -Ofast -Wall -Wextra -pedantic -Werror -Wimplicit-fallthrough -I./include/ -static -I../../include/ -Wno-int-conversion -Wno-unused-parameter
-OBJ=crt0.o libc.o malloc/malloc.o pty.o sys/mman/mmap.o sys/mman/munmap.o memset.o assert.o stdio/snprintf.o stdio/vfprintf.o string/memcpy.o string/memcmp.o string/strcmp.o ubsan.o string/strcpy.o isspace.o stdio/puts.o stdio/putchar.o dirent/opendir.o dirent/readdir.o dirent/closedir.o unistd/getopt.o dirent/scandir.o dirent/alphasort.o stdio/printf.o stdio/vdprintf.o stdio/vprintf.o stdio/dprintf.o stdio/vprintf.o string/strlen.o string/strnlen.o stdio/stdin.o stdio/getchar.o stdio/fgetc.o arpa/inet/htons.o arpa/inet/htonl.o stdio/fread.o stdio/fwrite.o stdio/fopen.o stdio/fclose.o stdio/fseek.o ctype/isascii.o stdio/fprintf.o stdlib/atoi.o stdlib/strtol.o ctype/toupper.o ctype/tolower.o string/strcat.o string/strchr.o string/sscanf.o sys/stat/stat.o stdlib/getenv.o string/strrchr.o stdio/ftell.o stdio/tmpfile.o stdio/fgets.o stdio/feof.o stdio/fscanf.o stdio/ungetc.o string/strncmp.o stdio/fputc.o string/strncpy.o stdio/remove.o stdio/ferror.o stdio/fputs.o stdlib/rand.o stdlib/srand.o unistd/getpid.o stdlib/strtoul.o stdio/fflush.o stdlib/abort.o string/strcspn.o time/localtime.o time/time.o time/clock_gettime.o time/gmtime.o time/strftime.o string/strpbrk.o ctype/isdigit.o ctype/isalpha.o ctype/isxdigit.o ctype/ispunct.o stdio/setvbuf.o stdio/fileno.o stdio/putc.o stdio/sprintf.o stdlib/abs.o string/strspn.o stdlib/qsort.o string/memmove.o setjmp/longjmp.o setjmp/setjmp.o libgen/basename.o string/strdup.o string/strndup.o string/strlcpy.o stdlib/atexit.o stdio/open_memstream.o libgen/dirname.o unistd/unlink.o string/strstr.o string/strcasecmp.o string/strncasecmp.o stdlib/mkstemp.o string/strtok.o unistd/execvp.o unistd/_exit.o ctype/isalnum.o time/ctime_r.o stdlib/strtold.o sys/time/gettimeofday.o stdio/fgetpos.o stdio/fsetpos.o ctype/isprint.o stdlib/system.o stdio/tmpnam.o unistd/msleep.o stdlib/atof.o stdlib/strtod.o stdio/rename.o sys/stat/mkdir.o unistd/uptime.o unistd/ftruncate.o sys/socket/recvfrom.o sys/socket/sendto.o signal/kill.o signal/sigaction.o unistd/chdir.o unistd/getcwd.o stdio/getdelim.o stdio/getline.o unistd/isatty.o sys/socket/listen.o stdlib/realpath.o systemcall.o sys/random/randomfill.o fcntl/open.o unistd/write.o unistd/pwrite.o fcntl/open_process.o tb/sb.o tb/sv.o string/memchr.o stdlib/atol.o stdlib/atoll.o stdlib/strtoll.o sys/stat/fstat.o unistd/lseek.o ctype/isupper.o ctype/islower.o ctype/isblank.o ctype/isgraph.o ctype/iscntrl.o math/ldexp.o sys/socket/connect.o sys/socket/setsockopt.o arpa/inet/ntohl.o arpa/inet/ntohs.o netdb/getaddrinfo.o tb/sha1.o sys/socket/getpeername.o fcntl/fcntl.o queue.o sys/sendfile.o
+CFLAGS = -ggdb -ffreestanding -O2 -Wall -Wextra -pedantic -Werror -Wimplicit-fallthrough -I./include/ -static -I../../include/ -Wno-int-conversion -Wno-unused-parameter
+OBJ=crt0.o libc.o malloc/malloc.o pty.o sys/mman/mmap.o sys/mman/munmap.o memset.o assert.o stdio/snprintf.o stdio/vfprintf.o string/memcpy.o string/memcmp.o string/strcmp.o ubsan.o string/strcpy.o isspace.o stdio/puts.o stdio/putchar.o dirent/opendir.o dirent/readdir.o dirent/closedir.o unistd/getopt.o dirent/scandir.o dirent/alphasort.o stdio/printf.o stdio/vdprintf.o stdio/vprintf.o stdio/dprintf.o stdio/vprintf.o string/strlen.o string/strnlen.o stdio/stdin.o stdio/getchar.o stdio/fgetc.o arpa/inet/htons.o arpa/inet/htonl.o stdio/fread.o stdio/fwrite.o stdio/fopen.o stdio/fclose.o stdio/fseek.o ctype/isascii.o stdio/fprintf.o stdlib/atoi.o stdlib/strtol.o ctype/toupper.o ctype/tolower.o string/strcat.o string/strchr.o string/sscanf.o sys/stat/stat.o stdlib/getenv.o string/strrchr.o stdio/ftell.o stdio/tmpfile.o stdio/fgets.o stdio/feof.o stdio/fscanf.o stdio/ungetc.o string/strncmp.o stdio/fputc.o string/strncpy.o stdio/remove.o stdio/ferror.o stdio/fputs.o stdlib/rand.o stdlib/srand.o unistd/getpid.o stdlib/strtoul.o stdio/fflush.o stdlib/abort.o string/strcspn.o time/localtime.o time/time.o time/clock_gettime.o time/gmtime.o time/strftime.o string/strpbrk.o ctype/isdigit.o ctype/isalpha.o ctype/isxdigit.o ctype/ispunct.o stdio/setvbuf.o stdio/fileno.o stdio/putc.o stdio/sprintf.o stdlib/abs.o string/strspn.o stdlib/qsort.o string/memmove.o setjmp/longjmp.o setjmp/setjmp.o libgen/basename.o string/strdup.o string/strndup.o string/strlcpy.o stdlib/atexit.o stdio/open_memstream.o libgen/dirname.o unistd/unlink.o string/strstr.o string/strcasecmp.o string/strncasecmp.o stdlib/mkstemp.o string/strtok.o unistd/execvp.o unistd/_exit.o ctype/isalnum.o time/ctime_r.o stdlib/strtold.o sys/time/gettimeofday.o stdio/fgetpos.o stdio/fsetpos.o ctype/isprint.o stdlib/system.o stdio/tmpnam.o unistd/msleep.o stdlib/atof.o stdlib/strtod.o stdio/rename.o sys/stat/mkdir.o unistd/uptime.o unistd/ftruncate.o sys/socket/recvfrom.o sys/socket/sendto.o signal/kill.o signal/sigaction.o unistd/chdir.o unistd/getcwd.o stdio/getdelim.o stdio/getline.o unistd/isatty.o sys/socket/listen.o stdlib/realpath.o systemcall.o sys/random/randomfill.o fcntl/open.o unistd/write.o unistd/pwrite.o fcntl/open_process.o tb/sb.o tb/sv.o string/memchr.o stdlib/atol.o stdlib/atoll.o stdlib/strtoll.o sys/stat/fstat.o unistd/lseek.o ctype/isupper.o ctype/islower.o ctype/isblank.o ctype/isgraph.o ctype/iscntrl.o math/ldexp.o sys/socket/connect.o sys/socket/setsockopt.o arpa/inet/ntohl.o arpa/inet/ntohs.o netdb/getaddrinfo.o tb/sha1.o sys/socket/getpeername.o fcntl/fcntl.o queue.o sys/sendfile.o stdio/fdopen.o unistd/dup.o
all: libc.a
%.o: %.c
- $(CC) $(CFLAGS) -I. -o $@ -c $< -lgcc
+ $(CC) $(CFLAGS) -I. -o $@ -c $<
%.o: %.s
$(AS) $< -o $@
diff --git a/userland/libc/include/stdio.h b/userland/libc/include/stdio.h
index ac49a67..781b431 100644
--- a/userland/libc/include/stdio.h
+++ b/userland/libc/include/stdio.h
@@ -33,6 +33,12 @@ struct __IO_FILE {
int buffered_char;
int has_buffered_char;
int fd;
+
+ int has_control_over_the_fd;
+ int can_write;
+ int can_read;
+ int append;
+
uint8_t is_eof;
uint8_t has_error;
uint64_t file_size;
@@ -89,6 +95,7 @@ int getchar(void);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
FILE *fopen(const char *pathname, const char *mode);
+FILE *fdopen(int fildes, const char *mode);
int fclose(FILE *stream);
int fseek(FILE *stream, long offset, int whence);
int fprintf(FILE *f, const char *fmt, ...);
diff --git a/userland/libc/stdio/fclose.c b/userland/libc/stdio/fclose.c
index eb92387..5d66830 100644
--- a/userland/libc/stdio/fclose.c
+++ b/userland/libc/stdio/fclose.c
@@ -1,5 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/fclose.html
// FIXME: Do some actual error checking.
@@ -8,6 +9,9 @@ int fclose(FILE *stream) {
if (stream->fflush) {
stream->fflush(stream);
}
+ if (stream->has_control_over_the_fd) {
+ close(stream->fd);
+ }
free(stream->cookie);
}
free(stream);
diff --git a/userland/libc/stdio/fopen.c b/userland/libc/stdio/fopen.c
index 52e78d1..fe0b5cf 100644
--- a/userland/libc/stdio/fopen.c
+++ b/userland/libc/stdio/fopen.c
@@ -1,16 +1,10 @@
#include <fcntl.h>
-#include <stdint.h>
#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
+#include <unistd.h>
-// FIXME: All modes not implemented
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html
FILE *fopen(const char *pathname, const char *mode) {
- uint8_t read = 0;
- uint8_t write = 0;
-// uint8_t append = 0;
- // FIXME: Not parsed correctly
+ int flag = 0;
for (; *mode; mode++) {
// r or rb
// Open file for reading.
@@ -21,41 +15,30 @@ FILE *fopen(const char *pathname, const char *mode) {
// end-of-file.
switch (*mode) {
case 'r':
- read = 1;
+ flag |= O_READ;
break;
case 'w':
- write = 1;
+ flag |= O_WRITE;
break;
case 'a':
-// append = 1;
+ flag |= O_APPEND;
break;
}
}
- int flag = 0;
- if (read)
- flag |= O_READ;
- if (write)
- flag |= O_WRITE;
int fd = open(pathname, flag, 0);
- if (-1 == fd)
+ if (-1 == fd) {
return NULL;
+ }
- struct stat s;
- stat(pathname, &s);
-
- FILE *r = calloc(1, sizeof(FILE));
- r->read = read_fd;
- r->write = write_fd;
- r->seek = seek_fd;
- r->has_error = 0;
- r->is_eof = 0;
- r->offset_in_file = 0;
- r->file_size = s.st_size;
- r->cookie = NULL;
- r->fd = fd;
- r->read_buffer = NULL;
- r->read_buffer_stored = 0;
- r->fflush = fflush_fd;
+ FILE *r = fdopen(fd, mode);
+ if (!r) {
+ close(fd);
+ return NULL;
+ }
+ if(flag & O_WRITE) {
+ ftruncate(fd, 0);
+ }
+ r->has_control_over_the_fd = 1;
return r;
}
diff --git a/userland/libc/stdio/fwrite.c b/userland/libc/stdio/fwrite.c
index 6499529..d2086cb 100644
--- a/userland/libc/stdio/fwrite.c
+++ b/userland/libc/stdio/fwrite.c
@@ -2,6 +2,11 @@
#include <sys/types.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
+ if (!stream->has_control_over_the_fd) {
+ if (stream->append) {
+ fseek(stream, 0, SEEK_END);
+ }
+ }
// FIXME: Check for overflow
size_t bytes_to_write = nmemb * size;
size_t rc = stream->write(stream, ptr, bytes_to_write);