コード例 #1
0
    def fsobj_checkpath(self, pkgplan, final_path):
        """Verifies that the specified path doesn't contain one or more
                symlinks relative to the image root.  Raises an
                ActionExecutionError exception if path check fails."""

        valid_dirs = pkgplan.image.imageplan.valid_directories
        parent_path = os.path.dirname(final_path)
        if parent_path in valid_dirs:
            return

        real_parent_path = os.path.realpath(parent_path)
        if parent_path == real_parent_path:
            valid_dirs.add(parent_path)
            return

        fmri = pkgplan.destination_fmri

        # Now test each component of the parent path until one is found
        # to be a link.  When found, that's the parent that has been
        # redirected to some other location.
        idx = 0
        while idx < len(parent_path) and parent_path[idx] == os.path.sep:
            idx += 1
        tmp = parent_path[idx - 1:]
        if pkgplan.image.root != os.path.sep:
            img_root = pkgplan.image.root.rstrip(os.path.sep)
        else:
            img_root = pkgplan.image.root
        while 1:
            if tmp == img_root:
                # No parent directories up to the root were
                # found to be links, so assume this is ok.
                valid_dirs.add(parent_path)
                return

            if os.path.islink(tmp):
                # We've found the parent that changed locations.
                break
            # Drop the final component.
            tmp = os.path.split(tmp)[0]

        parent_dir = tmp
        parent_target = os.path.realpath(parent_dir)
        err_txt = _(
            "Cannot install '%(final_path)s'; parent directory "
            "%(parent_dir)s is a link to %(parent_target)s.  To "
            "continue, move the directory to its original location and "
            "try again.") % locals()
        raise apx.ActionExecutionError(self, details=err_txt, fmri=fmri)
コード例 #2
0
ファイル: group.py プロジェクト: alhazred/v9os-pkg5
    def install(self, pkgplan, orig, retry=False):
        """client-side method that adds the group
                   use gid from disk if different"""
        if not have_cfgfiles:
            # the group action is ignored if cfgfiles is not available
            return

        template = self.extract(["groupname", "gid"])

        gr = GroupFile(pkgplan.image)

        cur_attrs = gr.getvalue(template)

        # check for (wrong) pre-existing definition
        # if so, rewrite entry using existing defs but new group entry
        #        (XXX this doesn't chown any files on-disk)
        # else, nothing to do
        if cur_attrs:
            if (cur_attrs["gid"] != self.attrs["gid"]):
                template = cur_attrs
                template["gid"] = self.attrs["gid"]
            else:
                return
        # XXX needs modification if more attrs are used
        gr.setvalue(template)
        try:
            gr.writefile()
        except EnvironmentError as e:
            if e.errno != errno.ENOENT:
                raise
            # If we're in the postinstall phase and the
            # files *still* aren't there, bail gracefully.
            if retry:
                txt = _("Group cannot be installed "
                        "without group database files "
                        "present.")
                raise apx.ActionExecutionError(self,
                                               error=e,
                                               details=txt,
                                               fmri=pkgplan.destination_fmri)
            img = pkgplan.image
            img._groups.add(self)
            if "gid" in self.attrs:
                img._groupsbyname[self.attrs["groupname"]] = \
                    int(self.attrs["gid"])
