blob: d767a0c94542a165dcae7a7a1198d80a03b8022e [file] [log] [blame]
Tarek Ziadéc3399782010-02-23 05:39:18 +00001"""Utility functions for copying and archiving files and directory trees.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +00002
Guido van Rossum959fa011999-08-18 20:03:17 +00003XXX The functions here don't copy the resource fork or other metadata on Mac.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +00004
5"""
Guido van Rossumc6360141990-10-13 19:23:40 +00006
Guido van Rossumc96207a1992-03-31 18:55:40 +00007import os
Guido van Rossum83c03e21999-02-23 23:07:51 +00008import sys
Guido van Rossum9d0a3df1997-04-29 14:45:19 +00009import stat
Brett Cannon1c3fa182004-06-19 21:11:35 +000010from os.path import abspath
Georg Brandl2ee470f2008-07-16 12:55:28 +000011import fnmatch
Tarek Ziadé396fad72010-02-23 05:30:31 +000012import collections
Antoine Pitrou910bd512010-03-22 20:11:09 +000013import errno
Tarek Ziadé6ac91722010-04-28 17:51:36 +000014import tarfile
Tarek Ziadé396fad72010-02-23 05:30:31 +000015
16try:
Tarek Ziadéffa155a2010-04-29 13:34:35 +000017 import bz2
Florent Xicluna54540ec2011-11-04 08:29:17 +010018 del bz2
Tarek Ziadéffa155a2010-04-29 13:34:35 +000019 _BZ2_SUPPORTED = True
Brett Cannoncd171c82013-07-04 17:43:24 -040020except ImportError:
Tarek Ziadéffa155a2010-04-29 13:34:35 +000021 _BZ2_SUPPORTED = False
22
23try:
Tarek Ziadé396fad72010-02-23 05:30:31 +000024 from pwd import getpwnam
Brett Cannoncd171c82013-07-04 17:43:24 -040025except ImportError:
Tarek Ziadé396fad72010-02-23 05:30:31 +000026 getpwnam = None
27
28try:
29 from grp import getgrnam
Brett Cannoncd171c82013-07-04 17:43:24 -040030except ImportError:
Tarek Ziadé396fad72010-02-23 05:30:31 +000031 getgrnam = None
Guido van Rossumc6360141990-10-13 19:23:40 +000032
Tarek Ziadéc3399782010-02-23 05:39:18 +000033__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
34 "copytree", "move", "rmtree", "Error", "SpecialFileError",
35 "ExecError", "make_archive", "get_archive_formats",
Tarek Ziadé6ac91722010-04-28 17:51:36 +000036 "register_archive_format", "unregister_archive_format",
37 "get_unpack_formats", "register_unpack_format",
Éric Araujoc5efe652011-08-21 14:30:00 +020038 "unregister_unpack_format", "unpack_archive",
Berker Peksag8083cd62014-11-01 11:04:06 +020039 "ignore_patterns", "chown", "which", "get_terminal_size",
40 "SameFileError"]
Éric Araujoe4d5b8e2011-08-08 16:51:11 +020041 # disk_usage is added later, if available on the platform
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000042
Andrew Svetlov3438fa42012-12-17 23:35:18 +020043class Error(OSError):
Martin v. Löwise9ce0b02002-10-07 13:23:24 +000044 pass
Guido van Rossumc6360141990-10-13 19:23:40 +000045
Hynek Schlawack48653762012-10-07 12:49:58 +020046class SameFileError(Error):
47 """Raised when source and destination are the same file."""
48
Andrew Svetlov3438fa42012-12-17 23:35:18 +020049class SpecialFileError(OSError):
Antoine Pitrou7fff0962009-05-01 21:09:44 +000050 """Raised when trying to do a kind of operation (e.g. copying) which is
51 not supported on a special file (e.g. a named pipe)"""
52
Andrew Svetlov3438fa42012-12-17 23:35:18 +020053class ExecError(OSError):
Tarek Ziadé396fad72010-02-23 05:30:31 +000054 """Raised when a command could not be executed"""
55
Andrew Svetlov3438fa42012-12-17 23:35:18 +020056class ReadError(OSError):
Tarek Ziadé6ac91722010-04-28 17:51:36 +000057 """Raised when an archive cannot be read"""
58
59class RegistryError(Exception):
Ezio Melotti30b9d5d2013-08-17 15:50:46 +030060 """Raised when a registry operation with the archiving
Tarek Ziadé6ac91722010-04-28 17:51:36 +000061 and unpacking registeries fails"""
62
63
Greg Stein42bb8b32000-07-12 09:55:30 +000064def copyfileobj(fsrc, fdst, length=16*1024):
65 """copy data from file-like object fsrc to file-like object fdst"""
66 while 1:
67 buf = fsrc.read(length)
68 if not buf:
69 break
70 fdst.write(buf)
71
Johannes Gijsbers46f14592004-08-14 13:30:02 +000072def _samefile(src, dst):
73 # Macintosh, Unix.
Tarek Ziadé1eab9cc2010-04-19 21:19:57 +000074 if hasattr(os.path, 'samefile'):
Johannes Gijsbersf9a098e2004-08-14 14:51:01 +000075 try:
76 return os.path.samefile(src, dst)
77 except OSError:
78 return False
Johannes Gijsbers46f14592004-08-14 13:30:02 +000079
80 # All other platforms: check for same pathname.
81 return (os.path.normcase(os.path.abspath(src)) ==
82 os.path.normcase(os.path.abspath(dst)))
Tim Peters495ad3c2001-01-15 01:36:40 +000083
Larry Hastingsb4038062012-07-15 10:57:38 -070084def copyfile(src, dst, *, follow_symlinks=True):
Antoine Pitrou78091e62011-12-29 18:54:15 +010085 """Copy data from src to dst.
86
Larry Hastingsb4038062012-07-15 10:57:38 -070087 If follow_symlinks is not set and src is a symbolic link, a new
Antoine Pitrou78091e62011-12-29 18:54:15 +010088 symlink will be created instead of copying the file it points to.
89
90 """
Johannes Gijsbers46f14592004-08-14 13:30:02 +000091 if _samefile(src, dst):
Hynek Schlawack48653762012-10-07 12:49:58 +020092 raise SameFileError("{!r} and {!r} are the same file".format(src, dst))
Johannes Gijsbers46f14592004-08-14 13:30:02 +000093
Antoine Pitrou7fff0962009-05-01 21:09:44 +000094 for fn in [src, dst]:
95 try:
96 st = os.stat(fn)
97 except OSError:
98 # File most likely does not exist
99 pass
Benjamin Petersonc0d98aa2009-06-05 19:13:27 +0000100 else:
101 # XXX What about other special files? (sockets, devices...)
102 if stat.S_ISFIFO(st.st_mode):
103 raise SpecialFileError("`%s` is a named pipe" % fn)
Tarek Ziadéb01142b2010-05-05 22:43:04 +0000104
Larry Hastingsb4038062012-07-15 10:57:38 -0700105 if not follow_symlinks and os.path.islink(src):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100106 os.symlink(os.readlink(src), dst)
107 else:
108 with open(src, 'rb') as fsrc:
109 with open(dst, 'wb') as fdst:
110 copyfileobj(fsrc, fdst)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500111 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000112
Larry Hastingsb4038062012-07-15 10:57:38 -0700113def copymode(src, dst, *, follow_symlinks=True):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100114 """Copy mode bits from src to dst.
Guido van Rossumc6360141990-10-13 19:23:40 +0000115
Larry Hastingsb4038062012-07-15 10:57:38 -0700116 If follow_symlinks is not set, symlinks aren't followed if and only
117 if both `src` and `dst` are symlinks. If `lchmod` isn't available
118 (e.g. Linux) this method does nothing.
Antoine Pitrou78091e62011-12-29 18:54:15 +0100119
120 """
Larry Hastingsb4038062012-07-15 10:57:38 -0700121 if not follow_symlinks and os.path.islink(src) and os.path.islink(dst):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100122 if hasattr(os, 'lchmod'):
123 stat_func, chmod_func = os.lstat, os.lchmod
124 else:
125 return
126 elif hasattr(os, 'chmod'):
127 stat_func, chmod_func = os.stat, os.chmod
128 else:
129 return
130
131 st = stat_func(src)
132 chmod_func(dst, stat.S_IMODE(st.st_mode))
133
Larry Hastingsad5ae042012-07-14 17:55:11 -0700134if hasattr(os, 'listxattr'):
Larry Hastingsb4038062012-07-15 10:57:38 -0700135 def _copyxattr(src, dst, *, follow_symlinks=True):
Larry Hastingsad5ae042012-07-14 17:55:11 -0700136 """Copy extended filesystem attributes from `src` to `dst`.
137
138 Overwrite existing attributes.
139
Larry Hastingsb4038062012-07-15 10:57:38 -0700140 If `follow_symlinks` is false, symlinks won't be followed.
Larry Hastingsad5ae042012-07-14 17:55:11 -0700141
142 """
143
Hynek Schlawack0beab052013-02-05 08:22:44 +0100144 try:
145 names = os.listxattr(src, follow_symlinks=follow_symlinks)
146 except OSError as e:
147 if e.errno not in (errno.ENOTSUP, errno.ENODATA):
148 raise
149 return
150 for name in names:
Larry Hastingsad5ae042012-07-14 17:55:11 -0700151 try:
Larry Hastingsb4038062012-07-15 10:57:38 -0700152 value = os.getxattr(src, name, follow_symlinks=follow_symlinks)
153 os.setxattr(dst, name, value, follow_symlinks=follow_symlinks)
Larry Hastingsad5ae042012-07-14 17:55:11 -0700154 except OSError as e:
155 if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA):
156 raise
157else:
158 def _copyxattr(*args, **kwargs):
159 pass
160
Larry Hastingsb4038062012-07-15 10:57:38 -0700161def copystat(src, dst, *, follow_symlinks=True):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100162 """Copy all stat info (mode bits, atime, mtime, flags) from src to dst.
163
Larry Hastingsb4038062012-07-15 10:57:38 -0700164 If the optional flag `follow_symlinks` is not set, symlinks aren't followed if and
Antoine Pitrou78091e62011-12-29 18:54:15 +0100165 only if both `src` and `dst` are symlinks.
166
167 """
Larry Hastings9cf065c2012-06-22 16:30:09 -0700168 def _nop(*args, ns=None, follow_symlinks=None):
Antoine Pitrou78091e62011-12-29 18:54:15 +0100169 pass
170
Larry Hastings9cf065c2012-06-22 16:30:09 -0700171 # follow symlinks (aka don't not follow symlinks)
Larry Hastingsb4038062012-07-15 10:57:38 -0700172 follow = follow_symlinks or not (os.path.islink(src) and os.path.islink(dst))
Larry Hastings9cf065c2012-06-22 16:30:09 -0700173 if follow:
174 # use the real function if it exists
175 def lookup(name):
176 return getattr(os, name, _nop)
Antoine Pitrou78091e62011-12-29 18:54:15 +0100177 else:
Larry Hastings9cf065c2012-06-22 16:30:09 -0700178 # use the real function only if it exists
179 # *and* it supports follow_symlinks
180 def lookup(name):
181 fn = getattr(os, name, _nop)
182 if fn in os.supports_follow_symlinks:
183 return fn
184 return _nop
Antoine Pitrou78091e62011-12-29 18:54:15 +0100185
Larry Hastings9cf065c2012-06-22 16:30:09 -0700186 st = lookup("stat")(src, follow_symlinks=follow)
Walter Dörwald294bbf32002-06-06 09:48:13 +0000187 mode = stat.S_IMODE(st.st_mode)
Larry Hastings9cf065c2012-06-22 16:30:09 -0700188 lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns),
189 follow_symlinks=follow)
190 try:
191 lookup("chmod")(dst, mode, follow_symlinks=follow)
192 except NotImplementedError:
193 # if we got a NotImplementedError, it's because
194 # * follow_symlinks=False,
195 # * lchown() is unavailable, and
196 # * either
Ezio Melotti30b9d5d2013-08-17 15:50:46 +0300197 # * fchownat() is unavailable or
Larry Hastings9cf065c2012-06-22 16:30:09 -0700198 # * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW.
199 # (it returned ENOSUP.)
200 # therefore we're out of options--we simply cannot chown the
201 # symlink. give up, suppress the error.
202 # (which is what shutil always did in this circumstance.)
203 pass
Antoine Pitrou78091e62011-12-29 18:54:15 +0100204 if hasattr(st, 'st_flags'):
Antoine Pitrou910bd512010-03-22 20:11:09 +0000205 try:
Larry Hastings9cf065c2012-06-22 16:30:09 -0700206 lookup("chflags")(dst, st.st_flags, follow_symlinks=follow)
Antoine Pitrou910bd512010-03-22 20:11:09 +0000207 except OSError as why:
Ned Deilybaf75712012-05-10 17:05:19 -0700208 for err in 'EOPNOTSUPP', 'ENOTSUP':
209 if hasattr(errno, err) and why.errno == getattr(errno, err):
210 break
211 else:
Antoine Pitrou910bd512010-03-22 20:11:09 +0000212 raise
Larry Hastingsb4038062012-07-15 10:57:38 -0700213 _copyxattr(src, dst, follow_symlinks=follow)
Antoine Pitrou424246f2012-05-12 19:02:01 +0200214
Larry Hastingsb4038062012-07-15 10:57:38 -0700215def copy(src, dst, *, follow_symlinks=True):
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500216 """Copy data and mode bits ("cp src dst"). Return the file's destination.
Tim Peters495ad3c2001-01-15 01:36:40 +0000217
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000218 The destination may be a directory.
219
Larry Hastingsb4038062012-07-15 10:57:38 -0700220 If follow_symlinks is false, symlinks won't be followed. This
Antoine Pitrou78091e62011-12-29 18:54:15 +0100221 resembles GNU's "cp -P src dst".
222
Hynek Schlawack48653762012-10-07 12:49:58 +0200223 If source and destination are the same file, a SameFileError will be
224 raised.
225
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000226 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000227 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000228 dst = os.path.join(dst, os.path.basename(src))
Larry Hastingsb4038062012-07-15 10:57:38 -0700229 copyfile(src, dst, follow_symlinks=follow_symlinks)
230 copymode(src, dst, follow_symlinks=follow_symlinks)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500231 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000232
Larry Hastingsb4038062012-07-15 10:57:38 -0700233def copy2(src, dst, *, follow_symlinks=True):
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500234 """Copy data and all stat info ("cp -p src dst"). Return the file's
235 destination."
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000236
237 The destination may be a directory.
238
Larry Hastingsb4038062012-07-15 10:57:38 -0700239 If follow_symlinks is false, symlinks won't be followed. This
Antoine Pitrou78091e62011-12-29 18:54:15 +0100240 resembles GNU's "cp -P src dst".
241
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000242 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000243 if os.path.isdir(dst):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000244 dst = os.path.join(dst, os.path.basename(src))
Larry Hastingsb4038062012-07-15 10:57:38 -0700245 copyfile(src, dst, follow_symlinks=follow_symlinks)
246 copystat(src, dst, follow_symlinks=follow_symlinks)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500247 return dst
Guido van Rossumc6360141990-10-13 19:23:40 +0000248
Georg Brandl2ee470f2008-07-16 12:55:28 +0000249def ignore_patterns(*patterns):
250 """Function that can be used as copytree() ignore parameter.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000251
Georg Brandl2ee470f2008-07-16 12:55:28 +0000252 Patterns is a sequence of glob-style patterns
253 that are used to exclude files"""
254 def _ignore_patterns(path, names):
255 ignored_names = []
256 for pattern in patterns:
257 ignored_names.extend(fnmatch.filter(names, pattern))
258 return set(ignored_names)
259 return _ignore_patterns
260
Tarek Ziadéfb437512010-04-20 08:57:33 +0000261def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
262 ignore_dangling_symlinks=False):
Tarek Ziadé5340db32010-04-19 22:30:51 +0000263 """Recursively copy a directory tree.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000264
265 The destination directory must not already exist.
Neal Norwitza4c93b62003-02-23 21:36:32 +0000266 If exception(s) occur, an Error is raised with a list of reasons.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000267
268 If the optional symlinks flag is true, symbolic links in the
269 source tree result in symbolic links in the destination tree; if
270 it is false, the contents of the files pointed to by symbolic
Tarek Ziadéfb437512010-04-20 08:57:33 +0000271 links are copied. If the file pointed by the symlink doesn't
272 exist, an exception will be added in the list of errors raised in
273 an Error exception at the end of the copy process.
274
275 You can set the optional ignore_dangling_symlinks flag to true if you
Tarek Ziadé8c26c7d2010-04-23 13:03:50 +0000276 want to silence this exception. Notice that this has no effect on
277 platforms that don't support os.symlink.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000278
Georg Brandl2ee470f2008-07-16 12:55:28 +0000279 The optional ignore argument is a callable. If given, it
280 is called with the `src` parameter, which is the directory
281 being visited by copytree(), and `names` which is the list of
282 `src` contents, as returned by os.listdir():
283
284 callable(src, names) -> ignored_names
285
286 Since copytree() is called recursively, the callable will be
287 called once for each directory that is copied. It returns a
288 list of names relative to the `src` directory that should
289 not be copied.
290
Tarek Ziadé5340db32010-04-19 22:30:51 +0000291 The optional copy_function argument is a callable that will be used
292 to copy each file. It will be called with the source path and the
293 destination path as arguments. By default, copy2() is used, but any
294 function that supports the same signature (like copy()) can be used.
Guido van Rossum9d0a3df1997-04-29 14:45:19 +0000295
296 """
Guido van Rossuma2baf461997-04-29 14:06:46 +0000297 names = os.listdir(src)
Georg Brandl2ee470f2008-07-16 12:55:28 +0000298 if ignore is not None:
299 ignored_names = ignore(src, names)
300 else:
301 ignored_names = set()
302
Johannes Gijsberse4172ea2005-01-08 12:31:29 +0000303 os.makedirs(dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000304 errors = []
Guido van Rossuma2baf461997-04-29 14:06:46 +0000305 for name in names:
Georg Brandl2ee470f2008-07-16 12:55:28 +0000306 if name in ignored_names:
307 continue
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000308 srcname = os.path.join(src, name)
309 dstname = os.path.join(dst, name)
310 try:
Tarek Ziadéfb437512010-04-20 08:57:33 +0000311 if os.path.islink(srcname):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000312 linkto = os.readlink(srcname)
Tarek Ziadéfb437512010-04-20 08:57:33 +0000313 if symlinks:
Antoine Pitrou78091e62011-12-29 18:54:15 +0100314 # We can't just leave it to `copy_function` because legacy
315 # code with a custom `copy_function` may rely on copytree
316 # doing the right thing.
Tarek Ziadéfb437512010-04-20 08:57:33 +0000317 os.symlink(linkto, dstname)
Larry Hastingsb4038062012-07-15 10:57:38 -0700318 copystat(srcname, dstname, follow_symlinks=not symlinks)
Tarek Ziadéfb437512010-04-20 08:57:33 +0000319 else:
320 # ignore dangling symlink if the flag is on
321 if not os.path.exists(linkto) and ignore_dangling_symlinks:
322 continue
323 # otherwise let the copy occurs. copy2 will raise an error
Berker Peksag5a294d82015-07-25 14:53:48 +0300324 if os.path.isdir(srcname):
325 copytree(srcname, dstname, symlinks, ignore,
326 copy_function)
327 else:
328 copy_function(srcname, dstname)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000329 elif os.path.isdir(srcname):
Tarek Ziadé5340db32010-04-19 22:30:51 +0000330 copytree(srcname, dstname, symlinks, ignore, copy_function)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000331 else:
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000332 # Will raise a SpecialFileError for unsupported file types
Tarek Ziadé5340db32010-04-19 22:30:51 +0000333 copy_function(srcname, dstname)
Georg Brandla1be88e2005-08-31 22:48:45 +0000334 # catch the Error from the recursive copytree so that we can
335 # continue with other files
Guido van Rossumb940e112007-01-10 16:19:56 +0000336 except Error as err:
Georg Brandla1be88e2005-08-31 22:48:45 +0000337 errors.extend(err.args[0])
Andrew Svetlov3438fa42012-12-17 23:35:18 +0200338 except OSError as why:
Antoine Pitrou7fff0962009-05-01 21:09:44 +0000339 errors.append((srcname, dstname, str(why)))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000340 try:
341 copystat(src, dst)
Guido van Rossumb940e112007-01-10 16:19:56 +0000342 except OSError as why:
Andrew Svetlov2606a6f2012-12-19 14:33:35 +0200343 # Copying file access times may fail on Windows
Berker Peksag884afd92014-12-10 02:50:32 +0200344 if getattr(why, 'winerror', None) is None:
Georg Brandlc8076df2012-08-25 10:11:57 +0200345 errors.append((src, dst, str(why)))
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000346 if errors:
Collin Winterce36ad82007-08-30 01:19:48 +0000347 raise Error(errors)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500348 return dst
Guido van Rossumd7673291998-02-06 21:38:09 +0000349
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200350# version vulnerable to race conditions
351def _rmtree_unsafe(path, onerror):
Christian Heimes9bd667a2008-01-20 15:14:11 +0000352 try:
353 if os.path.islink(path):
354 # symlinks to directories are forbidden, see bug #1669
355 raise OSError("Cannot call rmtree on a symbolic link")
356 except OSError:
357 onerror(os.path.islink, path, sys.exc_info())
358 # can't continue even if onerror hook returns
359 return
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000360 names = []
361 try:
362 names = os.listdir(path)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200363 except OSError:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000364 onerror(os.listdir, path, sys.exc_info())
365 for name in names:
366 fullname = os.path.join(path, name)
367 try:
368 mode = os.lstat(fullname).st_mode
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200369 except OSError:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000370 mode = 0
371 if stat.S_ISDIR(mode):
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200372 _rmtree_unsafe(fullname, onerror)
Barry Warsaw234d9a92003-01-24 17:36:15 +0000373 else:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000374 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200375 os.unlink(fullname)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200376 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200377 onerror(os.unlink, fullname, sys.exc_info())
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000378 try:
379 os.rmdir(path)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200380 except OSError:
Johannes Gijsbersef5ffc42004-10-31 12:05:31 +0000381 onerror(os.rmdir, path, sys.exc_info())
Guido van Rossumd7673291998-02-06 21:38:09 +0000382
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200383# Version using fd-based APIs to protect against races
384def _rmtree_safe_fd(topfd, path, onerror):
385 names = []
386 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200387 names = os.listdir(topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100388 except OSError as err:
389 err.filename = path
Hynek Schlawack2100b422012-06-23 20:28:32 +0200390 onerror(os.listdir, path, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200391 for name in names:
392 fullname = os.path.join(path, name)
393 try:
Hynek Schlawacka75cd1c2012-06-28 12:07:29 +0200394 orig_st = os.stat(name, dir_fd=topfd, follow_symlinks=False)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200395 mode = orig_st.st_mode
Hynek Schlawackb5501102012-12-10 09:11:25 +0100396 except OSError:
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200397 mode = 0
398 if stat.S_ISDIR(mode):
399 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200400 dirfd = os.open(name, os.O_RDONLY, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100401 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200402 onerror(os.open, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200403 else:
404 try:
405 if os.path.samestat(orig_st, os.fstat(dirfd)):
406 _rmtree_safe_fd(dirfd, fullname, onerror)
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200407 try:
408 os.rmdir(name, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100409 except OSError:
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200410 onerror(os.rmdir, fullname, sys.exc_info())
Hynek Schlawackb5501102012-12-10 09:11:25 +0100411 else:
412 try:
413 # This can only happen if someone replaces
414 # a directory with a symlink after the call to
415 # stat.S_ISDIR above.
416 raise OSError("Cannot call rmtree on a symbolic "
417 "link")
418 except OSError:
419 onerror(os.path.islink, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200420 finally:
421 os.close(dirfd)
422 else:
423 try:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200424 os.unlink(name, dir_fd=topfd)
Hynek Schlawackb5501102012-12-10 09:11:25 +0100425 except OSError:
Hynek Schlawack2100b422012-06-23 20:28:32 +0200426 onerror(os.unlink, fullname, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200427
Hynek Schlawackd0f6e0a2012-06-29 08:28:20 +0200428_use_fd_functions = ({os.open, os.stat, os.unlink, os.rmdir} <=
429 os.supports_dir_fd and
430 os.listdir in os.supports_fd and
431 os.stat in os.supports_follow_symlinks)
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000432
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200433def rmtree(path, ignore_errors=False, onerror=None):
434 """Recursively delete a directory tree.
435
436 If ignore_errors is set, errors are ignored; otherwise, if onerror
437 is set, it is called to handle the error with arguments (func,
Hynek Schlawack2100b422012-06-23 20:28:32 +0200438 path, exc_info) where func is platform and implementation dependent;
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200439 path is the argument to that function that caused it to fail; and
440 exc_info is a tuple returned by sys.exc_info(). If ignore_errors
441 is false and onerror is None, an exception is raised.
442
443 """
444 if ignore_errors:
445 def onerror(*args):
446 pass
447 elif onerror is None:
448 def onerror(*args):
449 raise
450 if _use_fd_functions:
Hynek Schlawack3b527782012-06-25 13:27:31 +0200451 # While the unsafe rmtree works fine on bytes, the fd based does not.
452 if isinstance(path, bytes):
453 path = os.fsdecode(path)
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200454 # Note: To guard against symlink races, we use the standard
455 # lstat()/open()/fstat() trick.
456 try:
457 orig_st = os.lstat(path)
458 except Exception:
459 onerror(os.lstat, path, sys.exc_info())
460 return
461 try:
462 fd = os.open(path, os.O_RDONLY)
463 except Exception:
464 onerror(os.lstat, path, sys.exc_info())
465 return
466 try:
Hynek Schlawackb5501102012-12-10 09:11:25 +0100467 if os.path.samestat(orig_st, os.fstat(fd)):
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200468 _rmtree_safe_fd(fd, path, onerror)
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200469 try:
470 os.rmdir(path)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200471 except OSError:
Hynek Schlawack9f558cc2012-06-28 15:30:47 +0200472 onerror(os.rmdir, path, sys.exc_info())
Hynek Schlawacka75cd1c2012-06-28 12:07:29 +0200473 else:
Hynek Schlawackb5501102012-12-10 09:11:25 +0100474 try:
475 # symlinks to directories are forbidden, see bug #1669
476 raise OSError("Cannot call rmtree on a symbolic link")
477 except OSError:
478 onerror(os.path.islink, path, sys.exc_info())
Hynek Schlawack67be92b2012-06-23 17:58:42 +0200479 finally:
480 os.close(fd)
481 else:
482 return _rmtree_unsafe(path, onerror)
483
Nick Coghlan5b0eca12012-06-24 16:43:06 +1000484# Allow introspection of whether or not the hardening against symlink
485# attacks is supported on the current platform
486rmtree.avoids_symlink_attacks = _use_fd_functions
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000487
Christian Heimesada8c3b2008-03-18 18:26:33 +0000488def _basename(path):
489 # A basename() variant which first strips the trailing slash, if present.
490 # Thus we always get the last component of the path, even for directories.
Serhiy Storchaka3a308b92014-02-11 10:30:59 +0200491 sep = os.path.sep + (os.path.altsep or '')
492 return os.path.basename(path.rstrip(sep))
Christian Heimesada8c3b2008-03-18 18:26:33 +0000493
494def move(src, dst):
495 """Recursively move a file or directory to another location. This is
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500496 similar to the Unix "mv" command. Return the file or directory's
497 destination.
Christian Heimesada8c3b2008-03-18 18:26:33 +0000498
499 If the destination is a directory or a symlink to a directory, the source
500 is moved inside the directory. The destination path must not already
501 exist.
502
503 If the destination already exists but is not a directory, it may be
504 overwritten depending on os.rename() semantics.
505
506 If the destination is on our current filesystem, then rename() is used.
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +0100507 Otherwise, src is copied to the destination and then removed. Symlinks are
508 recreated under the new name if os.rename() fails because of cross
509 filesystem renames.
510
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000511 A lot more could be done here... A look at a mv.c shows a lot of
512 the issues this implementation glosses over.
513
514 """
Christian Heimesada8c3b2008-03-18 18:26:33 +0000515 real_dst = dst
516 if os.path.isdir(dst):
Ronald Oussorenf51738b2011-05-06 10:23:04 +0200517 if _samefile(src, dst):
518 # We might be on a case insensitive filesystem,
519 # perform the rename anyway.
520 os.rename(src, dst)
521 return
522
Christian Heimesada8c3b2008-03-18 18:26:33 +0000523 real_dst = os.path.join(dst, _basename(src))
524 if os.path.exists(real_dst):
525 raise Error("Destination path '%s' already exists" % real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000526 try:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000527 os.rename(src, real_dst)
Éric Araujocfcc9772011-08-10 20:54:33 +0200528 except OSError:
Antoine Pitrou0a08d7a2012-01-06 20:16:19 +0100529 if os.path.islink(src):
530 linkto = os.readlink(src)
531 os.symlink(linkto, real_dst)
532 os.unlink(src)
533 elif os.path.isdir(src):
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000534 if _destinsrc(src, dst):
Collin Winterce36ad82007-08-30 01:19:48 +0000535 raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst))
Christian Heimesada8c3b2008-03-18 18:26:33 +0000536 copytree(src, real_dst, symlinks=True)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000537 rmtree(src)
538 else:
Christian Heimesada8c3b2008-03-18 18:26:33 +0000539 copy2(src, real_dst)
Martin v. Löwise9ce0b02002-10-07 13:23:24 +0000540 os.unlink(src)
Brian Curtin0d0a1de2012-06-18 18:41:07 -0500541 return real_dst
Brett Cannon1c3fa182004-06-19 21:11:35 +0000542
Benjamin Peterson247a9b82009-02-20 04:09:19 +0000543def _destinsrc(src, dst):
Antoine Pitrou0dcc3cd2009-01-29 20:26:59 +0000544 src = abspath(src)
545 dst = abspath(dst)
546 if not src.endswith(os.path.sep):
547 src += os.path.sep
548 if not dst.endswith(os.path.sep):
549 dst += os.path.sep
550 return dst.startswith(src)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000551
552def _get_gid(name):
553 """Returns a gid, given a group name."""
554 if getgrnam is None or name is None:
555 return None
556 try:
557 result = getgrnam(name)
558 except KeyError:
559 result = None
560 if result is not None:
561 return result[2]
562 return None
563
564def _get_uid(name):
565 """Returns an uid, given a user name."""
566 if getpwnam is None or name is None:
567 return None
568 try:
569 result = getpwnam(name)
570 except KeyError:
571 result = None
572 if result is not None:
573 return result[2]
574 return None
575
576def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
577 owner=None, group=None, logger=None):
578 """Create a (possibly compressed) tar file from all the files under
579 'base_dir'.
580
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000581 'compress' must be "gzip" (the default), "bzip2", or None.
Tarek Ziadé396fad72010-02-23 05:30:31 +0000582
583 'owner' and 'group' can be used to define an owner and a group for the
584 archive that is being built. If not provided, the current owner and group
585 will be used.
586
Éric Araujo4433a5f2010-12-15 20:26:30 +0000587 The output tar file will be named 'base_name' + ".tar", possibly plus
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000588 the appropriate compression extension (".gz", or ".bz2").
Tarek Ziadé396fad72010-02-23 05:30:31 +0000589
590 Returns the output filename.
591 """
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000592 tar_compression = {'gzip': 'gz', None: ''}
593 compress_ext = {'gzip': '.gz'}
594
595 if _BZ2_SUPPORTED:
596 tar_compression['bzip2'] = 'bz2'
597 compress_ext['bzip2'] = '.bz2'
Tarek Ziadé396fad72010-02-23 05:30:31 +0000598
599 # flags for compression program, each element of list will be an argument
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200600 if compress is not None and compress not in compress_ext:
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000601 raise ValueError("bad value for 'compress', or compression format not "
602 "supported : {0}".format(compress))
Tarek Ziadé396fad72010-02-23 05:30:31 +0000603
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000604 archive_name = base_name + '.tar' + compress_ext.get(compress, '')
Tarek Ziadé396fad72010-02-23 05:30:31 +0000605 archive_dir = os.path.dirname(archive_name)
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000606
Serhiy Storchaka9a4fc192014-11-28 00:48:46 +0200607 if archive_dir and not os.path.exists(archive_dir):
Éric Araujoac4e58e2011-01-29 20:32:11 +0000608 if logger is not None:
Éric Araujo43a7ee12011-08-19 02:55:11 +0200609 logger.info("creating %s", archive_dir)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000610 if not dry_run:
611 os.makedirs(archive_dir)
612
Tarek Ziadé396fad72010-02-23 05:30:31 +0000613 # creating the tarball
Tarek Ziadé396fad72010-02-23 05:30:31 +0000614 if logger is not None:
615 logger.info('Creating tar archive')
616
617 uid = _get_uid(owner)
618 gid = _get_gid(group)
619
620 def _set_uid_gid(tarinfo):
621 if gid is not None:
622 tarinfo.gid = gid
623 tarinfo.gname = group
624 if uid is not None:
625 tarinfo.uid = uid
626 tarinfo.uname = owner
627 return tarinfo
628
629 if not dry_run:
630 tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress])
631 try:
632 tar.add(base_dir, filter=_set_uid_gid)
633 finally:
634 tar.close()
635
Tarek Ziadé396fad72010-02-23 05:30:31 +0000636 return archive_name
637
Tarek Ziadée2124162010-04-21 13:35:21 +0000638def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False):
Tarek Ziadé396fad72010-02-23 05:30:31 +0000639 # XXX see if we want to keep an external call here
640 if verbose:
641 zipoptions = "-r"
642 else:
643 zipoptions = "-rq"
644 from distutils.errors import DistutilsExecError
645 from distutils.spawn import spawn
646 try:
647 spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run)
648 except DistutilsExecError:
649 # XXX really should distinguish between "couldn't find
650 # external 'zip' command" and "zip failed".
651 raise ExecError("unable to create zip file '%s': "
652 "could neither import the 'zipfile' module nor "
653 "find a standalone zip utility") % zip_filename
654
655def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
656 """Create a zip file from all the files under 'base_dir'.
657
Éric Araujo4433a5f2010-12-15 20:26:30 +0000658 The output zip file will be named 'base_name' + ".zip". Uses either the
Tarek Ziadé396fad72010-02-23 05:30:31 +0000659 "zipfile" Python module (if available) or the InfoZIP "zip" utility
660 (if installed and found on the default search path). If neither tool is
661 available, raises ExecError. Returns the name of the output zip
662 file.
663 """
664 zip_filename = base_name + ".zip"
665 archive_dir = os.path.dirname(base_name)
666
Serhiy Storchaka9a4fc192014-11-28 00:48:46 +0200667 if archive_dir and not os.path.exists(archive_dir):
Tarek Ziadé396fad72010-02-23 05:30:31 +0000668 if logger is not None:
669 logger.info("creating %s", archive_dir)
670 if not dry_run:
671 os.makedirs(archive_dir)
672
673 # If zipfile module is not available, try spawning an external 'zip'
674 # command.
675 try:
676 import zipfile
Brett Cannoncd171c82013-07-04 17:43:24 -0400677 except ImportError:
Tarek Ziadé396fad72010-02-23 05:30:31 +0000678 zipfile = None
679
680 if zipfile is None:
Tarek Ziadée2124162010-04-21 13:35:21 +0000681 _call_external_zip(base_dir, zip_filename, verbose, dry_run)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000682 else:
683 if logger is not None:
684 logger.info("creating '%s' and adding '%s' to it",
685 zip_filename, base_dir)
686
687 if not dry_run:
Benjamin Peterson091d3862014-02-02 15:30:22 -0500688 with zipfile.ZipFile(zip_filename, "w",
689 compression=zipfile.ZIP_DEFLATED) as zf:
Serhiy Storchaka2504cec2015-09-08 05:47:23 +0300690 path = os.path.normpath(base_dir)
691 zf.write(path, path)
692 if logger is not None:
693 logger.info("adding '%s'", path)
Benjamin Peterson091d3862014-02-02 15:30:22 -0500694 for dirpath, dirnames, filenames in os.walk(base_dir):
Serhiy Storchaka2504cec2015-09-08 05:47:23 +0300695 for name in sorted(dirnames):
696 path = os.path.normpath(os.path.join(dirpath, name))
697 zf.write(path, path)
698 if logger is not None:
699 logger.info("adding '%s'", path)
Benjamin Peterson091d3862014-02-02 15:30:22 -0500700 for name in filenames:
701 path = os.path.normpath(os.path.join(dirpath, name))
702 if os.path.isfile(path):
703 zf.write(path, path)
704 if logger is not None:
705 logger.info("adding '%s'", path)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000706
707 return zip_filename
708
709_ARCHIVE_FORMATS = {
710 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"),
Tarek Ziadé396fad72010-02-23 05:30:31 +0000711 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"),
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200712 'zip': (_make_zipfile, [], "ZIP file")
Tarek Ziadé396fad72010-02-23 05:30:31 +0000713 }
714
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000715if _BZ2_SUPPORTED:
716 _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')],
717 "bzip2'ed tar-file")
718
Tarek Ziadé396fad72010-02-23 05:30:31 +0000719def get_archive_formats():
720 """Returns a list of supported formats for archiving and unarchiving.
721
722 Each element of the returned sequence is a tuple (name, description)
723 """
724 formats = [(name, registry[2]) for name, registry in
725 _ARCHIVE_FORMATS.items()]
726 formats.sort()
727 return formats
728
729def register_archive_format(name, function, extra_args=None, description=''):
730 """Registers an archive format.
731
732 name is the name of the format. function is the callable that will be
733 used to create archives. If provided, extra_args is a sequence of
734 (name, value) tuples that will be passed as arguments to the callable.
735 description can be provided to describe the format, and will be returned
736 by the get_archive_formats() function.
737 """
738 if extra_args is None:
739 extra_args = []
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200740 if not callable(function):
Tarek Ziadé396fad72010-02-23 05:30:31 +0000741 raise TypeError('The %s object is not callable' % function)
742 if not isinstance(extra_args, (tuple, list)):
743 raise TypeError('extra_args needs to be a sequence')
744 for element in extra_args:
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200745 if not isinstance(element, (tuple, list)) or len(element) !=2:
Tarek Ziadé396fad72010-02-23 05:30:31 +0000746 raise TypeError('extra_args elements are : (arg_name, value)')
747
748 _ARCHIVE_FORMATS[name] = (function, extra_args, description)
749
750def unregister_archive_format(name):
751 del _ARCHIVE_FORMATS[name]
752
753def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
754 dry_run=0, owner=None, group=None, logger=None):
755 """Create an archive file (eg. zip or tar).
756
757 'base_name' is the name of the file to create, minus any format-specific
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000758 extension; 'format' is the archive format: one of "zip", "tar", "bztar"
759 or "gztar".
Tarek Ziadé396fad72010-02-23 05:30:31 +0000760
761 'root_dir' is a directory that will be the root directory of the
762 archive; ie. we typically chdir into 'root_dir' before creating the
763 archive. 'base_dir' is the directory where we start archiving from;
764 ie. 'base_dir' will be the common prefix of all files and
765 directories in the archive. 'root_dir' and 'base_dir' both default
766 to the current directory. Returns the name of the archive file.
767
768 'owner' and 'group' are used when creating a tar archive. By default,
769 uses the current owner and group.
770 """
771 save_cwd = os.getcwd()
772 if root_dir is not None:
773 if logger is not None:
774 logger.debug("changing into '%s'", root_dir)
775 base_name = os.path.abspath(base_name)
776 if not dry_run:
777 os.chdir(root_dir)
778
779 if base_dir is None:
780 base_dir = os.curdir
781
782 kwargs = {'dry_run': dry_run, 'logger': logger}
783
784 try:
785 format_info = _ARCHIVE_FORMATS[format]
786 except KeyError:
787 raise ValueError("unknown archive format '%s'" % format)
788
789 func = format_info[0]
790 for arg, val in format_info[1]:
791 kwargs[arg] = val
792
793 if format != 'zip':
794 kwargs['owner'] = owner
795 kwargs['group'] = group
796
797 try:
798 filename = func(base_name, base_dir, **kwargs)
799 finally:
800 if root_dir is not None:
801 if logger is not None:
802 logger.debug("changing back to '%s'", save_cwd)
803 os.chdir(save_cwd)
804
805 return filename
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000806
807
808def get_unpack_formats():
809 """Returns a list of supported formats for unpacking.
810
811 Each element of the returned sequence is a tuple
812 (name, extensions, description)
813 """
814 formats = [(name, info[0], info[3]) for name, info in
815 _UNPACK_FORMATS.items()]
816 formats.sort()
817 return formats
818
819def _check_unpack_options(extensions, function, extra_args):
820 """Checks what gets registered as an unpacker."""
821 # first make sure no other unpacker is registered for this extension
822 existing_extensions = {}
823 for name, info in _UNPACK_FORMATS.items():
824 for ext in info[0]:
825 existing_extensions[ext] = name
826
827 for extension in extensions:
828 if extension in existing_extensions:
829 msg = '%s is already registered for "%s"'
830 raise RegistryError(msg % (extension,
831 existing_extensions[extension]))
832
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200833 if not callable(function):
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000834 raise TypeError('The registered function must be a callable')
835
836
837def register_unpack_format(name, extensions, function, extra_args=None,
838 description=''):
839 """Registers an unpack format.
840
841 `name` is the name of the format. `extensions` is a list of extensions
842 corresponding to the format.
843
844 `function` is the callable that will be
845 used to unpack archives. The callable will receive archives to unpack.
846 If it's unable to handle an archive, it needs to raise a ReadError
847 exception.
848
849 If provided, `extra_args` is a sequence of
850 (name, value) tuples that will be passed as arguments to the callable.
851 description can be provided to describe the format, and will be returned
852 by the get_unpack_formats() function.
853 """
854 if extra_args is None:
855 extra_args = []
856 _check_unpack_options(extensions, function, extra_args)
857 _UNPACK_FORMATS[name] = extensions, function, extra_args, description
858
859def unregister_unpack_format(name):
860 """Removes the pack format from the registery."""
861 del _UNPACK_FORMATS[name]
862
863def _ensure_directory(path):
864 """Ensure that the parent directory of `path` exists"""
865 dirname = os.path.dirname(path)
866 if not os.path.isdir(dirname):
867 os.makedirs(dirname)
868
869def _unpack_zipfile(filename, extract_dir):
870 """Unpack zip `filename` to `extract_dir`
871 """
872 try:
873 import zipfile
Brett Cannoncd171c82013-07-04 17:43:24 -0400874 except ImportError:
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000875 raise ReadError('zlib not supported, cannot unpack this archive.')
876
877 if not zipfile.is_zipfile(filename):
878 raise ReadError("%s is not a zip file" % filename)
879
880 zip = zipfile.ZipFile(filename)
881 try:
882 for info in zip.infolist():
883 name = info.filename
884
885 # don't extract absolute paths or ones with .. in them
886 if name.startswith('/') or '..' in name:
887 continue
888
889 target = os.path.join(extract_dir, *name.split('/'))
890 if not target:
891 continue
892
893 _ensure_directory(target)
894 if not name.endswith('/'):
895 # file
896 data = zip.read(info.filename)
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200897 f = open(target, 'wb')
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000898 try:
899 f.write(data)
900 finally:
901 f.close()
902 del data
903 finally:
904 zip.close()
905
906def _unpack_tarfile(filename, extract_dir):
907 """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir`
908 """
909 try:
910 tarobj = tarfile.open(filename)
911 except tarfile.TarError:
912 raise ReadError(
913 "%s is not a compressed or uncompressed tar file" % filename)
914 try:
915 tarobj.extractall(extract_dir)
916 finally:
917 tarobj.close()
918
919_UNPACK_FORMATS = {
920 'gztar': (['.tar.gz', '.tgz'], _unpack_tarfile, [], "gzip'ed tar-file"),
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000921 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"),
922 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file")
923 }
924
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000925if _BZ2_SUPPORTED:
926 _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [],
927 "bzip2'ed tar-file")
928
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000929def _find_unpack_format(filename):
930 for name, info in _UNPACK_FORMATS.items():
931 for extension in info[0]:
932 if filename.endswith(extension):
933 return name
934 return None
935
936def unpack_archive(filename, extract_dir=None, format=None):
937 """Unpack an archive.
938
939 `filename` is the name of the archive.
940
941 `extract_dir` is the name of the target directory, where the archive
942 is unpacked. If not provided, the current working directory is used.
943
944 `format` is the archive format: one of "zip", "tar", or "gztar". Or any
945 other registered format. If not provided, unpack_archive will use the
946 filename extension and see if an unpacker was registered for that
947 extension.
948
949 In case none is found, a ValueError is raised.
950 """
951 if extract_dir is None:
952 extract_dir = os.getcwd()
953
954 if format is not None:
955 try:
956 format_info = _UNPACK_FORMATS[format]
957 except KeyError:
958 raise ValueError("Unknown unpack format '{0}'".format(format))
959
Nick Coghlanabf202d2011-03-16 13:52:20 -0400960 func = format_info[1]
961 func(filename, extract_dir, **dict(format_info[2]))
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000962 else:
963 # we need to look at the registered unpackers supported extensions
964 format = _find_unpack_format(filename)
965 if format is None:
966 raise ReadError("Unknown archive format '{0}'".format(filename))
967
968 func = _UNPACK_FORMATS[format][1]
969 kwargs = dict(_UNPACK_FORMATS[format][2])
970 func(filename, extract_dir, **kwargs)
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +0200971
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200972
973if hasattr(os, 'statvfs'):
974
975 __all__.append('disk_usage')
976 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +0200977
978 def disk_usage(path):
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200979 """Return disk usage statistics about the given path.
980
Sandro Tosif8ae4fa2012-04-23 20:07:15 +0200981 Returned value is a named tuple with attributes 'total', 'used' and
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200982 'free', which are the amount of total, used and free space, in bytes.
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +0200983 """
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200984 st = os.statvfs(path)
985 free = st.f_bavail * st.f_frsize
986 total = st.f_blocks * st.f_frsize
987 used = (st.f_blocks - st.f_bfree) * st.f_frsize
988 return _ntuple_diskusage(total, used, free)
989
990elif os.name == 'nt':
991
992 import nt
993 __all__.append('disk_usage')
994 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
995
996 def disk_usage(path):
997 """Return disk usage statistics about the given path.
998
Ezio Melotti30b9d5d2013-08-17 15:50:46 +0300999 Returned values is a named tuple with attributes 'total', 'used' and
Éric Araujoe4d5b8e2011-08-08 16:51:11 +02001000 'free', which are the amount of total, used and free space, in bytes.
1001 """
1002 total, free = nt._getdiskusage(path)
1003 used = total - free
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +02001004 return _ntuple_diskusage(total, used, free)
Sandro Tosid902a142011-08-22 23:28:27 +02001005
Éric Araujo0ac4a5d2011-09-01 08:31:51 +02001006
Sandro Tosid902a142011-08-22 23:28:27 +02001007def chown(path, user=None, group=None):
1008 """Change owner user and group of the given path.
1009
1010 user and group can be the uid/gid or the user/group names, and in that case,
1011 they are converted to their respective uid/gid.
1012 """
1013
1014 if user is None and group is None:
1015 raise ValueError("user and/or group must be set")
1016
1017 _user = user
1018 _group = group
1019
1020 # -1 means don't change it
1021 if user is None:
1022 _user = -1
1023 # user can either be an int (the uid) or a string (the system username)
1024 elif isinstance(user, str):
1025 _user = _get_uid(user)
1026 if _user is None:
1027 raise LookupError("no such user: {!r}".format(user))
1028
1029 if group is None:
1030 _group = -1
1031 elif not isinstance(group, int):
1032 _group = _get_gid(group)
1033 if _group is None:
1034 raise LookupError("no such group: {!r}".format(group))
1035
1036 os.chown(path, _user, _group)
Antoine Pitroubcf2b592012-02-08 23:28:36 +01001037
1038def get_terminal_size(fallback=(80, 24)):
1039 """Get the size of the terminal window.
1040
1041 For each of the two dimensions, the environment variable, COLUMNS
1042 and LINES respectively, is checked. If the variable is defined and
1043 the value is a positive integer, it is used.
1044
1045 When COLUMNS or LINES is not defined, which is the common case,
1046 the terminal connected to sys.__stdout__ is queried
1047 by invoking os.get_terminal_size.
1048
1049 If the terminal size cannot be successfully queried, either because
1050 the system doesn't support querying, or because we are not
1051 connected to a terminal, the value given in fallback parameter
1052 is used. Fallback defaults to (80, 24) which is the default
1053 size used by many terminal emulators.
1054
1055 The value returned is a named tuple of type os.terminal_size.
1056 """
1057 # columns, lines are the working values
1058 try:
1059 columns = int(os.environ['COLUMNS'])
1060 except (KeyError, ValueError):
1061 columns = 0
1062
1063 try:
1064 lines = int(os.environ['LINES'])
1065 except (KeyError, ValueError):
1066 lines = 0
1067
1068 # only query if necessary
1069 if columns <= 0 or lines <= 0:
1070 try:
1071 size = os.get_terminal_size(sys.__stdout__.fileno())
1072 except (NameError, OSError):
1073 size = os.terminal_size(fallback)
1074 if columns <= 0:
1075 columns = size.columns
1076 if lines <= 0:
1077 lines = size.lines
1078
1079 return os.terminal_size((columns, lines))
Brian Curtinc57a3452012-06-22 16:00:30 -05001080
1081def which(cmd, mode=os.F_OK | os.X_OK, path=None):
Brian Curtindc00f1e2012-06-22 22:49:12 -05001082 """Given a command, mode, and a PATH string, return the path which
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001083 conforms to the given mode on the PATH, or None if there is no such
1084 file.
1085
1086 `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
1087 of os.environ.get("PATH"), or can be overridden with a custom search
1088 path.
1089
1090 """
Victor Stinner1d006a22013-12-16 23:39:40 +01001091 # Check that a given file can be accessed with the correct mode.
1092 # Additionally check that `file` is not a directory, as on Windows
1093 # directories pass the os.access check.
1094 def _access_check(fn, mode):
1095 return (os.path.exists(fn) and os.access(fn, mode)
1096 and not os.path.isdir(fn))
1097
Serhiy Storchaka8bea2002013-01-23 10:44:21 +02001098 # If we're given a path with a directory part, look it up directly rather
1099 # than referring to PATH directories. This includes checking relative to the
1100 # current directory, e.g. ./script
1101 if os.path.dirname(cmd):
1102 if _access_check(cmd, mode):
1103 return cmd
1104 return None
Brian Curtinc57a3452012-06-22 16:00:30 -05001105
Barry Warsaw618738b2013-04-16 11:05:03 -04001106 if path is None:
1107 path = os.environ.get("PATH", os.defpath)
1108 if not path:
1109 return None
Victor Stinner1d006a22013-12-16 23:39:40 +01001110 path = path.split(os.pathsep)
Brian Curtinc57a3452012-06-22 16:00:30 -05001111
1112 if sys.platform == "win32":
1113 # The current directory takes precedence on Windows.
1114 if not os.curdir in path:
1115 path.insert(0, os.curdir)
1116
1117 # PATHEXT is necessary to check on Windows.
1118 pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
1119 # See if the given file matches any of the expected path extensions.
1120 # This will allow us to short circuit when given "python.exe".
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001121 # If it does match, only test that one, otherwise we have to try
1122 # others.
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001123 if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
1124 files = [cmd]
1125 else:
1126 files = [cmd + ext for ext in pathext]
Brian Curtinc57a3452012-06-22 16:00:30 -05001127 else:
1128 # On other platforms you don't have things like PATHEXT to tell you
1129 # what file suffixes are executable, so just pass on cmd as-is.
1130 files = [cmd]
1131
1132 seen = set()
1133 for dir in path:
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001134 normdir = os.path.normcase(dir)
1135 if not normdir in seen:
1136 seen.add(normdir)
Brian Curtinc57a3452012-06-22 16:00:30 -05001137 for thefile in files:
1138 name = os.path.join(dir, thefile)
1139 if _access_check(name, mode):
1140 return name
1141 return None