directory.py revision 1281
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#!/usr/bin/python2.4
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen# CDDL HEADER START
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen# The contents of this file are subject to the terms of the
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen# Common Development and Distribution License (the "License").
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen# You may not use this file except in compliance with the License.
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen# or http://www.opensolaris.org/os/licensing.
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen# See the License for the specific language governing permissions
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen# and limitations under the License.
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen# When distributing Covered Code, include this CDDL HEADER in each
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen# If applicable, add the following below this CDDL HEADER, with the
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen# fields enclosed by brackets "[]" replaced with your own identifying
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen# information: Portions Copyright [yyyy] [name of copyright owner]
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen# CDDL HEADER END
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen#
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen# Use is subject to license terms.
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen#
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen"""module describing a directory packaging object
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo SirainenThis module contains the DirectoryAction class, which represents a
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainendirectory-type packaging object."""
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenimport os
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenimport errno
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenimport stat
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenimport generic
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenimport pkg.portable as portable
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenimport pkg.actions
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainenclass DirectoryAction(generic.Action):
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen """Class representing a directory-type packaging object."""
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen name = "dir"
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen attributes = ("mode", "owner", "group", "path")
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen key_attr = "path"
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen def __init__(self, data=None, **attrs):
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen generic.Action.__init__(self, data, **attrs)
e7ca5f820d6a1a8fe549a2966ac707a60e055ef4Timo Sirainen if "path" in self.attrs:
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen self.attrs["path"] = self.attrs["path"].lstrip(
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen os.path.sep)
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if not self.attrs["path"]:
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen raise pkg.actions.InvalidActionError(
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen str(self), _("Empty path attribute"))
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen def compare(self, other):
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen return cmp(self.attrs["path"], other.attrs["path"])
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen def directory_references(self):
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen return [os.path.normpath(self.attrs["path"])]
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen def install(self, pkgplan, orig):
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen """Client-side method that installs a directory."""
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen path = self.attrs["path"]
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen mode = int(self.attrs["mode"], 8)
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen owner = pkgplan.image.get_user_by_name(self.attrs["owner"])
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen group = pkgplan.image.get_group_by_name(self.attrs["group"])
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen if orig:
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen omode = int(orig.attrs["mode"], 8)
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen oowner = pkgplan.image.get_user_by_name(
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen orig.attrs["owner"])
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen ogroup = pkgplan.image.get_group_by_name(
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen orig.attrs["group"])
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen path = os.path.normpath(os.path.sep.join(
f428ea9564d72894c18b8f3876bfaaf677ce19aaTimo Sirainen (pkgplan.image.get_root(), path)))
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen # XXX Hack! (See below comment.)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if not portable.is_admin():
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen mode |= 0200
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if not orig:
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen try:
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen self.makedirs(path, mode = mode)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen except OSError, e:
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if e.errno != errno.EEXIST:
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen raise
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen # The downside of chmodding the directory is that as a non-root
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen # user, if we set perms u-w, we won't be able to put anything in
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen # it, which is often not what we want at install time. We save
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen # the chmods for the postinstall phase, but it's always possible
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen # that a later package install will want to place something in
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen # this directory and then be unable to. So perhaps we need to
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen # (in all action types) chmod the parent directory to u+w on
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen # failure, and chmod it back aftwards. The trick is to
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen # recognize failure due to missing file_dac_write in contrast to
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen # other failures. Or can we require that everyone simply have
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen # file_dac_write who wants to use the tools. Probably not.
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen elif mode != omode:
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen os.chmod(path, mode)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if not orig or oowner != owner or ogroup != group:
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen try:
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen portable.chown(path, owner, group)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen except OSError, e:
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if e.errno != errno.EPERM and \
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen e.errno != errno.ENOSYS:
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen raise
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen def verify(self, img, **args):
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen """ make sure directory is correctly installed"""
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen lstat, errors, abort = \
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen self.verify_fsobj_common(img, stat.S_IFDIR)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return errors
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen def remove(self, pkgplan):
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen localpath = os.path.normpath(self.attrs["path"])
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen path = os.path.normpath(os.path.sep.join(
12ef7b394dfdf4d53d432ac576f6bfcd20ebad6dTimo Sirainen (pkgplan.image.get_root(), localpath)))
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen try:
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen os.rmdir(path)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen except OSError, e:
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen if e.errno == errno.ENOENT:
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen pass
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen elif e.errno == errno.EEXIST or \
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen e.errno == errno.ENOTEMPTY:
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen # cannot remove directory since it's
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen # not empty...
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen pkgplan.image.salvagedir(localpath)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen elif e.errno != errno.EACCES: # this happens on Windows
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen raise
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen def generate_indices(self):
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen """Generates the indices needed by the search dictionary. See
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen generic.py for a more detailed explanation."""
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen return [
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen ("directory", "basename",
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen os.path.basename(self.attrs["path"].rstrip(os.path.sep)),
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen None),
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen ("directory", "path", os.path.sep + self.attrs["path"],
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen None)
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen ]
7fb70daba4e571eab5b64f496d20b9e37e31141bTimo Sirainen