tools/nolibc: implement fd-based FILE streams
This enables the usage of the stream APIs with arbitrary filedescriptors. It will be used by a future testcase. Signed-off-by: Thomas Weißschuh <linux@weissschuh.net> Signed-off-by: Willy Tarreau <w@1wt.eu> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
This commit is contained in:
committed by
Paul E. McKenney
parent
e8842cf04e
commit
5df28c153d
@ -21,17 +21,75 @@
|
||||
#define EOF (-1)
|
||||
#endif
|
||||
|
||||
/* just define FILE as a non-empty type */
|
||||
/* just define FILE as a non-empty type. The value of the pointer gives
|
||||
* the FD: FILE=~fd for fd>=0 or NULL for fd<0. This way positive FILE
|
||||
* are immediately identified as abnormal entries (i.e. possible copies
|
||||
* of valid pointers to something else).
|
||||
*/
|
||||
typedef struct FILE {
|
||||
char dummy[1];
|
||||
} FILE;
|
||||
|
||||
/* We define the 3 common stdio files as constant invalid pointers that
|
||||
* are easily recognized.
|
||||
*/
|
||||
static __attribute__((unused)) FILE* const stdin = (FILE*)-3;
|
||||
static __attribute__((unused)) FILE* const stdout = (FILE*)-2;
|
||||
static __attribute__((unused)) FILE* const stderr = (FILE*)-1;
|
||||
static __attribute__((unused)) FILE* const stdin = (FILE*)(intptr_t)~STDIN_FILENO;
|
||||
static __attribute__((unused)) FILE* const stdout = (FILE*)(intptr_t)~STDOUT_FILENO;
|
||||
static __attribute__((unused)) FILE* const stderr = (FILE*)(intptr_t)~STDERR_FILENO;
|
||||
|
||||
/* provides a FILE* equivalent of fd. The mode is ignored. */
|
||||
static __attribute__((unused))
|
||||
FILE *fdopen(int fd, const char *mode __attribute__((unused)))
|
||||
{
|
||||
if (fd < 0) {
|
||||
SET_ERRNO(EBADF);
|
||||
return NULL;
|
||||
}
|
||||
return (FILE*)(intptr_t)~fd;
|
||||
}
|
||||
|
||||
/* provides the fd of stream. */
|
||||
static __attribute__((unused))
|
||||
int fileno(FILE *stream)
|
||||
{
|
||||
intptr_t i = (intptr_t)stream;
|
||||
|
||||
if (i >= 0) {
|
||||
SET_ERRNO(EBADF);
|
||||
return -1;
|
||||
}
|
||||
return ~i;
|
||||
}
|
||||
|
||||
/* flush a stream. */
|
||||
static __attribute__((unused))
|
||||
int fflush(FILE *stream)
|
||||
{
|
||||
intptr_t i = (intptr_t)stream;
|
||||
|
||||
/* NULL is valid here. */
|
||||
if (i > 0) {
|
||||
SET_ERRNO(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Don't do anything, nolibc does not support buffering. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* flush a stream. */
|
||||
static __attribute__((unused))
|
||||
int fclose(FILE *stream)
|
||||
{
|
||||
intptr_t i = (intptr_t)stream;
|
||||
|
||||
if (i >= 0) {
|
||||
SET_ERRNO(EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (close(~i))
|
||||
return EOF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* getc(), fgetc(), getchar() */
|
||||
|
||||
@ -41,14 +99,8 @@ static __attribute__((unused))
|
||||
int fgetc(FILE* stream)
|
||||
{
|
||||
unsigned char ch;
|
||||
int fd;
|
||||
|
||||
if (stream < stdin || stream > stderr)
|
||||
return EOF;
|
||||
|
||||
fd = 3 + (long)stream;
|
||||
|
||||
if (read(fd, &ch, 1) <= 0)
|
||||
if (read(fileno(stream), &ch, 1) <= 0)
|
||||
return EOF;
|
||||
return ch;
|
||||
}
|
||||
@ -68,14 +120,8 @@ static __attribute__((unused))
|
||||
int fputc(int c, FILE* stream)
|
||||
{
|
||||
unsigned char ch = c;
|
||||
int fd;
|
||||
|
||||
if (stream < stdin || stream > stderr)
|
||||
return EOF;
|
||||
|
||||
fd = 3 + (long)stream;
|
||||
|
||||
if (write(fd, &ch, 1) <= 0)
|
||||
if (write(fileno(stream), &ch, 1) <= 0)
|
||||
return EOF;
|
||||
return ch;
|
||||
}
|
||||
@ -96,12 +142,7 @@ static __attribute__((unused))
|
||||
int _fwrite(const void *buf, size_t size, FILE *stream)
|
||||
{
|
||||
ssize_t ret;
|
||||
int fd;
|
||||
|
||||
if (stream < stdin || stream > stderr)
|
||||
return EOF;
|
||||
|
||||
fd = 3 + (long)stream;
|
||||
int fd = fileno(stream);
|
||||
|
||||
while (size) {
|
||||
ret = write(fd, buf, size);
|
||||
|
Reference in New Issue
Block a user