readwrite.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  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 "apr_arch_file_io.h"
  19. #include "apr_file_io.h"
  20. #include "apr_lib.h"
  21. #include "apr_strings.h"
  22. #include <malloc.h>
  23. APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_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. apr_thread_mutex_lock(thefile->mutex);
  36. if (thefile->direction == 1) {
  37. int rv = apr_file_flush(thefile);
  38. if (rv != APR_SUCCESS) {
  39. apr_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. thefile->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. apr_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(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_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. apr_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 == thefile->bufsize) /* write buffer is full */
  121. /* XXX bug; - rc is double-transformed os->apr below */
  122. rc = apr_file_flush(thefile);
  123. blocksize = size > thefile->bufsize - thefile->bufpos ? thefile->bufsize - thefile->bufpos : size;
  124. memcpy(thefile->buffer + thefile->bufpos, pos, blocksize);
  125. thefile->bufpos += blocksize;
  126. pos += blocksize;
  127. size -= blocksize;
  128. }
  129. apr_thread_mutex_unlock(thefile->mutex);
  130. return APR_FROM_OS_ERROR(rc);
  131. } else {
  132. if (thefile->flags & APR_FOPEN_APPEND) {
  133. FILELOCK all = { 0, 0x7fffffff };
  134. ULONG newpos;
  135. rc = DosSetFileLocks(thefile->filedes, NULL, &all, -1, 0);
  136. if (rc == 0) {
  137. rc = DosSetFilePtr(thefile->filedes, 0, FILE_END, &newpos);
  138. if (rc == 0) {
  139. rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
  140. }
  141. DosSetFileLocks(thefile->filedes, &all, NULL, -1, 0);
  142. }
  143. } else {
  144. rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
  145. }
  146. if (rc) {
  147. *nbytes = 0;
  148. return APR_FROM_OS_ERROR(rc);
  149. }
  150. *nbytes = byteswritten;
  151. return APR_SUCCESS;
  152. }
  153. }
  154. #ifdef HAVE_WRITEV
  155. APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iovec *vec, apr_size_t nvec, apr_size_t *nbytes)
  156. {
  157. int bytes;
  158. if (thefile->buffered) {
  159. apr_status_t rv = apr_file_flush(thefile);
  160. if (rv != APR_SUCCESS) {
  161. return rv;
  162. }
  163. }
  164. if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) {
  165. *nbytes = 0;
  166. return errno;
  167. }
  168. else {
  169. *nbytes = bytes;
  170. return APR_SUCCESS;
  171. }
  172. }
  173. #endif
  174. APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile)
  175. {
  176. ULONG rc;
  177. ULONG byteswritten;
  178. if (!thefile->isopen) {
  179. return APR_EBADF;
  180. }
  181. rc = DosWrite(thefile->filedes, &ch, 1, &byteswritten);
  182. if (rc) {
  183. return APR_FROM_OS_ERROR(rc);
  184. }
  185. return APR_SUCCESS;
  186. }
  187. APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile)
  188. {
  189. apr_off_t offset = -1;
  190. return apr_file_seek(thefile, APR_CUR, &offset);
  191. }
  192. APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile)
  193. {
  194. ULONG rc;
  195. apr_size_t bytesread;
  196. if (!thefile->isopen) {
  197. return APR_EBADF;
  198. }
  199. bytesread = 1;
  200. rc = apr_file_read(thefile, ch, &bytesread);
  201. if (rc) {
  202. return rc;
  203. }
  204. if (bytesread == 0) {
  205. thefile->eof_hit = TRUE;
  206. return APR_EOF;
  207. }
  208. return APR_SUCCESS;
  209. }
  210. APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile)
  211. {
  212. apr_size_t len;
  213. len = strlen(str);
  214. return apr_file_write(thefile, str, &len);
  215. }
  216. APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile)
  217. {
  218. if (thefile->buffered) {
  219. ULONG written = 0;
  220. int rc = 0;
  221. if (thefile->direction == 1 && thefile->bufpos) {
  222. rc = DosWrite(thefile->filedes, thefile->buffer, thefile->bufpos, &written);
  223. thefile->filePtr += written;
  224. if (rc == 0)
  225. thefile->bufpos = 0;
  226. }
  227. return APR_FROM_OS_ERROR(rc);
  228. } else {
  229. /* There isn't anything to do if we aren't buffering the output
  230. * so just return success.
  231. */
  232. return APR_SUCCESS;
  233. }
  234. }
  235. APR_DECLARE(apr_status_t) apr_file_sync(apr_file_t *thefile)
  236. {
  237. return APR_ENOTIMPL;
  238. }
  239. APR_DECLARE(apr_status_t) apr_file_datasync(apr_file_t *thefile)
  240. {
  241. return APR_ENOTIMPL;
  242. }
  243. APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile)
  244. {
  245. apr_size_t readlen;
  246. apr_status_t rv = APR_SUCCESS;
  247. int i;
  248. for (i = 0; i < len-1; i++) {
  249. readlen = 1;
  250. rv = apr_file_read(thefile, str+i, &readlen);
  251. if (rv != APR_SUCCESS) {
  252. break;
  253. }
  254. if (readlen != 1) {
  255. rv = APR_EOF;
  256. break;
  257. }
  258. if (str[i] == '\n') {
  259. i++;
  260. break;
  261. }
  262. }
  263. str[i] = 0;
  264. if (i > 0) {
  265. /* we stored chars; don't report EOF or any other errors;
  266. * the app will find out about that on the next call
  267. */
  268. return APR_SUCCESS;
  269. }
  270. return rv;
  271. }
  272. APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr,
  273. const char *format, ...)
  274. {
  275. int cc;
  276. va_list ap;
  277. char *buf;
  278. int len;
  279. buf = malloc(HUGE_STRING_LEN);
  280. if (buf == NULL) {
  281. return 0;
  282. }
  283. va_start(ap, format);
  284. len = apr_vsnprintf(buf, HUGE_STRING_LEN, format, ap);
  285. cc = apr_file_puts(buf, fptr);
  286. va_end(ap);
  287. free(buf);
  288. return (cc == APR_SUCCESS) ? len : -1;
  289. }
  290. apr_status_t apr_file_check_read(apr_file_t *fd)
  291. {
  292. int rc;
  293. if (!fd->pipe)
  294. return APR_SUCCESS; /* Not a pipe, assume no waiting */
  295. rc = DosWaitEventSem(fd->pipeSem, SEM_IMMEDIATE_RETURN);
  296. if (rc == ERROR_TIMEOUT)
  297. return APR_TIMEUP;
  298. return APR_FROM_OS_ERROR(rc);
  299. }