blob: fc6fb4edd24c15dab829eac3ea9005fc341c4f2a [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
Georg Brandl2ee470f2008-07-16 12:55:28 +000010import fnmatch
Tarek Ziadé396fad72010-02-23 05:30:31 +000011import collections
Antoine Pitrou910bd512010-03-22 20:11:09 +000012import errno
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +020013
14try:
15 import zlib
16 del zlib
17 _ZLIB_SUPPORTED = True
18except ImportError:
19 _ZLIB_SUPPORTED = False
Tarek Ziadé396fad72010-02-23 05:30:31 +000020
21try:
Tarek Ziadéffa155a2010-04-29 13:34:35 +000022 import bz2
Florent Xicluna54540ec2011-11-04 08:29:17 +010023 del bz2
Tarek Ziadéffa155a2010-04-29 13:34:35 +000024 _BZ2_SUPPORTED = True
Brett Cannoncd171c82013-07-04 17:43:24 -040025except ImportError:
Tarek Ziadéffa155a2010-04-29 13:34:35 +000026 _BZ2_SUPPORTED = False
27
28try:
Serhiy Storchaka11213772014-08-06 18:50:19 +030029 import lzma
30 del lzma
31 _LZMA_SUPPORTED = True
32except ImportError:
33 _LZMA_SUPPORTED = False
34
35try:
Tarek Ziadé396fad72010-02-23 05:30:31 +000036 from pwd import getpwnam
Brett Cannoncd171c82013-07-04 17:43:24 -040037except ImportError:
Tarek Ziadé396fad72010-02-23 05:30:31 +000038 getpwnam = None
39
40try:
41 from grp import getgrnam
Brett Cannoncd171c82013-07-04 17:43:24 -040042except ImportError:
Tarek Ziadé396fad72010-02-23 05:30:31 +000043 getgrnam = None
Guido van Rossumc6360141990-10-13 19:23:40 +000044
Tarek Ziadéc3399782010-02-23 05:39:18 +000045__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
46 "copytree", "move", "rmtree", "Error", "SpecialFileError",
47 "ExecError", "make_archive", "get_archive_formats",
Tarek Ziadé6ac91722010-04-28 17:51:36 +000048 "register_archive_format", "unregister_archive_format",
49 "get_unpack_formats", "register_unpack_format",
Éric Araujoc5efe652011-08-21 14:30:00 +020050 "unregister_unpack_format", "unpack_archive",
Berker Peksag8083cd62014-11-01 11:04:06 +020051 "ignore_patterns", "chown", "which", "get_terminal_size",
52 "SameFileError"]
Éric Araujoe4d5b8e2011-08-08 16:51:11 +020053 # disk_usage is added later, if available on the platform
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000054
Andrew Svetlov3438fa42012-12-17 23:35:18 +020055class Error(OSError):
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000056 pass
Guido van Rossumc6360141990-10-13 19:23:40 +000057
Hynek Schlawack48653762012-10-07 12:49:58 +020058class SameFileError(Error):
59 """Raised when source and destination are the same file."""
60
Andrew Svetlov3438fa42012-12-17 23:35:18 +020061class SpecialFileError(OSError):
Antoine Pitrou7fff0962009-05-01 21:09:44 +000062 """Raised when trying to do a kind of operation (e.g. copying) which is
63 not supported on a special file (e.g. a named pipe)"""
64
Andrew Svetlov3438fa42012-12-17 23:35:18 +020065class ExecError(OSError):
Tarek Ziadé396fad72010-02-23 05:30:31 +000066 """Raised when a command could not be executed"""
67
Andrew Svetlov3438fa42012-12-17 23:35:18 +020068class ReadError(OSError):
Tarek Ziadé6ac91722010-04-28 17:51:36 +000069 """Raised when an archive cannot be read"""
70
71class RegistryError(Exception):
Ezio Melotti30b9d5d2013-08-17 15:50:46 +030072 """Raised when a registry operation with the archiving
Raymond Hettinger15f44ab2016-08-30 10:47:49 -070073 and unpacking registries fails"""
Tarek Ziadé6ac91722010-04-28 17:51:36 +000074
75
Greg Stein42bb8b32000-07-12 09:55:30 +000076def copyfileobj(fsrc, fdst, length=16*1024):
77 """copy data from file-like object fsrc to file-like object fdst"""
78 while 1:
79 buf = fsrc.read(length)
80 if not buf:
81 break
82 fdst.write(buf)
83
Johannes Gijsbers46f14592004-08-14 13:30:02 +000084def _samefile(src, dst):
85 # Macintosh, Unix.
Tarek Ziadé1eab9cc2010-04-19 21:19:57 +000086 if hasattr(os.path, 'samefile'):
Johannes Gijsbersf9a098e2004-08-14 14:51:01 +000087 try:
88 return os.path.samefile(src, dst)
89 except OSError:
90 return False
Johannes Gijsbers46f14592004-08-14 13:30:02 +000091
92 # All other platforms: check for same pathname.
93 return (os.path.normcase(os.path.abspath(src)) ==
94 os.path.normcase(os.path.abspath(dst)))
Tim Peters495ad3c2001-01-15 01:36:40 +000095
Larry Hastingsb4038062012-07-15 10:57:38 -070096def copyfile(src, dst, *, follow_symlinks=True):
Antoine Pitrou78091e62011-12-29 18:54:15 +010097 """Copy data from src to dst.
98
Larry Hastingsb4038062012-07-15 10:57:38 -070099 If follow_symlinks is not set and src is a symbolic link, a new
Antoine Pitrou78091e62011-12-29 18:54:15 +0100100 symlink will be created instead of copying the file it points to.
101
102 """
Johannes Gijsbers46f14592004-08-14 13:30:02 +0000103 if _samefile(src, dst):
Hynek Schlawack48653762012-10-07 12:49:58 +0200104 raise SameFileError("{!r} and {!r} are the same file".format(src, dst))
Johannes Gijsbers46f14592004-08-14 13:30:02 +0000105
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000106 for fn in [src, dst]:
107 try:
108 st = os.stat(fn)
109 except OSError:
110 # File most likely does not exist
111 pass
Benjamin Petersonc0d98aa2009-06-05 19:13:27 +0000112 else:
113 # XXX What about other special files? (sockets, devices...)
114 if stat.S_ISFIFO(st.st_mode):
115 raise SpecialFileError("`%s` is a named pipe" % fn)
Tarek Ziadéb01142b2010-05-05 22:43:04 +0000116
Larry Hastingsb4038062012-07-15 10:57:38 -0700117 if not follow_symlinks and os.path.islink(src):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100118 os.symlink(os.readlink(src), dst)
119 else:
120 with open(src, 'rb') as fsrc:
121 with open(dst, 'wb') as fdst:
122 copyfileobj(fsrc, fdst)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500123 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000124
Larry Hastingsb4038062012-07-15 10:57:38 -0700125def copymode(src, dst, *, follow_symlinks=True):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100126 """Copy mode bits from src to dst.
Guido van Rossumc6360141990-10-13 19:23:40 +0000127
Larry Hastingsb4038062012-07-15 10:57:38 -0700128 If follow_symlinks is not set, symlinks aren't followed if and only
129 if both `src` and `dst` are symlinks. If `lchmod` isn't available
130 (e.g. Linux) this method does nothing.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100131
132 """
Larry Hastingsb4038062012-07-15 10:57:38 -0700133 if not follow_symlinks and os.path.islink(src) and os.path.islink(dst):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100134 if hasattr(os, 'lchmod'):
135 stat_func, chmod_func = os.lstat, os.lchmod
136 else:
137 return
138 elif hasattr(os, 'chmod'):
139 stat_func, chmod_func = os.stat, os.chmod
140 else:
141 return
142
143 st = stat_func(src)
144 chmod_func(dst, stat.S_IMODE(st.st_mode))
145
Larry Hastingsad5ae042012-07-14 17:55:11 -0700146if hasattr(os, 'listxattr'):
Larry Hastingsb4038062012-07-15 10:57:38 -0700147 def _copyxattr(src, dst, *, follow_symlinks=True):
Larry Hastingsad5ae042012-07-14 17:55:11 -0700148 """Copy extended filesystem attributes from `src` to `dst`.
149
150 Overwrite existing attributes.
151
Larry Hastingsb4038062012-07-15 10:57:38 -0700152 If `follow_symlinks` is false, symlinks won't be followed.
Larry Hastingsad5ae042012-07-14 17:55:11 -0700153
154 """
155
Hynek Schlawack0beab052013-02-05 08:22:44 +0100156 try:
157 names = os.listxattr(src, follow_symlinks=follow_symlinks)
158 except OSError as e:
Miss Islington (bot)f1487b32019-05-29 22:58:30 -0700159 if e.errno not in (errno.ENOTSUP, errno.ENODATA, errno.EINVAL):
Hynek Schlawack0beab052013-02-05 08:22:44 +0100160 raise
161 return
162 for name in names:
Larry Hastingsad5ae042012-07-14 17:55:11 -0700163 try:
Larry Hastingsb4038062012-07-15 10:57:38 -0700164 value = os.getxattr(src, name, follow_symlinks=follow_symlinks)
165 os.setxattr(dst, name, value, follow_symlinks=follow_symlinks)
Larry Hastingsad5ae042012-07-14 17:55:11 -0700166 except OSError as e:
Miss Islington (bot)f1487b32019-05-29 22:58:30 -0700167 if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA,
168 errno.EINVAL):
Larry Hastingsad5ae042012-07-14 17:55:11 -0700169 raise
170else:
171 def _copyxattr(*args, **kwargs):
172 pass
173
Larry Hastingsb4038062012-07-15 10:57:38 -0700174def copystat(src, dst, *, follow_symlinks=True):
Zsolt Cserna861f61b2018-10-23 23:57:55 +0200175 """Copy file metadata
Antoine Pitrou78091e62011-12-29 18:54:15 +0100176
Zsolt Cserna861f61b2018-10-23 23:57:55 +0200177 Copy the permission bits, last access time, last modification time, and
178 flags from `src` to `dst`. On Linux, copystat() also copies the "extended
179 attributes" where possible. The file contents, owner, and group are
180 unaffected. `src` and `dst` are path names given as strings.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100181
Zsolt Cserna861f61b2018-10-23 23:57:55 +0200182 If the optional flag `follow_symlinks` is not set, symlinks aren't
183 followed if and only if both `src` and `dst` are symlinks.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100184 """
Larry Hastings9cf065c2012-06-22 16:30:09 -0700185 def _nop(*args, ns=None, follow_symlinks=None):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100186 pass
187
Larry Hastings9cf065c2012-06-22 16:30:09 -0700188 # follow symlinks (aka don't not follow symlinks)
Larry Hastingsb4038062012-07-15 10:57:38 -0700189 follow = follow_symlinks or not (os.path.islink(src) and os.path.islink(dst))
Larry Hastings9cf065c2012-06-22 16:30:09 -0700190 if follow:
191 # use the real function if it exists
192 def lookup(name):
193 return getattr(os, name, _nop)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100194 else:
Larry Hastings9cf065c2012-06-22 16:30:09 -0700195 # use the real function only if it exists
196 # *and* it supports follow_symlinks
197 def lookup(name):
198 fn = getattr(os, name, _nop)
199 if fn in os.supports_follow_symlinks:
200 return fn
201 return _nop
Antoine Pitrou78091e62011-12-29 18:54:15 +0100202
Larry Hastings9cf065c2012-06-22 16:30:09 -0700203 st = lookup("stat")(src, follow_symlinks=follow)
Walter Dörwald294bbf32002-06-06 09:48:13 +0000204 mode = stat.S_IMODE(st.st_mode)
Larry Hastings9cf065c2012-06-22 16:30:09 -0700205 lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns),
206 follow_symlinks=follow)
Miss Islington (bot)0a5b88e2019-05-13 22:30:22 -0700207 # We must copy extended attributes before the file is (potentially)
208 # chmod()'ed read-only, otherwise setxattr() will error with -EACCES.
209 _copyxattr(src, dst, follow_symlinks=follow)
Larry Hastings9cf065c2012-06-22 16:30:09 -0700210 try:
211 lookup("chmod")(dst, mode, follow_symlinks=follow)
212 except NotImplementedError:
213 # if we got a NotImplementedError, it's because
214 # * follow_symlinks=False,
215 # * lchown() is unavailable, and
216 # * either
Ezio Melotti30b9d5d2013-08-17 15:50:46 +0300217 # * fchownat() is unavailable or
Larry Hastings9cf065c2012-06-22 16:30:09 -0700218 # * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW.
219 # (it returned ENOSUP.)
220 # therefore we're out of options--we simply cannot chown the
221 # symlink. give up, suppress the error.
222 # (which is what shutil always did in this circumstance.)
223 pass
Antoine Pitrou78091e62011-12-29 18:54:15 +0100224 if hasattr(st, 'st_flags'):
Antoine Pitrou910bd512010-03-22 20:11:09 +0000225 try:
Larry Hastings9cf065c2012-06-22 16:30:09 -0700226 lookup("chflags")(dst, st.st_flags, follow_symlinks=follow)
Antoine Pitrou910bd512010-03-22 20:11:09 +0000227 except OSError as why:
Ned Deilybaf75712012-05-10 17:05:19 -0700228 for err in 'EOPNOTSUPP', 'ENOTSUP':
229 if hasattr(errno, err) and why.errno == getattr(errno, err):
230 break
231 else:
Antoine Pitrou910bd512010-03-22 20:11:09 +0000232 raise
Antoine Pitrou424246f2012-05-12 19:02:01 +0200233
Larry Hastingsb4038062012-07-15 10:57:38 -0700234def copy(src, dst, *, follow_symlinks=True):
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500235 """Copy data and mode bits ("cp src dst"). Return the file's destination.
Tim Peters495ad3c2001-01-15 01:36:40 +0000236
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000237 The destination may be a directory.
238
Larry Hastingsb4038062012-07-15 10:57:38 -0700239 If follow_symlinks is false, symlinks won't be followed. This
Antoine Pitrou78091e62011-12-29 18:54:15 +0100240 resembles GNU's "cp -P src dst".
241
Hynek Schlawack48653762012-10-07 12:49:58 +0200242 If source and destination are the same file, a SameFileError will be
243 raised.
244
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000245 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000246 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000247 dst = os.path.join(dst, os.path.basename(src))
Larry Hastingsb4038062012-07-15 10:57:38 -0700248 copyfile(src, dst, follow_symlinks=follow_symlinks)
249 copymode(src, dst, follow_symlinks=follow_symlinks)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500250 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000251
Larry Hastingsb4038062012-07-15 10:57:38 -0700252def copy2(src, dst, *, follow_symlinks=True):
Zsolt Cserna861f61b2018-10-23 23:57:55 +0200253 """Copy data and metadata. Return the file's destination.
254
255 Metadata is copied with copystat(). Please see the copystat function
256 for more information.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000257
258 The destination may be a directory.
259
Larry Hastingsb4038062012-07-15 10:57:38 -0700260 If follow_symlinks is false, symlinks won't be followed. This
Antoine Pitrou78091e62011-12-29 18:54:15 +0100261 resembles GNU's "cp -P src dst".
262
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000263 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000264 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000265 dst = os.path.join(dst, os.path.basename(src))
Larry Hastingsb4038062012-07-15 10:57:38 -0700266 copyfile(src, dst, follow_symlinks=follow_symlinks)
267 copystat(src, dst, follow_symlinks=follow_symlinks)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500268 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000269
Georg Brandl2ee470f2008-07-16 12:55:28 +0000270def ignore_patterns(*patterns):
271 """Function that can be used as copytree() ignore parameter.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000272
Georg Brandl2ee470f2008-07-16 12:55:28 +0000273 Patterns is a sequence of glob-style patterns
274 that are used to exclude files"""
275 def _ignore_patterns(path, names):
276 ignored_names = []
277 for pattern in patterns:
278 ignored_names.extend(fnmatch.filter(names, pattern))
279 return set(ignored_names)
280 return _ignore_patterns
281
Tarek Ziadéfb437512010-04-20 08:57:33 +0000282def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
283 ignore_dangling_symlinks=False):
Tarek Ziadé5340db32010-04-19 22:30:51 +0000284 """Recursively copy a directory tree.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000285
286 The destination directory must not already exist.
Neal Norwitza4c93b62003-02-23 21:36:32 +0000287 If exception(s) occur, an Error is raised with a list of reasons.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000288
289 If the optional symlinks flag is true, symbolic links in the
290 source tree result in symbolic links in the destination tree; if
291 it is false, the contents of the files pointed to by symbolic
Tarek Ziadéfb437512010-04-20 08:57:33 +0000292 links are copied. If the file pointed by the symlink doesn't
293 exist, an exception will be added in the list of errors raised in
294 an Error exception at the end of the copy process.
295
296 You can set the optional ignore_dangling_symlinks flag to true if you
Tarek Ziadé8c26c7d2010-04-23 13:03:50 +0000297 want to silence this exception. Notice that this has no effect on
298 platforms that don't support os.symlink.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000299
Georg Brandl2ee470f2008-07-16 12:55:28 +0000300 The optional ignore argument is a callable. If given, it
301 is called with the `src` parameter, which is the directory
302 being visited by copytree(), and `names` which is the list of
303 `src` contents, as returned by os.listdir():
304
305 callable(src, names) -> ignored_names
306
307 Since copytree() is called recursively, the callable will be
308 called once for each directory that is copied. It returns a
309 list of names relative to the `src` directory that should
310 not be copied.
311
Tarek Ziadé5340db32010-04-19 22:30:51 +0000312 The optional copy_function argument is a callable that will be used
313 to copy each file. It will be called with the source path and the
314 destination path as arguments. By default, copy2() is used, but any
315 function that supports the same signature (like copy()) can be used.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000316
317 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000318 names = os.listdir(src)
Georg Brandl2ee470f2008-07-16 12:55:28 +0000319 if ignore is not None:
320 ignored_names = ignore(src, names)
321 else:
322 ignored_names = set()
323
Johannes Gijsberse4172ea2005-01-08 12:31:29 +0000324 os.makedirs(dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000325 errors = []
Guido van Rossuma2baf461997-04-29 14:06:46 +0000326 for name in names:
Georg Brandl2ee470f2008-07-16 12:55:28 +0000327 if name in ignored_names:
328 continue
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000329 srcname = os.path.join(src, name)
330 dstname = os.path.join(dst, name)
331 try:
Tarek Ziadéfb437512010-04-20 08:57:33 +0000332 if os.path.islink(srcname):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000333 linkto = os.readlink(srcname)
Tarek Ziadéfb437512010-04-20 08:57:33 +0000334 if symlinks:
Antoine Pitrou78091e62011-12-29 18:54:15 +0100335 # We can't just leave it to `copy_function` because legacy
336 # code with a custom `copy_function` may rely on copytree
337 # doing the right thing.
Tarek Ziadéfb437512010-04-20 08:57:33 +0000338 os.symlink(linkto, dstname)
Larry Hastingsb4038062012-07-15 10:57:38 -0700339 copystat(srcname, dstname, follow_symlinks=not symlinks)
Tarek Ziadéfb437512010-04-20 08:57:33 +0000340 else:
341 # ignore dangling symlink if the flag is on
342 if not os.path.exists(linkto) and ignore_dangling_symlinks:
343 continue
344 # otherwise let the copy occurs. copy2 will raise an error
Berker Peksag5a294d82015-07-25 14:53:48 +0300345 if os.path.isdir(srcname):
346 copytree(srcname, dstname, symlinks, ignore,
347 copy_function)
348 else:
349 copy_function(srcname, dstname)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000350 elif os.path.isdir(srcname):
Tarek Ziadé5340db32010-04-19 22:30:51 +0000351 copytree(srcname, dstname, symlinks, ignore, copy_function)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000352 else:
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000353 # Will raise a SpecialFileError for unsupported file types
Tarek Ziadé5340db32010-04-19 22:30:51 +0000354 copy_function(srcname, dstname)
Georg Brandla1be88e2005-08-31 22:48:45 +0000355 # catch the Error from the recursive copytree so that we can
356 # continue with other files
Guido van Rossumb940e112007-01-10 16:19:56 +0000357 except Error as err:
Georg Brandla1be88e2005-08-31 22:48:45 +0000358 errors.extend(err.args[0])
Andrew Svetlov3438fa42012-12-17 23:35:18 +0200359 except OSError as why:
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000360 errors.append((srcname, dstname, str(why)))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000361 try:
362 copystat(src, dst)
Guido van Rossumb940e112007-01-10 16:19:56 +0000363 except OSError as why:
Andrew Svetlov2606a6f2012-12-19 14:33:35 +0200364 # Copying file access times may fail on Windows
Berker Peksag884afd92014-12-10 02:50:32 +0200365 if getattr(why, 'winerror', None) is None:
Georg Brandlc8076df2012-08-25 10:11:57 +0200366 errors.append((src, dst, str(why)))
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000367 if errors:
Collin Winterce36ad82007-08-30 01:19:48 +0000368 raise Error(errors)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500369 return dst
Guido van Rossumd7673291998-02-06 21:38:09 +0000370
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200371# version vulnerable to race conditions
372def _rmtree_unsafe(path, onerror):
Christian Heimes9bd667a2008-01-20 15:14:11 +0000373 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200374 with os.scandir(path) as scandir_it:
375 entries = list(scandir_it)
Christian Heimes9bd667a2008-01-20 15:14:11 +0000376 except OSError:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200377 onerror(os.scandir, path, sys.exc_info())
378 entries = []
379 for entry in entries:
380 fullname = entry.path
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000381 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200382 is_dir = entry.is_dir(follow_symlinks=False)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200383 except OSError:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200384 is_dir = False
385 if is_dir:
386 try:
387 if entry.is_symlink():
388 # This can only happen if someone replaces
389 # a directory with a symlink after the call to
390 # os.scandir or entry.is_dir above.
391 raise OSError("Cannot call rmtree on a symbolic link")
392 except OSError:
393 onerror(os.path.islink, fullname, sys.exc_info())
394 continue
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200395 _rmtree_unsafe(fullname, onerror)
Barry Warsaw234d9a92003-01-24 17:36:15 +0000396 else:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000397 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200398 os.unlink(fullname)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200399 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200400 onerror(os.unlink, fullname, sys.exc_info())
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000401 try:
402 os.rmdir(path)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200403 except OSError:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000404 onerror(os.rmdir, path, sys.exc_info())
Guido van Rossumd7673291998-02-06 21:38:09 +0000405
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200406# Version using fd-based APIs to protect against races
407def _rmtree_safe_fd(topfd, path, onerror):
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200408 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200409 with os.scandir(topfd) as scandir_it:
410 entries = list(scandir_it)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100411 except OSError as err:
412 err.filename = path
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200413 onerror(os.scandir, path, sys.exc_info())
414 return
415 for entry in entries:
416 fullname = os.path.join(path, entry.name)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200417 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200418 is_dir = entry.is_dir(follow_symlinks=False)
419 if is_dir:
420 orig_st = entry.stat(follow_symlinks=False)
421 is_dir = stat.S_ISDIR(orig_st.st_mode)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100422 except OSError:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200423 is_dir = False
424 if is_dir:
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200425 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200426 dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100427 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200428 onerror(os.open, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200429 else:
430 try:
431 if os.path.samestat(orig_st, os.fstat(dirfd)):
432 _rmtree_safe_fd(dirfd, fullname, onerror)
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200433 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200434 os.rmdir(entry.name, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100435 except OSError:
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200436 onerror(os.rmdir, fullname, sys.exc_info())
Hynek Schlawackb5501102012-12-10 09:11:25 +0100437 else:
438 try:
439 # This can only happen if someone replaces
440 # a directory with a symlink after the call to
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200441 # os.scandir or stat.S_ISDIR above.
Hynek Schlawackb5501102012-12-10 09:11:25 +0100442 raise OSError("Cannot call rmtree on a symbolic "
443 "link")
444 except OSError:
445 onerror(os.path.islink, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200446 finally:
447 os.close(dirfd)
448 else:
449 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200450 os.unlink(entry.name, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100451 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200452 onerror(os.unlink, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200453
Hynek Schlawackd0f6e0a2012-06-29 08:28:20 +0200454_use_fd_functions = ({os.open, os.stat, os.unlink, os.rmdir} <=
455 os.supports_dir_fd and
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200456 os.scandir in os.supports_fd and
Hynek Schlawackd0f6e0a2012-06-29 08:28:20 +0200457 os.stat in os.supports_follow_symlinks)
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000458
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200459def rmtree(path, ignore_errors=False, onerror=None):
460 """Recursively delete a directory tree.
461
462 If ignore_errors is set, errors are ignored; otherwise, if onerror
463 is set, it is called to handle the error with arguments (func,
Hynek Schlawack2100b422012-06-23 20:28:32 +0200464 path, exc_info) where func is platform and implementation dependent;
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200465 path is the argument to that function that caused it to fail; and
466 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
467 is false and onerror is None, an exception is raised.
468
469 """
470 if ignore_errors:
471 def onerror(*args):
472 pass
473 elif onerror is None:
474 def onerror(*args):
475 raise
476 if _use_fd_functions:
Hynek Schlawack3b527782012-06-25 13:27:31 +0200477 # While the unsafe rmtree works fine on bytes, the fd based does not.
478 if isinstance(path, bytes):
479 path = os.fsdecode(path)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200480 # Note: To guard against symlink races, we use the standard
481 # lstat()/open()/fstat() trick.
482 try:
483 orig_st = os.lstat(path)
484 except Exception:
485 onerror(os.lstat, path, sys.exc_info())
486 return
487 try:
488 fd = os.open(path, os.O_RDONLY)
489 except Exception:
490 onerror(os.lstat, path, sys.exc_info())
491 return
492 try:
Hynek Schlawackb5501102012-12-10 09:11:25 +0100493 if os.path.samestat(orig_st, os.fstat(fd)):
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200494 _rmtree_safe_fd(fd, path, onerror)
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200495 try:
496 os.rmdir(path)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200497 except OSError:
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200498 onerror(os.rmdir, path, sys.exc_info())
Hynek Schlawacka75cd1c2012-06-28 12:07:29 +0200499 else:
Hynek Schlawackb5501102012-12-10 09:11:25 +0100500 try:
501 # symlinks to directories are forbidden, see bug #1669
502 raise OSError("Cannot call rmtree on a symbolic link")
503 except OSError:
504 onerror(os.path.islink, path, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200505 finally:
506 os.close(fd)
507 else:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200508 try:
509 if os.path.islink(path):
510 # symlinks to directories are forbidden, see bug #1669
511 raise OSError("Cannot call rmtree on a symbolic link")
512 except OSError:
513 onerror(os.path.islink, path, sys.exc_info())
514 # can't continue even if onerror hook returns
515 return
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200516 return _rmtree_unsafe(path, onerror)
517
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000518# Allow introspection of whether or not the hardening against symlink
519# attacks is supported on the current platform
520rmtree.avoids_symlink_attacks = _use_fd_functions
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000521
Christian Heimesada8c3b2008-03-18 18:26:33 +0000522def _basename(path):
523 # A basename() variant which first strips the trailing slash, if present.
524 # Thus we always get the last component of the path, even for directories.
Serhiy Storchaka3a308b92014-02-11 10:30:59 +0200525 sep = os.path.sep + (os.path.altsep or '')
526 return os.path.basename(path.rstrip(sep))
Christian Heimesada8c3b2008-03-18 18:26:33 +0000527
R David Murray6ffface2014-06-11 14:40:13 -0400528def move(src, dst, copy_function=copy2):
Christian Heimesada8c3b2008-03-18 18:26:33 +0000529 """Recursively move a file or directory to another location. This is
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500530 similar to the Unix "mv" command. Return the file or directory's
531 destination.
Christian Heimesada8c3b2008-03-18 18:26:33 +0000532
533 If the destination is a directory or a symlink to a directory, the source
534 is moved inside the directory. The destination path must not already
535 exist.
536
537 If the destination already exists but is not a directory, it may be
538 overwritten depending on os.rename() semantics.
539
540 If the destination is on our current filesystem, then rename() is used.
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +0100541 Otherwise, src is copied to the destination and then removed. Symlinks are
542 recreated under the new name if os.rename() fails because of cross
543 filesystem renames.
544
R David Murray6ffface2014-06-11 14:40:13 -0400545 The optional `copy_function` argument is a callable that will be used
546 to copy the source or it will be delegated to `copytree`.
547 By default, copy2() is used, but any function that supports the same
548 signature (like copy()) can be used.
549
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000550 A lot more could be done here... A look at a mv.c shows a lot of
551 the issues this implementation glosses over.
552
553 """
Christian Heimesada8c3b2008-03-18 18:26:33 +0000554 real_dst = dst
555 if os.path.isdir(dst):
Ronald Oussorenf51738b2011-05-06 10:23:04 +0200556 if _samefile(src, dst):
557 # We might be on a case insensitive filesystem,
558 # perform the rename anyway.
559 os.rename(src, dst)
560 return
561
Christian Heimesada8c3b2008-03-18 18:26:33 +0000562 real_dst = os.path.join(dst, _basename(src))
563 if os.path.exists(real_dst):
564 raise Error("Destination path '%s' already exists" % real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000565 try:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000566 os.rename(src, real_dst)
Éric Araujocfcc9772011-08-10 20:54:33 +0200567 except OSError:
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +0100568 if os.path.islink(src):
569 linkto = os.readlink(src)
570 os.symlink(linkto, real_dst)
571 os.unlink(src)
572 elif os.path.isdir(src):
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000573 if _destinsrc(src, dst):
R David Murray6ffface2014-06-11 14:40:13 -0400574 raise Error("Cannot move a directory '%s' into itself"
575 " '%s'." % (src, dst))
576 copytree(src, real_dst, copy_function=copy_function,
577 symlinks=True)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000578 rmtree(src)
579 else:
R David Murray6ffface2014-06-11 14:40:13 -0400580 copy_function(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000581 os.unlink(src)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500582 return real_dst
Brett Cannon1c3fa182004-06-19 21:11:35 +0000583
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000584def _destinsrc(src, dst):
Berker Peksag3715da52014-09-18 05:11:15 +0300585 src = os.path.abspath(src)
586 dst = os.path.abspath(dst)
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +0000587 if not src.endswith(os.path.sep):
588 src += os.path.sep
589 if not dst.endswith(os.path.sep):
590 dst += os.path.sep
591 return dst.startswith(src)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000592
593def _get_gid(name):
594 """Returns a gid, given a group name."""
595 if getgrnam is None or name is None:
596 return None
597 try:
598 result = getgrnam(name)
599 except KeyError:
600 result = None
601 if result is not None:
602 return result[2]
603 return None
604
605def _get_uid(name):
606 """Returns an uid, given a user name."""
607 if getpwnam is None or name is None:
608 return None
609 try:
610 result = getpwnam(name)
611 except KeyError:
612 result = None
613 if result is not None:
614 return result[2]
615 return None
616
617def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
618 owner=None, group=None, logger=None):
619 """Create a (possibly compressed) tar file from all the files under
620 'base_dir'.
621
Serhiy Storchaka11213772014-08-06 18:50:19 +0300622 'compress' must be "gzip" (the default), "bzip2", "xz", or None.
Tarek Ziadé396fad72010-02-23 05:30:31 +0000623
624 'owner' and 'group' can be used to define an owner and a group for the
625 archive that is being built. If not provided, the current owner and group
626 will be used.
627
Éric Araujo4433a5f2010-12-15 20:26:30 +0000628 The output tar file will be named 'base_name' + ".tar", possibly plus
Serhiy Storchaka11213772014-08-06 18:50:19 +0300629 the appropriate compression extension (".gz", ".bz2", or ".xz").
Tarek Ziadé396fad72010-02-23 05:30:31 +0000630
631 Returns the output filename.
632 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200633 if compress is None:
634 tar_compression = ''
635 elif _ZLIB_SUPPORTED and compress == 'gzip':
636 tar_compression = 'gz'
637 elif _BZ2_SUPPORTED and compress == 'bzip2':
638 tar_compression = 'bz2'
639 elif _LZMA_SUPPORTED and compress == 'xz':
640 tar_compression = 'xz'
641 else:
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000642 raise ValueError("bad value for 'compress', or compression format not "
643 "supported : {0}".format(compress))
Tarek Ziadé396fad72010-02-23 05:30:31 +0000644
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200645 import tarfile # late import for breaking circular dependency
646
647 compress_ext = '.' + tar_compression if compress else ''
648 archive_name = base_name + '.tar' + compress_ext
Tarek Ziadé396fad72010-02-23 05:30:31 +0000649 archive_dir = os.path.dirname(archive_name)
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000650
Serhiy Storchaka9a4fc192014-11-28 00:48:46 +0200651 if archive_dir and not os.path.exists(archive_dir):
Éric Araujoac4e58e2011-01-29 20:32:11 +0000652 if logger is not None:
Éric Araujo43a7ee12011-08-19 02:55:11 +0200653 logger.info("creating %s", archive_dir)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000654 if not dry_run:
655 os.makedirs(archive_dir)
656
Tarek Ziadé396fad72010-02-23 05:30:31 +0000657 # creating the tarball
Tarek Ziadé396fad72010-02-23 05:30:31 +0000658 if logger is not None:
659 logger.info('Creating tar archive')
660
661 uid = _get_uid(owner)
662 gid = _get_gid(group)
663
664 def _set_uid_gid(tarinfo):
665 if gid is not None:
666 tarinfo.gid = gid
667 tarinfo.gname = group
668 if uid is not None:
669 tarinfo.uid = uid
670 tarinfo.uname = owner
671 return tarinfo
672
673 if not dry_run:
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200674 tar = tarfile.open(archive_name, 'w|%s' % tar_compression)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000675 try:
676 tar.add(base_dir, filter=_set_uid_gid)
677 finally:
678 tar.close()
679
Tarek Ziadé396fad72010-02-23 05:30:31 +0000680 return archive_name
681
Tarek Ziadé396fad72010-02-23 05:30:31 +0000682def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
683 """Create a zip file from all the files under 'base_dir'.
684
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200685 The output zip file will be named 'base_name' + ".zip". Returns the
686 name of the output zip file.
Tarek Ziadé396fad72010-02-23 05:30:31 +0000687 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200688 import zipfile # late import for breaking circular dependency
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400689
Tarek Ziadé396fad72010-02-23 05:30:31 +0000690 zip_filename = base_name + ".zip"
691 archive_dir = os.path.dirname(base_name)
692
Serhiy Storchaka9a4fc192014-11-28 00:48:46 +0200693 if archive_dir and not os.path.exists(archive_dir):
Tarek Ziadé396fad72010-02-23 05:30:31 +0000694 if logger is not None:
695 logger.info("creating %s", archive_dir)
696 if not dry_run:
697 os.makedirs(archive_dir)
698
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400699 if logger is not None:
700 logger.info("creating '%s' and adding '%s' to it",
701 zip_filename, base_dir)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000702
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400703 if not dry_run:
704 with zipfile.ZipFile(zip_filename, "w",
705 compression=zipfile.ZIP_DEFLATED) as zf:
Serhiy Storchakad941d7a2015-09-08 05:51:00 +0300706 path = os.path.normpath(base_dir)
Serhiy Storchaka666de772016-10-23 15:55:09 +0300707 if path != os.curdir:
708 zf.write(path, path)
709 if logger is not None:
710 logger.info("adding '%s'", path)
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400711 for dirpath, dirnames, filenames in os.walk(base_dir):
Serhiy Storchakad941d7a2015-09-08 05:51:00 +0300712 for name in sorted(dirnames):
713 path = os.path.normpath(os.path.join(dirpath, name))
714 zf.write(path, path)
715 if logger is not None:
716 logger.info("adding '%s'", path)
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400717 for name in filenames:
718 path = os.path.normpath(os.path.join(dirpath, name))
719 if os.path.isfile(path):
720 zf.write(path, path)
721 if logger is not None:
722 logger.info("adding '%s'", path)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000723
724 return zip_filename
725
726_ARCHIVE_FORMATS = {
Tarek Ziadé396fad72010-02-23 05:30:31 +0000727 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"),
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200728}
729
730if _ZLIB_SUPPORTED:
731 _ARCHIVE_FORMATS['gztar'] = (_make_tarball, [('compress', 'gzip')],
732 "gzip'ed tar-file")
733 _ARCHIVE_FORMATS['zip'] = (_make_zipfile, [], "ZIP file")
Tarek Ziadé396fad72010-02-23 05:30:31 +0000734
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000735if _BZ2_SUPPORTED:
736 _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')],
737 "bzip2'ed tar-file")
738
Serhiy Storchaka11213772014-08-06 18:50:19 +0300739if _LZMA_SUPPORTED:
740 _ARCHIVE_FORMATS['xztar'] = (_make_tarball, [('compress', 'xz')],
741 "xz'ed tar-file")
742
Tarek Ziadé396fad72010-02-23 05:30:31 +0000743def get_archive_formats():
744 """Returns a list of supported formats for archiving and unarchiving.
745
746 Each element of the returned sequence is a tuple (name, description)
747 """
748 formats = [(name, registry[2]) for name, registry in
749 _ARCHIVE_FORMATS.items()]
750 formats.sort()
751 return formats
752
753def register_archive_format(name, function, extra_args=None, description=''):
754 """Registers an archive format.
755
756 name is the name of the format. function is the callable that will be
757 used to create archives. If provided, extra_args is a sequence of
758 (name, value) tuples that will be passed as arguments to the callable.
759 description can be provided to describe the format, and will be returned
760 by the get_archive_formats() function.
761 """
762 if extra_args is None:
763 extra_args = []
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200764 if not callable(function):
Tarek Ziadé396fad72010-02-23 05:30:31 +0000765 raise TypeError('The %s object is not callable' % function)
766 if not isinstance(extra_args, (tuple, list)):
767 raise TypeError('extra_args needs to be a sequence')
768 for element in extra_args:
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200769 if not isinstance(element, (tuple, list)) or len(element) !=2:
Tarek Ziadé396fad72010-02-23 05:30:31 +0000770 raise TypeError('extra_args elements are : (arg_name, value)')
771
772 _ARCHIVE_FORMATS[name] = (function, extra_args, description)
773
774def unregister_archive_format(name):
775 del _ARCHIVE_FORMATS[name]
776
777def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
778 dry_run=0, owner=None, group=None, logger=None):
779 """Create an archive file (eg. zip or tar).
780
781 'base_name' is the name of the file to create, minus any format-specific
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200782 extension; 'format' is the archive format: one of "zip", "tar", "gztar",
783 "bztar", or "xztar". Or any other registered format.
Tarek Ziadé396fad72010-02-23 05:30:31 +0000784
785 'root_dir' is a directory that will be the root directory of the
786 archive; ie. we typically chdir into 'root_dir' before creating the
787 archive. 'base_dir' is the directory where we start archiving from;
788 ie. 'base_dir' will be the common prefix of all files and
789 directories in the archive. 'root_dir' and 'base_dir' both default
790 to the current directory. Returns the name of the archive file.
791
792 'owner' and 'group' are used when creating a tar archive. By default,
793 uses the current owner and group.
794 """
795 save_cwd = os.getcwd()
796 if root_dir is not None:
797 if logger is not None:
798 logger.debug("changing into '%s'", root_dir)
799 base_name = os.path.abspath(base_name)
800 if not dry_run:
801 os.chdir(root_dir)
802
803 if base_dir is None:
804 base_dir = os.curdir
805
806 kwargs = {'dry_run': dry_run, 'logger': logger}
807
808 try:
809 format_info = _ARCHIVE_FORMATS[format]
810 except KeyError:
Serhiy Storchaka5affd232017-04-05 09:37:24 +0300811 raise ValueError("unknown archive format '%s'" % format) from None
Tarek Ziadé396fad72010-02-23 05:30:31 +0000812
813 func = format_info[0]
814 for arg, val in format_info[1]:
815 kwargs[arg] = val
816
817 if format != 'zip':
818 kwargs['owner'] = owner
819 kwargs['group'] = group
820
821 try:
822 filename = func(base_name, base_dir, **kwargs)
823 finally:
824 if root_dir is not None:
825 if logger is not None:
826 logger.debug("changing back to '%s'", save_cwd)
827 os.chdir(save_cwd)
828
829 return filename
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000830
831
832def get_unpack_formats():
833 """Returns a list of supported formats for unpacking.
834
835 Each element of the returned sequence is a tuple
836 (name, extensions, description)
837 """
838 formats = [(name, info[0], info[3]) for name, info in
839 _UNPACK_FORMATS.items()]
840 formats.sort()
841 return formats
842
843def _check_unpack_options(extensions, function, extra_args):
844 """Checks what gets registered as an unpacker."""
845 # first make sure no other unpacker is registered for this extension
846 existing_extensions = {}
847 for name, info in _UNPACK_FORMATS.items():
848 for ext in info[0]:
849 existing_extensions[ext] = name
850
851 for extension in extensions:
852 if extension in existing_extensions:
853 msg = '%s is already registered for "%s"'
854 raise RegistryError(msg % (extension,
855 existing_extensions[extension]))
856
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200857 if not callable(function):
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000858 raise TypeError('The registered function must be a callable')
859
860
861def register_unpack_format(name, extensions, function, extra_args=None,
862 description=''):
863 """Registers an unpack format.
864
865 `name` is the name of the format. `extensions` is a list of extensions
866 corresponding to the format.
867
868 `function` is the callable that will be
869 used to unpack archives. The callable will receive archives to unpack.
870 If it's unable to handle an archive, it needs to raise a ReadError
871 exception.
872
873 If provided, `extra_args` is a sequence of
874 (name, value) tuples that will be passed as arguments to the callable.
875 description can be provided to describe the format, and will be returned
876 by the get_unpack_formats() function.
877 """
878 if extra_args is None:
879 extra_args = []
880 _check_unpack_options(extensions, function, extra_args)
881 _UNPACK_FORMATS[name] = extensions, function, extra_args, description
882
883def unregister_unpack_format(name):
Martin Pantereb995702016-07-28 01:11:04 +0000884 """Removes the pack format from the registry."""
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000885 del _UNPACK_FORMATS[name]
886
887def _ensure_directory(path):
888 """Ensure that the parent directory of `path` exists"""
889 dirname = os.path.dirname(path)
890 if not os.path.isdir(dirname):
891 os.makedirs(dirname)
892
893def _unpack_zipfile(filename, extract_dir):
894 """Unpack zip `filename` to `extract_dir`
895 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200896 import zipfile # late import for breaking circular dependency
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000897
898 if not zipfile.is_zipfile(filename):
899 raise ReadError("%s is not a zip file" % filename)
900
901 zip = zipfile.ZipFile(filename)
902 try:
903 for info in zip.infolist():
904 name = info.filename
905
906 # don't extract absolute paths or ones with .. in them
907 if name.startswith('/') or '..' in name:
908 continue
909
910 target = os.path.join(extract_dir, *name.split('/'))
911 if not target:
912 continue
913
914 _ensure_directory(target)
915 if not name.endswith('/'):
916 # file
917 data = zip.read(info.filename)
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200918 f = open(target, 'wb')
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000919 try:
920 f.write(data)
921 finally:
922 f.close()
923 del data
924 finally:
925 zip.close()
926
927def _unpack_tarfile(filename, extract_dir):
Serhiy Storchaka11213772014-08-06 18:50:19 +0300928 """Unpack tar/tar.gz/tar.bz2/tar.xz `filename` to `extract_dir`
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000929 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200930 import tarfile # late import for breaking circular dependency
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000931 try:
932 tarobj = tarfile.open(filename)
933 except tarfile.TarError:
934 raise ReadError(
935 "%s is not a compressed or uncompressed tar file" % filename)
936 try:
937 tarobj.extractall(extract_dir)
938 finally:
939 tarobj.close()
940
941_UNPACK_FORMATS = {
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000942 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"),
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200943 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file"),
944}
945
946if _ZLIB_SUPPORTED:
947 _UNPACK_FORMATS['gztar'] = (['.tar.gz', '.tgz'], _unpack_tarfile, [],
948 "gzip'ed tar-file")
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000949
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000950if _BZ2_SUPPORTED:
Serhiy Storchaka11213772014-08-06 18:50:19 +0300951 _UNPACK_FORMATS['bztar'] = (['.tar.bz2', '.tbz2'], _unpack_tarfile, [],
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000952 "bzip2'ed tar-file")
953
Serhiy Storchaka11213772014-08-06 18:50:19 +0300954if _LZMA_SUPPORTED:
955 _UNPACK_FORMATS['xztar'] = (['.tar.xz', '.txz'], _unpack_tarfile, [],
956 "xz'ed tar-file")
957
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000958def _find_unpack_format(filename):
959 for name, info in _UNPACK_FORMATS.items():
960 for extension in info[0]:
961 if filename.endswith(extension):
962 return name
963 return None
964
965def unpack_archive(filename, extract_dir=None, format=None):
966 """Unpack an archive.
967
968 `filename` is the name of the archive.
969
970 `extract_dir` is the name of the target directory, where the archive
971 is unpacked. If not provided, the current working directory is used.
972
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200973 `format` is the archive format: one of "zip", "tar", "gztar", "bztar",
974 or "xztar". Or any other registered format. If not provided,
975 unpack_archive will use the filename extension and see if an unpacker
976 was registered for that extension.
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000977
978 In case none is found, a ValueError is raised.
979 """
980 if extract_dir is None:
981 extract_dir = os.getcwd()
982
Jelle Zijlstraa12df7b2017-05-05 14:27:12 -0700983 extract_dir = os.fspath(extract_dir)
984 filename = os.fspath(filename)
985
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000986 if format is not None:
987 try:
988 format_info = _UNPACK_FORMATS[format]
989 except KeyError:
Serhiy Storchaka5affd232017-04-05 09:37:24 +0300990 raise ValueError("Unknown unpack format '{0}'".format(format)) from None
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000991
Nick Coghlanabf202d2011-03-16 13:52:20 -0400992 func = format_info[1]
993 func(filename, extract_dir, **dict(format_info[2]))
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000994 else:
995 # we need to look at the registered unpackers supported extensions
996 format = _find_unpack_format(filename)
997 if format is None:
998 raise ReadError("Unknown archive format '{0}'".format(filename))
999
1000 func = _UNPACK_FORMATS[format][1]
1001 kwargs = dict(_UNPACK_FORMATS[format][2])
1002 func(filename, extract_dir, **kwargs)
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001003
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001004
1005if hasattr(os, 'statvfs'):
1006
1007 __all__.append('disk_usage')
1008 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
Raymond Hettinger5b798ab2015-08-17 22:04:45 -07001009 _ntuple_diskusage.total.__doc__ = 'Total space in bytes'
1010 _ntuple_diskusage.used.__doc__ = 'Used space in bytes'
1011 _ntuple_diskusage.free.__doc__ = 'Free space in bytes'
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001012
1013 def disk_usage(path):
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001014 """Return disk usage statistics about the given path.
1015
Sandro Tosif8ae4fa2012-04-23 20:07:15 +02001016 Returned value is a named tuple with attributes 'total', 'used' and
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001017 'free', which are the amount of total, used and free space, in bytes.
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001018 """
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001019 st = os.statvfs(path)
1020 free = st.f_bavail * st.f_frsize
1021 total = st.f_blocks * st.f_frsize
1022 used = (st.f_blocks - st.f_bfree) * st.f_frsize
1023 return _ntuple_diskusage(total, used, free)
1024
1025elif os.name == 'nt':
1026
1027 import nt
1028 __all__.append('disk_usage')
1029 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
1030
1031 def disk_usage(path):
1032 """Return disk usage statistics about the given path.
1033
Ezio Melotti30b9d5d2013-08-17 15:50:46 +03001034 Returned values is a named tuple with attributes 'total', 'used' and
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001035 'free', which are the amount of total, used and free space, in bytes.
1036 """
1037 total, free = nt._getdiskusage(path)
1038 used = total - free
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001039 return _ntuple_diskusage(total, used, free)
Sandro Tosid902a142011-08-22 23:28:27 +02001040
Éric Araujo0ac4a5d2011-09-01 08:31:51 +02001041
Sandro Tosid902a142011-08-22 23:28:27 +02001042def chown(path, user=None, group=None):
1043 """Change owner user and group of the given path.
1044
1045 user and group can be the uid/gid or the user/group names, and in that case,
1046 they are converted to their respective uid/gid.
1047 """
1048
1049 if user is None and group is None:
1050 raise ValueError("user and/or group must be set")
1051
1052 _user = user
1053 _group = group
1054
1055 # -1 means don't change it
1056 if user is None:
1057 _user = -1
1058 # user can either be an int (the uid) or a string (the system username)
1059 elif isinstance(user, str):
1060 _user = _get_uid(user)
1061 if _user is None:
1062 raise LookupError("no such user: {!r}".format(user))
1063
1064 if group is None:
1065 _group = -1
1066 elif not isinstance(group, int):
1067 _group = _get_gid(group)
1068 if _group is None:
1069 raise LookupError("no such group: {!r}".format(group))
1070
1071 os.chown(path, _user, _group)
Antoine Pitroubcf2b592012-02-08 23:28:36 +01001072
1073def get_terminal_size(fallback=(80, 24)):
1074 """Get the size of the terminal window.
1075
1076 For each of the two dimensions, the environment variable, COLUMNS
1077 and LINES respectively, is checked. If the variable is defined and
1078 the value is a positive integer, it is used.
1079
1080 When COLUMNS or LINES is not defined, which is the common case,
1081 the terminal connected to sys.__stdout__ is queried
1082 by invoking os.get_terminal_size.
1083
1084 If the terminal size cannot be successfully queried, either because
1085 the system doesn't support querying, or because we are not
1086 connected to a terminal, the value given in fallback parameter
1087 is used. Fallback defaults to (80, 24) which is the default
1088 size used by many terminal emulators.
1089
1090 The value returned is a named tuple of type os.terminal_size.
1091 """
1092 # columns, lines are the working values
1093 try:
1094 columns = int(os.environ['COLUMNS'])
1095 except (KeyError, ValueError):
1096 columns = 0
1097
1098 try:
1099 lines = int(os.environ['LINES'])
1100 except (KeyError, ValueError):
1101 lines = 0
1102
1103 # only query if necessary
1104 if columns <= 0 or lines <= 0:
1105 try:
1106 size = os.get_terminal_size(sys.__stdout__.fileno())
Serhiy Storchakad30829d2016-04-24 09:58:43 +03001107 except (AttributeError, ValueError, OSError):
1108 # stdout is None, closed, detached, or not a terminal, or
1109 # os.get_terminal_size() is unsupported
Antoine Pitroubcf2b592012-02-08 23:28:36 +01001110 size = os.terminal_size(fallback)
1111 if columns <= 0:
1112 columns = size.columns
1113 if lines <= 0:
1114 lines = size.lines
1115
1116 return os.terminal_size((columns, lines))
Brian Curtinc57a3452012-06-22 16:00:30 -05001117
1118def which(cmd, mode=os.F_OK | os.X_OK, path=None):
Brian Curtindc00f1e2012-06-22 22:49:12 -05001119 """Given a command, mode, and a PATH string, return the path which
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001120 conforms to the given mode on the PATH, or None if there is no such
1121 file.
1122
1123 `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
1124 of os.environ.get("PATH"), or can be overridden with a custom search
1125 path.
1126
1127 """
Victor Stinner1d006a22013-12-16 23:39:40 +01001128 # Check that a given file can be accessed with the correct mode.
1129 # Additionally check that `file` is not a directory, as on Windows
1130 # directories pass the os.access check.
1131 def _access_check(fn, mode):
1132 return (os.path.exists(fn) and os.access(fn, mode)
1133 and not os.path.isdir(fn))
1134
Serhiy Storchaka8bea2002013-01-23 10:44:21 +02001135 # If we're given a path with a directory part, look it up directly rather
1136 # than referring to PATH directories. This includes checking relative to the
1137 # current directory, e.g. ./script
1138 if os.path.dirname(cmd):
1139 if _access_check(cmd, mode):
1140 return cmd
1141 return None
Brian Curtinc57a3452012-06-22 16:00:30 -05001142
Barry Warsaw618738b2013-04-16 11:05:03 -04001143 if path is None:
Victor Stinner394b9912019-04-17 18:38:06 +02001144 path = os.environ.get("PATH", None)
1145 if path is None:
1146 try:
1147 path = os.confstr("CS_PATH")
1148 except (AttributeError, ValueError):
1149 # os.confstr() or CS_PATH is not available
1150 path = os.defpath
1151 # bpo-35755: Don't use os.defpath if the PATH environment variable is
1152 # set to an empty string
1153
1154 # PATH='' doesn't match, whereas PATH=':' looks in the current directory
Barry Warsaw618738b2013-04-16 11:05:03 -04001155 if not path:
1156 return None
Victor Stinner1d006a22013-12-16 23:39:40 +01001157 path = path.split(os.pathsep)
Brian Curtinc57a3452012-06-22 16:00:30 -05001158
1159 if sys.platform == "win32":
1160 # The current directory takes precedence on Windows.
1161 if not os.curdir in path:
1162 path.insert(0, os.curdir)
1163
1164 # PATHEXT is necessary to check on Windows.
1165 pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
1166 # See if the given file matches any of the expected path extensions.
1167 # This will allow us to short circuit when given "python.exe".
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001168 # If it does match, only test that one, otherwise we have to try
1169 # others.
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001170 if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
1171 files = [cmd]
1172 else:
1173 files = [cmd + ext for ext in pathext]
Brian Curtinc57a3452012-06-22 16:00:30 -05001174 else:
1175 # On other platforms you don't have things like PATHEXT to tell you
1176 # what file suffixes are executable, so just pass on cmd as-is.
1177 files = [cmd]
1178
1179 seen = set()
1180 for dir in path:
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001181 normdir = os.path.normcase(dir)
1182 if not normdir in seen:
1183 seen.add(normdir)
Brian Curtinc57a3452012-06-22 16:00:30 -05001184 for thefile in files:
1185 name = os.path.join(dir, thefile)
1186 if _access_check(name, mode):
1187 return name
1188 return None