mirror of
https://github.com/python/cpython.git
synced 2025-12-15 21:44:50 +00:00
Issue 23193: Add numeric_owner to tarfile.TarFile.extract() and tarfile.TarFile.extractall().
This commit is contained in:
parent
28edf12cd4
commit
7a80389ce5
6 changed files with 200 additions and 33 deletions
|
|
@ -1972,12 +1972,13 @@ class TarFile(object):
|
|||
|
||||
self.members.append(tarinfo)
|
||||
|
||||
def extractall(self, path=".", members=None):
|
||||
def extractall(self, path=".", members=None, *, numeric_owner=False):
|
||||
"""Extract all members from the archive to the current working
|
||||
directory and set owner, modification time and permissions on
|
||||
directories afterwards. `path' specifies a different directory
|
||||
to extract to. `members' is optional and must be a subset of the
|
||||
list returned by getmembers().
|
||||
list returned by getmembers(). If `numeric_owner` is True, only
|
||||
the numbers for user/group names are used and not the names.
|
||||
"""
|
||||
directories = []
|
||||
|
||||
|
|
@ -1991,7 +1992,8 @@ class TarFile(object):
|
|||
tarinfo = copy.copy(tarinfo)
|
||||
tarinfo.mode = 0o700
|
||||
# Do not set_attrs directories, as we will do that further down
|
||||
self.extract(tarinfo, path, set_attrs=not tarinfo.isdir())
|
||||
self.extract(tarinfo, path, set_attrs=not tarinfo.isdir(),
|
||||
numeric_owner=numeric_owner)
|
||||
|
||||
# Reverse sort directories.
|
||||
directories.sort(key=lambda a: a.name)
|
||||
|
|
@ -2001,7 +2003,7 @@ class TarFile(object):
|
|||
for tarinfo in directories:
|
||||
dirpath = os.path.join(path, tarinfo.name)
|
||||
try:
|
||||
self.chown(tarinfo, dirpath)
|
||||
self.chown(tarinfo, dirpath, numeric_owner=numeric_owner)
|
||||
self.utime(tarinfo, dirpath)
|
||||
self.chmod(tarinfo, dirpath)
|
||||
except ExtractError as e:
|
||||
|
|
@ -2010,12 +2012,14 @@ class TarFile(object):
|
|||
else:
|
||||
self._dbg(1, "tarfile: %s" % e)
|
||||
|
||||
def extract(self, member, path="", set_attrs=True):
|
||||
def extract(self, member, path="", set_attrs=True, *, numeric_owner=False):
|
||||
"""Extract a member from the archive to the current working directory,
|
||||
using its full name. Its file information is extracted as accurately
|
||||
as possible. `member' may be a filename or a TarInfo object. You can
|
||||
specify a different directory using `path'. File attributes (owner,
|
||||
mtime, mode) are set unless `set_attrs' is False.
|
||||
mtime, mode) are set unless `set_attrs' is False. If `numeric_owner`
|
||||
is True, only the numbers for user/group names are used and not
|
||||
the names.
|
||||
"""
|
||||
self._check("r")
|
||||
|
||||
|
|
@ -2030,7 +2034,8 @@ class TarFile(object):
|
|||
|
||||
try:
|
||||
self._extract_member(tarinfo, os.path.join(path, tarinfo.name),
|
||||
set_attrs=set_attrs)
|
||||
set_attrs=set_attrs,
|
||||
numeric_owner=numeric_owner)
|
||||
except OSError as e:
|
||||
if self.errorlevel > 0:
|
||||
raise
|
||||
|
|
@ -2076,7 +2081,8 @@ class TarFile(object):
|
|||
# blkdev, etc.), return None instead of a file object.
|
||||
return None
|
||||
|
||||
def _extract_member(self, tarinfo, targetpath, set_attrs=True):
|
||||
def _extract_member(self, tarinfo, targetpath, set_attrs=True,
|
||||
numeric_owner=False):
|
||||
"""Extract the TarInfo object tarinfo to a physical
|
||||
file called targetpath.
|
||||
"""
|
||||
|
|
@ -2114,7 +2120,7 @@ class TarFile(object):
|
|||
self.makefile(tarinfo, targetpath)
|
||||
|
||||
if set_attrs:
|
||||
self.chown(tarinfo, targetpath)
|
||||
self.chown(tarinfo, targetpath, numeric_owner)
|
||||
if not tarinfo.issym():
|
||||
self.chmod(tarinfo, targetpath)
|
||||
self.utime(tarinfo, targetpath)
|
||||
|
|
@ -2203,19 +2209,24 @@ class TarFile(object):
|
|||
except KeyError:
|
||||
raise ExtractError("unable to resolve link inside archive")
|
||||
|
||||
def chown(self, tarinfo, targetpath):
|
||||
"""Set owner of targetpath according to tarinfo.
|
||||
def chown(self, tarinfo, targetpath, numeric_owner):
|
||||
"""Set owner of targetpath according to tarinfo. If numeric_owner
|
||||
is True, use .gid/.uid instead of .gname/.uname.
|
||||
"""
|
||||
if pwd and hasattr(os, "geteuid") and os.geteuid() == 0:
|
||||
# We have to be root to do so.
|
||||
try:
|
||||
g = grp.getgrnam(tarinfo.gname)[2]
|
||||
except KeyError:
|
||||
if numeric_owner:
|
||||
g = tarinfo.gid
|
||||
try:
|
||||
u = pwd.getpwnam(tarinfo.uname)[2]
|
||||
except KeyError:
|
||||
u = tarinfo.uid
|
||||
else:
|
||||
try:
|
||||
g = grp.getgrnam(tarinfo.gname)[2]
|
||||
except KeyError:
|
||||
g = tarinfo.gid
|
||||
try:
|
||||
u = pwd.getpwnam(tarinfo.uname)[2]
|
||||
except KeyError:
|
||||
u = tarinfo.uid
|
||||
try:
|
||||
if tarinfo.issym() and hasattr(os, "lchown"):
|
||||
os.lchown(targetpath, u, g)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue