#!/usr/bin/env python
# Copyright (C) 2007 Oracle.  All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License v2 as published by the Free Software Foundation.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
# 
# You should have received a copy of the GNU General Public
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 021110-1307, USA.
#
import sys, os, stat, fcntl
from optparse import OptionParser

def copylink(srcname, dst, filename, statinfo, force_name):
    dstname = os.path.join(dst, force_name or filename)
    if not os.path.exists(dstname):
        link_target = os.readlink(srcname)
        os.symlink(link_target, dstname)

def copydev(srcname, dst, filename, statinfo, force_name):
    devbits = statinfo.st_mode & (stat.S_IFBLK | stat.S_IFCHR)
    mode = stat.S_IMODE(statinfo.st_mode) | devbits
    dstname = os.path.join(dst, force_name or filename)
    if not os.path.exists(dstname):
        os.mknod(dstname, mode, statinfo.st_rdev)

def copyfile(srcname, dst, filename, statinfo, force_name):
    written = 0
    dstname = os.path.join(dst, force_name or filename)

    st_mode = statinfo.st_mode
    if stat.S_ISLNK(st_mode):
        copylink(srcname, dst, part, statinfo, None)
        return
    elif stat.S_ISBLK(st_mode) or stat.S_ISCHR(st_mode):
        copydev(srcname, dst, part, statinfo, None)
        return
    elif not stat.S_ISREG(st_mode):
        return

    try:
        os.unlink(dstname)
    except:
        pass

    if options.link:
        os.link(srcname, dstname)
        return

    dstf = file(dstname, 'w')
    srcf = file(srcname, 'r')

    ret = 1

    try:
        if not options.copy:
            ret = fcntl.ioctl(dstf.fileno(), 1074041865, srcf.fileno())
    except:
        pass

    if ret != 0:
        while True:
            buf = srcf.read(256 * 1024)
            if not buf:
                break
            written += len(buf)
            dstf.write(buf)

    os.chmod(dstname, stat.S_IMODE(statinfo.st_mode))
    os.chown(dstname, statinfo.st_uid, statinfo.st_gid)


usage = "usage: %prog [options]"
parser = OptionParser(usage=usage)
parser.add_option("-l", "--link", help="Create hard links", default=False,
                  action="store_true")
parser.add_option("-c", "--copy", help="Copy file bytes (don't cow)",
                  default=False, action="store_true")

(options,args) = parser.parse_args()

if len(args) < 2:
    sys.stderr.write("source or destination not specified\n")
    sys.exit(1)

if options.link and options.copy:
    sys.stderr.write("Both -l and -c specified, using copy mode\n")
    options.link = False


total_args = len(args)
src_args = total_args - 1
orig_dst = args[-1]

if src_args > 1:
    if not os.path.exists(orig_dst):
        os.makedirs(orig_dst)
    if not os.path.isdir(orig_dst):
        sys.stderr.write("Destination %s is not a directory\n" % orig_dst)
        exit(1)

for srci in xrange(0, src_args):
    src = args[srci]
    if os.path.isfile(src):
        statinfo = os.lstat(src)
        force_name = None
        if src_args == 1:
            if not os.path.isdir(orig_dst):
                force_name = os.path.basename(orig_dst)
                orig_dst = os.path.dirname(orig_dst) or '.'
        copyfile(src, orig_dst, os.path.basename(src), statinfo, force_name)
        continue

    if src_args > 1 or os.path.exists(orig_dst):
        dst = os.path.join(orig_dst, os.path.basename(src))
    else:
        dst = orig_dst

    if not os.path.exists(dst):
        os.makedirs(dst)
        statinfo = os.stat(src)
        os.chmod(dst, stat.S_IMODE(statinfo.st_mode))
        os.chown(dst, statinfo.st_uid, statinfo.st_gid)
        
    iter = os.walk(src, topdown=True)

    for (dirpath, dirnames, filenames) in iter:
        for x in dirnames:
            srcname = os.path.join(dirpath, x)
            statinfo = os.lstat(srcname)

            part = os.path.relpath(srcname, src)

            if stat.S_ISLNK(statinfo.st_mode):
                copylink(srcname, dst, part, statinfo, None)
                continue

            dst_dir = os.path.join(dst, part)
            if not os.path.exists(dst_dir):
                os.makedirs(dst_dir)

            os.chmod(dst_dir, stat.S_IMODE(statinfo.st_mode))
            os.chown(dst_dir, statinfo.st_uid, statinfo.st_gid)

        for f in filenames:
            srcname = os.path.join(dirpath, f)
            part = os.path.relpath(srcname, src)

            statinfo = os.lstat(srcname)
            copyfile(srcname, dst, part, statinfo, None)


