diff --git a/file_io/unix/readwrite.c b/file_io/unix/readwrite.c index 0759495affb..ee204ab45bc 100644 --- a/file_io/unix/readwrite.c +++ b/file_io/unix/readwrite.c @@ -373,6 +373,7 @@ APR_DECLARE(apr_status_t) apr_file_sync(apr_file_t *thefile) APR_DECLARE(apr_status_t) apr_file_datasync(apr_file_t *thefile) { apr_status_t rv = APR_SUCCESS; + int os_status = 0; file_lock(thefile); @@ -386,12 +387,17 @@ APR_DECLARE(apr_status_t) apr_file_datasync(apr_file_t *thefile) } #ifdef HAVE_FDATASYNC - if (fdatasync(thefile->filedes)) { + os_status = fdatasync(thefile->filedes); #elif defined(F_FULLFSYNC) - if (fcntl(thefile->filedes, F_FULLFSYNC)) { + os_status = fcntl(thefile->filedes, F_FULLFSYNC); + if (os_status) { + /* Fall back to fsync() if the device doesn't support F_FULLFSYNC. */ + os_status = fsync(thefile->filedes); + } #else - if (fsync(thefile->filedes)) { + os_status = fsync(thefile->filedes); #endif + if (os_status) { rv = apr_get_os_error(); } diff --git a/test/testfile.c b/test/testfile.c index 36ab4f0d8f1..f90ca92baed 100644 --- a/test/testfile.c +++ b/test/testfile.c @@ -1219,6 +1219,41 @@ static void test_xthread(abts_case *tc, void *data) apr_file_close(f); } +static void test_datasync_on_file(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = DIRNAME "/testtest_datasync.dat"; + apr_size_t bytes_written; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for writing", rv); + rv = apr_file_write_full(f, "abcdef", 6, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + rv = apr_file_datasync(f); + APR_ASSERT_SUCCESS(tc, "sync file contents", rv); + apr_file_close(f); + + apr_file_remove(fname, p); +} + +static void test_datasync_on_stream(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + apr_size_t bytes_written; + + rv = apr_file_open_stdout(&f, p); + APR_ASSERT_SUCCESS(tc, "open stdout", rv); + rv = apr_file_write_full(f, "abcdef\b\b\b\b\b\b\b", 12, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to stdout", rv); + rv = apr_file_datasync(f); + APR_ASSERT_SUCCESS(tc, "sync stdout", rv); +} + abts_suite *testfile(abts_suite *suite) { suite = ADD_SUITE(suite) @@ -1263,6 +1298,8 @@ abts_suite *testfile(abts_suite *suite) abts_run_test(suite, test_fail_read_flush, NULL); abts_run_test(suite, test_buffer_set_get, NULL); abts_run_test(suite, test_xthread, NULL); + abts_run_test(suite, test_datasync_on_file, NULL); + abts_run_test(suite, test_datasync_on_stream, NULL); return suite; }