stdio.h: freopen

This commit is contained in:
bumbread 2022-07-26 02:10:48 +11:00
parent 4bf696c2fb
commit aa3073904d
2 changed files with 78 additions and 19 deletions

View File

@ -70,13 +70,12 @@ static void close_list_remove(FILE *stream) {
if(next == NULL) streams_to_close = prev; if(next == NULL) streams_to_close = prev;
} }
static inline FILE *create_stream( static inline void init_stream(
FILE *stream,
HANDLE handle, HANDLE handle,
stream_io_mode_t io_mode, stream_io_mode_t io_mode,
stream_bt_mode_t bt_mode stream_bt_mode_t bt_mode
) { ) {
FILE *stream = malloc(sizeof(FILE));
if(stream == NULL) return NULL;
stream->handle = handle; stream->handle = handle;
stream->char_width = STREAM_CHAR_UNSET; stream->char_width = STREAM_CHAR_UNSET;
stream->mbstate = (mbstate_t){0}; stream->mbstate = (mbstate_t){0};
@ -85,6 +84,16 @@ static inline FILE *create_stream(
stream->bt_mode = bt_mode; stream->bt_mode = bt_mode;
stream->eof = 0; stream->eof = 0;
stream->err = 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); mtx_init(&stream->lock, mtx_recursive);
close_list_add(stream); close_list_add(stream);
return stream; return stream;
@ -116,13 +125,19 @@ void _setup_io() {
stderr->buffer = (stream_buffer_t){1, _IONBF, 0, NULL}; 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 access = 0;
DWORD share = 0; DWORD share = 0;
DWORD disp = 0; DWORD disp = 0;
DWORD flags = FILE_FLAG_WRITE_THROUGH;
stream_io_mode_t io_mode = 0; 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_p = 0;
int flag_b = 0; int flag_b = 0;
int flag_x = 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 'r': io_mode = STREAM_INPUT; break;
case 'w': io_mode = STREAM_OUTPUT; break; case 'w': io_mode = STREAM_OUTPUT; break;
case 'a': io_mode = STREAM_UPDATE; break; case 'a': io_mode = STREAM_UPDATE; break;
default: return NULL; default: return 0;
} }
while(*mode) switch(*mode++) { while(*mode) switch(*mode++) {
case '+': flag_p = 1; break; case '+': flag_p = 1; break;
case 'b': flag_b = 1; break; case 'b': flag_b = 1; break;
case 'x': flag_x = 1; break; case 'x': flag_x = 1; break;
default: return NULL; default: return 0;
} }
bt_mode = flag_b? STREAM_BINARY : STREAM_TEXT; bt_mode = flag_b? STREAM_BINARY : STREAM_TEXT;
// Not sure about the sharing modes // Not sure about the sharing modes
@ -160,6 +175,24 @@ FILE *fopen(const char *restrict name, const char *restrict mode) {
disp = OPEN_ALWAYS; disp = OPEN_ALWAYS;
} break; } 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); HANDLE handle = CreateFileA(name, access, share, NULL, disp, flags, NULL);
if(handle == INVALID_HANDLE_VALUE) { if(handle == INVALID_HANDLE_VALUE) {
return NULL; 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) { 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) { FILE *tmpfile(void) {

View File

@ -1,17 +1,16 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
int main(void) int main(void)
{ {
char const *filename = "todo"; puts("stdout is printed to console");
FILE *f = fopen(filename, "rb"); if (freopen("redir.txt", "w", stdout) == NULL)
if(f == NULL) { {
printf("File %s doesn't exist\n", filename); perror("freopen() failed");
return 1; return EXIT_FAILURE;
} }
int c; puts("stdout is redirected to a file"); // this is written to redir.txt
while((c=fgetc(f)) != EOF) { fclose(stdout);
putchar(c); return EXIT_SUCCESS;
}
return 0;
} }