コード例 #3
0
    def install(self, pkgplan, orig, retry=False):
        """client-side method that adds the user...
                   update any attrs that changed from orig
                   unless the on-disk stuff was changed"""

        if not have_cfgfiles:
            # The user action is ignored if cfgfiles is not
            # available.
            return

        username = self.attrs["username"]

        try:
            pw, gr, ftp, cur_attrs = \
                self.readstate(pkgplan.image, username, lock=True)

            self.attrs["gid"] = str(
                pkgplan.image.get_group_by_name(self.attrs["group"]))

            orig_attrs = {}
            default_attrs = pw.getdefaultvalues()
            if orig:
                # Grab default values from files, extend by
                # specifics from original manifest for
                # comparisons sake.
                orig_attrs.update(default_attrs)
                orig_attrs["group-list"] = []
                orig_attrs["ftpuser"] = "******"
                orig_attrs.update(orig.attrs)
            else:
                # If we're installing a user for the first time,
                # we want to override whatever value might be
                # represented by the presence or absence of the
                # user in the ftpusers file.  Remove the value
                # from the representation of the file so that
                # the new value takes precedence in the merge.
                del cur_attrs["ftpuser"]

            # add default values to new attrs if not present
            for attr in default_attrs:
                if attr not in self.attrs:
                    self.attrs[attr] = default_attrs[attr]

            self.attrs["group-list"] = self.attrlist("group-list")
            final_attrs = self.merge(orig_attrs, cur_attrs)

            pw.setvalue(final_attrs)

            if "group-list" in final_attrs:
                gr.setgroups(username, final_attrs["group-list"])

            ftp.setuser(username, final_attrs.get("ftpuser", "true") == "true")

            pw.writefile()
            gr.writefile()
            ftp.writefile()
        except EnvironmentError as e:
            if e.errno != errno.ENOENT:
                raise
            # If we're in the postinstall phase and the files
            # *still* aren't there, bail gracefully.
            if retry:
                txt = _("User cannot be installed without user "
                        "database files present.")
                raise apx.ActionExecutionError(self,
                                               error=e,
                                               details=txt,
                                               fmri=pkgplan.destination_fmri)
            img = pkgplan.image
            img._users.add(self)
            if "uid" in self.attrs:
                img._usersbyname[self.attrs["username"]] = \
                    int(self.attrs["uid"])
            raise pkg.actions.ActionRetry(self)
        except KeyError as e:
            # cannot find group
            self.validate()  # should raise error if no group in action
            txt = _("{group} is an unknown or invalid group").format(
                group=self.attrs.get("group", "None"))
            raise apx.ActionExecutionError(self,
                                           details=txt,
                                           fmri=pkgplan.destination_fmri)

        finally:
            if "pw" in locals():
                pw.unlock()
コード例 #4
0
ファイル: group.py プロジェクト: thenovum/pkg5
        def install(self, pkgplan, orig, retry=False):
                """client-side method that adds the group
                   use gid from disk if different"""
                if not have_cfgfiles:
                        # the group action is ignored if cfgfiles is not
                        # available.
                        return

                template = self.extract(["groupname", "gid"])

                root = pkgplan.image.get_root()
                try:
                        pw = PasswordFile(root, lock=True)
                except EnvironmentError as e:
                        if e.errno != errno.ENOENT:
                                raise
                        pw = None

                gr = GroupFile(pkgplan.image)

                cur_attrs = gr.getvalue(template)

                # check for (wrong) pre-existing definition
                # if so, rewrite entry using existing defs but new group entry
                #        (XXX this doesn't chown any files on-disk)
                # else, nothing to do
                if cur_attrs:
                        if "gid" not in self.attrs:
                                self.attrs["gid"] = cur_attrs["gid"]
                        elif self.attrs["gid"] != cur_attrs["gid"]:
                                cur_gid = cur_attrs["gid"]
                                template = cur_attrs;
                                template["gid"] = self.attrs["gid"]
                                # Update the user database with the new gid
                                # as well in case group is someone's primary
                                # group.
                                usernames = pkgplan.image.get_usernames_by_gid(
                                    cur_gid)
                                try:
                                        for username in usernames:
                                                user_entry = pw.getuser(
                                                        username)
                                                user_entry["gid"] = self.attrs[
                                                        "gid"]
                                                pw.setvalue(user_entry)
                                except Exception as e:
                                        if pw:
                                                pw.unlock()
                                                txt = _("Group cannot be installed. "
                                                        "Updating related user entries "
                                                        "failed.")
                                                raise apx.ActionExecutionError(self,
                                                    error=e, details=txt,
                                                    fmri=pkgplan.destination_fmri)

                        # Deal with other columns in the group row.
                        #
                        # pkg has no support for the legacy password field
                        # in the group table and thus requires it to be
                        # empty for any pkg delivered group.  So there is
                        # explicitly no support for updating
                        # template["password"] since we require it to be empty.
                        #
                        # If the admin has assigned any users to a group that is
                        # delivered as an action we preserve that list without
                        # attempting to validate it in any way.
                        if cur_attrs["user-list"]:
                            template["user-list"] = cur_attrs["user-list"]

                gr.setvalue(template)
                try:
                        gr.writefile()
                        if pw:
                                pw.writefile()
                except EnvironmentError as e:
                        if e.errno != errno.ENOENT:
                                raise
                        # If we're in the postinstall phase and the
                        # files *still* aren't there, bail gracefully.
                        if retry:
                                txt = _("Group cannot be installed "
                                    "without group database files "
                                    "present.")
                                raise apx.ActionExecutionError(self, error=e,
                                    details=txt, fmri=pkgplan.destination_fmri)
                        img = pkgplan.image
                        img._groups.add(self)
                        if "gid" in self.attrs:
                                img._groupsbyname[self.attrs["groupname"]] = \
                                    int(self.attrs["gid"])
                        raise pkg.actions.ActionRetry(self)
                finally:
                        if pw:
                                pw.unlock()
