util: copy_bytes: Multiple changes 25/189425/12
authorKarol Lewandowski <k.lewandowsk@samsung.com>
Wed, 3 Oct 2018 11:36:17 +0000 (13:36 +0200)
committerKarol Lewandowski <lmctl@lmctl.net>
Wed, 7 Nov 2018 22:43:36 +0000 (23:43 +0100)
 - Use max possible buffer size for sendfile()

   The fewer we call sendfile() the better (performance)

 - Provide read()/write() fallback when sendfile will
   not work (eg. copying data from pipe to pipe)

 - Add third argument with number of copied bytes. This is
   to avoid mixing error code (negative) with transferred size.

 - Make API available for rest of codebase

Change-Id: If80feb578b01fb715008a20e7c000c5ede9b62a1

CMakeLists.txt
src/shared/util.c
src/shared/util.h

index 96ecea7..9834ed5 100644 (file)
@@ -3,6 +3,8 @@ PROJECT(crash-worker C)
 
 SET(PREFIX ${CMAKE_INSTALL_PREFIX})
 
+ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64)
+
 # Sub modules
 ADD_SUBDIRECTORY(src/crash-manager)
 
index b83dbaa..d6fdd31 100644 (file)
@@ -19,6 +19,7 @@
 #endif
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/time.h>
@@ -167,19 +168,60 @@ int write_fd(int fd, const void *buf, int len)
        return total;
 }
 
-static int copy_bytes(int dfd, int sfd)
+static int copy_bytes_sendfile(int destfd, int srcfd, off_t *ncopied)
 {
-       int res = 1;
-       ssize_t bytes_sent;
-       do
-               bytes_sent = sendfile(dfd, sfd, NULL, PIPE_BUF);
-       while (bytes_sent > 0);
+       ssize_t nsent;
+       off_t total = 0;
 
-       if (bytes_sent == -1) {
-               _E("sendfile() error: %m\n");
-               res = -1;
-       }
-       return res;
+       do {
+               nsent = sendfile(destfd, srcfd, NULL, INT32_MAX);
+               if (nsent > 0)
+                       total += nsent;
+               else if (nsent < 0 && errno == EAGAIN)
+                       continue;
+               else
+                       break;
+       } while (1);
+
+       if (ncopied)
+               *ncopied = total;
+
+       return nsent == -1 ? -1 : 0;
+}
+
+static int copy_bytes_rw(int destfd, int srcfd, off_t *ncopied)
+{
+       ssize_t n;
+       char buf[4096];
+       off_t total = 0;
+
+       do {
+               n = read(srcfd, buf, sizeof buf);
+               if (n < 0) {
+                       if (errno == EAGAIN || errno == EINTR)
+                               continue;
+                       _E("read: %m");
+                       return -1;
+               }
+
+               int m = write_fd(destfd, buf, n);
+               if (m != n) {
+                       _E("failed to write data to destination fd: %m");
+                       return -1;
+               }
+               total += m;
+       } while (n > 0);
+
+       if (ncopied)
+               *ncopied = total;
+
+       return 0;
+}
+
+int copy_bytes(int destfd, int srcfd, off_t *ncopied)
+{
+       int r = copy_bytes_sendfile(destfd, srcfd, ncopied);
+       return r == 0 ? r : copy_bytes_rw(destfd, srcfd, ncopied);
 }
 
 int copy_file(char *src, char *dst)
@@ -204,7 +246,7 @@ int copy_file(char *src, char *dst)
                return -1;
        }
 
-       res = copy_bytes(dfd, sfd);
+       res = copy_bytes(dfd, sfd, NULL);
 
        close(sfd);
        close(dfd);
@@ -235,7 +277,7 @@ int dump_file_write_fd(char *src, int dfd)
                return -1;
        }
 
-       res = copy_bytes(dfd, sfd);
+       res = copy_bytes(dfd, sfd, NULL);
 
        close(sfd);
        return res;
index 03de693..a010b7e 100644 (file)
@@ -39,6 +39,8 @@ int wait_system_command(int pid);
 
 int write_fd(int fd, const void *buf, int len);
 
+int copy_bytes(int destfd, int srcfd, off_t *ncopied);
+
 int copy_file(char *src, char *dst);
 
 int move_file(char *src, char *dst);