blob: 37bf98df796723a806833f21903448788cf1a4b9 [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
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -070035_WINDOWS = os.name == 'nt'
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020036posix = nt = None
37if os.name == 'posix':
38 import posix
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -070039elif _WINDOWS:
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020040 import nt
41
Inada Naoki4f190302019-03-02 13:31:01 +090042COPY_BUFSIZE = 1024 * 1024 if _WINDOWS else 64 * 1024
Giampaolo Rodola413d9552019-05-30 14:05:41 +080043_USE_CP_SENDFILE = hasattr(os, "sendfile") and sys.platform.startswith("linux")
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -070044_HAS_FCOPYFILE = posix and hasattr(posix, "_fcopyfile") # macOS
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020045
Christopher Marchfelderda6f0982020-10-23 12:08:24 +020046# CMD defaults in Windows 10
47_WIN_DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC"
48
Tarek Ziadéc3399782010-02-23 05:39:18 +000049__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
50 "copytree", "move", "rmtree", "Error", "SpecialFileError",
51 "ExecError", "make_archive", "get_archive_formats",
Tarek Ziadé6ac91722010-04-28 17:51:36 +000052 "register_archive_format", "unregister_archive_format",
53 "get_unpack_formats", "register_unpack_format",
Éric Araujoc5efe652011-08-21 14:30:00 +020054 "unregister_unpack_format", "unpack_archive",
Berker Peksag8083cd62014-11-01 11:04:06 +020055 "ignore_patterns", "chown", "which", "get_terminal_size",
56 "SameFileError"]
Éric Araujoe4d5b8e2011-08-08 16:51:11 +020057 # disk_usage is added later, if available on the platform
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000058
Andrew Svetlov3438fa42012-12-17 23:35:18 +020059class Error(OSError):
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000060 pass
Guido van Rossumc6360141990-10-13 19:23:40 +000061
Hynek Schlawack48653762012-10-07 12:49:58 +020062class SameFileError(Error):
63 """Raised when source and destination are the same file."""
64
Andrew Svetlov3438fa42012-12-17 23:35:18 +020065class SpecialFileError(OSError):
Antoine Pitrou7fff0962009-05-01 21:09:44 +000066 """Raised when trying to do a kind of operation (e.g. copying) which is
67 not supported on a special file (e.g. a named pipe)"""
68
Andrew Svetlov3438fa42012-12-17 23:35:18 +020069class ExecError(OSError):
Tarek Ziadé396fad72010-02-23 05:30:31 +000070 """Raised when a command could not be executed"""
71
Andrew Svetlov3438fa42012-12-17 23:35:18 +020072class ReadError(OSError):
Tarek Ziadé6ac91722010-04-28 17:51:36 +000073 """Raised when an archive cannot be read"""
74
75class RegistryError(Exception):
Ezio Melotti30b9d5d2013-08-17 15:50:46 +030076 """Raised when a registry operation with the archiving
Raymond Hettinger15f44ab2016-08-30 10:47:49 -070077 and unpacking registries fails"""
Tarek Ziadé6ac91722010-04-28 17:51:36 +000078
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020079class _GiveupOnFastCopy(Exception):
80 """Raised as a signal to fallback on using raw read()/write()
81 file copy when fast-copy functions fail to do so.
82 """
Tarek Ziadé6ac91722010-04-28 17:51:36 +000083
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -070084def _fastcopy_fcopyfile(fsrc, fdst, flags):
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020085 """Copy a regular file content or metadata by using high-performance
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -070086 fcopyfile(3) syscall (macOS).
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020087 """
88 try:
89 infd = fsrc.fileno()
90 outfd = fdst.fileno()
91 except Exception as err:
92 raise _GiveupOnFastCopy(err) # not a regular file
93
94 try:
95 posix._fcopyfile(infd, outfd, flags)
96 except OSError as err:
97 err.filename = fsrc.name
98 err.filename2 = fdst.name
99 if err.errno in {errno.EINVAL, errno.ENOTSUP}:
100 raise _GiveupOnFastCopy(err)
101 else:
102 raise err from None
103
104def _fastcopy_sendfile(fsrc, fdst):
105 """Copy data from one regular mmap-like fd to another by using
106 high-performance sendfile(2) syscall.
Giampaolo Rodola413d9552019-05-30 14:05:41 +0800107 This should work on Linux >= 2.6.33 only.
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200108 """
109 # Note: copyfileobj() is left alone in order to not introduce any
110 # unexpected breakage. Possible risks by using zero-copy calls
111 # in copyfileobj() are:
112 # - fdst cannot be open in "a"(ppend) mode
113 # - fsrc and fdst may be open in "t"(ext) mode
114 # - fsrc may be a BufferedReader (which hides unread data in a buffer),
115 # GzipFile (which decompresses data), HTTPResponse (which decodes
116 # chunks).
117 # - possibly others (e.g. encrypted fs/partition?)
Giampaolo Rodola413d9552019-05-30 14:05:41 +0800118 global _USE_CP_SENDFILE
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200119 try:
120 infd = fsrc.fileno()
121 outfd = fdst.fileno()
122 except Exception as err:
123 raise _GiveupOnFastCopy(err) # not a regular file
124
125 # Hopefully the whole file will be copied in a single call.
126 # sendfile() is called in a loop 'till EOF is reached (0 return)
127 # so a bufsize smaller or bigger than the actual file size
128 # should not make any difference, also in case the file content
129 # changes while being copied.
130 try:
Giampaolo Rodola94e16502019-10-01 11:40:54 +0800131 blocksize = max(os.fstat(infd).st_size, 2 ** 23) # min 8MiB
132 except OSError:
133 blocksize = 2 ** 27 # 128MiB
134 # On 32-bit architectures truncate to 1GiB to avoid OverflowError,
135 # see bpo-38319.
136 if sys.maxsize < 2 ** 32:
137 blocksize = min(blocksize, 2 ** 30)
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200138
139 offset = 0
140 while True:
141 try:
142 sent = os.sendfile(outfd, infd, offset, blocksize)
143 except OSError as err:
144 # ...in oder to have a more informative exception.
145 err.filename = fsrc.name
146 err.filename2 = fdst.name
147
148 if err.errno == errno.ENOTSOCK:
149 # sendfile() on this platform (probably Linux < 2.6.33)
150 # does not support copies between regular files (only
151 # sockets).
Giampaolo Rodola413d9552019-05-30 14:05:41 +0800152 _USE_CP_SENDFILE = False
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200153 raise _GiveupOnFastCopy(err)
154
155 if err.errno == errno.ENOSPC: # filesystem is full
156 raise err from None
157
158 # Give up on first call and if no data was copied.
159 if offset == 0 and os.lseek(outfd, 0, os.SEEK_CUR) == 0:
160 raise _GiveupOnFastCopy(err)
161
162 raise err
163 else:
164 if sent == 0:
165 break # EOF
166 offset += sent
167
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700168def _copyfileobj_readinto(fsrc, fdst, length=COPY_BUFSIZE):
169 """readinto()/memoryview() based variant of copyfileobj().
170 *fsrc* must support readinto() method and both files must be
171 open in binary mode.
172 """
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200173 # Localize variable access to minimize overhead.
174 fsrc_readinto = fsrc.readinto
175 fdst_write = fdst.write
176 with memoryview(bytearray(length)) as mv:
177 while True:
178 n = fsrc_readinto(mv)
179 if not n:
180 break
181 elif n < length:
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700182 with mv[:n] as smv:
183 fdst.write(smv)
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200184 else:
185 fdst_write(mv)
186
Giampaolo Rodola3b0abb02019-02-24 15:46:40 -0800187def copyfileobj(fsrc, fdst, length=0):
Greg Stein42bb8b32000-07-12 09:55:30 +0000188 """copy data from file-like object fsrc to file-like object fdst"""
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700189 # Localize variable access to minimize overhead.
Giampaolo Rodola3b0abb02019-02-24 15:46:40 -0800190 if not length:
191 length = COPY_BUFSIZE
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700192 fsrc_read = fsrc.read
193 fdst_write = fdst.write
194 while True:
195 buf = fsrc_read(length)
196 if not buf:
197 break
198 fdst_write(buf)
Greg Stein42bb8b32000-07-12 09:55:30 +0000199
Johannes Gijsbers46f14592004-08-14 13:30:02 +0000200def _samefile(src, dst):
201 # Macintosh, Unix.
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800202 if isinstance(src, os.DirEntry) and hasattr(os.path, 'samestat'):
203 try:
204 return os.path.samestat(src.stat(), os.stat(dst))
205 except OSError:
206 return False
207
Tarek Ziadé1eab9cc2010-04-19 21:19:57 +0000208 if hasattr(os.path, 'samefile'):
Johannes Gijsbersf9a098e2004-08-14 14:51:01 +0000209 try:
210 return os.path.samefile(src, dst)
211 except OSError:
212 return False
Johannes Gijsbers46f14592004-08-14 13:30:02 +0000213
214 # All other platforms: check for same pathname.
215 return (os.path.normcase(os.path.abspath(src)) ==
216 os.path.normcase(os.path.abspath(dst)))
Tim Peters495ad3c2001-01-15 01:36:40 +0000217
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800218def _stat(fn):
219 return fn.stat() if isinstance(fn, os.DirEntry) else os.stat(fn)
220
221def _islink(fn):
222 return fn.is_symlink() if isinstance(fn, os.DirEntry) else os.path.islink(fn)
223
Larry Hastingsb4038062012-07-15 10:57:38 -0700224def copyfile(src, dst, *, follow_symlinks=True):
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700225 """Copy data from src to dst in the most efficient way possible.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100226
Larry Hastingsb4038062012-07-15 10:57:38 -0700227 If follow_symlinks is not set and src is a symbolic link, a new
Antoine Pitrou78091e62011-12-29 18:54:15 +0100228 symlink will be created instead of copying the file it points to.
229
230 """
Saiyang Gou7514f4f2020-02-12 23:47:42 -0800231 sys.audit("shutil.copyfile", src, dst)
232
Johannes Gijsbers46f14592004-08-14 13:30:02 +0000233 if _samefile(src, dst):
Hynek Schlawack48653762012-10-07 12:49:58 +0200234 raise SameFileError("{!r} and {!r} are the same file".format(src, dst))
Johannes Gijsbers46f14592004-08-14 13:30:02 +0000235
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700236 file_size = 0
237 for i, fn in enumerate([src, dst]):
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000238 try:
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800239 st = _stat(fn)
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000240 except OSError:
241 # File most likely does not exist
242 pass
Benjamin Petersonc0d98aa2009-06-05 19:13:27 +0000243 else:
244 # XXX What about other special files? (sockets, devices...)
245 if stat.S_ISFIFO(st.st_mode):
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800246 fn = fn.path if isinstance(fn, os.DirEntry) else fn
Benjamin Petersonc0d98aa2009-06-05 19:13:27 +0000247 raise SpecialFileError("`%s` is a named pipe" % fn)
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700248 if _WINDOWS and i == 0:
249 file_size = st.st_size
Tarek Ziadéb01142b2010-05-05 22:43:04 +0000250
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800251 if not follow_symlinks and _islink(src):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100252 os.symlink(os.readlink(src), dst)
253 else:
Miss Islington (bot)41d48bc2021-09-21 15:14:40 -0700254 with open(src, 'rb') as fsrc:
255 try:
256 with open(dst, 'wb') as fdst:
257 # macOS
258 if _HAS_FCOPYFILE:
259 try:
260 _fastcopy_fcopyfile(fsrc, fdst, posix._COPYFILE_DATA)
261 return dst
262 except _GiveupOnFastCopy:
263 pass
264 # Linux
265 elif _USE_CP_SENDFILE:
266 try:
267 _fastcopy_sendfile(fsrc, fdst)
268 return dst
269 except _GiveupOnFastCopy:
270 pass
271 # Windows, see:
272 # https://github.com/python/cpython/pull/7160#discussion_r195405230
273 elif _WINDOWS and file_size > 0:
274 _copyfileobj_readinto(fsrc, fdst, min(file_size, COPY_BUFSIZE))
Miss Islington (bot)15772592021-07-09 21:07:35 -0700275 return dst
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200276
Miss Islington (bot)41d48bc2021-09-21 15:14:40 -0700277 copyfileobj(fsrc, fdst)
Miss Islington (bot)15772592021-07-09 21:07:35 -0700278
Miss Islington (bot)41d48bc2021-09-21 15:14:40 -0700279 # Issue 43219, raise a less confusing exception
280 except IsADirectoryError as e:
281 if not os.path.exists(dst):
282 raise FileNotFoundError(f'Directory does not exist: {dst}') from e
283 else:
284 raise
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200285
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500286 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000287
Larry Hastingsb4038062012-07-15 10:57:38 -0700288def copymode(src, dst, *, follow_symlinks=True):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100289 """Copy mode bits from src to dst.
Guido van Rossumc6360141990-10-13 19:23:40 +0000290
Larry Hastingsb4038062012-07-15 10:57:38 -0700291 If follow_symlinks is not set, symlinks aren't followed if and only
292 if both `src` and `dst` are symlinks. If `lchmod` isn't available
293 (e.g. Linux) this method does nothing.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100294
295 """
Saiyang Gou7514f4f2020-02-12 23:47:42 -0800296 sys.audit("shutil.copymode", src, dst)
297
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800298 if not follow_symlinks and _islink(src) and os.path.islink(dst):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100299 if hasattr(os, 'lchmod'):
300 stat_func, chmod_func = os.lstat, os.lchmod
301 else:
302 return
Antoine Pitrou78091e62011-12-29 18:54:15 +0100303 else:
Anthony Sottile8377cd42019-02-25 14:32:27 -0800304 stat_func, chmod_func = _stat, os.chmod
Antoine Pitrou78091e62011-12-29 18:54:15 +0100305
306 st = stat_func(src)
307 chmod_func(dst, stat.S_IMODE(st.st_mode))
308
Larry Hastingsad5ae042012-07-14 17:55:11 -0700309if hasattr(os, 'listxattr'):
Larry Hastingsb4038062012-07-15 10:57:38 -0700310 def _copyxattr(src, dst, *, follow_symlinks=True):
Larry Hastingsad5ae042012-07-14 17:55:11 -0700311 """Copy extended filesystem attributes from `src` to `dst`.
312
313 Overwrite existing attributes.
314
Larry Hastingsb4038062012-07-15 10:57:38 -0700315 If `follow_symlinks` is false, symlinks won't be followed.
Larry Hastingsad5ae042012-07-14 17:55:11 -0700316
317 """
318
Hynek Schlawack0beab052013-02-05 08:22:44 +0100319 try:
320 names = os.listxattr(src, follow_symlinks=follow_symlinks)
321 except OSError as e:
Ying Wanga16387a2019-05-29 23:25:31 -0400322 if e.errno not in (errno.ENOTSUP, errno.ENODATA, errno.EINVAL):
Hynek Schlawack0beab052013-02-05 08:22:44 +0100323 raise
324 return
325 for name in names:
Larry Hastingsad5ae042012-07-14 17:55:11 -0700326 try:
Larry Hastingsb4038062012-07-15 10:57:38 -0700327 value = os.getxattr(src, name, follow_symlinks=follow_symlinks)
328 os.setxattr(dst, name, value, follow_symlinks=follow_symlinks)
Larry Hastingsad5ae042012-07-14 17:55:11 -0700329 except OSError as e:
Ying Wanga16387a2019-05-29 23:25:31 -0400330 if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA,
331 errno.EINVAL):
Larry Hastingsad5ae042012-07-14 17:55:11 -0700332 raise
333else:
334 def _copyxattr(*args, **kwargs):
335 pass
336
Larry Hastingsb4038062012-07-15 10:57:38 -0700337def copystat(src, dst, *, follow_symlinks=True):
Zsolt Cserna4f399be2018-10-23 12:09:50 +0200338 """Copy file metadata
Antoine Pitrou78091e62011-12-29 18:54:15 +0100339
Zsolt Cserna4f399be2018-10-23 12:09:50 +0200340 Copy the permission bits, last access time, last modification time, and
341 flags from `src` to `dst`. On Linux, copystat() also copies the "extended
342 attributes" where possible. The file contents, owner, and group are
Boris Verhovsky9488a522019-09-09 09:51:56 -0600343 unaffected. `src` and `dst` are path-like objects or path names given as
344 strings.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100345
Zsolt Cserna4f399be2018-10-23 12:09:50 +0200346 If the optional flag `follow_symlinks` is not set, symlinks aren't
347 followed if and only if both `src` and `dst` are symlinks.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100348 """
Saiyang Gou7514f4f2020-02-12 23:47:42 -0800349 sys.audit("shutil.copystat", src, dst)
350
Larry Hastings9cf065c2012-06-22 16:30:09 -0700351 def _nop(*args, ns=None, follow_symlinks=None):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100352 pass
353
Larry Hastings9cf065c2012-06-22 16:30:09 -0700354 # follow symlinks (aka don't not follow symlinks)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800355 follow = follow_symlinks or not (_islink(src) and os.path.islink(dst))
Larry Hastings9cf065c2012-06-22 16:30:09 -0700356 if follow:
357 # use the real function if it exists
358 def lookup(name):
359 return getattr(os, name, _nop)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100360 else:
Larry Hastings9cf065c2012-06-22 16:30:09 -0700361 # use the real function only if it exists
362 # *and* it supports follow_symlinks
363 def lookup(name):
364 fn = getattr(os, name, _nop)
365 if fn in os.supports_follow_symlinks:
366 return fn
367 return _nop
Antoine Pitrou78091e62011-12-29 18:54:15 +0100368
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800369 if isinstance(src, os.DirEntry):
370 st = src.stat(follow_symlinks=follow)
371 else:
372 st = lookup("stat")(src, follow_symlinks=follow)
Walter Dörwald294bbf32002-06-06 09:48:13 +0000373 mode = stat.S_IMODE(st.st_mode)
Larry Hastings9cf065c2012-06-22 16:30:09 -0700374 lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns),
375 follow_symlinks=follow)
Olexa Bilaniuk79efbb72019-05-09 22:22:06 -0500376 # We must copy extended attributes before the file is (potentially)
377 # chmod()'ed read-only, otherwise setxattr() will error with -EACCES.
378 _copyxattr(src, dst, follow_symlinks=follow)
Larry Hastings9cf065c2012-06-22 16:30:09 -0700379 try:
380 lookup("chmod")(dst, mode, follow_symlinks=follow)
381 except NotImplementedError:
382 # if we got a NotImplementedError, it's because
383 # * follow_symlinks=False,
384 # * lchown() is unavailable, and
385 # * either
Ezio Melotti30b9d5d2013-08-17 15:50:46 +0300386 # * fchownat() is unavailable or
Larry Hastings9cf065c2012-06-22 16:30:09 -0700387 # * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW.
388 # (it returned ENOSUP.)
389 # therefore we're out of options--we simply cannot chown the
390 # symlink. give up, suppress the error.
391 # (which is what shutil always did in this circumstance.)
392 pass
Antoine Pitrou78091e62011-12-29 18:54:15 +0100393 if hasattr(st, 'st_flags'):
Antoine Pitrou910bd512010-03-22 20:11:09 +0000394 try:
Larry Hastings9cf065c2012-06-22 16:30:09 -0700395 lookup("chflags")(dst, st.st_flags, follow_symlinks=follow)
Antoine Pitrou910bd512010-03-22 20:11:09 +0000396 except OSError as why:
Ned Deilybaf75712012-05-10 17:05:19 -0700397 for err in 'EOPNOTSUPP', 'ENOTSUP':
398 if hasattr(errno, err) and why.errno == getattr(errno, err):
399 break
400 else:
Antoine Pitrou910bd512010-03-22 20:11:09 +0000401 raise
Antoine Pitrou424246f2012-05-12 19:02:01 +0200402
Larry Hastingsb4038062012-07-15 10:57:38 -0700403def copy(src, dst, *, follow_symlinks=True):
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500404 """Copy data and mode bits ("cp src dst"). Return the file's destination.
Tim Peters495ad3c2001-01-15 01:36:40 +0000405
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000406 The destination may be a directory.
407
Larry Hastingsb4038062012-07-15 10:57:38 -0700408 If follow_symlinks is false, symlinks won't be followed. This
Antoine Pitrou78091e62011-12-29 18:54:15 +0100409 resembles GNU's "cp -P src dst".
410
Hynek Schlawack48653762012-10-07 12:49:58 +0200411 If source and destination are the same file, a SameFileError will be
412 raised.
413
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000414 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000415 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000416 dst = os.path.join(dst, os.path.basename(src))
Larry Hastingsb4038062012-07-15 10:57:38 -0700417 copyfile(src, dst, follow_symlinks=follow_symlinks)
418 copymode(src, dst, follow_symlinks=follow_symlinks)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500419 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000420
Larry Hastingsb4038062012-07-15 10:57:38 -0700421def copy2(src, dst, *, follow_symlinks=True):
Zsolt Cserna4f399be2018-10-23 12:09:50 +0200422 """Copy data and metadata. Return the file's destination.
423
424 Metadata is copied with copystat(). Please see the copystat function
425 for more information.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000426
427 The destination may be a directory.
428
Larry Hastingsb4038062012-07-15 10:57:38 -0700429 If follow_symlinks is false, symlinks won't be followed. This
Antoine Pitrou78091e62011-12-29 18:54:15 +0100430 resembles GNU's "cp -P src dst".
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000431 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000432 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000433 dst = os.path.join(dst, os.path.basename(src))
Larry Hastingsb4038062012-07-15 10:57:38 -0700434 copyfile(src, dst, follow_symlinks=follow_symlinks)
435 copystat(src, dst, follow_symlinks=follow_symlinks)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500436 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000437
Georg Brandl2ee470f2008-07-16 12:55:28 +0000438def ignore_patterns(*patterns):
439 """Function that can be used as copytree() ignore parameter.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000440
Georg Brandl2ee470f2008-07-16 12:55:28 +0000441 Patterns is a sequence of glob-style patterns
442 that are used to exclude files"""
443 def _ignore_patterns(path, names):
444 ignored_names = []
445 for pattern in patterns:
446 ignored_names.extend(fnmatch.filter(names, pattern))
447 return set(ignored_names)
448 return _ignore_patterns
449
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800450def _copytree(entries, src, dst, symlinks, ignore, copy_function,
jab9e00d9e2018-12-28 13:03:40 -0500451 ignore_dangling_symlinks, dirs_exist_ok=False):
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800452 if ignore is not None:
mbarkhau88704332020-01-24 14:51:16 +0000453 ignored_names = ignore(os.fspath(src), [x.name for x in entries])
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800454 else:
455 ignored_names = set()
456
jab9e00d9e2018-12-28 13:03:40 -0500457 os.makedirs(dst, exist_ok=dirs_exist_ok)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800458 errors = []
459 use_srcentry = copy_function is copy2 or copy_function is copy
460
461 for srcentry in entries:
462 if srcentry.name in ignored_names:
463 continue
464 srcname = os.path.join(src, srcentry.name)
465 dstname = os.path.join(dst, srcentry.name)
466 srcobj = srcentry if use_srcentry else srcname
467 try:
Steve Dowerdf2d4a62019-08-21 15:27:33 -0700468 is_symlink = srcentry.is_symlink()
469 if is_symlink and os.name == 'nt':
470 # Special check for directory junctions, which appear as
471 # symlinks but we want to recurse.
472 lstat = srcentry.stat(follow_symlinks=False)
473 if lstat.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT:
474 is_symlink = False
475 if is_symlink:
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800476 linkto = os.readlink(srcname)
477 if symlinks:
478 # We can't just leave it to `copy_function` because legacy
479 # code with a custom `copy_function` may rely on copytree
480 # doing the right thing.
481 os.symlink(linkto, dstname)
482 copystat(srcobj, dstname, follow_symlinks=not symlinks)
483 else:
484 # ignore dangling symlink if the flag is on
485 if not os.path.exists(linkto) and ignore_dangling_symlinks:
486 continue
jab9e00d9e2018-12-28 13:03:40 -0500487 # otherwise let the copy occur. copy2 will raise an error
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800488 if srcentry.is_dir():
489 copytree(srcobj, dstname, symlinks, ignore,
jab9e00d9e2018-12-28 13:03:40 -0500490 copy_function, dirs_exist_ok=dirs_exist_ok)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800491 else:
492 copy_function(srcobj, dstname)
493 elif srcentry.is_dir():
jab9e00d9e2018-12-28 13:03:40 -0500494 copytree(srcobj, dstname, symlinks, ignore, copy_function,
495 dirs_exist_ok=dirs_exist_ok)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800496 else:
497 # Will raise a SpecialFileError for unsupported file types
Giampaolo Rodolac606a9c2019-02-26 12:04:41 +0100498 copy_function(srcobj, dstname)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800499 # catch the Error from the recursive copytree so that we can
500 # continue with other files
501 except Error as err:
502 errors.extend(err.args[0])
503 except OSError as why:
504 errors.append((srcname, dstname, str(why)))
505 try:
506 copystat(src, dst)
507 except OSError as why:
508 # Copying file access times may fail on Windows
509 if getattr(why, 'winerror', None) is None:
510 errors.append((src, dst, str(why)))
511 if errors:
512 raise Error(errors)
513 return dst
514
Tarek Ziadéfb437512010-04-20 08:57:33 +0000515def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
jab9e00d9e2018-12-28 13:03:40 -0500516 ignore_dangling_symlinks=False, dirs_exist_ok=False):
517 """Recursively copy a directory tree and return the destination directory.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000518
jab9e00d9e2018-12-28 13:03:40 -0500519 dirs_exist_ok dictates whether to raise an exception in case dst or any
520 missing parent directory already exists.
521
Neal Norwitza4c93b62003-02-23 21:36:32 +0000522 If exception(s) occur, an Error is raised with a list of reasons.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000523
524 If the optional symlinks flag is true, symbolic links in the
525 source tree result in symbolic links in the destination tree; if
526 it is false, the contents of the files pointed to by symbolic
Tarek Ziadéfb437512010-04-20 08:57:33 +0000527 links are copied. If the file pointed by the symlink doesn't
528 exist, an exception will be added in the list of errors raised in
529 an Error exception at the end of the copy process.
530
531 You can set the optional ignore_dangling_symlinks flag to true if you
Tarek Ziadé8c26c7d2010-04-23 13:03:50 +0000532 want to silence this exception. Notice that this has no effect on
533 platforms that don't support os.symlink.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000534
Georg Brandl2ee470f2008-07-16 12:55:28 +0000535 The optional ignore argument is a callable. If given, it
536 is called with the `src` parameter, which is the directory
537 being visited by copytree(), and `names` which is the list of
538 `src` contents, as returned by os.listdir():
539
540 callable(src, names) -> ignored_names
541
542 Since copytree() is called recursively, the callable will be
543 called once for each directory that is copied. It returns a
544 list of names relative to the `src` directory that should
545 not be copied.
546
Tarek Ziadé5340db32010-04-19 22:30:51 +0000547 The optional copy_function argument is a callable that will be used
548 to copy each file. It will be called with the source path and the
549 destination path as arguments. By default, copy2() is used, but any
550 function that supports the same signature (like copy()) can be used.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000551
552 """
Steve Dower60419a72019-06-24 08:42:54 -0700553 sys.audit("shutil.copytree", src, dst)
Bruno P. Kinoshita9bbcbc92019-11-27 14:10:37 +1300554 with os.scandir(src) as itr:
555 entries = list(itr)
556 return _copytree(entries=entries, src=src, dst=dst, symlinks=symlinks,
557 ignore=ignore, copy_function=copy_function,
558 ignore_dangling_symlinks=ignore_dangling_symlinks,
559 dirs_exist_ok=dirs_exist_ok)
Guido van Rossumd7673291998-02-06 21:38:09 +0000560
Ned Deily7fcc2082019-08-29 17:20:03 -0400561if hasattr(os.stat_result, 'st_file_attributes'):
Steve Dowerdf2d4a62019-08-21 15:27:33 -0700562 # Special handling for directory junctions to make them behave like
563 # symlinks for shutil.rmtree, since in general they do not appear as
564 # regular links.
565 def _rmtree_isdir(entry):
566 try:
567 st = entry.stat(follow_symlinks=False)
568 return (stat.S_ISDIR(st.st_mode) and not
569 (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT
570 and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT))
571 except OSError:
572 return False
573
574 def _rmtree_islink(path):
575 try:
576 st = os.lstat(path)
577 return (stat.S_ISLNK(st.st_mode) or
578 (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT
579 and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT))
580 except OSError:
581 return False
582else:
583 def _rmtree_isdir(entry):
584 try:
585 return entry.is_dir(follow_symlinks=False)
586 except OSError:
587 return False
588
589 def _rmtree_islink(path):
590 return os.path.islink(path)
591
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200592# version vulnerable to race conditions
593def _rmtree_unsafe(path, onerror):
Christian Heimes9bd667a2008-01-20 15:14:11 +0000594 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200595 with os.scandir(path) as scandir_it:
596 entries = list(scandir_it)
Christian Heimes9bd667a2008-01-20 15:14:11 +0000597 except OSError:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200598 onerror(os.scandir, path, sys.exc_info())
599 entries = []
600 for entry in entries:
601 fullname = entry.path
Steve Dowerdf2d4a62019-08-21 15:27:33 -0700602 if _rmtree_isdir(entry):
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200603 try:
604 if entry.is_symlink():
605 # This can only happen if someone replaces
606 # a directory with a symlink after the call to
607 # os.scandir or entry.is_dir above.
608 raise OSError("Cannot call rmtree on a symbolic link")
609 except OSError:
610 onerror(os.path.islink, fullname, sys.exc_info())
611 continue
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200612 _rmtree_unsafe(fullname, onerror)
Barry Warsaw234d9a92003-01-24 17:36:15 +0000613 else:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000614 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200615 os.unlink(fullname)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200616 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200617 onerror(os.unlink, fullname, sys.exc_info())
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000618 try:
619 os.rmdir(path)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200620 except OSError:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000621 onerror(os.rmdir, path, sys.exc_info())
Guido van Rossumd7673291998-02-06 21:38:09 +0000622
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200623# Version using fd-based APIs to protect against races
624def _rmtree_safe_fd(topfd, path, onerror):
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200625 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200626 with os.scandir(topfd) as scandir_it:
627 entries = list(scandir_it)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100628 except OSError as err:
629 err.filename = path
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200630 onerror(os.scandir, path, sys.exc_info())
631 return
632 for entry in entries:
633 fullname = os.path.join(path, entry.name)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200634 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200635 is_dir = entry.is_dir(follow_symlinks=False)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100636 except OSError:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200637 is_dir = False
Serhiy Storchakae9b51c02019-05-31 11:30:37 +0300638 else:
639 if is_dir:
640 try:
641 orig_st = entry.stat(follow_symlinks=False)
642 is_dir = stat.S_ISDIR(orig_st.st_mode)
643 except OSError:
644 onerror(os.lstat, fullname, sys.exc_info())
645 continue
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200646 if is_dir:
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200647 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200648 dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd)
Miss Islington (bot)95d62712022-02-21 00:07:46 -0800649 dirfd_closed = False
Hynek Schlawackb5501102012-12-10 09:11:25 +0100650 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200651 onerror(os.open, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200652 else:
653 try:
654 if os.path.samestat(orig_st, os.fstat(dirfd)):
655 _rmtree_safe_fd(dirfd, fullname, onerror)
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200656 try:
Miss Islington (bot)95d62712022-02-21 00:07:46 -0800657 os.close(dirfd)
658 dirfd_closed = True
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200659 os.rmdir(entry.name, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100660 except OSError:
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200661 onerror(os.rmdir, fullname, sys.exc_info())
Hynek Schlawackb5501102012-12-10 09:11:25 +0100662 else:
663 try:
664 # This can only happen if someone replaces
665 # a directory with a symlink after the call to
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200666 # os.scandir or stat.S_ISDIR above.
Hynek Schlawackb5501102012-12-10 09:11:25 +0100667 raise OSError("Cannot call rmtree on a symbolic "
668 "link")
669 except OSError:
670 onerror(os.path.islink, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200671 finally:
Miss Islington (bot)95d62712022-02-21 00:07:46 -0800672 if not dirfd_closed:
673 os.close(dirfd)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200674 else:
675 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200676 os.unlink(entry.name, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100677 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200678 onerror(os.unlink, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200679
Hynek Schlawackd0f6e0a2012-06-29 08:28:20 +0200680_use_fd_functions = ({os.open, os.stat, os.unlink, os.rmdir} <=
681 os.supports_dir_fd and
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200682 os.scandir in os.supports_fd and
Hynek Schlawackd0f6e0a2012-06-29 08:28:20 +0200683 os.stat in os.supports_follow_symlinks)
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000684
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200685def rmtree(path, ignore_errors=False, onerror=None):
686 """Recursively delete a directory tree.
687
688 If ignore_errors is set, errors are ignored; otherwise, if onerror
689 is set, it is called to handle the error with arguments (func,
Hynek Schlawack2100b422012-06-23 20:28:32 +0200690 path, exc_info) where func is platform and implementation dependent;
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200691 path is the argument to that function that caused it to fail; and
692 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
693 is false and onerror is None, an exception is raised.
694
695 """
Steve Dower60419a72019-06-24 08:42:54 -0700696 sys.audit("shutil.rmtree", path)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200697 if ignore_errors:
698 def onerror(*args):
699 pass
700 elif onerror is None:
701 def onerror(*args):
702 raise
703 if _use_fd_functions:
Hynek Schlawack3b527782012-06-25 13:27:31 +0200704 # While the unsafe rmtree works fine on bytes, the fd based does not.
705 if isinstance(path, bytes):
706 path = os.fsdecode(path)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200707 # Note: To guard against symlink races, we use the standard
708 # lstat()/open()/fstat() trick.
709 try:
710 orig_st = os.lstat(path)
711 except Exception:
712 onerror(os.lstat, path, sys.exc_info())
713 return
714 try:
715 fd = os.open(path, os.O_RDONLY)
Miss Islington (bot)95d62712022-02-21 00:07:46 -0800716 fd_closed = False
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200717 except Exception:
Michal Čihaře59b2de2020-11-10 17:06:02 +0100718 onerror(os.open, path, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200719 return
720 try:
Hynek Schlawackb5501102012-12-10 09:11:25 +0100721 if os.path.samestat(orig_st, os.fstat(fd)):
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200722 _rmtree_safe_fd(fd, path, onerror)
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200723 try:
Miss Islington (bot)95d62712022-02-21 00:07:46 -0800724 os.close(fd)
725 fd_closed = True
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200726 os.rmdir(path)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200727 except OSError:
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200728 onerror(os.rmdir, path, sys.exc_info())
Hynek Schlawacka75cd1c2012-06-28 12:07:29 +0200729 else:
Hynek Schlawackb5501102012-12-10 09:11:25 +0100730 try:
731 # symlinks to directories are forbidden, see bug #1669
732 raise OSError("Cannot call rmtree on a symbolic link")
733 except OSError:
734 onerror(os.path.islink, path, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200735 finally:
Miss Islington (bot)95d62712022-02-21 00:07:46 -0800736 if not fd_closed:
737 os.close(fd)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200738 else:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200739 try:
Steve Dowerdf2d4a62019-08-21 15:27:33 -0700740 if _rmtree_islink(path):
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200741 # symlinks to directories are forbidden, see bug #1669
742 raise OSError("Cannot call rmtree on a symbolic link")
743 except OSError:
744 onerror(os.path.islink, path, sys.exc_info())
745 # can't continue even if onerror hook returns
746 return
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200747 return _rmtree_unsafe(path, onerror)
748
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000749# Allow introspection of whether or not the hardening against symlink
750# attacks is supported on the current platform
751rmtree.avoids_symlink_attacks = _use_fd_functions
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000752
Christian Heimesada8c3b2008-03-18 18:26:33 +0000753def _basename(path):
Maxwell A McKinnoncf57cab2019-09-30 19:41:16 -0700754 """A basename() variant which first strips the trailing slash, if present.
755 Thus we always get the last component of the path, even for directories.
756
757 path: Union[PathLike, str]
758
759 e.g.
760 >>> os.path.basename('/bar/foo')
761 'foo'
762 >>> os.path.basename('/bar/foo/')
763 ''
764 >>> _basename('/bar/foo/')
765 'foo'
766 """
767 path = os.fspath(path)
Serhiy Storchaka3a308b92014-02-11 10:30:59 +0200768 sep = os.path.sep + (os.path.altsep or '')
769 return os.path.basename(path.rstrip(sep))
Christian Heimesada8c3b2008-03-18 18:26:33 +0000770
R David Murray6ffface2014-06-11 14:40:13 -0400771def move(src, dst, copy_function=copy2):
Christian Heimesada8c3b2008-03-18 18:26:33 +0000772 """Recursively move a file or directory to another location. This is
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500773 similar to the Unix "mv" command. Return the file or directory's
774 destination.
Christian Heimesada8c3b2008-03-18 18:26:33 +0000775
776 If the destination is a directory or a symlink to a directory, the source
777 is moved inside the directory. The destination path must not already
778 exist.
779
780 If the destination already exists but is not a directory, it may be
781 overwritten depending on os.rename() semantics.
782
783 If the destination is on our current filesystem, then rename() is used.
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +0100784 Otherwise, src is copied to the destination and then removed. Symlinks are
785 recreated under the new name if os.rename() fails because of cross
786 filesystem renames.
787
R David Murray6ffface2014-06-11 14:40:13 -0400788 The optional `copy_function` argument is a callable that will be used
789 to copy the source or it will be delegated to `copytree`.
790 By default, copy2() is used, but any function that supports the same
791 signature (like copy()) can be used.
792
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000793 A lot more could be done here... A look at a mv.c shows a lot of
794 the issues this implementation glosses over.
795
796 """
Saiyang Gou7514f4f2020-02-12 23:47:42 -0800797 sys.audit("shutil.move", src, dst)
Christian Heimesada8c3b2008-03-18 18:26:33 +0000798 real_dst = dst
799 if os.path.isdir(dst):
Ronald Oussorenf51738b2011-05-06 10:23:04 +0200800 if _samefile(src, dst):
801 # We might be on a case insensitive filesystem,
802 # perform the rename anyway.
803 os.rename(src, dst)
804 return
805
Maxwell A McKinnoncf57cab2019-09-30 19:41:16 -0700806 # Using _basename instead of os.path.basename is important, as we must
807 # ignore any trailing slash to avoid the basename returning ''
Christian Heimesada8c3b2008-03-18 18:26:33 +0000808 real_dst = os.path.join(dst, _basename(src))
Maxwell A McKinnoncf57cab2019-09-30 19:41:16 -0700809
Christian Heimesada8c3b2008-03-18 18:26:33 +0000810 if os.path.exists(real_dst):
811 raise Error("Destination path '%s' already exists" % real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000812 try:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000813 os.rename(src, real_dst)
Éric Araujocfcc9772011-08-10 20:54:33 +0200814 except OSError:
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +0100815 if os.path.islink(src):
816 linkto = os.readlink(src)
817 os.symlink(linkto, real_dst)
818 os.unlink(src)
819 elif os.path.isdir(src):
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000820 if _destinsrc(src, dst):
R David Murray6ffface2014-06-11 14:40:13 -0400821 raise Error("Cannot move a directory '%s' into itself"
822 " '%s'." % (src, dst))
Winson Luk132131b2021-03-02 15:53:15 -0500823 if (_is_immutable(src)
824 or (not os.access(src, os.W_OK) and os.listdir(src)
825 and sys.platform == 'darwin')):
826 raise PermissionError("Cannot move the non-empty directory "
827 "'%s': Lacking write permission to '%s'."
828 % (src, src))
R David Murray6ffface2014-06-11 14:40:13 -0400829 copytree(src, real_dst, copy_function=copy_function,
830 symlinks=True)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000831 rmtree(src)
832 else:
R David Murray6ffface2014-06-11 14:40:13 -0400833 copy_function(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000834 os.unlink(src)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500835 return real_dst
Brett Cannon1c3fa182004-06-19 21:11:35 +0000836
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000837def _destinsrc(src, dst):
Berker Peksag3715da52014-09-18 05:11:15 +0300838 src = os.path.abspath(src)
839 dst = os.path.abspath(dst)
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +0000840 if not src.endswith(os.path.sep):
841 src += os.path.sep
842 if not dst.endswith(os.path.sep):
843 dst += os.path.sep
844 return dst.startswith(src)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000845
Winson Luk132131b2021-03-02 15:53:15 -0500846def _is_immutable(src):
847 st = _stat(src)
848 immutable_states = [stat.UF_IMMUTABLE, stat.SF_IMMUTABLE]
849 return hasattr(st, 'st_flags') and st.st_flags in immutable_states
850
Tarek Ziadé396fad72010-02-23 05:30:31 +0000851def _get_gid(name):
852 """Returns a gid, given a group name."""
Victor Stinnerd72e8d42021-03-23 17:42:51 +0100853 if name is None:
Tarek Ziadé396fad72010-02-23 05:30:31 +0000854 return None
Victor Stinnerd72e8d42021-03-23 17:42:51 +0100855
856 try:
857 from grp import getgrnam
858 except ImportError:
859 return None
860
Tarek Ziadé396fad72010-02-23 05:30:31 +0000861 try:
862 result = getgrnam(name)
863 except KeyError:
864 result = None
865 if result is not None:
866 return result[2]
867 return None
868
869def _get_uid(name):
870 """Returns an uid, given a user name."""
Victor Stinnerd72e8d42021-03-23 17:42:51 +0100871 if name is None:
Tarek Ziadé396fad72010-02-23 05:30:31 +0000872 return None
Victor Stinnerd72e8d42021-03-23 17:42:51 +0100873
874 try:
875 from pwd import getpwnam
876 except ImportError:
877 return None
878
Tarek Ziadé396fad72010-02-23 05:30:31 +0000879 try:
880 result = getpwnam(name)
881 except KeyError:
882 result = None
883 if result is not None:
884 return result[2]
885 return None
886
887def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
888 owner=None, group=None, logger=None):
889 """Create a (possibly compressed) tar file from all the files under
890 'base_dir'.
891
Serhiy Storchaka11213772014-08-06 18:50:19 +0300892 'compress' must be "gzip" (the default), "bzip2", "xz", or None.
Tarek Ziadé396fad72010-02-23 05:30:31 +0000893
894 'owner' and 'group' can be used to define an owner and a group for the
895 archive that is being built. If not provided, the current owner and group
896 will be used.
897
Éric Araujo4433a5f2010-12-15 20:26:30 +0000898 The output tar file will be named 'base_name' + ".tar", possibly plus
Serhiy Storchaka11213772014-08-06 18:50:19 +0300899 the appropriate compression extension (".gz", ".bz2", or ".xz").
Tarek Ziadé396fad72010-02-23 05:30:31 +0000900
901 Returns the output filename.
902 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200903 if compress is None:
904 tar_compression = ''
905 elif _ZLIB_SUPPORTED and compress == 'gzip':
906 tar_compression = 'gz'
907 elif _BZ2_SUPPORTED and compress == 'bzip2':
908 tar_compression = 'bz2'
909 elif _LZMA_SUPPORTED and compress == 'xz':
910 tar_compression = 'xz'
911 else:
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000912 raise ValueError("bad value for 'compress', or compression format not "
913 "supported : {0}".format(compress))
Tarek Ziadé396fad72010-02-23 05:30:31 +0000914
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200915 import tarfile # late import for breaking circular dependency
916
917 compress_ext = '.' + tar_compression if compress else ''
918 archive_name = base_name + '.tar' + compress_ext
Tarek Ziadé396fad72010-02-23 05:30:31 +0000919 archive_dir = os.path.dirname(archive_name)
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000920
Serhiy Storchaka9a4fc192014-11-28 00:48:46 +0200921 if archive_dir and not os.path.exists(archive_dir):
Éric Araujoac4e58e2011-01-29 20:32:11 +0000922 if logger is not None:
Éric Araujo43a7ee12011-08-19 02:55:11 +0200923 logger.info("creating %s", archive_dir)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000924 if not dry_run:
925 os.makedirs(archive_dir)
926
Tarek Ziadé396fad72010-02-23 05:30:31 +0000927 # creating the tarball
Tarek Ziadé396fad72010-02-23 05:30:31 +0000928 if logger is not None:
929 logger.info('Creating tar archive')
930
931 uid = _get_uid(owner)
932 gid = _get_gid(group)
933
934 def _set_uid_gid(tarinfo):
935 if gid is not None:
936 tarinfo.gid = gid
937 tarinfo.gname = group
938 if uid is not None:
939 tarinfo.uid = uid
940 tarinfo.uname = owner
941 return tarinfo
942
943 if not dry_run:
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200944 tar = tarfile.open(archive_name, 'w|%s' % tar_compression)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000945 try:
946 tar.add(base_dir, filter=_set_uid_gid)
947 finally:
948 tar.close()
949
Tarek Ziadé396fad72010-02-23 05:30:31 +0000950 return archive_name
951
Tarek Ziadé396fad72010-02-23 05:30:31 +0000952def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
953 """Create a zip file from all the files under 'base_dir'.
954
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200955 The output zip file will be named 'base_name' + ".zip". Returns the
956 name of the output zip file.
Tarek Ziadé396fad72010-02-23 05:30:31 +0000957 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200958 import zipfile # late import for breaking circular dependency
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400959
Tarek Ziadé396fad72010-02-23 05:30:31 +0000960 zip_filename = base_name + ".zip"
961 archive_dir = os.path.dirname(base_name)
962
Serhiy Storchaka9a4fc192014-11-28 00:48:46 +0200963 if archive_dir and not os.path.exists(archive_dir):
Tarek Ziadé396fad72010-02-23 05:30:31 +0000964 if logger is not None:
965 logger.info("creating %s", archive_dir)
966 if not dry_run:
967 os.makedirs(archive_dir)
968
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400969 if logger is not None:
970 logger.info("creating '%s' and adding '%s' to it",
971 zip_filename, base_dir)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000972
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400973 if not dry_run:
974 with zipfile.ZipFile(zip_filename, "w",
975 compression=zipfile.ZIP_DEFLATED) as zf:
Serhiy Storchakad941d7a2015-09-08 05:51:00 +0300976 path = os.path.normpath(base_dir)
Serhiy Storchaka666de772016-10-23 15:55:09 +0300977 if path != os.curdir:
978 zf.write(path, path)
979 if logger is not None:
980 logger.info("adding '%s'", path)
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400981 for dirpath, dirnames, filenames in os.walk(base_dir):
Serhiy Storchakad941d7a2015-09-08 05:51:00 +0300982 for name in sorted(dirnames):
983 path = os.path.normpath(os.path.join(dirpath, name))
984 zf.write(path, path)
985 if logger is not None:
986 logger.info("adding '%s'", path)
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400987 for name in filenames:
988 path = os.path.normpath(os.path.join(dirpath, name))
989 if os.path.isfile(path):
990 zf.write(path, path)
991 if logger is not None:
992 logger.info("adding '%s'", path)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000993
994 return zip_filename
995
996_ARCHIVE_FORMATS = {
Tarek Ziadé396fad72010-02-23 05:30:31 +0000997 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"),
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200998}
999
1000if _ZLIB_SUPPORTED:
1001 _ARCHIVE_FORMATS['gztar'] = (_make_tarball, [('compress', 'gzip')],
1002 "gzip'ed tar-file")
1003 _ARCHIVE_FORMATS['zip'] = (_make_zipfile, [], "ZIP file")
Tarek Ziadé396fad72010-02-23 05:30:31 +00001004
Tarek Ziadéffa155a2010-04-29 13:34:35 +00001005if _BZ2_SUPPORTED:
1006 _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')],
1007 "bzip2'ed tar-file")
1008
Serhiy Storchaka11213772014-08-06 18:50:19 +03001009if _LZMA_SUPPORTED:
1010 _ARCHIVE_FORMATS['xztar'] = (_make_tarball, [('compress', 'xz')],
1011 "xz'ed tar-file")
1012
Tarek Ziadé396fad72010-02-23 05:30:31 +00001013def get_archive_formats():
1014 """Returns a list of supported formats for archiving and unarchiving.
1015
1016 Each element of the returned sequence is a tuple (name, description)
1017 """
1018 formats = [(name, registry[2]) for name, registry in
1019 _ARCHIVE_FORMATS.items()]
1020 formats.sort()
1021 return formats
1022
1023def register_archive_format(name, function, extra_args=None, description=''):
1024 """Registers an archive format.
1025
1026 name is the name of the format. function is the callable that will be
1027 used to create archives. If provided, extra_args is a sequence of
1028 (name, value) tuples that will be passed as arguments to the callable.
1029 description can be provided to describe the format, and will be returned
1030 by the get_archive_formats() function.
1031 """
1032 if extra_args is None:
1033 extra_args = []
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001034 if not callable(function):
Tarek Ziadé396fad72010-02-23 05:30:31 +00001035 raise TypeError('The %s object is not callable' % function)
1036 if not isinstance(extra_args, (tuple, list)):
1037 raise TypeError('extra_args needs to be a sequence')
1038 for element in extra_args:
Éric Araujoc1b7e7f2011-09-18 23:12:30 +02001039 if not isinstance(element, (tuple, list)) or len(element) !=2:
Tarek Ziadé396fad72010-02-23 05:30:31 +00001040 raise TypeError('extra_args elements are : (arg_name, value)')
1041
1042 _ARCHIVE_FORMATS[name] = (function, extra_args, description)
1043
1044def unregister_archive_format(name):
1045 del _ARCHIVE_FORMATS[name]
1046
1047def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
1048 dry_run=0, owner=None, group=None, logger=None):
1049 """Create an archive file (eg. zip or tar).
1050
1051 'base_name' is the name of the file to create, minus any format-specific
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +02001052 extension; 'format' is the archive format: one of "zip", "tar", "gztar",
1053 "bztar", or "xztar". Or any other registered format.
Tarek Ziadé396fad72010-02-23 05:30:31 +00001054
1055 'root_dir' is a directory that will be the root directory of the
1056 archive; ie. we typically chdir into 'root_dir' before creating the
1057 archive. 'base_dir' is the directory where we start archiving from;
1058 ie. 'base_dir' will be the common prefix of all files and
1059 directories in the archive. 'root_dir' and 'base_dir' both default
1060 to the current directory. Returns the name of the archive file.
1061
1062 'owner' and 'group' are used when creating a tar archive. By default,
1063 uses the current owner and group.
1064 """
Steve Dower60419a72019-06-24 08:42:54 -07001065 sys.audit("shutil.make_archive", base_name, format, root_dir, base_dir)
Tarek Ziadé396fad72010-02-23 05:30:31 +00001066 save_cwd = os.getcwd()
1067 if root_dir is not None:
1068 if logger is not None:
1069 logger.debug("changing into '%s'", root_dir)
1070 base_name = os.path.abspath(base_name)
1071 if not dry_run:
1072 os.chdir(root_dir)
1073
1074 if base_dir is None:
1075 base_dir = os.curdir
1076
1077 kwargs = {'dry_run': dry_run, 'logger': logger}
1078
1079 try:
1080 format_info = _ARCHIVE_FORMATS[format]
1081 except KeyError:
Serhiy Storchaka5affd232017-04-05 09:37:24 +03001082 raise ValueError("unknown archive format '%s'" % format) from None
Tarek Ziadé396fad72010-02-23 05:30:31 +00001083
1084 func = format_info[0]
1085 for arg, val in format_info[1]:
1086 kwargs[arg] = val
1087
1088 if format != 'zip':
1089 kwargs['owner'] = owner
1090 kwargs['group'] = group
1091
1092 try:
1093 filename = func(base_name, base_dir, **kwargs)
1094 finally:
1095 if root_dir is not None:
1096 if logger is not None:
1097 logger.debug("changing back to '%s'", save_cwd)
1098 os.chdir(save_cwd)
1099
1100 return filename
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001101
1102
1103def get_unpack_formats():
1104 """Returns a list of supported formats for unpacking.
1105
1106 Each element of the returned sequence is a tuple
1107 (name, extensions, description)
1108 """
1109 formats = [(name, info[0], info[3]) for name, info in
1110 _UNPACK_FORMATS.items()]
1111 formats.sort()
1112 return formats
1113
1114def _check_unpack_options(extensions, function, extra_args):
1115 """Checks what gets registered as an unpacker."""
1116 # first make sure no other unpacker is registered for this extension
1117 existing_extensions = {}
1118 for name, info in _UNPACK_FORMATS.items():
1119 for ext in info[0]:
1120 existing_extensions[ext] = name
1121
1122 for extension in extensions:
1123 if extension in existing_extensions:
1124 msg = '%s is already registered for "%s"'
1125 raise RegistryError(msg % (extension,
1126 existing_extensions[extension]))
1127
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001128 if not callable(function):
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001129 raise TypeError('The registered function must be a callable')
1130
1131
1132def register_unpack_format(name, extensions, function, extra_args=None,
1133 description=''):
1134 """Registers an unpack format.
1135
1136 `name` is the name of the format. `extensions` is a list of extensions
1137 corresponding to the format.
1138
1139 `function` is the callable that will be
1140 used to unpack archives. The callable will receive archives to unpack.
1141 If it's unable to handle an archive, it needs to raise a ReadError
1142 exception.
1143
1144 If provided, `extra_args` is a sequence of
1145 (name, value) tuples that will be passed as arguments to the callable.
1146 description can be provided to describe the format, and will be returned
1147 by the get_unpack_formats() function.
1148 """
1149 if extra_args is None:
1150 extra_args = []
1151 _check_unpack_options(extensions, function, extra_args)
1152 _UNPACK_FORMATS[name] = extensions, function, extra_args, description
1153
1154def unregister_unpack_format(name):
Martin Pantereb995702016-07-28 01:11:04 +00001155 """Removes the pack format from the registry."""
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001156 del _UNPACK_FORMATS[name]
1157
1158def _ensure_directory(path):
1159 """Ensure that the parent directory of `path` exists"""
1160 dirname = os.path.dirname(path)
1161 if not os.path.isdir(dirname):
1162 os.makedirs(dirname)
1163
1164def _unpack_zipfile(filename, extract_dir):
1165 """Unpack zip `filename` to `extract_dir`
1166 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +02001167 import zipfile # late import for breaking circular dependency
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001168
1169 if not zipfile.is_zipfile(filename):
1170 raise ReadError("%s is not a zip file" % filename)
1171
1172 zip = zipfile.ZipFile(filename)
1173 try:
1174 for info in zip.infolist():
1175 name = info.filename
1176
1177 # don't extract absolute paths or ones with .. in them
1178 if name.startswith('/') or '..' in name:
1179 continue
1180
Miss Islington (bot)7a588622021-05-17 10:35:30 -07001181 targetpath = os.path.join(extract_dir, *name.split('/'))
1182 if not targetpath:
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001183 continue
1184
Miss Islington (bot)7a588622021-05-17 10:35:30 -07001185 _ensure_directory(targetpath)
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001186 if not name.endswith('/'):
1187 # file
Miss Islington (bot)7a588622021-05-17 10:35:30 -07001188 with zip.open(name, 'r') as source, \
1189 open(targetpath, 'wb') as target:
1190 copyfileobj(source, target)
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001191 finally:
1192 zip.close()
1193
1194def _unpack_tarfile(filename, extract_dir):
Serhiy Storchaka11213772014-08-06 18:50:19 +03001195 """Unpack tar/tar.gz/tar.bz2/tar.xz `filename` to `extract_dir`
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001196 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +02001197 import tarfile # late import for breaking circular dependency
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001198 try:
1199 tarobj = tarfile.open(filename)
1200 except tarfile.TarError:
1201 raise ReadError(
1202 "%s is not a compressed or uncompressed tar file" % filename)
1203 try:
1204 tarobj.extractall(extract_dir)
1205 finally:
1206 tarobj.close()
1207
1208_UNPACK_FORMATS = {
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001209 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"),
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +02001210 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file"),
1211}
1212
1213if _ZLIB_SUPPORTED:
1214 _UNPACK_FORMATS['gztar'] = (['.tar.gz', '.tgz'], _unpack_tarfile, [],
1215 "gzip'ed tar-file")
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001216
Tarek Ziadéffa155a2010-04-29 13:34:35 +00001217if _BZ2_SUPPORTED:
Serhiy Storchaka11213772014-08-06 18:50:19 +03001218 _UNPACK_FORMATS['bztar'] = (['.tar.bz2', '.tbz2'], _unpack_tarfile, [],
Tarek Ziadéffa155a2010-04-29 13:34:35 +00001219 "bzip2'ed tar-file")
1220
Serhiy Storchaka11213772014-08-06 18:50:19 +03001221if _LZMA_SUPPORTED:
1222 _UNPACK_FORMATS['xztar'] = (['.tar.xz', '.txz'], _unpack_tarfile, [],
1223 "xz'ed tar-file")
1224
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001225def _find_unpack_format(filename):
1226 for name, info in _UNPACK_FORMATS.items():
1227 for extension in info[0]:
1228 if filename.endswith(extension):
1229 return name
1230 return None
1231
1232def unpack_archive(filename, extract_dir=None, format=None):
1233 """Unpack an archive.
1234
1235 `filename` is the name of the archive.
1236
1237 `extract_dir` is the name of the target directory, where the archive
1238 is unpacked. If not provided, the current working directory is used.
1239
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +02001240 `format` is the archive format: one of "zip", "tar", "gztar", "bztar",
1241 or "xztar". Or any other registered format. If not provided,
1242 unpack_archive will use the filename extension and see if an unpacker
1243 was registered for that extension.
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001244
1245 In case none is found, a ValueError is raised.
1246 """
Saiyang Gou7514f4f2020-02-12 23:47:42 -08001247 sys.audit("shutil.unpack_archive", filename, extract_dir, format)
1248
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001249 if extract_dir is None:
1250 extract_dir = os.getcwd()
1251
Jelle Zijlstraa12df7b2017-05-05 14:27:12 -07001252 extract_dir = os.fspath(extract_dir)
1253 filename = os.fspath(filename)
1254
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001255 if format is not None:
1256 try:
1257 format_info = _UNPACK_FORMATS[format]
1258 except KeyError:
Serhiy Storchaka5affd232017-04-05 09:37:24 +03001259 raise ValueError("Unknown unpack format '{0}'".format(format)) from None
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001260
Nick Coghlanabf202d2011-03-16 13:52:20 -04001261 func = format_info[1]
1262 func(filename, extract_dir, **dict(format_info[2]))
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001263 else:
1264 # we need to look at the registered unpackers supported extensions
1265 format = _find_unpack_format(filename)
1266 if format is None:
1267 raise ReadError("Unknown archive format '{0}'".format(filename))
1268
1269 func = _UNPACK_FORMATS[format][1]
1270 kwargs = dict(_UNPACK_FORMATS[format][2])
1271 func(filename, extract_dir, **kwargs)
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001272
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001273
1274if hasattr(os, 'statvfs'):
1275
1276 __all__.append('disk_usage')
1277 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
Raymond Hettinger5b798ab2015-08-17 22:04:45 -07001278 _ntuple_diskusage.total.__doc__ = 'Total space in bytes'
1279 _ntuple_diskusage.used.__doc__ = 'Used space in bytes'
1280 _ntuple_diskusage.free.__doc__ = 'Free space in bytes'
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001281
1282 def disk_usage(path):
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001283 """Return disk usage statistics about the given path.
1284
Sandro Tosif8ae4fa2012-04-23 20:07:15 +02001285 Returned value is a named tuple with attributes 'total', 'used' and
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001286 'free', which are the amount of total, used and free space, in bytes.
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001287 """
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001288 st = os.statvfs(path)
1289 free = st.f_bavail * st.f_frsize
1290 total = st.f_blocks * st.f_frsize
1291 used = (st.f_blocks - st.f_bfree) * st.f_frsize
1292 return _ntuple_diskusage(total, used, free)
1293
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -07001294elif _WINDOWS:
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001295
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001296 __all__.append('disk_usage')
1297 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
1298
1299 def disk_usage(path):
1300 """Return disk usage statistics about the given path.
1301
Ezio Melotti30b9d5d2013-08-17 15:50:46 +03001302 Returned values is a named tuple with attributes 'total', 'used' and
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001303 'free', which are the amount of total, used and free space, in bytes.
1304 """
1305 total, free = nt._getdiskusage(path)
1306 used = total - free
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001307 return _ntuple_diskusage(total, used, free)
Sandro Tosid902a142011-08-22 23:28:27 +02001308
Éric Araujo0ac4a5d2011-09-01 08:31:51 +02001309
Sandro Tosid902a142011-08-22 23:28:27 +02001310def chown(path, user=None, group=None):
1311 """Change owner user and group of the given path.
1312
1313 user and group can be the uid/gid or the user/group names, and in that case,
1314 they are converted to their respective uid/gid.
1315 """
Saiyang Gou7514f4f2020-02-12 23:47:42 -08001316 sys.audit('shutil.chown', path, user, group)
Sandro Tosid902a142011-08-22 23:28:27 +02001317
1318 if user is None and group is None:
1319 raise ValueError("user and/or group must be set")
1320
1321 _user = user
1322 _group = group
1323
1324 # -1 means don't change it
1325 if user is None:
1326 _user = -1
1327 # user can either be an int (the uid) or a string (the system username)
1328 elif isinstance(user, str):
1329 _user = _get_uid(user)
1330 if _user is None:
1331 raise LookupError("no such user: {!r}".format(user))
1332
1333 if group is None:
1334 _group = -1
1335 elif not isinstance(group, int):
1336 _group = _get_gid(group)
1337 if _group is None:
1338 raise LookupError("no such group: {!r}".format(group))
1339
1340 os.chown(path, _user, _group)
Antoine Pitroubcf2b592012-02-08 23:28:36 +01001341
1342def get_terminal_size(fallback=(80, 24)):
1343 """Get the size of the terminal window.
1344
1345 For each of the two dimensions, the environment variable, COLUMNS
1346 and LINES respectively, is checked. If the variable is defined and
1347 the value is a positive integer, it is used.
1348
1349 When COLUMNS or LINES is not defined, which is the common case,
1350 the terminal connected to sys.__stdout__ is queried
1351 by invoking os.get_terminal_size.
1352
1353 If the terminal size cannot be successfully queried, either because
1354 the system doesn't support querying, or because we are not
1355 connected to a terminal, the value given in fallback parameter
1356 is used. Fallback defaults to (80, 24) which is the default
1357 size used by many terminal emulators.
1358
1359 The value returned is a named tuple of type os.terminal_size.
1360 """
1361 # columns, lines are the working values
1362 try:
1363 columns = int(os.environ['COLUMNS'])
1364 except (KeyError, ValueError):
1365 columns = 0
1366
1367 try:
1368 lines = int(os.environ['LINES'])
1369 except (KeyError, ValueError):
1370 lines = 0
1371
1372 # only query if necessary
1373 if columns <= 0 or lines <= 0:
1374 try:
1375 size = os.get_terminal_size(sys.__stdout__.fileno())
Serhiy Storchakad30829d2016-04-24 09:58:43 +03001376 except (AttributeError, ValueError, OSError):
1377 # stdout is None, closed, detached, or not a terminal, or
1378 # os.get_terminal_size() is unsupported
Antoine Pitroubcf2b592012-02-08 23:28:36 +01001379 size = os.terminal_size(fallback)
1380 if columns <= 0:
1381 columns = size.columns
1382 if lines <= 0:
1383 lines = size.lines
1384
1385 return os.terminal_size((columns, lines))
Brian Curtinc57a3452012-06-22 16:00:30 -05001386
Cheryl Sabella5680f652019-02-13 06:25:10 -05001387
1388# Check that a given file can be accessed with the correct mode.
1389# Additionally check that `file` is not a directory, as on Windows
1390# directories pass the os.access check.
1391def _access_check(fn, mode):
1392 return (os.path.exists(fn) and os.access(fn, mode)
1393 and not os.path.isdir(fn))
1394
1395
Brian Curtinc57a3452012-06-22 16:00:30 -05001396def which(cmd, mode=os.F_OK | os.X_OK, path=None):
Brian Curtindc00f1e2012-06-22 22:49:12 -05001397 """Given a command, mode, and a PATH string, return the path which
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001398 conforms to the given mode on the PATH, or None if there is no such
1399 file.
1400
1401 `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
1402 of os.environ.get("PATH"), or can be overridden with a custom search
1403 path.
1404
1405 """
Serhiy Storchaka8bea2002013-01-23 10:44:21 +02001406 # If we're given a path with a directory part, look it up directly rather
1407 # than referring to PATH directories. This includes checking relative to the
1408 # current directory, e.g. ./script
1409 if os.path.dirname(cmd):
1410 if _access_check(cmd, mode):
1411 return cmd
1412 return None
Brian Curtinc57a3452012-06-22 16:00:30 -05001413
Cheryl Sabella5680f652019-02-13 06:25:10 -05001414 use_bytes = isinstance(cmd, bytes)
1415
Barry Warsaw618738b2013-04-16 11:05:03 -04001416 if path is None:
Victor Stinner228a3c92019-04-17 16:26:36 +02001417 path = os.environ.get("PATH", None)
1418 if path is None:
1419 try:
1420 path = os.confstr("CS_PATH")
1421 except (AttributeError, ValueError):
1422 # os.confstr() or CS_PATH is not available
1423 path = os.defpath
1424 # bpo-35755: Don't use os.defpath if the PATH environment variable is
Victor Stinner197f0442019-04-17 17:44:06 +02001425 # set to an empty string
Victor Stinner228a3c92019-04-17 16:26:36 +02001426
1427 # PATH='' doesn't match, whereas PATH=':' looks in the current directory
Barry Warsaw618738b2013-04-16 11:05:03 -04001428 if not path:
1429 return None
Victor Stinner228a3c92019-04-17 16:26:36 +02001430
Cheryl Sabella5680f652019-02-13 06:25:10 -05001431 if use_bytes:
1432 path = os.fsencode(path)
1433 path = path.split(os.fsencode(os.pathsep))
1434 else:
1435 path = os.fsdecode(path)
1436 path = path.split(os.pathsep)
Brian Curtinc57a3452012-06-22 16:00:30 -05001437
1438 if sys.platform == "win32":
1439 # The current directory takes precedence on Windows.
Cheryl Sabella5680f652019-02-13 06:25:10 -05001440 curdir = os.curdir
1441 if use_bytes:
1442 curdir = os.fsencode(curdir)
1443 if curdir not in path:
1444 path.insert(0, curdir)
Brian Curtinc57a3452012-06-22 16:00:30 -05001445
1446 # PATHEXT is necessary to check on Windows.
Christopher Marchfelderda6f0982020-10-23 12:08:24 +02001447 pathext_source = os.getenv("PATHEXT") or _WIN_DEFAULT_PATHEXT
1448 pathext = [ext for ext in pathext_source.split(os.pathsep) if ext]
1449
Cheryl Sabella5680f652019-02-13 06:25:10 -05001450 if use_bytes:
1451 pathext = [os.fsencode(ext) for ext in pathext]
Brian Curtinc57a3452012-06-22 16:00:30 -05001452 # See if the given file matches any of the expected path extensions.
1453 # This will allow us to short circuit when given "python.exe".
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001454 # If it does match, only test that one, otherwise we have to try
1455 # others.
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001456 if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
1457 files = [cmd]
1458 else:
1459 files = [cmd + ext for ext in pathext]
Brian Curtinc57a3452012-06-22 16:00:30 -05001460 else:
1461 # On other platforms you don't have things like PATHEXT to tell you
1462 # what file suffixes are executable, so just pass on cmd as-is.
1463 files = [cmd]
1464
1465 seen = set()
1466 for dir in path:
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001467 normdir = os.path.normcase(dir)
1468 if not normdir in seen:
1469 seen.add(normdir)
Brian Curtinc57a3452012-06-22 16:00:30 -05001470 for thefile in files:
1471 name = os.path.join(dir, thefile)
1472 if _access_check(name, mode):
1473 return name
1474 return None