directory.py revision 1100
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen#!/usr/bin/python2.4
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger# CDDL HEADER START
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen# The contents of this file are subject to the terms of the
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen# Common Development and Distribution License (the "License").
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen# You may not use this file except in compliance with the License.
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen#
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen# or http://www.opensolaris.org/os/licensing.
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger# See the License for the specific language governing permissions
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen# and limitations under the License.
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen#
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen# When distributing Covered Code, include this CDDL HEADER in each
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen# If applicable, add the following below this CDDL HEADER, with the
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen# fields enclosed by brackets "[]" replaced with your own identifying
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen# information: Portions Copyright [yyyy] [name of copyright owner]
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen#
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen# CDDL HEADER END
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen#
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen#
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen# Use is subject to license terms.
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen#
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen"""module describing a directory packaging object
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo SirainenThis module contains the DirectoryAction class, which represents a
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainendirectory-type packaging object."""
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainenimport os
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainenimport errno
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenfrom stat import *
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenimport generic
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenimport pkg.portable as portable
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenimport pkg.actions
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenclass DirectoryAction(generic.Action):
150e64c376365becf1ec5c9d45912ecb840eea96Timo Sirainen """Class representing a directory-type packaging object."""
150e64c376365becf1ec5c9d45912ecb840eea96Timo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen name = "dir"
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen attributes = ("mode", "owner", "group", "path")
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen key_attr = "path"
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen def __init__(self, data=None, **attrs):
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen generic.Action.__init__(self, data, **attrs)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if "path" in self.attrs:
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen self.attrs["path"] = self.attrs["path"].lstrip(
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen os.path.sep)
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen if not self.attrs["path"]:
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen raise pkg.actions.InvalidActionError(
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen str(self), _("Empty path attribute"))
5afa8e2edf4f313cd56e5909f92f39c3b5b7b4d3Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen def compare(self, other):
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return cmp(self.attrs["path"], other.attrs["path"])
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen def directory_references(self):
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return [os.path.normpath(self.attrs["path"])]
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen def install(self, pkgplan, orig):
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen """Client-side method that installs a directory."""
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen path = self.attrs["path"]
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen mode = int(self.attrs["mode"], 8)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen owner = pkgplan.image.get_user_by_name(self.attrs["owner"])
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen group = pkgplan.image.get_group_by_name(self.attrs["group"])
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if orig:
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen omode = int(orig.attrs["mode"], 8)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen oowner = pkgplan.image.get_user_by_name(
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen orig.attrs["owner"])
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen ogroup = pkgplan.image.get_group_by_name(
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen orig.attrs["group"])
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen path = os.path.normpath(os.path.sep.join(
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen (pkgplan.image.get_root(), path)))
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen # XXX Hack! (See below comment.)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if not portable.is_admin():
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen mode |= 0200
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if not orig:
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen try:
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen self.makedirs(path, mode = mode)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen except OSError, e:
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen if e.errno != errno.EEXIST:
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen raise
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen # The downside of chmodding the directory is that as a non-root
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen # user, if we set perms u-w, we won't be able to put anything in
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen # it, which is often not what we want at install time. We save
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen # the chmods for the postinstall phase, but it's always possible
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen # that a later package install will want to place something in
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen # this directory and then be unable to. So perhaps we need to
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen # (in all action types) chmod the parent directory to u+w on
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen # failure, and chmod it back aftwards. The trick is to
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen # recognize failure due to missing file_dac_write in contrast to
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen # other failures. Or can we require that everyone simply have
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen # file_dac_write who wants to use the tools. Probably not.
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen elif mode != omode:
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen os.chmod(path, mode)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
f2bd9e507b8befdd95a983f86664febf5c19bd95Timo Sirainen if not orig or oowner != owner or ogroup != group:
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen try:
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen portable.chown(path, owner, group)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen except OSError, e:
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if e.errno != errno.EPERM and \
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen e.errno != errno.ENOSYS:
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen raise
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen def verify(self, img, **args):
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen """ make sure directory is correctly installed"""
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen mode = int(self.attrs["mode"], 8)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen owner = img.get_user_by_name(self.attrs["owner"])
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen group = img.get_group_by_name(self.attrs["group"])
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen path = os.path.normpath(os.path.sep.join((img.get_root(),
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen self.attrs["path"])))
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen try:
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen stat = os.lstat(path)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen except OSError, e:
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if e.errno == errno.ENOENT:
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen return ["Directory does not exist"]
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if e.errno == errno.EACCES:
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen return ["Skipping: Permission denied"]
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen return ["Unexpected exception: %s" % e]
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen errors = []
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if not S_ISDIR(stat[ST_MODE]):
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen errors.append("Not a directory")
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if stat[ST_UID] != owner:
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen errors.append("Owner: '%s' should be '%s'" % \
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen (img.get_name_by_uid(stat[ST_UID], True),
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen img.get_name_by_uid(owner, True)))
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen if stat[ST_GID] != group:
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen errors.append("Group: '%s' should be '%s'" % \
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen (img.get_name_by_gid(stat[ST_GID], True),
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen img.get_name_by_gid(group, True)))
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if S_IMODE(stat[ST_MODE]) != mode:
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen errors.append("Mode: 0%.3o should be 0%.3o" % \
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen (S_IMODE(stat[ST_MODE]), mode))
bc3698b8892df8003b410daea6f5bbcd20433808Timo Sirainen
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen return errors
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen def remove(self, pkgplan):
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen localpath = os.path.normpath(self.attrs["path"])
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen path = os.path.normpath(os.path.sep.join(
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen (pkgplan.image.get_root(), localpath)))
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen try:
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen os.rmdir(path)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen except OSError, e:
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if e.errno == errno.ENOENT:
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen pass
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen elif e.errno == errno.EEXIST or \
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen e.errno == errno.ENOTEMPTY:
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen # cannot remove directory since it's
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen # not empty...
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen pkgplan.image.salvagedir(localpath)
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen elif e.errno != errno.EACCES: # this happens on Windows
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen raise
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen def generate_indices(self):
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen """Generates the indices needed by the search dictionary. See
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen generic.py for a more detailed explanation."""
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen return [
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen ("directory", "basename",
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen os.path.basename(self.attrs["path"].rstrip(os.path.sep)),
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen None),
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen ("directory", "path", os.path.sep + self.attrs["path"],
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen None)
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen ]
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen