Compare commits

..

No commits in common. "f7be2fe20b522c1975b4bcf487c9941125269d90" and "5458286309067b48101de6c45a902bc9c6049169" have entirely different histories.

7 changed files with 10 additions and 202 deletions

View File

@ -41,4 +41,3 @@ luna_app(pivot_root.cpp pivot_root)
luna_app(cp.cpp cp) luna_app(cp.cpp cp)
luna_app(kill.cpp kill) luna_app(kill.cpp kill)
luna_app(gol.cpp gol) luna_app(gol.cpp gol)
luna_app(buffer-test.cpp buffer-test)

View File

@ -1,27 +0,0 @@
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
fprintf(stderr, "Writing incomplete line to stdout (_IOLBF=%d)...\n", stdout->_mode);
fputs("hi!", stdout);
sleep(3);
putchar('\n');
fprintf(stderr, "Incomplete line should have been written.\n");
FILE* f = fopen("/dev/console", "w+");
assert(f);
assert(setvbuf(f, NULL, _IOFBF, 0) == 0);
fprintf(stderr, "Writing long text to file (_IOFBF=%d)...\n", f->_mode);
fputs("Hello world!\nHow are you doing!\nThis is a test for many lines of buffering.\n", f);
sleep(3);
fflush(f);
fprintf(stderr, "Long text should have been written.\n");
fclose(f);
}

View File

@ -31,7 +31,6 @@ char* getpass()
tcsetpgrp(STDIN_FILENO, getpgid(0)); tcsetpgrp(STDIN_FILENO, getpgid(0));
fputs("Password: ", stdout); fputs("Password: ", stdout);
fflush(stdout);
if (tcgetattr(STDIN_FILENO, &orig) < 0) if (tcgetattr(STDIN_FILENO, &orig) < 0)
{ {

View File

@ -10,20 +10,11 @@
#define __need_NULL #define __need_NULL
#include <stddef.h> #include <stddef.h>
#define FOPEN_MAX 64 // Make sure this value matches FD_MAX in the kernel source.
typedef struct typedef struct
{ {
int _fd; int _fd;
int _err; int _err;
int _eof; int _eof;
size_t _bufcap;
size_t _bufsize;
size_t _bufindex;
char* _buffer;
int _flags;
int _pending;
int _mode;
} FILE; } FILE;
#define EOF -1 #define EOF -1
@ -35,15 +26,11 @@ extern FILE* stderr;
#define stdout stdout #define stdout stdout
#define stderr stderr #define stderr stderr
#define BUFSIZ 4096 #define BUFSIZ 1024
#define FILENAME_MAX \ #define FILENAME_MAX \
1024 // As Luna does not impose a limit on this, this is the recommended size for character arrays holding a file 1024 // As Luna does not impose a limit on this, this is the recommended size for character arrays holding a file
// name. // name.
#define _IONBF 0
#define _IOLBF 1
#define _IOFBF 2
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
@ -185,9 +172,6 @@ extern "C"
/* Create a unique temporary file. */ /* Create a unique temporary file. */
FILE* tmpfile(void); FILE* tmpfile(void);
/* Change a file's buffering mode and internal buffer. */
int setvbuf(FILE* stream, char* buf, int mode, size_t size);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,4 +1,3 @@
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
typedef void (*atexit_func_t)(void); typedef void (*atexit_func_t)(void);
@ -24,8 +23,6 @@ extern "C"
{ {
while (atexit_registered_funcs--) { atexit_funcs[atexit_registered_funcs](); } while (atexit_registered_funcs--) { atexit_funcs[atexit_registered_funcs](); }
fflush(NULL);
_Exit(status); _Exit(status);
} }
} }

View File

