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; } }