DirectoryBundle.py revision 1955
1516N/A#!/usr/bin/python
565N/A#
565N/A# CDDL HEADER START
565N/A#
565N/A# The contents of this file are subject to the terms of the
565N/A# Common Development and Distribution License (the "License").
565N/A# You may not use this file except in compliance with the License.
565N/A#
565N/A# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
565N/A# or http://www.opensolaris.org/os/licensing.
565N/A# See the License for the specific language governing permissions
565N/A# and limitations under the License.
565N/A#
565N/A# When distributing Covered Code, include this CDDL HEADER in each
565N/A# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
565N/A# If applicable, add the following below this CDDL HEADER, with the
565N/A# fields enclosed by brackets "[]" replaced with your own identifying
565N/A# information: Portions Copyright [yyyy] [name of copyright owner]
565N/A#
565N/A# CDDL HEADER END
565N/A#
926N/A
926N/A#
3020N/A# Copyright (c) 2008, 2010 Oracle and/or its affiliates. All rights reserved.
926N/A#
565N/A
2026N/Aimport os
3094N/Aimport stat
1050N/Aimport pkg.misc
2524N/A
926N/Aimport pkg.bundle
926N/Aimport pkg.actions.file
2339N/Aimport pkg.actions.link
2339N/Aimport pkg.actions.hardlink
2339N/A
926N/Aclass DirectoryBundle(object):
926N/A """The DirectoryBundle class assists in the conversion of a directory
926N/A tree to a pkg(5) package by traversing the tree and emitting actions for
838N/A all files, directories, and links found therein.
565N/A
2034N/A Paths are published relative to the given directory. Hardlinks are
2034N/A resolved as long as their companions are in the tree as well.
2034N/A
1540N/A All owners are set to "root" and groups to "bin", as the ownership
1540N/A information is not considered to be valid. These can be set by the
1540N/A caller once the action has been emitted.
1540N/A """
1540N/A
1968N/A def __init__(self, path, targetpaths=()):
1540N/A # XXX This could be more intelligent. Or get user input. Or
2034N/A # extend API to take FMRI.
2034N/A self.rootdir = os.path.normpath(path)
2200N/A self.pkgname = os.path.basename(self.rootdir)
2034N/A self.inodes = {}
2034N/A self.targetpaths = targetpaths
2034N/A
565N/A def __iter__(self):
2339N/A # Pre-populate self.inodes with the paths of known targets
2339N/A for p in self.targetpaths:
2339N/A fp = os.path.join(self.rootdir, p)
2339N/A pstat = os.lstat(fp)
2339N/A self.inodes[pstat.st_ino] = fp
2339N/A
2524N/A for root, dirs, files in os.walk(self.rootdir):
2524N/A for obj in dirs + files:
2524N/A act = self.action(os.path.join(root, obj))
2524N/A if act:
2524N/A yield act
2524N/A
2524N/A def action(self, path):
2524N/A rootdir = self.rootdir
2524N/A pubpath = os.path.relpath(path, rootdir)
2524N/A pstat = os.lstat(path)
2524N/A mode = oct(stat.S_IMODE(pstat.st_mode))
2524N/A timestamp = pkg.misc.time_to_timestamp(pstat.st_mtime)
2524N/A
2524N/A if stat.S_ISREG(pstat.st_mode):
2524N/A inode = pstat.st_ino
2524N/A # Any inode in self.inodes will either have been visited
2524N/A # before or will have been pre-populated from the list
2524N/A # of known targets. Create file actions for known
2524N/A # targets and unvisited inodes.
2524N/A if pubpath in self.targetpaths or \
2524N/A inode not in self.inodes:
2524N/A if pstat.st_nlink > 1:
2524N/A self.inodes.setdefault(inode, path)
2524N/A return pkg.actions.file.FileAction(
2524N/A open(path, "rb"), mode=mode, owner="root",
2524N/A group="bin", path=pubpath,
2524N/A timestamp=timestamp)
2524N/A else:
2524N/A # Find the relative path to the link target.
2524N/A target = os.path.relpath(self.inodes[inode],
2524N/A os.path.dirname(path))
2524N/A return pkg.actions.hardlink.HardLinkAction(
2524N/A path=pubpath, target=target)
2524N/A elif stat.S_ISLNK(pstat.st_mode):
2524N/A return pkg.actions.link.LinkAction(
2524N/A target=os.readlink(path), path=pubpath)
2524N/A elif stat.S_ISDIR(pstat.st_mode):
2524N/A return pkg.actions.directory.DirectoryAction(
2524N/A timestamp=timestamp, mode=mode, owner="root",
2524N/A group="bin", path=pubpath)
2524N/A
2524N/Adef test(filename):
2524N/A return stat.S_ISDIR(os.stat(filename).st_mode)
2524N/A