diff -r 60163fc72017 Lib/tarfile.py --- a/Lib/tarfile.py Mon Jan 13 13:51:42 2014 -0500 +++ b/Lib/tarfile.py Mon Jan 13 21:58:43 2014 +0200 @@ -1603,21 +1603,24 @@ except (ImportError, AttributeError): raise CompressionError("gzip module is not available") - extfileobj = fileobj is not None try: fileobj = gzip.GzipFile(name, mode + "b", compresslevel, fileobj) + except OSError: + if fileobj is not None and mode == 'r': + raise ReadError("not a gzip file") + raise + + try: t = cls.taropen(name, mode, fileobj, **kwargs) except OSError: - if not extfileobj and fileobj is not None: - fileobj.close() - if fileobj is None: - raise - raise ReadError("not a gzip file") + fileobj.close() + if mode == 'r': + raise ReadError("not a gzip file") + raise except: - if not extfileobj and fileobj is not None: - fileobj.close() + fileobj.close() raise - t._extfileobj = extfileobj + t._extfileobj = False return t @classmethod @@ -1640,7 +1643,9 @@ t = cls.taropen(name, mode, fileobj, **kwargs) except (OSError, EOFError): fileobj.close() - raise ReadError("not a bzip2 file") + if mode == 'r': + raise ReadError("not a bzip2 file") + raise t._extfileobj = False return t @@ -1663,7 +1668,9 @@ t = cls.taropen(name, mode, fileobj, **kwargs) except (lzma.LZMAError, EOFError): fileobj.close() - raise ReadError("not an lzma file") + if mode == 'r': + raise ReadError("not an lzma file") + raise t._extfileobj = False return t diff -r 60163fc72017 Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py Mon Jan 13 13:51:42 2014 -0500 +++ b/Lib/test/test_tarfile.py Mon Jan 13 21:58:43 2014 +0200 @@ -1137,6 +1137,22 @@ finally: os.chdir(cwd) + def test_open_nonwritable_fileobj(self): + for exctype in OSError, EOFError, RuntimeError: + class BadFile(io.BytesIO): + first = True + def write(self, data): + if self.first: + self.first = False + raise exctype + + f = BadFile() + with self.assertRaises(exctype): + tar = tarfile.open(tmpname, self.mode, fileobj=f, + format=tarfile.PAX_FORMAT, + pax_headers={'non': 'empty'}) + self.assertFalse(f.closed) + class GzipWriteTest(GzipTest, WriteTest): pass