--- a/src/Makefile Mon Oct 08 13:18:41 2007 -0700
+++ b/src/Makefile Mon Oct 08 13:36:55 2007 -0700
@@ -96,6 +96,7 @@
modules/actions/file.py \
modules/actions/generic.py \
modules/actions/hardlink.py \
+ modules/actions/license.py \
modules/actions/link.py \
modules/actions/unknown.py
PYCACTIONMODS = $(PYACTIONMODS:%.py=%.pyc)
--- a/src/modules/actions/directory.py Mon Oct 08 13:18:41 2007 -0700
+++ b/src/modules/actions/directory.py Mon Oct 08 13:36:55 2007 -0700
@@ -47,7 +47,7 @@
def __init__(self, data=None, **attrs):
generic.Action.__init__(self, data, **attrs)
- def install(self, image, orig):
+ def install(self, pkgplan, orig):
"""Client-side method that installs a directory."""
path = self.attrs["path"]
mode = int(self.attrs["mode"], 8)
@@ -60,14 +60,14 @@
ogroup = grp.getgrnam(orig.attrs["group"]).gr_gid
path = os.path.normpath(os.path.sep.join(
- (image.get_root(), path)))
+ (pkgplan.image.get_root(), path)))
# XXX Hack! (See below comment.)
mode |= 0200
if not orig:
try:
- self.makedirs(path, mode)
+ self.makedirs(path, mode = mode)
except OSError, e:
if e.errno != errno.EEXIST:
raise
@@ -93,9 +93,9 @@
if e.errno != errno.EPERM:
raise
- def remove(self, image):
+ def remove(self, pkgplan):
path = os.path.normpath(os.path.sep.join(
- (image.get_root(), self.attrs["path"])))
+ (pkgplan.image.get_root(), self.attrs["path"])))
try:
os.rmdir(path)
--- a/src/modules/actions/driver.py Mon Oct 08 13:18:41 2007 -0700
+++ b/src/modules/actions/driver.py Mon Oct 08 13:36:55 2007 -0700
@@ -60,7 +60,8 @@
def __init__(self, data=None, **attrs):
generic.Action.__init__(self, data, **attrs)
- def install(self, image, orig):
+ def install(self, pkgplan, orig):
+ image = pkgplan.image
n2m = os.path.normpath(os.path.sep.join(
(image.get_root(), "etc/name_to_major")))
@@ -191,11 +192,11 @@
"return code %s" % \
(self.name, self.attrs["name"], retcode)
- def remove(self, image):
+ def remove(self, pkgplan):
args = (
self.rem_drv,
"-b",
- image.get_root(),
+ pkgplan.image.get_root(),
self.attrs["name"]
)
--- a/src/modules/actions/file.py Mon Oct 08 13:18:41 2007 -0700
+++ b/src/modules/actions/file.py Mon Oct 08 13:36:55 2007 -0700
@@ -49,7 +49,7 @@
generic.Action.__init__(self, data, **attrs)
self.hash = "NOHASH"
- def install(self, image, orig):
+ def install(self, pkgplan, orig):
"""Client-side method that installs a file."""
path = self.attrs["path"]
mode = int(self.attrs["mode"], 8)
@@ -57,7 +57,7 @@
group = grp.getgrnam(self.attrs["group"]).gr_gid
final_path = os.path.normpath(os.path.sep.join(
- (image.get_root(), path)))
+ (pkgplan.image.get_root(), path)))
# If we're upgrading, extract the attributes from the old file.
if orig:
@@ -94,7 +94,7 @@
# XXX This needs to be controlled by policy.
if self.needsdata(orig):
temp = os.path.normpath(os.path.sep.join(
- (image.get_root(), path + "." + self.hash)))
+ (pkgplan.image.get_root(), path + "." + self.hash)))
stream = self.data()
tfile = file(temp, "wb")
@@ -138,9 +138,9 @@
return False
- def remove(self, image):
+ def remove(self, pkgplan):
path = os.path.normpath(os.path.sep.join(
- (image.get_root(), self.attrs["path"])))
+ (pkgplan.image.get_root(), self.attrs["path"])))
os.unlink(path)
--- a/src/modules/actions/generic.py Mon Oct 08 13:18:41 2007 -0700
+++ b/src/modules/actions/generic.py Mon Oct 08 13:36:55 2007 -0700
@@ -273,14 +273,16 @@
return indices
@staticmethod
- def makedirs(path, leafmode):
- """Make directory specified by 'path' with mode 'leafmode', as
- well as all missing parent directories.
+ def makedirs(path, **kw):
+ """Make directory specified by 'path' with given permissions, as
+ well as all missing parent directories. Permissions are
+ specified by the keyword arguments 'mode', 'uid', and 'gid'.
- The difference between this and os.makedirs() is that 'leafmode'
- specifies only the mode of the leaf directory. Missing parent
- directories are created with the permissions of the deepest
- existing directory."""
+ The difference between this and os.makedirs() is that the
+ permissions specify only those of the leaf directory. Missing
+ parent directories inherit the permissions of the deepest
+ existing directory. The leaf directory will also inherit any
+ permissions not explicitly set."""
pathlist = path.split("/")
pathlist[0] = "/"
@@ -289,13 +291,32 @@
for i, e in g:
if not os.path.isdir(os.path.join("/", *pathlist[:i + 1])):
break
+ else:
+ # If we run off the end of the list, the requested
+ # directory is present, so we can just return.
+ return
- # XXX need to set owner/group, too
- mode = os.stat(os.path.join("/", *pathlist[:i])).st_mode
+ stat = os.stat(os.path.join("/", *pathlist[:i]))
for i, e in g:
- os.mkdir(os.path.join("/", *pathlist[:i]), mode)
+ p = os.path.join("/", *pathlist[:i])
+ os.mkdir(p, stat.st_mode)
+ try:
+ os.chown(p, stat.st_uid, stat.st_gid)
+ except OSError, e:
+ if e.errno != errno.EPERM:
+ raise
- os.mkdir(path, leafmode)
+ # Create the leaf with any requested permissions, substituting
+ # missing perms with the parent's perms.
+ mode = kw.get("mode", stat.st_mode)
+ uid = kw.get("uid", stat.st_uid)
+ gid = kw.get("gid", stat.st_gid)
+ os.mkdir(path, mode)
+ try:
+ os.chown(path, uid, gid)
+ except OSError, e:
+ if e.errno != errno.EPERM:
+ raise
def needsdata(self, orig):
"""Returns True if the action transition requires a
@@ -310,26 +331,26 @@
else:
return [ value ]
- def preinstall(self, image, orig):
+ def preinstall(self, pkgplan, orig):
"""Client-side method that performs pre-install actions."""
pass
- def install(self, image, orig):
+ def install(self, pkgplan, orig):
"""Client-side method that installs the object."""
pass
- def postinstall(self, image, orig):
+ def postinstall(self, pkgplan, orig):
"""Client-side method that performs post-install actions."""
pass
- def preremove(self, image):
+ def preremove(self, pkgplan):
"""Client-side method that performs pre-remove actions."""
pass
- def remove(self, image):
+ def remove(self, pkgplan):
"""Client-side method that removes the object."""
pass
- def postremove(self, image):
+ def postremove(self, pkgplan):
"""Client-side method that performs post-remove actions."""
pass
--- a/src/modules/actions/hardlink.py Mon Oct 08 13:18:41 2007 -0700
+++ b/src/modules/actions/hardlink.py Mon Oct 08 13:36:55 2007 -0700
@@ -42,14 +42,14 @@
def __init__(self, data=None, **attrs):
link.LinkAction.__init__(self, data, **attrs)
- def install(self, image, orig):
+ def install(self, pkgplan, orig):
"""Client-side method that installs a hard link."""
path = self.attrs["path"]
target = self.attrs["target"]
path = os.path.normpath(os.path.sep.join(
- (image.get_root(), path)))
+ (pkgplan.image.get_root(), path)))
if os.path.exists(path):
os.unlink(path)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/modules/actions/license.py Mon Oct 08 13:36:55 2007 -0700
@@ -0,0 +1,84 @@
+#!/usr/bin/python
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+"""module describing a license packaging object
+
+This module contains the LicenseAction class, which represents a license
+packaging object. This contains a payload of the license text, and a single
+attribute, 'license', which is the name of the license. Licenses are
+installed on the system in the package's directory."""
+
+import os
+import errno
+import sha
+
+import generic
+
+class LicenseAction(generic.Action):
+ """Class representing a license packaging object."""
+
+ name = "license"
+ key_attr = "license"
+ reverse_indices = ("license", )
+
+ def __init__(self, data=None, **attrs):
+ generic.Action.__init__(self, data, **attrs)
+ self.hash = "NOHASH"
+
+ def install(self, pkgplan, orig):
+ """Client-side method that installs the license."""
+ mode = 0444
+ owner = 0
+ group = 0
+
+ path = os.path.normpath(os.path.join(pkgplan.image.imgdir,
+ "pkg", pkgplan.destination_fmri.get_dir_path(),
+ "license." + self.attrs["license"]))
+
+ stream = self.data()
+ lfile = file(path, "wb")
+ # XXX Should throw an exception if shasum doesn't match
+ # self.hash
+ shasum = generic.gunzip_from_stream(stream, lfile)
+
+ lfile.close()
+ stream.close()
+
+ os.chmod(path, mode)
+
+ try:
+ os.chown(path, owner, group)
+ except OSError, e:
+ if e.errno != errno.EPERM:
+ raise
+
+ def remove(self, pkgplan):
+ path = os.path.normpath(os.path.join(pkgplan.image.imgdir,
+ "pkg", pkgplan.origin_fmri.get_dir_path(),
+ "license." + self.attrs["license"]))
+
+ os.unlink(path)
--- a/src/modules/actions/link.py Mon Oct 08 13:18:41 2007 -0700
+++ b/src/modules/actions/link.py Mon Oct 08 13:36:55 2007 -0700
@@ -44,7 +44,7 @@
def __init__(self, data=None, **attrs):
generic.Action.__init__(self, data, **attrs)
- def install(self, image, orig):
+ def install(self, pkgplan, orig):
"""Client-side method that installs a link."""
# XXX The exists-unlink-symlink path appears to be as safe as it
# gets with the current symlink(2) interface.
@@ -53,15 +53,15 @@
target = self.attrs["target"]
path = os.path.normpath(os.path.sep.join(
- (image.get_root(), path)))
+ (pkgplan.image.get_root(), path)))
if os.path.lexists(path):
os.unlink(path)
os.symlink(target, path)
- def remove(self, image):
+ def remove(self, pkgplan):
path = os.path.normpath(os.path.sep.join(
- (image.get_root(), self.attrs["path"])))
+ (pkgplan.image.get_root(), self.attrs["path"])))
os.unlink(path)
--- a/src/modules/client/pkgplan.py Mon Oct 08 13:18:41 2007 -0700
+++ b/src/modules/client/pkgplan.py Mon Oct 08 13:36:55 2007 -0700
@@ -164,9 +164,9 @@
for src, dest in self.actions:
if dest:
- dest.preinstall(self.image, src)
+ dest.preinstall(self, src)
else:
- src.preremove(self.image)
+ src.preremove(self)
if dest and dest.needsdata(src) and flist_supported:
@@ -212,7 +212,7 @@
for src, dest in self.actions:
if dest:
try:
- dest.install(self.image, src)
+ dest.install(self, src)
except Exception, e:
print "Action install failed for '%s' (%s):\n %s: %s" % \
(dest.attrs.get(dest.key_attr, id(dest)),
@@ -220,7 +220,7 @@
e.__class__.__name__, e)
raise
else:
- src.remove(self.image)
+ src.remove(self)
def postexecute(self):
"""Perform actions required after installation or removal of a package.
@@ -232,9 +232,9 @@
# record that package states are consistent
for src, dest in self.actions:
if dest:
- dest.postinstall(self.image, src)
+ dest.postinstall(self, src)
else:
- src.postremove(self.image)
+ src.postremove(self)
# In the case of an upgrade, remove the installation turds from
# the origin's directory.
--- a/src/publish.py Mon Oct 08 13:18:41 2007 -0700
+++ b/src/publish.py Mon Oct 08 13:36:55 2007 -0700
@@ -165,7 +165,7 @@
print "No transaction ID specified in $PKG_TRANS_ID"
sys.exit(1)
- if args[0] == "file":
+ if args[0] in ("file", "license"):
action = pkg.actions.fromlist(args[0], args[2:])
def opener():
return open(args[1])