(self, tarfile)
return next
Process an extended or global header as described in
           POSIX.1-2008.
Process an extended or global header as described in
           POSIX.1-2008.
Process an extended or global header as described in POSIX . 1 - 2008 .
def _proc_pax(self, tarfile):
        """Process an extended or global header as described in
           POSIX.1-2008.
        """
        # Read the header information.
        buf = tarfile.fileobj.read(self._block(self.size))

        # A pax header stores supplemental information for either
        # the following file (extended) or all following files
        # (global).
        if self.type == XGLTYPE:
            pax_headers = tarfile.pax_headers
        else:
            pax_headers = tarfile.pax_headers.copy()

        # Check if the pax header contains a hdrcharset field. This tells us
        # the encoding of the path, linkpath, uname and gname fields. Normally,
        # these fields are UTF-8 encoded but since POSIX.1-2008 tar
        # implementations are allowed to store them as raw binary strings if
        # the translation to UTF-8 fails.
        match = re.search(br"\d+ hdrcharset=([^\n]+)\n", buf)
        if match is not None:
            pax_headers["hdrcharset"] = match.group(1).decode("utf8")

        # For the time being, we don't care about anything other than "BINARY".
        # The only other value that is currently allowed by the standard is
        # "ISO-IR 10646 2000 UTF-8" in other words UTF-8.
        hdrcharset = pax_headers.get("hdrcharset")
        if hdrcharset == "BINARY":
            encoding = tarfile.encoding
        else:
            encoding = "utf8"

        # Parse pax header information. A record looks like that:
        # "%d %s=%s\n" % (length, keyword, value). length is the size
        # of the complete record including the length field itself and
        # the newline. keyword and value are both UTF-8 encoded strings.
        regex = re.compile(br"(\d+) ([^=]+)=")
        pos = 0
        while True:
            match = regex.match(buf, pos)
            if not match:
                break

            length, keyword = match.groups()
            length = int(length)
            value = buf[match.end(2) + 1:match.start(1) + length - 1]

            # Normally, we could just use "utf8" as the encoding and "strict"
            # as the error handler, but we better not take the risk. For
            # example, GNU tar <= 1.23 is known to store filenames it cannot
            # translate to UTF-8 as raw strings (unfortunately without a
            # hdrcharset=BINARY header).
            # We first try the strict standard encoding, and if that fails we
            # fall back on the user's encoding and error handler.
            keyword = self._decode_pax_field(keyword, "utf8", "utf8",
                    tarfile.errors)
            if keyword in PAX_NAME_FIELDS:
                value = self._decode_pax_field(value, encoding, tarfile.encoding,
                        tarfile.errors)
            else:
                value = self._decode_pax_field(value, "utf8", "utf8",
                        tarfile.errors)

            pax_headers[keyword] = value
            pos += length

        # Fetch the next header.
        try:
            next = self.fromtarfile(tarfile)
        except HeaderError:
            raise SubsequentHeaderError("missing or bad subsequent header")

        # Process GNU sparse information.
        if "GNU.sparse.map" in pax_headers:
            # GNU extended sparse format version 0.1.
            self._proc_gnusparse_01(next, pax_headers)

        elif "GNU.sparse.size" in pax_headers:
            # GNU extended sparse format version 0.0.
            self._proc_gnusparse_00(next, pax_headers, buf)

        elif pax_headers.get("GNU.sparse.major") == "1" and pax_headers.get("GNU.sparse.minor") == "0":
            # GNU extended sparse format version 1.0.
            self._proc_gnusparse_10(next, pax_headers, tarfile)

        if self.type in (XHDTYPE, SOLARIS_XHDTYPE):
            # Patch the TarInfo object with the extended header info.
            next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors)
            next.offset = self.offset

            if "size" in pax_headers:
                # If the extended header replaces the size field,
                # we need to recalculate the offset where the next
                # header starts.
                offset = next.offset_data
                if next.isreg() or next.type not in SUPPORTED_TYPES:
                    offset += next._block(next.size)
                tarfile.offset = offset

        return next
def _proc_pax ( self , tarfile ) : # Read the header information. buf = tarfile . fileobj . read ( self . _block ( self . size ) ) # A pax header stores supplemental information for either # the following file (extended) or all following files # (global). if self . type == XGLTYPE : pax_headers = tarfile . pax_headers else : pax_headers = tarfile . pax_headers . copy ( ) # Check if the pax header contains a hdrcharset field. This tells us # the encoding of the path, linkpath, uname and gname fields. Normally, # these fields are UTF-8 encoded but since POSIX.1-2008 tar # implementations are allowed to store them as raw binary strings if # the translation to UTF-8 fails. match = re . search ( br"\d+ hdrcharset=([^\n]+)\n" , buf ) if match is not None : pax_headers [ "hdrcharset" ] = match . group ( 1 ) . decode ( "utf8" ) # For the time being, we don't care about anything other than "BINARY". # The only other value that is currently allowed by the standard is # "ISO-IR 10646 2000 UTF-8" in other words UTF-8. hdrcharset = pax_headers . get ( "hdrcharset" ) if hdrcharset == "BINARY" : encoding = tarfile . encoding else : encoding = "utf8" # Parse pax header information. A record looks like that: # "%d %s=%s\n" % (length, keyword, value). length is the size # of the complete record including the length field itself and # the newline. keyword and value are both UTF-8 encoded strings. regex = re . compile ( br"(\d+) ([^=]+)=" ) pos = 0 while True : match = regex . match ( buf , pos ) if not match : break length , keyword = match . groups ( ) length = int ( length ) value = buf [ match . end ( 2 ) + 1 : match . start ( 1 ) + length - 1 ] # Normally, we could just use "utf8" as the encoding and "strict" # as the error handler, but we better not take the risk. For # example, GNU tar <= 1.23 is known to store filenames it cannot # translate to UTF-8 as raw strings (unfortunately without a # hdrcharset=BINARY header). # We first try the strict standard encoding, and if that fails we # fall back on the user's encoding and error handler. keyword = self . _decode_pax_field ( keyword , "utf8" , "utf8" , tarfile . errors ) if keyword in PAX_NAME_FIELDS : value = self . _decode_pax_field ( value , encoding , tarfile . encoding , tarfile . errors ) else : value = self . _decode_pax_field ( value , "utf8" , "utf8" , tarfile . errors ) pax_headers [ keyword ] = value pos += length # Fetch the next header. try : next = self . fromtarfile ( tarfile ) except HeaderError : raise SubsequentHeaderError ( "missing or bad subsequent header" ) # Process GNU sparse information. if "GNU.sparse.map" in pax_headers : # GNU extended sparse format version 0.1. self . _proc_gnusparse_01 ( next , pax_headers ) elif "GNU.sparse.size" in pax_headers : # GNU extended sparse format version 0.0. self . _proc_gnusparse_00 ( next , pax_headers , buf ) elif pax_headers . get ( "GNU.sparse.major" ) == "1" and pax_headers . get ( "GNU.sparse.minor" ) == "0" : # GNU extended sparse format version 1.0. self . _proc_gnusparse_10 ( next , pax_headers , tarfile ) if self . type in ( XHDTYPE , SOLARIS_XHDTYPE ) : # Patch the TarInfo object with the extended header info. next . _apply_pax_info ( pax_headers , tarfile . encoding , tarfile . errors ) next . offset = self . offset if "size" in pax_headers : # If the extended header replaces the size field, # we need to recalculate the offset where the next # header starts. offset = next . offset_data if next . isreg ( ) or next . type not in SUPPORTED_TYPES : offset += next . _block ( next . size ) tarfile . offset = offset return next