mirror of
https://github.com/borgbackup/borg.git
synced 2026-03-30 14:18:09 -04:00
commit
1c05ab32db
4 changed files with 34 additions and 9 deletions
|
|
@ -26,12 +26,21 @@ def parse_local_timestamp(timestamp, tzinfo=None):
|
|||
return dt
|
||||
|
||||
|
||||
_EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc)
|
||||
|
||||
|
||||
def utcfromtimestampns(ts_ns: int) -> datetime:
|
||||
# similar to datetime.fromtimestamp, but works with ns and avoids floating point.
|
||||
# also, it would avoid an overflow on 32bit platforms with old glibc.
|
||||
return _EPOCH + timedelta(microseconds=ts_ns // 1000)
|
||||
|
||||
|
||||
def timestamp(s):
|
||||
"""Convert a --timestamp=s argument to a datetime object."""
|
||||
try:
|
||||
# is it pointing to a file / directory?
|
||||
ts = safe_s(os.stat(s).st_mtime)
|
||||
return datetime.fromtimestamp(ts, tz=timezone.utc)
|
||||
ts_ns = safe_ns(os.stat(s).st_mtime_ns)
|
||||
return utcfromtimestampns(ts_ns)
|
||||
except OSError:
|
||||
# didn't work, try parsing as an ISO timestamp. if no TZ is given, we assume local timezone.
|
||||
return parse_local_timestamp(s)
|
||||
|
|
@ -44,7 +53,7 @@ def timestamp(s):
|
|||
# As long as people are using borg on 32bit platforms to access borg archives, we must
|
||||
# keep this value True. But we can expect that we can stop supporting 32bit platforms
|
||||
# well before coming close to the year 2038, so this will never be a practical problem.
|
||||
SUPPORT_32BIT_PLATFORMS = True # set this to False before y2038.
|
||||
SUPPORT_32BIT_PLATFORMS = False # set this to False before y2038.
|
||||
|
||||
if SUPPORT_32BIT_PLATFORMS:
|
||||
# second timestamps will fit into a signed int32 (platform time_t limit).
|
||||
|
|
@ -84,7 +93,7 @@ def safe_ns(ts):
|
|||
|
||||
def safe_timestamp(item_timestamp_ns):
|
||||
t_ns = safe_ns(item_timestamp_ns)
|
||||
return datetime.fromtimestamp(t_ns / 1e9, timezone.utc) # return tz-aware utc datetime obj
|
||||
return utcfromtimestampns(t_ns) # return tz-aware utc datetime obj
|
||||
|
||||
|
||||
def format_time(ts: datetime, format_spec=""):
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ def test_nobirthtime(archivers, request):
|
|||
assert same_ts_ns(sti.st_birthtime * 1e9, birthtime * 1e9)
|
||||
assert same_ts_ns(sto.st_birthtime * 1e9, mtime * 1e9)
|
||||
assert same_ts_ns(sti.st_mtime_ns, sto.st_mtime_ns)
|
||||
assert same_ts_ns(sto.st_mtime_ns, mtime * 1e9)
|
||||
assert same_ts_ns(sto.st_mtime_ns, mtime * 10**9)
|
||||
|
||||
|
||||
def test_create_stdin(archivers, request):
|
||||
|
|
|
|||
|
|
@ -153,13 +153,13 @@ def test_atime(archivers, request):
|
|||
sti = os.stat("input/file1")
|
||||
sto = os.stat("output/input/file1")
|
||||
assert same_ts_ns(sti.st_mtime_ns, sto.st_mtime_ns)
|
||||
assert same_ts_ns(sto.st_mtime_ns, mtime * 1e9)
|
||||
assert same_ts_ns(sto.st_mtime_ns, mtime * 10**9)
|
||||
if have_noatime:
|
||||
assert same_ts_ns(sti.st_atime_ns, sto.st_atime_ns)
|
||||
assert same_ts_ns(sto.st_atime_ns, atime * 1e9)
|
||||
assert same_ts_ns(sto.st_atime_ns, atime * 10**9)
|
||||
else:
|
||||
# it touched the input file's atime while backing it up
|
||||
assert same_ts_ns(sto.st_atime_ns, atime * 1e9)
|
||||
assert same_ts_ns(sto.st_atime_ns, atime * 10**9)
|
||||
|
||||
|
||||
@pytest.mark.skipif(not is_utime_fully_supported(), reason="cannot setup and execute test without utime")
|
||||
|
|
@ -179,7 +179,7 @@ def test_birthtime(archivers, request):
|
|||
assert same_ts_ns(sti.st_birthtime * 1e9, sto.st_birthtime * 1e9)
|
||||
assert same_ts_ns(sto.st_birthtime * 1e9, birthtime * 1e9)
|
||||
assert same_ts_ns(sti.st_mtime_ns, sto.st_mtime_ns)
|
||||
assert same_ts_ns(sto.st_mtime_ns, mtime * 1e9)
|
||||
assert same_ts_ns(sto.st_mtime_ns, mtime * 10**9)
|
||||
|
||||
|
||||
@pytest.mark.skipif(is_win32, reason="frequent test failures on github CI on win32")
|
||||
|
|
@ -825,3 +825,19 @@ def test_extract_existing_directory(archivers, request):
|
|||
cmd(archiver, "extract", "test")
|
||||
st2 = os.stat("input/dir")
|
||||
assert st1.st_ino == st2.st_ino
|
||||
|
||||
|
||||
@pytest.mark.skipif(not is_utime_fully_supported(), reason="cannot properly setup and execute test without utime")
|
||||
def test_extract_y2261(archivers, request):
|
||||
# test if roundtripping of timestamps well beyond y2038 works
|
||||
archiver = request.getfixturevalue(archivers)
|
||||
create_regular_file(archiver.input_path, "file_y2261", contents=b"post y2038 test")
|
||||
# 2261-01-01 00:00:00 UTC as a Unix timestamp (seconds).
|
||||
time_y2261 = 9183110400
|
||||
os.utime("input/file_y2261", (time_y2261, time_y2261))
|
||||
cmd(archiver, "repo-create", RK_ENCRYPTION)
|
||||
cmd(archiver, "create", "test", "input")
|
||||
with changedir("output"):
|
||||
cmd(archiver, "extract", "test")
|
||||
sto = os.stat("output/input/file_y2261")
|
||||
assert same_ts_ns(sto.st_mtime_ns, time_y2261 * 10**9)
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in a new issue