readwrite.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /* Licensed to the Apache Software Foundation (ASF) under one or more
  2. * contributor license agreements. See the NOTICE file distributed with
  3. * this work for additional information regarding copyright ownership.
  4. * The ASF licenses this file to You under the Apache License, Version 2.0
  5. * (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #define INCL_DOS
  17. #define INCL_DOSERRORS
  18. #include "fspr_arch_file_io.h"
  19. #include "fspr_file_io.h"
  20. #include "fspr_lib.h"
  21. #include "fspr_strings.h"
  22. #include <malloc.h>
  23. APR_DECLARE(fspr_status_t) fspr_file_read(fspr_file_t *thefile, void *buf, fspr_size_t *nbytes)
  24. {
  25. ULONG rc = 0;
  26. ULONG bytesread;
  27. if (!thefile->isopen) {
  28. *nbytes = 0;
  29. return APR_EBADF;
  30. }
  31. if (thefile->buffered) {
  32. char *pos = (char *)buf;
  33. ULONG blocksize;
  34. ULONG size = *nbytes;
  35. fspr_thread_mutex_lock(thefile->mutex);
  36. if (thefile->direction == 1) {
  37. int rv = fspr_file_flush(thefile);
  38. if (rv != APR_SUCCESS) {
  39. fspr_thread_mutex_unlock(thefile->mutex);
  40. return rv;
  41. }
  42. thefile->bufpos = 0;
  43. thefile->direction = 0;
  44. thefile->dataRead = 0;
  45. }
  46. while (rc == 0 && size > 0) {
  47. if (thefile->bufpos >= thefile->dataRead) {
  48. ULONG bytesread;
  49. rc = DosRead(thefile->filedes, thefile->buffer,
  50. APR_FILE_BUFSIZE, &bytesread);
  51. if (bytesread == 0) {
  52. if (rc == 0)
  53. thefile->eof_hit = TRUE;
  54. break;
  55. }
  56. thefile->dataRead = bytesread;
  57. thefile->filePtr += thefile->dataRead;
  58. thefile->bufpos = 0;
  59. }
  60. blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size;
  61. memcpy(pos, thefile->buffer + thefile->bufpos, blocksize);
  62. thefile->bufpos += blocksize;
  63. pos += blocksize;
  64. size -= blocksize;
  65. }
  66. *nbytes = rc == 0 ? pos - (char *)buf : 0;
  67. fspr_thread_mutex_unlock(thefile->mutex);
  68. if (*nbytes == 0 && rc == 0 && thefile->eof_hit) {
  69. return APR_EOF;
  70. }
  71. return APR_FROM_OS_ERROR(rc);
  72. } else {
  73. if (thefile->pipe)
  74. DosResetEventSem(thefile->pipeSem, &rc);
  75. rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread);
  76. if (rc == ERROR_NO_DATA && thefile->timeout != 0) {
  77. int rcwait = DosWaitEventSem(thefile->pipeSem, thefile->timeout >= 0 ? thefile->timeout / 1000 : SEM_INDEFINITE_WAIT);
  78. if (rcwait == 0) {
  79. rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread);
  80. }
  81. else if (rcwait == ERROR_TIMEOUT) {
  82. *nbytes = 0;
  83. return APR_TIMEUP;
  84. }
  85. }
  86. if (rc) {
  87. *nbytes = 0;
  88. return APR_FROM_OS_ERROR(rc);
  89. }
  90. *nbytes = bytesread;
  91. if (bytesread == 0) {
  92. thefile->eof_hit = TRUE;
  93. return APR_EOF;
  94. }
  95. return APR_SUCCESS;
  96. }
  97. }
  98. APR_DECLARE(fspr_status_t) fspr_file_write(fspr_file_t *thefile, const void *buf, fspr_size_t *nbytes)
  99. {
  100. ULONG rc = 0;
  101. ULONG byteswritten;
  102. if (!thefile->isopen) {
  103. *nbytes = 0;
  104. return APR_EBADF;
  105. }
  106. if (thefile->buffered) {
  107. char *pos = (char *)buf;
  108. int blocksize;
  109. int size = *nbytes;
  110. fspr_thread_mutex_lock(thefile->mutex);
  111. if ( thefile->direction == 0 ) {
  112. // Position file pointer for writing at the offset we are logically reading from
  113. ULONG offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
  114. if (offset != thefile->filePtr)
  115. DosSetFilePtr(thefile->filedes, offset, FILE_BEGIN, &thefile->filePtr );
  116. thefile->bufpos = thefile->dataRead = 0;
  117. thefile->direction = 1;
  118. }
  119. while (rc == 0 && size > 0) {
  120. if (thefile->bufpos == APR_FILE_BUFSIZE) // write buffer is full
  121. rc = fspr_file_flush(thefile);
  122. blocksize = size > APR_FILE_BUFSIZE - thefile->bufpos ? APR_FILE_BUFSIZE - thefile->bufpos : size;
  123. memcpy(thefile->buffer + thefile->bufpos, pos, blocksize);
  124. thefile->bufpos += blocksize;
  125. pos += blocksize;
  126. size -= blocksize;
  127. }
  128. fspr_thread_mutex_unlock(thefile->mutex);
  129. return APR_FROM_OS_ERROR(rc);
  130. } else {
  131. if (thefile->flags & APR_APPEND) {
  132. FILELOCK all = { 0, 0x7fffffff };
  133. ULONG newpos;
  134. rc = DosSetFileLocks(thefile->filedes, NULL, &all, -1, 0);
  135. if (rc == 0) {
  136. rc = DosSetFilePtr(thefile->filedes, 0, FILE_END, &newpos);
  137. if (rc == 0) {
  138. rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
  139. }
  140. DosSetFileLocks(thefile->filedes, &all, NULL, -1, 0);
  141. }
  142. } else {
  143. rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
  144. }
  145. if (rc) {
  146. *nbytes = 0;
  147. return APR_FROM_OS_ERROR(rc);
  148. }
  149. *nbytes = byteswritten;
  150. return APR_SUCCESS;
  151. }
  152. }
  153. #ifdef HAVE_WRITEV
  154. APR_DECLARE(fspr_status_t) fspr_file_writev(fspr_file_t *thefile, const struct iovec *vec, fspr_size_t nvec, fspr_size_t *nbytes)
  155. {
  156. int bytes;
  157. if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) {
  158. *nbytes = 0;
  159. return errno;
  160. }
  161. else {
  162. *nbytes = bytes;
  163. return APR_SUCCESS;
  164. }
  165. }
  166. #endif
  167. APR_DECLARE(fspr_status_t) fspr_file_putc(char ch, fspr_file_t *thefile)
  168. {
  169. ULONG rc;
  170. ULONG byteswritten;
  171. if (!thefile->isopen) {
  172. return APR_EBADF;
  173. }
  174. rc = DosWrite(thefile->filedes, &ch, 1, &byteswritten);
  175. if (rc) {
  176. return APR_FROM_OS_ERROR(rc);
  177. }
  178. return APR_SUCCESS;
  179. }
  180. APR_DECLARE(fspr_status_t) fspr_file_ungetc(char ch, fspr_file_t *thefile)
  181. {
  182. fspr_off_t offset = -1;
  183. return fspr_file_seek(thefile, APR_CUR, &offset);
  184. }
  185. APR_DECLARE(fspr_status_t) fspr_file_getc(char *ch, fspr_file_t *thefile)
  186. {
  187. ULONG rc;
  188. fspr_size_t bytesread;
  189. if (!thefile->isopen) {
  190. return APR_EBADF;
  191. }
  192. bytesread = 1;
  193. rc = fspr_file_read(thefile, ch, &bytesread);
  194. if (rc) {
  195. return rc;
  196. }
  197. if (bytesread == 0) {
  198. thefile->eof_hit = TRUE;
  199. return APR_EOF;
  200. }
  201. return APR_SUCCESS;
  202. }
  203. APR_DECLARE(fspr_status_t) fspr_file_puts(const char *str, fspr_file_t *thefile)
  204. {
  205. fspr_size_t len;
  206. len = strlen(str);
  207. return fspr_file_write(thefile, str, &len);
  208. }
  209. APR_DECLARE(fspr_status_t) fspr_file_flush(fspr_file_t *thefile)
  210. {
  211. if (thefile->buffered) {
  212. ULONG written = 0;
  213. int rc = 0;
  214. if (thefile->direction == 1 && thefile->bufpos) {
  215. rc = DosWrite(thefile->filedes, thefile->buffer, thefile->bufpos, &written);
  216. thefile->filePtr += written;
  217. if (rc == 0)
  218. thefile->bufpos = 0;
  219. }
  220. return APR_FROM_OS_ERROR(rc);
  221. } else {
  222. /* There isn't anything to do if we aren't buffering the output
  223. * so just return success.
  224. */
  225. return APR_SUCCESS;
  226. }
  227. }
  228. APR_DECLARE(fspr_status_t) fspr_file_gets(char *str, int len, fspr_file_t *thefile)
  229. {
  230. fspr_size_t readlen;
  231. fspr_status_t rv = APR_SUCCESS;
  232. int i;
  233. for (i = 0; i < len-1; i++) {
  234. readlen = 1;
  235. rv = fspr_file_read(thefile, str+i, &readlen);
  236. if (rv != APR_SUCCESS) {
  237. break;
  238. }
  239. if (readlen != 1) {
  240. rv = APR_EOF;
  241. break;
  242. }
  243. if (str[i] == '\n') {
  244. i++;
  245. break;
  246. }
  247. }
  248. str[i] = 0;
  249. if (i > 0) {
  250. /* we stored chars; don't report EOF or any other errors;
  251. * the app will find out about that on the next call
  252. */
  253. return APR_SUCCESS;
  254. }
  255. return rv;
  256. }
  257. APR_DECLARE_NONSTD(int) fspr_file_printf(fspr_file_t *fptr,
  258. const char *format, ...)
  259. {
  260. int cc;
  261. va_list ap;
  262. char *buf;
  263. int len;
  264. buf = malloc(HUGE_STRING_LEN);
  265. if (buf == NULL) {
  266. return 0;
  267. }
  268. va_start(ap, format);
  269. len = fspr_vsnprintf(buf, HUGE_STRING_LEN, format, ap);
  270. cc = fspr_file_puts(buf, fptr);
  271. va_end(ap);
  272. free(buf);
  273. return (cc == APR_SUCCESS) ? len : -1;
  274. }
  275. fspr_status_t fspr_file_check_read(fspr_file_t *fd)
  276. {
  277. int rc;
  278. if (!fd->pipe)
  279. return APR_SUCCESS; /* Not a pipe, assume no waiting */
  280. rc = DosWaitEventSem(fd->pipeSem, SEM_IMMEDIATE_RETURN);
  281. if (rc == ERROR_TIMEOUT)
  282. return APR_TIMEUP;
  283. return APR_FROM_OS_ERROR(rc);
  284. }