mirror of
https://github.com/leminlimez/Nugget.git
synced 2025-04-08 04:23:05 +08:00
read individual files rather than all at once
This commit is contained in:
@@ -23,19 +23,35 @@ class BackupFile:
|
||||
@dataclass
|
||||
class ConcreteFile(BackupFile):
|
||||
contents: bytes
|
||||
src_path: Optional[str] = None
|
||||
owner: int = 0
|
||||
group: int = 0
|
||||
inode: Optional[int] = None
|
||||
mode: _FileMode = DEFAULT
|
||||
|
||||
hash: bytes = None
|
||||
size: int = None
|
||||
|
||||
def read_contents(self) -> bytes:
|
||||
contents = self.contents
|
||||
if self.contents == None:
|
||||
with open(self.src_path, "rb") as in_file:
|
||||
contents = in_file.read()
|
||||
# prepopulate hash and size
|
||||
self.hash = sha1(contents).digest()
|
||||
self.size = len(contents)
|
||||
return contents
|
||||
|
||||
def to_record(self) -> mbdb.MbdbRecord:
|
||||
if self.inode is None:
|
||||
self.inode = int.from_bytes(randbytes(8), "big")
|
||||
if self.hash == None or self.size == None:
|
||||
self.read_contents()
|
||||
return mbdb.MbdbRecord(
|
||||
domain=self.domain,
|
||||
filename=self.path,
|
||||
link="",
|
||||
hash=sha1(self.contents).digest(),
|
||||
hash=self.hash,
|
||||
key=b"",
|
||||
mode=self.mode | _FileMode.S_IFREG,
|
||||
#unknown2=0,
|
||||
@@ -46,7 +62,7 @@ class ConcreteFile(BackupFile):
|
||||
mtime=int(datetime.now().timestamp()),
|
||||
atime=int(datetime.now().timestamp()),
|
||||
ctime=int(datetime.now().timestamp()),
|
||||
size=len(self.contents),
|
||||
size=self.size,
|
||||
flags=4,
|
||||
properties=[]
|
||||
)
|
||||
@@ -126,7 +142,7 @@ class Backup:
|
||||
if isinstance(file, ConcreteFile):
|
||||
#print("Writing", file.path, "to", directory / sha1((file.domain + "-" + file.path).encode()).digest().hex())
|
||||
with open(directory / sha1((file.domain + "-" + file.path).encode()).digest().hex(), "wb") as f:
|
||||
f.write(file.contents)
|
||||
f.write(file.read_contents())
|
||||
|
||||
with open(directory / "Manifest.mbdb", "wb") as f:
|
||||
f.write(self.generate_manifest_db().to_bytes())
|
||||
|
||||
@@ -4,8 +4,9 @@ from pymobiledevice3.services.installation_proxy import InstallationProxyService
|
||||
import os
|
||||
|
||||
class FileToRestore:
|
||||
def __init__(self, contents: str, restore_path: str, domain: str = None, owner: int = 501, group: int = 501):
|
||||
def __init__(self, contents: str, restore_path: str, contents_path: str = None, domain: str = None, owner: int = 501, group: int = 501):
|
||||
self.contents = contents
|
||||
self.contents_path = contents_path
|
||||
self.restore_path = restore_path
|
||||
self.domain = domain
|
||||
self.owner = owner
|
||||
@@ -75,7 +76,8 @@ def concat_regular_file(file: FileToRestore, files_list: list[FileToRestore], la
|
||||
file.domain,
|
||||
owner=file.owner,
|
||||
group=file.group,
|
||||
contents=file.contents
|
||||
contents=file.contents,
|
||||
src_path=file.contents_path
|
||||
))
|
||||
return new_last_domain, full_path
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import traceback
|
||||
import plistlib
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
from PySide6.QtWidgets import QMessageBox
|
||||
from PySide6.QtCore import QSettings
|
||||
@@ -304,6 +304,7 @@ class DeviceManager:
|
||||
# create the restore file list
|
||||
files_to_restore: dict[FileToRestore] = [
|
||||
]
|
||||
tmp_pb_dir = None # temporary directory for unzipping pb files
|
||||
|
||||
# set the plist keys
|
||||
if not resetting:
|
||||
@@ -325,7 +326,8 @@ class DeviceManager:
|
||||
if tweak.enabled and tweak.file_location.value.startswith("/var/mobile/"):
|
||||
uses_domains = True
|
||||
elif isinstance(tweak, PosterboardTweak):
|
||||
tweak.apply_tweak(files_to_restore=files_to_restore)
|
||||
tmp_pb_dir = TemporaryDirectory()
|
||||
tweak.apply_tweak(files_to_restore=files_to_restore, output_dir=tmp_pb_dir.name)
|
||||
else:
|
||||
if gestalt_plist != None:
|
||||
gestalt_plist = tweak.apply_tweak(gestalt_plist)
|
||||
@@ -413,12 +415,16 @@ class DeviceManager:
|
||||
update_label("Restoring to device...")
|
||||
try:
|
||||
restore_files(files=files_to_restore, reboot=self.auto_reboot, lockdown_client=self.data_singleton.current_device.ld)
|
||||
if tmp_pb_dir != None:
|
||||
tmp_pb_dir.cleanup()
|
||||
msg = "Your device will now restart."
|
||||
if not self.auto_reboot:
|
||||
msg = "Please restart your device to see changes."
|
||||
QMessageBox.information(None, "Success!", "All done! " + msg)
|
||||
update_label("Success!")
|
||||
except Exception as e:
|
||||
if tmp_pb_dir != None:
|
||||
tmp_pb_dir.cleanup()
|
||||
show_apply_error(e, update_label)
|
||||
|
||||
## RESETTING MOBILE GESTALT
|
||||
|
||||
@@ -19,7 +19,7 @@ from tweaks.custom_gestalt_tweaks import CustomGestaltTweaks, ValueTypeStrings
|
||||
from tweaks.daemons_tweak import Daemon
|
||||
|
||||
App_Version = "5.0"
|
||||
App_Build = 1
|
||||
App_Build = 2
|
||||
|
||||
class Page(Enum):
|
||||
Home = 0
|
||||
|
||||
@@ -2,7 +2,6 @@ from .tweak_classes import Tweak
|
||||
from Sparserestore.restore import FileToRestore
|
||||
import os
|
||||
import zipfile
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
class PosterboardTweak(Tweak):
|
||||
def __init__(self):
|
||||
@@ -13,19 +12,18 @@ class PosterboardTweak(Tweak):
|
||||
|
||||
def recursive_add(self, files_to_restore: list[FileToRestore], curr_path: str, restore_path: str = "", isAdding: bool = False):
|
||||
for folder in sorted(os.listdir(curr_path)):
|
||||
if folder == ".DS_Store" or folder == "__MACOSX":
|
||||
if folder.startswith('.') or folder == "__MACOSX":
|
||||
continue
|
||||
if isAdding:
|
||||
# if file then add it, otherwise recursively call again
|
||||
if os.path.isfile(os.path.join(curr_path, folder)):
|
||||
try:
|
||||
with open(os.path.join(curr_path, folder), "rb") as in_file:
|
||||
contents = in_file.read()
|
||||
files_to_restore.append(FileToRestore(
|
||||
contents=contents,
|
||||
restore_path=f"{restore_path}/{folder}",
|
||||
domain=f"AppDomain-{self.bundle_id}"
|
||||
))
|
||||
files_to_restore.append(FileToRestore(
|
||||
contents=None,
|
||||
contents_path=os.path.join(curr_path, folder),
|
||||
restore_path=f"{restore_path}/{folder}",
|
||||
domain=f"AppDomain-{self.bundle_id}"
|
||||
))
|
||||
except IOError:
|
||||
print(f"Failed to open file: {folder}") # TODO: Add QDebug equivalent
|
||||
else:
|
||||
@@ -38,7 +36,7 @@ class PosterboardTweak(Tweak):
|
||||
else:
|
||||
self.recursive_add(files_to_restore, os.path.join(curr_path, folder), isAdding=False)
|
||||
|
||||
def apply_tweak(self, files_to_restore: list[FileToRestore]):
|
||||
def apply_tweak(self, files_to_restore: list[FileToRestore], output_dir: str):
|
||||
# unzip the file
|
||||
if not self.enabled:
|
||||
return
|
||||
@@ -52,8 +50,7 @@ class PosterboardTweak(Tweak):
|
||||
return
|
||||
elif self.zip_path == None:
|
||||
return
|
||||
with TemporaryDirectory() as output_dir:
|
||||
with zipfile.ZipFile(self.zip_path, 'r') as zip_ref:
|
||||
zip_ref.extractall(output_dir)
|
||||
# add the files
|
||||
self.recursive_add(files_to_restore, curr_path=output_dir)
|
||||
with zipfile.ZipFile(self.zip_path, 'r') as zip_ref:
|
||||
zip_ref.extractall(output_dir)
|
||||
# add the files
|
||||
self.recursive_add(files_to_restore, curr_path=output_dir)
|
||||
Reference in New Issue
Block a user