コード例 #5
0
    def install(self, pkgplan, orig, retry=False):
        """client-side method that adds the group
                   use gid from disk if different"""
        if not have_cfgfiles:
            # the group action is ignored if cfgfiles is not
            # available.
            return

        template = self.extract(["groupname", "gid"])

        root = pkgplan.image.get_root()
        try:
            pw = PasswordFile(root, lock=True)
        except EnvironmentError as e:
            if e.errno != errno.ENOENT:
                raise
            pw = None

        gr = GroupFile(pkgplan.image)

        cur_attrs = gr.getvalue(template)

        # check for (wrong) pre-existing definition
        # if so, rewrite entry using existing defs but new group entry
        #        (XXX this doesn't chown any files on-disk)
        # else, nothing to do
        if cur_attrs:
            if (cur_attrs["gid"] == self.attrs["gid"]):
                if pw:
                    pw.unlock()
                return

            cur_gid = cur_attrs["gid"]
            template = cur_attrs
            template["gid"] = self.attrs["gid"]
            # Update the user database with the new gid
            # as well.
            try:
                usernames = pkgplan.image.get_usernames_by_gid(cur_gid)
                for username in usernames:
                    user_entry = pw.getuser(username)
                    user_entry["gid"] = self.attrs["gid"]
                    pw.setvalue(user_entry)
            except Exception as e:
                if pw:
                    pw.unlock()
                txt = _("Group cannot be installed. "
                        "Updating related user entries "
                        "failed.")
                raise apx.ActionExecutionError(self,
                                               error=e,
                                               details=txt,
                                               fmri=pkgplan.destination_fmri)

        # XXX needs modification if more attrs are used
        gr.setvalue(template)
        try:
            gr.writefile()
            if pw:
                pw.writefile()
        except EnvironmentError as e:
            if e.errno != errno.ENOENT:
                raise
            # If we're in the postinstall phase and the
            # files *still* aren't there, bail gracefully.
            if retry:
                txt = _("Group cannot be installed "
                        "without group database files "
                        "present.")
                raise apx.ActionExecutionError(self,
                                               error=e,
                                               details=txt,
                                               fmri=pkgplan.destination_fmri)
            img = pkgplan.image
            img._groups.add(self)
            if "gid" in self.attrs:
                img._groupsbyname[self.attrs["groupname"]] = \
                    int(self.attrs["gid"])
            raise pkg.actions.ActionRetry(self)
        finally:
            if pw:
                pw.unlock()
