xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/shutil.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker"""Utility functions for copying and archiving files and directory trees.
2*cda5da8dSAndroid Build Coastguard Worker
3*cda5da8dSAndroid Build Coastguard WorkerXXX The functions here don't copy the resource fork or other metadata on Mac.
4*cda5da8dSAndroid Build Coastguard Worker
5*cda5da8dSAndroid Build Coastguard Worker"""
6*cda5da8dSAndroid Build Coastguard Worker
7*cda5da8dSAndroid Build Coastguard Workerimport os
8*cda5da8dSAndroid Build Coastguard Workerimport sys
9*cda5da8dSAndroid Build Coastguard Workerimport stat
10*cda5da8dSAndroid Build Coastguard Workerimport fnmatch
11*cda5da8dSAndroid Build Coastguard Workerimport collections
12*cda5da8dSAndroid Build Coastguard Workerimport errno
13*cda5da8dSAndroid Build Coastguard Worker
14*cda5da8dSAndroid Build Coastguard Workertry:
15*cda5da8dSAndroid Build Coastguard Worker    import zlib
16*cda5da8dSAndroid Build Coastguard Worker    del zlib
17*cda5da8dSAndroid Build Coastguard Worker    _ZLIB_SUPPORTED = True
18*cda5da8dSAndroid Build Coastguard Workerexcept ImportError:
19*cda5da8dSAndroid Build Coastguard Worker    _ZLIB_SUPPORTED = False
20*cda5da8dSAndroid Build Coastguard Worker
21*cda5da8dSAndroid Build Coastguard Workertry:
22*cda5da8dSAndroid Build Coastguard Worker    import bz2
23*cda5da8dSAndroid Build Coastguard Worker    del bz2
24*cda5da8dSAndroid Build Coastguard Worker    _BZ2_SUPPORTED = True
25*cda5da8dSAndroid Build Coastguard Workerexcept ImportError:
26*cda5da8dSAndroid Build Coastguard Worker    _BZ2_SUPPORTED = False
27*cda5da8dSAndroid Build Coastguard Worker
28*cda5da8dSAndroid Build Coastguard Workertry:
29*cda5da8dSAndroid Build Coastguard Worker    import lzma
30*cda5da8dSAndroid Build Coastguard Worker    del lzma
31*cda5da8dSAndroid Build Coastguard Worker    _LZMA_SUPPORTED = True
32*cda5da8dSAndroid Build Coastguard Workerexcept ImportError:
33*cda5da8dSAndroid Build Coastguard Worker    _LZMA_SUPPORTED = False
34*cda5da8dSAndroid Build Coastguard Worker
35*cda5da8dSAndroid Build Coastguard Worker_WINDOWS = os.name == 'nt'
36*cda5da8dSAndroid Build Coastguard Workerposix = nt = None
37*cda5da8dSAndroid Build Coastguard Workerif os.name == 'posix':
38*cda5da8dSAndroid Build Coastguard Worker    import posix
39*cda5da8dSAndroid Build Coastguard Workerelif _WINDOWS:
40*cda5da8dSAndroid Build Coastguard Worker    import nt
41*cda5da8dSAndroid Build Coastguard Worker
42*cda5da8dSAndroid Build Coastguard WorkerCOPY_BUFSIZE = 1024 * 1024 if _WINDOWS else 64 * 1024
43*cda5da8dSAndroid Build Coastguard Worker# This should never be removed, see rationale in:
44*cda5da8dSAndroid Build Coastguard Worker# https://bugs.python.org/issue43743#msg393429
45*cda5da8dSAndroid Build Coastguard Worker_USE_CP_SENDFILE = hasattr(os, "sendfile") and sys.platform.startswith("linux")
46*cda5da8dSAndroid Build Coastguard Worker_HAS_FCOPYFILE = posix and hasattr(posix, "_fcopyfile")  # macOS
47*cda5da8dSAndroid Build Coastguard Worker
48*cda5da8dSAndroid Build Coastguard Worker# CMD defaults in Windows 10
49*cda5da8dSAndroid Build Coastguard Worker_WIN_DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC"
50*cda5da8dSAndroid Build Coastguard Worker
51*cda5da8dSAndroid Build Coastguard Worker__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
52*cda5da8dSAndroid Build Coastguard Worker           "copytree", "move", "rmtree", "Error", "SpecialFileError",
53*cda5da8dSAndroid Build Coastguard Worker           "ExecError", "make_archive", "get_archive_formats",
54*cda5da8dSAndroid Build Coastguard Worker           "register_archive_format", "unregister_archive_format",
55*cda5da8dSAndroid Build Coastguard Worker           "get_unpack_formats", "register_unpack_format",
56*cda5da8dSAndroid Build Coastguard Worker           "unregister_unpack_format", "unpack_archive",
57*cda5da8dSAndroid Build Coastguard Worker           "ignore_patterns", "chown", "which", "get_terminal_size",
58*cda5da8dSAndroid Build Coastguard Worker           "SameFileError"]
59*cda5da8dSAndroid Build Coastguard Worker           # disk_usage is added later, if available on the platform
60*cda5da8dSAndroid Build Coastguard Worker
61*cda5da8dSAndroid Build Coastguard Workerclass Error(OSError):
62*cda5da8dSAndroid Build Coastguard Worker    pass
63*cda5da8dSAndroid Build Coastguard Worker
64*cda5da8dSAndroid Build Coastguard Workerclass SameFileError(Error):
65*cda5da8dSAndroid Build Coastguard Worker    """Raised when source and destination are the same file."""
66*cda5da8dSAndroid Build Coastguard Worker
67*cda5da8dSAndroid Build Coastguard Workerclass SpecialFileError(OSError):
68*cda5da8dSAndroid Build Coastguard Worker    """Raised when trying to do a kind of operation (e.g. copying) which is
69*cda5da8dSAndroid Build Coastguard Worker    not supported on a special file (e.g. a named pipe)"""
70*cda5da8dSAndroid Build Coastguard Worker
71*cda5da8dSAndroid Build Coastguard Workerclass ExecError(OSError):
72*cda5da8dSAndroid Build Coastguard Worker    """Raised when a command could not be executed"""
73*cda5da8dSAndroid Build Coastguard Worker
74*cda5da8dSAndroid Build Coastguard Workerclass ReadError(OSError):
75*cda5da8dSAndroid Build Coastguard Worker    """Raised when an archive cannot be read"""
76*cda5da8dSAndroid Build Coastguard Worker
77*cda5da8dSAndroid Build Coastguard Workerclass RegistryError(Exception):
78*cda5da8dSAndroid Build Coastguard Worker    """Raised when a registry operation with the archiving
79*cda5da8dSAndroid Build Coastguard Worker    and unpacking registries fails"""
80*cda5da8dSAndroid Build Coastguard Worker
81*cda5da8dSAndroid Build Coastguard Workerclass _GiveupOnFastCopy(Exception):
82*cda5da8dSAndroid Build Coastguard Worker    """Raised as a signal to fallback on using raw read()/write()
83*cda5da8dSAndroid Build Coastguard Worker    file copy when fast-copy functions fail to do so.
84*cda5da8dSAndroid Build Coastguard Worker    """
85*cda5da8dSAndroid Build Coastguard Worker
86*cda5da8dSAndroid Build Coastguard Workerdef _fastcopy_fcopyfile(fsrc, fdst, flags):
87*cda5da8dSAndroid Build Coastguard Worker    """Copy a regular file content or metadata by using high-performance
88*cda5da8dSAndroid Build Coastguard Worker    fcopyfile(3) syscall (macOS).
89*cda5da8dSAndroid Build Coastguard Worker    """
90*cda5da8dSAndroid Build Coastguard Worker    try:
91*cda5da8dSAndroid Build Coastguard Worker        infd = fsrc.fileno()
92*cda5da8dSAndroid Build Coastguard Worker        outfd = fdst.fileno()
93*cda5da8dSAndroid Build Coastguard Worker    except Exception as err:
94*cda5da8dSAndroid Build Coastguard Worker        raise _GiveupOnFastCopy(err)  # not a regular file
95*cda5da8dSAndroid Build Coastguard Worker
96*cda5da8dSAndroid Build Coastguard Worker    try:
97*cda5da8dSAndroid Build Coastguard Worker        posix._fcopyfile(infd, outfd, flags)
98*cda5da8dSAndroid Build Coastguard Worker    except OSError as err:
99*cda5da8dSAndroid Build Coastguard Worker        err.filename = fsrc.name
100*cda5da8dSAndroid Build Coastguard Worker        err.filename2 = fdst.name
101*cda5da8dSAndroid Build Coastguard Worker        if err.errno in {errno.EINVAL, errno.ENOTSUP}:
102*cda5da8dSAndroid Build Coastguard Worker            raise _GiveupOnFastCopy(err)
103*cda5da8dSAndroid Build Coastguard Worker        else:
104*cda5da8dSAndroid Build Coastguard Worker            raise err from None
105*cda5da8dSAndroid Build Coastguard Worker
106*cda5da8dSAndroid Build Coastguard Workerdef _fastcopy_sendfile(fsrc, fdst):
107*cda5da8dSAndroid Build Coastguard Worker    """Copy data from one regular mmap-like fd to another by using
108*cda5da8dSAndroid Build Coastguard Worker    high-performance sendfile(2) syscall.
109*cda5da8dSAndroid Build Coastguard Worker    This should work on Linux >= 2.6.33 only.
110*cda5da8dSAndroid Build Coastguard Worker    """
111*cda5da8dSAndroid Build Coastguard Worker    # Note: copyfileobj() is left alone in order to not introduce any
112*cda5da8dSAndroid Build Coastguard Worker    # unexpected breakage. Possible risks by using zero-copy calls
113*cda5da8dSAndroid Build Coastguard Worker    # in copyfileobj() are:
114*cda5da8dSAndroid Build Coastguard Worker    # - fdst cannot be open in "a"(ppend) mode
115*cda5da8dSAndroid Build Coastguard Worker    # - fsrc and fdst may be open in "t"(ext) mode
116*cda5da8dSAndroid Build Coastguard Worker    # - fsrc may be a BufferedReader (which hides unread data in a buffer),
117*cda5da8dSAndroid Build Coastguard Worker    #   GzipFile (which decompresses data), HTTPResponse (which decodes
118*cda5da8dSAndroid Build Coastguard Worker    #   chunks).
119*cda5da8dSAndroid Build Coastguard Worker    # - possibly others (e.g. encrypted fs/partition?)
120*cda5da8dSAndroid Build Coastguard Worker    global _USE_CP_SENDFILE
121*cda5da8dSAndroid Build Coastguard Worker    try:
122*cda5da8dSAndroid Build Coastguard Worker        infd = fsrc.fileno()
123*cda5da8dSAndroid Build Coastguard Worker        outfd = fdst.fileno()
124*cda5da8dSAndroid Build Coastguard Worker    except Exception as err:
125*cda5da8dSAndroid Build Coastguard Worker        raise _GiveupOnFastCopy(err)  # not a regular file
126*cda5da8dSAndroid Build Coastguard Worker
127*cda5da8dSAndroid Build Coastguard Worker    # Hopefully the whole file will be copied in a single call.
128*cda5da8dSAndroid Build Coastguard Worker    # sendfile() is called in a loop 'till EOF is reached (0 return)
129*cda5da8dSAndroid Build Coastguard Worker    # so a bufsize smaller or bigger than the actual file size
130*cda5da8dSAndroid Build Coastguard Worker    # should not make any difference, also in case the file content
131*cda5da8dSAndroid Build Coastguard Worker    # changes while being copied.
132*cda5da8dSAndroid Build Coastguard Worker    try:
133*cda5da8dSAndroid Build Coastguard Worker        blocksize = max(os.fstat(infd).st_size, 2 ** 23)  # min 8MiB
134*cda5da8dSAndroid Build Coastguard Worker    except OSError:
135*cda5da8dSAndroid Build Coastguard Worker        blocksize = 2 ** 27  # 128MiB
136*cda5da8dSAndroid Build Coastguard Worker    # On 32-bit architectures truncate to 1GiB to avoid OverflowError,
137*cda5da8dSAndroid Build Coastguard Worker    # see bpo-38319.
138*cda5da8dSAndroid Build Coastguard Worker    if sys.maxsize < 2 ** 32:
139*cda5da8dSAndroid Build Coastguard Worker        blocksize = min(blocksize, 2 ** 30)
140*cda5da8dSAndroid Build Coastguard Worker
141*cda5da8dSAndroid Build Coastguard Worker    offset = 0
142*cda5da8dSAndroid Build Coastguard Worker    while True:
143*cda5da8dSAndroid Build Coastguard Worker        try:
144*cda5da8dSAndroid Build Coastguard Worker            sent = os.sendfile(outfd, infd, offset, blocksize)
145*cda5da8dSAndroid Build Coastguard Worker        except OSError as err:
146*cda5da8dSAndroid Build Coastguard Worker            # ...in oder to have a more informative exception.
147*cda5da8dSAndroid Build Coastguard Worker            err.filename = fsrc.name
148*cda5da8dSAndroid Build Coastguard Worker            err.filename2 = fdst.name
149*cda5da8dSAndroid Build Coastguard Worker
150*cda5da8dSAndroid Build Coastguard Worker            if err.errno == errno.ENOTSOCK:
151*cda5da8dSAndroid Build Coastguard Worker                # sendfile() on this platform (probably Linux < 2.6.33)
152*cda5da8dSAndroid Build Coastguard Worker                # does not support copies between regular files (only
153*cda5da8dSAndroid Build Coastguard Worker                # sockets).
154*cda5da8dSAndroid Build Coastguard Worker                _USE_CP_SENDFILE = False
155*cda5da8dSAndroid Build Coastguard Worker                raise _GiveupOnFastCopy(err)
156*cda5da8dSAndroid Build Coastguard Worker
157*cda5da8dSAndroid Build Coastguard Worker            if err.errno == errno.ENOSPC:  # filesystem is full
158*cda5da8dSAndroid Build Coastguard Worker                raise err from None
159*cda5da8dSAndroid Build Coastguard Worker
160*cda5da8dSAndroid Build Coastguard Worker            # Give up on first call and if no data was copied.
161*cda5da8dSAndroid Build Coastguard Worker            if offset == 0 and os.lseek(outfd, 0, os.SEEK_CUR) == 0:
162*cda5da8dSAndroid Build Coastguard Worker                raise _GiveupOnFastCopy(err)
163*cda5da8dSAndroid Build Coastguard Worker
164*cda5da8dSAndroid Build Coastguard Worker            raise err
165*cda5da8dSAndroid Build Coastguard Worker        else:
166*cda5da8dSAndroid Build Coastguard Worker            if sent == 0:
167*cda5da8dSAndroid Build Coastguard Worker                break  # EOF
168*cda5da8dSAndroid Build Coastguard Worker            offset += sent
169*cda5da8dSAndroid Build Coastguard Worker
170*cda5da8dSAndroid Build Coastguard Workerdef _copyfileobj_readinto(fsrc, fdst, length=COPY_BUFSIZE):
171*cda5da8dSAndroid Build Coastguard Worker    """readinto()/memoryview() based variant of copyfileobj().
172*cda5da8dSAndroid Build Coastguard Worker    *fsrc* must support readinto() method and both files must be
173*cda5da8dSAndroid Build Coastguard Worker    open in binary mode.
174*cda5da8dSAndroid Build Coastguard Worker    """
175*cda5da8dSAndroid Build Coastguard Worker    # Localize variable access to minimize overhead.
176*cda5da8dSAndroid Build Coastguard Worker    fsrc_readinto = fsrc.readinto
177*cda5da8dSAndroid Build Coastguard Worker    fdst_write = fdst.write
178*cda5da8dSAndroid Build Coastguard Worker    with memoryview(bytearray(length)) as mv:
179*cda5da8dSAndroid Build Coastguard Worker        while True:
180*cda5da8dSAndroid Build Coastguard Worker            n = fsrc_readinto(mv)
181*cda5da8dSAndroid Build Coastguard Worker            if not n:
182*cda5da8dSAndroid Build Coastguard Worker                break
183*cda5da8dSAndroid Build Coastguard Worker            elif n < length:
184*cda5da8dSAndroid Build Coastguard Worker                with mv[:n] as smv:
185*cda5da8dSAndroid Build Coastguard Worker                    fdst.write(smv)
186*cda5da8dSAndroid Build Coastguard Worker            else:
187*cda5da8dSAndroid Build Coastguard Worker                fdst_write(mv)
188*cda5da8dSAndroid Build Coastguard Worker
189*cda5da8dSAndroid Build Coastguard Workerdef copyfileobj(fsrc, fdst, length=0):
190*cda5da8dSAndroid Build Coastguard Worker    """copy data from file-like object fsrc to file-like object fdst"""
191*cda5da8dSAndroid Build Coastguard Worker    if not length:
192*cda5da8dSAndroid Build Coastguard Worker        length = COPY_BUFSIZE
193*cda5da8dSAndroid Build Coastguard Worker    # Localize variable access to minimize overhead.
194*cda5da8dSAndroid Build Coastguard Worker    fsrc_read = fsrc.read
195*cda5da8dSAndroid Build Coastguard Worker    fdst_write = fdst.write
196*cda5da8dSAndroid Build Coastguard Worker    while True:
197*cda5da8dSAndroid Build Coastguard Worker        buf = fsrc_read(length)
198*cda5da8dSAndroid Build Coastguard Worker        if not buf:
199*cda5da8dSAndroid Build Coastguard Worker            break
200*cda5da8dSAndroid Build Coastguard Worker        fdst_write(buf)
201*cda5da8dSAndroid Build Coastguard Worker
202*cda5da8dSAndroid Build Coastguard Workerdef _samefile(src, dst):
203*cda5da8dSAndroid Build Coastguard Worker    # Macintosh, Unix.
204*cda5da8dSAndroid Build Coastguard Worker    if isinstance(src, os.DirEntry) and hasattr(os.path, 'samestat'):
205*cda5da8dSAndroid Build Coastguard Worker        try:
206*cda5da8dSAndroid Build Coastguard Worker            return os.path.samestat(src.stat(), os.stat(dst))
207*cda5da8dSAndroid Build Coastguard Worker        except OSError:
208*cda5da8dSAndroid Build Coastguard Worker            return False
209*cda5da8dSAndroid Build Coastguard Worker
210*cda5da8dSAndroid Build Coastguard Worker    if hasattr(os.path, 'samefile'):
211*cda5da8dSAndroid Build Coastguard Worker        try:
212*cda5da8dSAndroid Build Coastguard Worker            return os.path.samefile(src, dst)
213*cda5da8dSAndroid Build Coastguard Worker        except OSError:
214*cda5da8dSAndroid Build Coastguard Worker            return False
215*cda5da8dSAndroid Build Coastguard Worker
216*cda5da8dSAndroid Build Coastguard Worker    # All other platforms: check for same pathname.
217*cda5da8dSAndroid Build Coastguard Worker    return (os.path.normcase(os.path.abspath(src)) ==
218*cda5da8dSAndroid Build Coastguard Worker            os.path.normcase(os.path.abspath(dst)))
219*cda5da8dSAndroid Build Coastguard Worker
220*cda5da8dSAndroid Build Coastguard Workerdef _stat(fn):
221*cda5da8dSAndroid Build Coastguard Worker    return fn.stat() if isinstance(fn, os.DirEntry) else os.stat(fn)
222*cda5da8dSAndroid Build Coastguard Worker
223*cda5da8dSAndroid Build Coastguard Workerdef _islink(fn):
224*cda5da8dSAndroid Build Coastguard Worker    return fn.is_symlink() if isinstance(fn, os.DirEntry) else os.path.islink(fn)
225*cda5da8dSAndroid Build Coastguard Worker
226*cda5da8dSAndroid Build Coastguard Workerdef copyfile(src, dst, *, follow_symlinks=True):
227*cda5da8dSAndroid Build Coastguard Worker    """Copy data from src to dst in the most efficient way possible.
228*cda5da8dSAndroid Build Coastguard Worker
229*cda5da8dSAndroid Build Coastguard Worker    If follow_symlinks is not set and src is a symbolic link, a new
230*cda5da8dSAndroid Build Coastguard Worker    symlink will be created instead of copying the file it points to.
231*cda5da8dSAndroid Build Coastguard Worker
232*cda5da8dSAndroid Build Coastguard Worker    """
233*cda5da8dSAndroid Build Coastguard Worker    sys.audit("shutil.copyfile", src, dst)
234*cda5da8dSAndroid Build Coastguard Worker
235*cda5da8dSAndroid Build Coastguard Worker    if _samefile(src, dst):
236*cda5da8dSAndroid Build Coastguard Worker        raise SameFileError("{!r} and {!r} are the same file".format(src, dst))
237*cda5da8dSAndroid Build Coastguard Worker
238*cda5da8dSAndroid Build Coastguard Worker    file_size = 0
239*cda5da8dSAndroid Build Coastguard Worker    for i, fn in enumerate([src, dst]):
240*cda5da8dSAndroid Build Coastguard Worker        try:
241*cda5da8dSAndroid Build Coastguard Worker            st = _stat(fn)
242*cda5da8dSAndroid Build Coastguard Worker        except OSError:
243*cda5da8dSAndroid Build Coastguard Worker            # File most likely does not exist
244*cda5da8dSAndroid Build Coastguard Worker            pass
245*cda5da8dSAndroid Build Coastguard Worker        else:
246*cda5da8dSAndroid Build Coastguard Worker            # XXX What about other special files? (sockets, devices...)
247*cda5da8dSAndroid Build Coastguard Worker            if stat.S_ISFIFO(st.st_mode):
248*cda5da8dSAndroid Build Coastguard Worker                fn = fn.path if isinstance(fn, os.DirEntry) else fn
249*cda5da8dSAndroid Build Coastguard Worker                raise SpecialFileError("`%s` is a named pipe" % fn)
250*cda5da8dSAndroid Build Coastguard Worker            if _WINDOWS and i == 0:
251*cda5da8dSAndroid Build Coastguard Worker                file_size = st.st_size
252*cda5da8dSAndroid Build Coastguard Worker
253*cda5da8dSAndroid Build Coastguard Worker    if not follow_symlinks and _islink(src):
254*cda5da8dSAndroid Build Coastguard Worker        os.symlink(os.readlink(src), dst)
255*cda5da8dSAndroid Build Coastguard Worker    else:
256*cda5da8dSAndroid Build Coastguard Worker        with open(src, 'rb') as fsrc:
257*cda5da8dSAndroid Build Coastguard Worker            try:
258*cda5da8dSAndroid Build Coastguard Worker                with open(dst, 'wb') as fdst:
259*cda5da8dSAndroid Build Coastguard Worker                    # macOS
260*cda5da8dSAndroid Build Coastguard Worker                    if _HAS_FCOPYFILE:
261*cda5da8dSAndroid Build Coastguard Worker                        try:
262*cda5da8dSAndroid Build Coastguard Worker                            _fastcopy_fcopyfile(fsrc, fdst, posix._COPYFILE_DATA)
263*cda5da8dSAndroid Build Coastguard Worker                            return dst
264*cda5da8dSAndroid Build Coastguard Worker                        except _GiveupOnFastCopy:
265*cda5da8dSAndroid Build Coastguard Worker                            pass
266*cda5da8dSAndroid Build Coastguard Worker                    # Linux
267*cda5da8dSAndroid Build Coastguard Worker                    elif _USE_CP_SENDFILE:
268*cda5da8dSAndroid Build Coastguard Worker                        try:
269*cda5da8dSAndroid Build Coastguard Worker                            _fastcopy_sendfile(fsrc, fdst)
270*cda5da8dSAndroid Build Coastguard Worker                            return dst
271*cda5da8dSAndroid Build Coastguard Worker                        except _GiveupOnFastCopy:
272*cda5da8dSAndroid Build Coastguard Worker                            pass
273*cda5da8dSAndroid Build Coastguard Worker                    # Windows, see:
274*cda5da8dSAndroid Build Coastguard Worker                    # https://github.com/python/cpython/pull/7160#discussion_r195405230
275*cda5da8dSAndroid Build Coastguard Worker                    elif _WINDOWS and file_size > 0:
276*cda5da8dSAndroid Build Coastguard Worker                        _copyfileobj_readinto(fsrc, fdst, min(file_size, COPY_BUFSIZE))
277*cda5da8dSAndroid Build Coastguard Worker                        return dst
278*cda5da8dSAndroid Build Coastguard Worker
279*cda5da8dSAndroid Build Coastguard Worker                    copyfileobj(fsrc, fdst)
280*cda5da8dSAndroid Build Coastguard Worker
281*cda5da8dSAndroid Build Coastguard Worker            # Issue 43219, raise a less confusing exception
282*cda5da8dSAndroid Build Coastguard Worker            except IsADirectoryError as e:
283*cda5da8dSAndroid Build Coastguard Worker                if not os.path.exists(dst):
284*cda5da8dSAndroid Build Coastguard Worker                    raise FileNotFoundError(f'Directory does not exist: {dst}') from e
285*cda5da8dSAndroid Build Coastguard Worker                else:
286*cda5da8dSAndroid Build Coastguard Worker                    raise
287*cda5da8dSAndroid Build Coastguard Worker
288*cda5da8dSAndroid Build Coastguard Worker    return dst
289*cda5da8dSAndroid Build Coastguard Worker
290*cda5da8dSAndroid Build Coastguard Workerdef copymode(src, dst, *, follow_symlinks=True):
291*cda5da8dSAndroid Build Coastguard Worker    """Copy mode bits from src to dst.
292*cda5da8dSAndroid Build Coastguard Worker
293*cda5da8dSAndroid Build Coastguard Worker    If follow_symlinks is not set, symlinks aren't followed if and only
294*cda5da8dSAndroid Build Coastguard Worker    if both `src` and `dst` are symlinks.  If `lchmod` isn't available
295*cda5da8dSAndroid Build Coastguard Worker    (e.g. Linux) this method does nothing.
296*cda5da8dSAndroid Build Coastguard Worker
297*cda5da8dSAndroid Build Coastguard Worker    """
298*cda5da8dSAndroid Build Coastguard Worker    sys.audit("shutil.copymode", src, dst)
299*cda5da8dSAndroid Build Coastguard Worker
300*cda5da8dSAndroid Build Coastguard Worker    if not follow_symlinks and _islink(src) and os.path.islink(dst):
301*cda5da8dSAndroid Build Coastguard Worker        if hasattr(os, 'lchmod'):
302*cda5da8dSAndroid Build Coastguard Worker            stat_func, chmod_func = os.lstat, os.lchmod
303*cda5da8dSAndroid Build Coastguard Worker        else:
304*cda5da8dSAndroid Build Coastguard Worker            return
305*cda5da8dSAndroid Build Coastguard Worker    else:
306*cda5da8dSAndroid Build Coastguard Worker        stat_func, chmod_func = _stat, os.chmod
307*cda5da8dSAndroid Build Coastguard Worker
308*cda5da8dSAndroid Build Coastguard Worker    st = stat_func(src)
309*cda5da8dSAndroid Build Coastguard Worker    chmod_func(dst, stat.S_IMODE(st.st_mode))
310*cda5da8dSAndroid Build Coastguard Worker
311*cda5da8dSAndroid Build Coastguard Workerif hasattr(os, 'listxattr'):
312*cda5da8dSAndroid Build Coastguard Worker    def _copyxattr(src, dst, *, follow_symlinks=True):
313*cda5da8dSAndroid Build Coastguard Worker        """Copy extended filesystem attributes from `src` to `dst`.
314*cda5da8dSAndroid Build Coastguard Worker
315*cda5da8dSAndroid Build Coastguard Worker        Overwrite existing attributes.
316*cda5da8dSAndroid Build Coastguard Worker
317*cda5da8dSAndroid Build Coastguard Worker        If `follow_symlinks` is false, symlinks won't be followed.
318*cda5da8dSAndroid Build Coastguard Worker
319*cda5da8dSAndroid Build Coastguard Worker        """
320*cda5da8dSAndroid Build Coastguard Worker
321*cda5da8dSAndroid Build Coastguard Worker        try:
322*cda5da8dSAndroid Build Coastguard Worker            names = os.listxattr(src, follow_symlinks=follow_symlinks)
323*cda5da8dSAndroid Build Coastguard Worker        except OSError as e:
324*cda5da8dSAndroid Build Coastguard Worker            if e.errno not in (errno.ENOTSUP, errno.ENODATA, errno.EINVAL):
325*cda5da8dSAndroid Build Coastguard Worker                raise
326*cda5da8dSAndroid Build Coastguard Worker            return
327*cda5da8dSAndroid Build Coastguard Worker        for name in names:
328*cda5da8dSAndroid Build Coastguard Worker            try:
329*cda5da8dSAndroid Build Coastguard Worker                value = os.getxattr(src, name, follow_symlinks=follow_symlinks)
330*cda5da8dSAndroid Build Coastguard Worker                os.setxattr(dst, name, value, follow_symlinks=follow_symlinks)
331*cda5da8dSAndroid Build Coastguard Worker            except OSError as e:
332*cda5da8dSAndroid Build Coastguard Worker                if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA,
333*cda5da8dSAndroid Build Coastguard Worker                                   errno.EINVAL):
334*cda5da8dSAndroid Build Coastguard Worker                    raise
335*cda5da8dSAndroid Build Coastguard Workerelse:
336*cda5da8dSAndroid Build Coastguard Worker    def _copyxattr(*args, **kwargs):
337*cda5da8dSAndroid Build Coastguard Worker        pass
338*cda5da8dSAndroid Build Coastguard Worker
339*cda5da8dSAndroid Build Coastguard Workerdef copystat(src, dst, *, follow_symlinks=True):
340*cda5da8dSAndroid Build Coastguard Worker    """Copy file metadata
341*cda5da8dSAndroid Build Coastguard Worker
342*cda5da8dSAndroid Build Coastguard Worker    Copy the permission bits, last access time, last modification time, and
343*cda5da8dSAndroid Build Coastguard Worker    flags from `src` to `dst`. On Linux, copystat() also copies the "extended
344*cda5da8dSAndroid Build Coastguard Worker    attributes" where possible. The file contents, owner, and group are
345*cda5da8dSAndroid Build Coastguard Worker    unaffected. `src` and `dst` are path-like objects or path names given as
346*cda5da8dSAndroid Build Coastguard Worker    strings.
347*cda5da8dSAndroid Build Coastguard Worker
348*cda5da8dSAndroid Build Coastguard Worker    If the optional flag `follow_symlinks` is not set, symlinks aren't
349*cda5da8dSAndroid Build Coastguard Worker    followed if and only if both `src` and `dst` are symlinks.
350*cda5da8dSAndroid Build Coastguard Worker    """
351*cda5da8dSAndroid Build Coastguard Worker    sys.audit("shutil.copystat", src, dst)
352*cda5da8dSAndroid Build Coastguard Worker
353*cda5da8dSAndroid Build Coastguard Worker    def _nop(*args, ns=None, follow_symlinks=None):
354*cda5da8dSAndroid Build Coastguard Worker        pass
355*cda5da8dSAndroid Build Coastguard Worker
356*cda5da8dSAndroid Build Coastguard Worker    # follow symlinks (aka don't not follow symlinks)
357*cda5da8dSAndroid Build Coastguard Worker    follow = follow_symlinks or not (_islink(src) and os.path.islink(dst))
358*cda5da8dSAndroid Build Coastguard Worker    if follow:
359*cda5da8dSAndroid Build Coastguard Worker        # use the real function if it exists
360*cda5da8dSAndroid Build Coastguard Worker        def lookup(name):
361*cda5da8dSAndroid Build Coastguard Worker            return getattr(os, name, _nop)
362*cda5da8dSAndroid Build Coastguard Worker    else:
363*cda5da8dSAndroid Build Coastguard Worker        # use the real function only if it exists
364*cda5da8dSAndroid Build Coastguard Worker        # *and* it supports follow_symlinks
365*cda5da8dSAndroid Build Coastguard Worker        def lookup(name):
366*cda5da8dSAndroid Build Coastguard Worker            fn = getattr(os, name, _nop)
367*cda5da8dSAndroid Build Coastguard Worker            if fn in os.supports_follow_symlinks:
368*cda5da8dSAndroid Build Coastguard Worker                return fn
369*cda5da8dSAndroid Build Coastguard Worker            return _nop
370*cda5da8dSAndroid Build Coastguard Worker
371*cda5da8dSAndroid Build Coastguard Worker    if isinstance(src, os.DirEntry):
372*cda5da8dSAndroid Build Coastguard Worker        st = src.stat(follow_symlinks=follow)
373*cda5da8dSAndroid Build Coastguard Worker    else:
374*cda5da8dSAndroid Build Coastguard Worker        st = lookup("stat")(src, follow_symlinks=follow)
375*cda5da8dSAndroid Build Coastguard Worker    mode = stat.S_IMODE(st.st_mode)
376*cda5da8dSAndroid Build Coastguard Worker    lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns),
377*cda5da8dSAndroid Build Coastguard Worker        follow_symlinks=follow)
378*cda5da8dSAndroid Build Coastguard Worker    # We must copy extended attributes before the file is (potentially)
379*cda5da8dSAndroid Build Coastguard Worker    # chmod()'ed read-only, otherwise setxattr() will error with -EACCES.
380*cda5da8dSAndroid Build Coastguard Worker    _copyxattr(src, dst, follow_symlinks=follow)
381*cda5da8dSAndroid Build Coastguard Worker    try:
382*cda5da8dSAndroid Build Coastguard Worker        lookup("chmod")(dst, mode, follow_symlinks=follow)
383*cda5da8dSAndroid Build Coastguard Worker    except NotImplementedError:
384*cda5da8dSAndroid Build Coastguard Worker        # if we got a NotImplementedError, it's because
385*cda5da8dSAndroid Build Coastguard Worker        #   * follow_symlinks=False,
386*cda5da8dSAndroid Build Coastguard Worker        #   * lchown() is unavailable, and
387*cda5da8dSAndroid Build Coastguard Worker        #   * either
388*cda5da8dSAndroid Build Coastguard Worker        #       * fchownat() is unavailable or
389*cda5da8dSAndroid Build Coastguard Worker        #       * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW.
390*cda5da8dSAndroid Build Coastguard Worker        #         (it returned ENOSUP.)
391*cda5da8dSAndroid Build Coastguard Worker        # therefore we're out of options--we simply cannot chown the
392*cda5da8dSAndroid Build Coastguard Worker        # symlink.  give up, suppress the error.
393*cda5da8dSAndroid Build Coastguard Worker        # (which is what shutil always did in this circumstance.)
394*cda5da8dSAndroid Build Coastguard Worker        pass
395*cda5da8dSAndroid Build Coastguard Worker    if hasattr(st, 'st_flags'):
396*cda5da8dSAndroid Build Coastguard Worker        try:
397*cda5da8dSAndroid Build Coastguard Worker            lookup("chflags")(dst, st.st_flags, follow_symlinks=follow)
398*cda5da8dSAndroid Build Coastguard Worker        except OSError as why:
399*cda5da8dSAndroid Build Coastguard Worker            for err in 'EOPNOTSUPP', 'ENOTSUP':
400*cda5da8dSAndroid Build Coastguard Worker                if hasattr(errno, err) and why.errno == getattr(errno, err):
401*cda5da8dSAndroid Build Coastguard Worker                    break
402*cda5da8dSAndroid Build Coastguard Worker            else:
403*cda5da8dSAndroid Build Coastguard Worker                raise
404*cda5da8dSAndroid Build Coastguard Worker
405*cda5da8dSAndroid Build Coastguard Workerdef copy(src, dst, *, follow_symlinks=True):
406*cda5da8dSAndroid Build Coastguard Worker    """Copy data and mode bits ("cp src dst"). Return the file's destination.
407*cda5da8dSAndroid Build Coastguard Worker
408*cda5da8dSAndroid Build Coastguard Worker    The destination may be a directory.
409*cda5da8dSAndroid Build Coastguard Worker
410*cda5da8dSAndroid Build Coastguard Worker    If follow_symlinks is false, symlinks won't be followed. This
411*cda5da8dSAndroid Build Coastguard Worker    resembles GNU's "cp -P src dst".
412*cda5da8dSAndroid Build Coastguard Worker
413*cda5da8dSAndroid Build Coastguard Worker    If source and destination are the same file, a SameFileError will be
414*cda5da8dSAndroid Build Coastguard Worker    raised.
415*cda5da8dSAndroid Build Coastguard Worker
416*cda5da8dSAndroid Build Coastguard Worker    """
417*cda5da8dSAndroid Build Coastguard Worker    if os.path.isdir(dst):
418*cda5da8dSAndroid Build Coastguard Worker        dst = os.path.join(dst, os.path.basename(src))
419*cda5da8dSAndroid Build Coastguard Worker    copyfile(src, dst, follow_symlinks=follow_symlinks)
420*cda5da8dSAndroid Build Coastguard Worker    copymode(src, dst, follow_symlinks=follow_symlinks)
421*cda5da8dSAndroid Build Coastguard Worker    return dst
422*cda5da8dSAndroid Build Coastguard Worker
423*cda5da8dSAndroid Build Coastguard Workerdef copy2(src, dst, *, follow_symlinks=True):
424*cda5da8dSAndroid Build Coastguard Worker    """Copy data and metadata. Return the file's destination.
425*cda5da8dSAndroid Build Coastguard Worker
426*cda5da8dSAndroid Build Coastguard Worker    Metadata is copied with copystat(). Please see the copystat function
427*cda5da8dSAndroid Build Coastguard Worker    for more information.
428*cda5da8dSAndroid Build Coastguard Worker
429*cda5da8dSAndroid Build Coastguard Worker    The destination may be a directory.
430*cda5da8dSAndroid Build Coastguard Worker
431*cda5da8dSAndroid Build Coastguard Worker    If follow_symlinks is false, symlinks won't be followed. This
432*cda5da8dSAndroid Build Coastguard Worker    resembles GNU's "cp -P src dst".
433*cda5da8dSAndroid Build Coastguard Worker    """
434*cda5da8dSAndroid Build Coastguard Worker    if os.path.isdir(dst):
435*cda5da8dSAndroid Build Coastguard Worker        dst = os.path.join(dst, os.path.basename(src))
436*cda5da8dSAndroid Build Coastguard Worker    copyfile(src, dst, follow_symlinks=follow_symlinks)
437*cda5da8dSAndroid Build Coastguard Worker    copystat(src, dst, follow_symlinks=follow_symlinks)
438*cda5da8dSAndroid Build Coastguard Worker    return dst
439*cda5da8dSAndroid Build Coastguard Worker
440*cda5da8dSAndroid Build Coastguard Workerdef ignore_patterns(*patterns):
441*cda5da8dSAndroid Build Coastguard Worker    """Function that can be used as copytree() ignore parameter.
442*cda5da8dSAndroid Build Coastguard Worker
443*cda5da8dSAndroid Build Coastguard Worker    Patterns is a sequence of glob-style patterns
444*cda5da8dSAndroid Build Coastguard Worker    that are used to exclude files"""
445*cda5da8dSAndroid Build Coastguard Worker    def _ignore_patterns(path, names):
446*cda5da8dSAndroid Build Coastguard Worker        ignored_names = []
447*cda5da8dSAndroid Build Coastguard Worker        for pattern in patterns:
448*cda5da8dSAndroid Build Coastguard Worker            ignored_names.extend(fnmatch.filter(names, pattern))
449*cda5da8dSAndroid Build Coastguard Worker        return set(ignored_names)
450*cda5da8dSAndroid Build Coastguard Worker    return _ignore_patterns
451*cda5da8dSAndroid Build Coastguard Worker
452*cda5da8dSAndroid Build Coastguard Workerdef _copytree(entries, src, dst, symlinks, ignore, copy_function,
453*cda5da8dSAndroid Build Coastguard Worker              ignore_dangling_symlinks, dirs_exist_ok=False):
454*cda5da8dSAndroid Build Coastguard Worker    if ignore is not None:
455*cda5da8dSAndroid Build Coastguard Worker        ignored_names = ignore(os.fspath(src), [x.name for x in entries])
456*cda5da8dSAndroid Build Coastguard Worker    else:
457*cda5da8dSAndroid Build Coastguard Worker        ignored_names = set()
458*cda5da8dSAndroid Build Coastguard Worker
459*cda5da8dSAndroid Build Coastguard Worker    os.makedirs(dst, exist_ok=dirs_exist_ok)
460*cda5da8dSAndroid Build Coastguard Worker    errors = []
461*cda5da8dSAndroid Build Coastguard Worker    use_srcentry = copy_function is copy2 or copy_function is copy
462*cda5da8dSAndroid Build Coastguard Worker
463*cda5da8dSAndroid Build Coastguard Worker    for srcentry in entries:
464*cda5da8dSAndroid Build Coastguard Worker        if srcentry.name in ignored_names:
465*cda5da8dSAndroid Build Coastguard Worker            continue
466*cda5da8dSAndroid Build Coastguard Worker        srcname = os.path.join(src, srcentry.name)
467*cda5da8dSAndroid Build Coastguard Worker        dstname = os.path.join(dst, srcentry.name)
468*cda5da8dSAndroid Build Coastguard Worker        srcobj = srcentry if use_srcentry else srcname
469*cda5da8dSAndroid Build Coastguard Worker        try:
470*cda5da8dSAndroid Build Coastguard Worker            is_symlink = srcentry.is_symlink()
471*cda5da8dSAndroid Build Coastguard Worker            if is_symlink and os.name == 'nt':
472*cda5da8dSAndroid Build Coastguard Worker                # Special check for directory junctions, which appear as
473*cda5da8dSAndroid Build Coastguard Worker                # symlinks but we want to recurse.
474*cda5da8dSAndroid Build Coastguard Worker                lstat = srcentry.stat(follow_symlinks=False)
475*cda5da8dSAndroid Build Coastguard Worker                if lstat.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT:
476*cda5da8dSAndroid Build Coastguard Worker                    is_symlink = False
477*cda5da8dSAndroid Build Coastguard Worker            if is_symlink:
478*cda5da8dSAndroid Build Coastguard Worker                linkto = os.readlink(srcname)
479*cda5da8dSAndroid Build Coastguard Worker                if symlinks:
480*cda5da8dSAndroid Build Coastguard Worker                    # We can't just leave it to `copy_function` because legacy
481*cda5da8dSAndroid Build Coastguard Worker                    # code with a custom `copy_function` may rely on copytree
482*cda5da8dSAndroid Build Coastguard Worker                    # doing the right thing.
483*cda5da8dSAndroid Build Coastguard Worker                    os.symlink(linkto, dstname)
484*cda5da8dSAndroid Build Coastguard Worker                    copystat(srcobj, dstname, follow_symlinks=not symlinks)
485*cda5da8dSAndroid Build Coastguard Worker                else:
486*cda5da8dSAndroid Build Coastguard Worker                    # ignore dangling symlink if the flag is on
487*cda5da8dSAndroid Build Coastguard Worker                    if not os.path.exists(linkto) and ignore_dangling_symlinks:
488*cda5da8dSAndroid Build Coastguard Worker                        continue
489*cda5da8dSAndroid Build Coastguard Worker                    # otherwise let the copy occur. copy2 will raise an error
490*cda5da8dSAndroid Build Coastguard Worker                    if srcentry.is_dir():
491*cda5da8dSAndroid Build Coastguard Worker                        copytree(srcobj, dstname, symlinks, ignore,
492*cda5da8dSAndroid Build Coastguard Worker                                 copy_function, ignore_dangling_symlinks,
493*cda5da8dSAndroid Build Coastguard Worker                                 dirs_exist_ok)
494*cda5da8dSAndroid Build Coastguard Worker                    else:
495*cda5da8dSAndroid Build Coastguard Worker                        copy_function(srcobj, dstname)
496*cda5da8dSAndroid Build Coastguard Worker            elif srcentry.is_dir():
497*cda5da8dSAndroid Build Coastguard Worker                copytree(srcobj, dstname, symlinks, ignore, copy_function,
498*cda5da8dSAndroid Build Coastguard Worker                         ignore_dangling_symlinks, dirs_exist_ok)
499*cda5da8dSAndroid Build Coastguard Worker            else:
500*cda5da8dSAndroid Build Coastguard Worker                # Will raise a SpecialFileError for unsupported file types
501*cda5da8dSAndroid Build Coastguard Worker                copy_function(srcobj, dstname)
502*cda5da8dSAndroid Build Coastguard Worker        # catch the Error from the recursive copytree so that we can
503*cda5da8dSAndroid Build Coastguard Worker        # continue with other files
504*cda5da8dSAndroid Build Coastguard Worker        except Error as err:
505*cda5da8dSAndroid Build Coastguard Worker            errors.extend(err.args[0])
506*cda5da8dSAndroid Build Coastguard Worker        except OSError as why:
507*cda5da8dSAndroid Build Coastguard Worker            errors.append((srcname, dstname, str(why)))
508*cda5da8dSAndroid Build Coastguard Worker    try:
509*cda5da8dSAndroid Build Coastguard Worker        copystat(src, dst)
510*cda5da8dSAndroid Build Coastguard Worker    except OSError as why:
511*cda5da8dSAndroid Build Coastguard Worker        # Copying file access times may fail on Windows
512*cda5da8dSAndroid Build Coastguard Worker        if getattr(why, 'winerror', None) is None:
513*cda5da8dSAndroid Build Coastguard Worker            errors.append((src, dst, str(why)))
514*cda5da8dSAndroid Build Coastguard Worker    if errors:
515*cda5da8dSAndroid Build Coastguard Worker        raise Error(errors)
516*cda5da8dSAndroid Build Coastguard Worker    return dst
517*cda5da8dSAndroid Build Coastguard Worker
518*cda5da8dSAndroid Build Coastguard Workerdef copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
519*cda5da8dSAndroid Build Coastguard Worker             ignore_dangling_symlinks=False, dirs_exist_ok=False):
520*cda5da8dSAndroid Build Coastguard Worker    """Recursively copy a directory tree and return the destination directory.
521*cda5da8dSAndroid Build Coastguard Worker
522*cda5da8dSAndroid Build Coastguard Worker    If exception(s) occur, an Error is raised with a list of reasons.
523*cda5da8dSAndroid Build Coastguard Worker
524*cda5da8dSAndroid Build Coastguard Worker    If the optional symlinks flag is true, symbolic links in the
525*cda5da8dSAndroid Build Coastguard Worker    source tree result in symbolic links in the destination tree; if
526*cda5da8dSAndroid Build Coastguard Worker    it is false, the contents of the files pointed to by symbolic
527*cda5da8dSAndroid Build Coastguard Worker    links are copied. If the file pointed by the symlink doesn't
528*cda5da8dSAndroid Build Coastguard Worker    exist, an exception will be added in the list of errors raised in
529*cda5da8dSAndroid Build Coastguard Worker    an Error exception at the end of the copy process.
530*cda5da8dSAndroid Build Coastguard Worker
531*cda5da8dSAndroid Build Coastguard Worker    You can set the optional ignore_dangling_symlinks flag to true if you
532*cda5da8dSAndroid Build Coastguard Worker    want to silence this exception. Notice that this has no effect on
533*cda5da8dSAndroid Build Coastguard Worker    platforms that don't support os.symlink.
534*cda5da8dSAndroid Build Coastguard Worker
535*cda5da8dSAndroid Build Coastguard Worker    The optional ignore argument is a callable. If given, it
536*cda5da8dSAndroid Build Coastguard Worker    is called with the `src` parameter, which is the directory
537*cda5da8dSAndroid Build Coastguard Worker    being visited by copytree(), and `names` which is the list of
538*cda5da8dSAndroid Build Coastguard Worker    `src` contents, as returned by os.listdir():
539*cda5da8dSAndroid Build Coastguard Worker
540*cda5da8dSAndroid Build Coastguard Worker        callable(src, names) -> ignored_names
541*cda5da8dSAndroid Build Coastguard Worker
542*cda5da8dSAndroid Build Coastguard Worker    Since copytree() is called recursively, the callable will be
543*cda5da8dSAndroid Build Coastguard Worker    called once for each directory that is copied. It returns a
544*cda5da8dSAndroid Build Coastguard Worker    list of names relative to the `src` directory that should
545*cda5da8dSAndroid Build Coastguard Worker    not be copied.
546*cda5da8dSAndroid Build Coastguard Worker
547*cda5da8dSAndroid Build Coastguard Worker    The optional copy_function argument is a callable that will be used
548*cda5da8dSAndroid Build Coastguard Worker    to copy each file. It will be called with the source path and the
549*cda5da8dSAndroid Build Coastguard Worker    destination path as arguments. By default, copy2() is used, but any
550*cda5da8dSAndroid Build Coastguard Worker    function that supports the same signature (like copy()) can be used.
551*cda5da8dSAndroid Build Coastguard Worker
552*cda5da8dSAndroid Build Coastguard Worker    If dirs_exist_ok is false (the default) and `dst` already exists, a
553*cda5da8dSAndroid Build Coastguard Worker    `FileExistsError` is raised. If `dirs_exist_ok` is true, the copying
554*cda5da8dSAndroid Build Coastguard Worker    operation will continue if it encounters existing directories, and files
555*cda5da8dSAndroid Build Coastguard Worker    within the `dst` tree will be overwritten by corresponding files from the
556*cda5da8dSAndroid Build Coastguard Worker    `src` tree.
557*cda5da8dSAndroid Build Coastguard Worker    """
558*cda5da8dSAndroid Build Coastguard Worker    sys.audit("shutil.copytree", src, dst)
559*cda5da8dSAndroid Build Coastguard Worker    with os.scandir(src) as itr:
560*cda5da8dSAndroid Build Coastguard Worker        entries = list(itr)
561*cda5da8dSAndroid Build Coastguard Worker    return _copytree(entries=entries, src=src, dst=dst, symlinks=symlinks,
562*cda5da8dSAndroid Build Coastguard Worker                     ignore=ignore, copy_function=copy_function,
563*cda5da8dSAndroid Build Coastguard Worker                     ignore_dangling_symlinks=ignore_dangling_symlinks,
564*cda5da8dSAndroid Build Coastguard Worker                     dirs_exist_ok=dirs_exist_ok)
565*cda5da8dSAndroid Build Coastguard Worker
566*cda5da8dSAndroid Build Coastguard Workerif hasattr(os.stat_result, 'st_file_attributes'):
567*cda5da8dSAndroid Build Coastguard Worker    # Special handling for directory junctions to make them behave like
568*cda5da8dSAndroid Build Coastguard Worker    # symlinks for shutil.rmtree, since in general they do not appear as
569*cda5da8dSAndroid Build Coastguard Worker    # regular links.
570*cda5da8dSAndroid Build Coastguard Worker    def _rmtree_isdir(entry):
571*cda5da8dSAndroid Build Coastguard Worker        try:
572*cda5da8dSAndroid Build Coastguard Worker            st = entry.stat(follow_symlinks=False)
573*cda5da8dSAndroid Build Coastguard Worker            return (stat.S_ISDIR(st.st_mode) and not
574*cda5da8dSAndroid Build Coastguard Worker                (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT
575*cda5da8dSAndroid Build Coastguard Worker                 and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT))
576*cda5da8dSAndroid Build Coastguard Worker        except OSError:
577*cda5da8dSAndroid Build Coastguard Worker            return False
578*cda5da8dSAndroid Build Coastguard Worker
579*cda5da8dSAndroid Build Coastguard Worker    def _rmtree_islink(path):
580*cda5da8dSAndroid Build Coastguard Worker        try:
581*cda5da8dSAndroid Build Coastguard Worker            st = os.lstat(path)
582*cda5da8dSAndroid Build Coastguard Worker            return (stat.S_ISLNK(st.st_mode) or
583*cda5da8dSAndroid Build Coastguard Worker                (st.st_file_attributes & stat.FILE_ATTRIBUTE_REPARSE_POINT
584*cda5da8dSAndroid Build Coastguard Worker                 and st.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT))
585*cda5da8dSAndroid Build Coastguard Worker        except OSError:
586*cda5da8dSAndroid Build Coastguard Worker            return False
587*cda5da8dSAndroid Build Coastguard Workerelse:
588*cda5da8dSAndroid Build Coastguard Worker    def _rmtree_isdir(entry):
589*cda5da8dSAndroid Build Coastguard Worker        try:
590*cda5da8dSAndroid Build Coastguard Worker            return entry.is_dir(follow_symlinks=False)
591*cda5da8dSAndroid Build Coastguard Worker        except OSError:
592*cda5da8dSAndroid Build Coastguard Worker            return False
593*cda5da8dSAndroid Build Coastguard Worker
594*cda5da8dSAndroid Build Coastguard Worker    def _rmtree_islink(path):
595*cda5da8dSAndroid Build Coastguard Worker        return os.path.islink(path)
596*cda5da8dSAndroid Build Coastguard Worker
597*cda5da8dSAndroid Build Coastguard Worker# version vulnerable to race conditions
598*cda5da8dSAndroid Build Coastguard Workerdef _rmtree_unsafe(path, onerror):
599*cda5da8dSAndroid Build Coastguard Worker    try:
600*cda5da8dSAndroid Build Coastguard Worker        with os.scandir(path) as scandir_it:
601*cda5da8dSAndroid Build Coastguard Worker            entries = list(scandir_it)
602*cda5da8dSAndroid Build Coastguard Worker    except OSError:
603*cda5da8dSAndroid Build Coastguard Worker        onerror(os.scandir, path, sys.exc_info())
604*cda5da8dSAndroid Build Coastguard Worker        entries = []
605*cda5da8dSAndroid Build Coastguard Worker    for entry in entries:
606*cda5da8dSAndroid Build Coastguard Worker        fullname = entry.path
607*cda5da8dSAndroid Build Coastguard Worker        if _rmtree_isdir(entry):
608*cda5da8dSAndroid Build Coastguard Worker            try:
609*cda5da8dSAndroid Build Coastguard Worker                if entry.is_symlink():
610*cda5da8dSAndroid Build Coastguard Worker                    # This can only happen if someone replaces
611*cda5da8dSAndroid Build Coastguard Worker                    # a directory with a symlink after the call to
612*cda5da8dSAndroid Build Coastguard Worker                    # os.scandir or entry.is_dir above.
613*cda5da8dSAndroid Build Coastguard Worker                    raise OSError("Cannot call rmtree on a symbolic link")
614*cda5da8dSAndroid Build Coastguard Worker            except OSError:
615*cda5da8dSAndroid Build Coastguard Worker                onerror(os.path.islink, fullname, sys.exc_info())
616*cda5da8dSAndroid Build Coastguard Worker                continue
617*cda5da8dSAndroid Build Coastguard Worker            _rmtree_unsafe(fullname, onerror)
618*cda5da8dSAndroid Build Coastguard Worker        else:
619*cda5da8dSAndroid Build Coastguard Worker            try:
620*cda5da8dSAndroid Build Coastguard Worker                os.unlink(fullname)
621*cda5da8dSAndroid Build Coastguard Worker            except OSError:
622*cda5da8dSAndroid Build Coastguard Worker                onerror(os.unlink, fullname, sys.exc_info())
623*cda5da8dSAndroid Build Coastguard Worker    try:
624*cda5da8dSAndroid Build Coastguard Worker        os.rmdir(path)
625*cda5da8dSAndroid Build Coastguard Worker    except OSError:
626*cda5da8dSAndroid Build Coastguard Worker        onerror(os.rmdir, path, sys.exc_info())
627*cda5da8dSAndroid Build Coastguard Worker
628*cda5da8dSAndroid Build Coastguard Worker# Version using fd-based APIs to protect against races
629*cda5da8dSAndroid Build Coastguard Workerdef _rmtree_safe_fd(topfd, path, onerror):
630*cda5da8dSAndroid Build Coastguard Worker    try:
631*cda5da8dSAndroid Build Coastguard Worker        with os.scandir(topfd) as scandir_it:
632*cda5da8dSAndroid Build Coastguard Worker            entries = list(scandir_it)
633*cda5da8dSAndroid Build Coastguard Worker    except OSError as err:
634*cda5da8dSAndroid Build Coastguard Worker        err.filename = path
635*cda5da8dSAndroid Build Coastguard Worker        onerror(os.scandir, path, sys.exc_info())
636*cda5da8dSAndroid Build Coastguard Worker        return
637*cda5da8dSAndroid Build Coastguard Worker    for entry in entries:
638*cda5da8dSAndroid Build Coastguard Worker        fullname = os.path.join(path, entry.name)
639*cda5da8dSAndroid Build Coastguard Worker        try:
640*cda5da8dSAndroid Build Coastguard Worker            is_dir = entry.is_dir(follow_symlinks=False)
641*cda5da8dSAndroid Build Coastguard Worker        except OSError:
642*cda5da8dSAndroid Build Coastguard Worker            is_dir = False
643*cda5da8dSAndroid Build Coastguard Worker        else:
644*cda5da8dSAndroid Build Coastguard Worker            if is_dir:
645*cda5da8dSAndroid Build Coastguard Worker                try:
646*cda5da8dSAndroid Build Coastguard Worker                    orig_st = entry.stat(follow_symlinks=False)
647*cda5da8dSAndroid Build Coastguard Worker                    is_dir = stat.S_ISDIR(orig_st.st_mode)
648*cda5da8dSAndroid Build Coastguard Worker                except OSError:
649*cda5da8dSAndroid Build Coastguard Worker                    onerror(os.lstat, fullname, sys.exc_info())
650*cda5da8dSAndroid Build Coastguard Worker                    continue
651*cda5da8dSAndroid Build Coastguard Worker        if is_dir:
652*cda5da8dSAndroid Build Coastguard Worker            try:
653*cda5da8dSAndroid Build Coastguard Worker                dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd)
654*cda5da8dSAndroid Build Coastguard Worker                dirfd_closed = False
655*cda5da8dSAndroid Build Coastguard Worker            except OSError:
656*cda5da8dSAndroid Build Coastguard Worker                onerror(os.open, fullname, sys.exc_info())
657*cda5da8dSAndroid Build Coastguard Worker            else:
658*cda5da8dSAndroid Build Coastguard Worker                try:
659*cda5da8dSAndroid Build Coastguard Worker                    if os.path.samestat(orig_st, os.fstat(dirfd)):
660*cda5da8dSAndroid Build Coastguard Worker                        _rmtree_safe_fd(dirfd, fullname, onerror)
661*cda5da8dSAndroid Build Coastguard Worker                        try:
662*cda5da8dSAndroid Build Coastguard Worker                            os.close(dirfd)
663*cda5da8dSAndroid Build Coastguard Worker                            dirfd_closed = True
664*cda5da8dSAndroid Build Coastguard Worker                            os.rmdir(entry.name, dir_fd=topfd)
665*cda5da8dSAndroid Build Coastguard Worker                        except OSError:
666*cda5da8dSAndroid Build Coastguard Worker                            onerror(os.rmdir, fullname, sys.exc_info())
667*cda5da8dSAndroid Build Coastguard Worker                    else:
668*cda5da8dSAndroid Build Coastguard Worker                        try:
669*cda5da8dSAndroid Build Coastguard Worker                            # This can only happen if someone replaces
670*cda5da8dSAndroid Build Coastguard Worker                            # a directory with a symlink after the call to
671*cda5da8dSAndroid Build Coastguard Worker                            # os.scandir or stat.S_ISDIR above.
672*cda5da8dSAndroid Build Coastguard Worker                            raise OSError("Cannot call rmtree on a symbolic "
673*cda5da8dSAndroid Build Coastguard Worker                                          "link")
674*cda5da8dSAndroid Build Coastguard Worker                        except OSError:
675*cda5da8dSAndroid Build Coastguard Worker                            onerror(os.path.islink, fullname, sys.exc_info())
676*cda5da8dSAndroid Build Coastguard Worker                finally:
677*cda5da8dSAndroid Build Coastguard Worker                    if not dirfd_closed:
678*cda5da8dSAndroid Build Coastguard Worker                        os.close(dirfd)
679*cda5da8dSAndroid Build Coastguard Worker        else:
680*cda5da8dSAndroid Build Coastguard Worker            try:
681*cda5da8dSAndroid Build Coastguard Worker                os.unlink(entry.name, dir_fd=topfd)
682*cda5da8dSAndroid Build Coastguard Worker            except OSError:
683*cda5da8dSAndroid Build Coastguard Worker                onerror(os.unlink, fullname, sys.exc_info())
684*cda5da8dSAndroid Build Coastguard Worker
685*cda5da8dSAndroid Build Coastguard Worker_use_fd_functions = ({os.open, os.stat, os.unlink, os.rmdir} <=
686*cda5da8dSAndroid Build Coastguard Worker                     os.supports_dir_fd and
687*cda5da8dSAndroid Build Coastguard Worker                     os.scandir in os.supports_fd and
688*cda5da8dSAndroid Build Coastguard Worker                     os.stat in os.supports_follow_symlinks)
689*cda5da8dSAndroid Build Coastguard Worker
690*cda5da8dSAndroid Build Coastguard Workerdef rmtree(path, ignore_errors=False, onerror=None, *, dir_fd=None):
691*cda5da8dSAndroid Build Coastguard Worker    """Recursively delete a directory tree.
692*cda5da8dSAndroid Build Coastguard Worker
693*cda5da8dSAndroid Build Coastguard Worker    If dir_fd is not None, it should be a file descriptor open to a directory;
694*cda5da8dSAndroid Build Coastguard Worker    path will then be relative to that directory.
695*cda5da8dSAndroid Build Coastguard Worker    dir_fd may not be implemented on your platform.
696*cda5da8dSAndroid Build Coastguard Worker    If it is unavailable, using it will raise a NotImplementedError.
697*cda5da8dSAndroid Build Coastguard Worker
698*cda5da8dSAndroid Build Coastguard Worker    If ignore_errors is set, errors are ignored; otherwise, if onerror
699*cda5da8dSAndroid Build Coastguard Worker    is set, it is called to handle the error with arguments (func,
700*cda5da8dSAndroid Build Coastguard Worker    path, exc_info) where func is platform and implementation dependent;
701*cda5da8dSAndroid Build Coastguard Worker    path is the argument to that function that caused it to fail; and
702*cda5da8dSAndroid Build Coastguard Worker    exc_info is a tuple returned by sys.exc_info().  If ignore_errors
703*cda5da8dSAndroid Build Coastguard Worker    is false and onerror is None, an exception is raised.
704*cda5da8dSAndroid Build Coastguard Worker
705*cda5da8dSAndroid Build Coastguard Worker    """
706*cda5da8dSAndroid Build Coastguard Worker    sys.audit("shutil.rmtree", path, dir_fd)
707*cda5da8dSAndroid Build Coastguard Worker    if ignore_errors:
708*cda5da8dSAndroid Build Coastguard Worker        def onerror(*args):
709*cda5da8dSAndroid Build Coastguard Worker            pass
710*cda5da8dSAndroid Build Coastguard Worker    elif onerror is None:
711*cda5da8dSAndroid Build Coastguard Worker        def onerror(*args):
712*cda5da8dSAndroid Build Coastguard Worker            raise
713*cda5da8dSAndroid Build Coastguard Worker    if _use_fd_functions:
714*cda5da8dSAndroid Build Coastguard Worker        # While the unsafe rmtree works fine on bytes, the fd based does not.
715*cda5da8dSAndroid Build Coastguard Worker        if isinstance(path, bytes):
716*cda5da8dSAndroid Build Coastguard Worker            path = os.fsdecode(path)
717*cda5da8dSAndroid Build Coastguard Worker        # Note: To guard against symlink races, we use the standard
718*cda5da8dSAndroid Build Coastguard Worker        # lstat()/open()/fstat() trick.
719*cda5da8dSAndroid Build Coastguard Worker        try:
720*cda5da8dSAndroid Build Coastguard Worker            orig_st = os.lstat(path, dir_fd=dir_fd)
721*cda5da8dSAndroid Build Coastguard Worker        except Exception:
722*cda5da8dSAndroid Build Coastguard Worker            onerror(os.lstat, path, sys.exc_info())
723*cda5da8dSAndroid Build Coastguard Worker            return
724*cda5da8dSAndroid Build Coastguard Worker        try:
725*cda5da8dSAndroid Build Coastguard Worker            fd = os.open(path, os.O_RDONLY, dir_fd=dir_fd)
726*cda5da8dSAndroid Build Coastguard Worker            fd_closed = False
727*cda5da8dSAndroid Build Coastguard Worker        except Exception:
728*cda5da8dSAndroid Build Coastguard Worker            onerror(os.open, path, sys.exc_info())
729*cda5da8dSAndroid Build Coastguard Worker            return
730*cda5da8dSAndroid Build Coastguard Worker        try:
731*cda5da8dSAndroid Build Coastguard Worker            if os.path.samestat(orig_st, os.fstat(fd)):
732*cda5da8dSAndroid Build Coastguard Worker                _rmtree_safe_fd(fd, path, onerror)
733*cda5da8dSAndroid Build Coastguard Worker                try:
734*cda5da8dSAndroid Build Coastguard Worker                    os.close(fd)
735*cda5da8dSAndroid Build Coastguard Worker                    fd_closed = True
736*cda5da8dSAndroid Build Coastguard Worker                    os.rmdir(path, dir_fd=dir_fd)
737*cda5da8dSAndroid Build Coastguard Worker                except OSError:
738*cda5da8dSAndroid Build Coastguard Worker                    onerror(os.rmdir, path, sys.exc_info())
739*cda5da8dSAndroid Build Coastguard Worker            else:
740*cda5da8dSAndroid Build Coastguard Worker                try:
741*cda5da8dSAndroid Build Coastguard Worker                    # symlinks to directories are forbidden, see bug #1669
742*cda5da8dSAndroid Build Coastguard Worker                    raise OSError("Cannot call rmtree on a symbolic link")
743*cda5da8dSAndroid Build Coastguard Worker                except OSError:
744*cda5da8dSAndroid Build Coastguard Worker                    onerror(os.path.islink, path, sys.exc_info())
745*cda5da8dSAndroid Build Coastguard Worker        finally:
746*cda5da8dSAndroid Build Coastguard Worker            if not fd_closed:
747*cda5da8dSAndroid Build Coastguard Worker                os.close(fd)
748*cda5da8dSAndroid Build Coastguard Worker    else:
749*cda5da8dSAndroid Build Coastguard Worker        if dir_fd is not None:
750*cda5da8dSAndroid Build Coastguard Worker            raise NotImplementedError("dir_fd unavailable on this platform")
751*cda5da8dSAndroid Build Coastguard Worker        try:
752*cda5da8dSAndroid Build Coastguard Worker            if _rmtree_islink(path):
753*cda5da8dSAndroid Build Coastguard Worker                # symlinks to directories are forbidden, see bug #1669
754*cda5da8dSAndroid Build Coastguard Worker                raise OSError("Cannot call rmtree on a symbolic link")
755*cda5da8dSAndroid Build Coastguard Worker        except OSError:
756*cda5da8dSAndroid Build Coastguard Worker            onerror(os.path.islink, path, sys.exc_info())
757*cda5da8dSAndroid Build Coastguard Worker            # can't continue even if onerror hook returns
758*cda5da8dSAndroid Build Coastguard Worker            return
759*cda5da8dSAndroid Build Coastguard Worker        return _rmtree_unsafe(path, onerror)
760*cda5da8dSAndroid Build Coastguard Worker
761*cda5da8dSAndroid Build Coastguard Worker# Allow introspection of whether or not the hardening against symlink
762*cda5da8dSAndroid Build Coastguard Worker# attacks is supported on the current platform
763*cda5da8dSAndroid Build Coastguard Workerrmtree.avoids_symlink_attacks = _use_fd_functions
764*cda5da8dSAndroid Build Coastguard Worker
765*cda5da8dSAndroid Build Coastguard Workerdef _basename(path):
766*cda5da8dSAndroid Build Coastguard Worker    """A basename() variant which first strips the trailing slash, if present.
767*cda5da8dSAndroid Build Coastguard Worker    Thus we always get the last component of the path, even for directories.
768*cda5da8dSAndroid Build Coastguard Worker
769*cda5da8dSAndroid Build Coastguard Worker    path: Union[PathLike, str]
770*cda5da8dSAndroid Build Coastguard Worker
771*cda5da8dSAndroid Build Coastguard Worker    e.g.
772*cda5da8dSAndroid Build Coastguard Worker    >>> os.path.basename('/bar/foo')
773*cda5da8dSAndroid Build Coastguard Worker    'foo'
774*cda5da8dSAndroid Build Coastguard Worker    >>> os.path.basename('/bar/foo/')
775*cda5da8dSAndroid Build Coastguard Worker    ''
776*cda5da8dSAndroid Build Coastguard Worker    >>> _basename('/bar/foo/')
777*cda5da8dSAndroid Build Coastguard Worker    'foo'
778*cda5da8dSAndroid Build Coastguard Worker    """
779*cda5da8dSAndroid Build Coastguard Worker    path = os.fspath(path)
780*cda5da8dSAndroid Build Coastguard Worker    sep = os.path.sep + (os.path.altsep or '')
781*cda5da8dSAndroid Build Coastguard Worker    return os.path.basename(path.rstrip(sep))
782*cda5da8dSAndroid Build Coastguard Worker
783*cda5da8dSAndroid Build Coastguard Workerdef move(src, dst, copy_function=copy2):
784*cda5da8dSAndroid Build Coastguard Worker    """Recursively move a file or directory to another location. This is
785*cda5da8dSAndroid Build Coastguard Worker    similar to the Unix "mv" command. Return the file or directory's
786*cda5da8dSAndroid Build Coastguard Worker    destination.
787*cda5da8dSAndroid Build Coastguard Worker
788*cda5da8dSAndroid Build Coastguard Worker    If the destination is a directory or a symlink to a directory, the source
789*cda5da8dSAndroid Build Coastguard Worker    is moved inside the directory. The destination path must not already
790*cda5da8dSAndroid Build Coastguard Worker    exist.
791*cda5da8dSAndroid Build Coastguard Worker
792*cda5da8dSAndroid Build Coastguard Worker    If the destination already exists but is not a directory, it may be
793*cda5da8dSAndroid Build Coastguard Worker    overwritten depending on os.rename() semantics.
794*cda5da8dSAndroid Build Coastguard Worker
795*cda5da8dSAndroid Build Coastguard Worker    If the destination is on our current filesystem, then rename() is used.
796*cda5da8dSAndroid Build Coastguard Worker    Otherwise, src is copied to the destination and then removed. Symlinks are
797*cda5da8dSAndroid Build Coastguard Worker    recreated under the new name if os.rename() fails because of cross
798*cda5da8dSAndroid Build Coastguard Worker    filesystem renames.
799*cda5da8dSAndroid Build Coastguard Worker
800*cda5da8dSAndroid Build Coastguard Worker    The optional `copy_function` argument is a callable that will be used
801*cda5da8dSAndroid Build Coastguard Worker    to copy the source or it will be delegated to `copytree`.
802*cda5da8dSAndroid Build Coastguard Worker    By default, copy2() is used, but any function that supports the same
803*cda5da8dSAndroid Build Coastguard Worker    signature (like copy()) can be used.
804*cda5da8dSAndroid Build Coastguard Worker
805*cda5da8dSAndroid Build Coastguard Worker    A lot more could be done here...  A look at a mv.c shows a lot of
806*cda5da8dSAndroid Build Coastguard Worker    the issues this implementation glosses over.
807*cda5da8dSAndroid Build Coastguard Worker
808*cda5da8dSAndroid Build Coastguard Worker    """
809*cda5da8dSAndroid Build Coastguard Worker    sys.audit("shutil.move", src, dst)
810*cda5da8dSAndroid Build Coastguard Worker    real_dst = dst
811*cda5da8dSAndroid Build Coastguard Worker    if os.path.isdir(dst):
812*cda5da8dSAndroid Build Coastguard Worker        if _samefile(src, dst):
813*cda5da8dSAndroid Build Coastguard Worker            # We might be on a case insensitive filesystem,
814*cda5da8dSAndroid Build Coastguard Worker            # perform the rename anyway.
815*cda5da8dSAndroid Build Coastguard Worker            os.rename(src, dst)
816*cda5da8dSAndroid Build Coastguard Worker            return
817*cda5da8dSAndroid Build Coastguard Worker
818*cda5da8dSAndroid Build Coastguard Worker        # Using _basename instead of os.path.basename is important, as we must
819*cda5da8dSAndroid Build Coastguard Worker        # ignore any trailing slash to avoid the basename returning ''
820*cda5da8dSAndroid Build Coastguard Worker        real_dst = os.path.join(dst, _basename(src))
821*cda5da8dSAndroid Build Coastguard Worker
822*cda5da8dSAndroid Build Coastguard Worker        if os.path.exists(real_dst):
823*cda5da8dSAndroid Build Coastguard Worker            raise Error("Destination path '%s' already exists" % real_dst)
824*cda5da8dSAndroid Build Coastguard Worker    try:
825*cda5da8dSAndroid Build Coastguard Worker        os.rename(src, real_dst)
826*cda5da8dSAndroid Build Coastguard Worker    except OSError:
827*cda5da8dSAndroid Build Coastguard Worker        if os.path.islink(src):
828*cda5da8dSAndroid Build Coastguard Worker            linkto = os.readlink(src)
829*cda5da8dSAndroid Build Coastguard Worker            os.symlink(linkto, real_dst)
830*cda5da8dSAndroid Build Coastguard Worker            os.unlink(src)
831*cda5da8dSAndroid Build Coastguard Worker        elif os.path.isdir(src):
832*cda5da8dSAndroid Build Coastguard Worker            if _destinsrc(src, dst):
833*cda5da8dSAndroid Build Coastguard Worker                raise Error("Cannot move a directory '%s' into itself"
834*cda5da8dSAndroid Build Coastguard Worker                            " '%s'." % (src, dst))
835*cda5da8dSAndroid Build Coastguard Worker            if (_is_immutable(src)
836*cda5da8dSAndroid Build Coastguard Worker                    or (not os.access(src, os.W_OK) and os.listdir(src)
837*cda5da8dSAndroid Build Coastguard Worker                        and sys.platform == 'darwin')):
838*cda5da8dSAndroid Build Coastguard Worker                raise PermissionError("Cannot move the non-empty directory "
839*cda5da8dSAndroid Build Coastguard Worker                                      "'%s': Lacking write permission to '%s'."
840*cda5da8dSAndroid Build Coastguard Worker                                      % (src, src))
841*cda5da8dSAndroid Build Coastguard Worker            copytree(src, real_dst, copy_function=copy_function,
842*cda5da8dSAndroid Build Coastguard Worker                     symlinks=True)
843*cda5da8dSAndroid Build Coastguard Worker            rmtree(src)
844*cda5da8dSAndroid Build Coastguard Worker        else:
845*cda5da8dSAndroid Build Coastguard Worker            copy_function(src, real_dst)
846*cda5da8dSAndroid Build Coastguard Worker            os.unlink(src)
847*cda5da8dSAndroid Build Coastguard Worker    return real_dst
848*cda5da8dSAndroid Build Coastguard Worker
849*cda5da8dSAndroid Build Coastguard Workerdef _destinsrc(src, dst):
850*cda5da8dSAndroid Build Coastguard Worker    src = os.path.abspath(src)
851*cda5da8dSAndroid Build Coastguard Worker    dst = os.path.abspath(dst)
852*cda5da8dSAndroid Build Coastguard Worker    if not src.endswith(os.path.sep):
853*cda5da8dSAndroid Build Coastguard Worker        src += os.path.sep
854*cda5da8dSAndroid Build Coastguard Worker    if not dst.endswith(os.path.sep):
855*cda5da8dSAndroid Build Coastguard Worker        dst += os.path.sep
856*cda5da8dSAndroid Build Coastguard Worker    return dst.startswith(src)
857*cda5da8dSAndroid Build Coastguard Worker
858*cda5da8dSAndroid Build Coastguard Workerdef _is_immutable(src):
859*cda5da8dSAndroid Build Coastguard Worker    st = _stat(src)
860*cda5da8dSAndroid Build Coastguard Worker    immutable_states = [stat.UF_IMMUTABLE, stat.SF_IMMUTABLE]
861*cda5da8dSAndroid Build Coastguard Worker    return hasattr(st, 'st_flags') and st.st_flags in immutable_states
862*cda5da8dSAndroid Build Coastguard Worker
863*cda5da8dSAndroid Build Coastguard Workerdef _get_gid(name):
864*cda5da8dSAndroid Build Coastguard Worker    """Returns a gid, given a group name."""
865*cda5da8dSAndroid Build Coastguard Worker    if name is None:
866*cda5da8dSAndroid Build Coastguard Worker        return None
867*cda5da8dSAndroid Build Coastguard Worker
868*cda5da8dSAndroid Build Coastguard Worker    try:
869*cda5da8dSAndroid Build Coastguard Worker        from grp import getgrnam
870*cda5da8dSAndroid Build Coastguard Worker    except ImportError:
871*cda5da8dSAndroid Build Coastguard Worker        return None
872*cda5da8dSAndroid Build Coastguard Worker
873*cda5da8dSAndroid Build Coastguard Worker    try:
874*cda5da8dSAndroid Build Coastguard Worker        result = getgrnam(name)
875*cda5da8dSAndroid Build Coastguard Worker    except KeyError:
876*cda5da8dSAndroid Build Coastguard Worker        result = None
877*cda5da8dSAndroid Build Coastguard Worker    if result is not None:
878*cda5da8dSAndroid Build Coastguard Worker        return result[2]
879*cda5da8dSAndroid Build Coastguard Worker    return None
880*cda5da8dSAndroid Build Coastguard Worker
881*cda5da8dSAndroid Build Coastguard Workerdef _get_uid(name):
882*cda5da8dSAndroid Build Coastguard Worker    """Returns an uid, given a user name."""
883*cda5da8dSAndroid Build Coastguard Worker    if name is None:
884*cda5da8dSAndroid Build Coastguard Worker        return None
885*cda5da8dSAndroid Build Coastguard Worker
886*cda5da8dSAndroid Build Coastguard Worker    try:
887*cda5da8dSAndroid Build Coastguard Worker        from pwd import getpwnam
888*cda5da8dSAndroid Build Coastguard Worker    except ImportError:
889*cda5da8dSAndroid Build Coastguard Worker        return None
890*cda5da8dSAndroid Build Coastguard Worker
891*cda5da8dSAndroid Build Coastguard Worker    try:
892*cda5da8dSAndroid Build Coastguard Worker        result = getpwnam(name)
893*cda5da8dSAndroid Build Coastguard Worker    except KeyError:
894*cda5da8dSAndroid Build Coastguard Worker        result = None
895*cda5da8dSAndroid Build Coastguard Worker    if result is not None:
896*cda5da8dSAndroid Build Coastguard Worker        return result[2]
897*cda5da8dSAndroid Build Coastguard Worker    return None
898*cda5da8dSAndroid Build Coastguard Worker
899*cda5da8dSAndroid Build Coastguard Workerdef _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
900*cda5da8dSAndroid Build Coastguard Worker                  owner=None, group=None, logger=None, root_dir=None):
901*cda5da8dSAndroid Build Coastguard Worker    """Create a (possibly compressed) tar file from all the files under
902*cda5da8dSAndroid Build Coastguard Worker    'base_dir'.
903*cda5da8dSAndroid Build Coastguard Worker
904*cda5da8dSAndroid Build Coastguard Worker    'compress' must be "gzip" (the default), "bzip2", "xz", or None.
905*cda5da8dSAndroid Build Coastguard Worker
906*cda5da8dSAndroid Build Coastguard Worker    'owner' and 'group' can be used to define an owner and a group for the
907*cda5da8dSAndroid Build Coastguard Worker    archive that is being built. If not provided, the current owner and group
908*cda5da8dSAndroid Build Coastguard Worker    will be used.
909*cda5da8dSAndroid Build Coastguard Worker
910*cda5da8dSAndroid Build Coastguard Worker    The output tar file will be named 'base_name' +  ".tar", possibly plus
911*cda5da8dSAndroid Build Coastguard Worker    the appropriate compression extension (".gz", ".bz2", or ".xz").
912*cda5da8dSAndroid Build Coastguard Worker
913*cda5da8dSAndroid Build Coastguard Worker    Returns the output filename.
914*cda5da8dSAndroid Build Coastguard Worker    """
915*cda5da8dSAndroid Build Coastguard Worker    if compress is None:
916*cda5da8dSAndroid Build Coastguard Worker        tar_compression = ''
917*cda5da8dSAndroid Build Coastguard Worker    elif _ZLIB_SUPPORTED and compress == 'gzip':
918*cda5da8dSAndroid Build Coastguard Worker        tar_compression = 'gz'
919*cda5da8dSAndroid Build Coastguard Worker    elif _BZ2_SUPPORTED and compress == 'bzip2':
920*cda5da8dSAndroid Build Coastguard Worker        tar_compression = 'bz2'
921*cda5da8dSAndroid Build Coastguard Worker    elif _LZMA_SUPPORTED and compress == 'xz':
922*cda5da8dSAndroid Build Coastguard Worker        tar_compression = 'xz'
923*cda5da8dSAndroid Build Coastguard Worker    else:
924*cda5da8dSAndroid Build Coastguard Worker        raise ValueError("bad value for 'compress', or compression format not "
925*cda5da8dSAndroid Build Coastguard Worker                         "supported : {0}".format(compress))
926*cda5da8dSAndroid Build Coastguard Worker
927*cda5da8dSAndroid Build Coastguard Worker    import tarfile  # late import for breaking circular dependency
928*cda5da8dSAndroid Build Coastguard Worker
929*cda5da8dSAndroid Build Coastguard Worker    compress_ext = '.' + tar_compression if compress else ''
930*cda5da8dSAndroid Build Coastguard Worker    archive_name = base_name + '.tar' + compress_ext
931*cda5da8dSAndroid Build Coastguard Worker    archive_dir = os.path.dirname(archive_name)
932*cda5da8dSAndroid Build Coastguard Worker
933*cda5da8dSAndroid Build Coastguard Worker    if archive_dir and not os.path.exists(archive_dir):
934*cda5da8dSAndroid Build Coastguard Worker        if logger is not None:
935*cda5da8dSAndroid Build Coastguard Worker            logger.info("creating %s", archive_dir)
936*cda5da8dSAndroid Build Coastguard Worker        if not dry_run:
937*cda5da8dSAndroid Build Coastguard Worker            os.makedirs(archive_dir)
938*cda5da8dSAndroid Build Coastguard Worker
939*cda5da8dSAndroid Build Coastguard Worker    # creating the tarball
940*cda5da8dSAndroid Build Coastguard Worker    if logger is not None:
941*cda5da8dSAndroid Build Coastguard Worker        logger.info('Creating tar archive')
942*cda5da8dSAndroid Build Coastguard Worker
943*cda5da8dSAndroid Build Coastguard Worker    uid = _get_uid(owner)
944*cda5da8dSAndroid Build Coastguard Worker    gid = _get_gid(group)
945*cda5da8dSAndroid Build Coastguard Worker
946*cda5da8dSAndroid Build Coastguard Worker    def _set_uid_gid(tarinfo):
947*cda5da8dSAndroid Build Coastguard Worker        if gid is not None:
948*cda5da8dSAndroid Build Coastguard Worker            tarinfo.gid = gid
949*cda5da8dSAndroid Build Coastguard Worker            tarinfo.gname = group
950*cda5da8dSAndroid Build Coastguard Worker        if uid is not None:
951*cda5da8dSAndroid Build Coastguard Worker            tarinfo.uid = uid
952*cda5da8dSAndroid Build Coastguard Worker            tarinfo.uname = owner
953*cda5da8dSAndroid Build Coastguard Worker        return tarinfo
954*cda5da8dSAndroid Build Coastguard Worker
955*cda5da8dSAndroid Build Coastguard Worker    if not dry_run:
956*cda5da8dSAndroid Build Coastguard Worker        tar = tarfile.open(archive_name, 'w|%s' % tar_compression)
957*cda5da8dSAndroid Build Coastguard Worker        arcname = base_dir
958*cda5da8dSAndroid Build Coastguard Worker        if root_dir is not None:
959*cda5da8dSAndroid Build Coastguard Worker            base_dir = os.path.join(root_dir, base_dir)
960*cda5da8dSAndroid Build Coastguard Worker        try:
961*cda5da8dSAndroid Build Coastguard Worker            tar.add(base_dir, arcname, filter=_set_uid_gid)
962*cda5da8dSAndroid Build Coastguard Worker        finally:
963*cda5da8dSAndroid Build Coastguard Worker            tar.close()
964*cda5da8dSAndroid Build Coastguard Worker
965*cda5da8dSAndroid Build Coastguard Worker    if root_dir is not None:
966*cda5da8dSAndroid Build Coastguard Worker        archive_name = os.path.abspath(archive_name)
967*cda5da8dSAndroid Build Coastguard Worker    return archive_name
968*cda5da8dSAndroid Build Coastguard Worker
969*cda5da8dSAndroid Build Coastguard Workerdef _make_zipfile(base_name, base_dir, verbose=0, dry_run=0,
970*cda5da8dSAndroid Build Coastguard Worker                  logger=None, owner=None, group=None, root_dir=None):
971*cda5da8dSAndroid Build Coastguard Worker    """Create a zip file from all the files under 'base_dir'.
972*cda5da8dSAndroid Build Coastguard Worker
973*cda5da8dSAndroid Build Coastguard Worker    The output zip file will be named 'base_name' + ".zip".  Returns the
974*cda5da8dSAndroid Build Coastguard Worker    name of the output zip file.
975*cda5da8dSAndroid Build Coastguard Worker    """
976*cda5da8dSAndroid Build Coastguard Worker    import zipfile  # late import for breaking circular dependency
977*cda5da8dSAndroid Build Coastguard Worker
978*cda5da8dSAndroid Build Coastguard Worker    zip_filename = base_name + ".zip"
979*cda5da8dSAndroid Build Coastguard Worker    archive_dir = os.path.dirname(base_name)
980*cda5da8dSAndroid Build Coastguard Worker
981*cda5da8dSAndroid Build Coastguard Worker    if archive_dir and not os.path.exists(archive_dir):
982*cda5da8dSAndroid Build Coastguard Worker        if logger is not None:
983*cda5da8dSAndroid Build Coastguard Worker            logger.info("creating %s", archive_dir)
984*cda5da8dSAndroid Build Coastguard Worker        if not dry_run:
985*cda5da8dSAndroid Build Coastguard Worker            os.makedirs(archive_dir)
986*cda5da8dSAndroid Build Coastguard Worker
987*cda5da8dSAndroid Build Coastguard Worker    if logger is not None:
988*cda5da8dSAndroid Build Coastguard Worker        logger.info("creating '%s' and adding '%s' to it",
989*cda5da8dSAndroid Build Coastguard Worker                    zip_filename, base_dir)
990*cda5da8dSAndroid Build Coastguard Worker
991*cda5da8dSAndroid Build Coastguard Worker    if not dry_run:
992*cda5da8dSAndroid Build Coastguard Worker        with zipfile.ZipFile(zip_filename, "w",
993*cda5da8dSAndroid Build Coastguard Worker                             compression=zipfile.ZIP_DEFLATED) as zf:
994*cda5da8dSAndroid Build Coastguard Worker            arcname = os.path.normpath(base_dir)
995*cda5da8dSAndroid Build Coastguard Worker            if root_dir is not None:
996*cda5da8dSAndroid Build Coastguard Worker                base_dir = os.path.join(root_dir, base_dir)
997*cda5da8dSAndroid Build Coastguard Worker            base_dir = os.path.normpath(base_dir)
998*cda5da8dSAndroid Build Coastguard Worker            if arcname != os.curdir:
999*cda5da8dSAndroid Build Coastguard Worker                zf.write(base_dir, arcname)
1000*cda5da8dSAndroid Build Coastguard Worker                if logger is not None:
1001*cda5da8dSAndroid Build Coastguard Worker                    logger.info("adding '%s'", base_dir)
1002*cda5da8dSAndroid Build Coastguard Worker            for dirpath, dirnames, filenames in os.walk(base_dir):
1003*cda5da8dSAndroid Build Coastguard Worker                arcdirpath = dirpath
1004*cda5da8dSAndroid Build Coastguard Worker                if root_dir is not None:
1005*cda5da8dSAndroid Build Coastguard Worker                    arcdirpath = os.path.relpath(arcdirpath, root_dir)
1006*cda5da8dSAndroid Build Coastguard Worker                arcdirpath = os.path.normpath(arcdirpath)
1007*cda5da8dSAndroid Build Coastguard Worker                for name in sorted(dirnames):
1008*cda5da8dSAndroid Build Coastguard Worker                    path = os.path.join(dirpath, name)
1009*cda5da8dSAndroid Build Coastguard Worker                    arcname = os.path.join(arcdirpath, name)
1010*cda5da8dSAndroid Build Coastguard Worker                    zf.write(path, arcname)
1011*cda5da8dSAndroid Build Coastguard Worker                    if logger is not None:
1012*cda5da8dSAndroid Build Coastguard Worker                        logger.info("adding '%s'", path)
1013*cda5da8dSAndroid Build Coastguard Worker                for name in filenames:
1014*cda5da8dSAndroid Build Coastguard Worker                    path = os.path.join(dirpath, name)
1015*cda5da8dSAndroid Build Coastguard Worker                    path = os.path.normpath(path)
1016*cda5da8dSAndroid Build Coastguard Worker                    if os.path.isfile(path):
1017*cda5da8dSAndroid Build Coastguard Worker                        arcname = os.path.join(arcdirpath, name)
1018*cda5da8dSAndroid Build Coastguard Worker                        zf.write(path, arcname)
1019*cda5da8dSAndroid Build Coastguard Worker                        if logger is not None:
1020*cda5da8dSAndroid Build Coastguard Worker                            logger.info("adding '%s'", path)
1021*cda5da8dSAndroid Build Coastguard Worker
1022*cda5da8dSAndroid Build Coastguard Worker    if root_dir is not None:
1023*cda5da8dSAndroid Build Coastguard Worker        zip_filename = os.path.abspath(zip_filename)
1024*cda5da8dSAndroid Build Coastguard Worker    return zip_filename
1025*cda5da8dSAndroid Build Coastguard Worker
1026*cda5da8dSAndroid Build Coastguard Worker# Maps the name of the archive format to a tuple containing:
1027*cda5da8dSAndroid Build Coastguard Worker# * the archiving function
1028*cda5da8dSAndroid Build Coastguard Worker# * extra keyword arguments
1029*cda5da8dSAndroid Build Coastguard Worker# * description
1030*cda5da8dSAndroid Build Coastguard Worker# * does it support the root_dir argument?
1031*cda5da8dSAndroid Build Coastguard Worker_ARCHIVE_FORMATS = {
1032*cda5da8dSAndroid Build Coastguard Worker    'tar':   (_make_tarball, [('compress', None)],
1033*cda5da8dSAndroid Build Coastguard Worker              "uncompressed tar file", True),
1034*cda5da8dSAndroid Build Coastguard Worker}
1035*cda5da8dSAndroid Build Coastguard Worker
1036*cda5da8dSAndroid Build Coastguard Workerif _ZLIB_SUPPORTED:
1037*cda5da8dSAndroid Build Coastguard Worker    _ARCHIVE_FORMATS['gztar'] = (_make_tarball, [('compress', 'gzip')],
1038*cda5da8dSAndroid Build Coastguard Worker                                "gzip'ed tar-file", True)
1039*cda5da8dSAndroid Build Coastguard Worker    _ARCHIVE_FORMATS['zip'] = (_make_zipfile, [], "ZIP file", True)
1040*cda5da8dSAndroid Build Coastguard Worker
1041*cda5da8dSAndroid Build Coastguard Workerif _BZ2_SUPPORTED:
1042*cda5da8dSAndroid Build Coastguard Worker    _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')],
1043*cda5da8dSAndroid Build Coastguard Worker                                "bzip2'ed tar-file", True)
1044*cda5da8dSAndroid Build Coastguard Worker
1045*cda5da8dSAndroid Build Coastguard Workerif _LZMA_SUPPORTED:
1046*cda5da8dSAndroid Build Coastguard Worker    _ARCHIVE_FORMATS['xztar'] = (_make_tarball, [('compress', 'xz')],
1047*cda5da8dSAndroid Build Coastguard Worker                                "xz'ed tar-file", True)
1048*cda5da8dSAndroid Build Coastguard Worker
1049*cda5da8dSAndroid Build Coastguard Workerdef get_archive_formats():
1050*cda5da8dSAndroid Build Coastguard Worker    """Returns a list of supported formats for archiving and unarchiving.
1051*cda5da8dSAndroid Build Coastguard Worker
1052*cda5da8dSAndroid Build Coastguard Worker    Each element of the returned sequence is a tuple (name, description)
1053*cda5da8dSAndroid Build Coastguard Worker    """
1054*cda5da8dSAndroid Build Coastguard Worker    formats = [(name, registry[2]) for name, registry in
1055*cda5da8dSAndroid Build Coastguard Worker               _ARCHIVE_FORMATS.items()]
1056*cda5da8dSAndroid Build Coastguard Worker    formats.sort()
1057*cda5da8dSAndroid Build Coastguard Worker    return formats
1058*cda5da8dSAndroid Build Coastguard Worker
1059*cda5da8dSAndroid Build Coastguard Workerdef register_archive_format(name, function, extra_args=None, description=''):
1060*cda5da8dSAndroid Build Coastguard Worker    """Registers an archive format.
1061*cda5da8dSAndroid Build Coastguard Worker
1062*cda5da8dSAndroid Build Coastguard Worker    name is the name of the format. function is the callable that will be
1063*cda5da8dSAndroid Build Coastguard Worker    used to create archives. If provided, extra_args is a sequence of
1064*cda5da8dSAndroid Build Coastguard Worker    (name, value) tuples that will be passed as arguments to the callable.
1065*cda5da8dSAndroid Build Coastguard Worker    description can be provided to describe the format, and will be returned
1066*cda5da8dSAndroid Build Coastguard Worker    by the get_archive_formats() function.
1067*cda5da8dSAndroid Build Coastguard Worker    """
1068*cda5da8dSAndroid Build Coastguard Worker    if extra_args is None:
1069*cda5da8dSAndroid Build Coastguard Worker        extra_args = []
1070*cda5da8dSAndroid Build Coastguard Worker    if not callable(function):
1071*cda5da8dSAndroid Build Coastguard Worker        raise TypeError('The %s object is not callable' % function)
1072*cda5da8dSAndroid Build Coastguard Worker    if not isinstance(extra_args, (tuple, list)):
1073*cda5da8dSAndroid Build Coastguard Worker        raise TypeError('extra_args needs to be a sequence')
1074*cda5da8dSAndroid Build Coastguard Worker    for element in extra_args:
1075*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(element, (tuple, list)) or len(element) !=2:
1076*cda5da8dSAndroid Build Coastguard Worker            raise TypeError('extra_args elements are : (arg_name, value)')
1077*cda5da8dSAndroid Build Coastguard Worker
1078*cda5da8dSAndroid Build Coastguard Worker    _ARCHIVE_FORMATS[name] = (function, extra_args, description, False)
1079*cda5da8dSAndroid Build Coastguard Worker
1080*cda5da8dSAndroid Build Coastguard Workerdef unregister_archive_format(name):
1081*cda5da8dSAndroid Build Coastguard Worker    del _ARCHIVE_FORMATS[name]
1082*cda5da8dSAndroid Build Coastguard Worker
1083*cda5da8dSAndroid Build Coastguard Workerdef make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
1084*cda5da8dSAndroid Build Coastguard Worker                 dry_run=0, owner=None, group=None, logger=None):
1085*cda5da8dSAndroid Build Coastguard Worker    """Create an archive file (eg. zip or tar).
1086*cda5da8dSAndroid Build Coastguard Worker
1087*cda5da8dSAndroid Build Coastguard Worker    'base_name' is the name of the file to create, minus any format-specific
1088*cda5da8dSAndroid Build Coastguard Worker    extension; 'format' is the archive format: one of "zip", "tar", "gztar",
1089*cda5da8dSAndroid Build Coastguard Worker    "bztar", or "xztar".  Or any other registered format.
1090*cda5da8dSAndroid Build Coastguard Worker
1091*cda5da8dSAndroid Build Coastguard Worker    'root_dir' is a directory that will be the root directory of the
1092*cda5da8dSAndroid Build Coastguard Worker    archive; ie. we typically chdir into 'root_dir' before creating the
1093*cda5da8dSAndroid Build Coastguard Worker    archive.  'base_dir' is the directory where we start archiving from;
1094*cda5da8dSAndroid Build Coastguard Worker    ie. 'base_dir' will be the common prefix of all files and
1095*cda5da8dSAndroid Build Coastguard Worker    directories in the archive.  'root_dir' and 'base_dir' both default
1096*cda5da8dSAndroid Build Coastguard Worker    to the current directory.  Returns the name of the archive file.
1097*cda5da8dSAndroid Build Coastguard Worker
1098*cda5da8dSAndroid Build Coastguard Worker    'owner' and 'group' are used when creating a tar archive. By default,
1099*cda5da8dSAndroid Build Coastguard Worker    uses the current owner and group.
1100*cda5da8dSAndroid Build Coastguard Worker    """
1101*cda5da8dSAndroid Build Coastguard Worker    sys.audit("shutil.make_archive", base_name, format, root_dir, base_dir)
1102*cda5da8dSAndroid Build Coastguard Worker    try:
1103*cda5da8dSAndroid Build Coastguard Worker        format_info = _ARCHIVE_FORMATS[format]
1104*cda5da8dSAndroid Build Coastguard Worker    except KeyError:
1105*cda5da8dSAndroid Build Coastguard Worker        raise ValueError("unknown archive format '%s'" % format) from None
1106*cda5da8dSAndroid Build Coastguard Worker
1107*cda5da8dSAndroid Build Coastguard Worker    kwargs = {'dry_run': dry_run, 'logger': logger,
1108*cda5da8dSAndroid Build Coastguard Worker              'owner': owner, 'group': group}
1109*cda5da8dSAndroid Build Coastguard Worker
1110*cda5da8dSAndroid Build Coastguard Worker    func = format_info[0]
1111*cda5da8dSAndroid Build Coastguard Worker    for arg, val in format_info[1]:
1112*cda5da8dSAndroid Build Coastguard Worker        kwargs[arg] = val
1113*cda5da8dSAndroid Build Coastguard Worker
1114*cda5da8dSAndroid Build Coastguard Worker    if base_dir is None:
1115*cda5da8dSAndroid Build Coastguard Worker        base_dir = os.curdir
1116*cda5da8dSAndroid Build Coastguard Worker
1117*cda5da8dSAndroid Build Coastguard Worker    support_root_dir = format_info[3]
1118*cda5da8dSAndroid Build Coastguard Worker    save_cwd = None
1119*cda5da8dSAndroid Build Coastguard Worker    if root_dir is not None:
1120*cda5da8dSAndroid Build Coastguard Worker        if support_root_dir:
1121*cda5da8dSAndroid Build Coastguard Worker            # Support path-like base_name here for backwards-compatibility.
1122*cda5da8dSAndroid Build Coastguard Worker            base_name = os.fspath(base_name)
1123*cda5da8dSAndroid Build Coastguard Worker            kwargs['root_dir'] = root_dir
1124*cda5da8dSAndroid Build Coastguard Worker        else:
1125*cda5da8dSAndroid Build Coastguard Worker            save_cwd = os.getcwd()
1126*cda5da8dSAndroid Build Coastguard Worker            if logger is not None:
1127*cda5da8dSAndroid Build Coastguard Worker                logger.debug("changing into '%s'", root_dir)
1128*cda5da8dSAndroid Build Coastguard Worker            base_name = os.path.abspath(base_name)
1129*cda5da8dSAndroid Build Coastguard Worker            if not dry_run:
1130*cda5da8dSAndroid Build Coastguard Worker                os.chdir(root_dir)
1131*cda5da8dSAndroid Build Coastguard Worker
1132*cda5da8dSAndroid Build Coastguard Worker    try:
1133*cda5da8dSAndroid Build Coastguard Worker        filename = func(base_name, base_dir, **kwargs)
1134*cda5da8dSAndroid Build Coastguard Worker    finally:
1135*cda5da8dSAndroid Build Coastguard Worker        if save_cwd is not None:
1136*cda5da8dSAndroid Build Coastguard Worker            if logger is not None:
1137*cda5da8dSAndroid Build Coastguard Worker                logger.debug("changing back to '%s'", save_cwd)
1138*cda5da8dSAndroid Build Coastguard Worker            os.chdir(save_cwd)
1139*cda5da8dSAndroid Build Coastguard Worker
1140*cda5da8dSAndroid Build Coastguard Worker    return filename
1141*cda5da8dSAndroid Build Coastguard Worker
1142*cda5da8dSAndroid Build Coastguard Worker
1143*cda5da8dSAndroid Build Coastguard Workerdef get_unpack_formats():
1144*cda5da8dSAndroid Build Coastguard Worker    """Returns a list of supported formats for unpacking.
1145*cda5da8dSAndroid Build Coastguard Worker
1146*cda5da8dSAndroid Build Coastguard Worker    Each element of the returned sequence is a tuple
1147*cda5da8dSAndroid Build Coastguard Worker    (name, extensions, description)
1148*cda5da8dSAndroid Build Coastguard Worker    """
1149*cda5da8dSAndroid Build Coastguard Worker    formats = [(name, info[0], info[3]) for name, info in
1150*cda5da8dSAndroid Build Coastguard Worker               _UNPACK_FORMATS.items()]
1151*cda5da8dSAndroid Build Coastguard Worker    formats.sort()
1152*cda5da8dSAndroid Build Coastguard Worker    return formats
1153*cda5da8dSAndroid Build Coastguard Worker
1154*cda5da8dSAndroid Build Coastguard Workerdef _check_unpack_options(extensions, function, extra_args):
1155*cda5da8dSAndroid Build Coastguard Worker    """Checks what gets registered as an unpacker."""
1156*cda5da8dSAndroid Build Coastguard Worker    # first make sure no other unpacker is registered for this extension
1157*cda5da8dSAndroid Build Coastguard Worker    existing_extensions = {}
1158*cda5da8dSAndroid Build Coastguard Worker    for name, info in _UNPACK_FORMATS.items():
1159*cda5da8dSAndroid Build Coastguard Worker        for ext in info[0]:
1160*cda5da8dSAndroid Build Coastguard Worker            existing_extensions[ext] = name
1161*cda5da8dSAndroid Build Coastguard Worker
1162*cda5da8dSAndroid Build Coastguard Worker    for extension in extensions:
1163*cda5da8dSAndroid Build Coastguard Worker        if extension in existing_extensions:
1164*cda5da8dSAndroid Build Coastguard Worker            msg = '%s is already registered for "%s"'
1165*cda5da8dSAndroid Build Coastguard Worker            raise RegistryError(msg % (extension,
1166*cda5da8dSAndroid Build Coastguard Worker                                       existing_extensions[extension]))
1167*cda5da8dSAndroid Build Coastguard Worker
1168*cda5da8dSAndroid Build Coastguard Worker    if not callable(function):
1169*cda5da8dSAndroid Build Coastguard Worker        raise TypeError('The registered function must be a callable')
1170*cda5da8dSAndroid Build Coastguard Worker
1171*cda5da8dSAndroid Build Coastguard Worker
1172*cda5da8dSAndroid Build Coastguard Workerdef register_unpack_format(name, extensions, function, extra_args=None,
1173*cda5da8dSAndroid Build Coastguard Worker                           description=''):
1174*cda5da8dSAndroid Build Coastguard Worker    """Registers an unpack format.
1175*cda5da8dSAndroid Build Coastguard Worker
1176*cda5da8dSAndroid Build Coastguard Worker    `name` is the name of the format. `extensions` is a list of extensions
1177*cda5da8dSAndroid Build Coastguard Worker    corresponding to the format.
1178*cda5da8dSAndroid Build Coastguard Worker
1179*cda5da8dSAndroid Build Coastguard Worker    `function` is the callable that will be
1180*cda5da8dSAndroid Build Coastguard Worker    used to unpack archives. The callable will receive archives to unpack.
1181*cda5da8dSAndroid Build Coastguard Worker    If it's unable to handle an archive, it needs to raise a ReadError
1182*cda5da8dSAndroid Build Coastguard Worker    exception.
1183*cda5da8dSAndroid Build Coastguard Worker
1184*cda5da8dSAndroid Build Coastguard Worker    If provided, `extra_args` is a sequence of
1185*cda5da8dSAndroid Build Coastguard Worker    (name, value) tuples that will be passed as arguments to the callable.
1186*cda5da8dSAndroid Build Coastguard Worker    description can be provided to describe the format, and will be returned
1187*cda5da8dSAndroid Build Coastguard Worker    by the get_unpack_formats() function.
1188*cda5da8dSAndroid Build Coastguard Worker    """
1189*cda5da8dSAndroid Build Coastguard Worker    if extra_args is None:
1190*cda5da8dSAndroid Build Coastguard Worker        extra_args = []
1191*cda5da8dSAndroid Build Coastguard Worker    _check_unpack_options(extensions, function, extra_args)
1192*cda5da8dSAndroid Build Coastguard Worker    _UNPACK_FORMATS[name] = extensions, function, extra_args, description
1193*cda5da8dSAndroid Build Coastguard Worker
1194*cda5da8dSAndroid Build Coastguard Workerdef unregister_unpack_format(name):
1195*cda5da8dSAndroid Build Coastguard Worker    """Removes the pack format from the registry."""
1196*cda5da8dSAndroid Build Coastguard Worker    del _UNPACK_FORMATS[name]
1197*cda5da8dSAndroid Build Coastguard Worker
1198*cda5da8dSAndroid Build Coastguard Workerdef _ensure_directory(path):
1199*cda5da8dSAndroid Build Coastguard Worker    """Ensure that the parent directory of `path` exists"""
1200*cda5da8dSAndroid Build Coastguard Worker    dirname = os.path.dirname(path)
1201*cda5da8dSAndroid Build Coastguard Worker    if not os.path.isdir(dirname):
1202*cda5da8dSAndroid Build Coastguard Worker        os.makedirs(dirname)
1203*cda5da8dSAndroid Build Coastguard Worker
1204*cda5da8dSAndroid Build Coastguard Workerdef _unpack_zipfile(filename, extract_dir):
1205*cda5da8dSAndroid Build Coastguard Worker    """Unpack zip `filename` to `extract_dir`
1206*cda5da8dSAndroid Build Coastguard Worker    """
1207*cda5da8dSAndroid Build Coastguard Worker    import zipfile  # late import for breaking circular dependency
1208*cda5da8dSAndroid Build Coastguard Worker
1209*cda5da8dSAndroid Build Coastguard Worker    if not zipfile.is_zipfile(filename):
1210*cda5da8dSAndroid Build Coastguard Worker        raise ReadError("%s is not a zip file" % filename)
1211*cda5da8dSAndroid Build Coastguard Worker
1212*cda5da8dSAndroid Build Coastguard Worker    zip = zipfile.ZipFile(filename)
1213*cda5da8dSAndroid Build Coastguard Worker    try:
1214*cda5da8dSAndroid Build Coastguard Worker        for info in zip.infolist():
1215*cda5da8dSAndroid Build Coastguard Worker            name = info.filename
1216*cda5da8dSAndroid Build Coastguard Worker
1217*cda5da8dSAndroid Build Coastguard Worker            # don't extract absolute paths or ones with .. in them
1218*cda5da8dSAndroid Build Coastguard Worker            if name.startswith('/') or '..' in name:
1219*cda5da8dSAndroid Build Coastguard Worker                continue
1220*cda5da8dSAndroid Build Coastguard Worker
1221*cda5da8dSAndroid Build Coastguard Worker            targetpath = os.path.join(extract_dir, *name.split('/'))
1222*cda5da8dSAndroid Build Coastguard Worker            if not targetpath:
1223*cda5da8dSAndroid Build Coastguard Worker                continue
1224*cda5da8dSAndroid Build Coastguard Worker
1225*cda5da8dSAndroid Build Coastguard Worker            _ensure_directory(targetpath)
1226*cda5da8dSAndroid Build Coastguard Worker            if not name.endswith('/'):
1227*cda5da8dSAndroid Build Coastguard Worker                # file
1228*cda5da8dSAndroid Build Coastguard Worker                with zip.open(name, 'r') as source, \
1229*cda5da8dSAndroid Build Coastguard Worker                        open(targetpath, 'wb') as target:
1230*cda5da8dSAndroid Build Coastguard Worker                    copyfileobj(source, target)
1231*cda5da8dSAndroid Build Coastguard Worker    finally:
1232*cda5da8dSAndroid Build Coastguard Worker        zip.close()
1233*cda5da8dSAndroid Build Coastguard Worker
1234*cda5da8dSAndroid Build Coastguard Workerdef _unpack_tarfile(filename, extract_dir, *, filter=None):
1235*cda5da8dSAndroid Build Coastguard Worker    """Unpack tar/tar.gz/tar.bz2/tar.xz `filename` to `extract_dir`
1236*cda5da8dSAndroid Build Coastguard Worker    """
1237*cda5da8dSAndroid Build Coastguard Worker    import tarfile  # late import for breaking circular dependency
1238*cda5da8dSAndroid Build Coastguard Worker    try:
1239*cda5da8dSAndroid Build Coastguard Worker        tarobj = tarfile.open(filename)
1240*cda5da8dSAndroid Build Coastguard Worker    except tarfile.TarError:
1241*cda5da8dSAndroid Build Coastguard Worker        raise ReadError(
1242*cda5da8dSAndroid Build Coastguard Worker            "%s is not a compressed or uncompressed tar file" % filename)
1243*cda5da8dSAndroid Build Coastguard Worker    try:
1244*cda5da8dSAndroid Build Coastguard Worker        tarobj.extractall(extract_dir, filter=filter)
1245*cda5da8dSAndroid Build Coastguard Worker    finally:
1246*cda5da8dSAndroid Build Coastguard Worker        tarobj.close()
1247*cda5da8dSAndroid Build Coastguard Worker
1248*cda5da8dSAndroid Build Coastguard Worker# Maps the name of the unpack format to a tuple containing:
1249*cda5da8dSAndroid Build Coastguard Worker# * extensions
1250*cda5da8dSAndroid Build Coastguard Worker# * the unpacking function
1251*cda5da8dSAndroid Build Coastguard Worker# * extra keyword arguments
1252*cda5da8dSAndroid Build Coastguard Worker# * description
1253*cda5da8dSAndroid Build Coastguard Worker_UNPACK_FORMATS = {
1254*cda5da8dSAndroid Build Coastguard Worker    'tar':   (['.tar'], _unpack_tarfile, [], "uncompressed tar file"),
1255*cda5da8dSAndroid Build Coastguard Worker    'zip':   (['.zip'], _unpack_zipfile, [], "ZIP file"),
1256*cda5da8dSAndroid Build Coastguard Worker}
1257*cda5da8dSAndroid Build Coastguard Worker
1258*cda5da8dSAndroid Build Coastguard Workerif _ZLIB_SUPPORTED:
1259*cda5da8dSAndroid Build Coastguard Worker    _UNPACK_FORMATS['gztar'] = (['.tar.gz', '.tgz'], _unpack_tarfile, [],
1260*cda5da8dSAndroid Build Coastguard Worker                                "gzip'ed tar-file")
1261*cda5da8dSAndroid Build Coastguard Worker
1262*cda5da8dSAndroid Build Coastguard Workerif _BZ2_SUPPORTED:
1263*cda5da8dSAndroid Build Coastguard Worker    _UNPACK_FORMATS['bztar'] = (['.tar.bz2', '.tbz2'], _unpack_tarfile, [],
1264*cda5da8dSAndroid Build Coastguard Worker                                "bzip2'ed tar-file")
1265*cda5da8dSAndroid Build Coastguard Worker
1266*cda5da8dSAndroid Build Coastguard Workerif _LZMA_SUPPORTED:
1267*cda5da8dSAndroid Build Coastguard Worker    _UNPACK_FORMATS['xztar'] = (['.tar.xz', '.txz'], _unpack_tarfile, [],
1268*cda5da8dSAndroid Build Coastguard Worker                                "xz'ed tar-file")
1269*cda5da8dSAndroid Build Coastguard Worker
1270*cda5da8dSAndroid Build Coastguard Workerdef _find_unpack_format(filename):
1271*cda5da8dSAndroid Build Coastguard Worker    for name, info in _UNPACK_FORMATS.items():
1272*cda5da8dSAndroid Build Coastguard Worker        for extension in info[0]:
1273*cda5da8dSAndroid Build Coastguard Worker            if filename.endswith(extension):
1274*cda5da8dSAndroid Build Coastguard Worker                return name
1275*cda5da8dSAndroid Build Coastguard Worker    return None
1276*cda5da8dSAndroid Build Coastguard Worker
1277*cda5da8dSAndroid Build Coastguard Workerdef unpack_archive(filename, extract_dir=None, format=None, *, filter=None):
1278*cda5da8dSAndroid Build Coastguard Worker    """Unpack an archive.
1279*cda5da8dSAndroid Build Coastguard Worker
1280*cda5da8dSAndroid Build Coastguard Worker    `filename` is the name of the archive.
1281*cda5da8dSAndroid Build Coastguard Worker
1282*cda5da8dSAndroid Build Coastguard Worker    `extract_dir` is the name of the target directory, where the archive
1283*cda5da8dSAndroid Build Coastguard Worker    is unpacked. If not provided, the current working directory is used.
1284*cda5da8dSAndroid Build Coastguard Worker
1285*cda5da8dSAndroid Build Coastguard Worker    `format` is the archive format: one of "zip", "tar", "gztar", "bztar",
1286*cda5da8dSAndroid Build Coastguard Worker    or "xztar".  Or any other registered format.  If not provided,
1287*cda5da8dSAndroid Build Coastguard Worker    unpack_archive will use the filename extension and see if an unpacker
1288*cda5da8dSAndroid Build Coastguard Worker    was registered for that extension.
1289*cda5da8dSAndroid Build Coastguard Worker
1290*cda5da8dSAndroid Build Coastguard Worker    In case none is found, a ValueError is raised.
1291*cda5da8dSAndroid Build Coastguard Worker
1292*cda5da8dSAndroid Build Coastguard Worker    If `filter` is given, it is passed to the underlying
1293*cda5da8dSAndroid Build Coastguard Worker    extraction function.
1294*cda5da8dSAndroid Build Coastguard Worker    """
1295*cda5da8dSAndroid Build Coastguard Worker    sys.audit("shutil.unpack_archive", filename, extract_dir, format)
1296*cda5da8dSAndroid Build Coastguard Worker
1297*cda5da8dSAndroid Build Coastguard Worker    if extract_dir is None:
1298*cda5da8dSAndroid Build Coastguard Worker        extract_dir = os.getcwd()
1299*cda5da8dSAndroid Build Coastguard Worker
1300*cda5da8dSAndroid Build Coastguard Worker    extract_dir = os.fspath(extract_dir)
1301*cda5da8dSAndroid Build Coastguard Worker    filename = os.fspath(filename)
1302*cda5da8dSAndroid Build Coastguard Worker
1303*cda5da8dSAndroid Build Coastguard Worker    if filter is None:
1304*cda5da8dSAndroid Build Coastguard Worker        filter_kwargs = {}
1305*cda5da8dSAndroid Build Coastguard Worker    else:
1306*cda5da8dSAndroid Build Coastguard Worker        filter_kwargs = {'filter': filter}
1307*cda5da8dSAndroid Build Coastguard Worker    if format is not None:
1308*cda5da8dSAndroid Build Coastguard Worker        try:
1309*cda5da8dSAndroid Build Coastguard Worker            format_info = _UNPACK_FORMATS[format]
1310*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
1311*cda5da8dSAndroid Build Coastguard Worker            raise ValueError("Unknown unpack format '{0}'".format(format)) from None
1312*cda5da8dSAndroid Build Coastguard Worker
1313*cda5da8dSAndroid Build Coastguard Worker        func = format_info[1]
1314*cda5da8dSAndroid Build Coastguard Worker        func(filename, extract_dir, **dict(format_info[2]), **filter_kwargs)
1315*cda5da8dSAndroid Build Coastguard Worker    else:
1316*cda5da8dSAndroid Build Coastguard Worker        # we need to look at the registered unpackers supported extensions
1317*cda5da8dSAndroid Build Coastguard Worker        format = _find_unpack_format(filename)
1318*cda5da8dSAndroid Build Coastguard Worker        if format is None:
1319*cda5da8dSAndroid Build Coastguard Worker            raise ReadError("Unknown archive format '{0}'".format(filename))
1320*cda5da8dSAndroid Build Coastguard Worker
1321*cda5da8dSAndroid Build Coastguard Worker        func = _UNPACK_FORMATS[format][1]
1322*cda5da8dSAndroid Build Coastguard Worker        kwargs = dict(_UNPACK_FORMATS[format][2]) | filter_kwargs
1323*cda5da8dSAndroid Build Coastguard Worker        func(filename, extract_dir, **kwargs)
1324*cda5da8dSAndroid Build Coastguard Worker
1325*cda5da8dSAndroid Build Coastguard Worker
1326*cda5da8dSAndroid Build Coastguard Workerif hasattr(os, 'statvfs'):
1327*cda5da8dSAndroid Build Coastguard Worker
1328*cda5da8dSAndroid Build Coastguard Worker    __all__.append('disk_usage')
1329*cda5da8dSAndroid Build Coastguard Worker    _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
1330*cda5da8dSAndroid Build Coastguard Worker    _ntuple_diskusage.total.__doc__ = 'Total space in bytes'
1331*cda5da8dSAndroid Build Coastguard Worker    _ntuple_diskusage.used.__doc__ = 'Used space in bytes'
1332*cda5da8dSAndroid Build Coastguard Worker    _ntuple_diskusage.free.__doc__ = 'Free space in bytes'
1333*cda5da8dSAndroid Build Coastguard Worker
1334*cda5da8dSAndroid Build Coastguard Worker    def disk_usage(path):
1335*cda5da8dSAndroid Build Coastguard Worker        """Return disk usage statistics about the given path.
1336*cda5da8dSAndroid Build Coastguard Worker
1337*cda5da8dSAndroid Build Coastguard Worker        Returned value is a named tuple with attributes 'total', 'used' and
1338*cda5da8dSAndroid Build Coastguard Worker        'free', which are the amount of total, used and free space, in bytes.
1339*cda5da8dSAndroid Build Coastguard Worker        """
1340*cda5da8dSAndroid Build Coastguard Worker        st = os.statvfs(path)
1341*cda5da8dSAndroid Build Coastguard Worker        free = st.f_bavail * st.f_frsize
1342*cda5da8dSAndroid Build Coastguard Worker        total = st.f_blocks * st.f_frsize
1343*cda5da8dSAndroid Build Coastguard Worker        used = (st.f_blocks - st.f_bfree) * st.f_frsize
1344*cda5da8dSAndroid Build Coastguard Worker        return _ntuple_diskusage(total, used, free)
1345*cda5da8dSAndroid Build Coastguard Worker
1346*cda5da8dSAndroid Build Coastguard Workerelif _WINDOWS:
1347*cda5da8dSAndroid Build Coastguard Worker
1348*cda5da8dSAndroid Build Coastguard Worker    __all__.append('disk_usage')
1349*cda5da8dSAndroid Build Coastguard Worker    _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
1350*cda5da8dSAndroid Build Coastguard Worker
1351*cda5da8dSAndroid Build Coastguard Worker    def disk_usage(path):
1352*cda5da8dSAndroid Build Coastguard Worker        """Return disk usage statistics about the given path.
1353*cda5da8dSAndroid Build Coastguard Worker
1354*cda5da8dSAndroid Build Coastguard Worker        Returned values is a named tuple with attributes 'total', 'used' and
1355*cda5da8dSAndroid Build Coastguard Worker        'free', which are the amount of total, used and free space, in bytes.
1356*cda5da8dSAndroid Build Coastguard Worker        """
1357*cda5da8dSAndroid Build Coastguard Worker        total, free = nt._getdiskusage(path)
1358*cda5da8dSAndroid Build Coastguard Worker        used = total - free
1359*cda5da8dSAndroid Build Coastguard Worker        return _ntuple_diskusage(total, used, free)
1360*cda5da8dSAndroid Build Coastguard Worker
1361*cda5da8dSAndroid Build Coastguard Worker
1362*cda5da8dSAndroid Build Coastguard Workerdef chown(path, user=None, group=None):
1363*cda5da8dSAndroid Build Coastguard Worker    """Change owner user and group of the given path.
1364*cda5da8dSAndroid Build Coastguard Worker
1365*cda5da8dSAndroid Build Coastguard Worker    user and group can be the uid/gid or the user/group names, and in that case,
1366*cda5da8dSAndroid Build Coastguard Worker    they are converted to their respective uid/gid.
1367*cda5da8dSAndroid Build Coastguard Worker    """
1368*cda5da8dSAndroid Build Coastguard Worker    sys.audit('shutil.chown', path, user, group)
1369*cda5da8dSAndroid Build Coastguard Worker
1370*cda5da8dSAndroid Build Coastguard Worker    if user is None and group is None:
1371*cda5da8dSAndroid Build Coastguard Worker        raise ValueError("user and/or group must be set")
1372*cda5da8dSAndroid Build Coastguard Worker
1373*cda5da8dSAndroid Build Coastguard Worker    _user = user
1374*cda5da8dSAndroid Build Coastguard Worker    _group = group
1375*cda5da8dSAndroid Build Coastguard Worker
1376*cda5da8dSAndroid Build Coastguard Worker    # -1 means don't change it
1377*cda5da8dSAndroid Build Coastguard Worker    if user is None:
1378*cda5da8dSAndroid Build Coastguard Worker        _user = -1
1379*cda5da8dSAndroid Build Coastguard Worker    # user can either be an int (the uid) or a string (the system username)
1380*cda5da8dSAndroid Build Coastguard Worker    elif isinstance(user, str):
1381*cda5da8dSAndroid Build Coastguard Worker        _user = _get_uid(user)
1382*cda5da8dSAndroid Build Coastguard Worker        if _user is None:
1383*cda5da8dSAndroid Build Coastguard Worker            raise LookupError("no such user: {!r}".format(user))
1384*cda5da8dSAndroid Build Coastguard Worker
1385*cda5da8dSAndroid Build Coastguard Worker    if group is None:
1386*cda5da8dSAndroid Build Coastguard Worker        _group = -1
1387*cda5da8dSAndroid Build Coastguard Worker    elif not isinstance(group, int):
1388*cda5da8dSAndroid Build Coastguard Worker        _group = _get_gid(group)
1389*cda5da8dSAndroid Build Coastguard Worker        if _group is None:
1390*cda5da8dSAndroid Build Coastguard Worker            raise LookupError("no such group: {!r}".format(group))
1391*cda5da8dSAndroid Build Coastguard Worker
1392*cda5da8dSAndroid Build Coastguard Worker    os.chown(path, _user, _group)
1393*cda5da8dSAndroid Build Coastguard Worker
1394*cda5da8dSAndroid Build Coastguard Workerdef get_terminal_size(fallback=(80, 24)):
1395*cda5da8dSAndroid Build Coastguard Worker    """Get the size of the terminal window.
1396*cda5da8dSAndroid Build Coastguard Worker
1397*cda5da8dSAndroid Build Coastguard Worker    For each of the two dimensions, the environment variable, COLUMNS
1398*cda5da8dSAndroid Build Coastguard Worker    and LINES respectively, is checked. If the variable is defined and
1399*cda5da8dSAndroid Build Coastguard Worker    the value is a positive integer, it is used.
1400*cda5da8dSAndroid Build Coastguard Worker
1401*cda5da8dSAndroid Build Coastguard Worker    When COLUMNS or LINES is not defined, which is the common case,
1402*cda5da8dSAndroid Build Coastguard Worker    the terminal connected to sys.__stdout__ is queried
1403*cda5da8dSAndroid Build Coastguard Worker    by invoking os.get_terminal_size.
1404*cda5da8dSAndroid Build Coastguard Worker
1405*cda5da8dSAndroid Build Coastguard Worker    If the terminal size cannot be successfully queried, either because
1406*cda5da8dSAndroid Build Coastguard Worker    the system doesn't support querying, or because we are not
1407*cda5da8dSAndroid Build Coastguard Worker    connected to a terminal, the value given in fallback parameter
1408*cda5da8dSAndroid Build Coastguard Worker    is used. Fallback defaults to (80, 24) which is the default
1409*cda5da8dSAndroid Build Coastguard Worker    size used by many terminal emulators.
1410*cda5da8dSAndroid Build Coastguard Worker
1411*cda5da8dSAndroid Build Coastguard Worker    The value returned is a named tuple of type os.terminal_size.
1412*cda5da8dSAndroid Build Coastguard Worker    """
1413*cda5da8dSAndroid Build Coastguard Worker    # columns, lines are the working values
1414*cda5da8dSAndroid Build Coastguard Worker    try:
1415*cda5da8dSAndroid Build Coastguard Worker        columns = int(os.environ['COLUMNS'])
1416*cda5da8dSAndroid Build Coastguard Worker    except (KeyError, ValueError):
1417*cda5da8dSAndroid Build Coastguard Worker        columns = 0
1418*cda5da8dSAndroid Build Coastguard Worker
1419*cda5da8dSAndroid Build Coastguard Worker    try:
1420*cda5da8dSAndroid Build Coastguard Worker        lines = int(os.environ['LINES'])
1421*cda5da8dSAndroid Build Coastguard Worker    except (KeyError, ValueError):
1422*cda5da8dSAndroid Build Coastguard Worker        lines = 0
1423*cda5da8dSAndroid Build Coastguard Worker
1424*cda5da8dSAndroid Build Coastguard Worker    # only query if necessary
1425*cda5da8dSAndroid Build Coastguard Worker    if columns <= 0 or lines <= 0:
1426*cda5da8dSAndroid Build Coastguard Worker        try:
1427*cda5da8dSAndroid Build Coastguard Worker            size = os.get_terminal_size(sys.__stdout__.fileno())
1428*cda5da8dSAndroid Build Coastguard Worker        except (AttributeError, ValueError, OSError):
1429*cda5da8dSAndroid Build Coastguard Worker            # stdout is None, closed, detached, or not a terminal, or
1430*cda5da8dSAndroid Build Coastguard Worker            # os.get_terminal_size() is unsupported
1431*cda5da8dSAndroid Build Coastguard Worker            size = os.terminal_size(fallback)
1432*cda5da8dSAndroid Build Coastguard Worker        if columns <= 0:
1433*cda5da8dSAndroid Build Coastguard Worker            columns = size.columns or fallback[0]
1434*cda5da8dSAndroid Build Coastguard Worker        if lines <= 0:
1435*cda5da8dSAndroid Build Coastguard Worker            lines = size.lines or fallback[1]
1436*cda5da8dSAndroid Build Coastguard Worker
1437*cda5da8dSAndroid Build Coastguard Worker    return os.terminal_size((columns, lines))
1438*cda5da8dSAndroid Build Coastguard Worker
1439*cda5da8dSAndroid Build Coastguard Worker
1440*cda5da8dSAndroid Build Coastguard Worker# Check that a given file can be accessed with the correct mode.
1441*cda5da8dSAndroid Build Coastguard Worker# Additionally check that `file` is not a directory, as on Windows
1442*cda5da8dSAndroid Build Coastguard Worker# directories pass the os.access check.
1443*cda5da8dSAndroid Build Coastguard Workerdef _access_check(fn, mode):
1444*cda5da8dSAndroid Build Coastguard Worker    return (os.path.exists(fn) and os.access(fn, mode)
1445*cda5da8dSAndroid Build Coastguard Worker            and not os.path.isdir(fn))
1446*cda5da8dSAndroid Build Coastguard Worker
1447*cda5da8dSAndroid Build Coastguard Worker
1448*cda5da8dSAndroid Build Coastguard Workerdef which(cmd, mode=os.F_OK | os.X_OK, path=None):
1449*cda5da8dSAndroid Build Coastguard Worker    """Given a command, mode, and a PATH string, return the path which
1450*cda5da8dSAndroid Build Coastguard Worker    conforms to the given mode on the PATH, or None if there is no such
1451*cda5da8dSAndroid Build Coastguard Worker    file.
1452*cda5da8dSAndroid Build Coastguard Worker
1453*cda5da8dSAndroid Build Coastguard Worker    `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
1454*cda5da8dSAndroid Build Coastguard Worker    of os.environ.get("PATH"), or can be overridden with a custom search
1455*cda5da8dSAndroid Build Coastguard Worker    path.
1456*cda5da8dSAndroid Build Coastguard Worker
1457*cda5da8dSAndroid Build Coastguard Worker    """
1458*cda5da8dSAndroid Build Coastguard Worker    # If we're given a path with a directory part, look it up directly rather
1459*cda5da8dSAndroid Build Coastguard Worker    # than referring to PATH directories. This includes checking relative to the
1460*cda5da8dSAndroid Build Coastguard Worker    # current directory, e.g. ./script
1461*cda5da8dSAndroid Build Coastguard Worker    if os.path.dirname(cmd):
1462*cda5da8dSAndroid Build Coastguard Worker        if _access_check(cmd, mode):
1463*cda5da8dSAndroid Build Coastguard Worker            return cmd
1464*cda5da8dSAndroid Build Coastguard Worker        return None
1465*cda5da8dSAndroid Build Coastguard Worker
1466*cda5da8dSAndroid Build Coastguard Worker    use_bytes = isinstance(cmd, bytes)
1467*cda5da8dSAndroid Build Coastguard Worker
1468*cda5da8dSAndroid Build Coastguard Worker    if path is None:
1469*cda5da8dSAndroid Build Coastguard Worker        path = os.environ.get("PATH", None)
1470*cda5da8dSAndroid Build Coastguard Worker        if path is None:
1471*cda5da8dSAndroid Build Coastguard Worker            try:
1472*cda5da8dSAndroid Build Coastguard Worker                path = os.confstr("CS_PATH")
1473*cda5da8dSAndroid Build Coastguard Worker            except (AttributeError, ValueError):
1474*cda5da8dSAndroid Build Coastguard Worker                # os.confstr() or CS_PATH is not available
1475*cda5da8dSAndroid Build Coastguard Worker                path = os.defpath
1476*cda5da8dSAndroid Build Coastguard Worker        # bpo-35755: Don't use os.defpath if the PATH environment variable is
1477*cda5da8dSAndroid Build Coastguard Worker        # set to an empty string
1478*cda5da8dSAndroid Build Coastguard Worker
1479*cda5da8dSAndroid Build Coastguard Worker    # PATH='' doesn't match, whereas PATH=':' looks in the current directory
1480*cda5da8dSAndroid Build Coastguard Worker    if not path:
1481*cda5da8dSAndroid Build Coastguard Worker        return None
1482*cda5da8dSAndroid Build Coastguard Worker
1483*cda5da8dSAndroid Build Coastguard Worker    if use_bytes:
1484*cda5da8dSAndroid Build Coastguard Worker        path = os.fsencode(path)
1485*cda5da8dSAndroid Build Coastguard Worker        path = path.split(os.fsencode(os.pathsep))
1486*cda5da8dSAndroid Build Coastguard Worker    else:
1487*cda5da8dSAndroid Build Coastguard Worker        path = os.fsdecode(path)
1488*cda5da8dSAndroid Build Coastguard Worker        path = path.split(os.pathsep)
1489*cda5da8dSAndroid Build Coastguard Worker
1490*cda5da8dSAndroid Build Coastguard Worker    if sys.platform == "win32":
1491*cda5da8dSAndroid Build Coastguard Worker        # The current directory takes precedence on Windows.
1492*cda5da8dSAndroid Build Coastguard Worker        curdir = os.curdir
1493*cda5da8dSAndroid Build Coastguard Worker        if use_bytes:
1494*cda5da8dSAndroid Build Coastguard Worker            curdir = os.fsencode(curdir)
1495*cda5da8dSAndroid Build Coastguard Worker        if curdir not in path:
1496*cda5da8dSAndroid Build Coastguard Worker            path.insert(0, curdir)
1497*cda5da8dSAndroid Build Coastguard Worker
1498*cda5da8dSAndroid Build Coastguard Worker        # PATHEXT is necessary to check on Windows.
1499*cda5da8dSAndroid Build Coastguard Worker        pathext_source = os.getenv("PATHEXT") or _WIN_DEFAULT_PATHEXT
1500*cda5da8dSAndroid Build Coastguard Worker        pathext = [ext for ext in pathext_source.split(os.pathsep) if ext]
1501*cda5da8dSAndroid Build Coastguard Worker
1502*cda5da8dSAndroid Build Coastguard Worker        if use_bytes:
1503*cda5da8dSAndroid Build Coastguard Worker            pathext = [os.fsencode(ext) for ext in pathext]
1504*cda5da8dSAndroid Build Coastguard Worker        # See if the given file matches any of the expected path extensions.
1505*cda5da8dSAndroid Build Coastguard Worker        # This will allow us to short circuit when given "python.exe".
1506*cda5da8dSAndroid Build Coastguard Worker        # If it does match, only test that one, otherwise we have to try
1507*cda5da8dSAndroid Build Coastguard Worker        # others.
1508*cda5da8dSAndroid Build Coastguard Worker        if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
1509*cda5da8dSAndroid Build Coastguard Worker            files = [cmd]
1510*cda5da8dSAndroid Build Coastguard Worker        else:
1511*cda5da8dSAndroid Build Coastguard Worker            files = [cmd + ext for ext in pathext]
1512*cda5da8dSAndroid Build Coastguard Worker    else:
1513*cda5da8dSAndroid Build Coastguard Worker        # On other platforms you don't have things like PATHEXT to tell you
1514*cda5da8dSAndroid Build Coastguard Worker        # what file suffixes are executable, so just pass on cmd as-is.
1515*cda5da8dSAndroid Build Coastguard Worker        files = [cmd]
1516*cda5da8dSAndroid Build Coastguard Worker
1517*cda5da8dSAndroid Build Coastguard Worker    seen = set()
1518*cda5da8dSAndroid Build Coastguard Worker    for dir in path:
1519*cda5da8dSAndroid Build Coastguard Worker        normdir = os.path.normcase(dir)
1520*cda5da8dSAndroid Build Coastguard Worker        if not normdir in seen:
1521*cda5da8dSAndroid Build Coastguard Worker            seen.add(normdir)
1522*cda5da8dSAndroid Build Coastguard Worker            for thefile in files:
1523*cda5da8dSAndroid Build Coastguard Worker                name = os.path.join(dir, thefile)
1524*cda5da8dSAndroid Build Coastguard Worker                if _access_check(name, mode):
1525*cda5da8dSAndroid Build Coastguard Worker                    return name
1526*cda5da8dSAndroid Build Coastguard Worker    return None
1527