diff options
author | bojan <bojan@13f79535-47bb-0310-9956-ffa450edef68> | 2007-05-11 02:11:25 +0000 |
---|---|---|
committer | bojan <bojan@13f79535-47bb-0310-9956-ffa450edef68> | 2007-05-11 02:11:25 +0000 |
commit | 567718da876063aeb57ae5d884c7799f762e66ec (patch) | |
tree | ec42b4e701e7a9e40503b21e78678e477b43028e | |
parent | 0054746b016c46cf445f3023ad8b37e7a6495424 (diff) | |
download | libapr-567718da876063aeb57ae5d884c7799f762e66ec.tar.gz |
The file pointer position must be recalculated and set when writev()ing to a
buffered file.
Fix by Davi Arnaut for bug #40963
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@537066 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | file_io/unix/readwrite.c | 9 | ||||
-rw-r--r-- | test/testfile.c | 39 |
2 files changed, 48 insertions, 0 deletions
diff --git a/file_io/unix/readwrite.c b/file_io/unix/readwrite.c index 3511846d9..412d7c8ba 100644 --- a/file_io/unix/readwrite.c +++ b/file_io/unix/readwrite.c @@ -252,6 +252,15 @@ APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iove if (rv != APR_SUCCESS) { return rv; } + if (thefile->direction == 0) { + /* Position file pointer for writing at the offset we are + * logically reading from + */ + apr_int64_t offset = thefile->filePtr - thefile->dataRead + thefile->bufpos; + if (offset != thefile->filePtr) + lseek(thefile->filedes, offset, SEEK_SET); + thefile->bufpos = thefile->dataRead = 0; + } } #ifdef HAVE_WRITEV diff --git a/test/testfile.c b/test/testfile.c index df63d081f..9f24dcc54 100644 --- a/test/testfile.c +++ b/test/testfile.c @@ -715,6 +715,44 @@ static void test_writev_buffered(abts_case *tc, void *data) strlen(TESTSTR) + strlen(LINE1) + strlen(LINE2)); } +static void test_writev_buffered_seek(abts_case *tc, void *data) +{ + apr_file_t *f; + apr_status_t rv; + apr_off_t off = 0; + struct iovec vec[3]; + apr_size_t nbytes = strlen(TESTSTR); + char *str = apr_pcalloc(p, nbytes+1); + const char *fname = "data/testwritev_buffered.dat"; + + APR_ASSERT_SUCCESS(tc, "open file for writing", + apr_file_open(&f, fname, + APR_WRITE | APR_READ | APR_BUFFERED, + APR_OS_DEFAULT, p)); + + rv = apr_file_read(f, str, &nbytes); + ABTS_STR_EQUAL(tc, TESTSTR, str); + APR_ASSERT_SUCCESS(tc, "buffered seek", apr_file_seek(f, APR_SET, &off)); + + vec[0].iov_base = LINE1; + vec[0].iov_len = strlen(LINE1); + vec[1].iov_base = LINE2; + vec[1].iov_len = strlen(LINE2); + vec[2].iov_base = TESTSTR; + vec[2].iov_len = strlen(TESTSTR); + + APR_ASSERT_SUCCESS(tc, "writev of size 2 to file", + apr_file_writev(f, vec, 3, &nbytes)); + + APR_ASSERT_SUCCESS(tc, "close for writing", + apr_file_close(f)); + + file_contents_equal(tc, fname, LINE1 LINE2 TESTSTR, + strlen(LINE1) + strlen(LINE2) + strlen(TESTSTR)); + + APR_ASSERT_SUCCESS(tc, "remove file", apr_file_remove(fname, p)); +} + static void test_truncate(abts_case *tc, void *data) { apr_status_t rv; @@ -941,6 +979,7 @@ abts_suite *testfile(abts_suite *suite) abts_run_test(suite, test_writev, NULL); abts_run_test(suite, test_writev_full, NULL); abts_run_test(suite, test_writev_buffered, NULL); + abts_run_test(suite, test_writev_buffered_seek, NULL); abts_run_test(suite, test_bigread, NULL); abts_run_test(suite, test_mod_neg, NULL); abts_run_test(suite, test_truncate, NULL); |