def process_elf_dependencies(action, pkg_vars, dyn_tok_conv, kernel_paths, **kwargs): """Produce the elf dependencies for the file delivered in the action provided. 'action' is the file action to analyze. 'pkg_vars' is the list of variants against which the package delivering the action was published. 'dyn_tok_conv' is the dictionary which maps the dynamic tokens, like $PLATFORM, to the values they should be expanded to. 'kernel_paths' contains the run paths which kernel modules should use. """ if not action.name == "file": return [], [], {} installed_path = action.attrs[action.key_attr] proto_file = action.attrs[PD_LOCAL_PATH] if not os.path.exists(proto_file): raise base.MissingFile(proto_file) if not elf.is_elf_object(proto_file): return [], [], {} try: ei = elf.get_info(proto_file) ed = elf.get_dynamic(proto_file) except elf.ElfError, e: raise BadElfFile(proto_file, e)
def process_script_deps(action, proto_dir, pkg_vars, **kwargs): """Given an action and a place to find the file it references, if the file starts with #! a list containing a ScriptDependency is returned. Further, if the file is of a known type, it is further analyzed and any dependencies found are added to the list returned.""" # localpath is path to actual file # path is path in installed image if action.name != "file": return [] path = action.attrs[action.key_attr] localpath = os.path.join(proto_dir, path) try: f = open(localpath, "rb") except EnvironmentError: raise base.MissingFile(localpath) l = f.readline() f.close() # add #! dependency if l.startswith("#!"): # usedlist omits leading / p = (l[2:].split()[0]) # first part of string is path (removes # options) # we don't handle dependencies through links, so fix up the # common one p = p.strip() if p.startswith("/bin"): p = os.path.join("/usr", p) deps = [ScriptDependency(action, p, pkg_vars, proto_dir)] elist = [] if "python" in l: ds, errs = python.process_python_dependencies(localpath, proto_dir, action, pkg_vars) elist.extend(errs) deps.extend(ds) return deps, elist return [], []
def __make_manifest(fp, basedirs=None, load_data=True): """Given the file path, 'fp', return a Manifest for that path.""" m = manifest.Manifest() fh = open(fp, "rb") acts = [] missing_files = [] accumulate = "" for l in fh: l = l.strip() if l.endswith("\\"): accumulate += l[0:-1] continue elif accumulate: l = accumulate + l accumulate = "" if not l or l[0] == '#': continue try: a, local_path, used_bd = actions.internalizestr(l, basedirs=basedirs, load_data=load_data) if local_path: assert portable.PD_LOCAL_PATH not in a.attrs a.attrs[portable.PD_LOCAL_PATH] = local_path a.attrs[portable.PD_PROTO_DIR] = used_bd a.attrs[portable.PD_PROTO_DIR_LIST] = basedirs acts.append(a) except actions.ActionDataError, e: new_a, local_path, used_bd = actions.internalizestr( l, basedirs=basedirs, load_data=False) if new_a.name == "license": acts.append(new_a) else: path = e.path # If the path was not set, then parse the # action, without trying to load the data and # use the path defined in the action. if not path: path = new_a.attrs["path"] missing_files.append(base.MissingFile(path))
def process_elf_dependencies(action, proto_dir, pkg_vars, **kwargs): """Given a file action and proto directory, produce the elf dependencies for that file.""" if not action.name == "file": return [] installed_path = action.attrs[action.key_attr] proto_file = os.path.join(proto_dir, installed_path) if not os.path.exists(proto_file): raise base.MissingFile(proto_file) if not elf.is_elf_object(proto_file): return [] try: ei = elf.get_info(proto_file) ed = elf.get_dynamic(proto_file) except elf.ElfError, e: raise BadElfFile(proto_file, e)
def process_elf_dependencies(action, pkg_vars, dyn_tok_conv, run_paths, **kwargs): """Produce the elf dependencies for the file delivered in the action provided. 'action' is the file action to analyze. 'pkg_vars' is the list of variants against which the package delivering the action was published. 'dyn_tok_conv' is the dictionary which maps the dynamic tokens, like $PLATFORM, to the values they should be expanded to. 'run_paths' contains the run paths which elf binaries should use. """ if not action.name == "file": return [], [], {} installed_path = action.attrs[action.key_attr] proto_file = action.attrs[PD_LOCAL_PATH] if not os.path.exists(proto_file): raise base.MissingFile(proto_file) if not elf.is_elf_object(proto_file): return [], [], {} try: ei = elf.get_info(proto_file) ed = elf.get_dynamic(proto_file) except elf.ElfError as e: raise BadElfFile(proto_file, e) deps = [ d[0] for d in ed.get("deps", []) ] rp = ed.get("runpath", "").split(":") if len(rp) == 1 and rp[0] == "": rp = [] dyn_tok_conv["$ORIGIN"] = [os.path.join("/", os.path.dirname(installed_path))] kernel64 = None # For kernel modules, default path resolution is /platform/<platform>, # /kernel, /usr/kernel. But how do we know what <platform> would be for # a given module? Does it do fallbacks to, say, sun4u? if installed_path.startswith("kernel") or \ installed_path.startswith("usr/kernel") or \ (installed_path.startswith("platform") and \ installed_path.split("/")[2] == "kernel"): if rp and (len(rp) > 1 or not re.match(r'^/usr/gcc/\d/lib$', rp[0])): raise RuntimeError("RUNPATH set for kernel module " "({0}): {1}".format(installed_path, rp)) # Add this platform to the search path. if installed_path.startswith("platform"): rp.append("/platform/{0}/kernel".format( installed_path.split("/")[1])) else: for p in dyn_tok_conv.get("$PLATFORM", []): rp.append("/platform/{0}/kernel".format(p)) # Default kernel search path rp.extend(["/kernel", "/usr/kernel"]) # What subdirectory should we look in for 64-bit kernel modules? if ei["bits"] == 64: if ei["arch"] == "i386": kernel64 = "amd64" elif ei["arch"] == "sparc": kernel64 = "sparcv9" else: raise RuntimeError("Unknown arch:{0}".format( ei["arch"])) else: for p in default_run_paths: if ei["bits"] == 64: p += "/64" if p not in rp: rp.append(p) elist = [] if run_paths: # add our detected runpaths into the user-supplied one (if any) rp = base.insert_default_runpath(rp, run_paths) rp, errs = expand_variables(rp, dyn_tok_conv) elist.extend([ UnsupportedDynamicToken(proto_file, installed_path, p, tok) for p, tok in errs ]) res = [] for d in deps: pn, fn = os.path.split(d) pathlist = [] for p in rp: if kernel64: # Find 64-bit modules the way krtld does. # XXX We don't resolve dependencies found in # /platform, since we don't know where under # /platform to look. deppath = \ os.path.join(p, pn, kernel64, fn).lstrip( os.path.sep) else: deppath = os.path.join(p, d).lstrip(os.path.sep) # deppath includes filename; remove that. head, tail = os.path.split(deppath) if head: pathlist.append(head) res.append(ElfDependency(action, fn, pathlist, pkg_vars, action.attrs[PD_PROTO_DIR])) del dyn_tok_conv["$ORIGIN"] return res, elist, {}
def no_such_file(action, **kwargs): """Function to handle dispatch of files not found on the system.""" return [], [base.MissingFile(action.attrs["path"])], {}