Mirror of :pserver:cvs@cvs.fefe.de:/cvs libowfat https://www.fefe.de/libowfat/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

120 lines
2.4 KiB

  1. #define _FILE_OFFSET_BITS 64
  2. #include "io_internal.h"
  3. #include "havebsdsf.h"
  4. #if defined(HAVE_BSDSENDFILE)
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <sys/uio.h>
  8. int64 io_sendfile(int64 s,int64 fd,uint64 off,uint64 n) {
  9. off_t sbytes;
  10. int r=sendfile(fd,s,off,n,0,&sbytes,0);
  11. if (r==-1)
  12. return (errno==EAGAIN?(sbytes?sbytes:-1):-3);
  13. return n;
  14. }
  15. #elif defined(__linux__)
  16. #if defined(__GLIBC__)
  17. #include <sys/sendfile.h>
  18. #elif defined(__dietlibc__)
  19. #include <sys/sendfile.h>
  20. #else
  21. #include <linux/unistd.h>
  22. _syscall4(int,sendfile,int,out,int,in,long *,offset,unsigned long,count)
  23. #endif
  24. int64 io_sendfile(int64 s,int64 fd,uint64 off,uint64 n) {
  25. off_t o=off;
  26. io_entry* e=array_get(&io_fds,sizeof(io_entry),s);
  27. off_t i=sendfile(s,fd,&o,n);
  28. if (i==-1) {
  29. if (e) {
  30. e->canwrite=0;
  31. e->next_write=-1;
  32. }
  33. if (errno!=EAGAIN) i=-3;
  34. }
  35. return i;
  36. }
  37. #else
  38. #include <unistd.h>
  39. #include <sys/mman.h>
  40. #define BUFSIZE 16384
  41. int64 io_sendfile(int64 out,int64 in,uint64 off,uint64 bytes) {
  42. char buf[BUFSIZE];
  43. int n,m;
  44. uint64 sent=0;
  45. io_entry* e=array_get(&io_fds,sizeof(io_entry),out);
  46. if (e) {
  47. const char* c;
  48. long left;
  49. do {
  50. if (e->mmapped) {
  51. /* did we already map the right chunk? */
  52. if (off>=e->mapofs && off<e->mapofs+e->maplen)
  53. goto mapok; /* ok; mmapped the right chunk*/
  54. munmap(e->mmapped,e->maplen);
  55. }
  56. e->mapofs=off&0xffffffffffff0000ull;
  57. if (e->mapofs+0x10000>off+bytes)
  58. e->maplen=off+bytes-e->mapofs;
  59. else
  60. e->maplen=0x10000;
  61. if ((e->mmapped=mmap(0,e->maplen,PROT_READ,MAP_SHARED,in,e->mapofs))==MAP_FAILED) {
  62. e->mmapped=0;
  63. goto readwrite;
  64. }
  65. mapok:
  66. c=(const char*)(e->mmapped)+(off&0xffff);
  67. left=e->maplen-(off&0xffff);
  68. while (left>0) {
  69. m=write(out,c,left);
  70. if (m==-1) {
  71. e->canwrite=0;
  72. e->next_write=-1;
  73. return errno==EAGAIN?(sent?sent:-1):-3;
  74. }
  75. if (m==0) return sent;
  76. sent+=m;
  77. left-=m;
  78. bytes-=m;
  79. off+=m;
  80. }
  81. } while (bytes);
  82. return sent;
  83. }
  84. readwrite:
  85. if (lseek(in,off,SEEK_SET) != off)
  86. return -1;
  87. while (bytes>0) {
  88. char* tmp=buf;
  89. if ((n=read(in,tmp,(bytes<BUFSIZE)?bytes:BUFSIZE))<=0)
  90. return (sent?sent:-1);
  91. while (n>0) {
  92. if ((m=write(out,tmp,n))<0) {
  93. if (m==-1) {
  94. if (e) {
  95. e->canwrite=0;
  96. e->next_write=-1;
  97. }
  98. return errno==EAGAIN?(sent?sent:-1):-3;
  99. }
  100. goto abort;
  101. }
  102. sent+=m;
  103. n-=m;
  104. tmp+=m;
  105. }
  106. }
  107. abort:
  108. return sent;
  109. }
  110. #endif