示例#1
0
        def install(self, pkgplan, orig):
                """Client-side method that installs the license."""
                mode = 0444
                owner = 0
                group = 0

                path = self.attrs["path"]

                stream = self.data()

                path = os.path.normpath(os.path.sep.join(
                    (pkgplan.image.get_root(), path)))

                # make sure the directory exists and the file is writable
                if not os.path.exists(os.path.dirname(path)):
                        self.makedirs(os.path.dirname(path), mode=0755)
                elif os.path.exists(path):
                        os.chmod(path, 0644)

                lfile = file(path, "wb")
                # XXX Should throw an exception if shasum doesn't match
                # self.hash
                shasum = misc.gunzip_from_stream(stream, lfile)

                lfile.close()
                stream.close()

                os.chmod(path, mode)

                try:
                        portable.chown(path, owner, group)
                except OSError, e:
                        if e.errno != errno.EPERM:
                                raise
示例#2
0
    def install(self, pkgplan, orig):
        """Client-side method that installs the license."""
        owner = 0
        group = 0

        path = self.attrs["path"]

        stream = self.data()

        path = os.path.normpath(
            os.path.sep.join((pkgplan.image.get_root(), path)))

        # make sure the directory exists and the file is writable
        if not os.path.exists(os.path.dirname(path)):
            self.makedirs(os.path.dirname(path),
                          mode=misc.PKG_DIR_MODE,
                          fmri=pkgplan.destination_fmri)
        elif os.path.exists(path):
            os.chmod(path, misc.PKG_FILE_MODE)

        lfile = file(path, "wb")
        # XXX Should throw an exception if shasum doesn't match
        # self.hash
        shasum = misc.gunzip_from_stream(stream, lfile)

        lfile.close()
        stream.close()

        os.chmod(path, misc.PKG_RO_FILE_MODE)

        try:
            portable.chown(path, owner, group)
        except OSError, e:
            if e.errno != errno.EPERM:
                raise
示例#3
0
def copyfile(src_path, dst_path):
    """copy a file, preserving attributes, ownership, etc. where possible"""
    fs = os.lstat(src_path)
    shutil.copy2(src_path, dst_path)
    try:
        portable.chown(dst_path, fs.st_uid, fs.st_gid)
    except OSError, e:
        if e.errno != errno.EPERM:
            raise
def copyfile(src_path, dst_path):
        """copy a file, preserving attributes, ownership, etc. where possible"""
        fs = os.lstat(src_path)
        shutil.copy2(src_path, dst_path)
        try:
                portable.chown(dst_path, fs.st_uid, fs.st_gid)
        except OSError, e:
                if e.errno != errno.EPERM:
                        raise
示例#5
0
    def install(self, pkgplan, orig):
        """Client-side method that installs the license."""
        owner = 0
        group = 0

        # ensure "path" is initialized.  it may not be if we've loaded
        # a plan that was previously prepared.
        self.preinstall(pkgplan, orig)

        stream = self.data()

        path = self.get_installed_path(pkgplan.image.get_root())

        # make sure the directory exists and the file is writable
        if not os.path.exists(os.path.dirname(path)):
            self.makedirs(os.path.dirname(path),
                          mode=misc.PKG_DIR_MODE,
                          fmri=pkgplan.destination_fmri)
        elif os.path.exists(path):
            os.chmod(path, misc.PKG_FILE_MODE)

        lfile = open(path, "wb")
        try:
            hash_attr, hash_val, hash_func = \
                digest.get_preferred_hash(self)
            shasum = misc.gunzip_from_stream(stream,
                                             lfile,
                                             hash_func=hash_func)
        except zlib.error as e:
            raise ActionExecutionError(
                self,
                details=_("Error "
                          "decompressing payload: {0}").format(" ".join(
                              [str(a) for a in e.args])),
                error=e)
        finally:
            lfile.close()
            stream.close()

        if shasum != hash_val:
            raise ActionExecutionError(
                self,
                details=_("Action "
                          "data hash verification failure: expected: "
                          "{expected} computed: {actual} action: "
                          "{action}").format(expected=hash_val,
                                             actual=shasum,
                                             action=self))

        os.chmod(path, misc.PKG_RO_FILE_MODE)

        try:
            portable.chown(path, owner, group)
        except OSError as e:
            if e.errno != errno.EPERM:
                raise
