diff options
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/files.c | 55 |
1 files changed, 36 insertions, 19 deletions
diff --git a/src/tools/files.c b/src/tools/files.c index b3b516ea..27ebf72d 100644 --- a/src/tools/files.c +++ b/src/tools/files.c @@ -402,7 +402,7 @@ static int copy_file(const char *src, int ifd = -1; int ofd = -1; char buf[1024]; - ssize_t cnt, written, offset; + ssize_t cnt, written, res; struct stat fstatbuf; ifd = open(src, O_RDONLY); @@ -454,27 +454,44 @@ static int copy_file(const char *src, goto fail; } - while ((cnt = read(ifd, buf, sizeof(buf))) > 0) { - offset = 0; - while (cnt > 0) { - written = write(ofd, buf+offset, (size_t)cnt); - if (written == -1) { - ret = errno; - DEBUG(1, ("Cannot write() to source file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - goto fail; + while ((cnt = read(ifd, buf, sizeof(buf))) != 0) { + if (cnt == -1) { + if (errno == EINTR || errno == EAGAIN) { + continue; } - offset += written; - cnt -= written; + + DEBUG(1, ("Cannot read() from source file '%s': [%d][%s].\n", + src, ret, strerror(ret))); + goto fail; + } + else if (cnt > 0) { + /* Copy the buffer to the new file */ + written = 0; + while (written < cnt) { + res = write(ofd, buf+written, (size_t)cnt-written); + if (res == -1) { + ret = errno; + if (ret == EINTR || ret == EAGAIN) { + /* retry the write */ + continue; + } + DEBUG(1, ("Cannot write() to destination file '%s': [%d][%s].\n", + dst, ret, strerror(ret))); + goto fail; + } + else if (res <= 0) { + DEBUG(1, ("Unexpected result from write(): [%d]\n", res)); + goto fail; + } + + written += res; + } + } + else { + DEBUG(1, ("Unexpected return code of read [%d]\n", cnt)); + goto fail; } } - if (cnt == -1) { - ret = errno; - DEBUG(1, ("Cannot read() from source file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - goto fail; - } - ret = close(ifd); ifd = -1; |