def __init__(self, path): """The constructor for the SolarisPackage class. The "path" argument may be a directory -- in which case it is assumed to be a directory-format package -- or a file -- in which case it's tested whether or not it's a datastream package. """ if os.path.isfile(path): f = open(path) if f.readline().strip() == PKG_MAGIC: fo = f else: f.seek(0) try: g = gzip.GzipFile(fileobj=f) if g.readline().rstrip() == PKG_MAGIC: fo = g else: raise IOError, "not a package" except IOError, e: if e.args[0] not in ( "Not a gzipped file", "not a package"): raise else: g.close() raise ValueError, "%s is not a package" % path pkgs = [] while True: line = fo.readline().rstrip() if line == PKG_HDR_END: break pkgs += [ line.split()[0] ] if len(pkgs) > 1: raise MultiPackageDatastreamException( "%s contains %s packages" % \ (path, len(pkgs))) # The cpio archive containing all the packages' pkginfo # and pkgmap files starts on the next 512-byte boundary # after the header, so seek to that point. fo.seek(fo.tell() + 512 - fo.tell() % 512) self.datastream = CpioFile.open(mode="r|", fileobj=fo) # We're going to need to extract and cache the contents # of the pkginfo and pkgmap files because we're not # guaranteed random access to the datastream. At least # they should be reasonably small in size; the largest # delivered in Solaris is a little over 2MB. for ci in self.datastream: if ci.name.endswith("/pkginfo"): self._pkginfo = self.datastream.extractfile(ci).readlines() elif ci.name.endswith("/pkgmap"): self._pkgmap = self.datastream.extractfile(ci).readlines() # XXX Here we allow for only one package. :( self.datastream = self.datastream.get_next_archive()
def __iter__(self): faspac = [] if "faspac" in self.pkg.pkginfo: faspac = self.pkg.pkginfo["faspac"] # Want to access the manifest as a dict. pkgmap = {} for p in self.pkg.manifest: pkgmap[p.pathname] = p if not self.data: for p in self.pkg.manifest: act = self.action(p, None) if act: yield act return def j(path): return os.path.join(self.pkg.basedir, path) faspac_contents = set() for klass in faspac: fpath = os.path.join(self.filename, "archive", klass) # We accept either bz2 or 7zip'd files for x in [".bz2", ".7z"]: if os.path.exists(fpath + x): cf = CpioFile.open(fpath + x) break for ci in cf: faspac_contents.add(j(ci.name)) act = self.action(pkgmap[j(ci.name)], ci.extractfile()) if act: yield act # Remove BASEDIR from the path. The extra work is because if # BASEDIR is not empty (non-"/"), then we probably need to strip # an extra slash from the beginning of the path, but if BASEDIR # is "" ("/" in the pkginfo file), then we don't need to do # anything extra. def r(path, type): if type == "i": return path p = path[len(self.pkg.basedir):] if p[0] == "/": p = p[1:] return p for p in self.pkg.manifest: # Just do the files that remain. Only regular file # types end up compressed; so skip them and only them. # Files with special characters in their names may not # end up in the faspac archive, so we still need to emit # the ones that aren't. if p.type in "fev" and p.klass in faspac and \ p.pathname in faspac_contents: continue # These are the only valid file types in SysV packages if p.type in "fevbcdxpls": act = self.action(p, os.path.join(self.filename, "reloc", r(p.pathname, p.type))) if act: yield act elif p.type == "i": a = self.action(p, os.path.join(self.filename, "install", r(p.pathname, p.type))) if a: yield a
def __init__(self, path): """The constructor for the SolarisPackage class. The "path" argument may be a directory -- in which case it is assumed to be a directory-format package -- or a file -- in which case it's tested whether or not it's a datastream package. """ if os.path.isfile(path): f = open(path) if f.readline().strip() == PKG_MAGIC: fo = f else: f.seek(0) try: g = gzip.GzipFile(fileobj=f) if g.readline().rstrip() == PKG_MAGIC: fo = g else: raise IOError("not a package") except IOError as e: if e.args[0] not in ("Not a gzipped file", "not a package"): raise else: g.close() raise ValueError("{0} is not a package".format(path)) pkgs = [] while True: line = fo.readline().rstrip() if line == PKG_HDR_END: break pkgs += [line.split()[0]] if len(pkgs) > 1: raise MultiPackageDatastreamException( "{0} contains {1} packages".format(path, len(pkgs))) # The cpio archive containing all the packages' pkginfo # and pkgmap files starts on the next 512-byte boundary # after the header, so seek to that point. fo.seek(fo.tell() + 512 - fo.tell() % 512) self.datastream = CpioFile.open(mode="r|", fileobj=fo) # We're going to need to extract and cache the contents # of the pkginfo and pkgmap files because we're not # guaranteed random access to the datastream. At least # they should be reasonably small in size; the largest # delivered in Solaris is a little over 2MB. for ci in self.datastream: if ci.name.endswith("/pkginfo"): self._pkginfo = self.datastream.extractfile(ci).readlines() elif ci.name.endswith("/pkgmap"): self._pkgmap = self.datastream.extractfile(ci).readlines() # XXX Here we allow for only one package. :( self.datastream = self.datastream.get_next_archive() else: self.datastream = None self.pkgpath = path self.pkginfo = self.readPkginfoFile() # Snag BASEDIR, and remove leading and trailing slashes. try: assert self.pkginfo["BASEDIR"][0] == "/" self.basedir = self.pkginfo["BASEDIR"][1:].rstrip("/") except KeyError: self.basedir = "" self.deps = self.readDependFile() self.manifest = self.readPkgmapFile()
def _walk_bundle(self): faspac = [] if "faspac" in self.pkg.pkginfo: faspac = self.pkg.pkginfo["faspac"] # Want to access the manifest as a dict. pkgmap = {} for p in self.pkg.manifest: pkgmap[p.pathname] = p self.class_actions_dir[p.pathname] = p.klass self.class_action_names.add(p.klass) for act in self.pkginfo_actions: yield act.attrs.get("path"), act if not self.data: for p in self.pkg.manifest: act = self.action(p, None) if act: yield act.attrs.get("path"), act return def j(path): return os.path.join(self.pkg.basedir, path) faspac_contents = set() for klass in faspac: fpath = os.path.join(self.filename, "archive", klass) # We accept either bz2 or 7zip'd files for x in [".bz2", ".7z"]: if os.path.exists(fpath + x): cf = CpioFile.open(fpath + x) break for ci in cf: faspac_contents.add(j(ci.name)) act = self.action(pkgmap[j(ci.name)], ci.extractfile()) if act: yield act.attrs.get("path"), act # Remove BASEDIR from a relocatable path. The extra work is # because if BASEDIR is not empty (non-"/"), then we probably # need to strip an extra slash from the beginning of the path, # but if BASEDIR is "" ("/" in the pkginfo file), then we don't # need to do anything extra. def r(path, ptype): if ptype == "i": return path if path[0] == "/": return path[1:] p = path[len(self.pkg.basedir):] if p[0] == "/": p = p[1:] return p for p in self.pkg.manifest: # Just do the files that remain. Only regular file # types end up compressed; so skip them and only them. # Files with special characters in their names may not # end up in the faspac archive, so we still need to emit # the ones that aren't. if p.type in "fev" and p.klass in faspac and \ p.pathname in faspac_contents: continue # These are the only valid file types in SysV packages if p.type in "ifevbcdxpls": if p.type == "i": d = "install" elif p.pathname[0] == "/": d = "root" else: d = "reloc" act = self.action( p, os.path.join(self.filename, d, r(p.pathname, p.type))) if act: if act.name == "license": # This relies on the fact that # license actions have their # hash set to the package path. yield act.hash, act else: yield os.path.join(d, act.attrs.get("path", "")), act
def __init__(self, path): """The constructor for the SolarisPackage class. The "path" argument may be a directory -- in which case it is assumed to be a directory-format package -- or a file -- in which case it's tested whether or not it's a datastream package. """ if os.path.isfile(path): f = open(path) if f.readline().strip() == PKG_MAGIC: fo = f else: f.seek(0) try: g = gzip.GzipFile(fileobj=f) if g.readline().rstrip() == PKG_MAGIC: fo = g else: raise IOError, "not a package" except IOError, e: if e.args[0] not in ("Not a gzipped file", "not a package"): raise else: g.close() raise ValueError, "%s is not a package" % path pkgs = [] while True: line = fo.readline().rstrip() if line == PKG_HDR_END: break pkgs += [line.split()[0]] if len(pkgs) > 1: # XXX probably want a more generic message, but # have the package list in the exception payload # This exception isn't currently raised high in # the stack, so it isn't important yet. raise ValueError, "%s contains %s packages" % \ (path, len(pkgs)) # The cpio archive containing all the packages' pkginfo # and pkgmap files starts on the next 512-byte boundary # after the header, so seek to that point. fo.seek(fo.tell() + 512 - fo.tell() % 512) self.datastream = CpioFile.open(mode="r|", fileobj=fo) # We're going to need to extract and cache the contents # of the pkginfo and pkgmap files because we're not # guaranteed random access to the datastream. At least # they should be reasonably small in size; the largest # delivered in Solaris is a little over 2MB. for ci in self.datastream: if ci.name.endswith("/pkginfo"): self._pkginfo = self.datastream.extractfile(ci).readlines() elif ci.name.endswith("/pkgmap"): self._pkgmap = self.datastream.extractfile(ci).readlines() # XXX Here we allow for only one package. :( self.datastream = self.datastream.get_next_archive()
def _walk_bundle(self): faspac = [] if "faspac" in self.pkg.pkginfo: faspac = self.pkg.pkginfo["faspac"] # Want to access the manifest as a dict. pkgmap = {} for p in self.pkg.manifest: pkgmap[p.pathname] = p self.class_actions_dir[p.pathname] = p.klass self.class_action_names.add(p.klass) for act in self.pkginfo_actions: yield act.attrs.get("path"), act if not self.data: for p in self.pkg.manifest: act = self.action(p, None) if act: yield act.attrs.get("path"), act return def j(path): return os.path.join(self.pkg.basedir, path) faspac_contents = set() for klass in faspac: fpath = os.path.join(self.filename, "archive", klass) # We accept either bz2 or 7zip'd files for x in [".bz2", ".7z"]: if os.path.exists(fpath + x): cf = CpioFile.open(fpath + x) break for ci in cf: faspac_contents.add(j(ci.name)) act = self.action(pkgmap[j(ci.name)], ci.extractfile()) if act: yield act.attrs.get("path"), act # Remove BASEDIR from a relocatable path. The extra work is # because if BASEDIR is not empty (non-"/"), then we probably # need to strip an extra slash from the beginning of the path, # but if BASEDIR is "" ("/" in the pkginfo file), then we don't # need to do anything extra. def r(path, ptype): if ptype == "i": return path if path[0] == "/": return path[1:] p = path[len(self.pkg.basedir):] if p[0] == "/": p = p[1:] return p for p in self.pkg.manifest: # Just do the files that remain. Only regular file # types end up compressed; so skip them and only them. # Files with special characters in their names may not # end up in the faspac archive, so we still need to emit # the ones that aren't. if p.type in "fev" and p.klass in faspac and \ p.pathname in faspac_contents: continue # These are the only valid file types in SysV packages if p.type in "ifevbcdxpls": if p.type == "i": d = "install" elif p.pathname[0] == "/": d = "root" else: d = "reloc" act = self.action(p, os.path.join(self.filename, d, r(p.pathname, p.type))) if act: if act.name == "license": # This relies on the fact that # license actions have their # hash set to the package path. yield act.hash, act else: yield os.path.join(d, act.attrs.get( "path", "")), act
def __iter__(self): faspac = [] if "faspac" in self.pkg.pkginfo: faspac = self.pkg.pkginfo["faspac"] # Want to access the manifest as a dict. pkgmap = {} for p in self.pkg.manifest: pkgmap[p.pathname] = p if not self.data: for p in self.pkg.manifest: yield self.action(p, None) return def j(path): return os.path.join(self.pkg.basedir, path) faspac_contents = set() for klass in faspac: fpath = os.path.join(self.filename, "archive", klass) # We accept either bz2 or 7zip'd files for x in [".bz2", ".7z"]: if os.path.exists(fpath + x): cf = CpioFile.open(fpath + x) break for ci in cf: faspac_contents.add(j(ci.name)) yield self.action(pkgmap[j(ci.name)], ci.extractfile()) # Remove BASEDIR from the path. The extra work is because if # BASEDIR is not empty (non-"/"), then we probably need to strip # an extra slash from the beginning of the path, but if BASEDIR # is "" ("/" in the pkginfo file), then we don't need to do # anything extra. def r(path, type): if type == "i": return path p = path[len(self.pkg.basedir):] if p[0] == "/": p = p[1:] return p for p in self.pkg.manifest: # Just do the files that remain. Only regular file # types end up compressed; so skip them and only them. # Files with special characters in their names may not # end up in the faspac archive, so we still need to emit # the ones that aren't. if p.type in "fev" and p.klass in faspac and \ p.pathname in faspac_contents: continue # These are the only valid file types in SysV packages if p.type in "fevbcdxpls": yield self.action(p, os.path.join(self.filename, "reloc", r(p.pathname, p.type))) elif p.type == "i": yield self.action(p, os.path.join(self.filename, "install", r(p.pathname, p.type)))