diff options
-rw-r--r-- | inc/abrtlib.h | 7 | ||||
-rw-r--r-- | lib/Utils/copyfd.cpp | 41 | ||||
-rw-r--r-- | src/Hooks/abrt-hook-ccpp.cpp | 6 |
3 files changed, 40 insertions, 14 deletions
diff --git a/inc/abrtlib.h b/inc/abrtlib.h index 7cafc99c..6303f759 100644 --- a/inc/abrtlib.h +++ b/inc/abrtlib.h @@ -119,8 +119,11 @@ extern ssize_t safe_write(int fd, const void *buf, size_t count); extern ssize_t full_write(int fd, const void *buf, size_t count); /* copyfd_XX print read/write errors and return -1 if they occur */ -off_t copyfd_eof(int src_fd, int dst_fd); -off_t copyfd_size(int src_fd, int dst_fd, off_t size); +enum { + COPYFD_SPARSE = 1 << 0, +}; +off_t copyfd_eof(int src_fd, int dst_fd, int flags = 0); +off_t copyfd_size(int src_fd, int dst_fd, off_t size, int flags = 0); void copyfd_exact_size(int src_fd, int dst_fd, off_t size); off_t copy_file(const char *src_name, const char *dst_name, int mode); diff --git a/lib/Utils/copyfd.cpp b/lib/Utils/copyfd.cpp index fad716f2..cbcf7005 100644 --- a/lib/Utils/copyfd.cpp +++ b/lib/Utils/copyfd.cpp @@ -29,10 +29,11 @@ static const char msg_write_error[] = "write error"; static const char msg_read_error[] = "read error"; -static off_t full_fd_action(int src_fd, int dst_fd, off_t size) +static off_t full_fd_action(int src_fd, int dst_fd, off_t size, int flags = 0) { int status = -1; off_t total = 0; + int last_was_seek = 0; #if CONFIG_FEATURE_COPYBUF_KB <= 4 char buffer[CONFIG_FEATURE_COPYBUF_KB * 1024]; enum { buffer_size = sizeof(buffer) }; @@ -67,6 +68,14 @@ static off_t full_fd_action(int src_fd, int dst_fd, off_t size) rd = safe_read(src_fd, buffer, size > buffer_size ? buffer_size : size); if (!rd) { /* eof - all done */ + if (last_was_seek) { + if (lseek(dst_fd, -1, SEEK_CUR) < 0 + || safe_write(dst_fd, "", 1) != 1 + ) { + perror_msg("%s", msg_write_error); + break; + } + } status = 0; break; } @@ -76,10 +85,24 @@ static off_t full_fd_action(int src_fd, int dst_fd, off_t size) } /* dst_fd == -1 is a fake, else... */ if (dst_fd >= 0) { - ssize_t wr = full_write(dst_fd, buffer, rd); - if (wr < rd) { - perror_msg("%s", msg_write_error); - break; + if (flags & COPYFD_SPARSE) { + ssize_t cnt = rd; + while (--cnt >= 0) + if (buffer[cnt] != 0) + goto need2write; + if (lseek(dst_fd, rd, SEEK_CUR) < 0) { + flags &= ~COPYFD_SPARSE; + goto need2write; + } + last_was_seek = 1; + } else { + need2write: + ssize_t wr = full_write(dst_fd, buffer, rd); + if (wr < rd) { + perror_msg("%s", msg_write_error); + break; + } + last_was_seek = 0; } } total += rd; @@ -101,10 +124,10 @@ static off_t full_fd_action(int src_fd, int dst_fd, off_t size) return status ? -1 : total; } -off_t copyfd_size(int fd1, int fd2, off_t size) +off_t copyfd_size(int fd1, int fd2, off_t size, int flags) { if (size) { - return full_fd_action(fd1, fd2, size); + return full_fd_action(fd1, fd2, size, flags); } return 0; } @@ -120,9 +143,9 @@ void copyfd_exact_size(int fd1, int fd2, off_t size) xfunc_die(); } -off_t copyfd_eof(int fd1, int fd2) +off_t copyfd_eof(int fd1, int fd2, int flags) { - return full_fd_action(fd1, fd2, 0); + return full_fd_action(fd1, fd2, 0, flags); } off_t copy_file(const char *src_name, const char *dst_name, int mode) diff --git a/src/Hooks/abrt-hook-ccpp.cpp b/src/Hooks/abrt-hook-ccpp.cpp index d21b8e6b..951bea9d 100644 --- a/src/Hooks/abrt-hook-ccpp.cpp +++ b/src/Hooks/abrt-hook-ccpp.cpp @@ -189,7 +189,7 @@ int main(int argc, char** argv) */ snprintf(path, sizeof(path), "%s/abrtd-coredump", dddir); core_fd = xopen3(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - core_size = copyfd_eof(STDIN_FILENO, core_fd); + core_size = copyfd_eof(STDIN_FILENO, core_fd, COPYFD_SPARSE); if (core_size < 0 || close(core_fd) != 0) { unlink(path); @@ -237,7 +237,7 @@ int main(int argc, char** argv) //Currently it is owned by 0:0 but is readable by anyone, so the owner //of the crashed binary still can access it, as he has //r-x access to the dump dir. - core_size = copyfd_eof(STDIN_FILENO, core_fd); + core_size = copyfd_eof(STDIN_FILENO, core_fd, COPYFD_SPARSE); if (core_size < 0 || fsync(core_fd) != 0) { unlink(path); @@ -367,7 +367,7 @@ int main(int argc, char** argv) /* Note: we do not copy more than ulimit_c */ off_t size; if (ftruncate(usercore_fd, 0) != 0 - || (size = copyfd_size(core_fd, usercore_fd, ulimit_c)) < 0 + || (size = copyfd_size(core_fd, usercore_fd, ulimit_c, COPYFD_SPARSE)) < 0 || close(usercore_fd) != 0 ) { /* perror first, otherwise unlink may trash errno */ |