示例#6
0
        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 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."""

                # generate the components of the path.  The first
                # element will be empty since all absolute paths
                # always start with a root specifier.
                pathlist = portable.split_path(path)

                # Fill in the first path with the root of the filesystem
                # (this ends up being something like C:\ on windows systems,
                # and "/" on unix.
                pathlist[0] = portable.get_root(path)

                g = enumerate(pathlist)
                for i, e in g:
                        if not os.path.isdir(os.path.join(*pathlist[:i + 1])):
                                break
                else:
                        # XXX Because the filelist codepath may create
                        # directories with incorrect permissions (see
                        # pkgtarfile.py), we need to correct those permissions
                        # here.  Note that this solution relies on all
                        # intermediate directories being explicitly created by
                        # the packaging system; otherwise intermediate
                        # directories will not get their permissions corrected.
                        stat = os.stat(path)
                        mode = kw.get("mode", stat.st_mode)
                        uid = kw.get("uid", stat.st_uid)
                        gid = kw.get("gid", stat.st_gid)
                        try:
                                if mode != stat.st_mode:
                                        os.chmod(path, mode)
                                if uid != stat.st_uid or gid != stat.st_gid:
                                        portable.chown(path, uid, gid)
                        except  OSError, e:
                                if e.errno != errno.EPERM and \
                                    e.errno != errno.ENOSYS:
                                        raise
                        return
示例#7
0
    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 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."""

        # generate the components of the path.  The first
        # element will be empty since all absolute paths
        # always start with a root specifier.
        pathlist = portable.split_path(path)

        # Fill in the first path with the root of the filesystem
        # (this ends up being something like C:\ on windows systems,
        # and "/" on unix.
        pathlist[0] = portable.get_root(path)

        g = enumerate(pathlist)
        for i, e in g:
            if not os.path.isdir(os.path.join(*pathlist[:i + 1])):
                break
        else:
            # XXX Because the filelist codepath may create
            # directories with incorrect permissions (see
            # pkgtarfile.py), we need to correct those permissions
            # here.  Note that this solution relies on all
            # intermediate directories being explicitly created by
            # the packaging system; otherwise intermediate
            # directories will not get their permissions corrected.
            stat = os.stat(path)
            mode = kw.get("mode", stat.st_mode)
            uid = kw.get("uid", stat.st_uid)
            gid = kw.get("gid", stat.st_gid)
            try:
                if mode != stat.st_mode:
                    os.chmod(path, mode)
                if uid != stat.st_uid or gid != stat.st_gid:
                    portable.chown(path, uid, gid)
            except OSError, e:
                if e.errno != errno.EPERM and \
                    e.errno != errno.ENOSYS:
                    raise
            return
                        # XXX Because the filelist codepath may create
                        # directories with incorrect permissions (see
                        # pkgtarfile.py), we need to correct those permissions
                        # here.  Note that this solution relies on all
                        # intermediate directories being explicitly created by
                        # the packaging system; otherwise intermediate
                        # directories will not get their permissions corrected.
                        fs = os.lstat(path)
                        mode = kw.get("mode", fs.st_mode)
                        uid = kw.get("uid", fs.st_uid)
                        gid = kw.get("gid", fs.st_gid)
                        try:
                                if mode != fs.st_mode:
                                        os.chmod(path, mode)
                                if uid != fs.st_uid or gid != fs.st_gid:
                                        portable.chown(path, uid, gid)
                        except  OSError, e:
                                if e.errno != errno.EPERM and \
                                    e.errno != errno.ENOSYS:
                                        raise
                        return

                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 "
示例#9
0
                        # XXX Because the filelist codepath may create
                        # directories with incorrect permissions (see
                        # pkgtarfile.py), we need to correct those permissions
                        # here.  Note that this solution relies on all
                        # intermediate directories being explicitly created by
                        # the packaging system; otherwise intermediate
                        # directories will not get their permissions corrected.
                        fs = os.lstat(path)
                        mode = kw.get("mode", fs.st_mode)
                        uid = kw.get("uid", fs.st_uid)
                        gid = kw.get("gid", fs.st_gid)
                        try:
                                if mode != fs.st_mode:
                                        os.chmod(path, mode)
                                if uid != fs.st_uid or gid != fs.st_gid:
                                        portable.chown(path, uid, gid)
                        except  OSError, e:
                                if e.errno != errno.EPERM and \
                                    e.errno != errno.ENOSYS:
                                        raise
                        return

                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 "
