diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -706,6 +706,31 @@ Availability: Unix, and Windows starting in 2.2.3. +.. function:: fullsync(fd) + + The POSIX standart requires that :c:func:`fsync` must transfer the buffered + data to the storage device, not that the data is actually written by the + device itself. It explicitely leaves it up to operating system implementors + whether users are given stronger guarantees on data integrity or not. Some + systems also offer special functions which overtake the part of making such + stronger guarantees, i.e., Mac OS X and NetBSD. :func:`fullsync` is + identical to :func:`fsync` unless there is such special functionality + available, in which case that will be used. + To strive for best-possible data integrity, the following can be done:: + + # Force writeout of local buffer modifications + f.flush() + # Then synchronize the changes to physical backing store + if hasattr(os, 'fsync'): + os.fullsync(f.fileno()) + + ..note:: + Calling this function may take a long time, since it may block + until the disk reports that the transfer has been completed. + + Availability: See :func:`fsync`. + + .. function:: ftruncate(fd, length) Truncate the file corresponding to file descriptor *fd*, so that it is at most diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -554,7 +554,7 @@ class TestInvalidFD(unittest.TestCase): singles = ["fchdir", "fdopen", "dup", "fdatasync", "fstat", - "fstatvfs", "fsync", "tcgetpgrp", "ttyname"] + "fstatvfs", "fsync", "fullsync", "tcgetpgrp", "ttyname"] #singles.append("close") #We omit close because it doesn'r raise an exception on some platforms def get_single(f): diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1855,6 +1855,42 @@ { return posix_fildes(fdobj, fsync); } + +PyDoc_STRVAR(fullsync__doc__, +"fullsync(fd)\n\n" +"force write of file buffers to disk, and the flush of disk caches\n" +"of the file given by file descriptor fd."); + +static PyObject * +fullsync(PyObject *self, PyObject *fdobj) +{ + /* See issue 11877 discussion */ + int res, fd = PyObject_AsFileDescriptor(fdobj); + if (fd < 0) + return NULL; + if (!_PyVerify_fd(fd)) + return posix_error(); + + Py_BEGIN_ALLOW_THREADS +# if defined __APPLE__ + /* F_FULLFSYNC is not supported for all types of FDs/FSYSs; + * be on the safe side and test for inappropriate ioctl errors. + * Because plain fsync() may succeed even then, let it decide about error */ + res = fcntl(fd, F_FULLFSYNC); + if (res < 0 && errno == ENOTTY) + res = fsync(fd); +# elif defined __NetBSD__ + res = fsync_range(fd, FFILESYNC | FDISKSYNC, 0, 0); +# else + res = fsync(fd); +# endif + Py_END_ALLOW_THREADS + + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +} #endif /* HAVE_FSYNC */ #ifdef HAVE_FDATASYNC @@ -8953,6 +8989,7 @@ #endif #ifdef HAVE_FSYNC {"fsync", posix_fsync, METH_O, posix_fsync__doc__}, + {"fullsync", fullsync, METH_O, fullsync__doc__}, #endif #ifdef HAVE_FDATASYNC {"fdatasync", posix_fdatasync, METH_O, posix_fdatasync__doc__},

AltStyle によって変換されたページ (->オリジナル) /