aboutsummaryrefslogtreecommitdiffstats
path: root/com32/lib/sys/read.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-08-09 16:13:55 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-08-09 16:45:05 -0700
commitf614a40876843b7de58d8410b47c8c68e2ab6992 (patch)
tree7d0d0d8e42a0a2a019bedb869b58699c208267e1 /com32/lib/sys/read.c
parent8b0f75f79811a30cd3f8460e305c6eea82f288a0 (diff)
downloadsyslinux-f614a40876843b7de58d8410b47c8c68e2ab6992.tar.gz
syslinux-f614a40876843b7de58d8410b47c8c68e2ab6992.tar.xz
syslinux-f614a40876843b7de58d8410b47c8c68e2ab6992.zip
lib: add unread() syscall; use it to implement ungetc()
Add an unread() syscall, which allows some read bytes to be pushed back into the read buffer. This allows us to read a header from a file and then push it back. This also makes ungetc() implementable. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'com32/lib/sys/read.c')
-rw-r--r--com32/lib/sys/read.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/com32/lib/sys/read.c b/com32/lib/sys/read.c
index e097ade1..388f6987 100644
--- a/com32/lib/sys/read.c
+++ b/com32/lib/sys/read.c
@@ -41,11 +41,29 @@
ssize_t read(int fd, void *buf, size_t count)
{
struct file_info *fp = &__file_info[fd];
+ size_t n0, n1;
if (fd >= NFILES || !fp->iop) {
errno = EBADF;
return -1;
}
- return fp->iop->read(fp, buf, count);
+ if (!count)
+ return 0;
+
+ n0 = min(fp->i.unread_bytes, count);
+ if (n0) {
+ memcpy(buf, unread_data(fp), n0);
+ fp->i.unread_bytes -= n0;
+ count -= n0;
+ if (!count)
+ return n0;
+ }
+
+ n1 = fp->iop->read(fp, buf, count);
+
+ if (n1 == -1 && n0 > 0)
+ return n0;
+ else
+ return n0 + n1;
}