From aa3073904d398a87f9e3251d99e26bf33f9936a4 Mon Sep 17 00:00:00 2001 From: bumbread Date: Tue, 26 Jul 2022 02:10:48 +1100 Subject: [PATCH] stdio.h: freopen --- src/_win/stdio.c | 78 ++++++++++++++++++++++++++++++++++++++++++------ test/test_io.c | 19 ++++++------ 2 files changed, 78 insertions(+), 19 deletions(-) diff --git a/src/_win/stdio.c b/src/_win/stdio.c index 18b2676..3e19698 100644 --- a/src/_win/stdio.c +++ b/src/_win/stdio.c @@ -70,13 +70,12 @@ static void close_list_remove(FILE *stream) { if(next == NULL) streams_to_close = prev; } -static inline FILE *create_stream( +static inline void init_stream( + FILE *stream, HANDLE handle, stream_io_mode_t io_mode, stream_bt_mode_t bt_mode ) { - FILE *stream = malloc(sizeof(FILE)); - if(stream == NULL) return NULL; stream->handle = handle; stream->char_width = STREAM_CHAR_UNSET; stream->mbstate = (mbstate_t){0}; @@ -85,6 +84,16 @@ static inline FILE *create_stream( stream->bt_mode = bt_mode; stream->eof = 0; stream->err = 0; +} + +static inline FILE *create_stream( + HANDLE handle, + stream_io_mode_t io_mode, + stream_bt_mode_t bt_mode +) { + FILE *stream = malloc(sizeof(FILE)); + if(stream == NULL) return NULL; + init_stream(stream, handle, io_mode, bt_mode); mtx_init(&stream->lock, mtx_recursive); close_list_add(stream); return stream; @@ -116,13 +125,19 @@ void _setup_io() { stderr->buffer = (stream_buffer_t){1, _IONBF, 0, NULL}; } -FILE *fopen(const char *restrict name, const char *restrict mode) { +int win_parse_mode( + char const *mode, + int *pio_mode, + int *pbt_mode, + DWORD *paccess, + DWORD *pshare, + DWORD *pdisp +) { DWORD access = 0; DWORD share = 0; DWORD disp = 0; - DWORD flags = FILE_FLAG_WRITE_THROUGH; stream_io_mode_t io_mode = 0; - stream_bt_mode_t bt_mode; + stream_bt_mode_t bt_mode = 0; int flag_p = 0; int flag_b = 0; int flag_x = 0; @@ -130,13 +145,13 @@ FILE *fopen(const char *restrict name, const char *restrict mode) { case 'r': io_mode = STREAM_INPUT; break; case 'w': io_mode = STREAM_OUTPUT; break; case 'a': io_mode = STREAM_UPDATE; break; - default: return NULL; + default: return 0; } while(*mode) switch(*mode++) { case '+': flag_p = 1; break; case 'b': flag_b = 1; break; case 'x': flag_x = 1; break; - default: return NULL; + default: return 0; } bt_mode = flag_b? STREAM_BINARY : STREAM_TEXT; // Not sure about the sharing modes @@ -160,6 +175,24 @@ FILE *fopen(const char *restrict name, const char *restrict mode) { disp = OPEN_ALWAYS; } break; } + *paccess = access; + *pshare = share; + *pdisp = disp; + *pio_mode = io_mode; + *pbt_mode = bt_mode; + return 1; +} + +FILE *fopen(const char *restrict name, const char *restrict mode) { + DWORD access; + DWORD share; + DWORD disp; + DWORD flags = FILE_FLAG_WRITE_THROUGH; + stream_io_mode_t io_mode; + stream_bt_mode_t bt_mode; + if(!win_parse_mode(mode, &io_mode, &bt_mode, &access, &share, &disp)) { + return NULL; + } HANDLE handle = CreateFileA(name, access, share, NULL, disp, flags, NULL); if(handle == INVALID_HANDLE_VALUE) { return NULL; @@ -171,7 +204,34 @@ FILE *fopen(const char *restrict name, const char *restrict mode) { } FILE *freopen(const char *restrict name, const char *restrict mode, FILE *restrict stream) { - return NULL; + if(stream == NULL) { + return NULL; + } + fflush(stream); + DWORD access; + DWORD share; + DWORD disp; + DWORD flags = FILE_FLAG_WRITE_THROUGH; + stream_io_mode_t io_mode; + stream_bt_mode_t bt_mode; + if(!win_parse_mode(mode, &io_mode, &bt_mode, &access, &share, &disp)) { + return NULL; + } + if(name == NULL) { + HANDLE handle = ReOpenFile(stream->handle, access, share, flags); + if(handle == INVALID_HANDLE_VALUE) { + return NULL; + } + } + else { + CloseHandle(stream->handle); + HANDLE handle = CreateFileA(name, access, share, NULL, disp, flags, NULL); + if(handle == INVALID_HANDLE_VALUE) { + return NULL; + } + init_stream(stream, handle, io_mode, bt_mode); + } + return stream; } FILE *tmpfile(void) { diff --git a/test/test_io.c b/test/test_io.c index 69e56cb..b72d908 100644 --- a/test/test_io.c +++ b/test/test_io.c @@ -1,17 +1,16 @@ #include +#include int main(void) { - char const *filename = "todo"; - FILE *f = fopen(filename, "rb"); - if(f == NULL) { - printf("File %s doesn't exist\n", filename); - return 1; + puts("stdout is printed to console"); + if (freopen("redir.txt", "w", stdout) == NULL) + { + perror("freopen() failed"); + return EXIT_FAILURE; } - int c; - while((c=fgetc(f)) != EOF) { - putchar(c); - } - return 0; + puts("stdout is redirected to a file"); // this is written to redir.txt + fclose(stdout); + return EXIT_SUCCESS; }