示例#10
0
                    os.chmod(path, mode)
                if uid != stat.st_uid or gid != stat.st_gid:
                    portable.chown(path, uid, gid)
            except OSError, e:
                if e.errno != errno.EPERM and \
                    e.errno != errno.ENOSYS:
                    raise
            return

        stat = os.stat(os.path.join(*pathlist[:i]))
        for i, e in g:
            p = os.path.join(*pathlist[:i])
            os.mkdir(p, stat.st_mode)
            os.chmod(p, stat.st_mode)
            try:
                portable.chown(p, stat.st_uid, stat.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", stat.st_mode)
        uid = kw.get("uid", stat.st_uid)
        gid = kw.get("gid", stat.st_gid)
        os.mkdir(path, mode)
        os.chmod(path, mode)
        try:
            portable.chown(path, uid, gid)
        except OSError, e:
            if e.errno != errno.EPERM:
示例#11
0
    def install(self, pkgplan, orig):
        """Client-side method that installs a file."""

        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)

        owner, group = self.get_fsobj_uid_gid(pkgplan,
                                              pkgplan.destination_fmri)

        final_path = self.get_installed_path(pkgplan.image.get_root())

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

        if not os.path.exists(os.path.dirname(final_path)):
            self.makedirs(os.path.dirname(final_path),
                          mode=misc.PKG_DIR_MODE,
                          fmri=pkgplan.destination_fmri)
        elif (not orig and not pkgplan.origin_fmri and "preserve" in self.attrs
              and self.attrs["preserve"] not in ("abandon", "install-only")
              and os.path.isfile(final_path)):
            # Unpackaged editable file is already present during
            # initial install; salvage it before continuing.
            pkgplan.salvage(final_path)

        # XXX If we're upgrading, do we need to preserve file perms from
        # existing file?

        # check if we have a save_file active; if so, simulate file
        # being already present rather than installed from scratch

        if "save_file" in self.attrs:
            orig = self.restore_file(pkgplan.image)

        # See if we need to preserve the file, and if so, set that up.
        #
        # XXX What happens when we transition from preserve to
        # non-preserve or vice versa? Do we want to treat a preserve
        # attribute as turning the action into a critical action?
        #
        # XXX We should save the originally installed file.  It can be
        # used as an ancestor for a three-way merge, for example.  Where
        # should it be stored?
        pres_type = self._check_preserve(orig, pkgplan)
        do_content = True
        old_path = None
        if pres_type == True or (pres_type and pkgplan.origin_fmri
                                 == pkgplan.destination_fmri):
            # File is marked to be preserved and exists so don't
            # reinstall content.
            do_content = False
        elif pres_type == "legacy":
            # Only rename old file if this is a transition to
            # preserve=legacy from something else.
            if orig.attrs.get("preserve", None) != "legacy":
                old_path = final_path + ".legacy"
        elif pres_type == "renameold.update":
            old_path = final_path + ".update"
        elif pres_type == "renameold":
            old_path = final_path + ".old"
        elif pres_type == "renamenew":
            final_path = final_path + ".new"
        elif pres_type == "abandon":
            return

        # If it is a directory (and not empty) then we should
        # salvage the contents.
        if os.path.exists(final_path) and \
            not os.path.islink(final_path) and \
            os.path.isdir(final_path):
            try:
                os.rmdir(final_path)
            except OSError as e:
                if e.errno == errno.ENOENT:
                    pass
                elif e.errno in (errno.EEXIST, errno.ENOTEMPTY):
                    pkgplan.salvage(final_path)
                elif e.errno != errno.EACCES:
                    # this happens on Windows
                    raise

        # XXX This needs to be modularized.
        if do_content and self.needsdata(orig, pkgplan):
            tfilefd, temp = tempfile.mkstemp(dir=os.path.dirname(final_path))
            if not self.data:
                # The state of the filesystem changed after the
                # plan was prepared; attempt a one-off
                # retrieval of the data.
                self.data = self.__set_data(pkgplan)
            stream = self.data()
            tfile = os.fdopen(tfilefd, "wb")
            try:
                # Always verify using the most preferred hash
                hash_attr, hash_val, hash_func  = \
                    digest.get_preferred_hash(self)
                shasum = misc.gunzip_from_stream(stream, tfile, hash_func)
            except zlib.error as e:
                raise ActionExecutionError(
                    self,
                    details=_("Error decompressing payload: "
                              "{0}").format(" ".join([str(a)
                                                      for a in e.args])),
                    error=e)
            finally:
                tfile.close()
                stream.close()

            if shasum != hash_val:
                raise ActionExecutionError(
                    self,
                    details=_("Action data hash verification "
                              "failure: expected: {expected} computed: "
                              "{actual} action: {action}").format(
                                  expected=hash_val,
                                  actual=shasum,
                                  action=self))

        else:
            temp = final_path

        try:
            os.chmod(temp, mode)
        except OSError as e:
            # If the file didn't exist, assume that's intentional,
            # and drive on.
            if e.errno != errno.ENOENT:
                raise
            else:
                return

        try:
            portable.chown(temp, owner, group)
        except OSError as e:
            if e.errno != errno.EPERM:
                raise

        # XXX There's a window where final_path doesn't exist, but we
        # probably don't care.
        if do_content and old_path:
            try:
                portable.rename(final_path, old_path)
            except OSError as e:
                if e.errno != errno.ENOENT:
                    # Only care if file isn't gone already.
                    raise

        # This is safe even if temp == final_path.
        try:
            portable.rename(temp, final_path)
        except OSError as e:
            raise api_errors.FileInUseException(final_path)

        # Handle timestamp if specified (and content was installed).
        if do_content and "timestamp" in self.attrs:
            t = misc.timestamp_to_time(self.attrs["timestamp"])
            try:
                os.utime(final_path, (t, t))
            except OSError as e:
                if e.errno != errno.EACCES:
                    raise

                # On Windows, the time cannot be changed on a
                # read-only file
                os.chmod(final_path, stat.S_IRUSR | stat.S_IWUSR)
                os.utime(final_path, (t, t))
                os.chmod(final_path, mode)

        # Handle system attributes.
        sattr = self.attrs.get("sysattr")
        if sattr:
            if isinstance(sattr, list):
                sattr = ",".join(sattr)
            sattrs = sattr.split(",")
            if len(sattrs) == 1 and \
                sattrs[0] not in portable.get_sysattr_dict():
                # not a verbose attr, try as a compact attr seq
                arg = sattrs[0]
            else:
                arg = sattrs

            try:
                portable.fsetattr(final_path, arg)
            except OSError as e:
                if e.errno != errno.EINVAL:
                    raise
                warn = _("System attributes are not supported "
                         "on the target image filesystem; 'sysattr'"
                         " ignored for {0}").format(self.attrs["path"])
                pkgplan.image.imageplan.pd.add_item_message(
                    pkgplan.destination_fmri,
                    misc.time_to_timestamp(time.time()), MSG_WARNING, warn)
            except ValueError as e:
                warn = _("Could not set system attributes for {path}"
                         "'{attrlist}': {err}").format(attrlist=sattr,
                                                       err=e,
                                                       path=self.attrs["path"])
                pkgplan.image.imageplan.pd.add_item_message(
                    pkgplan.destination_fmri,
                    misc.time_to_timestamp(time.time()), MSG_WARNING, warn)
