mirror of https://github.com/borgbackup/borg.git
parent
11687fbec1
commit
3ab53b776d
1
CHANGES
1
CHANGES
|
@ -15,6 +15,7 @@ Version 0.13
|
|||
- Fix bug where xattrs on symlinks were not correctly restored
|
||||
- Added cachedir support. CACHEDIR.TAG compatible cache directories
|
||||
can now be excluded using ``--exclude-caches`` (#74)
|
||||
- Fix crash on extreme mtime timestamps (year 2400+) (#81)
|
||||
|
||||
Version 0.12
|
||||
------------
|
||||
|
|
|
@ -18,7 +18,7 @@ from attic.platform import acl_get, acl_set
|
|||
from attic.chunker import chunkify
|
||||
from attic.hashindex import ChunkIndex
|
||||
from attic.helpers import Error, uid2user, user2uid, gid2group, group2gid, \
|
||||
Manifest, Statistics, decode_dict, st_mtime_ns, make_path_safe, StableDict
|
||||
Manifest, Statistics, decode_dict, st_mtime_ns, make_path_safe, StableDict, int_to_bigint, bigint_to_int
|
||||
|
||||
ITEMS_BUFFER = 1024 * 1024
|
||||
CHUNK_MIN = 1024
|
||||
|
@ -311,12 +311,13 @@ class Archive:
|
|||
os.chmod(path, item[b'mode'])
|
||||
elif has_lchmod: # Not available on Linux
|
||||
os.lchmod(path, item[b'mode'])
|
||||
mtime = bigint_to_int(item[b'mtime'])
|
||||
if fd and utime_supports_fd: # Python >= 3.3
|
||||
os.utime(fd, None, ns=(item[b'mtime'], item[b'mtime']))
|
||||
os.utime(fd, None, ns=(mtime, mtime))
|
||||
elif utime_supports_fd: # Python >= 3.3
|
||||
os.utime(path, None, ns=(item[b'mtime'], item[b'mtime']), follow_symlinks=False)
|
||||
os.utime(path, None, ns=(mtime, mtime), follow_symlinks=False)
|
||||
elif not symlink:
|
||||
os.utime(path, (item[b'mtime'] / 10**9, item[b'mtime'] / 10**9))
|
||||
os.utime(path, (mtime / 1e9, mtime / 1e9))
|
||||
acl_set(path, item, self.numeric_owner)
|
||||
# Only available on OS X and FreeBSD
|
||||
if has_lchflags and b'bsdflags' in item:
|
||||
|
@ -343,7 +344,7 @@ class Archive:
|
|||
b'mode': st.st_mode,
|
||||
b'uid': st.st_uid, b'user': uid2user(st.st_uid),
|
||||
b'gid': st.st_gid, b'group': gid2group(st.st_gid),
|
||||
b'mtime': st_mtime_ns(st),
|
||||
b'mtime': int_to_bigint(st_mtime_ns(st))
|
||||
}
|
||||
if self.numeric_owner:
|
||||
item[b'user'] = item[b'group'] = None
|
||||
|
|
|
@ -18,7 +18,7 @@ from attic.helpers import Error, location_validator, format_time, \
|
|||
format_file_mode, ExcludePattern, exclude_path, adjust_patterns, to_localtime, \
|
||||
get_cache_dir, get_keys_dir, format_timedelta, prune_within, prune_split, \
|
||||
Manifest, remove_surrogates, update_excludes, format_archive, check_extension_modules, Statistics, \
|
||||
is_cachedir
|
||||
is_cachedir, bigint_to_int
|
||||
from attic.remote import RepositoryServer, RemoteRepository
|
||||
|
||||
|
||||
|
@ -272,7 +272,7 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|||
size = sum(size for _, size, _ in item[b'chunks'])
|
||||
except KeyError:
|
||||
pass
|
||||
mtime = format_time(datetime.fromtimestamp(item[b'mtime'] / 10**9))
|
||||
mtime = format_time(datetime.fromtimestamp(bigint_to_int(item[b'mtime']) / 1e9))
|
||||
if b'source' in item:
|
||||
if type == 'l':
|
||||
extra = ' -> %s' % item[b'source']
|
||||
|
|
|
@ -280,7 +280,7 @@ def walk_path(path, skip_inodes=None):
|
|||
def format_time(t):
|
||||
"""Format datetime suitable for fixed length list output
|
||||
"""
|
||||
if (datetime.now() - t).days < 365:
|
||||
if abs((datetime.now() - t).days) < 365:
|
||||
return t.strftime('%b %d %H:%M')
|
||||
else:
|
||||
return t.strftime('%b %d %Y')
|
||||
|
@ -548,3 +548,21 @@ else:
|
|||
return st.st_mtime_ns
|
||||
|
||||
unhexlify = binascii.unhexlify
|
||||
|
||||
|
||||
def bigint_to_int(mtime):
|
||||
"""Convert bytearray to int
|
||||
"""
|
||||
if isinstance(mtime, bytes):
|
||||
return int.from_bytes(mtime, 'little', signed=True)
|
||||
return mtime
|
||||
|
||||
|
||||
def int_to_bigint(value):
|
||||
"""Convert integers larger than 64 bits to bytearray
|
||||
|
||||
Smaller integers are left alone
|
||||
"""
|
||||
if value.bit_length() > 63:
|
||||
return value.to_bytes((value.bit_length() + 9) // 8, 'little', signed=True)
|
||||
return value
|
||||
|
|
|
@ -120,6 +120,8 @@ class ArchiverTestCase(ArchiverTestCaseBase):
|
|||
"""
|
||||
# File
|
||||
self.create_regular_file('empty', size=0)
|
||||
# 2600-01-01 > 2**64 ns
|
||||
os.utime('input/empty', (19880895600, 19880895600))
|
||||
self.create_regular_file('file1', size=1024 * 80)
|
||||
self.create_regular_file('flagfile', size=1024)
|
||||
# Directory
|
||||
|
|
|
@ -5,11 +5,23 @@ import os
|
|||
import tempfile
|
||||
import unittest
|
||||
from attic.helpers import adjust_patterns, exclude_path, Location, format_timedelta, IncludePattern, ExcludePattern, make_path_safe, UpgradableLock, prune_within, prune_split, to_localtime, \
|
||||
StableDict
|
||||
StableDict, int_to_bigint, bigint_to_int
|
||||
from attic.testsuite import AtticTestCase
|
||||
import msgpack
|
||||
|
||||
|
||||
class BigIntTestCase(AtticTestCase):
|
||||
|
||||
def test_bigint(self):
|
||||
self.assert_equal(int_to_bigint(0), 0)
|
||||
self.assert_equal(int_to_bigint(2**63-1), 2**63-1)
|
||||
self.assert_equal(int_to_bigint(-2**63+1), -2**63+1)
|
||||
self.assert_equal(int_to_bigint(2**63), b'\x00\x00\x00\x00\x00\x00\x00\x80\x00')
|
||||
self.assert_equal(int_to_bigint(-2**63), b'\x00\x00\x00\x00\x00\x00\x00\x80\xff')
|
||||
self.assert_equal(bigint_to_int(int_to_bigint(-2**70)), -2**70)
|
||||
self.assert_equal(bigint_to_int(int_to_bigint(2**70)), 2**70)
|
||||
|
||||
|
||||
class LocationTestCase(AtticTestCase):
|
||||
|
||||
def test(self):
|
||||
|
|
Loading…
Reference in New Issue