blob: e4b640cd17f32a2f1bfece5fdf7a19548af449a0 [file] [log] [blame]
Tarek Ziadéc3399782010-02-23 05:39:18 +00001"""Utility functions for copying and archiving files and directory trees.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +00002
Guido van Rossum959fa011999-08-18 20:03:17 +00003XXX The functions here don't copy the resource fork or other metadata on Mac.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +00004
5"""
Guido van Rossumc6360141990-10-13 19:23:40 +00006
Guido van Rossumc96207a1992-03-31 18:55:40 +00007import os
Guido van Rossum83c03e21999-02-23 23:07:51 +00008import sys
Guido van Rossum9d0a3df1997-04-29 14:45:19 +00009import stat
Brett Cannon1c3fa182004-06-19 21:11:35 +000010from os.path import abspath
Georg Brandl2ee470f2008-07-16 12:55:28 +000011import fnmatch
Tarek Ziadé396fad72010-02-23 05:30:31 +000012import collections
Antoine Pitrou910bd512010-03-22 20:11:09 +000013import errno
Tarek Ziadé6ac91722010-04-28 17:51:36 +000014import tarfile
Tarek Ziadé396fad72010-02-23 05:30:31 +000015
16try:
Tarek Ziadéffa155a2010-04-29 13:34:35 +000017 import bz2
Florent Xicluna54540ec2011-11-04 08:29:17 +010018 del bz2
Tarek Ziadéffa155a2010-04-29 13:34:35 +000019 _BZ2_SUPPORTED = True
20except ImportError:
21 _BZ2_SUPPORTED = False
22
23try:
Tarek Ziadé396fad72010-02-23 05:30:31 +000024 from pwd import getpwnam
25except ImportError:
26 getpwnam = None
27
28try:
29 from grp import getgrnam
30except ImportError:
31 getgrnam = None
Guido van Rossumc6360141990-10-13 19:23:40 +000032
Tarek Ziadéc3399782010-02-23 05:39:18 +000033__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
34 "copytree", "move", "rmtree", "Error", "SpecialFileError",
35 "ExecError", "make_archive", "get_archive_formats",
Tarek Ziadé6ac91722010-04-28 17:51:36 +000036 "register_archive_format", "unregister_archive_format",
37 "get_unpack_formats", "register_unpack_format",
Éric Araujoc5efe652011-08-21 14:30:00 +020038 "unregister_unpack_format", "unpack_archive",
Brian Curtinc57a3452012-06-22 16:00:30 -050039 "ignore_patterns", "chown", "which"]
Éric Araujoe4d5b8e2011-08-08 16:51:11 +020040 # disk_usage is added later, if available on the platform
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000041
Neal Norwitz4ce69a52005-09-01 00:45:28 +000042class Error(EnvironmentError):
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000043 pass
Guido van Rossumc6360141990-10-13 19:23:40 +000044
Antoine Pitrou7fff0962009-05-01 21:09:44 +000045class SpecialFileError(EnvironmentError):
46 """Raised when trying to do a kind of operation (e.g. copying) which is
47 not supported on a special file (e.g. a named pipe)"""
48
Tarek Ziadé396fad72010-02-23 05:30:31 +000049class ExecError(EnvironmentError):
50 """Raised when a command could not be executed"""
51
Tarek Ziadé6ac91722010-04-28 17:51:36 +000052class ReadError(EnvironmentError):
53 """Raised when an archive cannot be read"""
54
55class RegistryError(Exception):
56 """Raised when a registery operation with the archiving
57 and unpacking registeries fails"""
58
59
Georg Brandl6aa2d1f2008-08-12 08:35:52 +000060try:
61 WindowsError
62except NameError:
63 WindowsError = None
64
Greg Stein42bb8b32000-07-12 09:55:30 +000065def copyfileobj(fsrc, fdst, length=16*1024):
66 """copy data from file-like object fsrc to file-like object fdst"""
67 while 1:
68 buf = fsrc.read(length)
69 if not buf:
70 break
71 fdst.write(buf)
72
Johannes Gijsbers46f14592004-08-14 13:30:02 +000073def _samefile(src, dst):
74 # Macintosh, Unix.
Tarek Ziadé1eab9cc2010-04-19 21:19:57 +000075 if hasattr(os.path, 'samefile'):
Johannes Gijsbersf9a098e2004-08-14 14:51:01 +000076 try:
77 return os.path.samefile(src, dst)
78 except OSError:
79 return False
Johannes Gijsbers46f14592004-08-14 13:30:02 +000080
81 # All other platforms: check for same pathname.
82 return (os.path.normcase(os.path.abspath(src)) ==
83 os.path.normcase(os.path.abspath(dst)))
Tim Peters495ad3c2001-01-15 01:36:40 +000084
Larry Hastingsb4038062012-07-15 10:57:38 -070085def copyfile(src, dst, *, follow_symlinks=True):
Antoine Pitrou78091e62011-12-29 18:54:15 +010086 """Copy data from src to dst.
87
Larry Hastingsb4038062012-07-15 10:57:38 -070088 If follow_symlinks is not set and src is a symbolic link, a new
Antoine Pitrou78091e62011-12-29 18:54:15 +010089 symlink will be created instead of copying the file it points to.
90
91 """
Johannes Gijsbers46f14592004-08-14 13:30:02 +000092 if _samefile(src, dst):
Hynek Schlawack26fe37d2012-07-19 21:41:02 +020093 raise Error("`%s` and `%s` are the same file" % (src, dst))
Johannes Gijsbers46f14592004-08-14 13:30:02 +000094
Antoine Pitrou7fff0962009-05-01 21:09:44 +000095 for fn in [src, dst]:
96 try:
97 st = os.stat(fn)
98 except OSError:
99 # File most likely does not exist
100 pass
Benjamin Petersonc0d98aa2009-06-05 19:13:27 +0000101 else:
102 # XXX What about other special files? (sockets, devices...)
103 if stat.S_ISFIFO(st.st_mode):
104 raise SpecialFileError("`%s` is a named pipe" % fn)
Tarek Ziadéb01142b2010-05-05 22:43:04 +0000105
Larry Hastingsb4038062012-07-15 10:57:38 -0700106 if not follow_symlinks and os.path.islink(src):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100107 os.symlink(os.readlink(src), dst)
108 else:
109 with open(src, 'rb') as fsrc:
110 with open(dst, 'wb') as fdst:
111 copyfileobj(fsrc, fdst)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500112 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000113
Larry Hastingsb4038062012-07-15 10:57:38 -0700114def copymode(src, dst, *, follow_symlinks=True):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100115 """Copy mode bits from src to dst.
Guido van Rossumc6360141990-10-13 19:23:40 +0000116
Larry Hastingsb4038062012-07-15 10:57:38 -0700117 If follow_symlinks is not set, symlinks aren't followed if and only
118 if both `src` and `dst` are symlinks. If `lchmod` isn't available
119 (e.g. Linux) this method does nothing.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100120
121 """
Larry Hastingsb4038062012-07-15 10:57:38 -0700122 if not follow_symlinks and os.path.islink(src) and os.path.islink(dst):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100123 if hasattr(os, 'lchmod'):
124 stat_func, chmod_func = os.lstat, os.lchmod
125 else:
126 return
127 elif hasattr(os, 'chmod'):
128 stat_func, chmod_func = os.stat, os.chmod
129 else:
130 return
131
132 st = stat_func(src)
133 chmod_func(dst, stat.S_IMODE(st.st_mode))
134
Larry Hastingsad5ae042012-07-14 17:55:11 -0700135if hasattr(os, 'listxattr'):
Larry Hastingsb4038062012-07-15 10:57:38 -0700136 def _copyxattr(src, dst, *, follow_symlinks=True):
Larry Hastingsad5ae042012-07-14 17:55:11 -0700137 """Copy extended filesystem attributes from `src` to `dst`.
138
139 Overwrite existing attributes.
140
Larry Hastingsb4038062012-07-15 10:57:38 -0700141 If `follow_symlinks` is false, symlinks won't be followed.
Larry Hastingsad5ae042012-07-14 17:55:11 -0700142
143 """
144
Larry Hastingsb4038062012-07-15 10:57:38 -0700145 for name in os.listxattr(src, follow_symlinks=follow_symlinks):
Larry Hastingsad5ae042012-07-14 17:55:11 -0700146 try:
Larry Hastingsb4038062012-07-15 10:57:38 -0700147 value = os.getxattr(src, name, follow_symlinks=follow_symlinks)
148 os.setxattr(dst, name, value, follow_symlinks=follow_symlinks)
Larry Hastingsad5ae042012-07-14 17:55:11 -0700149 except OSError as e:
150 if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA):
151 raise
152else:
153 def _copyxattr(*args, **kwargs):
154 pass
155
Larry Hastingsb4038062012-07-15 10:57:38 -0700156def copystat(src, dst, *, follow_symlinks=True):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100157 """Copy all stat info (mode bits, atime, mtime, flags) from src to dst.
158
Larry Hastingsb4038062012-07-15 10:57:38 -0700159 If the optional flag `follow_symlinks` is not set, symlinks aren't followed if and
Antoine Pitrou78091e62011-12-29 18:54:15 +0100160 only if both `src` and `dst` are symlinks.
161
162 """
Larry Hastings9cf065c2012-06-22 16:30:09 -0700163 def _nop(*args, ns=None, follow_symlinks=None):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100164 pass
165
Larry Hastings9cf065c2012-06-22 16:30:09 -0700166 # follow symlinks (aka don't not follow symlinks)
Larry Hastingsb4038062012-07-15 10:57:38 -0700167 follow = follow_symlinks or not (os.path.islink(src) and os.path.islink(dst))
Larry Hastings9cf065c2012-06-22 16:30:09 -0700168 if follow:
169 # use the real function if it exists
170 def lookup(name):
171 return getattr(os, name, _nop)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100172 else:
Larry Hastings9cf065c2012-06-22 16:30:09 -0700173 # use the real function only if it exists
174 # *and* it supports follow_symlinks
175 def lookup(name):
176 fn = getattr(os, name, _nop)
177 if fn in os.supports_follow_symlinks:
178 return fn
179 return _nop
Antoine Pitrou78091e62011-12-29 18:54:15 +0100180
Larry Hastings9cf065c2012-06-22 16:30:09 -0700181 st = lookup("stat")(src, follow_symlinks=follow)
Walter Dörwald294bbf32002-06-06 09:48:13 +0000182 mode = stat.S_IMODE(st.st_mode)
Larry Hastings9cf065c2012-06-22 16:30:09 -0700183 lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns),
184 follow_symlinks=follow)
185 try:
186 lookup("chmod")(dst, mode, follow_symlinks=follow)
187 except NotImplementedError:
188 # if we got a NotImplementedError, it's because
189 # * follow_symlinks=False,
190 # * lchown() is unavailable, and
191 # * either
192 # * fchownat() is unvailable or
193 # * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW.
194 # (it returned ENOSUP.)
195 # therefore we're out of options--we simply cannot chown the
196 # symlink. give up, suppress the error.
197 # (which is what shutil always did in this circumstance.)
198 pass
Antoine Pitrou78091e62011-12-29 18:54:15 +0100199 if hasattr(st, 'st_flags'):
Antoine Pitrou910bd512010-03-22 20:11:09 +0000200 try:
Larry Hastings9cf065c2012-06-22 16:30:09 -0700201 lookup("chflags")(dst, st.st_flags, follow_symlinks=follow)
Antoine Pitrou910bd512010-03-22 20:11:09 +0000202 except OSError as why:
Ned Deilybaf75712012-05-10 17:05:19 -0700203 for err in 'EOPNOTSUPP', 'ENOTSUP':
204 if hasattr(errno, err) and why.errno == getattr(errno, err):
205 break
206 else:
Antoine Pitrou910bd512010-03-22 20:11:09 +0000207 raise
Larry Hastingsb4038062012-07-15 10:57:38 -0700208 _copyxattr(src, dst, follow_symlinks=follow)
Antoine Pitrou424246f2012-05-12 19:02:01 +0200209
Larry Hastingsb4038062012-07-15 10:57:38 -0700210def copy(src, dst, *, follow_symlinks=True):
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500211 """Copy data and mode bits ("cp src dst"). Return the file's destination.
Tim Peters495ad3c2001-01-15 01:36:40 +0000212
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000213 The destination may be a directory.
214
Larry Hastingsb4038062012-07-15 10:57:38 -0700215 If follow_symlinks is false, symlinks won't be followed. This
Antoine Pitrou78091e62011-12-29 18:54:15 +0100216 resembles GNU's "cp -P src dst".
217
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000218 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000219 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000220 dst = os.path.join(dst, os.path.basename(src))
Larry Hastingsb4038062012-07-15 10:57:38 -0700221 copyfile(src, dst, follow_symlinks=follow_symlinks)
222 copymode(src, dst, follow_symlinks=follow_symlinks)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500223 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000224
Larry Hastingsb4038062012-07-15 10:57:38 -0700225def copy2(src, dst, *, follow_symlinks=True):
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500226 """Copy data and all stat info ("cp -p src dst"). Return the file's
227 destination."
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000228
229 The destination may be a directory.
230
Larry Hastingsb4038062012-07-15 10:57:38 -0700231 If follow_symlinks is false, symlinks won't be followed. This
Antoine Pitrou78091e62011-12-29 18:54:15 +0100232 resembles GNU's "cp -P src dst".
233
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000234 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000235 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000236 dst = os.path.join(dst, os.path.basename(src))
Larry Hastingsb4038062012-07-15 10:57:38 -0700237 copyfile(src, dst, follow_symlinks=follow_symlinks)
238 copystat(src, dst, follow_symlinks=follow_symlinks)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500239 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000240
Georg Brandl2ee470f2008-07-16 12:55:28 +0000241def ignore_patterns(*patterns):
242 """Function that can be used as copytree() ignore parameter.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000243
Georg Brandl2ee470f2008-07-16 12:55:28 +0000244 Patterns is a sequence of glob-style patterns
245 that are used to exclude files"""
246 def _ignore_patterns(path, names):
247 ignored_names = []
248 for pattern in patterns:
249 ignored_names.extend(fnmatch.filter(names, pattern))
250 return set(ignored_names)
251 return _ignore_patterns
252
Tarek Ziadéfb437512010-04-20 08:57:33 +0000253def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
254 ignore_dangling_symlinks=False):
Tarek Ziadé5340db32010-04-19 22:30:51 +0000255 """Recursively copy a directory tree.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000256
257 The destination directory must not already exist.
Neal Norwitza4c93b62003-02-23 21:36:32 +0000258 If exception(s) occur, an Error is raised with a list of reasons.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000259
260 If the optional symlinks flag is true, symbolic links in the
261 source tree result in symbolic links in the destination tree; if
262 it is false, the contents of the files pointed to by symbolic
Tarek Ziadéfb437512010-04-20 08:57:33 +0000263 links are copied. If the file pointed by the symlink doesn't
264 exist, an exception will be added in the list of errors raised in
265 an Error exception at the end of the copy process.
266
267 You can set the optional ignore_dangling_symlinks flag to true if you
Tarek Ziadé8c26c7d2010-04-23 13:03:50 +0000268 want to silence this exception. Notice that this has no effect on
269 platforms that don't support os.symlink.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000270
Georg Brandl2ee470f2008-07-16 12:55:28 +0000271 The optional ignore argument is a callable. If given, it
272 is called with the `src` parameter, which is the directory
273 being visited by copytree(), and `names` which is the list of
274 `src` contents, as returned by os.listdir():
275
276 callable(src, names) -> ignored_names
277
278 Since copytree() is called recursively, the callable will be
279 called once for each directory that is copied. It returns a
280 list of names relative to the `src` directory that should
281 not be copied.
282
Tarek Ziadé5340db32010-04-19 22:30:51 +0000283 The optional copy_function argument is a callable that will be used
284 to copy each file. It will be called with the source path and the
285 destination path as arguments. By default, copy2() is used, but any
286 function that supports the same signature (like copy()) can be used.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000287
288 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000289 names = os.listdir(src)
Georg Brandl2ee470f2008-07-16 12:55:28 +0000290 if ignore is not None:
291 ignored_names = ignore(src, names)
292 else:
293 ignored_names = set()
294
Johannes Gijsberse4172ea2005-01-08 12:31:29 +0000295 os.makedirs(dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000296 errors = []
Guido van Rossuma2baf461997-04-29 14:06:46 +0000297 for name in names:
Georg Brandl2ee470f2008-07-16 12:55:28 +0000298 if name in ignored_names:
299 continue
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000300 srcname = os.path.join(src, name)
301 dstname = os.path.join(dst, name)
302 try:
Tarek Ziadéfb437512010-04-20 08:57:33 +0000303 if os.path.islink(srcname):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000304 linkto = os.readlink(srcname)
Tarek Ziadéfb437512010-04-20 08:57:33 +0000305 if symlinks:
Antoine Pitrou78091e62011-12-29 18:54:15 +0100306 # We can't just leave it to `copy_function` because legacy
307 # code with a custom `copy_function` may rely on copytree
308 # doing the right thing.
Tarek Ziadéfb437512010-04-20 08:57:33 +0000309 os.symlink(linkto, dstname)
Larry Hastingsb4038062012-07-15 10:57:38 -0700310 copystat(srcname, dstname, follow_symlinks=not symlinks)
Tarek Ziadéfb437512010-04-20 08:57:33 +0000311 else:
312 # ignore dangling symlink if the flag is on
313 if not os.path.exists(linkto) and ignore_dangling_symlinks:
314 continue
315 # otherwise let the copy occurs. copy2 will raise an error
316 copy_function(srcname, dstname)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000317 elif os.path.isdir(srcname):
Tarek Ziadé5340db32010-04-19 22:30:51 +0000318 copytree(srcname, dstname, symlinks, ignore, copy_function)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000319 else:
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000320 # Will raise a SpecialFileError for unsupported file types
Tarek Ziadé5340db32010-04-19 22:30:51 +0000321 copy_function(srcname, dstname)
Georg Brandla1be88e2005-08-31 22:48:45 +0000322 # catch the Error from the recursive copytree so that we can
323 # continue with other files
Guido van Rossumb940e112007-01-10 16:19:56 +0000324 except Error as err:
Georg Brandla1be88e2005-08-31 22:48:45 +0000325 errors.extend(err.args[0])
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000326 except EnvironmentError as why:
327 errors.append((srcname, dstname, str(why)))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000328 try:
329 copystat(src, dst)
Guido van Rossumb940e112007-01-10 16:19:56 +0000330 except OSError as why:
Georg Brandl6aa2d1f2008-08-12 08:35:52 +0000331 if WindowsError is not None and isinstance(why, WindowsError):
332 # Copying file access times may fail on Windows
333 pass
334 else:
Georg Brandlc8076df2012-08-25 10:11:57 +0200335 errors.append((src, dst, str(why)))
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000336 if errors:
Collin Winterce36ad82007-08-30 01:19:48 +0000337 raise Error(errors)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500338 return dst
Guido van Rossumd7673291998-02-06 21:38:09 +0000339
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200340# version vulnerable to race conditions
341def _rmtree_unsafe(path, onerror):
Christian Heimes9bd667a2008-01-20 15:14:11 +0000342 try:
343 if os.path.islink(path):
344 # symlinks to directories are forbidden, see bug #1669
345 raise OSError("Cannot call rmtree on a symbolic link")
346 except OSError:
347 onerror(os.path.islink, path, sys.exc_info())
348 # can't continue even if onerror hook returns
349 return
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000350 names = []
351 try:
352 names = os.listdir(path)
Éric Araujocfcc9772011-08-10 20:54:33 +0200353 except os.error:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000354 onerror(os.listdir, path, sys.exc_info())
355 for name in names:
356 fullname = os.path.join(path, name)
357 try:
358 mode = os.lstat(fullname).st_mode
359 except os.error:
360 mode = 0
361 if stat.S_ISDIR(mode):
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200362 _rmtree_unsafe(fullname, onerror)
Barry Warsaw234d9a92003-01-24 17:36:15 +0000363 else:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000364 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200365 os.unlink(fullname)
Éric Araujocfcc9772011-08-10 20:54:33 +0200366 except os.error:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200367 onerror(os.unlink, fullname, sys.exc_info())
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000368 try:
369 os.rmdir(path)
370 except os.error:
371 onerror(os.rmdir, path, sys.exc_info())
Guido van Rossumd7673291998-02-06 21:38:09 +0000372
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200373# Version using fd-based APIs to protect against races
374def _rmtree_safe_fd(topfd, path, onerror):
375 names = []
376 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200377 names = os.listdir(topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100378 except OSError as err:
379 err.filename = path
Hynek Schlawack2100b422012-06-23 20:28:32 +0200380 onerror(os.listdir, path, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200381 for name in names:
382 fullname = os.path.join(path, name)
383 try:
Hynek Schlawacka75cd1c2012-06-28 12:07:29 +0200384 orig_st = os.stat(name, dir_fd=topfd, follow_symlinks=False)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200385 mode = orig_st.st_mode
Hynek Schlawackb5501102012-12-10 09:11:25 +0100386 except OSError:
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200387 mode = 0
388 if stat.S_ISDIR(mode):
389 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200390 dirfd = os.open(name, os.O_RDONLY, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100391 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200392 onerror(os.open, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200393 else:
394 try:
395 if os.path.samestat(orig_st, os.fstat(dirfd)):
396 _rmtree_safe_fd(dirfd, fullname, onerror)
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200397 try:
398 os.rmdir(name, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100399 except OSError:
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200400 onerror(os.rmdir, fullname, sys.exc_info())
Hynek Schlawackb5501102012-12-10 09:11:25 +0100401 else:
402 try:
403 # This can only happen if someone replaces
404 # a directory with a symlink after the call to
405 # stat.S_ISDIR above.
406 raise OSError("Cannot call rmtree on a symbolic "
407 "link")
408 except OSError:
409 onerror(os.path.islink, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200410 finally:
411 os.close(dirfd)
412 else:
413 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200414 os.unlink(name, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100415 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200416 onerror(os.unlink, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200417
Hynek Schlawackd0f6e0a2012-06-29 08:28:20 +0200418_use_fd_functions = ({os.open, os.stat, os.unlink, os.rmdir} <=
419 os.supports_dir_fd and
420 os.listdir in os.supports_fd and
421 os.stat in os.supports_follow_symlinks)
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000422
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200423def rmtree(path, ignore_errors=False, onerror=None):
424 """Recursively delete a directory tree.
425
426 If ignore_errors is set, errors are ignored; otherwise, if onerror
427 is set, it is called to handle the error with arguments (func,
Hynek Schlawack2100b422012-06-23 20:28:32 +0200428 path, exc_info) where func is platform and implementation dependent;
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200429 path is the argument to that function that caused it to fail; and
430 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
431 is false and onerror is None, an exception is raised.
432
433 """
434 if ignore_errors:
435 def onerror(*args):
436 pass
437 elif onerror is None:
438 def onerror(*args):
439 raise
440 if _use_fd_functions:
Hynek Schlawack3b527782012-06-25 13:27:31 +0200441 # While the unsafe rmtree works fine on bytes, the fd based does not.
442 if isinstance(path, bytes):
443 path = os.fsdecode(path)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200444 # Note: To guard against symlink races, we use the standard
445 # lstat()/open()/fstat() trick.
446 try:
447 orig_st = os.lstat(path)
448 except Exception:
449 onerror(os.lstat, path, sys.exc_info())
450 return
451 try:
452 fd = os.open(path, os.O_RDONLY)
453 except Exception:
454 onerror(os.lstat, path, sys.exc_info())
455 return
456 try:
Hynek Schlawackb5501102012-12-10 09:11:25 +0100457 if os.path.samestat(orig_st, os.fstat(fd)):
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200458 _rmtree_safe_fd(fd, path, onerror)
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200459 try:
460 os.rmdir(path)
461 except os.error:
462 onerror(os.rmdir, path, sys.exc_info())
Hynek Schlawacka75cd1c2012-06-28 12:07:29 +0200463 else:
Hynek Schlawackb5501102012-12-10 09:11:25 +0100464 try:
465 # symlinks to directories are forbidden, see bug #1669
466 raise OSError("Cannot call rmtree on a symbolic link")
467 except OSError:
468 onerror(os.path.islink, path, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200469 finally:
470 os.close(fd)
471 else:
472 return _rmtree_unsafe(path, onerror)
473
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000474# Allow introspection of whether or not the hardening against symlink
475# attacks is supported on the current platform
476rmtree.avoids_symlink_attacks = _use_fd_functions
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000477
Christian Heimesada8c3b2008-03-18 18:26:33 +0000478def _basename(path):
479 # A basename() variant which first strips the trailing slash, if present.
480 # Thus we always get the last component of the path, even for directories.
481 return os.path.basename(path.rstrip(os.path.sep))
482
483def move(src, dst):
484 """Recursively move a file or directory to another location. This is
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500485 similar to the Unix "mv" command. Return the file or directory's
486 destination.
Christian Heimesada8c3b2008-03-18 18:26:33 +0000487
488 If the destination is a directory or a symlink to a directory, the source
489 is moved inside the directory. The destination path must not already
490 exist.
491
492 If the destination already exists but is not a directory, it may be
493 overwritten depending on os.rename() semantics.
494
495 If the destination is on our current filesystem, then rename() is used.
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +0100496 Otherwise, src is copied to the destination and then removed. Symlinks are
497 recreated under the new name if os.rename() fails because of cross
498 filesystem renames.
499
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000500 A lot more could be done here... A look at a mv.c shows a lot of
501 the issues this implementation glosses over.
502
503 """
Christian Heimesada8c3b2008-03-18 18:26:33 +0000504 real_dst = dst
505 if os.path.isdir(dst):
Ronald Oussorenf51738b2011-05-06 10:23:04 +0200506 if _samefile(src, dst):
507 # We might be on a case insensitive filesystem,
508 # perform the rename anyway.
509 os.rename(src, dst)
510 return
511
Christian Heimesada8c3b2008-03-18 18:26:33 +0000512 real_dst = os.path.join(dst, _basename(src))
513 if os.path.exists(real_dst):
514 raise Error("Destination path '%s' already exists" % real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000515 try:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000516 os.rename(src, real_dst)
Éric Araujocfcc9772011-08-10 20:54:33 +0200517 except OSError:
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +0100518 if os.path.islink(src):
519 linkto = os.readlink(src)
520 os.symlink(linkto, real_dst)
521 os.unlink(src)
522 elif os.path.isdir(src):
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000523 if _destinsrc(src, dst):
Collin Winterce36ad82007-08-30 01:19:48 +0000524 raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst))
Christian Heimesada8c3b2008-03-18 18:26:33 +0000525 copytree(src, real_dst, symlinks=True)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000526 rmtree(src)
527 else:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000528 copy2(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000529 os.unlink(src)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500530 return real_dst
Brett Cannon1c3fa182004-06-19 21:11:35 +0000531
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000532def _destinsrc(src, dst):
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +0000533 src = abspath(src)
534 dst = abspath(dst)
535 if not src.endswith(os.path.sep):
536 src += os.path.sep
537 if not dst.endswith(os.path.sep):
538 dst += os.path.sep
539 return dst.startswith(src)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000540
541def _get_gid(name):
542 """Returns a gid, given a group name."""
543 if getgrnam is None or name is None:
544 return None
545 try:
546 result = getgrnam(name)
547 except KeyError:
548 result = None
549 if result is not None:
550 return result[2]
551 return None
552
553def _get_uid(name):
554 """Returns an uid, given a user name."""
555 if getpwnam is None or name is None:
556 return None
557 try:
558 result = getpwnam(name)
559 except KeyError:
560 result = None
561 if result is not None:
562 return result[2]
563 return None
564
565def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
566 owner=None, group=None, logger=None):
567 """Create a (possibly compressed) tar file from all the files under
568 'base_dir'.
569
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000570 'compress' must be "gzip" (the default), "bzip2", or None.
Tarek Ziadé396fad72010-02-23 05:30:31 +0000571
572 'owner' and 'group' can be used to define an owner and a group for the
573 archive that is being built. If not provided, the current owner and group
574 will be used.
575
Éric Araujo4433a5f2010-12-15 20:26:30 +0000576 The output tar file will be named 'base_name' + ".tar", possibly plus
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000577 the appropriate compression extension (".gz", or ".bz2").
Tarek Ziadé396fad72010-02-23 05:30:31 +0000578
579 Returns the output filename.
580 """
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000581 tar_compression = {'gzip': 'gz', None: ''}
582 compress_ext = {'gzip': '.gz'}
583
584 if _BZ2_SUPPORTED:
585 tar_compression['bzip2'] = 'bz2'
586 compress_ext['bzip2'] = '.bz2'
Tarek Ziadé396fad72010-02-23 05:30:31 +0000587
588 # flags for compression program, each element of list will be an argument
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200589 if compress is not None and compress not in compress_ext:
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000590 raise ValueError("bad value for 'compress', or compression format not "
591 "supported : {0}".format(compress))
Tarek Ziadé396fad72010-02-23 05:30:31 +0000592
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000593 archive_name = base_name + '.tar' + compress_ext.get(compress, '')
Tarek Ziadé396fad72010-02-23 05:30:31 +0000594 archive_dir = os.path.dirname(archive_name)
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000595
Tarek Ziadé396fad72010-02-23 05:30:31 +0000596 if not os.path.exists(archive_dir):
Éric Araujoac4e58e2011-01-29 20:32:11 +0000597 if logger is not None:
Éric Araujo43a7ee12011-08-19 02:55:11 +0200598 logger.info("creating %s", archive_dir)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000599 if not dry_run:
600 os.makedirs(archive_dir)
601
Tarek Ziadé396fad72010-02-23 05:30:31 +0000602 # creating the tarball
Tarek Ziadé396fad72010-02-23 05:30:31 +0000603 if logger is not None:
604 logger.info('Creating tar archive')
605
606 uid = _get_uid(owner)
607 gid = _get_gid(group)
608
609 def _set_uid_gid(tarinfo):
610 if gid is not None:
611 tarinfo.gid = gid
612 tarinfo.gname = group
613 if uid is not None:
614 tarinfo.uid = uid
615 tarinfo.uname = owner
616 return tarinfo
617
618 if not dry_run:
619 tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress])
620 try:
621 tar.add(base_dir, filter=_set_uid_gid)
622 finally:
623 tar.close()
624
Tarek Ziadé396fad72010-02-23 05:30:31 +0000625 return archive_name
626
Tarek Ziadée2124162010-04-21 13:35:21 +0000627def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False):
Tarek Ziadé396fad72010-02-23 05:30:31 +0000628 # XXX see if we want to keep an external call here
629 if verbose:
630 zipoptions = "-r"
631 else:
632 zipoptions = "-rq"
633 from distutils.errors import DistutilsExecError
634 from distutils.spawn import spawn
635 try:
636 spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run)
637 except DistutilsExecError:
638 # XXX really should distinguish between "couldn't find
639 # external 'zip' command" and "zip failed".
640 raise ExecError("unable to create zip file '%s': "
641 "could neither import the 'zipfile' module nor "
642 "find a standalone zip utility") % zip_filename
643
644def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
645 """Create a zip file from all the files under 'base_dir'.
646
Éric Araujo4433a5f2010-12-15 20:26:30 +0000647 The output zip file will be named 'base_name' + ".zip". Uses either the
Tarek Ziadé396fad72010-02-23 05:30:31 +0000648 "zipfile" Python module (if available) or the InfoZIP "zip" utility
649 (if installed and found on the default search path). If neither tool is
650 available, raises ExecError. Returns the name of the output zip
651 file.
652 """
653 zip_filename = base_name + ".zip"
654 archive_dir = os.path.dirname(base_name)
655
656 if not os.path.exists(archive_dir):
657 if logger is not None:
658 logger.info("creating %s", archive_dir)
659 if not dry_run:
660 os.makedirs(archive_dir)
661
662 # If zipfile module is not available, try spawning an external 'zip'
663 # command.
664 try:
665 import zipfile
666 except ImportError:
667 zipfile = None
668
669 if zipfile is None:
Tarek Ziadée2124162010-04-21 13:35:21 +0000670 _call_external_zip(base_dir, zip_filename, verbose, dry_run)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000671 else:
672 if logger is not None:
673 logger.info("creating '%s' and adding '%s' to it",
674 zip_filename, base_dir)
675
676 if not dry_run:
677 zip = zipfile.ZipFile(zip_filename, "w",
678 compression=zipfile.ZIP_DEFLATED)
679
680 for dirpath, dirnames, filenames in os.walk(base_dir):
681 for name in filenames:
682 path = os.path.normpath(os.path.join(dirpath, name))
683 if os.path.isfile(path):
684 zip.write(path, path)
685 if logger is not None:
686 logger.info("adding '%s'", path)
687 zip.close()
688
689 return zip_filename
690
691_ARCHIVE_FORMATS = {
692 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"),
Tarek Ziadé396fad72010-02-23 05:30:31 +0000693 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"),
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200694 'zip': (_make_zipfile, [], "ZIP file")
Tarek Ziadé396fad72010-02-23 05:30:31 +0000695 }
696
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000697if _BZ2_SUPPORTED:
698 _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')],
699 "bzip2'ed tar-file")
700
Tarek Ziadé396fad72010-02-23 05:30:31 +0000701def get_archive_formats():
702 """Returns a list of supported formats for archiving and unarchiving.
703
704 Each element of the returned sequence is a tuple (name, description)
705 """
706 formats = [(name, registry[2]) for name, registry in
707 _ARCHIVE_FORMATS.items()]
708 formats.sort()
709 return formats
710
711def register_archive_format(name, function, extra_args=None, description=''):
712 """Registers an archive format.
713
714 name is the name of the format. function is the callable that will be
715 used to create archives. If provided, extra_args is a sequence of
716 (name, value) tuples that will be passed as arguments to the callable.
717 description can be provided to describe the format, and will be returned
718 by the get_archive_formats() function.
719 """
720 if extra_args is None:
721 extra_args = []
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200722 if not callable(function):
Tarek Ziadé396fad72010-02-23 05:30:31 +0000723 raise TypeError('The %s object is not callable' % function)
724 if not isinstance(extra_args, (tuple, list)):
725 raise TypeError('extra_args needs to be a sequence')
726 for element in extra_args:
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200727 if not isinstance(element, (tuple, list)) or len(element) !=2:
Tarek Ziadé396fad72010-02-23 05:30:31 +0000728 raise TypeError('extra_args elements are : (arg_name, value)')
729
730 _ARCHIVE_FORMATS[name] = (function, extra_args, description)
731
732def unregister_archive_format(name):
733 del _ARCHIVE_FORMATS[name]
734
735def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
736 dry_run=0, owner=None, group=None, logger=None):
737 """Create an archive file (eg. zip or tar).
738
739 'base_name' is the name of the file to create, minus any format-specific
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000740 extension; 'format' is the archive format: one of "zip", "tar", "bztar"
741 or "gztar".
Tarek Ziadé396fad72010-02-23 05:30:31 +0000742
743 'root_dir' is a directory that will be the root directory of the
744 archive; ie. we typically chdir into 'root_dir' before creating the
745 archive. 'base_dir' is the directory where we start archiving from;
746 ie. 'base_dir' will be the common prefix of all files and
747 directories in the archive. 'root_dir' and 'base_dir' both default
748 to the current directory. Returns the name of the archive file.
749
750 'owner' and 'group' are used when creating a tar archive. By default,
751 uses the current owner and group.
752 """
753 save_cwd = os.getcwd()
754 if root_dir is not None:
755 if logger is not None:
756 logger.debug("changing into '%s'", root_dir)
757 base_name = os.path.abspath(base_name)
758 if not dry_run:
759 os.chdir(root_dir)
760
761 if base_dir is None:
762 base_dir = os.curdir
763
764 kwargs = {'dry_run': dry_run, 'logger': logger}
765
766 try:
767 format_info = _ARCHIVE_FORMATS[format]
768 except KeyError:
769 raise ValueError("unknown archive format '%s'" % format)
770
771 func = format_info[0]
772 for arg, val in format_info[1]:
773 kwargs[arg] = val
774
775 if format != 'zip':
776 kwargs['owner'] = owner
777 kwargs['group'] = group
778
779 try:
780 filename = func(base_name, base_dir, **kwargs)
781 finally:
782 if root_dir is not None:
783 if logger is not None:
784 logger.debug("changing back to '%s'", save_cwd)
785 os.chdir(save_cwd)
786
787 return filename
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000788
789
790def get_unpack_formats():
791 """Returns a list of supported formats for unpacking.
792
793 Each element of the returned sequence is a tuple
794 (name, extensions, description)
795 """
796 formats = [(name, info[0], info[3]) for name, info in
797 _UNPACK_FORMATS.items()]
798 formats.sort()
799 return formats
800
801def _check_unpack_options(extensions, function, extra_args):
802 """Checks what gets registered as an unpacker."""
803 # first make sure no other unpacker is registered for this extension
804 existing_extensions = {}
805 for name, info in _UNPACK_FORMATS.items():
806 for ext in info[0]:
807 existing_extensions[ext] = name
808
809 for extension in extensions:
810 if extension in existing_extensions:
811 msg = '%s is already registered for "%s"'
812 raise RegistryError(msg % (extension,
813 existing_extensions[extension]))
814
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200815 if not callable(function):
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000816 raise TypeError('The registered function must be a callable')
817
818
819def register_unpack_format(name, extensions, function, extra_args=None,
820 description=''):
821 """Registers an unpack format.
822
823 `name` is the name of the format. `extensions` is a list of extensions
824 corresponding to the format.
825
826 `function` is the callable that will be
827 used to unpack archives. The callable will receive archives to unpack.
828 If it's unable to handle an archive, it needs to raise a ReadError
829 exception.
830
831 If provided, `extra_args` is a sequence of
832 (name, value) tuples that will be passed as arguments to the callable.
833 description can be provided to describe the format, and will be returned
834 by the get_unpack_formats() function.
835 """
836 if extra_args is None:
837 extra_args = []
838 _check_unpack_options(extensions, function, extra_args)
839 _UNPACK_FORMATS[name] = extensions, function, extra_args, description
840
841def unregister_unpack_format(name):
842 """Removes the pack format from the registery."""
843 del _UNPACK_FORMATS[name]
844
845def _ensure_directory(path):
846 """Ensure that the parent directory of `path` exists"""
847 dirname = os.path.dirname(path)
848 if not os.path.isdir(dirname):
849 os.makedirs(dirname)
850
851def _unpack_zipfile(filename, extract_dir):
852 """Unpack zip `filename` to `extract_dir`
853 """
854 try:
855 import zipfile
856 except ImportError:
857 raise ReadError('zlib not supported, cannot unpack this archive.')
858
859 if not zipfile.is_zipfile(filename):
860 raise ReadError("%s is not a zip file" % filename)
861
862 zip = zipfile.ZipFile(filename)
863 try:
864 for info in zip.infolist():
865 name = info.filename
866
867 # don't extract absolute paths or ones with .. in them
868 if name.startswith('/') or '..' in name:
869 continue
870
871 target = os.path.join(extract_dir, *name.split('/'))
872 if not target:
873 continue
874
875 _ensure_directory(target)
876 if not name.endswith('/'):
877 # file
878 data = zip.read(info.filename)
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200879 f = open(target, 'wb')
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000880 try:
881 f.write(data)
882 finally:
883 f.close()
884 del data
885 finally:
886 zip.close()
887
888def _unpack_tarfile(filename, extract_dir):
889 """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir`
890 """
891 try:
892 tarobj = tarfile.open(filename)
893 except tarfile.TarError:
894 raise ReadError(
895 "%s is not a compressed or uncompressed tar file" % filename)
896 try:
897 tarobj.extractall(extract_dir)
898 finally:
899 tarobj.close()
900
901_UNPACK_FORMATS = {
902 'gztar': (['.tar.gz', '.tgz'], _unpack_tarfile, [], "gzip'ed tar-file"),
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000903 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"),
904 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file")
905 }
906
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000907if _BZ2_SUPPORTED:
908 _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [],
909 "bzip2'ed tar-file")
910
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000911def _find_unpack_format(filename):
912 for name, info in _UNPACK_FORMATS.items():
913 for extension in info[0]:
914 if filename.endswith(extension):
915 return name
916 return None
917
918def unpack_archive(filename, extract_dir=None, format=None):
919 """Unpack an archive.
920
921 `filename` is the name of the archive.
922
923 `extract_dir` is the name of the target directory, where the archive
924 is unpacked. If not provided, the current working directory is used.
925
926 `format` is the archive format: one of "zip", "tar", or "gztar". Or any
927 other registered format. If not provided, unpack_archive will use the
928 filename extension and see if an unpacker was registered for that
929 extension.
930
931 In case none is found, a ValueError is raised.
932 """
933 if extract_dir is None:
934 extract_dir = os.getcwd()
935
936 if format is not None:
937 try:
938 format_info = _UNPACK_FORMATS[format]
939 except KeyError:
940 raise ValueError("Unknown unpack format '{0}'".format(format))
941
Nick Coghlanabf202d2011-03-16 13:52:20 -0400942 func = format_info[1]
943 func(filename, extract_dir, **dict(format_info[2]))
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000944 else:
945 # we need to look at the registered unpackers supported extensions
946 format = _find_unpack_format(filename)
947 if format is None:
948 raise ReadError("Unknown archive format '{0}'".format(filename))
949
950 func = _UNPACK_FORMATS[format][1]
951 kwargs = dict(_UNPACK_FORMATS[format][2])
952 func(filename, extract_dir, **kwargs)
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +0200953
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200954
955if hasattr(os, 'statvfs'):
956
957 __all__.append('disk_usage')
958 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +0200959
960 def disk_usage(path):
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200961 """Return disk usage statistics about the given path.
962
Sandro Tosif8ae4fa2012-04-23 20:07:15 +0200963 Returned value is a named tuple with attributes 'total', 'used' and
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200964 'free', which are the amount of total, used and free space, in bytes.
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +0200965 """
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200966 st = os.statvfs(path)
967 free = st.f_bavail * st.f_frsize
968 total = st.f_blocks * st.f_frsize
969 used = (st.f_blocks - st.f_bfree) * st.f_frsize
970 return _ntuple_diskusage(total, used, free)
971
972elif os.name == 'nt':
973
974 import nt
975 __all__.append('disk_usage')
976 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
977
978 def disk_usage(path):
979 """Return disk usage statistics about the given path.
980
981 Returned valus is a named tuple with attributes 'total', 'used' and
982 'free', which are the amount of total, used and free space, in bytes.
983 """
984 total, free = nt._getdiskusage(path)
985 used = total - free
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +0200986 return _ntuple_diskusage(total, used, free)
Sandro Tosid902a142011-08-22 23:28:27 +0200987
Éric Araujo0ac4a5d2011-09-01 08:31:51 +0200988
Sandro Tosid902a142011-08-22 23:28:27 +0200989def chown(path, user=None, group=None):
990 """Change owner user and group of the given path.
991
992 user and group can be the uid/gid or the user/group names, and in that case,
993 they are converted to their respective uid/gid.
994 """
995
996 if user is None and group is None:
997 raise ValueError("user and/or group must be set")
998
999 _user = user
1000 _group = group
1001
1002 # -1 means don't change it
1003 if user is None:
1004 _user = -1
1005 # user can either be an int (the uid) or a string (the system username)
1006 elif isinstance(user, str):
1007 _user = _get_uid(user)
1008 if _user is None:
1009 raise LookupError("no such user: {!r}".format(user))
1010
1011 if group is None:
1012 _group = -1
1013 elif not isinstance(group, int):
1014 _group = _get_gid(group)
1015 if _group is None:
1016 raise LookupError("no such group: {!r}".format(group))
1017
1018 os.chown(path, _user, _group)
Antoine Pitroubcf2b592012-02-08 23:28:36 +01001019
1020def get_terminal_size(fallback=(80, 24)):
1021 """Get the size of the terminal window.
1022
1023 For each of the two dimensions, the environment variable, COLUMNS
1024 and LINES respectively, is checked. If the variable is defined and
1025 the value is a positive integer, it is used.
1026
1027 When COLUMNS or LINES is not defined, which is the common case,
1028 the terminal connected to sys.__stdout__ is queried
1029 by invoking os.get_terminal_size.
1030
1031 If the terminal size cannot be successfully queried, either because
1032 the system doesn't support querying, or because we are not
1033 connected to a terminal, the value given in fallback parameter
1034 is used. Fallback defaults to (80, 24) which is the default
1035 size used by many terminal emulators.
1036
1037 The value returned is a named tuple of type os.terminal_size.
1038 """
1039 # columns, lines are the working values
1040 try:
1041 columns = int(os.environ['COLUMNS'])
1042 except (KeyError, ValueError):
1043 columns = 0
1044
1045 try:
1046 lines = int(os.environ['LINES'])
1047 except (KeyError, ValueError):
1048 lines = 0
1049
1050 # only query if necessary
1051 if columns <= 0 or lines <= 0:
1052 try:
1053 size = os.get_terminal_size(sys.__stdout__.fileno())
1054 except (NameError, OSError):
1055 size = os.terminal_size(fallback)
1056 if columns <= 0:
1057 columns = size.columns
1058 if lines <= 0:
1059 lines = size.lines
1060
1061 return os.terminal_size((columns, lines))
Brian Curtinc57a3452012-06-22 16:00:30 -05001062
1063def which(cmd, mode=os.F_OK | os.X_OK, path=None):
Brian Curtindc00f1e2012-06-22 22:49:12 -05001064 """Given a command, mode, and a PATH string, return the path which
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001065 conforms to the given mode on the PATH, or None if there is no such
1066 file.
1067
1068 `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
1069 of os.environ.get("PATH"), or can be overridden with a custom search
1070 path.
1071
1072 """
Brian Curtinc57a3452012-06-22 16:00:30 -05001073 # Check that a given file can be accessed with the correct mode.
1074 # Additionally check that `file` is not a directory, as on Windows
1075 # directories pass the os.access check.
1076 def _access_check(fn, mode):
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001077 return (os.path.exists(fn) and os.access(fn, mode)
1078 and not os.path.isdir(fn))
Brian Curtinc57a3452012-06-22 16:00:30 -05001079
Serhiy Storchaka8bea2002013-01-23 10:44:21 +02001080 # If we're given a path with a directory part, look it up directly rather
1081 # than referring to PATH directories. This includes checking relative to the
1082 # current directory, e.g. ./script
1083 if os.path.dirname(cmd):
1084 if _access_check(cmd, mode):
1085 return cmd
1086 return None
Brian Curtinc57a3452012-06-22 16:00:30 -05001087
1088 path = (path or os.environ.get("PATH", os.defpath)).split(os.pathsep)
1089
1090 if sys.platform == "win32":
1091 # The current directory takes precedence on Windows.
1092 if not os.curdir in path:
1093 path.insert(0, os.curdir)
1094
1095 # PATHEXT is necessary to check on Windows.
1096 pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
1097 # See if the given file matches any of the expected path extensions.
1098 # This will allow us to short circuit when given "python.exe".
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001099 # If it does match, only test that one, otherwise we have to try
1100 # others.
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001101 if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
1102 files = [cmd]
1103 else:
1104 files = [cmd + ext for ext in pathext]
Brian Curtinc57a3452012-06-22 16:00:30 -05001105 else:
1106 # On other platforms you don't have things like PATHEXT to tell you
1107 # what file suffixes are executable, so just pass on cmd as-is.
1108 files = [cmd]
1109
1110 seen = set()
1111 for dir in path:
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001112 normdir = os.path.normcase(dir)
1113 if not normdir in seen:
1114 seen.add(normdir)
Brian Curtinc57a3452012-06-22 16:00:30 -05001115 for thefile in files:
1116 name = os.path.join(dir, thefile)
1117 if _access_check(name, mode):
1118 return name
1119 return None