    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one
    003 * or more contributor license agreements.  See the NOTICE file
    004 * distributed with this work for additional information
    005 * regarding copyright ownership.  The ASF licenses this file
    006 * to you under the Apache License, Version 2.0 (the
    007 * "License"); you may not use this file except in compliance
    008 * with the License.  You may obtain a copy of the License at
    009 *
    010 *   https://www.apache.org/licenses/LICENSE-2.0
    011 *
    012 * Unless required by applicable law or agreed to in writing,
    013 * software distributed under the License is distributed on an
    014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015 * KIND, either express or implied.  See the License for the
    016 * specific language governing permissions and limitations
    017 * under the License.
    018 */
    019package org.apache.commons.compress.archivers.tar;
    020
    021import java.io.IOException;
    022import java.util.ArrayList;
    023import java.util.List;
    024
    025/**
    026 * A sparse entry in a <a href="https://www.gnu.org/software/tar/manual/html_node/Standard.html">Tar archive</a>.
    027 *
    028 * <p>
    029 * The C structure for a sparse entry is:
    030 *
    031 * <pre>
    032 * struct posix_header {
    033 * struct sparse sp[21]; // TarConstants.SPARSELEN_GNU_SPARSE     - offset 0
    034 * char isextended;      // TarConstants.ISEXTENDEDLEN_GNU_SPARSE - offset 504
    035 * };
    036 * </pre>
    037 *
    038 * Whereas, "struct sparse" is:
    039 *
    040 * <pre>
    041 * struct sparse {
    042 * char offset[12];   // offset 0
    043 * char numbytes[12]; // offset 12
    044 * };
    045 * </pre>
    046 *
    047 * <p>
    048 * Each such struct describes a block of data that has actually been written to the archive. The offset describes where in the extracted file the data is
    049 * supposed to start and the numbytes provides the length of the block. When extracting the entry the gaps between the sparse structs are equivalent to areas
    050 * filled with zero bytes.
    051 * </p>
    052 */
    053
    054public class TarArchiveSparseEntry implements TarConstants {
    055    /** If an extension sparse header follows. */
    056    private final boolean isExtended;
    057
    058    private final List<TarArchiveStructSparse> sparseHeaders;
    059
    060    /**
    061     * Constructs an entry from an archive's header bytes. File is set to null.
    062     *
    063     * @param headerBuf The header bytes from a tar archive entry.
    064     * @throws IOException on unknown format
    065     */
    066    public TarArchiveSparseEntry(final byte[] headerBuf) throws IOException {
    067        int offset = 0;
    068        sparseHeaders = new ArrayList<>(TarUtils.readSparseStructs(headerBuf, 0, SPARSE_HEADERS_IN_EXTENSION_HEADER));
    069        offset += SPARSELEN_GNU_SPARSE;
    070        isExtended = TarUtils.parseBoolean(headerBuf, offset);
    071    }
    072
    073    /**
    074     * Gets information about the configuration for the sparse entry.
    075     *
    076     * @return information about the configuration for the sparse entry.
    077     * @since 1.20
    078     */
    079    public List<TarArchiveStructSparse> getSparseHeaders() {
    080        return sparseHeaders;
    081    }
    082
    083    /**
    084     * Tests whether this entry is extended.
    085     *
    086     * @return whether this entry is extended.
    087     */
    088    public boolean isExtended() {
    089        return isExtended;
    090    }
    091}