SolarisPackageDirBundle.py revision 1765
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#!/usr/bin/python
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# CDDL HEADER START
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# The contents of this file are subject to the terms of the
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# Common Development and Distribution License (the "License").
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# You may not use this file except in compliance with the License.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# or http://www.opensolaris.org/os/licensing.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# See the License for the specific language governing permissions
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen# and limitations under the License.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen# When distributing Covered Code, include this CDDL HEADER in each
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen# If applicable, add the following below this CDDL HEADER, with the
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen# fields enclosed by brackets "[]" replaced with your own identifying
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen# information: Portions Copyright [yyyy] [name of copyright owner]
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen#
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen# CDDL HEADER END
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen#
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen#
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen# Use is subject to license terms.
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen#
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainenimport os
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainenimport pkg.misc as misc
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainenfrom pkg.sysvpkg import SolarisPackage
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainenfrom pkg.cpiofile import CpioFile
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenfrom pkg.actions import *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenclass SolarisPackageDirBundle(object):
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen def __init__(self, filename, data=True):
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen self.pkg = SolarisPackage(filename)
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen self.pkgname = self.pkg.pkginfo["PKG"]
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen self.filename = filename
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen self.data = data
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen def __iter__(self):
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen faspac = []
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen if "faspac" in self.pkg.pkginfo:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen faspac = self.pkg.pkginfo["faspac"]
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen # Want to access the manifest as a dict.
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen pkgmap = {}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen for p in self.pkg.manifest:
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen pkgmap[p.pathname] = p
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if not self.data:
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen for p in self.pkg.manifest:
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen act = self.action(p, None)
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen if act:
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen yield act
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen def j(path):
f7d43647acc6dc80064c8c4cacf5bf86f754c530Timo Sirainen return os.path.join(self.pkg.basedir, path)
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen faspac_contents = set()
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen for klass in faspac:
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen fpath = os.path.join(self.filename, "archive", klass)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen # We accept either bz2 or 7zip'd files
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen for x in [".bz2", ".7z"]:
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen if os.path.exists(fpath + x):
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen cf = CpioFile.open(fpath + x)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen break
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen for ci in cf:
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen faspac_contents.add(j(ci.name))
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen act = self.action(pkgmap[j(ci.name)],
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen ci.extractfile())
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen if act:
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen yield act
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen # Remove BASEDIR from the path. The extra work is because if
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen # BASEDIR is not empty (non-"/"), then we probably need to strip
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen # an extra slash from the beginning of the path, but if BASEDIR
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen # is "" ("/" in the pkginfo file), then we don't need to do
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen # anything extra.
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen def r(path, type):
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if type == "i":
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen return path
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen p = path[len(self.pkg.basedir):]
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if p[0] == "/":
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen p = p[1:]
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return p
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen for p in self.pkg.manifest:
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen # Just do the files that remain. Only regular file
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen # types end up compressed; so skip them and only them.
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen # Files with special characters in their names may not
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen # end up in the faspac archive, so we still need to emit
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen # the ones that aren't.
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if p.type in "fev" and p.klass in faspac and \
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen p.pathname in faspac_contents:
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen continue
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen # These are the only valid file types in SysV packages
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen if p.type in "fevbcdxpls":
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen act = self.action(p, os.path.join(self.filename,
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen "reloc", r(p.pathname, p.type)))
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if act:
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen yield act
6288d3611eda14a017dae9927b73f46afb646c96Timo Sirainen elif p.type == "i":
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen a = self.action(p, os.path.join(self.filename,
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen "install", r(p.pathname, p.type)))
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if a:
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen yield a
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen def action(self, mapline, data):
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen preserve_dict = {
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen "renameold": "renameold",
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen "renamenew": "renamenew",
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen "preserve": "true",
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen "svmpreserve": "true"
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen }
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen # If any one of the mode, owner, or group is "?", then we're
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen # clearly not capable of delivering the object correctly, so
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen # ignore it.
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if mapline.type in "fevdx" and (mapline.mode == "?" or
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mapline.owner == "?" or mapline.group == "?"):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return None
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if mapline.type in "f":
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen a = file.FileAction(data, mode=mapline.mode,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen owner=mapline.owner, group=mapline.group,
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen path=mapline.pathname,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen timestamp=misc.time_to_timestamp(int(mapline.modtime)))
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if mapline.klass in preserve_dict:
2e937ed8585299b2e879a28314902a5f644813d2Timo Sirainen a.attrs["preserve"] = preserve_dict[mapline.klass]
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen return a
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen elif mapline.type in "ev":
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen # for editable files, map klass onto IPS names; if match
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen # fails, make sure we at least preserve file
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen preserve=preserve_dict.get(mapline.klass, "true")
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen return file.FileAction(data, mode=mapline.mode,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen owner=mapline.owner, group=mapline.group,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen path=mapline.pathname, preserve=preserve,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen timestamp=misc.time_to_timestamp(int(mapline.modtime)))
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen elif mapline.type in "dx":
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen return directory.DirectoryAction(mode=mapline.mode,
c3412ddeb9abc13f99d3caf50faf76cd99f7e9d2Timo Sirainen owner=mapline.owner, group=mapline.group,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen path=mapline.pathname)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen elif mapline.type == "s":
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen return link.LinkAction(path=mapline.pathname,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen target=mapline.target)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen elif mapline.type == "l":
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen return hardlink.HardLinkAction(path=mapline.pathname,
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen target=mapline.target)
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen elif mapline.type == "i" and mapline.pathname == "copyright":
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return license.LicenseAction(data,
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen license="%s.copyright" % self.pkgname,
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen path=mapline.pathname)
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen elif mapline.type == "i":
e8a35266a5ceacdfafeeffd6bddae77931ff97ebTimo Sirainen return None
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen else:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return unknown.UnknownAction(path=mapline.pathname)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainendef test(filename):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if os.path.isfile(os.path.join(filename, "pkginfo")) and \
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen os.path.isfile(os.path.join(filename, "pkgmap")):
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return True
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen return False
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen