1
0
Fork 0
mirror of https://github.com/borgbackup/borg.git synced 2025-02-23 14:41:43 +00:00

remove posix issues and fixup for unsupported methodes

This commit is contained in:
Emmo Emminghaus 2018-11-10 21:48:46 +01:00
parent b997d5ba5b
commit 558ca61d20
8 changed files with 93 additions and 68 deletions

View file

@ -680,43 +680,46 @@ def restore_attrs(self, path, item, symlink=False, fd=None):
gid = item.gid if gid is None else gid
# This code is a bit of a mess due to os specific differences
try:
if fd:
os.fchown(fd, uid, gid)
else:
os.chown(path, uid, gid, follow_symlinks=False)
except OSError:
pass
if fd:
os.fchmod(fd, item.mode)
elif not symlink:
os.chmod(path, item.mode)
elif has_lchmod: # Not available on Linux
os.lchmod(path, item.mode)
mtime = item.mtime
if 'atime' in item:
atime = item.atime
else:
# old archives only had mtime in item metadata
atime = mtime
if 'birthtime' in item:
birthtime = item.birthtime
try:
# This should work on FreeBSD, NetBSD, and Darwin and be harmless on other platforms.
# See utimes(2) on either of the BSDs for details.
if fd:
os.utime(fd, None, ns=(atime, birthtime))
os.fchown(fd, uid, gid)
else:
os.utime(path, None, ns=(atime, birthtime), follow_symlinks=False)
os.chown(path, uid, gid, follow_symlinks=False)
except OSError:
pass
if fd:
os.fchmod(fd, item.mode)
elif not symlink:
os.chmod(path, item.mode)
elif has_lchmod: # Not available on Linux
os.lchmod(path, item.mode)
mtime = item.mtime
if 'atime' in item:
atime = item.atime
else:
# old archives only had mtime in item metadata
atime = mtime
if 'birthtime' in item:
birthtime = item.birthtime
try:
# This should work on FreeBSD, NetBSD, and Darwin and be harmless on other platforms.
# See utimes(2) on either of the BSDs for details.
if fd:
os.utime(fd, None, ns=(atime, birthtime))
else:
os.utime(path, None, ns=(atime, birthtime), follow_symlinks=False)
except OSError:
# some systems don't support calling utime on a symlink
pass
try:
if fd:
os.utime(fd, None, ns=(atime, mtime))
else:
os.utime(path, None, ns=(atime, mtime), follow_symlinks=False)
except OSError:
# some systems don't support calling utime on a symlink
pass
try:
if fd:
os.utime(fd, None, ns=(atime, mtime))
else:
os.utime(path, None, ns=(atime, mtime), follow_symlinks=False)
except OSError:
# some systems don't support calling utime on a symlink
except AttributeError:
pass
acl_set(path, item, self.numeric_owner, fd=fd)
# chown removes Linux capabilities, so set the extended attributes at the end, after chown, since they include

View file

@ -1,4 +1,5 @@
import os
import sys
from .errors import Error
@ -8,9 +9,14 @@ class PythonLibcTooOld(Error):
def check_python():
required_funcs = {os.stat, os.utime, os.chown}
if sys.platform.startswith(('win32', )):
required_funcs = {os.stat}
else:
required_funcs = {os.stat, os.utime, os.chown}
if not os.supports_follow_symlinks.issuperset(required_funcs):
raise PythonLibcTooOld
pass
class ExtensionModuleError(Error):

View file

@ -19,6 +19,7 @@
from .posix import process_alive, local_pid_alive
# posix swidth implementation works for: linux, freebsd, darwin, openindiana, cygwin
from .posix import swidth
from .posix import get_errno
from .posix import uid2user, user2uid, gid2group, group2gid, getosusername
if sys.platform.startswith('linux'): # pragma: linux only

View file

@ -1,8 +1,6 @@
import errno
import os
from .posix import get_errno
from ..helpers import Buffer
@ -39,6 +37,7 @@ class BufferTooSmallError(Exception):
def _check(rv, path=None, detect_buffer_too_small=False):
from . import get_errno # circular reference if imported at global level!
if rv < 0:
e = get_errno()
if detect_buffer_too_small and e == errno.ERANGE:

View file

@ -652,6 +652,10 @@ def check_free_space(self):
except OSError as os_error:
logger.warning('Failed to check free space before committing: ' + str(os_error))
return
except AttributeError:
# TODO move the call to statvfs to platform
logger.warning('Failed to check free space before committing: no statvfs method available' )
return
# f_bavail: even as root - don't touch the Federal Block Reserve!
free_space = st_vfs.f_bavail * st_vfs.f_bsize
logger.debug('check_free_space: required bytes {}, free bytes {}'.format(required_free_space, free_space))

