summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--inc/abrtlib.h7
-rw-r--r--lib/Utils/copyfd.cpp41
-rw-r--r--src/Hooks/abrt-hook-ccpp.cpp6
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 */