readwrite.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  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 "apr_arch_file_io.h"
  17. #include "apr_strings.h"
  18. #include "apr_thread_mutex.h"
  19. #include "apr_support.h"
  20. /* The only case where we don't use wait_for_io_or_timeout is on
  21. * pre-BONE BeOS, so this check should be sufficient and simpler */
  22. #if !BEOS_R5
  23. #define USE_WAIT_FOR_IO
  24. #endif
  25. static apr_status_t file_read_buffered(apr_file_t *thefile, void *buf,
  26. apr_size_t *nbytes)
  27. {
  28. apr_ssize_t rv;
  29. char *pos = (char *)buf;
  30. apr_uint64_t blocksize;
  31. apr_uint64_t size = *nbytes;
  32. if (thefile->direction == 1) {
  33. rv = apr_file_flush_locked(thefile);
  34. if (rv) {
  35. return rv;
  36. }
  37. thefile->bufpos = 0;
  38. thefile->direction = 0;
  39. thefile->dataRead = 0;
  40. }
  41. rv = 0;
  42. if (thefile->ungetchar != -1) {
  43. *pos = (char)thefile->ungetchar;
  44. ++pos;
  45. --size;
  46. thefile->ungetchar = -1;
  47. }
  48. while (rv == 0 && size > 0) {
  49. if (thefile->bufpos >= thefile->dataRead) {
  50. int bytesread = read(thefile->filedes, thefile->buffer,
  51. thefile->bufsize);
  52. if (bytesread == 0) {
  53. thefile->eof_hit = TRUE;
  54. rv = APR_EOF;
  55. break;
  56. }
  57. else if (bytesread == -1) {
  58. rv = errno;
  59. break;
  60. }
  61. thefile->dataRead = bytesread;
  62. thefile->filePtr += thefile->dataRead;
  63. thefile->bufpos = 0;
  64. }
  65. blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size;
  66. memcpy(pos, thefile->buffer + thefile->bufpos, blocksize);
  67. thefile->bufpos += blocksize;
  68. pos += blocksize;
  69. size -= blocksize;
  70. }
  71. *nbytes = pos - (char *)buf;
  72. if (*nbytes) {
  73. rv = 0;
  74. }
  75. return rv;
  76. }
  77. APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *nbytes)
  78. {
  79. apr_ssize_t rv;
  80. apr_size_t bytes_read;
  81. if (*nbytes <= 0) {
  82. *nbytes = 0;
  83. return APR_SUCCESS;
  84. }
  85. if (thefile->buffered) {
  86. file_lock(thefile);
  87. rv = file_read_buffered(thefile, buf, nbytes);
  88. file_unlock(thefile);
  89. return rv;
  90. }
  91. else {
  92. bytes_read = 0;
  93. if (thefile->ungetchar != -1) {
  94. bytes_read = 1;
  95. *(char *)buf = (char)thefile->ungetchar;
  96. buf = (char *)buf + 1;
  97. (*nbytes)--;
  98. thefile->ungetchar = -1;
  99. if (*nbytes == 0) {
  100. *nbytes = bytes_read;
  101. return APR_SUCCESS;
  102. }
  103. }
  104. do {
  105. rv = read(thefile->filedes, buf, *nbytes);
  106. } while (rv == -1 && errno == EINTR);
  107. #ifdef USE_WAIT_FOR_IO
  108. if (rv == -1 &&
  109. (errno == EAGAIN || errno == EWOULDBLOCK) &&
  110. thefile->timeout != 0) {
  111. apr_status_t arv = apr_wait_for_io_or_timeout(thefile, NULL, 1);
  112. if (arv != APR_SUCCESS) {
  113. *nbytes = bytes_read;
  114. return arv;
  115. }
  116. else {
  117. do {
  118. rv = read(thefile->filedes, buf, *nbytes);
  119. } while (rv == -1 && errno == EINTR);
  120. }
  121. }
  122. #endif
  123. *nbytes = bytes_read;
  124. if (rv == 0) {
  125. thefile->eof_hit = TRUE;
  126. return APR_EOF;
  127. }
  128. if (rv > 0) {
  129. *nbytes += rv;
  130. return APR_SUCCESS;
  131. }
  132. return errno;
  133. }
  134. }
  135. APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes)
  136. {
  137. apr_size_t rv;
  138. if (thefile->buffered) {
  139. char *pos = (char *)buf;
  140. int blocksize;
  141. int size = *nbytes;
  142. file_lock(thefile);
  143. if ( thefile->direction == 0 ) {
  144. /* Position file pointer for writing at the offset we are
  145. * logically reading from
  146. */
  147. apr_int64_t offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
  148. if (offset != thefile->filePtr)
  149. lseek(thefile->filedes, offset, SEEK_SET);
  150. thefile->bufpos = thefile->dataRead = 0;
  151. thefile->direction = 1;
  152. }
  153. rv = 0;
  154. while (rv == 0 && size > 0) {
  155. if (thefile->bufpos == thefile->bufsize) /* write buffer is full*/
  156. rv = apr_file_flush_locked(thefile);
  157. blocksize = size > thefile->bufsize - thefile->bufpos ?
  158. thefile->bufsize - thefile->bufpos : size;
  159. memcpy(thefile->buffer + thefile->bufpos, pos, blocksize);
  160. thefile->bufpos += blocksize;
  161. pos += blocksize;
  162. size -= blocksize;
  163. }
  164. file_unlock(thefile);
  165. return rv;
  166. }
  167. else {
  168. do {
  169. rv = write(thefile->filedes, buf, *nbytes);
  170. } while (rv == (apr_size_t)-1 && errno == EINTR);
  171. #ifdef USE_WAIT_FOR_IO
  172. if (rv == (apr_size_t)-1 &&
  173. (errno == EAGAIN || errno == EWOULDBLOCK) &&
  174. thefile->timeout != 0) {
  175. apr_status_t arv = apr_wait_for_io_or_timeout(thefile, NULL, 0);
  176. if (arv != APR_SUCCESS) {
  177. *nbytes = 0;
  178. return arv;
  179. }
  180. else {
  181. do {
  182. do {
  183. rv = write(thefile->filedes, buf, *nbytes);
  184. } while (rv == (apr_size_t)-1 && errno == EINTR);
  185. if (rv == (apr_size_t)-1 &&
  186. (errno == EAGAIN || errno == EWOULDBLOCK)) {
  187. *nbytes /= 2; /* yes, we'll loop if kernel lied
  188. * and we can't even write 1 byte
  189. */
  190. }
  191. else {
  192. break;
  193. }
  194. } while (1);
  195. }
  196. }
  197. #endif
  198. if (rv == (apr_size_t)-1) {
  199. (*nbytes) = 0;
  200. return errno;
  201. }
  202. *nbytes = rv;
  203. return APR_SUCCESS;
  204. }
  205. }
  206. APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iovec *vec,
  207. apr_size_t nvec, apr_size_t *nbytes)
  208. {
  209. #ifdef HAVE_WRITEV
  210. apr_status_t rv;
  211. apr_ssize_t bytes;
  212. if (thefile->buffered) {
  213. file_lock(thefile);
  214. rv = apr_file_flush_locked(thefile);
  215. if (rv != APR_SUCCESS) {
  216. file_unlock(thefile);
  217. return rv;
  218. }
  219. if (thefile->direction == 0) {
  220. /* Position file pointer for writing at the offset we are
  221. * logically reading from
  222. */
  223. apr_int64_t offset = thefile->filePtr - thefile->dataRead +
  224. thefile->bufpos;
  225. if (offset != thefile->filePtr)
  226. lseek(thefile->filedes, offset, SEEK_SET);
  227. thefile->bufpos = thefile->dataRead = 0;
  228. }
  229. file_unlock(thefile);
  230. }
  231. if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) {
  232. *nbytes = 0;
  233. rv = errno;
  234. }
  235. else {
  236. *nbytes = bytes;
  237. rv = APR_SUCCESS;
  238. }
  239. return rv;
  240. #else
  241. /**
  242. * The problem with trying to output the entire iovec is that we cannot
  243. * maintain the behaviour that a real writev would have. If we iterate
  244. * over the iovec one at a time, we lose the atomic properties of
  245. * writev(). The other option is to combine the entire iovec into one
  246. * buffer that we could then send in one call to write(). This is not
  247. * reasonable since we do not know how much data an iovec could contain.
  248. *
  249. * The only reasonable option, that maintains the semantics of a real
  250. * writev(), is to only write the first iovec. Callers of file_writev()
  251. * must deal with partial writes as they normally would. If you want to
  252. * ensure an entire iovec is written, use apr_file_writev_full().
  253. */
  254. *nbytes = vec[0].iov_len;
  255. return apr_file_write(thefile, vec[0].iov_base, nbytes);
  256. #endif
  257. }
  258. APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile)
  259. {
  260. apr_size_t nbytes = 1;
  261. return apr_file_write(thefile, &ch, &nbytes);
  262. }
  263. APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile)
  264. {
  265. thefile->ungetchar = (unsigned char)ch;
  266. return APR_SUCCESS;
  267. }
  268. APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile)
  269. {
  270. apr_size_t nbytes = 1;
  271. return apr_file_read(thefile, ch, &nbytes);
  272. }
  273. APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile)
  274. {
  275. return apr_file_write_full(thefile, str, strlen(str), NULL);
  276. }
  277. apr_status_t apr_file_flush_locked(apr_file_t *thefile)
  278. {
  279. apr_status_t rv = APR_SUCCESS;
  280. if (thefile->direction == 1 && thefile->bufpos) {
  281. apr_ssize_t written = 0, ret;
  282. do {
  283. ret = write(thefile->filedes, thefile->buffer + written,
  284. thefile->bufpos - written);
  285. if (ret > 0)
  286. written += ret;
  287. } while (written < thefile->bufpos &&
  288. (ret > 0 || (ret == -1 && errno == EINTR)));
  289. if (ret == -1) {
  290. rv = errno;
  291. } else {
  292. thefile->filePtr += written;
  293. thefile->bufpos = 0;
  294. }
  295. }
  296. return rv;
  297. }
  298. APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile)
  299. {
  300. apr_status_t rv = APR_SUCCESS;
  301. if (thefile->buffered) {
  302. file_lock(thefile);
  303. rv = apr_file_flush_locked(thefile);
  304. file_unlock(thefile);
  305. }
  306. /* There isn't anything to do if we aren't buffering the output
  307. * so just return success.
  308. */
  309. return rv;
  310. }
  311. APR_DECLARE(apr_status_t) apr_file_sync(apr_file_t *thefile)
  312. {
  313. apr_status_t rv = APR_SUCCESS;
  314. file_lock(thefile);
  315. if (thefile->buffered) {
  316. rv = apr_file_flush_locked(thefile);
  317. if (rv != APR_SUCCESS) {
  318. file_unlock(thefile);
  319. return rv;
  320. }
  321. }
  322. if (fsync(thefile->filedes)) {
  323. rv = apr_get_os_error();
  324. }
  325. file_unlock(thefile);
  326. return rv;
  327. }
  328. APR_DECLARE(apr_status_t) apr_file_datasync(apr_file_t *thefile)
  329. {
  330. apr_status_t rv = APR_SUCCESS;
  331. file_lock(thefile);
  332. if (thefile->buffered) {
  333. rv = apr_file_flush_locked(thefile);
  334. if (rv != APR_SUCCESS) {
  335. file_unlock(thefile);
  336. return rv;
  337. }
  338. }
  339. #ifdef HAVE_FDATASYNC
  340. if (fdatasync(thefile->filedes)) {
  341. #else
  342. if (fsync(thefile->filedes)) {
  343. #endif
  344. rv = apr_get_os_error();
  345. }
  346. file_unlock(thefile);
  347. return rv;
  348. }
  349. APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile)
  350. {
  351. apr_status_t rv = APR_SUCCESS; /* get rid of gcc warning */
  352. apr_size_t nbytes;
  353. const char *str_start = str;
  354. char *final = str + len - 1;
  355. if (len <= 1) {
  356. /* sort of like fgets(), which returns NULL and stores no bytes
  357. */
  358. return APR_SUCCESS;
  359. }
  360. /* If we have an underlying buffer, we can be *much* more efficient
  361. * and skip over the apr_file_read calls.
  362. */
  363. if (thefile->buffered) {
  364. file_lock(thefile);
  365. if (thefile->direction == 1) {
  366. rv = apr_file_flush_locked(thefile);
  367. if (rv) {
  368. file_unlock(thefile);
  369. return rv;
  370. }
  371. thefile->direction = 0;
  372. thefile->bufpos = 0;
  373. thefile->dataRead = 0;
  374. }
  375. while (str < final) { /* leave room for trailing '\0' */
  376. /* Force ungetc leftover to call apr_file_read. */
  377. if (thefile->bufpos < thefile->dataRead &&
  378. thefile->ungetchar == -1) {
  379. *str = thefile->buffer[thefile->bufpos++];
  380. }
  381. else {
  382. nbytes = 1;
  383. rv = file_read_buffered(thefile, str, &nbytes);
  384. if (rv != APR_SUCCESS) {
  385. break;
  386. }
  387. }
  388. if (*str == '\n') {
  389. ++str;
  390. break;
  391. }
  392. ++str;
  393. }
  394. file_unlock(thefile);
  395. }
  396. else {
  397. while (str < final) { /* leave room for trailing '\0' */
  398. nbytes = 1;
  399. rv = apr_file_read(thefile, str, &nbytes);
  400. if (rv != APR_SUCCESS) {
  401. break;
  402. }
  403. if (*str == '\n') {
  404. ++str;
  405. break;
  406. }
  407. ++str;
  408. }
  409. }
  410. /* We must store a terminating '\0' if we've stored any chars. We can
  411. * get away with storing it if we hit an error first.
  412. */
  413. *str = '\0';
  414. if (str > str_start) {
  415. /* we stored chars; don't report EOF or any other errors;
  416. * the app will find out about that on the next call
  417. */
  418. return APR_SUCCESS;
  419. }
  420. return rv;
  421. }
  422. struct apr_file_printf_data {
  423. apr_vformatter_buff_t vbuff;
  424. apr_file_t *fptr;
  425. char *buf;
  426. };
  427. static int file_printf_flush(apr_vformatter_buff_t *buff)
  428. {
  429. struct apr_file_printf_data *data = (struct apr_file_printf_data *)buff;
  430. if (apr_file_write_full(data->fptr, data->buf,
  431. data->vbuff.curpos - data->buf, NULL)) {
  432. return -1;
  433. }
  434. data->vbuff.curpos = data->buf;
  435. return 0;
  436. }
  437. APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr,
  438. const char *format, ...)
  439. {
  440. struct apr_file_printf_data data;
  441. va_list ap;
  442. int count;
  443. /* don't really need a HUGE_STRING_LEN anymore */
  444. data.buf = malloc(HUGE_STRING_LEN);
  445. if (data.buf == NULL) {
  446. return -1;
  447. }
  448. data.vbuff.curpos = data.buf;
  449. data.vbuff.endpos = data.buf + HUGE_STRING_LEN;
  450. data.fptr = fptr;
  451. va_start(ap, format);
  452. count = apr_vformatter(file_printf_flush,
  453. (apr_vformatter_buff_t *)&data, format, ap);
  454. /* apr_vformatter does not call flush for the last bits */
  455. if (count >= 0) file_printf_flush((apr_vformatter_buff_t *)&data);
  456. va_end(ap);
  457. free(data.buf);
  458. return count;
  459. }