mirror of
https://github.com/FEX-Emu/FEX.git
synced 2024-12-12 16:46:23 +00:00
121f0a2c6c
Permissions mean we need to delete the folder before extracting. On error make sure to delete the image file as well to ensure it reruns everything.
193 lines
5.7 KiB
Python
Executable File
193 lines
5.7 KiB
Python
Executable File
#!/usr/bin/python3
|
|
import xxhash
|
|
import hashlib
|
|
import sys
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
|
|
def GetDistroInfo():
|
|
DistroName = "Unknown"
|
|
DistroVersion = "Unknown"
|
|
|
|
with open("/etc/lsb-release", 'r') as f:
|
|
while True:
|
|
Line = f.readline()
|
|
if not Line:
|
|
break
|
|
Split = Line.split("=")
|
|
if Split[0] == "DISTRIB_ID":
|
|
DistroName = Split[1].lower().rstrip()
|
|
if Split[0] == "DISTRIB_RELEASE":
|
|
DistroVersion = Split[1].rstrip()
|
|
|
|
return [DistroName, DistroVersion]
|
|
|
|
def FindBestImageFit(Distro, links_file):
|
|
CurrentFitSize = 0
|
|
BestFitDistro = None
|
|
BestFitDistroVersion = None
|
|
BestFitReadableName = None
|
|
BestFitImagePath = None
|
|
BestFitHash = None
|
|
|
|
with open(links_file, 'r') as f:
|
|
while True:
|
|
# Order:
|
|
# Distro Name
|
|
# Distro Version
|
|
# User readable name
|
|
# File Path
|
|
# Hash
|
|
|
|
DistroName = f.readline().strip()
|
|
if not DistroName:
|
|
break
|
|
|
|
DistroVersion = f.readline().strip()
|
|
DistroReadableName = f.readline().strip()
|
|
DistroImagePath = f.readline().strip()
|
|
DistroHash = f.readline().strip()
|
|
|
|
FitRate = 0
|
|
if (DistroName == Distro[0] or
|
|
DistroName == None):
|
|
FitRate += 1
|
|
|
|
if (DistroVersion == Distro[1] or
|
|
DistroVersion == None):
|
|
FitRate += 1
|
|
|
|
if FitRate > CurrentFitSize:
|
|
CurrentFitSize = FitRate
|
|
BestFitDistro = DistroName
|
|
BestFitDistroVersion = DistroVersion
|
|
BestFitReadableName = DistroReadableName
|
|
BestFitImagePath = DistroImagePath
|
|
BestFitHash = DistroHash
|
|
|
|
return [BestFitDistro, BestFitDistroVersion, BestFitReadableName, BestFitImagePath, int(BestFitHash, 16)]
|
|
|
|
|
|
def HashFile(file):
|
|
# 32MB buffer size
|
|
BUFFER_SIZE = 32 * 1024 * 1024
|
|
|
|
x = xxhash.xxh3_64(seed=0)
|
|
b = bytearray(BUFFER_SIZE)
|
|
mv = memoryview(b)
|
|
|
|
with open(file, 'rb') as f:
|
|
while n := f.readinto(mv):
|
|
x.update(mv[:n])
|
|
|
|
return int.from_bytes(x.digest(), "big")
|
|
|
|
def RemoveRootFSFolder(RootFSPath):
|
|
print("Removing previous rootfs extraction before copying")
|
|
shutil.rmtree(RootFSPath, ignore_errors = True)
|
|
# Recreate the folder
|
|
os.makedirs(RootFSPath)
|
|
|
|
def CheckFilesystemForFS(RootFSMountPath, RootFSPath, DistroFit):
|
|
# Check if rootfs mount path exists
|
|
if (not os.path.exists(RootFSMountPath) or
|
|
not os.path.isdir(RootFSMountPath)):
|
|
print("RootFS mount path is wrong")
|
|
return False
|
|
|
|
# Check if rootfs path exists
|
|
if (not os.path.exists(RootFSPath) or
|
|
not os.path.isdir(RootFSPath)):
|
|
# Create this directory
|
|
os.makedirs(RootFSPath)
|
|
|
|
# Check if rootfs path exists
|
|
if not os.path.isdir(RootFSPath):
|
|
print("RootFS path is not a directory")
|
|
return False
|
|
|
|
# Check rootfs folder for image, copy and extract as necessary
|
|
MountRootFSImagePath = RootFSMountPath + DistroFit[3]
|
|
RootFSImagePath = RootFSPath + "/" + os.path.basename(DistroFit[3])
|
|
NeedsExtraction = False
|
|
PreviouslyExistingRootFS = False
|
|
|
|
if not os.path.exists(MountRootFSImagePath):
|
|
print("Image {} doesn't exist".format(MountRootFSImagePath))
|
|
return False
|
|
|
|
if not os.path.exists(RootFSImagePath):
|
|
# Copy over
|
|
print("RootFS image doesn't exist. Copying")
|
|
RemoveRootFSFolder(RootFSPath)
|
|
shutil.copyfile(MountRootFSImagePath, RootFSImagePath)
|
|
NeedsExtraction = True
|
|
|
|
# Check if the image needs to be extracted
|
|
if not os.path.exists(RootFSPath + "/usr"):
|
|
NeedsExtraction = True
|
|
else:
|
|
PreviouslyExistingRootFS = True
|
|
|
|
# Now hash the image
|
|
RootFSHash = HashFile(RootFSImagePath)
|
|
if RootFSHash != DistroFit[4]:
|
|
print("Hash {} did not match {}, copying new image".format(hex(RootFSHash), hex(DistroFit[4])))
|
|
|
|
if PreviouslyExistingRootFS:
|
|
RemoveRootFSFolder(RootFSPath)
|
|
|
|
shutil.copyfile(MountRootFSImagePath, RootFSImagePath)
|
|
NeedsExtraction = True
|
|
|
|
if NeedsExtraction:
|
|
print("Extracting rootfs")
|
|
|
|
CmdResult = subprocess.call(["unsquashfs", "-f", "-d", RootFSPath, RootFSImagePath])
|
|
if CmdResult != 0:
|
|
print("Couldn't extract squashfs. Removing image file to be safe")
|
|
os.remove(RootFSImagePath)
|
|
return False
|
|
|
|
if not os.path.exists(RootFSPath + "/usr"):
|
|
print("Couldn't extract squashfs. Removing image file to be safe")
|
|
os.remove(RootFSImagePath)
|
|
return False
|
|
|
|
print("RootFS successfully checked and extracted")
|
|
|
|
return True
|
|
|
|
def main():
|
|
if sys.version_info[0] < 3:
|
|
logging.critical ("Python 3 or a more recent version is required.")
|
|
|
|
FEX_ROOTFS_MOUNT = os.getenv("FEX_ROOTFS_MOUNT")
|
|
FEX_ROOTFS_PATH = os.getenv("FEX_ROOTFS_PATH")
|
|
|
|
if FEX_ROOTFS_MOUNT == None:
|
|
print("Need FEX_ROOTFS_MOUNT set")
|
|
sys.exit(1)
|
|
|
|
if FEX_ROOTFS_PATH == None:
|
|
print("Need FEX_ROOTFS_PATH set")
|
|
sys.exit(1)
|
|
|
|
if shutil.which("unsquashfs") is None:
|
|
print("CI system didn't have unsquashfs installed")
|
|
sys.exit(1)
|
|
|
|
Distro = GetDistroInfo()
|
|
DistroFit = FindBestImageFit(Distro, FEX_ROOTFS_MOUNT + "/RootFS_links.txt")
|
|
|
|
if CheckFilesystemForFS(FEX_ROOTFS_MOUNT, FEX_ROOTFS_PATH, DistroFit) == False:
|
|
print("Couldn't load filesystem rootfs")
|
|
sys.exit(1)
|
|
|
|
return 0
|
|
|
|
if __name__ == "__main__":
|
|
# execute only if run as a script
|
|
sys.exit(main())
|