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:
parent
b997d5ba5b
commit
558ca61d20
8 changed files with 93 additions and 68 deletions
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in a new issue