2018-02-25 08:13:54 +03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <syscall.h>
|
|
|
|
#include <string.h>
|
2018-05-04 11:53:31 +03:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
2018-05-08 16:39:30 +03:00
|
|
|
#include <fcntl.h>
|
2018-07-18 04:45:42 +03:00
|
|
|
#include <errno.h>
|
2018-02-25 08:13:54 +03:00
|
|
|
|
2018-05-04 11:53:31 +03:00
|
|
|
struct _FILE {
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
char * read_buf;
|
|
|
|
int available;
|
|
|
|
int offset;
|
|
|
|
int read_from;
|
|
|
|
int ungetc;
|
2018-05-08 16:49:53 +03:00
|
|
|
int eof;
|
2018-06-25 06:11:33 +03:00
|
|
|
int bufsiz;
|
2018-10-12 09:03:22 +03:00
|
|
|
long last_read_start;
|
|
|
|
char * _name;
|
2021-04-07 05:38:31 +03:00
|
|
|
|
|
|
|
char * write_buf;
|
|
|
|
size_t written;
|
|
|
|
size_t wbufsiz;
|
2021-04-07 13:08:06 +03:00
|
|
|
|
|
|
|
struct _FILE * prev;
|
|
|
|
struct _FILE * next;
|
2018-05-04 11:53:31 +03:00
|
|
|
};
|
|
|
|
|
2018-02-25 08:13:54 +03:00
|
|
|
FILE _stdin = {
|
|
|
|
.fd = 0,
|
2018-05-04 11:53:31 +03:00
|
|
|
.read_buf = NULL,
|
|
|
|
.available = 0,
|
|
|
|
.offset = 0,
|
|
|
|
.read_from = 0,
|
|
|
|
.ungetc = -1,
|
2018-05-08 16:49:53 +03:00
|
|
|
.eof = 0,
|
2018-10-12 09:03:22 +03:00
|
|
|
.last_read_start = 0,
|
2018-06-25 06:11:33 +03:00
|
|
|
.bufsiz = BUFSIZ,
|
2021-04-07 05:38:31 +03:00
|
|
|
|
|
|
|
.wbufsiz = BUFSIZ,
|
|
|
|
.write_buf = NULL,
|
|
|
|
.written = 0,
|
2018-02-25 08:13:54 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
FILE _stdout = {
|
|
|
|
.fd = 1,
|
2018-05-04 11:53:31 +03:00
|
|
|
.read_buf = NULL,
|
|
|
|
.available = 0,
|
|
|
|
.offset = 0,
|
|
|
|
.read_from = 0,
|
|
|
|
.ungetc = -1,
|
2018-05-08 16:49:53 +03:00
|
|
|
.eof = 0,
|
2018-10-12 09:03:22 +03:00
|
|
|
.last_read_start = 0,
|
2018-06-25 06:11:33 +03:00
|
|
|
.bufsiz = BUFSIZ,
|
2021-04-07 05:38:31 +03:00
|
|
|
|
|
|
|
.wbufsiz = BUFSIZ,
|
|
|
|
.write_buf = NULL,
|
|
|
|
.written = 0,
|
2018-02-25 08:13:54 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
FILE _stderr = {
|
|
|
|
.fd = 2,
|
2018-05-04 11:53:31 +03:00
|
|
|
.read_buf = NULL,
|
|
|
|
.available = 0,
|
|
|
|
.offset = 0,
|
|
|
|
.read_from = 0,
|
|
|
|
.ungetc = -1,
|
2018-05-08 16:49:53 +03:00
|
|
|
.eof = 0,
|
2018-10-12 09:03:22 +03:00
|
|
|
.last_read_start = 0,
|
2018-06-25 06:11:33 +03:00
|
|
|
.bufsiz = BUFSIZ,
|
2021-04-07 05:38:31 +03:00
|
|
|
|
|
|
|
.wbufsiz = BUFSIZ,
|
|
|
|
.write_buf = NULL,
|
|
|
|
.written = 0,
|
2018-02-25 08:13:54 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
FILE * stdin = &_stdin;
|
|
|
|
FILE * stdout = &_stdout;
|
|
|
|
FILE * stderr = &_stderr;
|
|
|
|
|
2021-04-07 13:08:06 +03:00
|
|
|
static FILE * _head = NULL;
|
|
|
|
|
2018-05-04 11:53:31 +03:00
|
|
|
void __stdio_init_buffers(void) {
|
|
|
|
_stdin.read_buf = malloc(BUFSIZ);
|
2021-04-07 05:38:31 +03:00
|
|
|
_stdout.write_buf = malloc(BUFSIZ);
|
|
|
|
_stderr.write_buf = malloc(BUFSIZ);
|
2018-10-12 09:03:22 +03:00
|
|
|
_stdin._name = strdup("stdin");
|
|
|
|
_stdout._name = strdup("stdout");
|
|
|
|
_stderr._name = strdup("stderr");
|
2018-05-04 11:53:31 +03:00
|
|
|
}
|
|
|
|
|
2021-04-07 13:08:06 +03:00
|
|
|
void __stdio_cleanup(void) {
|
|
|
|
if (stdout) fflush(stdout);
|
|
|
|
if (stderr) fflush(stderr);
|
|
|
|
while (_head) {
|
|
|
|
fclose(_head);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-04 11:53:31 +03:00
|
|
|
#if 0
|
|
|
|
static char * stream_id(FILE * stream) {
|
|
|
|
static char out[] = "stream\0\0\0\0\0\0";
|
|
|
|
if (stream == &_stdin) return "stdin";
|
|
|
|
if (stream == &_stdout) return "stdout";
|
|
|
|
if (stream == &_stderr) return "stderr";
|
|
|
|
sprintf(out, "stream %d", fileno(stream));
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-10-12 09:03:22 +03:00
|
|
|
extern int __libc_debug;
|
2018-05-04 11:53:31 +03:00
|
|
|
extern char * _argv_0;
|
|
|
|
|
2018-06-25 06:11:33 +03:00
|
|
|
int setvbuf(FILE * stream, char * buf, int mode, size_t size) {
|
|
|
|
if (mode != _IOLBF) {
|
|
|
|
return -1; /* Unsupported */
|
|
|
|
}
|
|
|
|
if (buf) {
|
|
|
|
if (stream->read_buf) {
|
|
|
|
free(stream->read_buf);
|
|
|
|
}
|
2018-07-01 03:30:16 +03:00
|
|
|
stream->read_buf = buf;
|
2018-06-25 06:11:33 +03:00
|
|
|
stream->bufsiz = size;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2018-05-04 11:53:31 +03:00
|
|
|
|
2021-04-07 05:38:31 +03:00
|
|
|
int fflush(FILE * stream) {
|
|
|
|
if (!stream->write_buf) return EOF;
|
2021-04-07 15:22:23 +03:00
|
|
|
if (stream->written) {
|
|
|
|
syscall_write(stream->fd, stream->write_buf, stream->written);
|
|
|
|
stream->written = 0;
|
|
|
|
}
|
2021-04-07 05:38:31 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t write_bytes(FILE * f, char * buf, size_t len) {
|
|
|
|
if (!f->write_buf) return 0;
|
|
|
|
|
|
|
|
size_t newBytes = 0;
|
|
|
|
while (len > 0) {
|
|
|
|
f->write_buf[f->written++] = *buf;
|
2021-05-31 04:47:02 +03:00
|
|
|
if (f->written == (size_t)f->wbufsiz || *buf == '\n') {
|
2021-04-07 05:38:31 +03:00
|
|
|
fflush(f);
|
|
|
|
}
|
|
|
|
newBytes++;
|
|
|
|
buf++;
|
|
|
|
len--;
|
|
|
|
}
|
|
|
|
|
|
|
|
return newBytes;
|
|
|
|
}
|
|
|
|
|
2018-05-04 11:53:31 +03:00
|
|
|
static size_t read_bytes(FILE * f, char * out, size_t len) {
|
|
|
|
size_t r_out = 0;
|
|
|
|
|
|
|
|
//fprintf(stderr, "%s: Read %d bytes from %s\n", _argv_0, len, stream_id(f));
|
|
|
|
//fprintf(stderr, "%s: off[%d] avail[%d] read[%d]\n", _argv_0, f->offset, f->available, f->read_from);
|
|
|
|
|
|
|
|
while (len > 0) {
|
|
|
|
if (f->ungetc >= 0) {
|
|
|
|
*out = f->ungetc;
|
|
|
|
len--;
|
|
|
|
out++;
|
|
|
|
r_out++;
|
|
|
|
f->ungetc = -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (f->available == 0) {
|
2018-06-25 06:11:33 +03:00
|
|
|
if (f->offset == f->bufsiz) {
|
2018-05-04 11:53:31 +03:00
|
|
|
f->offset = 0;
|
|
|
|
}
|
2021-05-31 04:47:02 +03:00
|
|
|
f->last_read_start = syscall_seek(f->fd, 0, SEEK_CUR);
|
2018-06-25 06:11:33 +03:00
|
|
|
ssize_t r = read(fileno(f), &f->read_buf[f->offset], f->bufsiz - f->offset);
|
2018-05-04 11:53:31 +03:00
|
|
|
if (r < 0) {
|
|
|
|
//fprintf(stderr, "error condition\n");
|
|
|
|
return r_out;
|
|
|
|
} else {
|
|
|
|
f->read_from = f->offset;
|
|
|
|
f->available = r;
|
|
|
|
f->offset += f->available;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (f->available == 0) {
|
|
|
|
/* EOF condition */
|
|
|
|
//fprintf(stderr, "%s: no bytes available, returning read value of %d\n", _argv_0, r_out);
|
2018-05-08 16:49:53 +03:00
|
|
|
f->eof = 1;
|
2018-05-04 11:53:31 +03:00
|
|
|
return r_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
//fprintf(stderr, "%s: reading until %d reaches %d or %d reaches 0\n", _argv_0, f->read_from, f->offset, len);
|
2018-07-01 03:30:16 +03:00
|
|
|
while (f->read_from < f->offset && len > 0 && f->available > 0) {
|
2018-05-04 11:53:31 +03:00
|
|
|
*out = f->read_buf[f->read_from];
|
|
|
|
len--;
|
|
|
|
f->read_from++;
|
|
|
|
f->available--;
|
|
|
|
out++;
|
|
|
|
r_out += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//fprintf(stderr, "%s: read completed, returning read value of %d\n", _argv_0, r_out);
|
|
|
|
return r_out;
|
|
|
|
}
|
|
|
|
|
2018-06-25 06:11:33 +03:00
|
|
|
static void parse_mode(const char * mode, int * flags_, int * mask_) {
|
2018-02-25 11:14:43 +03:00
|
|
|
const char * x = mode;
|
|
|
|
|
|
|
|
int flags = 0;
|
2018-07-18 09:35:52 +03:00
|
|
|
int mask = 0644;
|
2018-02-25 11:14:43 +03:00
|
|
|
|
|
|
|
while (*x) {
|
|
|
|
if (*x == 'a') {
|
2018-05-08 16:39:30 +03:00
|
|
|
flags |= O_WRONLY;
|
|
|
|
flags |= O_APPEND;
|
|
|
|
flags |= O_CREAT;
|
2018-02-25 11:14:43 +03:00
|
|
|
}
|
|
|
|
if (*x == 'w') {
|
2018-05-08 16:39:30 +03:00
|
|
|
flags |= O_WRONLY;
|
2018-07-01 11:11:35 +03:00
|
|
|
flags |= O_CREAT;
|
2018-07-17 11:08:58 +03:00
|
|
|
flags |= O_TRUNC;
|
2018-07-01 11:11:35 +03:00
|
|
|
mask = 0666;
|
2018-02-25 11:14:43 +03:00
|
|
|
}
|
|
|
|
if (*x == '+') {
|
2018-07-17 11:08:58 +03:00
|
|
|
flags |= O_RDWR;
|
2018-07-17 13:44:15 +03:00
|
|
|
flags &= ~(O_APPEND); /* uh... */
|
2018-02-25 11:14:43 +03:00
|
|
|
}
|
|
|
|
++x;
|
|
|
|
}
|
|
|
|
|
2018-06-25 06:11:33 +03:00
|
|
|
*flags_ = flags;
|
|
|
|
*mask_ = mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FILE * fopen(const char *path, const char *mode) {
|
|
|
|
|
|
|
|
int flags, mask;
|
|
|
|
parse_mode(mode, &flags, &mask);
|
2018-02-25 11:14:43 +03:00
|
|
|
int fd = syscall_open(path, flags, mask);
|
2018-02-25 08:13:54 +03:00
|
|
|
|
|
|
|
if (fd < 0) {
|
2018-07-18 04:45:42 +03:00
|
|
|
errno = -fd;
|
2018-02-25 08:13:54 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
FILE * out = malloc(sizeof(FILE));
|
2018-10-12 09:03:22 +03:00
|
|
|
memset(out, 0, sizeof(struct _FILE));
|
2018-02-25 08:13:54 +03:00
|
|
|
out->fd = fd;
|
2018-05-04 11:53:31 +03:00
|
|
|
out->read_buf = malloc(BUFSIZ);
|
2018-06-25 06:11:33 +03:00
|
|
|
out->bufsiz = BUFSIZ;
|
2018-05-04 11:53:31 +03:00
|
|
|
out->available = 0;
|
|
|
|
out->read_from = 0;
|
|
|
|
out->offset = 0;
|
|
|
|
out->ungetc = -1;
|
2018-05-08 16:49:53 +03:00
|
|
|
out->eof = 0;
|
2018-10-12 09:03:22 +03:00
|
|
|
out->_name = strdup(path);
|
2018-02-25 08:13:54 +03:00
|
|
|
|
2021-04-07 05:38:31 +03:00
|
|
|
out->write_buf = malloc(BUFSIZ);
|
|
|
|
out->written = 0;
|
|
|
|
out->wbufsiz = BUFSIZ;
|
|
|
|
|
2021-04-07 13:08:06 +03:00
|
|
|
out->next = _head;
|
|
|
|
if (_head) _head->prev = out;
|
|
|
|
_head = out;
|
|
|
|
|
2018-02-25 08:13:54 +03:00
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2018-06-25 06:11:33 +03:00
|
|
|
/* This is very wrong */
|
|
|
|
FILE * freopen(const char *path, const char *mode, FILE * stream) {
|
|
|
|
|
|
|
|
if (path) {
|
2021-04-07 15:22:23 +03:00
|
|
|
fflush(stream);
|
|
|
|
syscall_close(stream->fd);
|
2018-06-25 06:11:33 +03:00
|
|
|
int flags, mask;
|
|
|
|
parse_mode(mode, &flags, &mask);
|
|
|
|
int fd = syscall_open(path, flags, mask);
|
|
|
|
stream->fd = fd;
|
|
|
|
stream->available = 0;
|
|
|
|
stream->read_from = 0;
|
|
|
|
stream->offset = 0;
|
|
|
|
stream->ungetc = -1;
|
|
|
|
stream->eof = 0;
|
2018-10-12 09:03:22 +03:00
|
|
|
stream->_name = strdup(path);
|
2021-04-07 05:38:31 +03:00
|
|
|
stream->written = 0;
|
2021-04-07 15:22:23 +03:00
|
|
|
if (stream != &_stdin && stream != &_stdout && stream != &_stderr) {
|
|
|
|
stream->next = _head;
|
|
|
|
if (_head) _head->prev = stream;
|
|
|
|
_head = stream;
|
|
|
|
}
|
2018-06-25 06:11:33 +03:00
|
|
|
if (fd < 0) {
|
2018-07-18 04:45:42 +03:00
|
|
|
errno = -fd;
|
2018-06-25 06:11:33 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
|
2018-05-04 11:53:31 +03:00
|
|
|
int ungetc(int c, FILE * stream) {
|
|
|
|
if (stream->ungetc > 0)
|
|
|
|
return EOF;
|
|
|
|
|
|
|
|
return (stream->ungetc = c);
|
|
|
|
}
|
|
|
|
|
2018-02-25 11:14:43 +03:00
|
|
|
FILE * fdopen(int fd, const char *mode){
|
|
|
|
FILE * out = malloc(sizeof(FILE));
|
2018-10-12 09:03:22 +03:00
|
|
|
memset(out, 0, sizeof(struct _FILE));
|
2018-02-25 11:14:43 +03:00
|
|
|
out->fd = fd;
|
2018-05-04 11:53:31 +03:00
|
|
|
out->read_buf = malloc(BUFSIZ);
|
2018-06-25 06:11:33 +03:00
|
|
|
out->bufsiz = BUFSIZ;
|
2018-05-04 11:53:31 +03:00
|
|
|
out->available = 0;
|
|
|
|
out->read_from = 0;
|
|
|
|
out->offset = 0;
|
|
|
|
out->ungetc = -1;
|
2018-05-08 16:49:53 +03:00
|
|
|
out->eof = 0;
|
2021-04-07 05:38:31 +03:00
|
|
|
|
2018-10-12 09:03:22 +03:00
|
|
|
char tmp[30];
|
|
|
|
sprintf(tmp, "fd[%d]", fd);
|
|
|
|
out->_name = strdup(tmp);
|
2018-02-25 11:14:43 +03:00
|
|
|
|
2021-04-07 05:38:31 +03:00
|
|
|
out->write_buf = malloc(BUFSIZ);
|
|
|
|
out->written = 0;
|
|
|
|
out->wbufsiz = BUFSIZ;
|
|
|
|
|
2021-04-07 13:08:18 +03:00
|
|
|
out->next = _head;
|
|
|
|
if (_head) _head->prev = out;
|
|
|
|
_head = out;
|
|
|
|
|
2018-02-25 11:14:43 +03:00
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2018-05-15 06:39:38 +03:00
|
|
|
int _fwouldblock(FILE * stream) {
|
|
|
|
return !stream->available;
|
|
|
|
}
|
|
|
|
|
2018-02-25 08:13:54 +03:00
|
|
|
int fclose(FILE * stream) {
|
2021-04-07 05:38:31 +03:00
|
|
|
fflush(stream);
|
2018-05-04 11:53:31 +03:00
|
|
|
int out = syscall_close(stream->fd);
|
2018-10-12 09:03:22 +03:00
|
|
|
free(stream->_name);
|
2018-05-04 11:53:31 +03:00
|
|
|
free(stream->read_buf);
|
2021-04-07 13:08:06 +03:00
|
|
|
if (stream->write_buf) free(stream->write_buf);
|
2021-04-07 15:22:23 +03:00
|
|
|
stream->write_buf = NULL;
|
2018-05-04 11:53:31 +03:00
|
|
|
if (stream == &_stdin || stream == &_stdout || stream == &_stderr) {
|
|
|
|
return out;
|
|
|
|
} else {
|
2021-04-07 13:08:06 +03:00
|
|
|
|
|
|
|
if (stream->prev) stream->prev->next = stream->next;
|
|
|
|
if (stream->next) stream->next->prev = stream->prev;
|
|
|
|
if (stream == _head) _head = stream->next;
|
|
|
|
|
2018-05-04 11:53:31 +03:00
|
|
|
free(stream);
|
|
|
|
return out;
|
|
|
|
}
|
2018-02-25 08:13:54 +03:00
|
|
|
}
|
|
|
|
|
2018-10-12 09:03:22 +03:00
|
|
|
static char * _whence_str(int whence) {
|
|
|
|
if (whence == SEEK_SET) return "SEEK_SET";
|
|
|
|
if (whence == SEEK_CUR) return "SEEK_CUR";
|
|
|
|
if (whence == SEEK_END) return "SEEK_END";
|
|
|
|
return "?";
|
|
|
|
}
|
|
|
|
|
2018-02-25 08:13:54 +03:00
|
|
|
int fseek(FILE * stream, long offset, int whence) {
|
2021-06-05 13:49:09 +03:00
|
|
|
if (stream->read_from && whence == SEEK_CUR) {
|
|
|
|
if (_argv_0 && strcmp(_argv_0, "ld.so")) {
|
2018-10-12 09:03:22 +03:00
|
|
|
if (__libc_debug) {
|
|
|
|
fprintf(stderr, "%s: fseek(%s, %ld, %s)\n", _argv_0, stream->_name, offset, _whence_str(whence));
|
|
|
|
fprintf(stderr, "\033[33;3mWARNING\033[0m: seeking when offset is currently %d\n", stream->read_from);
|
|
|
|
fprintf(stderr, "\033[33;3mWARNING\033[0m: this may not be reflected in kernel\n");
|
|
|
|
}
|
|
|
|
}
|
2021-06-05 13:49:09 +03:00
|
|
|
offset = offset + stream->read_from + stream->last_read_start;
|
|
|
|
whence = SEEK_SET;
|
2018-10-12 09:03:22 +03:00
|
|
|
}
|
2021-04-07 13:08:18 +03:00
|
|
|
if (stream->written) {
|
|
|
|
fflush(stream);
|
|
|
|
}
|
2018-05-04 11:53:31 +03:00
|
|
|
stream->offset = 0;
|
|
|
|
stream->read_from = 0;
|
|
|
|
stream->available = 0;
|
|
|
|
stream->ungetc = -1;
|
2018-05-08 16:49:53 +03:00
|
|
|
stream->eof = 0;
|
2018-05-04 11:53:31 +03:00
|
|
|
|
2021-05-31 04:47:02 +03:00
|
|
|
int resp = syscall_seek(stream->fd,offset,whence);
|
2018-02-25 08:13:54 +03:00
|
|
|
if (resp < 0) {
|
2018-07-18 04:45:42 +03:00
|
|
|
errno = -resp;
|
2018-02-25 08:13:54 +03:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
long ftell(FILE * stream) {
|
2018-10-12 09:03:22 +03:00
|
|
|
if (_argv_0 && strcmp(_argv_0, "ld.so") && __libc_debug) {
|
|
|
|
fprintf(stderr, "%s: ftell(%s)\n", _argv_0, stream->_name);
|
|
|
|
}
|
2021-04-07 13:08:18 +03:00
|
|
|
if (stream->written) {
|
|
|
|
fflush(stream);
|
|
|
|
}
|
2018-10-12 09:40:04 +03:00
|
|
|
if (stream->read_from || stream->last_read_start) {
|
|
|
|
return stream->last_read_start + stream->read_from;
|
|
|
|
}
|
2018-05-04 11:53:31 +03:00
|
|
|
stream->offset = 0;
|
|
|
|
stream->read_from = 0;
|
|
|
|
stream->available = 0;
|
|
|
|
stream->ungetc = -1;
|
2018-05-08 16:49:53 +03:00
|
|
|
stream->eof = 0;
|
2021-05-31 04:47:02 +03:00
|
|
|
long resp = syscall_seek(stream->fd, 0, SEEK_CUR);
|
2018-07-18 04:45:42 +03:00
|
|
|
if (resp < 0) {
|
|
|
|
errno = -resp;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return resp;
|
2018-02-25 08:13:54 +03:00
|
|
|
}
|
|
|
|
|
2018-10-12 04:35:28 +03:00
|
|
|
int fgetpos(FILE *stream, fpos_t *pos) {
|
|
|
|
long ret = ftell(stream);
|
|
|
|
if (ret == -1) return -1;
|
|
|
|
|
|
|
|
*pos = ret;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int fsetpos(FILE *stream, const fpos_t *pos) {
|
|
|
|
return fseek(stream, *pos, SEEK_SET);
|
|
|
|
}
|
|
|
|
|
2018-02-25 08:13:54 +03:00
|
|
|
size_t fread(void *ptr, size_t size, size_t nmemb, FILE * stream) {
|
|
|
|
char * tracking = (char*)ptr;
|
|
|
|
for (size_t i = 0; i < nmemb; ++i) {
|
2018-05-04 11:53:31 +03:00
|
|
|
int r = read_bytes(stream, tracking, size);
|
2018-02-25 08:13:54 +03:00
|
|
|
if (r < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
tracking += r;
|
2018-04-25 15:39:55 +03:00
|
|
|
if (r < (int)size) {
|
2018-02-25 08:13:54 +03:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nmemb;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE * stream) {
|
2021-04-07 05:38:31 +03:00
|
|
|
char * tracking = (char*)ptr;
|
|
|
|
for (size_t i = 0; i < nmemb; ++i) {
|
|
|
|
int r = write_bytes(stream, tracking, size);
|
|
|
|
if (r < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
tracking += r;
|
|
|
|
if (r < (int)size) {
|
|
|
|
return i;
|
|
|
|
}
|
2018-02-25 08:13:54 +03:00
|
|
|
}
|
2021-04-07 05:38:31 +03:00
|
|
|
return nmemb;
|
2018-02-25 08:13:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int fileno(FILE * stream) {
|
|
|
|
return stream->fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
int fputs(const char *s, FILE *stream) {
|
2021-04-07 05:38:31 +03:00
|
|
|
while (*s) {
|
|
|
|
fputc(*s++, stream);
|
|
|
|
}
|
2018-02-25 08:13:54 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int fputc(int c, FILE *stream) {
|
|
|
|
char data[] = {c};
|
2021-04-07 05:38:31 +03:00
|
|
|
write_bytes(stream, data, 1);
|
2018-02-25 08:13:54 +03:00
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2018-08-21 15:50:52 +03:00
|
|
|
int putc(int c, FILE *stream) __attribute__((weak, alias("fputc")));
|
|
|
|
|
2018-02-25 08:13:54 +03:00
|
|
|
int fgetc(FILE * stream) {
|
|
|
|
char buf[1];
|
|
|
|
int r;
|
|
|
|
r = fread(buf, 1, 1, stream);
|
|
|
|
if (r < 0) {
|
2018-05-08 16:49:53 +03:00
|
|
|
stream->eof = 1;
|
2018-02-25 08:13:54 +03:00
|
|
|
return EOF;
|
|
|
|
} else if (r == 0) {
|
2018-05-08 16:49:53 +03:00
|
|
|
stream->eof = 1;
|
2018-03-03 14:23:13 +03:00
|
|
|
return EOF;
|
2018-02-25 08:13:54 +03:00
|
|
|
}
|
2018-05-14 16:31:13 +03:00
|
|
|
return (unsigned char)buf[0];
|
2018-02-25 08:13:54 +03:00
|
|
|
}
|
|
|
|
|
2018-08-21 15:50:52 +03:00
|
|
|
int getc(FILE * stream) __attribute__((weak, alias("fgetc")));
|
|
|
|
|
|
|
|
int getchar(void) {
|
|
|
|
return fgetc(stdin);
|
|
|
|
}
|
|
|
|
|
2018-02-25 08:13:54 +03:00
|
|
|
char *fgets(char *s, int size, FILE *stream) {
|
|
|
|
int c;
|
|
|
|
char * out = s;
|
|
|
|
while ((c = fgetc(stream)) > 0) {
|
|
|
|
*s++ = c;
|
2018-05-04 11:53:31 +03:00
|
|
|
size--;
|
|
|
|
if (size == 0) {
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
*s = '\0';
|
2018-02-25 08:13:54 +03:00
|
|
|
if (c == '\n') {
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (c == EOF) {
|
2018-05-08 16:49:53 +03:00
|
|
|
stream->eof = 1;
|
2018-02-25 08:13:54 +03:00
|
|
|
if (out == s) {
|
|
|
|
return NULL;
|
|
|
|
} else {
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-02-25 11:14:43 +03:00
|
|
|
|
2018-05-04 11:53:31 +03:00
|
|
|
int putchar(int c) {
|
|
|
|
return fputc(c, stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
void rewind(FILE *stream) {
|
|
|
|
fseek(stream, 0, SEEK_SET);
|
|
|
|
}
|
|
|
|
|
2018-02-25 11:14:43 +03:00
|
|
|
void setbuf(FILE * stream, char * buf) {
|
|
|
|
// ...
|
|
|
|
}
|
2018-05-08 16:49:53 +03:00
|
|
|
|
|
|
|
int feof(FILE * stream) {
|
|
|
|
return stream->eof;
|
|
|
|
}
|
2018-05-09 11:02:31 +03:00
|
|
|
|
|
|
|
void clearerr(FILE * stream) {
|
|
|
|
stream->eof = 0;
|
|
|
|
}
|
2018-06-25 06:11:33 +03:00
|
|
|
|
|
|
|
int ferror(FILE * stream) {
|
|
|
|
return 0; /* TODO */
|
|
|
|
}
|