summaryrefslogtreecommitdiff
path: root/bcp
diff options
context:
space:
mode:
Diffstat (limited to 'bcp')
-rwxr-xr-xbcp159
1 files changed, 159 insertions, 0 deletions
diff --git a/bcp b/bcp
new file mode 100755
index 00000000..e7ca641a
--- /dev/null
+++ b/bcp
@@ -0,0 +1,159 @@
+#!/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)
+
+