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.
 
 
 
 

135 lines
3.3 KiB

  1. #include <unistd.h>
  2. #include <sys/time.h>
  3. #ifdef __MINGW32__
  4. #include <windows.h>
  5. #include <stdio.h>
  6. #else
  7. #include <poll.h>
  8. #endif
  9. #include <errno.h>
  10. #include "io_internal.h"
  11. #include "byte.h"
  12. #ifdef __MINGW32__
  13. /* In Windows, I/O works differently. */
  14. /* Instead of calling read until it says EAGAIN, you call read in
  15. * overlapping mode, and then wait for it to finish.
  16. * We map this to our API by having the first call to io_tryread always
  17. * return EAGAIN, wait for the I/O completion port to tell us the read
  18. * is finished, and then return the data we actually read the next time
  19. * we are called. */
  20. int64 io_tryread(int64 d,char* buf,int64 len) {
  21. io_entry* e=iarray_get(&io_fds,d);
  22. if (!e) { errno=EBADF; return -3; }
  23. if (len<0) { errno=EINVAL; return -3; }
  24. if (e->readqueued==2) {
  25. int x=e->bytes_read;
  26. if (e->errorcode) {
  27. errno=e->errorcode;
  28. e->canread=0;
  29. return -3;
  30. }
  31. if (x>len) x=len;
  32. if (x) {
  33. byte_copy(buf,x,e->inbuf);
  34. byte_copy(e->inbuf,e->bytes_read-x,e->inbuf+x);
  35. e->bytes_read-=x;
  36. }
  37. if (!e->bytes_read) {
  38. e->canread=0;
  39. if (len>x) {
  40. /* queue next read */
  41. if (len>sizeof(e->inbuf)) len=sizeof(e->inbuf);
  42. fprintf(stderr,"Queueing ReadFile on handle %p...",d);
  43. if (ReadFile((HANDLE)d,e->inbuf,len,0,&e->or)) {
  44. fprintf(stderr," got immediate answer\n");
  45. e->canread=1;
  46. e->readqueued=2;
  47. e->next_write=first_writeable;
  48. first_writeable=d;
  49. } else if ((e->errorcode=GetLastError())==ERROR_IO_PENDING) {
  50. fprintf(stderr," OK\n");
  51. e->readqueued=1;
  52. e->errorcode=0;
  53. } else {
  54. fprintf(stderr," error!\n");
  55. e->canread=1;
  56. e->readqueued=2;
  57. e->next_write=first_writeable;
  58. first_writeable=d;
  59. }
  60. }
  61. }
  62. return x;
  63. }
  64. if (!e->readqueued) {
  65. fprintf(stderr,"!e->readqueued\n");
  66. if (len>sizeof(e->inbuf)) len=sizeof(e->inbuf);
  67. if (ReadFile((HANDLE)d,e->inbuf,len,0,&e->or)) {
  68. e->readqueued=1;
  69. fprintf(stderr,"ReadFile returned nonzero\n");
  70. } else
  71. fprintf(stderr,"ReadFile returned zero\n");
  72. }
  73. errno=EAGAIN;
  74. return -1;
  75. }
  76. #else
  77. int64 io_tryread(int64 d,char* buf,int64 len) {
  78. long r;
  79. struct itimerval old,new;
  80. struct pollfd p;
  81. io_entry* e=iarray_get(&io_fds,d);
  82. if (!e) { errno=EBADF; return -3; }
  83. if (!e->nonblock) {
  84. p.fd=d;
  85. if (p.fd!=d) { errno=EBADF; return -3; } /* catch integer truncation */
  86. p.events=POLLIN;
  87. switch (poll(&p,1,0)) {
  88. case -1: return -3;
  89. case 0: errno=EAGAIN;
  90. e->canread=0;
  91. e->next_read=-1;
  92. return -1;
  93. }
  94. new.it_interval.tv_usec=10000;
  95. new.it_interval.tv_sec=0;
  96. new.it_value.tv_usec=10000;
  97. new.it_value.tv_sec=0;
  98. setitimer(ITIMER_REAL,&new,&old);
  99. }
  100. r=read(d,buf,len);
  101. if (!e->nonblock) {
  102. setitimer(ITIMER_REAL,&old,0);
  103. }
  104. if (r==-1 && errno==EAGAIN)
  105. io_eagain_read(d);
  106. if (r==-1) {
  107. if (errno==EINTR) errno=EAGAIN;
  108. if (errno!=EAGAIN)
  109. r=-3;
  110. }
  111. if (r!=len) {
  112. e->canread=0;
  113. io_eagain_read(d);
  114. #if defined(HAVE_SIGIO)
  115. #if 0
  116. debug_printf(("io_tryread: dequeueing %ld from alt read queue (next is %ld)\n",d,alt_firstread));
  117. alt_firstread=e->next_read;
  118. e->next_read=-1;
  119. #else
  120. } else {
  121. debug_printf(("io_tryread: enqueueing %ld into alt read queue (next is %ld)\n",d,alt_firstread));
  122. e->next_read=alt_firstread;
  123. alt_firstread=d;
  124. #endif
  125. #endif
  126. }
  127. return r;
  128. }
  129. #endif