コード例 #6
0
    def install(self, pkgplan, orig, retry=False):
        """client-side method that adds the user...
                   update any attrs that changed from orig
                   unless the on-disk stuff was changed"""

        if not have_cfgfiles:
            # The user action is ignored if cfgfiles is not
            # available.
            return

        username = self.attrs["username"]
        if "PKG_ACCOUNTS_DEBUG" in os.environ:
            sys.stderr.write("[D] Processing user " + username + "\n")

        try:
            pw, gr, ftp, cur_attrs = \
                self.readstate(pkgplan.image, username, lock=True)

            # Check if the UID is already occupied
            if "uid" in self.attrs:
                cur_attrs_uid = pw.getusersbyid(self.attrs["uid"])
                if cur_attrs_uid:
                    # ...if the UID definition(s) existed on-disk
                    # note there may be several aliases to same UID
                    if "PKG_ACCOUNTS_DEBUG" in os.environ:
                        sys.stderr.write("[D] User(s) with UID " +
                                         self.attrs["uid"] + ": " +
                                         str(cur_attrs_uid) + "\n")
                    may_proceed = False
                    existing_names = []
                    for cur_attrs_iter in cur_attrs_uid:
                        if cur_attrs_iter["username"] == self.attrs[
                                "username"]:
                            # At least one existing alias matches the user
                            # we would create at the UID we require
                            may_proceed = True
                            # Note: unlike group.py we do not reset cur_attrs
                            # entry here as the one we want to manage/update:
                            # readstate() did a diligent job of finding it by
                            # name and adding correlated data from elsewhere.
                        else:
                            existing_names.append(cur_attrs_iter["username"])

                    if not may_proceed:
                        # ...on-disk user name(s) all differ from
                        # what we want to make now
                        # TODO: want a 3-way check vs. orig(?) whether
                        # the earlier package version we are upgrading
                        # from delivered that other name, then we can
                        # safely just rename it... or add an alias?..
                        # Currently we safely bail and ask a human to
                        # handle this "properly".
                        if pw:
                            pw.unlock()
                        txt = _("User named '%s' cannot be installed. "
                                "Requested UID number '%s' is already "
                                "occupied by %s. "
                                "Please evacuate that user to another ID "
                                "first (including FS object ownership), or "
                                "rename (or alias) the account to the new "
                                "packaged name if applicable." %
                                (self.attrs["username"], str(
                                    self.attrs["uid"]), existing_names))
                        if "PKG_ACCOUNTS_COLLISION" in os.environ and os.environ[
                                "PKG_ACCOUNTS_COLLISION"] == "permit":
                            sys.stderr.write(
                                "WARNING (relaxed because PKG_ACCOUNTS_COLLISION==permit): "
                                + txt + "\n")
                        else:
                            raise apx.ActionExecutionError(
                                self,
                                details=txt,
                                fmri=pkgplan.destination_fmri)
                if "PKG_ACCOUNTS_DEBUG" in os.environ:
                    sys.stderr.write(
                        "[D] UID " + self.attrs["uid"] +
                        " is available or occupied by expected username\n")

            self.attrs["gid"] = str(
                pkgplan.image.get_group_by_name(self.attrs["group"]))

            orig_attrs = {}
            default_attrs = pw.getdefaultvalues()
            if orig:
                # Grab default values from files, extend by
                # specifics from original manifest for
                # comparisons sake.
                orig_attrs.update(default_attrs)
                orig_attrs["group-list"] = []
                orig_attrs["ftpuser"] = "******"
                orig_attrs.update(orig.attrs)
            else:
                # If we're installing a user for the first time,
                # we want to override whatever value might be
                # represented by the presence or absence of the
                # user in the ftpusers file.  Remove the value
                # from the representation of the file so that
                # the new value takes precedence in the merge.
                del cur_attrs["ftpuser"]

            # add default values to new attrs if not present
            for attr in default_attrs:
                if attr not in self.attrs:
                    self.attrs[attr] = default_attrs[attr]

            self.attrs["group-list"] = self.attrlist("group-list")
            final_attrs = self.merge(orig_attrs, cur_attrs)

            pw.setvalue(final_attrs)

            if "group-list" in final_attrs:
                gr.setgroups(username, final_attrs["group-list"])

            ftp.setuser(username, final_attrs.get("ftpuser", "true") == "true")

            pw.writefile()
            gr.writefile()
            ftp.writefile()
        except EnvironmentError as e:
            if e.errno != errno.ENOENT:
                raise
            # If we're in the postinstall phase and the files
            # *still* aren't there, bail gracefully.
            if retry:
                txt = _("User cannot be installed without user "
                        "database files present.")
                raise apx.ActionExecutionError(self,
                                               error=e,
                                               details=txt,
                                               fmri=pkgplan.destination_fmri)
            img = pkgplan.image
            img._users.add(self)
            if "uid" in self.attrs:
                img._usersbyname[self.attrs["username"]] = \
                    int(self.attrs["uid"])
            raise pkg.actions.ActionRetry(self)
        except KeyError as e:
            # cannot find group
            self.validate()  # should raise error if no group in action
            txt = _("{group} is an unknown or invalid group").format(
                group=self.attrs.get("group", "None"))
            raise apx.ActionExecutionError(self,
                                           details=txt,
                                           fmri=pkgplan.destination_fmri)

        finally:
            if "pw" in locals():
                pw.unlock()
