Files
osdev/libc/stdio.c
T
2018-10-01 17:25:57 -04:00

108 lines
2.3 KiB
C

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <malloc.h>
int __towrite(FILE *f) {
f->mode |= f->mode - 1;
if (f->flags & F_NOWR) {
f->flags |= F_ERR;
return EOF;
}
/* Clear read buffer (easier than summoning nasal demons) */
f->rpos = f->rend = 0;
/* Activate write through the buffer. */
f->wpos = f->wbase = f->buf;
f->wend = f->buf + f->buf_size;
return 0;
}
size_t __fwritex(const char *restrict s, size_t l, FILE *restrict f) {
size_t i = 0;
if (!f->wend && __towrite(f)) return 0;
if (l > f->wend - f->wpos) return f->write(f, s, l);
if (f->lbf >= 0) {
/* Match /^(.*\n|)/ */
for (i = l; i && s[i - 1] != '\n'; i--);
if (i) {
if (f->write(f, s, i) < i)
return i;
s += i;
l -= i;
}
}
memcpy(f->wpos, s, l);
f->wpos += l;
return l + i;
}
size_t fwrite(const void *restrict src, size_t size, size_t count, FILE *restrict f) {
size_t k, l = size * count;
if (!l) return l;
k = __fwritex(src, l, f);
return k == l ? count : k / size;
}
int fflush(FILE *f) {
/* If writing, flush output */
if (f->wpos != f->wbase) {
f->write(f, 0, 0);
if (!f->wpos) {
return EOF;
}
}
/* If reading, sync position, per POSIX */
if (f->rpos != f->rend) f->seek(f, f->rpos - f->rend, SEEK_CUR);
/* Clear read and write modes */
f->wpos = f->wbase = f->wend = 0;
f->rpos = f->rend = 0;
return 0;
}
int fclose(FILE *f) {
int r;
int perm;
if (!(perm = f->flags & F_PERM)) {
if (f->prev) f->prev->next = f->next;
if (f->next) f->next->prev = f->prev;
}
r = fflush(f);
r |= f->close(f);
// free(f->getln_buf); FIXME not implemented
if (!perm) free(f);
return r;
}
long ftell(FILE *f) {
off_t pos = f->seek(f, 0,
(f->flags & F_APP) && f->wpos != f->wbase
? SEEK_END : SEEK_CUR);
if (pos >= 0) {
/* Adjust for data in buffer. */
if (f->rend)
pos += f->rpos - f->rend;
else if (f->wbase)
pos += f->wpos - f->wbase;
}
if (pos > LONG_MAX) {
errno = EOVERFLOW;
return -1;
}
return (long) pos;
}