示例#12
0
文件: file.py 项目: aszeszo/test
                                    })
                else:
                        temp = final_path

                try:
                        os.chmod(temp, mode)
                except OSError, e:
                        # If the file didn't exist, assume that's intentional,
                        # and drive on.
                        if e.errno != errno.ENOENT:
                                raise
                        else:
                                return

                try:
                        portable.chown(temp, owner, group)
                except OSError, e:
                        if e.errno != errno.EPERM:
                                raise

                # XXX There's a window where final_path doesn't exist, but we
                # probably don't care.
                if do_content and old_path:
                        try:
                                portable.rename(final_path, old_path)
                        except OSError, e:
                                if e.errno != errno.ENOENT:
                                        # Only care if file isn't gone already.
                                        raise

                # This is safe even if temp == final_path.
示例#13
0
            # self.hash
        else:
            temp = final_path

        try:
            os.chmod(temp, mode)
        except OSError, e:
            # If the file didn't exist, assume that's intentional,
            # and drive on.
            if e.errno != errno.ENOENT:
                raise
            else:
                return

        try:
            portable.chown(temp, owner, group)
        except OSError, e:
            if e.errno != errno.EPERM:
                raise

        # XXX There's a window where final_path doesn't exist, but we
        # probably don't care.
        if do_content and pres_type == "renameold":
            portable.rename(final_path, old_path)

        # This is safe even if temp == final_path.
        portable.rename(temp, final_path)

        # Handle timestamp if specified (and content was installed).
        if do_content and "timestamp" in self.attrs:
            t = misc.timestamp_to_time(self.attrs["timestamp"])