コード例 #7
0
        def remove_fsobj(self, pkgplan, path):
                """Shared logic for removing file and link objects."""

                # Necessary since removal logic is reused by install.
                fmri = pkgplan.destination_fmri
                if not fmri:
                        fmri = pkgplan.origin_fmri

                try:
                        portable.remove(path)
                except EnvironmentError, e:
                        if e.errno == errno.ENOENT:
                                # Already gone; don't care.
                                return
                        elif e.errno == errno.EBUSY and os.path.ismount(path):
                                # User has replaced item with mountpoint, or a
                                # package has been poorly implemented.
                                err_txt = _("Unable to remove %s; it is in use "
                                    "as a mountpoint.  To continue, please "
                                    "unmount the filesystem at the target "
                                    "location and try again.") % path
                                raise apx.ActionExecutionError(self,
                                    details=err_txt, error=e, fmri=fmri)
                        elif e.errno == errno.EBUSY:
                                # os.path.ismount() is broken for lofs
                                # filesystems, so give a more generic
                                # error.
                                err_txt = _("Unable to remove %s; it is in "
                                    "use by the system, another process, or "
                                    "as a mountpoint.") % path
                                raise apx.ActionExecutionError(self,
                                    details=err_txt, error=e, fmri=fmri)
                        elif e.errno == errno.EPERM and \
                            not stat.S_ISDIR(os.lstat(path).st_mode):
                                # Was expecting a directory in this failure
                                # case, it is not, so raise the error.
                                raise
                        elif e.errno in (errno.EACCES, errno.EROFS):
                                # Raise these permissions exceptions as-is.
                                raise
                        elif e.errno != errno.EPERM:
                                # An unexpected error.
                                raise apx.ActionExecutionError(self, error=e,
                                    fmri=fmri)

                        # Attempting to remove a directory as performed above
                        # gives EPERM.  First, try to remove the directory,
                        # if it isn't empty, salvage it.
                        try:
                                os.rmdir(path)
                        except OSError, e:
                                if e.errno in (errno.EPERM, errno.EACCES):
                                        # Raise permissions exceptions as-is.
                                        raise
                                elif e.errno not in (errno.EEXIST,
                                    errno.ENOTEMPTY):
                                        # An unexpected error.
                                        raise apx.ActionExecutionError(self,
                                            error=e, fmri=fmri)

                                pkgplan.image.salvage(path)
コード例 #8
0
                fs = os.stat(os.path.join(*pathlist[:i]))
                for i, e in g:
                        p = os.path.join(*pathlist[:i])
                        try:
                                os.mkdir(p, fs.st_mode)
                        except OSError, e:
                                if e.ernno != errno.ENOTDIR:
                                        raise
                                err_txt = _("Unable to create %(path)s; a "
                                    "parent directory %(p)s has been replaced "
                                    "with a file or link.  Please restore the "
                                    "parent directory and try again.") % \
                                    locals()
                                raise apx.ActionExecutionError(self,
                                    details=err_txt, error=e,
                                    fmri=kw.get("fmri", None))

                        os.chmod(p, fs.st_mode)
                        try:
                                portable.chown(p, fs.st_uid, fs.st_gid)
                        except OSError, e:
                                if e.errno != errno.EPERM:
                                        raise

                # Create the leaf with any requested permissions, substituting
                # missing perms with the parent's perms.
                mode = kw.get("mode", fs.st_mode)
                uid = kw.get("uid", fs.st_uid)
                gid = kw.get("gid", fs.st_gid)
                os.mkdir(path, mode)
