From: Rose Date: Wed, 11 Jun 2025 19:21:46 +0000 (-0400) Subject: Fix error checking in writing files X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F2672%2Fhead;p=thirdparty%2Flibarchive.git Fix error checking in writing files For write, 0 may not mean an error at all. We need to instead check for the length not being the same. With fwrite, because 0 could mean an error, but not always. We must check that we wrote the entire file! Note that unlike write, fwrite's description according to POSIX does not mention returning a negative type at all. Nor does it say you can retry unlike write. Finally, with write, we need to check less than 0, not 0, as 0 is a valid return and does not mean an error. --- diff --git a/libarchive/archive_check_magic.c b/libarchive/archive_check_magic.c index d12f0c496..6b8e0c559 100644 --- a/libarchive/archive_check_magic.c +++ b/libarchive/archive_check_magic.c @@ -30,6 +30,7 @@ #endif #include +#include #ifdef HAVE_STDLIB_H #include #endif @@ -54,8 +55,14 @@ errmsg(const char *m) while (s > 0) { written = write(2, m, s); - if (written <= 0) + if (written == 0) return; + if (written < 0) + { + if (errno == EINTR) + continue; + return; + } m += written; s -= written; } diff --git a/libarchive/archive_write_open_fd.c b/libarchive/archive_write_open_fd.c index 8a3f68d06..ba034ed92 100644 --- a/libarchive/archive_write_open_fd.c +++ b/libarchive/archive_write_open_fd.c @@ -122,7 +122,7 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length mine = (struct write_fd_data *)client_data; for (;;) { bytesWritten = write(mine->fd, buff, length); - if (bytesWritten <= 0) { + if (bytesWritten < 0) { if (errno == EINTR) continue; archive_set_error(a, errno, "Write error"); diff --git a/libarchive/archive_write_open_file.c b/libarchive/archive_write_open_file.c index 4c6ebfb22..0b310f3da 100644 --- a/libarchive/archive_write_open_file.c +++ b/libarchive/archive_write_open_file.c @@ -85,16 +85,12 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length size_t bytesWritten; mine = client_data; - for (;;) { - bytesWritten = fwrite(buff, 1, length, mine->f); - if (bytesWritten <= 0) { - if (errno == EINTR) - continue; - archive_set_error(a, errno, "Write error"); - return (-1); - } - return (bytesWritten); + bytesWritten = fwrite(buff, 1, length, mine->f); + if (bytesWritten != length) { + archive_set_error(a, errno, "Write error"); + return (-1); } + return (bytesWritten); } static int diff --git a/libarchive/archive_write_open_filename.c b/libarchive/archive_write_open_filename.c index 633f7fe17..7d0f9bde1 100644 --- a/libarchive/archive_write_open_filename.c +++ b/libarchive/archive_write_open_filename.c @@ -228,7 +228,7 @@ file_write(struct archive *a, void *client_data, const void *buff, mine = (struct write_file_data *)client_data; for (;;) { bytesWritten = write(mine->fd, buff, length); - if (bytesWritten <= 0) { + if (bytesWritten < 0) { if (errno == EINTR) continue; archive_set_error(a, errno, "Write error");