blob: a4ce2c0290bc932c67661295f8ea661602c09fa3 [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
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -070045_WINDOWS = os.name == 'nt'
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020046posix = nt = None
47if os.name == 'posix':
48 import posix
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -070049elif _WINDOWS:
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020050 import nt
51
Inada Naoki4f190302019-03-02 13:31:01 +090052COPY_BUFSIZE = 1024 * 1024 if _WINDOWS else 64 * 1024
Giampaolo Rodola413d9552019-05-30 14:05:41 +080053_USE_CP_SENDFILE = hasattr(os, "sendfile") and sys.platform.startswith("linux")
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -070054_HAS_FCOPYFILE = posix and hasattr(posix, "_fcopyfile") # macOS
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020055
Tarek Ziadéc3399782010-02-23 05:39:18 +000056__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
57 "copytree", "move", "rmtree", "Error", "SpecialFileError",
58 "ExecError", "make_archive", "get_archive_formats",
Tarek Ziadé6ac91722010-04-28 17:51:36 +000059 "register_archive_format", "unregister_archive_format",
60 "get_unpack_formats", "register_unpack_format",
Éric Araujoc5efe652011-08-21 14:30:00 +020061 "unregister_unpack_format", "unpack_archive",
Berker Peksag8083cd62014-11-01 11:04:06 +020062 "ignore_patterns", "chown", "which", "get_terminal_size",
63 "SameFileError"]
Éric Araujoe4d5b8e2011-08-08 16:51:11 +020064 # disk_usage is added later, if available on the platform
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000065
Andrew Svetlov3438fa42012-12-17 23:35:18 +020066class Error(OSError):
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000067 pass
Guido van Rossumc6360141990-10-13 19:23:40 +000068
Hynek Schlawack48653762012-10-07 12:49:58 +020069class SameFileError(Error):
70 """Raised when source and destination are the same file."""
71
Andrew Svetlov3438fa42012-12-17 23:35:18 +020072class SpecialFileError(OSError):
Antoine Pitrou7fff0962009-05-01 21:09:44 +000073 """Raised when trying to do a kind of operation (e.g. copying) which is
74 not supported on a special file (e.g. a named pipe)"""
75
Andrew Svetlov3438fa42012-12-17 23:35:18 +020076class ExecError(OSError):
Tarek Ziadé396fad72010-02-23 05:30:31 +000077 """Raised when a command could not be executed"""
78
Andrew Svetlov3438fa42012-12-17 23:35:18 +020079class ReadError(OSError):
Tarek Ziadé6ac91722010-04-28 17:51:36 +000080 """Raised when an archive cannot be read"""
81
82class RegistryError(Exception):
Ezio Melotti30b9d5d2013-08-17 15:50:46 +030083 """Raised when a registry operation with the archiving
Raymond Hettinger15f44ab2016-08-30 10:47:49 -070084 and unpacking registries fails"""
Tarek Ziadé6ac91722010-04-28 17:51:36 +000085
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020086class _GiveupOnFastCopy(Exception):
87 """Raised as a signal to fallback on using raw read()/write()
88 file copy when fast-copy functions fail to do so.
89 """
Tarek Ziadé6ac91722010-04-28 17:51:36 +000090
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -070091def _fastcopy_fcopyfile(fsrc, fdst, flags):
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020092 """Copy a regular file content or metadata by using high-performance
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -070093 fcopyfile(3) syscall (macOS).
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +020094 """
95 try:
96 infd = fsrc.fileno()
97 outfd = fdst.fileno()
98 except Exception as err:
99 raise _GiveupOnFastCopy(err) # not a regular file
100
101 try:
102 posix._fcopyfile(infd, outfd, flags)
103 except OSError as err:
104 err.filename = fsrc.name
105 err.filename2 = fdst.name
106 if err.errno in {errno.EINVAL, errno.ENOTSUP}:
107 raise _GiveupOnFastCopy(err)
108 else:
109 raise err from None
110
111def _fastcopy_sendfile(fsrc, fdst):
112 """Copy data from one regular mmap-like fd to another by using
113 high-performance sendfile(2) syscall.
Giampaolo Rodola413d9552019-05-30 14:05:41 +0800114 This should work on Linux >= 2.6.33 only.
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200115 """
116 # Note: copyfileobj() is left alone in order to not introduce any
117 # unexpected breakage. Possible risks by using zero-copy calls
118 # in copyfileobj() are:
119 # - fdst cannot be open in "a"(ppend) mode
120 # - fsrc and fdst may be open in "t"(ext) mode
121 # - fsrc may be a BufferedReader (which hides unread data in a buffer),
122 # GzipFile (which decompresses data), HTTPResponse (which decodes
123 # chunks).
124 # - possibly others (e.g. encrypted fs/partition?)
Giampaolo Rodola413d9552019-05-30 14:05:41 +0800125 global _USE_CP_SENDFILE
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200126 try:
127 infd = fsrc.fileno()
128 outfd = fdst.fileno()
129 except Exception as err:
130 raise _GiveupOnFastCopy(err) # not a regular file
131
132 # Hopefully the whole file will be copied in a single call.
133 # sendfile() is called in a loop 'till EOF is reached (0 return)
134 # so a bufsize smaller or bigger than the actual file size
135 # should not make any difference, also in case the file content
136 # changes while being copied.
137 try:
Giampaolo Rodola94e16502019-10-01 11:40:54 +0800138 blocksize = max(os.fstat(infd).st_size, 2 ** 23) # min 8MiB
139 except OSError:
140 blocksize = 2 ** 27 # 128MiB
141 # On 32-bit architectures truncate to 1GiB to avoid OverflowError,
142 # see bpo-38319.
143 if sys.maxsize < 2 ** 32:
144 blocksize = min(blocksize, 2 ** 30)
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200145
146 offset = 0
147 while True:
148 try:
149 sent = os.sendfile(outfd, infd, offset, blocksize)
150 except OSError as err:
151 # ...in oder to have a more informative exception.
152 err.filename = fsrc.name
153 err.filename2 = fdst.name
154
155 if err.errno == errno.ENOTSOCK:
156 # sendfile() on this platform (probably Linux < 2.6.33)
157 # does not support copies between regular files (only
158 # sockets).
Giampaolo Rodola413d9552019-05-30 14:05:41 +0800159 _USE_CP_SENDFILE = False
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200160 raise _GiveupOnFastCopy(err)
161
162 if err.errno == errno.ENOSPC: # filesystem is full
163 raise err from None
164
165 # Give up on first call and if no data was copied.
166 if offset == 0 and os.lseek(outfd, 0, os.SEEK_CUR) == 0:
167 raise _GiveupOnFastCopy(err)
168
169 raise err
170 else:
171 if sent == 0:
172 break # EOF
173 offset += sent
174
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700175def _copyfileobj_readinto(fsrc, fdst, length=COPY_BUFSIZE):
176 """readinto()/memoryview() based variant of copyfileobj().
177 *fsrc* must support readinto() method and both files must be
178 open in binary mode.
179 """
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200180 # Localize variable access to minimize overhead.
181 fsrc_readinto = fsrc.readinto
182 fdst_write = fdst.write
183 with memoryview(bytearray(length)) as mv:
184 while True:
185 n = fsrc_readinto(mv)
186 if not n:
187 break
188 elif n < length:
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700189 with mv[:n] as smv:
190 fdst.write(smv)
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200191 else:
192 fdst_write(mv)
193
Giampaolo Rodola3b0abb02019-02-24 15:46:40 -0800194def copyfileobj(fsrc, fdst, length=0):
Greg Stein42bb8b32000-07-12 09:55:30 +0000195 """copy data from file-like object fsrc to file-like object fdst"""
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700196 # Localize variable access to minimize overhead.
Giampaolo Rodola3b0abb02019-02-24 15:46:40 -0800197 if not length:
198 length = COPY_BUFSIZE
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700199 fsrc_read = fsrc.read
200 fdst_write = fdst.write
201 while True:
202 buf = fsrc_read(length)
203 if not buf:
204 break
205 fdst_write(buf)
Greg Stein42bb8b32000-07-12 09:55:30 +0000206
Johannes Gijsbers46f14592004-08-14 13:30:02 +0000207def _samefile(src, dst):
208 # Macintosh, Unix.
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800209 if isinstance(src, os.DirEntry) and hasattr(os.path, 'samestat'):
210 try:
211 return os.path.samestat(src.stat(), os.stat(dst))
212 except OSError:
213 return False
214
Tarek Ziadé1eab9cc2010-04-19 21:19:57 +0000215 if hasattr(os.path, 'samefile'):
Johannes Gijsbersf9a098e2004-08-14 14:51:01 +0000216 try:
217 return os.path.samefile(src, dst)
218 except OSError:
219 return False
Johannes Gijsbers46f14592004-08-14 13:30:02 +0000220
221 # All other platforms: check for same pathname.
222 return (os.path.normcase(os.path.abspath(src)) ==
223 os.path.normcase(os.path.abspath(dst)))
Tim Peters495ad3c2001-01-15 01:36:40 +0000224
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800225def _stat(fn):
226 return fn.stat() if isinstance(fn, os.DirEntry) else os.stat(fn)
227
228def _islink(fn):
229 return fn.is_symlink() if isinstance(fn, os.DirEntry) else os.path.islink(fn)
230
Larry Hastingsb4038062012-07-15 10:57:38 -0700231def copyfile(src, dst, *, follow_symlinks=True):
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700232 """Copy data from src to dst in the most efficient way possible.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100233
Larry Hastingsb4038062012-07-15 10:57:38 -0700234 If follow_symlinks is not set and src is a symbolic link, a new
Antoine Pitrou78091e62011-12-29 18:54:15 +0100235 symlink will be created instead of copying the file it points to.
236
237 """
Saiyang Gou7514f4f2020-02-12 23:47:42 -0800238 sys.audit("shutil.copyfile", src, dst)
239
Johannes Gijsbers46f14592004-08-14 13:30:02 +0000240 if _samefile(src, dst):
Hynek Schlawack48653762012-10-07 12:49:58 +0200241 raise SameFileError("{!r} and {!r} are the same file".format(src, dst))
Johannes Gijsbers46f14592004-08-14 13:30:02 +0000242
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700243 file_size = 0
244 for i, fn in enumerate([src, dst]):
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000245 try:
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800246 st = _stat(fn)
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000247 except OSError:
248 # File most likely does not exist
249 pass
Benjamin Petersonc0d98aa2009-06-05 19:13:27 +0000250 else:
251 # XXX What about other special files? (sockets, devices...)
252 if stat.S_ISFIFO(st.st_mode):
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800253 fn = fn.path if isinstance(fn, os.DirEntry) else fn
Benjamin Petersonc0d98aa2009-06-05 19:13:27 +0000254 raise SpecialFileError("`%s` is a named pipe" % fn)
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700255 if _WINDOWS and i == 0:
256 file_size = st.st_size
Tarek Ziadéb01142b2010-05-05 22:43:04 +0000257
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800258 if not follow_symlinks and _islink(src):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100259 os.symlink(os.readlink(src), dst)
260 else:
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200261 with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst:
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700262 # macOS
263 if _HAS_FCOPYFILE:
264 try:
265 _fastcopy_fcopyfile(fsrc, fdst, posix._COPYFILE_DATA)
266 return dst
267 except _GiveupOnFastCopy:
268 pass
Giampaolo Rodola413d9552019-05-30 14:05:41 +0800269 # Linux
270 elif _USE_CP_SENDFILE:
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200271 try:
272 _fastcopy_sendfile(fsrc, fdst)
273 return dst
274 except _GiveupOnFastCopy:
275 pass
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700276 # Windows, see:
277 # https://github.com/python/cpython/pull/7160#discussion_r195405230
278 elif _WINDOWS and file_size > 0:
279 _copyfileobj_readinto(fsrc, fdst, min(file_size, COPY_BUFSIZE))
280 return dst
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200281
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -0700282 copyfileobj(fsrc, fdst)
Giampaolo Rodola4a172cc2018-06-12 23:04:50 +0200283
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500284 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000285
Larry Hastingsb4038062012-07-15 10:57:38 -0700286def copymode(src, dst, *, follow_symlinks=True):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100287 """Copy mode bits from src to dst.
Guido van Rossumc6360141990-10-13 19:23:40 +0000288
Larry Hastingsb4038062012-07-15 10:57:38 -0700289 If follow_symlinks is not set, symlinks aren't followed if and only
290 if both `src` and `dst` are symlinks. If `lchmod` isn't available
291 (e.g. Linux) this method does nothing.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100292
293 """
Saiyang Gou7514f4f2020-02-12 23:47:42 -0800294 sys.audit("shutil.copymode", src, dst)
295
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800296 if not follow_symlinks and _islink(src) and os.path.islink(dst):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100297 if hasattr(os, 'lchmod'):
298 stat_func, chmod_func = os.lstat, os.lchmod
299 else:
300 return
Antoine Pitrou78091e62011-12-29 18:54:15 +0100301 else:
Anthony Sottile8377cd42019-02-25 14:32:27 -0800302 stat_func, chmod_func = _stat, os.chmod
Antoine Pitrou78091e62011-12-29 18:54:15 +0100303
304 st = stat_func(src)
305 chmod_func(dst, stat.S_IMODE(st.st_mode))
306
Larry Hastingsad5ae042012-07-14 17:55:11 -0700307if hasattr(os, 'listxattr'):
Larry Hastingsb4038062012-07-15 10:57:38 -0700308 def _copyxattr(src, dst, *, follow_symlinks=True):
Larry Hastingsad5ae042012-07-14 17:55:11 -0700309 """Copy extended filesystem attributes from `src` to `dst`.
310
311 Overwrite existing attributes.
312
Larry Hastingsb4038062012-07-15 10:57:38 -0700313 If `follow_symlinks` is false, symlinks won't be followed.
Larry Hastingsad5ae042012-07-14 17:55:11 -0700314
315 """
316
Hynek Schlawack0beab052013-02-05 08:22:44 +0100317 try:
318 names = os.listxattr(src, follow_symlinks=follow_symlinks)
319 except OSError as e:
Ying Wanga16387a2019-05-29 23:25:31 -0400320 if e.errno not in (errno.ENOTSUP, errno.ENODATA, errno.EINVAL):
Hynek Schlawack0beab052013-02-05 08:22:44 +0100321 raise
322 return
323 for name in names:
Larry Hastingsad5ae042012-07-14 17:55:11 -0700324 try:
Larry Hastingsb4038062012-07-15 10:57:38 -0700325 value = os.getxattr(src, name, follow_symlinks=follow_symlinks)
326 os.setxattr(dst, name, value, follow_symlinks=follow_symlinks)
Larry Hastingsad5ae042012-07-14 17:55:11 -0700327 except OSError as e:
Ying Wanga16387a2019-05-29 23:25:31 -0400328 if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA,
329 errno.EINVAL):
Larry Hastingsad5ae042012-07-14 17:55:11 -0700330 raise
331else:
332 def _copyxattr(*args, **kwargs):
333 pass
334
Larry Hastingsb4038062012-07-15 10:57:38 -0700335def copystat(src, dst, *, follow_symlinks=True):
Zsolt Cserna4f399be2018-10-23 12:09:50 +0200336 """Copy file metadata
Antoine Pitrou78091e62011-12-29 18:54:15 +0100337
Zsolt Cserna4f399be2018-10-23 12:09:50 +0200338 Copy the permission bits, last access time, last modification time, and
339 flags from `src` to `dst`. On Linux, copystat() also copies the "extended
340 attributes" where possible. The file contents, owner, and group are
Boris Verhovsky9488a522019-09-09 09:51:56 -0600341 unaffected. `src` and `dst` are path-like objects or path names given as
342 strings.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100343
Zsolt Cserna4f399be2018-10-23 12:09:50 +0200344 If the optional flag `follow_symlinks` is not set, symlinks aren't
345 followed if and only if both `src` and `dst` are symlinks.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100346 """
Saiyang Gou7514f4f2020-02-12 23:47:42 -0800347 sys.audit("shutil.copystat", src, dst)
348
Larry Hastings9cf065c2012-06-22 16:30:09 -0700349 def _nop(*args, ns=None, follow_symlinks=None):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100350 pass
351
Larry Hastings9cf065c2012-06-22 16:30:09 -0700352 # follow symlinks (aka don't not follow symlinks)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800353 follow = follow_symlinks or not (_islink(src) and os.path.islink(dst))
Larry Hastings9cf065c2012-06-22 16:30:09 -0700354 if follow:
355 # use the real function if it exists
356 def lookup(name):
357 return getattr(os, name, _nop)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100358 else:
Larry Hastings9cf065c2012-06-22 16:30:09 -0700359 # use the real function only if it exists
360 # *and* it supports follow_symlinks
361 def lookup(name):
362 fn = getattr(os, name, _nop)
363 if fn in os.supports_follow_symlinks:
364 return fn
365 return _nop
Antoine Pitrou78091e62011-12-29 18:54:15 +0100366
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800367 if isinstance(src, os.DirEntry):
368 st = src.stat(follow_symlinks=follow)
369 else:
370 st = lookup("stat")(src, follow_symlinks=follow)
Walter Dörwald294bbf32002-06-06 09:48:13 +0000371 mode = stat.S_IMODE(st.st_mode)
Larry Hastings9cf065c2012-06-22 16:30:09 -0700372 lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns),
373 follow_symlinks=follow)
Olexa Bilaniuk79efbb72019-05-09 22:22:06 -0500374 # We must copy extended attributes before the file is (potentially)
375 # chmod()'ed read-only, otherwise setxattr() will error with -EACCES.
376 _copyxattr(src, dst, follow_symlinks=follow)
Larry Hastings9cf065c2012-06-22 16:30:09 -0700377 try:
378 lookup("chmod")(dst, mode, follow_symlinks=follow)
379 except NotImplementedError:
380 # if we got a NotImplementedError, it's because
381 # * follow_symlinks=False,
382 # * lchown() is unavailable, and
383 # * either
Ezio Melotti30b9d5d2013-08-17 15:50:46 +0300384 # * fchownat() is unavailable or
Larry Hastings9cf065c2012-06-22 16:30:09 -0700385 # * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW.
386 # (it returned ENOSUP.)
387 # therefore we're out of options--we simply cannot chown the
388 # symlink. give up, suppress the error.
389 # (which is what shutil always did in this circumstance.)
390 pass
Antoine Pitrou78091e62011-12-29 18:54:15 +0100391 if hasattr(st, 'st_flags'):
Antoine Pitrou910bd512010-03-22 20:11:09 +0000392 try:
Larry Hastings9cf065c2012-06-22 16:30:09 -0700393 lookup("chflags")(dst, st.st_flags, follow_symlinks=follow)
Antoine Pitrou910bd512010-03-22 20:11:09 +0000394 except OSError as why:
Ned Deilybaf75712012-05-10 17:05:19 -0700395 for err in 'EOPNOTSUPP', 'ENOTSUP':
396 if hasattr(errno, err) and why.errno == getattr(errno, err):
397 break
398 else:
Antoine Pitrou910bd512010-03-22 20:11:09 +0000399 raise
Antoine Pitrou424246f2012-05-12 19:02:01 +0200400
Larry Hastingsb4038062012-07-15 10:57:38 -0700401def copy(src, dst, *, follow_symlinks=True):
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500402 """Copy data and mode bits ("cp src dst"). Return the file's destination.
Tim Peters495ad3c2001-01-15 01:36:40 +0000403
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000404 The destination may be a directory.
405
Larry Hastingsb4038062012-07-15 10:57:38 -0700406 If follow_symlinks is false, symlinks won't be followed. This
Antoine Pitrou78091e62011-12-29 18:54:15 +0100407 resembles GNU's "cp -P src dst".
408
Hynek Schlawack48653762012-10-07 12:49:58 +0200409 If source and destination are the same file, a SameFileError will be
410 raised.
411
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000412 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000413 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000414 dst = os.path.join(dst, os.path.basename(src))
Larry Hastingsb4038062012-07-15 10:57:38 -0700415 copyfile(src, dst, follow_symlinks=follow_symlinks)
416 copymode(src, dst, follow_symlinks=follow_symlinks)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500417 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000418
Larry Hastingsb4038062012-07-15 10:57:38 -0700419def copy2(src, dst, *, follow_symlinks=True):
Zsolt Cserna4f399be2018-10-23 12:09:50 +0200420 """Copy data and metadata. Return the file's destination.
421
422 Metadata is copied with copystat(). Please see the copystat function
423 for more information.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000424
425 The destination may be a directory.
426
Larry Hastingsb4038062012-07-15 10:57:38 -0700427 If follow_symlinks is false, symlinks won't be followed. This
Antoine Pitrou78091e62011-12-29 18:54:15 +0100428 resembles GNU's "cp -P src dst".
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000429 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000430 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000431 dst = os.path.join(dst, os.path.basename(src))
Larry Hastingsb4038062012-07-15 10:57:38 -0700432 copyfile(src, dst, follow_symlinks=follow_symlinks)
433 copystat(src, dst, follow_symlinks=follow_symlinks)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500434 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000435
Georg Brandl2ee470f2008-07-16 12:55:28 +0000436def ignore_patterns(*patterns):
437 """Function that can be used as copytree() ignore parameter.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000438
Georg Brandl2ee470f2008-07-16 12:55:28 +0000439 Patterns is a sequence of glob-style patterns
440 that are used to exclude files"""
441 def _ignore_patterns(path, names):
442 ignored_names = []
443 for pattern in patterns:
444 ignored_names.extend(fnmatch.filter(names, pattern))
445 return set(ignored_names)
446 return _ignore_patterns
447
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800448def _copytree(entries, src, dst, symlinks, ignore, copy_function,
jab9e00d9e2018-12-28 13:03:40 -0500449 ignore_dangling_symlinks, dirs_exist_ok=False):
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800450 if ignore is not None:
mbarkhau88704332020-01-24 14:51:16 +0000451 ignored_names = ignore(os.fspath(src), [x.name for x in entries])
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800452 else:
453 ignored_names = set()
454
jab9e00d9e2018-12-28 13:03:40 -0500455 os.makedirs(dst, exist_ok=dirs_exist_ok)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800456 errors = []
457 use_srcentry = copy_function is copy2 or copy_function is copy
458
459 for srcentry in entries:
460 if srcentry.name in ignored_names:
461 continue
462 srcname = os.path.join(src, srcentry.name)
463 dstname = os.path.join(dst, srcentry.name)
464 srcobj = srcentry if use_srcentry else srcname
465 try:
Steve Dowerdf2d4a62019-08-21 15:27:33 -0700466 is_symlink = srcentry.is_symlink()
467 if is_symlink and os.name == 'nt':
468 # Special check for directory junctions, which appear as
469 # symlinks but we want to recurse.
470 lstat = srcentry.stat(follow_symlinks=False)
471 if lstat.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT:
472 is_symlink = False
473 if is_symlink:
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800474 linkto = os.readlink(srcname)
475 if symlinks:
476 # We can't just leave it to `copy_function` because legacy
477 # code with a custom `copy_function` may rely on copytree
478 # doing the right thing.
479 os.symlink(linkto, dstname)
480 copystat(srcobj, dstname, follow_symlinks=not symlinks)
481 else:
482 # ignore dangling symlink if the flag is on
483 if not os.path.exists(linkto) and ignore_dangling_symlinks:
484 continue
jab9e00d9e2018-12-28 13:03:40 -0500485 # otherwise let the copy occur. copy2 will raise an error
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800486 if srcentry.is_dir():
487 copytree(srcobj, dstname, symlinks, ignore,
jab9e00d9e2018-12-28 13:03:40 -0500488 copy_function, dirs_exist_ok=dirs_exist_ok)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800489 else:
490 copy_function(srcobj, dstname)
491 elif srcentry.is_dir():
jab9e00d9e2018-12-28 13:03:40 -0500492 copytree(srcobj, dstname, symlinks, ignore, copy_function,
493 dirs_exist_ok=dirs_exist_ok)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800494 else:
495 # Will raise a SpecialFileError for unsupported file types
Giampaolo Rodolac606a9c2019-02-26 12:04:41 +0100496 copy_function(srcobj, dstname)
Giampaolo Rodola19c46a42018-11-12 06:18:15 -0800497 # catch the Error from the recursive copytree so that we can
498 # continue with other files
499 except Error as err:
500 errors.extend(err.args[0])
501 except OSError as why:
502 errors.append((srcname, dstname, str(why)))
503 try:
504 copystat(src, dst)
505 except OSError as why:
506 # Copying file access times may fail on Windows
507 if getattr(why, 'winerror', None) is None:
508 errors.append((src, dst, str(why)))
509 if errors:
510 raise Error(errors)
511 return dst
512
Tarek Ziadéfb437512010-04-20 08:57:33 +0000513def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
jab9e00d9e2018-12-28 13:03:40 -0500514 ignore_dangling_symlinks=False, dirs_exist_ok=False):
515 """Recursively copy a directory tree and return the destination directory.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000516
jab9e00d9e2018-12-28 13:03:40 -0500517 dirs_exist_ok dictates whether to raise an exception in case dst or any
518 missing parent directory already exists.
519
Neal Norwitza4c93b62003-02-23 21:36:32 +0000520 If exception(s) occur, an Error is raised with a list of reasons.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000521
522 If the optional symlinks flag is true, symbolic links in the
523 source tree result in symbolic links in the destination tree; if
524 it is false, the contents of the files pointed to by symbolic
Tarek Ziadéfb437512010-04-20 08:57:33 +0000525 links are copied. If the file pointed by the symlink doesn't
526 exist, an exception will be added in the list of errors raised in
527 an Error exception at the end of the copy process.
528
529 You can set the optional ignore_dangling_symlinks flag to true if you
Tarek Ziadé8c26c7d2010-04-23 13:03:50 +0000530 want to silence this exception. Notice that this has no effect on
531 platforms that don't support os.symlink.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000532
Georg Brandl2ee470f2008-07-16 12:55:28 +0000533 The optional ignore argument is a callable. If given, it
534 is called with the `src` parameter, which is the directory
535 being visited by copytree(), and `names` which is the list of
536 `src` contents, as returned by os.listdir():
537
538 callable(src, names) -> ignored_names
539
540 Since copytree() is called recursively, the callable will be
541 called once for each directory that is copied. It returns a
542 list of names relative to the `src` directory that should
543 not be copied.
544
Tarek Ziadé5340db32010-04-19 22:30:51 +0000545 The optional copy_function argument is a callable that will be used
546 to copy each file. It will be called with the source path and the
547 destination path as arguments. By default, copy2() is used, but any
548 function that supports the same signature (like copy()) can be used.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000549
550 """
Steve Dower60419a72019-06-24 08:42:54 -0700551 sys.audit("shutil.copytree", src, dst)
Bruno P. Kinoshita9bbcbc92019-11-27 14:10:37 +1300552 with os.scandir(src) as itr:
553 entries = list(itr)
554 return _copytree(entries=entries, src=src, dst=dst, symlinks=symlinks,
555 ignore=ignore, copy_function=copy_function,
556 ignore_dangling_symlinks=ignore_dangling_symlinks,
557 dirs_exist_ok=dirs_exist_ok)
Guido van Rossumd7673291998-02-06 21:38:09 +0000558
Ned Deily7fcc2082019-08-29 17:20:03 -0400559if hasattr(os.stat_result, 'st_file_attributes'):
Steve Dowerdf2d4a62019-08-21 15:27:33 -0700560 # Special handling for directory junctions to make them behave like
561 # symlinks for shutil.rmtree, since in general they do not appear as
562 # regular links.
563 def _rmtree_isdir(entry):
564 try:
565 st = entry.stat(follow_symlinks=False)
566 return (stat.S_ISDIR(st.st_mode) and not
567 (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT
568 and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT))
569 except OSError:
570 return False
571
572 def _rmtree_islink(path):
573 try:
574 st = os.lstat(path)
575 return (stat.S_ISLNK(st.st_mode) or
576 (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT
577 and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT))
578 except OSError:
579 return False
580else:
581 def _rmtree_isdir(entry):
582 try:
583 return entry.is_dir(follow_symlinks=False)
584 except OSError:
585 return False
586
587 def _rmtree_islink(path):
588 return os.path.islink(path)
589
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200590# version vulnerable to race conditions
591def _rmtree_unsafe(path, onerror):
Christian Heimes9bd667a2008-01-20 15:14:11 +0000592 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200593 with os.scandir(path) as scandir_it:
594 entries = list(scandir_it)
Christian Heimes9bd667a2008-01-20 15:14:11 +0000595 except OSError:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200596 onerror(os.scandir, path, sys.exc_info())
597 entries = []
598 for entry in entries:
599 fullname = entry.path
Steve Dowerdf2d4a62019-08-21 15:27:33 -0700600 if _rmtree_isdir(entry):
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200601 try:
602 if entry.is_symlink():
603 # This can only happen if someone replaces
604 # a directory with a symlink after the call to
605 # os.scandir or entry.is_dir above.
606 raise OSError("Cannot call rmtree on a symbolic link")
607 except OSError:
608 onerror(os.path.islink, fullname, sys.exc_info())
609 continue
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200610 _rmtree_unsafe(fullname, onerror)
Barry Warsaw234d9a92003-01-24 17:36:15 +0000611 else:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000612 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200613 os.unlink(fullname)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200614 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200615 onerror(os.unlink, fullname, sys.exc_info())
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000616 try:
617 os.rmdir(path)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200618 except OSError:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000619 onerror(os.rmdir, path, sys.exc_info())
Guido van Rossumd7673291998-02-06 21:38:09 +0000620
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200621# Version using fd-based APIs to protect against races
622def _rmtree_safe_fd(topfd, path, onerror):
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200623 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200624 with os.scandir(topfd) as scandir_it:
625 entries = list(scandir_it)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100626 except OSError as err:
627 err.filename = path
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200628 onerror(os.scandir, path, sys.exc_info())
629 return
630 for entry in entries:
631 fullname = os.path.join(path, entry.name)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200632 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200633 is_dir = entry.is_dir(follow_symlinks=False)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100634 except OSError:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200635 is_dir = False
Serhiy Storchakae9b51c02019-05-31 11:30:37 +0300636 else:
637 if is_dir:
638 try:
639 orig_st = entry.stat(follow_symlinks=False)
640 is_dir = stat.S_ISDIR(orig_st.st_mode)
641 except OSError:
642 onerror(os.lstat, fullname, sys.exc_info())
643 continue
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200644 if is_dir:
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200645 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200646 dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100647 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200648 onerror(os.open, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200649 else:
650 try:
651 if os.path.samestat(orig_st, os.fstat(dirfd)):
652 _rmtree_safe_fd(dirfd, fullname, onerror)
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200653 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200654 os.rmdir(entry.name, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100655 except OSError:
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200656 onerror(os.rmdir, fullname, sys.exc_info())
Hynek Schlawackb5501102012-12-10 09:11:25 +0100657 else:
658 try:
659 # This can only happen if someone replaces
660 # a directory with a symlink after the call to
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200661 # os.scandir or stat.S_ISDIR above.
Hynek Schlawackb5501102012-12-10 09:11:25 +0100662 raise OSError("Cannot call rmtree on a symbolic "
663 "link")
664 except OSError:
665 onerror(os.path.islink, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200666 finally:
667 os.close(dirfd)
668 else:
669 try:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200670 os.unlink(entry.name, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100671 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200672 onerror(os.unlink, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200673
Hynek Schlawackd0f6e0a2012-06-29 08:28:20 +0200674_use_fd_functions = ({os.open, os.stat, os.unlink, os.rmdir} <=
675 os.supports_dir_fd and
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200676 os.scandir in os.supports_fd and
Hynek Schlawackd0f6e0a2012-06-29 08:28:20 +0200677 os.stat in os.supports_follow_symlinks)
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000678
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200679def rmtree(path, ignore_errors=False, onerror=None):
680 """Recursively delete a directory tree.
681
682 If ignore_errors is set, errors are ignored; otherwise, if onerror
683 is set, it is called to handle the error with arguments (func,
Hynek Schlawack2100b422012-06-23 20:28:32 +0200684 path, exc_info) where func is platform and implementation dependent;
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200685 path is the argument to that function that caused it to fail; and
686 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
687 is false and onerror is None, an exception is raised.
688
689 """
Steve Dower60419a72019-06-24 08:42:54 -0700690 sys.audit("shutil.rmtree", path)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200691 if ignore_errors:
692 def onerror(*args):
693 pass
694 elif onerror is None:
695 def onerror(*args):
696 raise
697 if _use_fd_functions:
Hynek Schlawack3b527782012-06-25 13:27:31 +0200698 # While the unsafe rmtree works fine on bytes, the fd based does not.
699 if isinstance(path, bytes):
700 path = os.fsdecode(path)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200701 # Note: To guard against symlink races, we use the standard
702 # lstat()/open()/fstat() trick.
703 try:
704 orig_st = os.lstat(path)
705 except Exception:
706 onerror(os.lstat, path, sys.exc_info())
707 return
708 try:
709 fd = os.open(path, os.O_RDONLY)
710 except Exception:
711 onerror(os.lstat, path, sys.exc_info())
712 return
713 try:
Hynek Schlawackb5501102012-12-10 09:11:25 +0100714 if os.path.samestat(orig_st, os.fstat(fd)):
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200715 _rmtree_safe_fd(fd, path, onerror)
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200716 try:
717 os.rmdir(path)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200718 except OSError:
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200719 onerror(os.rmdir, path, sys.exc_info())
Hynek Schlawacka75cd1c2012-06-28 12:07:29 +0200720 else:
Hynek Schlawackb5501102012-12-10 09:11:25 +0100721 try:
722 # symlinks to directories are forbidden, see bug #1669
723 raise OSError("Cannot call rmtree on a symbolic link")
724 except OSError:
725 onerror(os.path.islink, path, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200726 finally:
727 os.close(fd)
728 else:
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200729 try:
Steve Dowerdf2d4a62019-08-21 15:27:33 -0700730 if _rmtree_islink(path):
Serhiy Storchakad4d79bc2017-11-04 14:16:35 +0200731 # 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())
735 # can't continue even if onerror hook returns
736 return
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200737 return _rmtree_unsafe(path, onerror)
738
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000739# Allow introspection of whether or not the hardening against symlink
740# attacks is supported on the current platform
741rmtree.avoids_symlink_attacks = _use_fd_functions
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000742
Christian Heimesada8c3b2008-03-18 18:26:33 +0000743def _basename(path):
Maxwell A McKinnoncf57cab2019-09-30 19:41:16 -0700744 """A basename() variant which first strips the trailing slash, if present.
745 Thus we always get the last component of the path, even for directories.
746
747 path: Union[PathLike, str]
748
749 e.g.
750 >>> os.path.basename('/bar/foo')
751 'foo'
752 >>> os.path.basename('/bar/foo/')
753 ''
754 >>> _basename('/bar/foo/')
755 'foo'
756 """
757 path = os.fspath(path)
Serhiy Storchaka3a308b92014-02-11 10:30:59 +0200758 sep = os.path.sep + (os.path.altsep or '')
759 return os.path.basename(path.rstrip(sep))
Christian Heimesada8c3b2008-03-18 18:26:33 +0000760
R David Murray6ffface2014-06-11 14:40:13 -0400761def move(src, dst, copy_function=copy2):
Christian Heimesada8c3b2008-03-18 18:26:33 +0000762 """Recursively move a file or directory to another location. This is
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500763 similar to the Unix "mv" command. Return the file or directory's
764 destination.
Christian Heimesada8c3b2008-03-18 18:26:33 +0000765
766 If the destination is a directory or a symlink to a directory, the source
767 is moved inside the directory. The destination path must not already
768 exist.
769
770 If the destination already exists but is not a directory, it may be
771 overwritten depending on os.rename() semantics.
772
773 If the destination is on our current filesystem, then rename() is used.
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +0100774 Otherwise, src is copied to the destination and then removed. Symlinks are
775 recreated under the new name if os.rename() fails because of cross
776 filesystem renames.
777
R David Murray6ffface2014-06-11 14:40:13 -0400778 The optional `copy_function` argument is a callable that will be used
779 to copy the source or it will be delegated to `copytree`.
780 By default, copy2() is used, but any function that supports the same
781 signature (like copy()) can be used.
782
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000783 A lot more could be done here... A look at a mv.c shows a lot of
784 the issues this implementation glosses over.
785
786 """
Saiyang Gou7514f4f2020-02-12 23:47:42 -0800787 sys.audit("shutil.move", src, dst)
Christian Heimesada8c3b2008-03-18 18:26:33 +0000788 real_dst = dst
789 if os.path.isdir(dst):
Ronald Oussorenf51738b2011-05-06 10:23:04 +0200790 if _samefile(src, dst):
791 # We might be on a case insensitive filesystem,
792 # perform the rename anyway.
793 os.rename(src, dst)
794 return
795
Maxwell A McKinnoncf57cab2019-09-30 19:41:16 -0700796 # Using _basename instead of os.path.basename is important, as we must
797 # ignore any trailing slash to avoid the basename returning ''
Christian Heimesada8c3b2008-03-18 18:26:33 +0000798 real_dst = os.path.join(dst, _basename(src))
Maxwell A McKinnoncf57cab2019-09-30 19:41:16 -0700799
Christian Heimesada8c3b2008-03-18 18:26:33 +0000800 if os.path.exists(real_dst):
801 raise Error("Destination path '%s' already exists" % real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000802 try:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000803 os.rename(src, real_dst)
Éric Araujocfcc9772011-08-10 20:54:33 +0200804 except OSError:
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +0100805 if os.path.islink(src):
806 linkto = os.readlink(src)
807 os.symlink(linkto, real_dst)
808 os.unlink(src)
809 elif os.path.isdir(src):
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000810 if _destinsrc(src, dst):
R David Murray6ffface2014-06-11 14:40:13 -0400811 raise Error("Cannot move a directory '%s' into itself"
812 " '%s'." % (src, dst))
813 copytree(src, real_dst, copy_function=copy_function,
814 symlinks=True)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000815 rmtree(src)
816 else:
R David Murray6ffface2014-06-11 14:40:13 -0400817 copy_function(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000818 os.unlink(src)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500819 return real_dst
Brett Cannon1c3fa182004-06-19 21:11:35 +0000820
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000821def _destinsrc(src, dst):
Berker Peksag3715da52014-09-18 05:11:15 +0300822 src = os.path.abspath(src)
823 dst = os.path.abspath(dst)
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +0000824 if not src.endswith(os.path.sep):
825 src += os.path.sep
826 if not dst.endswith(os.path.sep):
827 dst += os.path.sep
828 return dst.startswith(src)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000829
830def _get_gid(name):
831 """Returns a gid, given a group name."""
832 if getgrnam is None or name is None:
833 return None
834 try:
835 result = getgrnam(name)
836 except KeyError:
837 result = None
838 if result is not None:
839 return result[2]
840 return None
841
842def _get_uid(name):
843 """Returns an uid, given a user name."""
844 if getpwnam is None or name is None:
845 return None
846 try:
847 result = getpwnam(name)
848 except KeyError:
849 result = None
850 if result is not None:
851 return result[2]
852 return None
853
854def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
855 owner=None, group=None, logger=None):
856 """Create a (possibly compressed) tar file from all the files under
857 'base_dir'.
858
Serhiy Storchaka11213772014-08-06 18:50:19 +0300859 'compress' must be "gzip" (the default), "bzip2", "xz", or None.
Tarek Ziadé396fad72010-02-23 05:30:31 +0000860
861 'owner' and 'group' can be used to define an owner and a group for the
862 archive that is being built. If not provided, the current owner and group
863 will be used.
864
Éric Araujo4433a5f2010-12-15 20:26:30 +0000865 The output tar file will be named 'base_name' + ".tar", possibly plus
Serhiy Storchaka11213772014-08-06 18:50:19 +0300866 the appropriate compression extension (".gz", ".bz2", or ".xz").
Tarek Ziadé396fad72010-02-23 05:30:31 +0000867
868 Returns the output filename.
869 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200870 if compress is None:
871 tar_compression = ''
872 elif _ZLIB_SUPPORTED and compress == 'gzip':
873 tar_compression = 'gz'
874 elif _BZ2_SUPPORTED and compress == 'bzip2':
875 tar_compression = 'bz2'
876 elif _LZMA_SUPPORTED and compress == 'xz':
877 tar_compression = 'xz'
878 else:
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000879 raise ValueError("bad value for 'compress', or compression format not "
880 "supported : {0}".format(compress))
Tarek Ziadé396fad72010-02-23 05:30:31 +0000881
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200882 import tarfile # late import for breaking circular dependency
883
884 compress_ext = '.' + tar_compression if compress else ''
885 archive_name = base_name + '.tar' + compress_ext
Tarek Ziadé396fad72010-02-23 05:30:31 +0000886 archive_dir = os.path.dirname(archive_name)
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000887
Serhiy Storchaka9a4fc192014-11-28 00:48:46 +0200888 if archive_dir and not os.path.exists(archive_dir):
Éric Araujoac4e58e2011-01-29 20:32:11 +0000889 if logger is not None:
Éric Araujo43a7ee12011-08-19 02:55:11 +0200890 logger.info("creating %s", archive_dir)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000891 if not dry_run:
892 os.makedirs(archive_dir)
893
Tarek Ziadé396fad72010-02-23 05:30:31 +0000894 # creating the tarball
Tarek Ziadé396fad72010-02-23 05:30:31 +0000895 if logger is not None:
896 logger.info('Creating tar archive')
897
898 uid = _get_uid(owner)
899 gid = _get_gid(group)
900
901 def _set_uid_gid(tarinfo):
902 if gid is not None:
903 tarinfo.gid = gid
904 tarinfo.gname = group
905 if uid is not None:
906 tarinfo.uid = uid
907 tarinfo.uname = owner
908 return tarinfo
909
910 if not dry_run:
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200911 tar = tarfile.open(archive_name, 'w|%s' % tar_compression)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000912 try:
913 tar.add(base_dir, filter=_set_uid_gid)
914 finally:
915 tar.close()
916
Tarek Ziadé396fad72010-02-23 05:30:31 +0000917 return archive_name
918
Tarek Ziadé396fad72010-02-23 05:30:31 +0000919def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
920 """Create a zip file from all the files under 'base_dir'.
921
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200922 The output zip file will be named 'base_name' + ".zip". Returns the
923 name of the output zip file.
Tarek Ziadé396fad72010-02-23 05:30:31 +0000924 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200925 import zipfile # late import for breaking circular dependency
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400926
Tarek Ziadé396fad72010-02-23 05:30:31 +0000927 zip_filename = base_name + ".zip"
928 archive_dir = os.path.dirname(base_name)
929
Serhiy Storchaka9a4fc192014-11-28 00:48:46 +0200930 if archive_dir and not os.path.exists(archive_dir):
Tarek Ziadé396fad72010-02-23 05:30:31 +0000931 if logger is not None:
932 logger.info("creating %s", archive_dir)
933 if not dry_run:
934 os.makedirs(archive_dir)
935
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400936 if logger is not None:
937 logger.info("creating '%s' and adding '%s' to it",
938 zip_filename, base_dir)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000939
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400940 if not dry_run:
941 with zipfile.ZipFile(zip_filename, "w",
942 compression=zipfile.ZIP_DEFLATED) as zf:
Serhiy Storchakad941d7a2015-09-08 05:51:00 +0300943 path = os.path.normpath(base_dir)
Serhiy Storchaka666de772016-10-23 15:55:09 +0300944 if path != os.curdir:
945 zf.write(path, path)
946 if logger is not None:
947 logger.info("adding '%s'", path)
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400948 for dirpath, dirnames, filenames in os.walk(base_dir):
Serhiy Storchakad941d7a2015-09-08 05:51:00 +0300949 for name in sorted(dirnames):
950 path = os.path.normpath(os.path.join(dirpath, name))
951 zf.write(path, path)
952 if logger is not None:
953 logger.info("adding '%s'", path)
Andrew Kuchlinga0934b22014-03-20 16:11:16 -0400954 for name in filenames:
955 path = os.path.normpath(os.path.join(dirpath, name))
956 if os.path.isfile(path):
957 zf.write(path, path)
958 if logger is not None:
959 logger.info("adding '%s'", path)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000960
961 return zip_filename
962
963_ARCHIVE_FORMATS = {
Tarek Ziadé396fad72010-02-23 05:30:31 +0000964 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"),
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +0200965}
966
967if _ZLIB_SUPPORTED:
968 _ARCHIVE_FORMATS['gztar'] = (_make_tarball, [('compress', 'gzip')],
969 "gzip'ed tar-file")
970 _ARCHIVE_FORMATS['zip'] = (_make_zipfile, [], "ZIP file")
Tarek Ziadé396fad72010-02-23 05:30:31 +0000971
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000972if _BZ2_SUPPORTED:
973 _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')],
974 "bzip2'ed tar-file")
975
Serhiy Storchaka11213772014-08-06 18:50:19 +0300976if _LZMA_SUPPORTED:
977 _ARCHIVE_FORMATS['xztar'] = (_make_tarball, [('compress', 'xz')],
978 "xz'ed tar-file")
979
Tarek Ziadé396fad72010-02-23 05:30:31 +0000980def get_archive_formats():
981 """Returns a list of supported formats for archiving and unarchiving.
982
983 Each element of the returned sequence is a tuple (name, description)
984 """
985 formats = [(name, registry[2]) for name, registry in
986 _ARCHIVE_FORMATS.items()]
987 formats.sort()
988 return formats
989
990def register_archive_format(name, function, extra_args=None, description=''):
991 """Registers an archive format.
992
993 name is the name of the format. function is the callable that will be
994 used to create archives. If provided, extra_args is a sequence of
995 (name, value) tuples that will be passed as arguments to the callable.
996 description can be provided to describe the format, and will be returned
997 by the get_archive_formats() function.
998 """
999 if extra_args is None:
1000 extra_args = []
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001001 if not callable(function):
Tarek Ziadé396fad72010-02-23 05:30:31 +00001002 raise TypeError('The %s object is not callable' % function)
1003 if not isinstance(extra_args, (tuple, list)):
1004 raise TypeError('extra_args needs to be a sequence')
1005 for element in extra_args:
Éric Araujoc1b7e7f2011-09-18 23:12:30 +02001006 if not isinstance(element, (tuple, list)) or len(element) !=2:
Tarek Ziadé396fad72010-02-23 05:30:31 +00001007 raise TypeError('extra_args elements are : (arg_name, value)')
1008
1009 _ARCHIVE_FORMATS[name] = (function, extra_args, description)
1010
1011def unregister_archive_format(name):
1012 del _ARCHIVE_FORMATS[name]
1013
1014def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
1015 dry_run=0, owner=None, group=None, logger=None):
1016 """Create an archive file (eg. zip or tar).
1017
1018 'base_name' is the name of the file to create, minus any format-specific
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +02001019 extension; 'format' is the archive format: one of "zip", "tar", "gztar",
1020 "bztar", or "xztar". Or any other registered format.
Tarek Ziadé396fad72010-02-23 05:30:31 +00001021
1022 'root_dir' is a directory that will be the root directory of the
1023 archive; ie. we typically chdir into 'root_dir' before creating the
1024 archive. 'base_dir' is the directory where we start archiving from;
1025 ie. 'base_dir' will be the common prefix of all files and
1026 directories in the archive. 'root_dir' and 'base_dir' both default
1027 to the current directory. Returns the name of the archive file.
1028
1029 'owner' and 'group' are used when creating a tar archive. By default,
1030 uses the current owner and group.
1031 """
Steve Dower60419a72019-06-24 08:42:54 -07001032 sys.audit("shutil.make_archive", base_name, format, root_dir, base_dir)
Tarek Ziadé396fad72010-02-23 05:30:31 +00001033 save_cwd = os.getcwd()
1034 if root_dir is not None:
1035 if logger is not None:
1036 logger.debug("changing into '%s'", root_dir)
1037 base_name = os.path.abspath(base_name)
1038 if not dry_run:
1039 os.chdir(root_dir)
1040
1041 if base_dir is None:
1042 base_dir = os.curdir
1043
1044 kwargs = {'dry_run': dry_run, 'logger': logger}
1045
1046 try:
1047 format_info = _ARCHIVE_FORMATS[format]
1048 except KeyError:
Serhiy Storchaka5affd232017-04-05 09:37:24 +03001049 raise ValueError("unknown archive format '%s'" % format) from None
Tarek Ziadé396fad72010-02-23 05:30:31 +00001050
1051 func = format_info[0]
1052 for arg, val in format_info[1]:
1053 kwargs[arg] = val
1054
1055 if format != 'zip':
1056 kwargs['owner'] = owner
1057 kwargs['group'] = group
1058
1059 try:
1060 filename = func(base_name, base_dir, **kwargs)
1061 finally:
1062 if root_dir is not None:
1063 if logger is not None:
1064 logger.debug("changing back to '%s'", save_cwd)
1065 os.chdir(save_cwd)
1066
1067 return filename
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001068
1069
1070def get_unpack_formats():
1071 """Returns a list of supported formats for unpacking.
1072
1073 Each element of the returned sequence is a tuple
1074 (name, extensions, description)
1075 """
1076 formats = [(name, info[0], info[3]) for name, info in
1077 _UNPACK_FORMATS.items()]
1078 formats.sort()
1079 return formats
1080
1081def _check_unpack_options(extensions, function, extra_args):
1082 """Checks what gets registered as an unpacker."""
1083 # first make sure no other unpacker is registered for this extension
1084 existing_extensions = {}
1085 for name, info in _UNPACK_FORMATS.items():
1086 for ext in info[0]:
1087 existing_extensions[ext] = name
1088
1089 for extension in extensions:
1090 if extension in existing_extensions:
1091 msg = '%s is already registered for "%s"'
1092 raise RegistryError(msg % (extension,
1093 existing_extensions[extension]))
1094
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001095 if not callable(function):
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001096 raise TypeError('The registered function must be a callable')
1097
1098
1099def register_unpack_format(name, extensions, function, extra_args=None,
1100 description=''):
1101 """Registers an unpack format.
1102
1103 `name` is the name of the format. `extensions` is a list of extensions
1104 corresponding to the format.
1105
1106 `function` is the callable that will be
1107 used to unpack archives. The callable will receive archives to unpack.
1108 If it's unable to handle an archive, it needs to raise a ReadError
1109 exception.
1110
1111 If provided, `extra_args` is a sequence of
1112 (name, value) tuples that will be passed as arguments to the callable.
1113 description can be provided to describe the format, and will be returned
1114 by the get_unpack_formats() function.
1115 """
1116 if extra_args is None:
1117 extra_args = []
1118 _check_unpack_options(extensions, function, extra_args)
1119 _UNPACK_FORMATS[name] = extensions, function, extra_args, description
1120
1121def unregister_unpack_format(name):
Martin Pantereb995702016-07-28 01:11:04 +00001122 """Removes the pack format from the registry."""
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001123 del _UNPACK_FORMATS[name]
1124
1125def _ensure_directory(path):
1126 """Ensure that the parent directory of `path` exists"""
1127 dirname = os.path.dirname(path)
1128 if not os.path.isdir(dirname):
1129 os.makedirs(dirname)
1130
1131def _unpack_zipfile(filename, extract_dir):
1132 """Unpack zip `filename` to `extract_dir`
1133 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +02001134 import zipfile # late import for breaking circular dependency
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001135
1136 if not zipfile.is_zipfile(filename):
1137 raise ReadError("%s is not a zip file" % filename)
1138
1139 zip = zipfile.ZipFile(filename)
1140 try:
1141 for info in zip.infolist():
1142 name = info.filename
1143
1144 # don't extract absolute paths or ones with .. in them
1145 if name.startswith('/') or '..' in name:
1146 continue
1147
1148 target = os.path.join(extract_dir, *name.split('/'))
1149 if not target:
1150 continue
1151
1152 _ensure_directory(target)
1153 if not name.endswith('/'):
1154 # file
1155 data = zip.read(info.filename)
Éric Araujoc1b7e7f2011-09-18 23:12:30 +02001156 f = open(target, 'wb')
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001157 try:
1158 f.write(data)
1159 finally:
1160 f.close()
1161 del data
1162 finally:
1163 zip.close()
1164
1165def _unpack_tarfile(filename, extract_dir):
Serhiy Storchaka11213772014-08-06 18:50:19 +03001166 """Unpack tar/tar.gz/tar.bz2/tar.xz `filename` to `extract_dir`
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001167 """
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +02001168 import tarfile # late import for breaking circular dependency
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001169 try:
1170 tarobj = tarfile.open(filename)
1171 except tarfile.TarError:
1172 raise ReadError(
1173 "%s is not a compressed or uncompressed tar file" % filename)
1174 try:
1175 tarobj.extractall(extract_dir)
1176 finally:
1177 tarobj.close()
1178
1179_UNPACK_FORMATS = {
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001180 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"),
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +02001181 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file"),
1182}
1183
1184if _ZLIB_SUPPORTED:
1185 _UNPACK_FORMATS['gztar'] = (['.tar.gz', '.tgz'], _unpack_tarfile, [],
1186 "gzip'ed tar-file")
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001187
Tarek Ziadéffa155a2010-04-29 13:34:35 +00001188if _BZ2_SUPPORTED:
Serhiy Storchaka11213772014-08-06 18:50:19 +03001189 _UNPACK_FORMATS['bztar'] = (['.tar.bz2', '.tbz2'], _unpack_tarfile, [],
Tarek Ziadéffa155a2010-04-29 13:34:35 +00001190 "bzip2'ed tar-file")
1191
Serhiy Storchaka11213772014-08-06 18:50:19 +03001192if _LZMA_SUPPORTED:
1193 _UNPACK_FORMATS['xztar'] = (['.tar.xz', '.txz'], _unpack_tarfile, [],
1194 "xz'ed tar-file")
1195
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001196def _find_unpack_format(filename):
1197 for name, info in _UNPACK_FORMATS.items():
1198 for extension in info[0]:
1199 if filename.endswith(extension):
1200 return name
1201 return None
1202
1203def unpack_archive(filename, extract_dir=None, format=None):
1204 """Unpack an archive.
1205
1206 `filename` is the name of the archive.
1207
1208 `extract_dir` is the name of the target directory, where the archive
1209 is unpacked. If not provided, the current working directory is used.
1210
Serhiy Storchaka20cdffd2016-12-16 18:58:33 +02001211 `format` is the archive format: one of "zip", "tar", "gztar", "bztar",
1212 or "xztar". Or any other registered format. If not provided,
1213 unpack_archive will use the filename extension and see if an unpacker
1214 was registered for that extension.
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001215
1216 In case none is found, a ValueError is raised.
1217 """
Saiyang Gou7514f4f2020-02-12 23:47:42 -08001218 sys.audit("shutil.unpack_archive", filename, extract_dir, format)
1219
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001220 if extract_dir is None:
1221 extract_dir = os.getcwd()
1222
Jelle Zijlstraa12df7b2017-05-05 14:27:12 -07001223 extract_dir = os.fspath(extract_dir)
1224 filename = os.fspath(filename)
1225
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001226 if format is not None:
1227 try:
1228 format_info = _UNPACK_FORMATS[format]
1229 except KeyError:
Serhiy Storchaka5affd232017-04-05 09:37:24 +03001230 raise ValueError("Unknown unpack format '{0}'".format(format)) from None
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001231
Nick Coghlanabf202d2011-03-16 13:52:20 -04001232 func = format_info[1]
1233 func(filename, extract_dir, **dict(format_info[2]))
Tarek Ziadé6ac91722010-04-28 17:51:36 +00001234 else:
1235 # we need to look at the registered unpackers supported extensions
1236 format = _find_unpack_format(filename)
1237 if format is None:
1238 raise ReadError("Unknown archive format '{0}'".format(filename))
1239
1240 func = _UNPACK_FORMATS[format][1]
1241 kwargs = dict(_UNPACK_FORMATS[format][2])
1242 func(filename, extract_dir, **kwargs)
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001243
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001244
1245if hasattr(os, 'statvfs'):
1246
1247 __all__.append('disk_usage')
1248 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
Raymond Hettinger5b798ab2015-08-17 22:04:45 -07001249 _ntuple_diskusage.total.__doc__ = 'Total space in bytes'
1250 _ntuple_diskusage.used.__doc__ = 'Used space in bytes'
1251 _ntuple_diskusage.free.__doc__ = 'Free space in bytes'
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001252
1253 def disk_usage(path):
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001254 """Return disk usage statistics about the given path.
1255
Sandro Tosif8ae4fa2012-04-23 20:07:15 +02001256 Returned value is a named tuple with attributes 'total', 'used' and
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001257 'free', which are the amount of total, used and free space, in bytes.
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001258 """
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001259 st = os.statvfs(path)
1260 free = st.f_bavail * st.f_frsize
1261 total = st.f_blocks * st.f_frsize
1262 used = (st.f_blocks - st.f_bfree) * st.f_frsize
1263 return _ntuple_diskusage(total, used, free)
1264
Giampaolo Rodolac7f02a92018-06-19 08:27:29 -07001265elif _WINDOWS:
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001266
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001267 __all__.append('disk_usage')
1268 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
1269
1270 def disk_usage(path):
1271 """Return disk usage statistics about the given path.
1272
Ezio Melotti30b9d5d2013-08-17 15:50:46 +03001273 Returned values is a named tuple with attributes 'total', 'used' and
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001274 'free', which are the amount of total, used and free space, in bytes.
1275 """
1276 total, free = nt._getdiskusage(path)
1277 used = total - free
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001278 return _ntuple_diskusage(total, used, free)
Sandro Tosid902a142011-08-22 23:28:27 +02001279
Éric Araujo0ac4a5d2011-09-01 08:31:51 +02001280
Sandro Tosid902a142011-08-22 23:28:27 +02001281def chown(path, user=None, group=None):
1282 """Change owner user and group of the given path.
1283
1284 user and group can be the uid/gid or the user/group names, and in that case,
1285 they are converted to their respective uid/gid.
1286 """
Saiyang Gou7514f4f2020-02-12 23:47:42 -08001287 sys.audit('shutil.chown', path, user, group)
Sandro Tosid902a142011-08-22 23:28:27 +02001288
1289 if user is None and group is None:
1290 raise ValueError("user and/or group must be set")
1291
1292 _user = user
1293 _group = group
1294
1295 # -1 means don't change it
1296 if user is None:
1297 _user = -1
1298 # user can either be an int (the uid) or a string (the system username)
1299 elif isinstance(user, str):
1300 _user = _get_uid(user)
1301 if _user is None:
1302 raise LookupError("no such user: {!r}".format(user))
1303
1304 if group is None:
1305 _group = -1
1306 elif not isinstance(group, int):
1307 _group = _get_gid(group)
1308 if _group is None:
1309 raise LookupError("no such group: {!r}".format(group))
1310
1311 os.chown(path, _user, _group)
Antoine Pitroubcf2b592012-02-08 23:28:36 +01001312
1313def get_terminal_size(fallback=(80, 24)):
1314 """Get the size of the terminal window.
1315
1316 For each of the two dimensions, the environment variable, COLUMNS
1317 and LINES respectively, is checked. If the variable is defined and
1318 the value is a positive integer, it is used.
1319
1320 When COLUMNS or LINES is not defined, which is the common case,
1321 the terminal connected to sys.__stdout__ is queried
1322 by invoking os.get_terminal_size.
1323
1324 If the terminal size cannot be successfully queried, either because
1325 the system doesn't support querying, or because we are not
1326 connected to a terminal, the value given in fallback parameter
1327 is used. Fallback defaults to (80, 24) which is the default
1328 size used by many terminal emulators.
1329
1330 The value returned is a named tuple of type os.terminal_size.
1331 """
1332 # columns, lines are the working values
1333 try:
1334 columns = int(os.environ['COLUMNS'])
1335 except (KeyError, ValueError):
1336 columns = 0
1337
1338 try:
1339 lines = int(os.environ['LINES'])
1340 except (KeyError, ValueError):
1341 lines = 0
1342
1343 # only query if necessary
1344 if columns <= 0 or lines <= 0:
1345 try:
1346 size = os.get_terminal_size(sys.__stdout__.fileno())
Serhiy Storchakad30829d2016-04-24 09:58:43 +03001347 except (AttributeError, ValueError, OSError):
1348 # stdout is None, closed, detached, or not a terminal, or
1349 # os.get_terminal_size() is unsupported
Antoine Pitroubcf2b592012-02-08 23:28:36 +01001350 size = os.terminal_size(fallback)
1351 if columns <= 0:
1352 columns = size.columns
1353 if lines <= 0:
1354 lines = size.lines
1355
1356 return os.terminal_size((columns, lines))
Brian Curtinc57a3452012-06-22 16:00:30 -05001357
Cheryl Sabella5680f652019-02-13 06:25:10 -05001358
1359# Check that a given file can be accessed with the correct mode.
1360# Additionally check that `file` is not a directory, as on Windows
1361# directories pass the os.access check.
1362def _access_check(fn, mode):
1363 return (os.path.exists(fn) and os.access(fn, mode)
1364 and not os.path.isdir(fn))
1365
1366
Brian Curtinc57a3452012-06-22 16:00:30 -05001367def which(cmd, mode=os.F_OK | os.X_OK, path=None):
Brian Curtindc00f1e2012-06-22 22:49:12 -05001368 """Given a command, mode, and a PATH string, return the path which
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001369 conforms to the given mode on the PATH, or None if there is no such
1370 file.
1371
1372 `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
1373 of os.environ.get("PATH"), or can be overridden with a custom search
1374 path.
1375
1376 """
Serhiy Storchaka8bea2002013-01-23 10:44:21 +02001377 # If we're given a path with a directory part, look it up directly rather
1378 # than referring to PATH directories. This includes checking relative to the
1379 # current directory, e.g. ./script
1380 if os.path.dirname(cmd):
1381 if _access_check(cmd, mode):
1382 return cmd
1383 return None
Brian Curtinc57a3452012-06-22 16:00:30 -05001384
Cheryl Sabella5680f652019-02-13 06:25:10 -05001385 use_bytes = isinstance(cmd, bytes)
1386
Barry Warsaw618738b2013-04-16 11:05:03 -04001387 if path is None:
Victor Stinner228a3c92019-04-17 16:26:36 +02001388 path = os.environ.get("PATH", None)
1389 if path is None:
1390 try:
1391 path = os.confstr("CS_PATH")
1392 except (AttributeError, ValueError):
1393 # os.confstr() or CS_PATH is not available
1394 path = os.defpath
1395 # bpo-35755: Don't use os.defpath if the PATH environment variable is
Victor Stinner197f0442019-04-17 17:44:06 +02001396 # set to an empty string
Victor Stinner228a3c92019-04-17 16:26:36 +02001397
1398 # PATH='' doesn't match, whereas PATH=':' looks in the current directory
Barry Warsaw618738b2013-04-16 11:05:03 -04001399 if not path:
1400 return None
Victor Stinner228a3c92019-04-17 16:26:36 +02001401
Cheryl Sabella5680f652019-02-13 06:25:10 -05001402 if use_bytes:
1403 path = os.fsencode(path)
1404 path = path.split(os.fsencode(os.pathsep))
1405 else:
1406 path = os.fsdecode(path)
1407 path = path.split(os.pathsep)
Brian Curtinc57a3452012-06-22 16:00:30 -05001408
1409 if sys.platform == "win32":
1410 # The current directory takes precedence on Windows.
Cheryl Sabella5680f652019-02-13 06:25:10 -05001411 curdir = os.curdir
1412 if use_bytes:
1413 curdir = os.fsencode(curdir)
1414 if curdir not in path:
1415 path.insert(0, curdir)
Brian Curtinc57a3452012-06-22 16:00:30 -05001416
1417 # PATHEXT is necessary to check on Windows.
1418 pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
Cheryl Sabella5680f652019-02-13 06:25:10 -05001419 if use_bytes:
1420 pathext = [os.fsencode(ext) for ext in pathext]
Brian Curtinc57a3452012-06-22 16:00:30 -05001421 # See if the given file matches any of the expected path extensions.
1422 # This will allow us to short circuit when given "python.exe".
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001423 # If it does match, only test that one, otherwise we have to try
1424 # others.
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001425 if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
1426 files = [cmd]
1427 else:
1428 files = [cmd + ext for ext in pathext]
Brian Curtinc57a3452012-06-22 16:00:30 -05001429 else:
1430 # On other platforms you don't have things like PATHEXT to tell you
1431 # what file suffixes are executable, so just pass on cmd as-is.
1432 files = [cmd]
1433
1434 seen = set()
1435 for dir in path:
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001436 normdir = os.path.normcase(dir)
1437 if not normdir in seen:
1438 seen.add(normdir)
Brian Curtinc57a3452012-06-22 16:00:30 -05001439 for thefile in files:
1440 name = os.path.join(dir, thefile)
1441 if _access_check(name, mode):
1442 return name
1443 return None