2 # Copyright (C) 2007 Oracle. All rights reserved.
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public
6 # License v2 as published by the Free Software Foundation.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # General Public License for more details.
13 # You should have received a copy of the GNU General Public
14 # License along with this program; if not, write to the
15 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 # Boston, MA 021110-1307, USA.
18 import sys
, os
, stat
, fcntl
19 from optparse
import OptionParser
21 def copylink(srcname
, dst
, filename
, statinfo
, force_name
):
22 dstname
= os
.path
.join(dst
, force_name
or filename
)
23 if not os
.path
.exists(dstname
):
24 link_target
= os
.readlink(srcname
)
25 os
.symlink(link_target
, dstname
)
27 def copydev(srcname
, dst
, filename
, statinfo
, force_name
):
28 devbits
= statinfo
.st_mode
& (stat
.S_IFBLK | stat
.S_IFCHR
)
29 mode
= stat
.S_IMODE(statinfo
.st_mode
) | devbits
30 dstname
= os
.path
.join(dst
, force_name
or filename
)
31 if not os
.path
.exists(dstname
):
32 os
.mknod(dstname
, mode
, statinfo
.st_rdev
)
34 def copyfile(srcname
, dst
, filename
, statinfo
, force_name
):
36 dstname
= os
.path
.join(dst
, force_name
or filename
)
38 st_mode
= statinfo
.st_mode
39 if stat
.S_ISLNK(st_mode
):
40 copylink(srcname
, dst
, part
, statinfo
, None)
42 elif stat
.S_ISBLK(st_mode
) or stat
.S_ISCHR(st_mode
):
43 copydev(srcname
, dst
, part
, statinfo
, None)
45 elif not stat
.S_ISREG(st_mode
):
54 os
.link(srcname
, dstname
)
57 dstf
= file(dstname
, 'w')
58 srcf
= file(srcname
, 'r')
64 ret
= fcntl
.ioctl(dstf
.fileno(), 1074041865, srcf
.fileno())
70 buf
= srcf
.read(256 * 1024)
76 os
.chmod(dstname
, stat
.S_IMODE(statinfo
.st_mode
))
77 os
.chown(dstname
, statinfo
.st_uid
, statinfo
.st_gid
)
80 usage
= "usage: %prog [options]"
81 parser
= OptionParser(usage
=usage
)
82 parser
.add_option("-l", "--link", help="Create hard links", default
=False,
84 parser
.add_option("-c", "--copy", help="Copy file bytes (don't cow)",
85 default
=False, action
="store_true")
87 (options
,args
) = parser
.parse_args()
90 sys
.stderr
.write("source or destination not specified\n")
93 if options
.link
and options
.copy
:
94 sys
.stderr
.write("Both -l and -c specified, using copy mode\n")
98 total_args
= len(args
)
99 src_args
= total_args
- 1
103 if not os
.path
.exists(orig_dst
):
104 os
.makedirs(orig_dst
)
105 if not os
.path
.isdir(orig_dst
):
106 sys
.stderr
.write("Destination %s is not a directory\n" % orig_dst
)
109 for srci
in xrange(0, src_args
):
111 if os
.path
.isfile(src
):
112 statinfo
= os
.lstat(src
)
115 if not os
.path
.isdir(orig_dst
):
116 force_name
= os
.path
.basename(orig_dst
)
117 orig_dst
= os
.path
.dirname(orig_dst
) or '.'
118 copyfile(src
, orig_dst
, os
.path
.basename(src
), statinfo
, force_name
)
121 if src_args
> 1 or os
.path
.exists(orig_dst
):
122 dst
= os
.path
.join(orig_dst
, os
.path
.basename(src
))
126 if not os
.path
.exists(dst
):
128 statinfo
= os
.stat(src
)
129 os
.chmod(dst
, stat
.S_IMODE(statinfo
.st_mode
))
130 os
.chown(dst
, statinfo
.st_uid
, statinfo
.st_gid
)
132 iter = os
.walk(src
, topdown
=True)
134 for (dirpath
, dirnames
, filenames
) in iter:
136 srcname
= os
.path
.join(dirpath
, x
)
137 statinfo
= os
.lstat(srcname
)
139 part
= os
.path
.relpath(srcname
, src
)
141 if stat
.S_ISLNK(statinfo
.st_mode
):
142 copylink(srcname
, dst
, part
, statinfo
, None)
145 dst_dir
= os
.path
.join(dst
, part
)
146 if not os
.path
.exists(dst_dir
):
149 os
.chmod(dst_dir
, stat
.S_IMODE(statinfo
.st_mode
))
150 os
.chown(dst_dir
, statinfo
.st_uid
, statinfo
.st_gid
)
153 srcname
= os
.path
.join(dirpath
, f
)
154 part
= os
.path
.relpath(srcname
, src
)
156 statinfo
= os
.lstat(srcname
)
157 copyfile(srcname
, dst
, part
, statinfo
, None)