summaryrefslogtreecommitdiff
path: root/lib/libc/stdio/fwrite.c
diff options
context:
space:
mode:
authorKacper <kacper@mail.openlinux.dev>2025-12-22 23:27:56 +0100
committerKacper <kacper@mail.openlinux.dev>2025-12-22 23:30:32 +0100
commit0f30d227497418c6d3bef7d52244407e30454504 (patch)
tree0e1ac19623d3268380cf74328cdf643648a2f43c /lib/libc/stdio/fwrite.c
parent90dad97fc07f049383903a166631e2c257f9b8c1 (diff)
Added c11 threads, fixed some locks and add *_unlocked functions
Diffstat (limited to 'lib/libc/stdio/fwrite.c')
-rw-r--r--lib/libc/stdio/fwrite.c136
1 files changed, 7 insertions, 129 deletions
diff --git a/lib/libc/stdio/fwrite.c b/lib/libc/stdio/fwrite.c
index c21054da..8d81c7ac 100644
--- a/lib/libc/stdio/fwrite.c
+++ b/lib/libc/stdio/fwrite.c
@@ -1,134 +1,12 @@
-#include "__stdio.h" // for __FILE, _IO_ERR
-#include "stddef.h" // for NULL
+#include <stdio.h>
-#include <atomic.h> // for LIBC_UNLOCK, LIBC_LOCK
-#include <errno.h> // for errno, EOVERFLOW, EBADF, EINVAL, EIO
-#include <fcntl.h> // for O_ACCMODE, O_RDONLY
-#include <stdio.h> // for fflush, fwrite, BUFSIZ, FILE, _IOFBF, _IOLBF
-#include <string.h> // for memcpy, memchr
-#include <unistd.h> // for size_t, ssize_t, write
-
-char __stdout_buffer[BUFSIZ];
-void (*__stdio_cleanup)(void);
-
-size_t fwrite(const void *restrict ptr, size_t size, size_t nitems,
- FILE *restrict stream)
+size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream)
{
- size_t total_bytes;
- size_t written = 0;
- const char *data = (const char *)ptr;
-
- if (ptr == NULL || stream == NULL || size == 0) {
- if (size == 0) {
- return nitems;
- }
- errno = EINVAL;
- return 0;
- }
-
- if (__FILE(stream)->fd == -1 && __FILE(stream)->buf != NULL) {
- if (__builtin_mul_overflow(size, nitems, &total_bytes)) {
- errno = EOVERFLOW;
- return 0;
- }
-
- size_t space_left =
- __FILE(stream)->buf_size > __FILE(stream)->buf_len ?
- __FILE(stream)->buf_size -
- __FILE(stream)->buf_len - 1 :
- 0;
-
- if (space_left == 0) {
- return 0;
- }
-
- size_t to_copy = total_bytes < space_left ? total_bytes :
- space_left;
-
- if (to_copy > 0) {
- memcpy(__FILE(stream)->buf + __FILE(stream)->buf_len,
- data, to_copy);
- __FILE(stream)->buf_len += to_copy;
- }
-
- return to_copy == total_bytes ? nitems : to_copy / size;
- }
-
- if (__builtin_mul_overflow(size, nitems, &total_bytes)) {
- errno = EOVERFLOW;
- return 0;
- }
-
- if ((__FILE(stream)->flags & O_ACCMODE) == O_RDONLY) {
- errno = EBADF;
- return 0;
- }
-
- if (__FILE(stream)->flags & _IO_ERR) {
- errno = EIO;
- return 0;
- }
-
- LIBC_LOCK(__FILE(stream)->lock);
-
- if (__FILE(stream)->type == _IONBF) {
- ssize_t result = write(__FILE(stream)->fd, data, total_bytes);
- LIBC_UNLOCK(__FILE(stream)->lock);
-
- if (result < 0) {
- __FILE(stream)->flags |= _IO_ERR;
- return 0;
- }
-
- return result == (ssize_t)total_bytes ? nitems : result / size;
- }
-
- size_t remaining = total_bytes;
-
- while (remaining > 0) {
- size_t space_available =
- __FILE(stream)->buf_size - __FILE(stream)->buf_len;
-
- if (space_available == 0) {
- LIBC_UNLOCK(__FILE(stream)->lock);
- if (fflush(stream) != 0) {
- return written / size;
- }
- space_available = __FILE(stream)->buf_size;
- }
-
- size_t to_copy = remaining < space_available ? remaining :
- space_available;
-
- memcpy(__FILE(stream)->buf + __FILE(stream)->buf_len,
- data + written, to_copy);
- __FILE(stream)->buf_len += to_copy;
- written += to_copy;
- remaining -= to_copy;
-
- if (__FILE(stream)->type == _IOLBF) {
- char *newline_pos = memchr(
- __FILE(stream)->buf + __FILE(stream)->buf_len -
- to_copy,
- '\n', to_copy);
- if (newline_pos != NULL) {
- LIBC_UNLOCK(__FILE(stream)->lock);
- if (fflush(stream) != 0) {
- return written / size;
- }
- }
- }
-
- else if (__FILE(stream)->type == _IOFBF &&
- __FILE(stream)->buf_len == __FILE(stream)->buf_size) {
- LIBC_UNLOCK(__FILE(stream)->lock);
- if (fflush(stream) != 0) {
- return written / size;
- }
- }
- }
+ size_t r;
- LIBC_UNLOCK(__FILE(stream)->lock);
+ flockfile(stream);
+ r = fwrite_unlocked(ptr, size, nitems, stream);
+ funlockfile(stream);
- return written == total_bytes ? nitems : written / size;
+ return r;
}