示例#14
0
文件: directory.py 项目: aszeszo/test
                        os.chmod(path, mode)

                # if we're salvaging contents, move 'em now.
                # directories with "salvage-from" attribute
                # set will scavenge any available contents
                # that matches specified directory and
                # move it underneath itself on install or update.
                # This is here to support directory rename
                # when old directory has unpackaged contents, or
                # consolidation of content from older directories.
                for salvage_from in self.attrlist("salvage-from"):
                        pkgplan.salvage_from(salvage_from, path)

                if not orig or oowner != owner or ogroup != group:
                        try:
                                portable.chown(path, owner, group)
                        except OSError, e:
                                if e.errno != errno.EPERM and \
                                    e.errno != errno.ENOSYS:
                                        raise

        def verify(self, img, **args):
                """Returns a tuple of lists of the form (errors, warnings,
                info).  The error list will be empty if the action has been
                correctly installed in the given image."""

                lstat, errors, warnings, info, abort = \
                    self.verify_fsobj_common(img, stat.S_IFDIR)
                return errors, warnings, info

        def remove(self, pkgplan):
示例#15
0
        # user, if we set perms u-w, we won't be able to put anything in
        # it, which is often not what we want at install time.  We save
        # the chmods for the postinstall phase, but it's always possible
        # that a later package install will want to place something in
        # this directory and then be unable to.  So perhaps we need to
        # (in all action types) chmod the parent directory to u+w on
        # failure, and chmod it back aftwards.  The trick is to
        # recognize failure due to missing file_dac_write in contrast to
        # other failures.  Or can we require that everyone simply have
        # file_dac_write who wants to use the tools.  Probably not.
        elif mode != omode:
            os.chmod(path, mode)

        if not orig or oowner != owner or ogroup != group:
            try:
                portable.chown(path, owner, group)
            except OSError, e:
                if e.errno != errno.EPERM and \
                    e.errno != errno.ENOSYS:
                    raise

    def verify(self, img, **args):
        """ make sure directory is correctly installed"""

        lstat, errors, abort = \
            self.verify_fsobj_common(img, stat.S_IFDIR)
        return errors

    def remove(self, pkgplan):
        localpath = os.path.normpath(self.attrs["path"])
        path = os.path.normpath(
示例#16
0
                                        os.chmod(path, mode)
                                if uid != stat.st_uid or gid != stat.st_gid:
                                        portable.chown(path, uid, gid)
                        except  OSError, e:
                                if e.errno != errno.EPERM and \
                                    e.errno != errno.ENOSYS:
                                        raise
                        return

                stat = os.stat(os.path.join(*pathlist[:i]))
                for i, e in g:
                        p = os.path.join(*pathlist[:i])
                        os.mkdir(p, stat.st_mode)
                        os.chmod(p, stat.st_mode)
                        try:
                                portable.chown(p, stat.st_uid, stat.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", stat.st_mode)
                uid = kw.get("uid", stat.st_uid)
                gid = kw.get("gid", stat.st_gid)
                os.mkdir(path, mode)
                os.chmod(path, mode)
                try:
                        portable.chown(path, uid, gid)
                except OSError, e:
                        if e.errno != errno.EPERM:
示例#17
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 = self.get_installed_path(pkgplan.image.get_root())

        # 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:
            self.__create_directory(pkgplan, path, mode)

        # The downside of chmodding the directory is that as a non-root
        # user, if we set perms u-w, we won't be able to put anything in
        # it, which is often not what we want at install time.  We save
        # the chmods for the postinstall phase, but it's always possible
        # that a later package install will want to place something in
        # this directory and then be unable to.  So perhaps we need to
        # (in all action types) chmod the parent directory to u+w on
        # failure, and chmod it back aftwards.  The trick is to
        # recognize failure due to missing file_dac_write in contrast to
        # other failures.  Or can we require that everyone simply have
        # file_dac_write who wants to use the tools.  Probably not.
        elif mode != omode:
            try:
                os.chmod(path, mode)
            except Exception as e:
                if e.errno != errno.EPERM and e.errno != \
                    errno.ENOSYS:
                    # Assume chmod failed due to a
                    # recoverable error.
                    self.__create_directory(pkgplan, path, mode)
                    omode = oowner = ogroup = None

        # if we're salvaging contents, move 'em now.
        # directories with "salvage-from" attribute
        # set will scavenge any available contents
        # that matches specified directory and
        # move it underneath itself on install or update.
        # This is here to support directory rename
        # when old directory has unpackaged contents, or
        # consolidation of content from older directories.
        for salvage_from in self.attrlist("salvage-from"):
            pkgplan.salvage_from(salvage_from, path)

        if not orig or oowner != owner or ogroup != group:
            try:
                portable.chown(path, owner, group)
            except OSError as e:
                if e.errno != errno.EPERM and \
                    e.errno != errno.ENOSYS:
                    # Assume chown failed due to a
                    # recoverable error.
                    self.__create_directory(pkgplan,
                                            path,
                                            mode,
                                            uid=owner,
                                            gid=group)