View file

@ -2,7 +2,11 @@
import filecmp
import functools
import os
import posix
try:
import posix # buildin but not everywhere
except:
posix = None
import stat
import sys
import sysconfig
@ -44,7 +48,7 @@
has_llfuse = False
# The mtime get/set precision varies on different OS and Python versions
if 'HAVE_FUTIMENS' in getattr(posix, '_have_functions', []):
if posix != None and 'HAVE_FUTIMENS' in getattr(posix, '_have_functions', []):
st_mtime_ns_round = 0
elif 'HAVE_UTIMES' in sysconfig.get_config_vars():
st_mtime_ns_round = -6
@ -95,7 +99,10 @@ def are_fifos_supported():
os.mkfifo(filepath)
return True
except OSError:
return False
pass
except NotImplementedError:
pass
return False
@functools.lru_cache()
@ -113,6 +120,8 @@ def is_utime_fully_supported():
return True
except OSError:
pass
except NotImplementedError:
pass
return False
@ -135,6 +144,8 @@ def is_birthtime_fully_supported():
return True
except OSError:
pass
except NotImplementedError:
pass
return False

View file

@ -8,7 +8,7 @@
from ..hashindex import NSIndex, ChunkIndex, ChunkIndexEntry
from .. import hashindex
from ..crypto.file_integrity import IntegrityCheckedFile, FileIntegrityError
from . import BaseTestCase
from . import BaseTestCase, unopened_tempfile
# Note: these tests are part of the self test, do not use or import py.test functionality here.
# See borg.selftest for details. If you add/remove test methods, update SELFTEST_COUNT
@ -55,21 +55,22 @@ def _generic_test(self, cls, make_value, sha):
self.assert_raises(KeyError, idx.__delitem__, H(x))
self.assert_equal(len(idx), 50)
idx_name = tempfile.NamedTemporaryFile()
idx.write(idx_name.name)
del idx
# Verify file contents
with open(idx_name.name, 'rb') as fd:
self.assert_equal(hashlib.sha256(fd.read()).hexdigest(), sha)
# Make sure we can open the file
idx = cls.read(idx_name.name)
self.assert_equal(len(idx), 50)
for x in range(50, 100):
self.assert_equal(idx[H(x)], make_value(x * 2))
idx.clear()
self.assert_equal(len(idx), 0)
idx.write(idx_name.name)
del idx
self.assert_equal(len(cls.read(idx_name.name)), 0)
with unopened_tempfile() as filepath:
idx.write(filepath)
del idx
# Verify file contents
with open(filepath, 'rb') as fd:
self.assert_equal(hashlib.sha256(fd.read()).hexdigest(), sha)
# Make sure we can open the file
idx = cls.read(filepath)
self.assert_equal(len(idx), 50)
for x in range(50, 100):
self.assert_equal(idx[H(x)], make_value(x * 2))
idx.clear()
self.assert_equal(len(idx), 0)
idx.write(filepath)
del idx
self.assert_equal(len(cls.read(filepath)), 0)
def test_nsindex(self):
self._generic_test(NSIndex, lambda x: (x, x),
@ -81,20 +82,20 @@ def test_chunkindex(self):
def test_resize(self):
n = 2000 # Must be >= MIN_BUCKETS
idx_name = tempfile.NamedTemporaryFile()
idx = NSIndex()
idx.write(idx_name.name)
initial_size = os.path.getsize(idx_name.name)
self.assert_equal(len(idx), 0)
for x in range(n):
idx[H(x)] = x, x
idx.write(idx_name.name)
self.assert_true(initial_size < os.path.getsize(idx_name.name))
for x in range(n):
del idx[H(x)]
self.assert_equal(len(idx), 0)
idx.write(idx_name.name)
self.assert_equal(initial_size, os.path.getsize(idx_name.name))
with unopened_tempfile() as filepath:
idx = NSIndex()
idx.write(filepath)
initial_size = os.path.getsize(filepath)
self.assert_equal(len(idx), 0)
for x in range(n):
idx[H(x)] = x, x
idx.write(filepath)
self.assert_true(initial_size < os.path.getsize(filepath))
for x in range(n):
del idx[H(x)]
self.assert_equal(len(idx), 0)
idx.write(filepath)
self.assert_equal(initial_size, os.path.getsize(filepath))
def test_iteritems(self):
idx = NSIndex()

View file

@ -4,7 +4,6 @@
import shutil
import sys
import tempfile
import pwd
import unittest
from ..platform import acl_get, acl_set, swidth
@ -44,6 +43,7 @@ def fakeroot_detected():
def user_exists(username):
try:
import pwd # buildin but not on all OS
pwd.getpwnam(username)
return True
except (KeyError, ValueError):