Issue #1531: Read fileobj from the current offset, do not seek to
the start.
(backport from r59260)
diff --git a/Lib/tarfile.py b/Lib/tarfile.py
index 45997cb..87b298e 100644
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -1065,7 +1065,8 @@
self.closed = False
self.members = [] # list of members as TarInfo objects
self._loaded = False # flag if all members have been read
- self.offset = 0L # current position in the archive file
+ self.offset = self.fileobj.tell()
+ # current position in the archive file
self.inodes = {} # dictionary caching the inodes of
# archive members already added
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index 5a50996..f3c090d 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -260,6 +260,38 @@
mode = self.mode + self.sep + "*"
self.tar = tarfile.open(tarname(self.comp), mode)
+class ReadFileobjTest(BaseTest):
+
+ def test_fileobj_with_offset(self):
+ # Skip the first member and store values from the second member
+ # of the testtar.
+ self.tar.next()
+ t = self.tar.next()
+ name = t.name
+ offset = t.offset
+ data = self.tar.extractfile(t).read()
+ self.tar.close()
+
+ # Open the testtar and seek to the offset of the second member.
+ if self.comp == "gz":
+ _open = gzip.GzipFile
+ elif self.comp == "bz2":
+ _open = bz2.BZ2File
+ else:
+ _open = open
+ fobj = _open(tarname(self.comp), "rb")
+ fobj.seek(offset)
+
+ # Test if the tarfile starts with the second member.
+ self.tar = tarfile.open(tarname(self.comp), "r:", fileobj=fobj)
+ t = self.tar.next()
+ self.assertEqual(t.name, name)
+ # Read to the end of fileobj and test if seeking back to the
+ # beginning works.
+ self.tar.getmembers()
+ self.assertEqual(self.tar.extractfile(t).read(), data,
+ "seek back did not work")
+
class WriteTest(BaseTest):
mode = 'w'
@@ -624,6 +656,8 @@
comp = "gz"
class ReadStreamAsteriskTestGzip(ReadStreamAsteriskTest):
comp = "gz"
+class ReadFileobjTestGzip(ReadFileobjTest):
+ comp = "gz"
# Filemode test cases
@@ -680,6 +714,8 @@
comp = "bz2"
class ReadStreamAsteriskTestBzip2(ReadStreamAsteriskTest):
comp = "bz2"
+ class ReadFileobjTestBzip2(ReadFileobjTest):
+ comp = "bz2"
# If importing gzip failed, discard the Gzip TestCases.
if not gzip:
@@ -713,6 +749,7 @@
ReadDetectFileobjTest,
ReadAsteriskTest,
ReadStreamAsteriskTest,
+ ReadFileobjTest,
WriteTest,
Write100Test,
WriteSize0Test,
@@ -730,7 +767,8 @@
ReadTestGzip, ReadStreamTestGzip,
WriteTestGzip, WriteStreamTestGzip,
ReadDetectTestGzip, ReadDetectFileobjTestGzip,
- ReadAsteriskTestGzip, ReadStreamAsteriskTestGzip
+ ReadAsteriskTestGzip, ReadStreamAsteriskTestGzip,
+ ReadFileobjTestGzip
])
if bz2:
@@ -738,7 +776,8 @@
ReadTestBzip2, ReadStreamTestBzip2,
WriteTestBzip2, WriteStreamTestBzip2,
ReadDetectTestBzip2, ReadDetectFileobjTestBzip2,
- ReadAsteriskTestBzip2, ReadStreamAsteriskTestBzip2
+ ReadAsteriskTestBzip2, ReadStreamAsteriskTestBzip2,
+ ReadFileobjTestBzip2
])
try:
test_support.run_unittest(*tests)