@ -4,9 +4,6 @@
extern char** environ; extern char** environ;
extern "C" FILE* _fdopen_impl(int, const char*, int);
extern "C" void _init_stdio();
extern "C" extern "C"
{ {
void libc_init(int argc, char** argv, int envc, char** envp) void libc_init(int argc, char** argv, int envc, char** envp)
@ -14,10 +11,8 @@ extern "C"
ignore(argc, argv, envc); ignore(argc, argv, envc);
environ = envp; environ = envp;
_init_stdio(); stdin = fdopen(STDIN_FILENO, "r");
stdout = fdopen(STDOUT_FILENO, "w");
stdin = _fdopen_impl(STDIN_FILENO, "r", _IOLBF); stderr = fdopen(STDERR_FILENO, "w");
stdout = _fdopen_impl(STDOUT_FILENO, "w", _IOLBF);
stderr = _fdopen_impl(STDERR_FILENO, "w", _IONBF);
} }
} }

View File

@ -11,10 +11,6 @@ FILE* stdin = nullptr;
FILE* stderr = nullptr; FILE* stderr = nullptr;
FILE* stdout = nullptr; FILE* stdout = nullptr;
FILE* s_open_files[FOPEN_MAX];
#define FFLAG_FREE_AFTER_BUFFER_USE (1 << 0)
static const char* read_tmpdir() static const char* read_tmpdir()
{ {
const char* tmpdir = getenv("TMPDIR"); const char* tmpdir = getenv("TMPDIR");
@ -55,71 +51,11 @@ static int fdopen_check_compatible_mode(int fd, int new_flags)
return 0; return 0;
} }
static int flush_write_buffer(FILE* stream)
{
if (stream->_mode == _IONBF) return 0;
ssize_t result = write(stream->_fd, stream->_buffer, stream->_bufsize);
stream->_bufindex = 0;
stream->_bufsize = 0;
return result < 0 ? EOF : 0;
}
static ssize_t write_into_buffer(FILE* stream, const u8* data, ssize_t size)
{
ssize_t total_written = 0;
while (size > 0)
{
ssize_t nwritten;
if (stream->_mode != _IONBF)
{
if ((stream->_bufsize + size) > stream->_bufcap)
{
if (flush_write_buffer(stream) < 0) return -1;
}
ssize_t size_remaining = stream->_bufcap - stream->_bufsize;
nwritten = size > size_remaining ? size_remaining : size;
memcpy(stream->_buffer + stream->_bufsize, data, nwritten);
stream->_bufsize += nwritten;
if (stream->_mode == _IOLBF && memchr(data, '\n', nwritten))
{
if (flush_write_buffer(stream) < 0) return -1;
}
}
else
nwritten = write(stream->_fd, data, size > BUFSIZ ? BUFSIZ : size);
if (nwritten < 0) return nwritten;
size -= nwritten;
data += nwritten;
total_written += nwritten;
}
return total_written;
}
extern "C" extern "C"
{ {
void _init_stdio() int fflush(FILE*)
{ {
memset(&s_open_files, 0, sizeof(s_open_files)); // FIXME: Files are not buffered right now.
}
int fflush(FILE* stream)
{
if (stream && stream->_mode != _IONBF) flush_write_buffer(stream);
else if (!stream)
{
for (int i = 0; i < FOPEN_MAX; i++)
{
if (s_open_files[i]) fflush(s_open_files[i]);
}
}
return 0; return 0;
} }
@ -142,19 +78,10 @@ extern "C"
f->_fd = fd; f->_fd = fd;
clearerr(f); clearerr(f);
f->_pending = 0;
f->_flags = flags;
f->_mode = isatty(fd) ? _IOLBF : _IOFBF;
f->_bufsize = f->_bufindex = 0;
f->_buffer = nullptr;
setvbuf(f, NULL, f->_mode, 0);
s_open_files[fd] = f;
return f; return f;
} }
FILE* _fdopen_impl(int fd, const char* mode, int buffering_mode) FILE* fdopen(int fd, const char* mode)
{ {
int flags; int flags;
@ -168,23 +95,9 @@ extern "C"
f->_fd = fd; f->_fd = fd;
clearerr(f); clearerr(f);
f->_pending = 0;
f->_flags = flags;
f->_mode = buffering_mode < 0 ? (isatty(fd) ? _IOLBF : _IOFBF) : buffering_mode;
f->_bufsize = f->_bufindex = 0;
f->_buffer = nullptr;
setvbuf(f, NULL, f->_mode, 0);
s_open_files[fd] = f;
return f; return f;
} }
FILE* fdopen(int fd, const char* mode)
{
return _fdopen_impl(fd, mode, -1);
}
FILE* freopen(const char* path, const char* mode, FILE* stream) FILE* freopen(const char* path, const char* mode, FILE* stream)
{ {
int flags; int flags;
@ -193,10 +106,6 @@ extern "C"
close(stream->_fd); close(stream->_fd);
s_open_files[stream->_fd] = nullptr;
if (stream->_buffer && (stream->_pending & FFLAG_FREE_AFTER_BUFFER_USE)) free(stream->_buffer);
if (!path) { fail("FIXME: freopen() called with path=nullptr"); } if (!path) { fail("FIXME: freopen() called with path=nullptr"); }
int fd = open(path, flags, 0666); int fd = open(path, flags, 0666);
@ -205,28 +114,13 @@ extern "C"
stream->_fd = fd; stream->_fd = fd;
clearerr(stream); clearerr(stream);
stream->_pending = 0;
stream->_flags = flags;
stream->_mode = isatty(fd) ? _IOLBF : _IOFBF;
stream->_bufsize = stream->_bufindex = 0;
stream->_buffer = nullptr;
setvbuf(stream, NULL, stream->_mode, 0);
s_open_files[fd] = stream;
return stream; return stream;
} }
int fclose(FILE* stream) int fclose(FILE* stream)
{ {
if (fflush(stream) < 0) return EOF;
if (close(stream->_fd) < 0) return EOF; if (close(stream->_fd) < 0) return EOF;
if (stream->_buffer && (stream->_pending & FFLAG_FREE_AFTER_BUFFER_USE)) free(stream->_buffer);
s_open_files[stream->_fd] = nullptr;
free(stream); free(stream);
return 0; return 0;
@ -261,12 +155,7 @@ extern "C"
{ {
if (size * nmemb == 0) return 0; if (size * nmemb == 0) return 0;
ssize_t nwrite = write_into_buffer(stream, (const u8*)buf, size * nmemb); ssize_t nwrite = write(stream->_fd, buf, size * nmemb);
if (nwrite < 0)
{
stream->_err = 1;
return 0;
}
return (size_t)nwrite / size; return (size_t)nwrite / size;
} }
@ -322,7 +211,7 @@ extern "C"
int fputc(int c, FILE* stream) int fputc(int c, FILE* stream)
{ {
u8 value = (u8)c; u8 value = (u8)c;
ssize_t rc = write_into_buffer(stream, &value, 1); ssize_t rc = write(stream->_fd, &value, 1);
if (rc <= 0) return EOF; if (rc <= 0) return EOF;
return c; return c;
} }
@ -339,7 +228,7 @@ extern "C"
int fputs(const char* str, FILE* stream) int fputs(const char* str, FILE* stream)
{ {
ssize_t rc = write_into_buffer(stream, (const u8*)str, strlen(str)); ssize_t rc = write(stream->_fd, str, strlen(str));
return (rc < 0) ? -1 : 0; return (rc < 0) ? -1 : 0;
} }
@ -607,32 +496,4 @@ extern "C"
{ {
fail("FIXME: ungetc: not implemented"); fail("FIXME: ungetc: not implemented");
} }
int setvbuf(FILE* stream, char* buf, int mode, size_t size)
{
int pending = 0;
if (mode < 0 || mode > _IOFBF) return errno = EINVAL, -1;
if (stream->_bufsize != 0 || stream->_bufindex != 0) return -1; // Buffer is already in use.
if (mode != _IONBF && buf == NULL)
{
size = BUFSIZ;
buf = (char*)calloc(size, 1);
if (!buf) return -1;
pending = FFLAG_FREE_AFTER_BUFFER_USE;
}
else
{
buf = NULL;
size = 0;
}
if (stream->_buffer && (stream->_pending & FFLAG_FREE_AFTER_BUFFER_USE)) free(stream->_buffer);
stream->_buffer = buf;
stream->_bufcap = size;
stream->_mode = mode;
stream->_pending = pending;
return 0;
}
} }