コード例 #9
0
    def install(self, pkgplan, orig, retry=False):
        """client-side method that adds the group
                   use gid from disk if different"""
        if not have_cfgfiles:
            # the group action is ignored if cfgfiles is not
            # available.
            return

        template = self.extract(["groupname", "gid"])
        if "PKG_ACCOUNTS_DEBUG" in os.environ:
            sys.stderr.write("[D] Processing group " +
                             self.attrs["groupname"] + "\n")

        root = pkgplan.image.get_root()
        try:
            pw = PasswordFile(root, lock=True)
        except EnvironmentError as e:
            if e.errno != errno.ENOENT:
                raise
            pw = None

        gr = GroupFile(pkgplan.image)

        # Read group attrs from on-disk data, if any
        cur_attrs = gr.getvalue(template)

        # Check if the gid number is occupied
        if "gid" in self.attrs:
            # ...if the pkg action required a gid number
            cur_attrs_gid = gr.getgroupsbyid(self.attrs["gid"])
            if cur_attrs_gid:
                # ...if the GID definition(s) existed on-disk
                # note there may be several aliases to same GID
                if "PKG_ACCOUNTS_DEBUG" in os.environ:
                    sys.stderr.write("[D] Group(s) with GID " +
                                     self.attrs["gid"] + ": " +
                                     str(cur_attrs_gid) + "\n")
                may_proceed = False
                existing_names = []
                for cur_attrs_iter in cur_attrs_gid:
                    if cur_attrs_iter["groupname"] == self.attrs["groupname"]:
                        # At least one existing alias matches the group
                        # we would create at the GID we require
                        may_proceed = True
                        # Of all possible aliases on this GID, this name
                        # entry is the one we want to manage/update
                        cur_attrs = cur_attrs_iter
                    else:
                        existing_names.append(cur_attrs_iter["groupname"])

                if not may_proceed:
                    # ...on-disk group name(s) all differ from
                    # what we want to make now
                    # TODO: want a 3-way check vs. orig(?) whether
                    # the earlier package version we are upgrading
                    # from delivered that other name, then we can
                    # safely just rename it... or add an alias?..
                    # Currently we safely bail and ask a human to
                    # handle this "properly".
                    if pw:
                        pw.unlock()
                    txt = _("Group named '%s' cannot be installed. "
                            "Requested GID number '%s' is already "
                            "occupied by %s. "
                            "Please evacuate that group to another ID "
                            "first (including FS object ownership), or "
                            "rename (or alias) the account to the new "
                            "packaged name if applicable." %
                            (self.attrs["groupname"], str(
                                self.attrs["gid"]), existing_names))
                    if "PKG_ACCOUNTS_COLLISION" in os.environ and os.environ[
                            "PKG_ACCOUNTS_COLLISION"] == "permit":
                        sys.stderr.write(
                            "WARNING (relaxed because PKG_ACCOUNTS_COLLISION==permit): "
                            + txt + "\n")
                    else:
                        raise apx.ActionExecutionError(
                            self, details=txt, fmri=pkgplan.destination_fmri)
            if "PKG_ACCOUNTS_DEBUG" in os.environ:
                sys.stderr.write(
                    "[D] GID " + self.attrs["gid"] +
                    " is available or occupied by expected groupname\n")

        # check for (maybe wrong) pre-existing definition
        # if so, rewrite entry using existing defs but new group entry
        #        (XXX this doesn't chown any files on-disk)
        # else, nothing to do
        if cur_attrs:
            # ...if the definition existed on-disk
            if "gid" not in self.attrs:
                # ...if the pkg action did not require a gid number
                self.attrs["gid"] = cur_attrs["gid"]
            elif self.attrs["gid"] != cur_attrs["gid"]:
                # ...if the pkg action required a gid number and
                # it differs from on-disk for same group name
                cur_gid = cur_attrs["gid"]
                template = cur_attrs
                template["gid"] = self.attrs["gid"]
                # Update the user database with the new gid
                # as well in case group is someone's primary
                # group.
                usernames = pkgplan.image.get_usernames_by_gid(cur_gid)
                try:
                    for username in usernames:
                        user_entry = pw.getuser(username)
                        user_entry["gid"] = self.attrs["gid"]
                        pw.setvalue(user_entry)
                except Exception as e:
                    if pw:
                        pw.unlock()
                        txt = _("Group cannot be installed. "
                                "Updating related user entries "
                                "failed.")
                        raise apx.ActionExecutionError(
                            self,
                            error=e,
                            details=txt,
                            fmri=pkgplan.destination_fmri)

            # Deal with other columns in the group row.
            #
            # pkg has no support for the legacy password field
            # in the group table and thus requires it to be
            # empty for any pkg delivered group.  So there is
            # explicitly no support for updating
            # template["password"] since we require it to be empty.
            #
            # If the admin has assigned any users to a group that is
            # delivered as an action we preserve that list without
            # attempting to validate it in any way.
            if cur_attrs["user-list"]:
                template["user-list"] = cur_attrs["user-list"]

        gr.setvalue(template)
        try:
            gr.writefile()
            if pw:
                pw.writefile()
        except EnvironmentError as e:
            if e.errno != errno.ENOENT:
                raise
            # If we're in the postinstall phase and the
            # files *still* aren't there, bail gracefully.
            if retry:
                txt = _("Group cannot be installed "
                        "without group database files "
                        "present.")
                raise apx.ActionExecutionError(self,
                                               error=e,
                                               details=txt,
                                               fmri=pkgplan.destination_fmri)
            img = pkgplan.image
            img._groups.add(self)
            if "gid" in self.attrs:
                img._groupsbyname[self.attrs["groupname"]] = \
                    int(self.attrs["gid"])
            raise pkg.actions.ActionRetry(self)
        finally:
            if pw:
                pw.unlock()
