#include "stdio.h"
#include "fcntl.h"
#include "unistd.h"
#include <string.h>
#include <stdlib.h>
#include <errno.h>
struct access_mode_struct {
unsigned read : 1;
unsigned write : 1;
unsigned create : 1;
unsigned truncate : 1;
unsigned append : 1;
};
struct __FILE {
FILE *previous;
FILE *next;
int fd;
unsigned tty : 1;
dev_t dev;
struct access_mode_struct access_mode;
off_t offset;
unsigned seekable : 1;
unsigned eof : 1;
unsigned error : 1;
unsigned pushed_back : 1;
unsigned char pushed_back_byte;
unsigned auto_buf : 1;
char *buf;
size_t buf_size;
unsigned line_buf : 1;
char *buf_end;
char *buf_read_end;
char *buf_cur;
int state;
};
#define reading_buf(stream) ((stream)->buf_cur < (stream)->buf_read_end)
#define writing_buf(stream) ((stream)->buf_cur > (stream)->buf_read_end)
#define empty_buf(stream) ((stream)->buf_cur == (stream)->buf_read_end)
#define full_buf(stream) ((stream)->buf_cur == (stream)->buf_end)
static struct __FILE stream_table[FOPEN_MAX];
static FILE *first_free;
static FILE *first_open;
static void init_stream_table()
{
unsigned int i;
for (i = 0; i < FOPEN_MAX - 1; i++)
stream_table[i].next = &stream_table[i + 1];
stream_table[FOPEN_MAX - 1].next = NULL;
first_free = &stream_table[0];
first_open = NULL;
}
static FILE *alloc_stream()
{
FILE *stream;
if (!first_free) {
errno = EMFILE;
return NULL;
}
stream = first_free;
first_free = first_free->next;
return stream;
}
static void free_stream(FILE *stream)
{
stream->next = first_free;
first_free = stream;
}
static void init_stream(FILE *stream, int fd, const struct access_mode_struct *access_mode, int buffered)
{
off_t offset;
int seekable;
if (!access_mode->read && access_mode->append) {
offset = __lseek(fd, 0, SEEK_END);
seekable = offset != -1 || errno != ESPIPE ? 1 : 0;
}
else {
offset = -1;
seekable = 1;
}
stream->previous = NULL;
stream->next = first_open;
stream->fd = fd;
stream->tty = 0;
stream->access_mode = *access_mode;
stream->offset = offset;
stream->seekable = seekable;
stream->eof = 0;
stream->error = 0;
stream->pushed_back = 0;
stream->auto_buf = buffered;
stream->buf = NULL;
if (first_open)
first_open->previous = stream;
first_open = stream;
}
static void destroy_stream(FILE *stream)
{
if (stream->previous)
stream->previous->next = stream->next;
else
first_open = stream->next;
if (stream->next)
stream->next->previous = stream->previous;
if (stream->auto_buf && stream->buf)
free(stream->buf);
}
static size_t io_read(FILE *stream, void *buf, size_t count)
{
ssize_t n;
if ((n = __read(stream->fd, buf, count)) == -1) {
stream->error = 1;
return 0;
}
if (n == 0) {
stream->eof = 1;
return 0;
}
if (stream->offset != -1)
stream->offset += n;
return n;
}
static int io_write(FILE *stream, const void *buf, size_t count)
{
ssize_t n;
if ((n = __write(stream->fd, buf, count)) == -1) {
stream->error = 1;
return EOF;
}
if (stream->offset != -1) {
if (!stream->access_mode.append)
stream->offset += n;
else
stream->offset = -1;
}
return 0;
}
static int io_seek(FILE *stream, off_t offset, int whence)
{
if ((stream->offset = __lseek(stream->fd, offset, whence)) == -1) {
if (errno == ESPIPE)
stream->seekable = 0;
return -1;
}
return 0;
}
static void init_buf(FILE *stream)
{
stream->buf_end = stream->buf + stream->buf_size;
stream->buf_read_end = stream->buf;
stream->buf_cur = stream->buf;
}
static int fill_buf(FILE *stream)
{
size_t n;
if (!(n = io_read(stream, stream->buf, stream->buf_size)))
return EOF;
stream->buf_read_end = stream->buf + n;
stream->buf_cur = stream->buf;
return 0;
}
static void discard_buf(FILE *stream)
{
stream->buf_read_end = stream->buf;
stream->buf_cur = stream->buf;
}
static int flush_buf(FILE *stream)
{
if (io_write(stream, stream->buf, stream->buf_cur - stream->buf) == EOF)
return EOF;
stream->buf_cur = stream->buf;
return 0;
}
static ssize_t count_buf(FILE *stream)
{
return stream->buf_cur - stream->buf_read_end;
}
static void attach_stream(FILE *stream, int fd, const struct access_mode_struct *access_mode, int buffered)
{
init_stream(stream, fd, access_mode, buffered);
}
static int detach_stream(FILE *stream, int *fd)
{
int errnum;
errnum = 0;
if (stream->buf && writing_buf(stream))
if (flush_buf(stream) == EOF)
errnum = errno;
*fd = stream->fd;
destroy_stream(stream);
return errnum ? errno = errnum, EOF : 0;
}
static void push_back_byte(FILE *stream, int c)
{
stream->pushed_back = 1;
stream->pushed_back_byte = c;
}
static int pop_byte(FILE *stream)
{
stream->pushed_back = 0;
return stream->pushed_back_byte;
}
static int set_buf(FILE *stream, char *buf, size_t size, int line_buffered)
{
struct stat statbuf;
if (buf)
stream->auto_buf = 0;
else {
if (!(buf = malloc(size)))
return -1;
stream->auto_buf = 1;
}
stream->buf = buf;
stream->buf_size = size;
stream->line_buf = line_buffered;
if (__fstat(stream->fd, &statbuf) == 0) {
stream->tty = S_ISCHR(statbuf.st_mode) && __isatty(stream->fd) ? 1 : 0;
if (stream->tty)
stream->dev = statbuf.st_rdev;
}
else
stream->tty = 0;
init_buf(stream);
return 0;
}
static int alloc_buf(FILE *stream)
{
struct stat statbuf;
if (__fstat(stream->fd, &statbuf) == 0) {
stream->tty = S_ISCHR(statbuf.st_mode) && __isatty(stream->fd) ? 1 : 0;
if (stream->tty)
stream->dev = statbuf.st_rdev;
}
else
stream->tty = 0;
if (!(stream->buf = malloc(statbuf.st_blksize))) {
stream->error = 1;
return EOF;
}
stream->buf_size = statbuf.st_blksize;
stream->line_buf = stream->tty;
init_buf(stream);
return 0;
}
static void flush_tty(dev_t dev)
{
FILE *stream;
for (stream = first_open; stream; stream = stream->next)
if (stream->tty && stream->dev == dev && stream->buf && writing_buf(stream))
flush_buf(stream);
}
static int flush_all()
{
int errnum;
FILE *stream;
errnum = 0;
for (stream = first_open; stream; stream = stream->next)
if (stream->buf && writing_buf(stream))
if (flush_buf(stream) == EOF)
if (!errnum)
errnum = errno;
return errnum ? errno = errnum, EOF : 0;
}
static int nbuf_get_byte(FILE *stream)
{
unsigned char b;
if (!io_read(stream, &b, 1))
return EOF;
return b;
}
static int buf_get_byte(FILE *stream)
{
unsigned char b;
b = *stream->buf_cur++;
if (empty_buf(stream))
discard_buf(stream);
return b;
}
static size_t nbuf_get_bytes(FILE *stream, void *ptr, size_t count)
{
return io_read(stream, ptr, count);
}
static size_t buf_get_bytes(FILE *stream, void *ptr, size_t count)
{
size_t avail;
avail = -count_buf(stream);
if (count > avail)
count = avail;
memcpy(ptr, stream->buf_cur, count);
stream->buf_cur += count;
if (empty_buf(stream))
discard_buf(stream);
return count;
}
static int nbuf_put_byte(FILE *stream, int c)
{
unsigned char b;
b = c;
if (io_write(stream, &b, 1) == EOF)
return EOF;
return b;
}
static int buf_put_byte(FILE *stream, int c)
{
unsigned char b;
b = c;
*stream->buf_cur++ = b;
if (stream->line_buf && b == '\n')
if (flush_buf(stream) == EOF)
return EOF;
return b;
}
static size_t nbuf_put_bytes(FILE *stream, const void *ptr, size_t count)
{
return io_write(stream, ptr, count) == 0 ? count : 0;
}
static size_t buf_put_bytes(FILE *stream, const void *ptr, size_t count)
{
size_t avail, n;
unsigned char b;
avail = stream->buf_size - count_buf(stream);
if (count > avail)
count = avail;
if (stream->line_buf) {
n = count;
while (n > 0) {
b = *(const unsigned char *)ptr++;
*stream->buf_cur++ = b;
n--;
if (b == '\n') {
if (flush_buf(stream) == EOF)
return 0;
break;
}
}
return count - n;
}
else {
memcpy(stream->buf_cur, ptr, count);
stream->buf_cur += count;
return count;
}
}
static void reset_state(FILE *stream)
{
stream->state = 0;
}
static int init_read(FILE *stream)
{
switch (stream->state) {
case 0:
if (!stream->access_mode.read) {
errno = EBADF;
stream->error = 1;
return EOF;
}
if (stream->pushed_back) {
stream->state = 1;
return 0;
}
case 2:
default:
if (stream->tty)
flush_tty(stream->dev);
if (stream->eof)
return EOF;
if (!stream->buf) {
if (!stream->auto_buf) {
stream->state = 3;
return 0;
}
if (alloc_buf(stream) == EOF)
return EOF;
}
else if (writing_buf(stream))
if (flush_buf(stream) == EOF)
return EOF;
stream->state = 4;
return 0;
}
}
static int get_byte(FILE *stream)
{
switch (stream->state) {
case 0:
case 2:
if (init_read(stream) == EOF)
return EOF;
}
switch (stream->state) {
case 1:
stream->state = 2;
return pop_byte(stream);
case 3:
return nbuf_get_byte(stream);
case 4:
default:
if (empty_buf(stream))
if (fill_buf(stream) == EOF)
return EOF;
return buf_get_byte(stream);
}
}
static size_t get_bytes(FILE *stream, void *ptr, size_t count)
{
size_t to_read, n;
to_read = count;
do {
switch (stream->state) {
case 0:
case 2:
if (init_read(stream) == EOF)
return 0;
}
switch (stream->state) {
case 1:
*(unsigned char *)ptr++ = pop_byte(stream);
to_read--;
stream->state = 2;
continue;
case 3:
if (!(n = nbuf_get_bytes(stream, ptr, to_read)))
goto end;
ptr += n;
to_read -= n;
continue;
case 4:
if (empty_buf(stream))
if (fill_buf(stream) == EOF)
goto end;
if (!(n = buf_get_bytes(stream, ptr, to_read)))
goto end;
ptr += n;
to_read -= n;
continue;
}
}
while (to_read > 0);
end:
return count - to_read;
}
static int init_write(FILE *stream)
{
if (!stream->access_mode.write) {
errno = EBADF;
stream->error = 1;
return EOF;
}
if (stream->access_mode.append)
stream->offset = -1;
stream->pushed_back = 0;
if (!stream->buf) {
if (!stream->auto_buf) {
stream->state = 1;
return 0;
}
if (alloc_buf(stream) == EOF)
return EOF;
}
else if (reading_buf(stream)) {
if (stream->seekable && !stream->access_mode.append)
if (io_seek(stream, count_buf(stream), SEEK_CUR) == -1 && stream->seekable)
return EOF;
discard_buf(stream);
}
stream->state = 2;
return 0;
}
static int put_byte(FILE *stream, int c)
{
switch (stream->state) {
case 0:
if (init_write(stream) == EOF)
return EOF;
}
switch (stream->state) {
case 1:
return nbuf_put_byte(stream, c);
case 2:
default:
if (full_buf(stream))
if (flush_buf(stream) == EOF)
return EOF;
return buf_put_byte(stream, c);
}
}
static size_t put_bytes(FILE *stream, const void *ptr, size_t count)
{
size_t to_write, n;
to_write = count;
do {
switch (stream->state) {
case 0:
if (init_write(stream) == EOF)
return 0;
}
switch (stream->state) {
case 1:
if (!(n = nbuf_put_bytes(stream, ptr, count)))
goto end;
ptr += n;
to_write -= n;
continue;
case 2:
if (full_buf(stream)) {
if (flush_buf(stream) == EOF)
goto end;
}
if (!(n = buf_put_bytes(stream, ptr, to_write)))
goto end;
ptr += n;
to_write -= n;
}
}
while (to_write > 0);
end:
return count - to_write;
}
static int get_access_mode(const char *mode, struct access_mode_struct *access_mode)
{
switch (*mode++) {
case 'r':
access_mode->read = 1;
access_mode->write = 0;
access_mode->create = 0;
access_mode->truncate = 0;
access_mode->append = 0;
break;
case 'w':
access_mode->read = 0;
access_mode->write = 1;
access_mode->create = 1;
access_mode->truncate = 1;
access_mode->append = 0;
break;
case 'a':
access_mode->read = 0;
access_mode->write = 1;
access_mode->create = 1;
access_mode->truncate = 0;
access_mode->append = 1;
break;
default:
return 0;
}
if (!*mode)
return 1;
if (*mode != '+')
mode++;
if (*mode == '+')
access_mode->write = access_mode->read = 1;
return 1;
}
static int get_oflag(const struct access_mode_struct *access_mode)
{
int oflag;
if (access_mode->read && access_mode->write)
oflag = O_RDWR;
else
oflag = access_mode->read ? O_RDONLY : O_WRONLY;
if (access_mode->truncate)
oflag |= O_TRUNC;
if (access_mode->append)
oflag |= O_APPEND;
return oflag;
}
FILE *stdin __attribute__ ((weak, visibility ("default")));
FILE *stdout __attribute__ ((weak, visibility ("default")));
FILE *stderr __attribute__ ((weak, visibility ("default")));
void __stdio_init()
{
static const struct access_mode_struct stdin_access_mode = {
.read = 1,
.write = 0,
.create = 0,
.truncate = 0,
.append = 0
};
static const struct access_mode_struct stdout_access_mode = {
.read = 0,
.write = 1,
.create = 0,
.truncate = 0,
.append = 0
};
static const struct access_mode_struct stderr_access_mode = {
.read = 1,
.write = 1,
.create = 0,
.truncate = 0,
.append = 0
};
init_stream_table();
stdin = alloc_stream();
attach_stream(stdin, STDIN_FILENO, &stdin_access_mode, 1);
stdout = alloc_stream();
attach_stream(stdout, STDOUT_FILENO, &stdout_access_mode, 1);
stderr = alloc_stream();
attach_stream(stderr, STDERR_FILENO, &stderr_access_mode, 0);
}
void __stdio_fini()
{
FILE *stream;
int fd;
while (first_open) {
stream = first_open;
detach_stream(stream, &fd);
free_stream(stream);
__close(fd);
}
}
static inline int openm(const char *filename, const struct access_mode_struct *access_mode)
{
int oflag;
oflag = get_oflag(access_mode);
if (access_mode->create)
return __open(filename, oflag | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
else
return __open(filename, oflag);
}
FILE __attribute__ ((weak, visibility ("default"))) *fopen(const char *filename, const char *mode)
{
struct access_mode_struct access_mode;
int fd;
FILE *stream;
int errnum;
if (!get_access_mode(mode, &access_mode)) {
errno = EINVAL;
return NULL;
}
if ((fd = openm(filename, &access_mode)) == -1)
return NULL;
if (!(stream = alloc_stream())) {
errnum = errno;
__close(fd);
errno = errnum;
return NULL;
}
attach_stream(stream, fd, &access_mode, 1);
return stream;
}
typeof (fopen) __fopen __attribute__ ((alias ("fopen")));
FILE __attribute__ ((weak, visibility ("default"))) *fdopen(int fd, const char *mode)
{
struct access_mode_struct access_mode;
FILE *stream;
if (!get_access_mode(mode, &access_mode)) {
errno = EINVAL;
return NULL;
}
if (!(stream = alloc_stream()))
return NULL;
attach_stream(stream, fd, &access_mode, 1);
return stream;
}
typeof (fdopen) __fdopen __attribute__ ((alias ("fdopen")));
FILE __attribute__ ((weak, visibility ("default"))) *freopen(const char *filename, const char *mode, FILE *stream)
{
int fd;
struct access_mode_struct access_mode;
int errnum;
if (!filename) {
errno = EINVAL;
return NULL;
}
detach_stream(stream, &fd);
__close(fd);
if (!get_access_mode(mode, &access_mode)) {
errnum = EINVAL;
goto error;
}
if ((fd = openm(filename, &access_mode)) == -1) {
errnum = errno;
goto error;
}
init_stream(stream, fd, &access_mode, 1);
return stream;
error:
free_stream(stream);
errno = errnum;
return NULL;
}
typeof (freopen) __freopen __attribute__ ((alias ("freopen")));
int __attribute__ ((weak, visibility ("default"))) fclose(FILE *stream)
{
int errnum;
int fd;
errnum = 0;
if (detach_stream(stream, &fd) == EOF)
errnum = errno;
free_stream(stream);
if (__close(fd) == -1)
if (!errnum)
errnum = errno;
return errnum ? errno = errnum, EOF : 0;
}
typeof (fclose) __fclose __attribute__ ((alias ("fclose")));
int __attribute__ ((weak, visibility ("default"))) setvbuf(FILE *stream, char *buf, int mode, size_t size)
{
int line_buf;
switch (mode) {
case _IONBF:
goto no_buf;
case _IOLBF:
line_buf = 1;
goto buf;
case _IOFBF:
line_buf = 0;
goto buf;
default:
errno = EINVAL;
return -1;
}
buf:
if (size == 0) {
if (buf)
goto no_buf;
errno = EINVAL;
return -1;
}
return set_buf(stream, buf, size, line_buf);
no_buf:
stream->auto_buf = 0;
stream->buf = NULL;
return 0;
}
typeof (setvbuf) __setvbuf __attribute__ ((alias ("setvbuf")));
void __attribute__ ((weak, visibility ("default"))) setbuf(FILE *stream, char *buf)
{
__setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
}
typeof (setbuf) __setbuf __attribute__ ((alias ("setbuf")));
void __attribute__ ((weak, visibility ("default"))) setbuffer(FILE *stream, char *buf, size_t size)
{
__setvbuf(stream, buf, buf ? _IOFBF : _IONBF, size);
}
typeof (setbuffer) __setbuffer __attribute__ ((alias ("setbuffer")));
void __attribute__ ((weak, visibility ("default"))) setlinebuf(FILE *stream)
{
__setvbuf(stream, NULL, _IOLBF, BUFSIZ);
}
typeof (setlinebuf) __setlinebuf __attribute__ ((alias ("setlinebuf")));
void __attribute__ ((weak, visibility ("default"))) clearerr(FILE *stream)
{
stream->eof = 0;
stream->error = 0;
}
typeof (clearerr) __clearerr __attribute__ ((alias ("clearerr")));
int __attribute__ ((weak, visibility ("default"))) feof(FILE *stream)
{
return stream->eof;
}
typeof (feof) __feof __attribute__ ((alias ("feof")));
int __attribute__ ((weak, visibility ("default"))) ferror(FILE *stream)
{
return stream->error;
}
typeof (ferror) __ferror __attribute__ ((alias ("ferror")));
int __attribute__ ((weak, visibility ("default"))) fileno(FILE *stream)
{
return stream->fd;
}
typeof (fileno) __fileno __attribute__ ((alias ("fileno")));
static inline void adjust_offset(FILE *stream, long *offset)
{
if (stream->buf)
*offset += count_buf(stream);
if (stream->pushed_back)
*offset -= 1;
}
int __attribute__ ((weak, visibility ("default"))) fseek(FILE *stream, long offset, int whence)
{
switch (whence) {
case SEEK_SET:
case SEEK_CUR:
case SEEK_END:
break;
default:
errno = EINVAL;
return -1;
}
if (stream->buf && writing_buf(stream))
if (flush_buf(stream) == EOF)
return -1;
if (whence == SEEK_CUR)
adjust_offset(stream, &offset);
stream->pushed_back = 0;
if (stream->buf && reading_buf(stream))
discard_buf(stream);
if (!stream->seekable) {
errno = ESPIPE;
return -1;
}
if (io_seek(stream, offset, whence) == -1)
return -1;
stream->eof = 0;
return 0;
}
typeof (fseek) __fseek __attribute__ ((alias ("fseek")));
long __attribute__ ((weak, visibility ("default"))) ftell(FILE *stream)
{
long offset;
if (stream->offset == -1) {
if (!stream->seekable) {
errno = ESPIPE;
return -1;
}
if (io_seek(stream, 0, stream->access_mode.append && stream->buf && writing_buf(stream) ? SEEK_END : SEEK_CUR) == -1)
return -1;
}
offset = stream->offset;
adjust_offset(stream, &offset);
return offset;
}
typeof (ftell) __ftell __attribute__ ((alias ("ftell")));
void __attribute__ ((weak, visibility ("default"))) rewind(FILE *stream)
{
__fseek(stream, 0, SEEK_SET);
__clearerr(stream);
}
typeof (rewind) __rewind __attribute__ ((alias ("rewind")));
int __attribute__ ((weak, visibility ("default"))) fgetpos(FILE *stream, fpos_t *pos)
{
return (*pos = __ftell(stream)) == -1 ? -1 : 0;
}
typeof (fgetpos) __fgetpos __attribute__ ((alias ("fgetpos")));
int __attribute__ ((weak, visibility ("default"))) fsetpos(FILE *stream, const fpos_t *pos)
{
return __fseek(stream, *pos, SEEK_SET);
}
typeof (fsetpos) __fsetpos __attribute__ ((alias ("fsetpos")));
int __attribute__ ((weak, visibility ("default"))) fgetc(FILE *stream)
{
reset_state(stream);
return get_byte(stream);
}
typeof (fgetc) __fgetc __attribute__ ((alias ("fgetc")));
char __attribute__ ((weak, visibility ("default"))) *fgets(char *s, int n, FILE *stream)
{
char *ptr;
int c;
if (n == 0)
return NULL;
n--;
ptr = s;
if (n == 0)
goto end;
reset_state(stream);
if ((c = get_byte(stream)) == EOF)
return NULL;
*(unsigned char *)ptr++ = c;
n--;
while (c != '\n' && n > 0) {
if ((c = get_byte(stream)) == EOF) {
if (stream->eof)
break;
return NULL;
}
*(unsigned char *)ptr++ = c;
n--;
}
end:
*ptr = '\0';
return s;
}
typeof (fgets) __fgets __attribute__ ((alias ("fgets")));
int __attribute__ ((weak, visibility ("default"))) getc(FILE *stream)
{
reset_state(stream);
return get_byte(stream);
}
typeof (getc) __getc __attribute__ ((alias ("getc")));
int __attribute__ ((weak, visibility ("default"))) getchar()
{
reset_state(stdin);
return get_byte(stdin);
}
typeof (getchar) __getchar __attribute__ ((alias ("getchar")));
char __attribute__ ((weak, visibility ("default"))) *gets(char *s)
{
char *ptr;
int c;
ptr = s;
reset_state(stdin);
if ((c = get_byte(stdin)) == EOF)
return NULL;
while (c != '\n') {
*(unsigned char *)ptr++ = c;
if ((c = get_byte(stdin)) == EOF) {
if (stdin->eof)
break;
return NULL;
}
}
*ptr = '\0';
return s;
}
typeof (gets) __gets __attribute__ ((alias ("gets")));
int __attribute__ ((weak, visibility ("default"))) ungetc(int c, FILE *stream)
{
if (c == EOF)
return EOF;
if (stream->pushed_back)
return EOF;
push_back_byte(stream, c);
stream->eof = 0;
return (unsigned char)c;
}
typeof (ungetc) __ungetc __attribute__ ((alias ("ungetc")));
int __attribute__ ((weak, visibility ("default"))) fputc(int c, FILE *stream)
{
reset_state(stream);
return put_byte(stream, c);
}
typeof (fputc) __fputc __attribute__ ((alias ("fputc")));
int __attribute__ ((weak, visibility ("default"))) fputs(const char *s, FILE *stream)
{
size_t len;
if (!*s)
return 0;
len = strlen(s);
reset_state(stream);
return put_bytes(stream, s, len) == len ? 0 : EOF;
}
typeof (fputs) __fputs __attribute__ ((alias ("fputs")));
int __attribute__ ((weak, visibility ("default"))) putc(int c, FILE *stream)
{
reset_state(stream);
return put_byte(stream, c);
}
typeof (putc) __putc __attribute__ ((alias ("putc")));
int __attribute__ ((weak, visibility ("default"))) putchar(int c)
{
reset_state(stdout);
return put_byte(stdout, c);
}
typeof (putchar) __putchar __attribute__ ((alias ("putchar")));
int __attribute__ ((weak, visibility ("default"))) puts(const char *s)
{
size_t len;
if (!*s)
return 0;
len = strlen(s);
reset_state(stdout);
if (put_bytes(stdout, s, len) != len)
return EOF;
if (put_byte(stdout, '\n') == EOF)
return EOF;
return 0;
}
typeof (puts) __puts __attribute__ ((alias ("puts")));
size_t __attribute__ ((weak, visibility ("default"))) fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
if (size == 0 || nmemb == 0)
return 0;
reset_state(stream);
return get_bytes(stream, ptr, nmemb * size) / size;
}
typeof (fread) __fread __attribute__ ((alias ("fread")));
size_t __attribute__ ((weak, visibility ("default"))) fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
if (size == 0 || nmemb == 0)
return 0;
reset_state(stream);
return put_bytes(stream, ptr, nmemb * size) / size;
}
typeof (fwrite) __fwrite __attribute__ ((alias ("fwrite")));
int __attribute__ ((weak, visibility ("default"))) fflush(FILE *stream)
{
if (!stream)
return flush_all();
return stream->buf && writing_buf(stream) ? flush_buf(stream) : 0;
}
typeof (fflush) __fflush __attribute__ ((alias ("fflush")));
int __attribute__ ((weak, visibility ("default"))) remove(const char *path)
{
struct stat statbuf;
if (__lstat(path, &statbuf) == -1)
return -1;
if (S_ISDIR(statbuf.st_mode))
return __rmdir(path);
else
return __unlink(path);
}
typeof (remove) __remove __attribute__ ((alias ("remove")));
void __attribute__ ((weak, visibility ("default"))) perror(const char *s)
{
int errnum;
errnum = errno;
if (s && *s)
fprintf(stderr, "%s: ", s);
if (errnum >= 0 && errnum < sys_nerr && sys_errlist[errnum])
fprintf(stderr, "%s\n", sys_errlist[errnum]);
else
fprintf(stderr, "Unknown error %d\n", errnum);
}