Fix iOS helper: correct date parsing and pull method

Date: AFC st_mtime is nanoseconds since epoch. Fix threshold check:
values > 1e18 are nanoseconds, > 1e9 are seconds. Dec 31 bug was
caused by mtime being treated as seconds when it was nanoseconds,
giving a timestamp near epoch (1970 = Dec 31 local time).

Pull: use get_file_contents() which is the correct async AFC method
(not pull/afc.open which don't exist in this pymobiledevice3 version).
This commit is contained in:
Kyle Bolen
2026-07-28 08:17:39 +00:00
parent 7f11a4b7d6
commit d947018f42

View File

@@ -90,9 +90,16 @@ async def cmd_list_photos():
try:
info = await afc.stat(device_path)
size_bytes = int(info.get('st_size', 0))
mtime_ns = int(info.get('st_mtime', 0))
# st_mtime may be nanoseconds or seconds depending on version
mtime_s = mtime_ns / 1_000_000_000 if mtime_ns > 1_700_000_000_000 else mtime_ns
mtime_raw = int(info.get('st_mtime', 0))
# AFC st_mtime is nanoseconds since epoch (not seconds)
# A reasonable photo date in nanoseconds is > 1e18
# In seconds it would be > 1e9 (year 2001+)
if mtime_raw > 1_000_000_000_000_000_000:
mtime_s = mtime_raw / 1_000_000_000
elif mtime_raw > 1_000_000_000:
mtime_s = mtime_raw # already seconds
else:
mtime_s = 0
if mtime_s > 0:
date_iso = datetime.fromtimestamp(mtime_s).isoformat()
except Exception:
@@ -120,7 +127,9 @@ async def cmd_pull(device_path: str, local_path: str):
lockdown = await get_lockdown()
afc = await get_afc(lockdown)
os.makedirs(os.path.dirname(os.path.abspath(local_path)), exist_ok=True)
await afc.pull(device_path, local_path)
data = await afc.get_file_contents(device_path)
with open(local_path, 'wb') as f:
f.write(data)
print(json.dumps({'ok': True, 'path': local_path}))
except Exception as e:
print(f'Error: {e}', file=sys.stderr)