コード例 #10
0
        def install(self, pkgplan, orig):
                """Client-side method that installs a directory."""

                mode = None
                try:
                        mode = int(self.attrs.get("mode", None), 8)
                except (TypeError, ValueError):
                        # Mode isn't valid, so let validate raise a more
                        # informative error.
                        self.validate(fmri=pkgplan.destination_fmri)

                omode = oowner = ogroup = None
                owner, group = self.get_fsobj_uid_gid(pkgplan,
                        pkgplan.destination_fmri)
                if orig:
                        try:
                                omode = int(orig.attrs.get("mode", None), 8)
                        except (TypeError, ValueError):
                                # Mode isn't valid, so let validate raise a more
                                # informative error.
                                orig.validate(fmri=pkgplan.origin_fmri)
                        oowner, ogroup = orig.get_fsobj_uid_gid(pkgplan,
                            pkgplan.origin_fmri)

                path = os.path.normpath(os.path.sep.join((
                    pkgplan.image.get_root(), self.attrs["path"])))

                # Don't allow installation through symlinks.
                self.fsobj_checkpath(pkgplan, path)

                # XXX Hack!  (See below comment.)
                if not portable.is_admin():
                        mode |= stat.S_IWUSR

                if not orig:
                        try:
                                self.makedirs(path, mode=mode,
                                    fmri=pkgplan.destination_fmri)
                        except OSError, e:
                                if e.filename != path:
                                        # makedirs failed for some component
                                        # of the path.
                                        raise

                                fs = os.lstat(path)
                                fs_mode = stat.S_IFMT(fs.st_mode)
                                if e.errno == errno.EROFS:
                                        # Treat EROFS like EEXIST if both are
                                        # applicable, since we'll end up with
                                        # EROFS instead.
                                        if stat.S_ISDIR(fs_mode):
                                                return
                                        raise
                                elif e.errno != errno.EEXIST:
                                        raise

                                if stat.S_ISLNK(fs_mode):
                                        # User has replaced directory with a
                                        # link, or a package has been poorly
                                        # implemented.  It isn't safe to
                                        # simply re-create the directory as
                                        # that won't restore the files that
                                        # are supposed to be contained within.
                                        err_txt = _("Unable to create "
                                            "directory %s; it has been "
                                            "replaced with a link.  To "
                                            "continue, please remove the "
                                            "link or restore the directory "
                                            "to its original location and "
                                            "try again.") % path
                                        raise apx.ActionExecutionError(
                                            self, details=err_txt, error=e,
                                            fmri=pkgplan.destination_fmri)
                                elif stat.S_ISREG(fs_mode):
                                        # User has replaced directory with a
                                        # file, or a package has been poorly
                                        # implemented.  Salvage what's there,
                                        # and drive on.
                                        pkgplan.image.salvage(path)
                                        os.mkdir(path, mode)
                                elif stat.S_ISDIR(fs_mode):
                                        # The directory already exists, but
                                        # ensure that the mode matches what's
                                        # expected.
                                        os.chmod(path, mode)