def GenerateModprobeInfo(cls): """Generates the modprobe information.""" Tools.Info("Generating modprobe information ...") # Copy modules.order and modules.builtin just so depmod doesn't spit out warnings. -_- Tools.Into(var.modules + "/modules.order") Tools.Into(var.modules + "/modules.builtin") result = call(["depmod", "-b", var.temp, var.kernel]) if result != 0: Tools.Fail( "Depmod was unable to refresh the dependency information for your initramfs!" )
def CopyDependencies(cls): """Gets the library dependencies for all our binaries and copies them into our initramfs.""" Tools.Info("Copying library dependencies ...") bindeps = set() # Musl and non-musl systems are supported. possible_libc_paths = [ var.lib64 + "/ld-linux-x86-64.so*", var.lib + "/ld-musl-x86_64.so*", ] libc_found = False for libc in possible_libc_paths: try: # (Dirty implementation) Use the exit code of grep with no messages being outputed to see if this interpreter exists. # We don't know the name yet which is why we are using the wildcard in the variable declaration. result = call("grep -Uqs thiswillnevermatch " + libc, shell=True) # 0 = match found # 1 = file exists but not found # 2 = file doesn't exist # In situations 0 or 1, we are good, since we just care that the file exists. if result != 0 and result != 1: continue # Get the interpreter name that is on this system result = check_output( "ls " + libc, shell=True, universal_newlines=True ).strip() # Add intepreter to deps since everything will depend on it bindeps.add(result) libc_found = True except Exception as e: pass if not libc_found: Tools.Fail("No libc interpreters were found!") # Get the dependencies for the binaries we've collected and add them to # our bindeps set. These will all be copied into the initramfs later. for binary in cls._binset: cmd = ( "ldd " + binary + " 2>&1 | grep -v 'not a dynamic executable' | awk -F '=>' '{print $2}' | awk -F ' ' '{print $1}' | sed '/^ *$/d'" ) results = check_output(cmd, shell=True, universal_newlines=True).strip() if results: for library in results.split("\n"): bindeps.add(library) # Copy all the dependencies of the binary files into the initramfs for library in bindeps: Tools.Into(library)
def CopyMan(cls, files): """Safely copies man pages if available. Will not fail.""" # Depending the ZFS version that the user is running, # some manual pages that the initramfs wants to copy might not # have yet been written. Therefore, attempt to copy the man pages, # but if we are unable to copy, then just continue. for f in files: Tools.Into(f, dontFail=True)
def CopyFirmware(cls): """Copies the firmware files/directories if necessary.""" if Firmware.IsEnabled(): Tools.Info("Copying firmware...") if os.path.isdir(var.firmwareDirectory): if Firmware.IsCopyAllEnabled(): Tools.CopyTree( var.firmwareDirectory, var.temp + var.firmwareDirectory ) else: # Copy the firmware files if Firmware.GetFiles(): try: for fw in Firmware.GetFiles(): Tools.Into(fw, directoryPrefix=var.firmwareDirectory) except FileNotFoundError: Tools.Warn( "An error occurred while copying the following firmware file: {}".format( fw ) ) # Copy the firmware directories if Firmware.GetDirectories(): try: for fw in Firmware.GetDirectories(): sourceFirmwareDirectory = os.path.join( var.firmwareDirectory, fw ) targetFirmwareDirectory = ( var.temp + sourceFirmwareDirectory ) Tools.CopyTree( sourceFirmwareDirectory, targetFirmwareDirectory ) except FileNotFoundError: Tools.Warn( "An error occurred while copying the following directory: {}".format( fw ) ) else: Tools.Fail( "The {} directory does not exist".format(var.firmwareDirectory) )
def FilterAndInstall(cls, vFiles, **optionalArgs): """Filters and installs each file in the array into the initramfs. Optional Args: dontFail - Same description as the one in Tools.Copy. """ for file in vFiles: # If the application is a binary, add it to our binary set. If the application is not # a binary, then we will get a CalledProcessError because the output will be null. try: check_output( "file -L " + file.strip() + ' | grep "linked"', shell=True, universal_newlines=True, ).strip() cls._binset.add(file) except CalledProcessError: pass # Copy the file into the initramfs Tools.Into(file, dontFail=optionalArgs.get("dontFail", False))
def CopyModules(cls): """Copy modules and their dependencies.""" moddeps = set() # Build the list of module dependencies Tools.Info("Copying modules ...") # Checks to see if all the modules in the list exist (if any) for file in Modules.GetFiles(): Tools.Flag("Module: {}".format(file)) try: cmd = ( "find " + var.modules + ' -iname "' + file + '.ko*" | grep ' + file + ".ko" ) result = check_output(cmd, universal_newlines=True, shell=True).strip() cls._modset.add(result) except CalledProcessError: Tools.ModuleDoesntExist(file) # Try to update the module dependencies database before searching it try: result = call(["depmod", var.kernel]) if result: Tools.Fail("Error updating module dependency database!") except FileNotFoundError: # This should never occur because the application checks # that root is the user that is running the application. # Non-administraative users normally don't have access # to the 'depmod' command. Tools.Fail("The 'depmod' command wasn't found.") # Get the dependencies for all the modules in our set for file in cls._modset: # Get only the name of the module match = re.search("(?<=/)[a-zA-Z0-9_-]+.ko", file) if match: sFile = match.group().split(".")[0] cmd = ( "modprobe -S " + var.kernel + " --show-depends " + sFile + " | awk -F ' ' '{print $2}'" ) results = check_output(cmd, shell=True, universal_newlines=True).strip() for i in results.split("\n"): moddeps.add(i.strip()) # Copy the modules/dependencies if not moddeps: return for module in moddeps: Tools.Into(module) # Update module dependency database inside the initramfs cls.GenerateModprobeInfo()