|
- # Implementation of hole punching via fallocate, if the OS
- # and filesystem support it.
-
- try:
- import os
- import ctypes
- import ctypes.util
-
- def make_fallocate():
- libc_name = ctypes.util.find_library('c')
- libc = ctypes.CDLL(libc_name, use_errno=True)
-
- _fallocate = libc.fallocate
- _fallocate.restype = ctypes.c_int
- _fallocate.argtypes = [ ctypes.c_int, ctypes.c_int,
- ctypes.c_int64, ctypes.c_int64 ]
-
- del libc
- del libc_name
-
- def fallocate(fd, mode, offset, len_):
- res = _fallocate(fd, mode, offset, len_)
- if res != 0: # pragma: no cover
- errno = ctypes.get_errno()
- raise IOError(errno, os.strerror(errno))
- return fallocate
-
- fallocate = make_fallocate()
- del make_fallocate
- except Exception: # pragma: no cover
- fallocate = None
-
- FALLOC_FL_KEEP_SIZE = 0x01
- FALLOC_FL_PUNCH_HOLE = 0x02
-
- def punch_hole(filename, offset, length, ignore_errors = True):
- """Punch a hole in the file. This isn't well supported, so errors
- are ignored by default."""
- try:
- if fallocate is None: # pragma: no cover
- raise IOError("fallocate not available")
- with open(filename, "r+") as f:
- fallocate(f.fileno(),
- FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
- offset, length)
- except IOError: # pragma: no cover
- if ignore_errors:
- return
- raise
|