From 7984cfc7c18c85c5db42c5c7d57927b12c846ce0 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Sun, 20 Jul 2003 21:11:43 +0000 Subject: * Argh, another short-write problem. Added wrappers around read()/write() to fix this once and for all. --- src/archive.cc | 2 +- src/archive.hh | 2 +- src/nix.cc | 17 +++-------------- src/references.cc | 7 +++---- src/store.cc | 11 +++-------- src/test.cc | 11 +++-------- src/util.cc | 23 +++++++++++++++++++++++ src/util.hh | 6 ++++++ 8 files changed, 43 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/archive.cc b/src/archive.cc index 73fc75fa27d4..9170ca3ad650 100644 --- a/src/archive.cc +++ b/src/archive.cc @@ -190,7 +190,7 @@ static string readString(RestoreSource & source) { unsigned int len = readInt(source); char buf[len]; - source((const unsigned char *) buf, len); + source((unsigned char *) buf, len); readPadding(len, source); return string(buf, len); } diff --git a/src/archive.hh b/src/archive.hh index 7d9b1e2b5676..e6006e454942 100644 --- a/src/archive.hh +++ b/src/archive.hh @@ -54,7 +54,7 @@ struct RestoreSource pointed to by data. It should block if that much data is not yet available, or throw an error if it is not going to be available. */ - virtual void operator () (const unsigned char * data, unsigned int len) = 0; + virtual void operator () (unsigned char * data, unsigned int len) = 0; }; void restorePath(const string & path, RestoreSource & source); diff --git a/src/nix.cc b/src/nix.cc index f5ca0b4d8793..ad4e6a468a0c 100644 --- a/src/nix.cc +++ b/src/nix.cc @@ -215,12 +215,7 @@ struct StdoutSink : DumpSink virtual void operator () (const unsigned char * data, unsigned int len) { - while (len) { - ssize_t res = write(STDOUT_FILENO, (char *) data, len); - if (res == -1) throw SysError("writing to stdout"); - len -= res; - data += res; - } + writeFull(STDOUT_FILENO, data, len); } }; @@ -247,15 +242,9 @@ static void opDump(Strings opFlags, Strings opArgs) /* A source that read restore intput to stdin. */ struct StdinSource : RestoreSource { - virtual void operator () (const unsigned char * data, unsigned int len) + virtual void operator () (unsigned char * data, unsigned int len) { - while (len) { - ssize_t res = read(STDIN_FILENO, (char *) data, len); - if (res == -1) throw SysError("reading from stdin"); - if (res == 0) throw Error("unexpected end-of-file on stdin"); - len -= res; - data += res; - } + readFull(STDIN_FILENO, data, len); } }; diff --git a/src/references.cc b/src/references.cc index a42c1aed02c1..8934d53061cd 100644 --- a/src/references.cc +++ b/src/references.cc @@ -55,12 +55,11 @@ void checkPath(const string & path, int fd = open(path.c_str(), O_RDONLY); if (fd == -1) throw SysError(format("opening file `%1%'") % path); - char * buf = new char[st.st_size]; + unsigned char * buf = new unsigned char[st.st_size]; - if (read(fd, buf, st.st_size) != st.st_size) - throw SysError(format("reading file %1%") % path); + readFull(fd, buf, st.st_size); - search(string(buf, st.st_size), ids, seen); + search(string((char *) buf, st.st_size), ids, seen); delete buf; /* !!! autodelete */ diff --git a/src/store.cc b/src/store.cc index 0ce5f26044fb..6f1a2fc39d1c 100644 --- a/src/store.cc +++ b/src/store.cc @@ -15,8 +15,7 @@ struct CopySink : DumpSink int fd; virtual void operator () (const unsigned char * data, unsigned int len) { - if (write(fd, (char *) data, len) != (ssize_t) len) - throw SysError("writing to child"); + writeFull(fd, data, len); } }; @@ -24,13 +23,9 @@ struct CopySink : DumpSink struct CopySource : RestoreSource { int fd; - virtual void operator () (const unsigned char * data, unsigned int len) + virtual void operator () (unsigned char * data, unsigned int len) { - ssize_t res = read(fd, (char *) data, len); - if (res == -1) - throw SysError("reading from parent"); - if (res != (ssize_t) len) - throw Error("not enough data available on parent"); + readFull(fd, data, len); } }; diff --git a/src/test.cc b/src/test.cc index fa7c93820558..5c7559af6afd 100644 --- a/src/test.cc +++ b/src/test.cc @@ -37,21 +37,16 @@ struct MySink : DumpSink virtual void operator () (const unsigned char * data, unsigned int len) { /* Don't use cout, it's slow as hell! */ - if (write(STDOUT_FILENO, (char *) data, len) != (ssize_t) len) - throw SysError("writing to stdout"); + writeFull(STDOUT_FILENO, data, len); } }; struct MySource : RestoreSource { - virtual void operator () (const unsigned char * data, unsigned int len) + virtual void operator () (unsigned char * data, unsigned int len) { - ssize_t res = read(STDIN_FILENO, (char *) data, len); - if (res == -1) - throw SysError("reading from stdin"); - if (res != (ssize_t) len) - throw Error("not enough data available on stdin"); + readFull(STDIN_FILENO, data, len); } }; diff --git a/src/util.cc b/src/util.cc index d7c1fe60e15a..a16643022a9d 100644 --- a/src/util.cc +++ b/src/util.cc @@ -159,3 +159,26 @@ void debug(const format & f) { msg(format("debug: %1%") % f.str()); } + + +void readFull(int fd, unsigned char * buf, size_t count) +{ + while (count) { + ssize_t res = read(fd, (char *) buf, count); + if (res == -1) throw SysError("reading from file"); + if (res == 0) throw Error("unexpected end-of-file"); + count -= res; + buf += res; + } +} + + +void writeFull(int fd, const unsigned char * buf, size_t count) +{ + while (count) { + ssize_t res = write(fd, (char *) buf, count); + if (res == -1) throw SysError("writing to file"); + count -= res; + buf += res; + } +} diff --git a/src/util.hh b/src/util.hh index 611612a589c6..8b23bee00b76 100644 --- a/src/util.hh +++ b/src/util.hh @@ -85,4 +85,10 @@ void msg(const format & f); void debug(const format & f); +/* Wrappers arount read()/write() that read/write exactly the + requested number of bytes. */ +void readFull(int fd, unsigned char * buf, size_t count); +void writeFull(int fd, const unsigned char * buf, size_t count); + + #endif /* !__UTIL_H */ -- cgit 1.4.1