diff --git a/games/conway.cpp b/games/conway.cpp
index c2b00b75..a5c63a70 100644
--- a/games/conway.cpp
+++ b/games/conway.cpp
@@ -58,7 +58,7 @@ void Clear()
bool FlushVGA()
{
- return writeall(vgafd, frame, sizeof(frame)) == 0;
+ return writeall(vgafd, frame, sizeof(frame)) < sizeof(frame);
}
int Init()
diff --git a/games/pong.cpp b/games/pong.cpp
index 1cd391f3..21ca3022 100644
--- a/games/pong.cpp
+++ b/games/pong.cpp
@@ -77,7 +77,7 @@ unsigned soundleft;
bool FlushVGA()
{
- return writeall(vgafd, frame, sizeof(frame)) == 0;
+ return writeall(vgafd, frame, sizeof(frame)) < sizeof(frame);
}
int Init()
diff --git a/games/snake.cpp b/games/snake.cpp
index 7b0ac392..4a2de0df 100644
--- a/games/snake.cpp
+++ b/games/snake.cpp
@@ -95,7 +95,7 @@ void Reset()
bool FlushVGA()
{
- return writeall(vgafd, frame, sizeof(frame)) == 0;
+ return writeall(vgafd, frame, sizeof(frame)) < sizeof(frame);
}
int Init()
diff --git a/libmaxsi/Makefile b/libmaxsi/Makefile
index 8ab7a061..face365e 100644
--- a/libmaxsi/Makefile
+++ b/libmaxsi/Makefile
@@ -40,6 +40,7 @@ sortix-sound.o \
process.o \
thread.o \
io.o \
+ioleast.o \
terminal.o \
kernelinfo.o \
init.o \
diff --git a/libmaxsi/include/unistd.h b/libmaxsi/include/unistd.h
index 00e1738c..49f2c160 100644
--- a/libmaxsi/include/unistd.h
+++ b/libmaxsi/include/unistd.h
@@ -178,8 +178,15 @@ ssize_t write(int, const void*, size_t);
#if defined(_SORTIX_SOURCE)
size_t getpagesize(void);
int memstat(size_t* memused, size_t* memtotal);
+size_t preadall(int fd, void* buf, size_t count, off_t off);
+size_t preadleast(int fd, void* buf, size_t least, size_t max, off_t off);
+size_t pwriteall(int fd, const void* buf, size_t count, off_t off);
+size_t pwriteleast(int fd, const void* buf, size_t least, size_t max, off_t off);
+size_t readall(int fd, void* buf, size_t count);
+size_t readleast(int fd, void* buf, size_t least, size_t max);
int uptime(uintmax_t* usecssinceboot);
-int writeall(int fd, const void* buffer, size_t len);
+size_t writeall(int fd, const void* buf, size_t count);
+size_t writeleast(int fd, const void* buf, size_t least, size_t max);
#endif
#if defined(_SORTIX_SOURCE) || defined(_SORTIX_ALWAYS_SBRK)
void* sbrk(intptr_t increment);
diff --git a/libmaxsi/io.cpp b/libmaxsi/io.cpp
index 5c768567..eaa19dbd 100644
--- a/libmaxsi/io.cpp
+++ b/libmaxsi/io.cpp
@@ -63,14 +63,12 @@ namespace Maxsi
size_t Print(const char* string)
{
size_t stringlen = String::Length(string);
- if ( writeall(1, string, stringlen) ) { return 0; }
- return stringlen;
+ return writeall(1, string, stringlen);
}
size_t PrintCallback(void* user, const char* string, size_t stringlen)
{
- if ( writeall(1, string, stringlen) ) { return 0; }
- return stringlen;
+ return writeall(1, string, stringlen);
}
size_t PrintF(const char* format, ...)
@@ -228,20 +226,6 @@ retry:
return result;
}
- extern "C" int writeall(int fd, const void* buffer, size_t len)
- {
- const char* buf = (const char*) buffer;
- while ( len )
- {
- ssize_t byteswritten = write(fd, buf, len);
- if ( byteswritten < 0 ) { return (int) byteswritten; }
- buf += byteswritten;
- len -= byteswritten;
- }
-
- return 0;
- }
-
extern "C" ssize_t pread(int, void*, size_t, off_t)
{
errno = ENOSYS;
diff --git a/libmaxsi/ioleast.cpp b/libmaxsi/ioleast.cpp
new file mode 100644
index 00000000..f4656251
--- /dev/null
+++ b/libmaxsi/ioleast.cpp
@@ -0,0 +1,119 @@
+/*******************************************************************************
+
+ COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2012.
+
+ This file is part of LibMaxsi.
+
+ LibMaxsi is free software: you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ LibMaxsi is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with LibMaxsi. If not, see .
+
+ ioleast.cpp
+ Versions of {,p}{read,write} that don't return until it has returned as much
+ data as requested, end of file, or an error occurs. This is sometimes needed
+ as read(2) and write(2) is not always guaranteed to fill up the entire
+ buffer or write it all.
+
+*******************************************************************************/
+
+#include
+#include
+#include
+#include
+
+#ifndef EEOF
+#define EEOF EIO
+#endif
+
+extern "C" size_t readleast(int fd, void* buf, size_t least, size_t max)
+{
+ ssize_t amount = read(fd, buf, max);
+ if ( amount < 0 ) { return 0; }
+ if ( least && !amount ) { errno = EEOF; return 0; }
+ if ( (size_t) amount < least )
+ {
+ void* nextbuf = (uint8_t*) buf + amount;
+ size_t nextleast = least - amount;
+ size_t nextmax = max - amount;
+ return readleast(fd, nextbuf, nextleast, nextmax);
+ }
+ return amount;
+}
+
+extern "C" size_t readall(int fd, void* buf, size_t count)
+{
+ return readleast(fd, buf, count, count);
+}
+
+extern "C" size_t preadleast(int fd, void* buf, size_t least, size_t max,
+ off_t off)
+{
+ ssize_t amount = pread(fd, buf, max, off);
+ if ( amount < 0 ) { return 0; }
+ if ( least && !amount ) { errno = EEOF; return 0; }
+ if ( (size_t) amount < least )
+ {
+ void* nextbuf = (uint8_t*) buf + amount;
+ size_t nextleast = least - amount;
+ size_t nextmax = max - amount;
+ off_t nextoff = off + amount;
+ return preadleast(fd, nextbuf, nextleast, nextmax, nextoff);
+ }
+ return amount;
+}
+
+extern "C" size_t preadall(int fd, void* buf, size_t count, off_t off)
+{
+ return preadleast(fd, buf, count, count, off);
+}
+
+extern "C" size_t writeleast(int fd, const void* buf, size_t least, size_t max)
+{
+ ssize_t amount = write(fd, buf, max);
+ if ( amount < 0 ) { return 0; }
+ if ( least && !amount ) { errno = EEOF; return 0; }
+ if ( (size_t) amount < least )
+ {
+ const void* nextbuf = (const uint8_t*) buf + amount;
+ size_t nextleast = least - amount;
+ size_t nextmax = max - amount;
+ return writeleast(fd, nextbuf, nextleast, nextmax);
+ }
+ return amount;
+}
+
+extern "C" size_t writeall(int fd, const void* buf, size_t count)
+{
+ return writeleast(fd, buf, count, count);
+}
+
+extern "C" size_t pwriteleast(int fd, const void* buf, size_t least, size_t max,
+ off_t off)
+{
+ ssize_t amount = pwrite(fd, buf, max, off);
+ if ( amount < 0 ) { return 0; }
+ if ( least && !amount ) { errno = EEOF; return 0; }
+ if ( (size_t) amount < least )
+ {
+ const void* nextbuf = (const uint8_t*) buf + amount;
+ size_t nextleast = least - amount;
+ size_t nextmax = max - amount;
+ off_t nextoff = off + amount;
+ return pwriteleast(fd, nextbuf, nextleast, nextmax, nextoff);
+ }
+ return amount;
+}
+
+extern "C" size_t pwriteall(int fd, const void* buf, size_t count, off_t off)
+{
+ return pwriteleast(fd, buf, count, count, off);
+}
diff --git a/utils/cat.cpp b/utils/cat.cpp
index 502f59bf..bd2baf55 100644
--- a/utils/cat.cpp
+++ b/utils/cat.cpp
@@ -41,7 +41,7 @@ int docat(const char* inputname, int fd)
error(0, errno, "read: %s", inputname);
return 1;
}
- if ( writeall(1, buffer, bytesread) )
+ if ( writeall(1, buffer, bytesread) < bytesread )
{
error(0, errno, "write: %s", inputname);
return 1;
diff --git a/utils/cp.cpp b/utils/cp.cpp
index f8b717ee..0af6bbcb 100644
--- a/utils/cp.cpp
+++ b/utils/cp.cpp
@@ -67,6 +67,10 @@ int main(int argc, char* argv[])
ssize_t bytesread = read(fromfd, buffer, BUFFER_SIZE);
if ( bytesread < 0 ) { error(1, errno, "read: %s", frompath); return 1; }
if ( bytesread == 0 ) { return 0; }
- if ( writeall(tofd, buffer, bytesread) ) { error(1, errno, "write: %s", topath); return 1; }
+ if ( writeall(tofd, buffer, bytesread) < bytesread )
+ {
+ error(1, errno, "write: %s", topath);
+ return 1;
+ }
}
}
diff --git a/utils/editor.cpp b/utils/editor.cpp
index 6d09d378..9857640e 100644
--- a/utils/editor.cpp
+++ b/utils/editor.cpp
@@ -304,7 +304,7 @@ bool savetofile(const char* path)
{
size_t len = strlen(buffers[y]);
buffers[y][len] = '\n';
- bool result = !writeall(fd, buffers[y], len+1);
+ bool result = writeall(fd, buffers[y], len+1) == len+1;
buffers[y][len] = 0;
if ( !result ) { error(0, errno, "write: %s", path); close(fd); return false; }
}