readwrite.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  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. #include "win32/apr_arch_file_io.h"
  17. #include "apr_file_io.h"
  18. #include "apr_general.h"
  19. #include "apr_strings.h"
  20. #include "apr_lib.h"
  21. #include "apr_errno.h"
  22. #include <malloc.h>
  23. #include "apr_arch_atime.h"
  24. #include "apr_arch_misc.h"
  25. /*
  26. * read_with_timeout()
  27. * Uses async i/o to emulate unix non-blocking i/o with timeouts.
  28. */
  29. static apr_status_t read_with_timeout(apr_file_t *file, void *buf, apr_size_t len_in, apr_size_t *nbytes)
  30. {
  31. apr_status_t rv;
  32. DWORD len = (DWORD)len_in;
  33. DWORD bytesread = 0;
  34. /* Handle the zero timeout non-blocking case */
  35. if (file->timeout == 0) {
  36. /* Peek at the pipe. If there is no data available, return APR_EAGAIN.
  37. * If data is available, go ahead and read it.
  38. */
  39. if (file->pipe) {
  40. DWORD bytes;
  41. if (!PeekNamedPipe(file->filehand, NULL, 0, NULL, &bytes, NULL)) {
  42. rv = apr_get_os_error();
  43. if (rv == APR_FROM_OS_ERROR(ERROR_BROKEN_PIPE)) {
  44. rv = APR_EOF;
  45. }
  46. *nbytes = 0;
  47. return rv;
  48. }
  49. else {
  50. if (bytes == 0) {
  51. *nbytes = 0;
  52. return APR_EAGAIN;
  53. }
  54. if (len > bytes) {
  55. len = bytes;
  56. }
  57. }
  58. }
  59. else {
  60. /* ToDo: Handle zero timeout non-blocking file i/o
  61. * This is not needed until an APR application needs to
  62. * timeout file i/o (which means setting file i/o non-blocking)
  63. */
  64. }
  65. }
  66. if (file->pOverlapped && !file->pipe) {
  67. file->pOverlapped->Offset = (DWORD)file->filePtr;
  68. file->pOverlapped->OffsetHigh = (DWORD)(file->filePtr >> 32);
  69. }
  70. rv = ReadFile(file->filehand, buf, len,
  71. &bytesread, file->pOverlapped);
  72. *nbytes = bytesread;
  73. if (!rv) {
  74. rv = apr_get_os_error();
  75. if (rv == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) {
  76. /* Wait for the pending i/o */
  77. if (file->timeout > 0) {
  78. /* timeout in milliseconds... */
  79. rv = WaitForSingleObject(file->pOverlapped->hEvent,
  80. (DWORD)(file->timeout/1000));
  81. }
  82. else if (file->timeout == -1) {
  83. rv = WaitForSingleObject(file->pOverlapped->hEvent, INFINITE);
  84. }
  85. switch (rv) {
  86. case WAIT_OBJECT_0:
  87. GetOverlappedResult(file->filehand, file->pOverlapped,
  88. &bytesread, TRUE);
  89. *nbytes = bytesread;
  90. rv = APR_SUCCESS;
  91. break;
  92. case WAIT_TIMEOUT:
  93. rv = APR_TIMEUP;
  94. break;
  95. case WAIT_FAILED:
  96. rv = apr_get_os_error();
  97. break;
  98. default:
  99. break;
  100. }
  101. if (rv != APR_SUCCESS) {
  102. if (apr_os_level >= APR_WIN_98) {
  103. CancelIo(file->filehand);
  104. }
  105. }
  106. }
  107. else if (rv == APR_FROM_OS_ERROR(ERROR_BROKEN_PIPE)) {
  108. /* Assume ERROR_BROKEN_PIPE signals an EOF reading from a pipe */
  109. rv = APR_EOF;
  110. }
  111. } else {
  112. /* OK and 0 bytes read ==> end of file */
  113. if (*nbytes == 0)
  114. rv = APR_EOF;
  115. else
  116. rv = APR_SUCCESS;
  117. }
  118. if (rv == APR_SUCCESS && file->pOverlapped && !file->pipe) {
  119. file->filePtr += *nbytes;
  120. }
  121. return rv;
  122. }
  123. APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *len)
  124. {
  125. apr_status_t rv;
  126. DWORD bytes_read = 0;
  127. if (*len <= 0) {
  128. *len = 0;
  129. return APR_SUCCESS;
  130. }
  131. /* If the file is open for xthread support, allocate and
  132. * initialize the overlapped and io completion event (hEvent).
  133. * Threads should NOT share an apr_file_t or its hEvent.
  134. */
  135. if ((thefile->flags & APR_XTHREAD) && !thefile->pOverlapped ) {
  136. thefile->pOverlapped = (OVERLAPPED*) apr_pcalloc(thefile->pool,
  137. sizeof(OVERLAPPED));
  138. thefile->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  139. if (!thefile->pOverlapped->hEvent) {
  140. rv = apr_get_os_error();
  141. return rv;
  142. }
  143. }
  144. /* Handle the ungetchar if there is one */
  145. if (thefile->ungetchar != -1) {
  146. bytes_read = 1;
  147. *(char *)buf = (char)thefile->ungetchar;
  148. buf = (char *)buf + 1;
  149. (*len)--;
  150. thefile->ungetchar = -1;
  151. if (*len == 0) {
  152. *len = bytes_read;
  153. return APR_SUCCESS;
  154. }
  155. }
  156. if (thefile->buffered) {
  157. char *pos = (char *)buf;
  158. apr_size_t blocksize;
  159. apr_size_t size = *len;
  160. apr_thread_mutex_lock(thefile->mutex);
  161. if (thefile->direction == 1) {
  162. rv = apr_file_flush(thefile);
  163. if (rv != APR_SUCCESS) {
  164. apr_thread_mutex_unlock(thefile->mutex);
  165. return rv;
  166. }
  167. thefile->bufpos = 0;
  168. thefile->direction = 0;
  169. thefile->dataRead = 0;
  170. }
  171. rv = 0;
  172. while (rv == 0 && size > 0) {
  173. if (thefile->bufpos >= thefile->dataRead) {
  174. apr_size_t read;
  175. rv = read_with_timeout(thefile, thefile->buffer,
  176. APR_FILE_BUFSIZE, &read);
  177. if (read == 0) {
  178. if (rv == APR_EOF)
  179. thefile->eof_hit = TRUE;
  180. break;
  181. }
  182. else {
  183. thefile->dataRead = read;
  184. thefile->filePtr += thefile->dataRead;
  185. thefile->bufpos = 0;
  186. }
  187. }
  188. blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size;
  189. memcpy(pos, thefile->buffer + thefile->bufpos, blocksize);
  190. thefile->bufpos += blocksize;
  191. pos += blocksize;
  192. size -= blocksize;
  193. }
  194. *len = pos - (char *)buf;
  195. if (*len) {
  196. rv = APR_SUCCESS;
  197. }
  198. apr_thread_mutex_unlock(thefile->mutex);
  199. } else {
  200. /* Unbuffered i/o */
  201. apr_size_t nbytes;
  202. rv = read_with_timeout(thefile, buf, *len, &nbytes);
  203. if (rv == APR_EOF)
  204. thefile->eof_hit = TRUE;
  205. *len = nbytes;
  206. }
  207. return rv;
  208. }
  209. APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes)
  210. {
  211. apr_status_t rv;
  212. DWORD bwrote;
  213. /* If the file is open for xthread support, allocate and
  214. * initialize the overlapped and io completion event (hEvent).
  215. * Threads should NOT share an apr_file_t or its hEvent.
  216. */
  217. if ((thefile->flags & APR_XTHREAD) && !thefile->pOverlapped ) {
  218. thefile->pOverlapped = (OVERLAPPED*) apr_pcalloc(thefile->pool,
  219. sizeof(OVERLAPPED));
  220. thefile->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  221. if (!thefile->pOverlapped->hEvent) {
  222. rv = apr_get_os_error();
  223. return rv;
  224. }
  225. }
  226. if (thefile->buffered) {
  227. char *pos = (char *)buf;
  228. apr_size_t blocksize;
  229. apr_size_t size = *nbytes;
  230. apr_thread_mutex_lock(thefile->mutex);
  231. if (thefile->direction == 0) {
  232. // Position file pointer for writing at the offset we are logically reading from
  233. apr_off_t offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
  234. DWORD offlo = (DWORD)offset;
  235. DWORD offhi = (DWORD)(offset >> 32);
  236. if (offset != thefile->filePtr)
  237. SetFilePointer(thefile->filehand, offlo, &offhi, FILE_BEGIN);
  238. thefile->bufpos = thefile->dataRead = 0;
  239. thefile->direction = 1;
  240. }
  241. rv = 0;
  242. while (rv == 0 && size > 0) {
  243. if (thefile->bufpos == APR_FILE_BUFSIZE) // write buffer is full
  244. rv = apr_file_flush(thefile);
  245. blocksize = size > APR_FILE_BUFSIZE - thefile->bufpos ? APR_FILE_BUFSIZE - thefile->bufpos : size;
  246. memcpy(thefile->buffer + thefile->bufpos, pos, blocksize);
  247. thefile->bufpos += blocksize;
  248. pos += blocksize;
  249. size -= blocksize;
  250. }
  251. apr_thread_mutex_unlock(thefile->mutex);
  252. return rv;
  253. } else {
  254. if (!thefile->pipe) {
  255. apr_off_t offset = 0;
  256. apr_status_t rc;
  257. if (thefile->append) {
  258. /* apr_file_lock will mutex the file across processes.
  259. * The call to apr_thread_mutex_lock is added to avoid
  260. * a race condition between LockFile and WriteFile
  261. * that occasionally leads to deadlocked threads.
  262. */
  263. apr_thread_mutex_lock(thefile->mutex);
  264. rc = apr_file_lock(thefile, APR_FLOCK_EXCLUSIVE);
  265. if (rc != APR_SUCCESS) {
  266. apr_thread_mutex_unlock(thefile->mutex);
  267. return rc;
  268. }
  269. rc = apr_file_seek(thefile, APR_END, &offset);
  270. if (rc != APR_SUCCESS) {
  271. apr_thread_mutex_unlock(thefile->mutex);
  272. return rc;
  273. }
  274. }
  275. if (thefile->pOverlapped) {
  276. thefile->pOverlapped->Offset = (DWORD)thefile->filePtr;
  277. thefile->pOverlapped->OffsetHigh = (DWORD)(thefile->filePtr >> 32);
  278. }
  279. rv = WriteFile(thefile->filehand, buf, (DWORD)*nbytes, &bwrote,
  280. thefile->pOverlapped);
  281. if (thefile->append) {
  282. apr_file_unlock(thefile);
  283. apr_thread_mutex_unlock(thefile->mutex);
  284. }
  285. }
  286. else {
  287. rv = WriteFile(thefile->filehand, buf, (DWORD)*nbytes, &bwrote,
  288. thefile->pOverlapped);
  289. }
  290. if (rv) {
  291. *nbytes = bwrote;
  292. rv = APR_SUCCESS;
  293. }
  294. else {
  295. (*nbytes) = 0;
  296. rv = apr_get_os_error();
  297. if (rv == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) {
  298. DWORD timeout_ms;
  299. if (thefile->timeout == 0) {
  300. timeout_ms = 0;
  301. }
  302. else if (thefile->timeout < 0) {
  303. timeout_ms = INFINITE;
  304. }
  305. else {
  306. timeout_ms = (DWORD)(thefile->timeout / 1000);
  307. }
  308. rv = WaitForSingleObject(thefile->pOverlapped->hEvent, timeout_ms);
  309. switch (rv) {
  310. case WAIT_OBJECT_0:
  311. GetOverlappedResult(thefile->filehand, thefile->pOverlapped,
  312. &bwrote, TRUE);
  313. *nbytes = bwrote;
  314. rv = APR_SUCCESS;
  315. break;
  316. case WAIT_TIMEOUT:
  317. rv = APR_TIMEUP;
  318. break;
  319. case WAIT_FAILED:
  320. rv = apr_get_os_error();
  321. break;
  322. default:
  323. break;
  324. }
  325. if (rv != APR_SUCCESS) {
  326. if (apr_os_level >= APR_WIN_98)
  327. CancelIo(thefile->filehand);
  328. }
  329. }
  330. }
  331. if (rv == APR_SUCCESS && thefile->pOverlapped && !thefile->pipe) {
  332. thefile->filePtr += *nbytes;
  333. }
  334. }
  335. return rv;
  336. }
  337. /* ToDo: Write for it anyway and test the oslevel!
  338. * Too bad WriteFileGather() is not supported on 95&98 (or NT prior to SP2)
  339. */
  340. APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile,
  341. const struct iovec *vec,
  342. apr_size_t nvec,
  343. apr_size_t *nbytes)
  344. {
  345. apr_status_t rv = APR_SUCCESS;
  346. apr_size_t i;
  347. apr_size_t bwrote = 0;
  348. char *buf;
  349. *nbytes = 0;
  350. for (i = 0; i < nvec; i++) {
  351. buf = vec[i].iov_base;
  352. bwrote = vec[i].iov_len;
  353. rv = apr_file_write(thefile, buf, &bwrote);
  354. *nbytes += bwrote;
  355. if (rv != APR_SUCCESS) {
  356. break;
  357. }
  358. }
  359. return rv;
  360. }
  361. APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile)
  362. {
  363. apr_size_t len = 1;
  364. return apr_file_write(thefile, &ch, &len);
  365. }
  366. APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile)
  367. {
  368. thefile->ungetchar = (unsigned char) ch;
  369. return APR_SUCCESS;
  370. }
  371. APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile)
  372. {
  373. apr_status_t rc;
  374. apr_size_t bread;
  375. bread = 1;
  376. rc = apr_file_read(thefile, ch, &bread);
  377. if (rc) {
  378. return rc;
  379. }
  380. if (bread == 0) {
  381. thefile->eof_hit = TRUE;
  382. return APR_EOF;
  383. }
  384. return APR_SUCCESS;
  385. }
  386. APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile)
  387. {
  388. apr_size_t len = strlen(str);
  389. return apr_file_write(thefile, str, &len);
  390. }
  391. APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile)
  392. {
  393. apr_size_t readlen;
  394. apr_status_t rv = APR_SUCCESS;
  395. int i;
  396. for (i = 0; i < len-1; i++) {
  397. readlen = 1;
  398. rv = apr_file_read(thefile, str+i, &readlen);
  399. if (rv != APR_SUCCESS && rv != APR_EOF)
  400. return rv;
  401. if (readlen == 0) {
  402. /* If we have bytes, defer APR_EOF to the next call */
  403. if (i > 0)
  404. rv = APR_SUCCESS;
  405. break;
  406. }
  407. if (str[i] == '\n') {
  408. i++; /* don't clobber this char below */
  409. break;
  410. }
  411. }
  412. str[i] = 0;
  413. return rv;
  414. }
  415. APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile)
  416. {
  417. if (thefile->buffered) {
  418. DWORD numbytes, written = 0;
  419. apr_status_t rc = 0;
  420. char *buffer;
  421. apr_size_t bytesleft;
  422. if (thefile->direction == 1 && thefile->bufpos) {
  423. buffer = thefile->buffer;
  424. bytesleft = thefile->bufpos;
  425. do {
  426. if (bytesleft > APR_DWORD_MAX) {
  427. numbytes = APR_DWORD_MAX;
  428. }
  429. else {
  430. numbytes = (DWORD)bytesleft;
  431. }
  432. if (!WriteFile(thefile->filehand, buffer, numbytes, &written, NULL)) {
  433. rc = apr_get_os_error();
  434. thefile->filePtr += written;
  435. break;
  436. }
  437. thefile->filePtr += written;
  438. bytesleft -= written;
  439. buffer += written;
  440. } while (bytesleft > 0);
  441. if (rc == 0)
  442. thefile->bufpos = 0;
  443. }
  444. return rc;
  445. }
  446. /* There isn't anything to do if we aren't buffering the output
  447. * so just return success.
  448. */
  449. return APR_SUCCESS;
  450. }
  451. struct apr_file_printf_data {
  452. apr_vformatter_buff_t vbuff;
  453. apr_file_t *fptr;
  454. char *buf;
  455. };
  456. static int file_printf_flush(apr_vformatter_buff_t *buff)
  457. {
  458. struct apr_file_printf_data *data = (struct apr_file_printf_data *)buff;
  459. if (apr_file_write_full(data->fptr, data->buf,
  460. data->vbuff.curpos - data->buf, NULL)) {
  461. return -1;
  462. }
  463. data->vbuff.curpos = data->buf;
  464. return 0;
  465. }
  466. APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr,
  467. const char *format, ...)
  468. {
  469. struct apr_file_printf_data data;
  470. va_list ap;
  471. int count;
  472. data.buf = malloc(HUGE_STRING_LEN);
  473. if (data.buf == NULL) {
  474. return 0;
  475. }
  476. data.vbuff.curpos = data.buf;
  477. data.vbuff.endpos = data.buf + HUGE_STRING_LEN;
  478. data.fptr = fptr;
  479. va_start(ap, format);
  480. count = apr_vformatter(file_printf_flush,
  481. (apr_vformatter_buff_t *)&data, format, ap);
  482. /* apr_vformatter does not call flush for the last bits */
  483. if (count >= 0) file_printf_flush((apr_vformatter_buff_t *)&data);
  484. va_end(ap);
  485. free(data.buf);
  486. return count;
  487. }