blob: e87d18e9c8054eec034c1cae64b5ac509dbd0293 [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:
690 for dirpath, dirnames, filenames in os.walk(base_dir):
691 for name in filenames:
692 path = os.path.normpath(os.path.join(dirpath, name))
693 if os.path.isfile(path):
694 zf.write(path, path)
695 if logger is not None:
696 logger.info("adding '%s'", path)
Tarek Ziadé396fad72010-02-23 05:30:31 +0000697
698 return zip_filename
699
700_ARCHIVE_FORMATS = {
701 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"),
Tarek Ziadé396fad72010-02-23 05:30:31 +0000702 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"),
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200703 'zip': (_make_zipfile, [], "ZIP file")
Tarek Ziadé396fad72010-02-23 05:30:31 +0000704 }
705
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000706if _BZ2_SUPPORTED:
707 _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')],
708 "bzip2'ed tar-file")
709
Tarek Ziadé396fad72010-02-23 05:30:31 +0000710def get_archive_formats():
711 """Returns a list of supported formats for archiving and unarchiving.
712
713 Each element of the returned sequence is a tuple (name, description)
714 """
715 formats = [(name, registry[2]) for name, registry in
716 _ARCHIVE_FORMATS.items()]
717 formats.sort()
718 return formats
719
720def register_archive_format(name, function, extra_args=None, description=''):
721 """Registers an archive format.
722
723 name is the name of the format. function is the callable that will be
724 used to create archives. If provided, extra_args is a sequence of
725 (name, value) tuples that will be passed as arguments to the callable.
726 description can be provided to describe the format, and will be returned
727 by the get_archive_formats() function.
728 """
729 if extra_args is None:
730 extra_args = []
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200731 if not callable(function):
Tarek Ziadé396fad72010-02-23 05:30:31 +0000732 raise TypeError('The %s object is not callable' % function)
733 if not isinstance(extra_args, (tuple, list)):
734 raise TypeError('extra_args needs to be a sequence')
735 for element in extra_args:
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200736 if not isinstance(element, (tuple, list)) or len(element) !=2:
Tarek Ziadé396fad72010-02-23 05:30:31 +0000737 raise TypeError('extra_args elements are : (arg_name, value)')
738
739 _ARCHIVE_FORMATS[name] = (function, extra_args, description)
740
741def unregister_archive_format(name):
742 del _ARCHIVE_FORMATS[name]
743
744def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
745 dry_run=0, owner=None, group=None, logger=None):
746 """Create an archive file (eg. zip or tar).
747
748 'base_name' is the name of the file to create, minus any format-specific
Tarek Ziadé5e2be872010-04-20 21:40:47 +0000749 extension; 'format' is the archive format: one of "zip", "tar", "bztar"
750 or "gztar".
Tarek Ziadé396fad72010-02-23 05:30:31 +0000751
752 'root_dir' is a directory that will be the root directory of the
753 archive; ie. we typically chdir into 'root_dir' before creating the
754 archive. 'base_dir' is the directory where we start archiving from;
755 ie. 'base_dir' will be the common prefix of all files and
756 directories in the archive. 'root_dir' and 'base_dir' both default
757 to the current directory. Returns the name of the archive file.
758
759 'owner' and 'group' are used when creating a tar archive. By default,
760 uses the current owner and group.
761 """
762 save_cwd = os.getcwd()
763 if root_dir is not None:
764 if logger is not None:
765 logger.debug("changing into '%s'", root_dir)
766 base_name = os.path.abspath(base_name)
767 if not dry_run:
768 os.chdir(root_dir)
769
770 if base_dir is None:
771 base_dir = os.curdir
772
773 kwargs = {'dry_run': dry_run, 'logger': logger}
774
775 try:
776 format_info = _ARCHIVE_FORMATS[format]
777 except KeyError:
778 raise ValueError("unknown archive format '%s'" % format)
779
780 func = format_info[0]
781 for arg, val in format_info[1]:
782 kwargs[arg] = val
783
784 if format != 'zip':
785 kwargs['owner'] = owner
786 kwargs['group'] = group
787
788 try:
789 filename = func(base_name, base_dir, **kwargs)
790 finally:
791 if root_dir is not None:
792 if logger is not None:
793 logger.debug("changing back to '%s'", save_cwd)
794 os.chdir(save_cwd)
795
796 return filename
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000797
798
799def get_unpack_formats():
800 """Returns a list of supported formats for unpacking.
801
802 Each element of the returned sequence is a tuple
803 (name, extensions, description)
804 """
805 formats = [(name, info[0], info[3]) for name, info in
806 _UNPACK_FORMATS.items()]
807 formats.sort()
808 return formats
809
810def _check_unpack_options(extensions, function, extra_args):
811 """Checks what gets registered as an unpacker."""
812 # first make sure no other unpacker is registered for this extension
813 existing_extensions = {}
814 for name, info in _UNPACK_FORMATS.items():
815 for ext in info[0]:
816 existing_extensions[ext] = name
817
818 for extension in extensions:
819 if extension in existing_extensions:
820 msg = '%s is already registered for "%s"'
821 raise RegistryError(msg % (extension,
822 existing_extensions[extension]))
823
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200824 if not callable(function):
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000825 raise TypeError('The registered function must be a callable')
826
827
828def register_unpack_format(name, extensions, function, extra_args=None,
829 description=''):
830 """Registers an unpack format.
831
832 `name` is the name of the format. `extensions` is a list of extensions
833 corresponding to the format.
834
835 `function` is the callable that will be
836 used to unpack archives. The callable will receive archives to unpack.
837 If it's unable to handle an archive, it needs to raise a ReadError
838 exception.
839
840 If provided, `extra_args` is a sequence of
841 (name, value) tuples that will be passed as arguments to the callable.
842 description can be provided to describe the format, and will be returned
843 by the get_unpack_formats() function.
844 """
845 if extra_args is None:
846 extra_args = []
847 _check_unpack_options(extensions, function, extra_args)
848 _UNPACK_FORMATS[name] = extensions, function, extra_args, description
849
850def unregister_unpack_format(name):
851 """Removes the pack format from the registery."""
852 del _UNPACK_FORMATS[name]
853
854def _ensure_directory(path):
855 """Ensure that the parent directory of `path` exists"""
856 dirname = os.path.dirname(path)
857 if not os.path.isdir(dirname):
858 os.makedirs(dirname)
859
860def _unpack_zipfile(filename, extract_dir):
861 """Unpack zip `filename` to `extract_dir`
862 """
863 try:
864 import zipfile
Brett Cannoncd171c82013-07-04 17:43:24 -0400865 except ImportError:
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000866 raise ReadError('zlib not supported, cannot unpack this archive.')
867
868 if not zipfile.is_zipfile(filename):
869 raise ReadError("%s is not a zip file" % filename)
870
871 zip = zipfile.ZipFile(filename)
872 try:
873 for info in zip.infolist():
874 name = info.filename
875
876 # don't extract absolute paths or ones with .. in them
877 if name.startswith('/') or '..' in name:
878 continue
879
880 target = os.path.join(extract_dir, *name.split('/'))
881 if not target:
882 continue
883
884 _ensure_directory(target)
885 if not name.endswith('/'):
886 # file
887 data = zip.read(info.filename)
Éric Araujoc1b7e7f2011-09-18 23:12:30 +0200888 f = open(target, 'wb')
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000889 try:
890 f.write(data)
891 finally:
892 f.close()
893 del data
894 finally:
895 zip.close()
896
897def _unpack_tarfile(filename, extract_dir):
898 """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir`
899 """
900 try:
901 tarobj = tarfile.open(filename)
902 except tarfile.TarError:
903 raise ReadError(
904 "%s is not a compressed or uncompressed tar file" % filename)
905 try:
906 tarobj.extractall(extract_dir)
907 finally:
908 tarobj.close()
909
910_UNPACK_FORMATS = {
911 'gztar': (['.tar.gz', '.tgz'], _unpack_tarfile, [], "gzip'ed tar-file"),
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000912 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"),
913 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file")
914 }
915
Tarek Ziadéffa155a2010-04-29 13:34:35 +0000916if _BZ2_SUPPORTED:
917 _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [],
918 "bzip2'ed tar-file")
919
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000920def _find_unpack_format(filename):
921 for name, info in _UNPACK_FORMATS.items():
922 for extension in info[0]:
923 if filename.endswith(extension):
924 return name
925 return None
926
927def unpack_archive(filename, extract_dir=None, format=None):
928 """Unpack an archive.
929
930 `filename` is the name of the archive.
931
932 `extract_dir` is the name of the target directory, where the archive
933 is unpacked. If not provided, the current working directory is used.
934
935 `format` is the archive format: one of "zip", "tar", or "gztar". Or any
936 other registered format. If not provided, unpack_archive will use the
937 filename extension and see if an unpacker was registered for that
938 extension.
939
940 In case none is found, a ValueError is raised.
941 """
942 if extract_dir is None:
943 extract_dir = os.getcwd()
944
945 if format is not None:
946 try:
947 format_info = _UNPACK_FORMATS[format]
948 except KeyError:
949 raise ValueError("Unknown unpack format '{0}'".format(format))
950
Nick Coghlanabf202d2011-03-16 13:52:20 -0400951 func = format_info[1]
952 func(filename, extract_dir, **dict(format_info[2]))
Tarek Ziadé6ac91722010-04-28 17:51:36 +0000953 else:
954 # we need to look at the registered unpackers supported extensions
955 format = _find_unpack_format(filename)
956 if format is None:
957 raise ReadError("Unknown archive format '{0}'".format(filename))
958
959 func = _UNPACK_FORMATS[format][1]
960 kwargs = dict(_UNPACK_FORMATS[format][2])
961 func(filename, extract_dir, **kwargs)
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +0200962
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200963
964if hasattr(os, 'statvfs'):
965
966 __all__.append('disk_usage')
967 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +0200968
969 def disk_usage(path):
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200970 """Return disk usage statistics about the given path.
971
Sandro Tosif8ae4fa2012-04-23 20:07:15 +0200972 Returned value is a named tuple with attributes 'total', 'used' and
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200973 'free', which are the amount of total, used and free space, in bytes.
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +0200974 """
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200975 st = os.statvfs(path)
976 free = st.f_bavail * st.f_frsize
977 total = st.f_blocks * st.f_frsize
978 used = (st.f_blocks - st.f_bfree) * st.f_frsize
979 return _ntuple_diskusage(total, used, free)
980
981elif os.name == 'nt':
982
983 import nt
984 __all__.append('disk_usage')
985 _ntuple_diskusage = collections.namedtuple('usage', 'total used free')
986
987 def disk_usage(path):
988 """Return disk usage statistics about the given path.
989
Ezio Melotti30b9d5d2013-08-17 15:50:46 +0300990 Returned values is a named tuple with attributes 'total', 'used' and
Éric Araujoe4d5b8e2011-08-08 16:51:11 +0200991 'free', which are the amount of total, used and free space, in bytes.
992 """
993 total, free = nt._getdiskusage(path)
994 used = total - free
Giampaolo Rodola'210e7ca2011-07-01 13:55:36 +0200995 return _ntuple_diskusage(total, used, free)
Sandro Tosid902a142011-08-22 23:28:27 +0200996
Éric Araujo0ac4a5d2011-09-01 08:31:51 +0200997
Sandro Tosid902a142011-08-22 23:28:27 +0200998def chown(path, user=None, group=None):
999 """Change owner user and group of the given path.
1000
1001 user and group can be the uid/gid or the user/group names, and in that case,
1002 they are converted to their respective uid/gid.
1003 """
1004
1005 if user is None and group is None:
1006 raise ValueError("user and/or group must be set")
1007
1008 _user = user
1009 _group = group
1010
1011 # -1 means don't change it
1012 if user is None:
1013 _user = -1
1014 # user can either be an int (the uid) or a string (the system username)
1015 elif isinstance(user, str):
1016 _user = _get_uid(user)
1017 if _user is None:
1018 raise LookupError("no such user: {!r}".format(user))
1019
1020 if group is None:
1021 _group = -1
1022 elif not isinstance(group, int):
1023 _group = _get_gid(group)
1024 if _group is None:
1025 raise LookupError("no such group: {!r}".format(group))
1026
1027 os.chown(path, _user, _group)
Antoine Pitroubcf2b592012-02-08 23:28:36 +01001028
1029def get_terminal_size(fallback=(80, 24)):
1030 """Get the size of the terminal window.
1031
1032 For each of the two dimensions, the environment variable, COLUMNS
1033 and LINES respectively, is checked. If the variable is defined and
1034 the value is a positive integer, it is used.
1035
1036 When COLUMNS or LINES is not defined, which is the common case,
1037 the terminal connected to sys.__stdout__ is queried
1038 by invoking os.get_terminal_size.
1039
1040 If the terminal size cannot be successfully queried, either because
1041 the system doesn't support querying, or because we are not
1042 connected to a terminal, the value given in fallback parameter
1043 is used. Fallback defaults to (80, 24) which is the default
1044 size used by many terminal emulators.
1045
1046 The value returned is a named tuple of type os.terminal_size.
1047 """
1048 # columns, lines are the working values
1049 try:
1050 columns = int(os.environ['COLUMNS'])
1051 except (KeyError, ValueError):
1052 columns = 0
1053
1054 try:
1055 lines = int(os.environ['LINES'])
1056 except (KeyError, ValueError):
1057 lines = 0
1058
1059 # only query if necessary
1060 if columns <= 0 or lines <= 0:
1061 try:
1062 size = os.get_terminal_size(sys.__stdout__.fileno())
1063 except (NameError, OSError):
1064 size = os.terminal_size(fallback)
1065 if columns <= 0:
1066 columns = size.columns
1067 if lines <= 0:
1068 lines = size.lines
1069
1070 return os.terminal_size((columns, lines))
Brian Curtinc57a3452012-06-22 16:00:30 -05001071
1072def which(cmd, mode=os.F_OK | os.X_OK, path=None):
Brian Curtindc00f1e2012-06-22 22:49:12 -05001073 """Given a command, mode, and a PATH string, return the path which
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001074 conforms to the given mode on the PATH, or None if there is no such
1075 file.
1076
1077 `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
1078 of os.environ.get("PATH"), or can be overridden with a custom search
1079 path.
1080
1081 """
Victor Stinner1d006a22013-12-16 23:39:40 +01001082 # Check that a given file can be accessed with the correct mode.
1083 # Additionally check that `file` is not a directory, as on Windows
1084 # directories pass the os.access check.
1085 def _access_check(fn, mode):
1086 return (os.path.exists(fn) and os.access(fn, mode)
1087 and not os.path.isdir(fn))
1088
Serhiy Storchaka8bea2002013-01-23 10:44:21 +02001089 # If we're given a path with a directory part, look it up directly rather
1090 # than referring to PATH directories. This includes checking relative to the
1091 # current directory, e.g. ./script
1092 if os.path.dirname(cmd):
1093 if _access_check(cmd, mode):
1094 return cmd
1095 return None
Brian Curtinc57a3452012-06-22 16:00:30 -05001096
Barry Warsaw618738b2013-04-16 11:05:03 -04001097 if path is None:
1098 path = os.environ.get("PATH", os.defpath)
1099 if not path:
1100 return None
Victor Stinner1d006a22013-12-16 23:39:40 +01001101 path = path.split(os.pathsep)
Brian Curtinc57a3452012-06-22 16:00:30 -05001102
1103 if sys.platform == "win32":
1104 # The current directory takes precedence on Windows.
1105 if not os.curdir in path:
1106 path.insert(0, os.curdir)
1107
1108 # PATHEXT is necessary to check on Windows.
1109 pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
1110 # See if the given file matches any of the expected path extensions.
1111 # This will allow us to short circuit when given "python.exe".
Philip Jenvey88bc0d22012-06-23 15:54:38 -07001112 # If it does match, only test that one, otherwise we have to try
1113 # others.
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001114 if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
1115 files = [cmd]
1116 else:
1117 files = [cmd + ext for ext in pathext]
Brian Curtinc57a3452012-06-22 16:00:30 -05001118 else:
1119 # On other platforms you don't have things like PATHEXT to tell you
1120 # what file suffixes are executable, so just pass on cmd as-is.
1121 files = [cmd]
1122
1123 seen = set()
1124 for dir in path:
Serhiy Storchaka014791f2013-01-21 15:00:27 +02001125 normdir = os.path.normcase(dir)
1126 if not normdir in seen:
1127 seen.add(normdir)
Brian Curtinc57a3452012-06-22 16:00:30 -05001128 for thefile in files:
1129 name = os.path.join(dir, thefile)
1130 if _access_check(name, mode):
1131 return name
1132 return None