Guest User

Untitled

a guest
Jan 21st, 2018
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.95 KB | None | 0 0
  1. /*
  2. * An example using splice syscall which avoids copying to/from user space buffers to kernel space
  3. * and uses the pipe buffers allocated in kernel space as an intermediate to directly xfer from one file to another
  4. *
  5. * gcc -o splice splice.c -g
  6. */
  7.  
  8. #define _GNU_SOURCE
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <fcntl.h>
  13. #include <unistd.h>
  14. #include <sys/stat.h>
  15.  
  16. #define __IO_BUFSIZE (4096) /*reasonable buffer size based on pipe buffers*/
  17.  
  18. #ifdef HAVE_SPLICE
  19. #define do_copy spliced_copy
  20. #else
  21. #define do_copy std_copy
  22. #endif
  23.  
  24. /*
  25. * Read from in and write to out without using user space buffers.
  26. * Directly splice using the pipe buffer.
  27. */
  28. #ifdef HAVE_SPLICE
  29. static int spliced_copy(int in_fd, int out_fd)
  30. {
  31. loff_t in_off = 0;
  32. loff_t out_off = 0;
  33. static int buf_size = __IO_BUFSIZE;
  34. off_t len;
  35. int filedes[2];
  36. int err = -1;
  37. struct stat stbuf;
  38. if(pipe(filedes) < 0)
  39. {
  40. perror("pipe:");
  41. goto out;
  42. }
  43. if(fstat(in_fd, &stbuf) < 0)
  44. {
  45. perror("fstat:");
  46. goto out_close;
  47. }
  48. len = stbuf.st_size;
  49. while(len > 0)
  50. {
  51. if(buf_size > len) buf_size = len;
  52. /*
  53. * move to pipe buffer.
  54. */
  55. err = splice(in_fd, &in_off, filedes[1], NULL, buf_size, SPLICE_F_MOVE | SPLICE_F_MORE);
  56. if(err < 0)
  57. {
  58. perror("splice:");
  59. goto out_close;
  60. }
  61. /*
  62. * move from pipe buffer to out_fd
  63. */
  64. err = splice(filedes[0], NULL, out_fd, &out_off, buf_size, SPLICE_F_MOVE | SPLICE_F_MORE);
  65. if(err < 0)
  66. {
  67. perror("splice2:");
  68. goto out_close;
  69. }
  70. len -= buf_size;
  71. }
  72. err = 0;
  73.  
  74. out_close:
  75. close(filedes[0]);
  76. close(filedes[1]);
  77.  
  78. out:
  79. return err;
  80. }
  81. #else
  82. static int std_copy(int in_fd, int out_fd)
  83. {
  84. char buf[__IO_BUFSIZE];
  85. int err = -1;
  86. int bytes;
  87. while( (bytes = read(in_fd, buf, sizeof(buf))) > 0 )
  88. {
  89. if(write(out_fd, buf, bytes) != bytes)
  90. {
  91. perror("write:");
  92. goto out;
  93. }
  94. }
  95. err = 0;
  96. out:
  97. return err;
  98. }
  99. #endif
  100.  
  101. int main(int argc, char **argv)
  102. {
  103. char infile[0xff+1], outfile[0xff+1];
  104. int in_fd = -1, out_fd = -1;
  105. int err = -1;
  106.  
  107. if(argc != 3)
  108. {
  109. fprintf(stderr, "%s infile outfile\n", argv[0]);
  110. goto out;
  111. }
  112.  
  113. infile[0] = 0, outfile[0] = 0;
  114. strncat(infile, argv[1], sizeof(infile)-1);
  115. strncat(outfile, argv[2], sizeof(outfile)-1);
  116. in_fd = open(infile, O_RDONLY);
  117. if(in_fd < 0)
  118. {
  119. perror("open:");
  120. goto out;
  121. }
  122. out_fd = open(outfile, O_CREAT | O_WRONLY | O_TRUNC, 0777);
  123. if(out_fd < 0)
  124. {
  125. perror("open2:");
  126. goto out_close;
  127. }
  128. if((err = do_copy(in_fd, out_fd)) < 0)
  129. {
  130. printf("Error copying input file [%s] to output file [%s]\n", infile, outfile);
  131. }
  132.  
  133. close(out_fd);
  134.  
  135. out_close:
  136. close(in_fd);
  137.  
  138. out:
  139. return err;
  140. }
Add Comment
Please, Sign In to add comment