    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 * http://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.cpio;
    020
    021import java.io.File;
    022import java.io.IOException;
    023import java.nio.charset.Charset;
    024import java.nio.file.Files;
    025import java.nio.file.LinkOption;
    026import java.nio.file.Path;
    027import java.nio.file.attribute.FileTime;
    028import java.util.Date;
    029import java.util.Objects;
    030
    031import org.apache.commons.compress.archivers.ArchiveEntry;
    032import org.apache.commons.compress.utils.ExactMath;
    033import org.apache.commons.compress.utils.TimeUtils;
    034
    035/**
    036 * A cpio archive consists of a sequence of files. There are several types of
    037 * headers defined in two categories of new and old format. The headers are
    038 * recognized by magic numbers:
    039 *
    040 * <ul>
    041 * <li>"070701" ASCII for new portable format</li>
    042 * <li>"070702" ASCII for new portable format with CRC</li>
    043 * <li>"070707" ASCII for old ASCII (also known as Portable ASCII, odc or old
    044 * character format</li>
    045 * <li>070707 binary for old binary</li>
    046 * </ul>
    047 *
    048 * <p>The old binary format is limited to 16 bits for user id, group
    049 * id, device, and inode numbers. It is limited to 4 gigabyte file
    050 * sizes.
    051 *
    052 * The old ASCII format is limited to 18 bits for the user id, group
    053 * id, device, and inode numbers. It is limited to 8 gigabyte file
    054 * sizes.
    055 *
    056 * The new ASCII format is limited to 4 gigabyte file sizes.
    057 *
    058 * CPIO 2.5 knows also about tar, but it is not recognized here.</p>
    059 *
    060 *
    061 * <h2>OLD FORMAT</h2>
    062 *
    063 * <p>Each file has a 76 (ascii) / 26 (binary) byte header, a variable
    064 * length, NUL terminated file name, and variable length file data. A
    065 * header for a file name "TRAILER!!!" indicates the end of the
    066 * archive.</p>
    067 *
    068 * <p>All the fields in the header are ISO 646 (approximately ASCII)
    069 * strings of octal numbers, left padded, not NUL terminated.</p>
    070 *
    071 * <pre>
    072 * FIELDNAME        NOTES
    073 * c_magic          The integer value octal 070707.  This value can be used to deter-
    074 *                  mine whether this archive is written with little-endian or big-
    075 *                  endian integers.
    076 * c_dev            Device that contains a directory entry for this file
    077 * c_ino            I-node number that identifies the input file to the file system
    078 * c_mode           The mode specifies both the regular permissions and the file type.
    079 * c_uid            Numeric User ID of the owner of the input file
    080 * c_gid            Numeric Group ID of the owner of the input file
    081 * c_nlink          Number of links that are connected to the input file
    082 * c_rdev           For block special and character special entries, this field
    083 *                  contains the associated device number.  For all other entry types,
    084 *                  it should be set to zero by writers and ignored by readers.
    085 * c_mtime[2]       Modification time of the file, indicated as the number of seconds
    086 *                  since the start of the epoch, 00:00:00 UTC January 1, 1970.  The
    087 *                  four-byte integer is stored with the most-significant 16 bits
    088 *                  first followed by the least-significant 16 bits.  Each of the two
    089 *                  16 bit values are stored in machine-native byte order.
    090 * c_namesize       Length of the path name, including the terminating null byte
    091 * c_filesize[2]    Length of the file in bytes. This is the length of the data
    092 *                  section that follows the header structure. Must be 0 for
    093 *                  FIFOs and directories
    094 *
    095 * All fields are unsigned short fields with 16-bit integer values
    096 * apart from c_mtime and c_filesize which are 32-bit integer values
    097 * </pre>
    098 *
    099 * <p>If necessary, the file name and file data are padded with a NUL byte to an even length</p>
    100 *
    101 * <p>Special files, directories, and the trailer are recorded with
    102 * the h_filesize field equal to 0.</p>
    103 *
    104 * <p>In the ASCII version of this format, the 16-bit entries are represented as 6-byte octal numbers,
    105 * and the 32-bit entries are represented as 11-byte octal numbers. No padding is added.</p>
    106 *
    107 * <h3>NEW FORMAT</h3>
    108 *
    109 * <p>Each file has a 110 byte header, a variable length, NUL
    110 * terminated file name, and variable length file data. A header for a
    111 * file name "TRAILER!!!" indicates the end of the archive. All the
    112 * fields in the header are ISO 646 (approximately ASCII) strings of
    113 * hexadecimal numbers, left padded, not NUL terminated.</p>
    114 *
    115 * <pre>
    116 * FIELDNAME        NOTES
    117 * c_magic[6]       The string 070701 for new ASCII, the string 070702 for new ASCII with CRC
    118 * c_ino[8]
    119 * c_mode[8]
    120 * c_uid[8]
    121 * c_gid[8]
    122 * c_nlink[8]
    123 * c_mtim[8]
    124 * c_filesize[8]    must be 0 for FIFOs and directories
    125 * c_maj[8]
    126 * c_min[8]
    127 * c_rmaj[8]        only valid for chr and blk special files
    128 * c_rmin[8]        only valid for chr and blk special files
    129 * c_namesize[8]    count includes terminating NUL in path name
    130 * c_check[8]       0 for "new" portable format; for CRC format
    131 *                  the sum of all the bytes in the file
    132 * </pre>
    133 *
    134 * <p>New ASCII Format The "new" ASCII format uses 8-byte hexadecimal
    135 * fields for all numbers and separates device numbers into separate
    136 * fields for major and minor numbers.</p>
    137 *
    138 * <p>The path name is followed by NUL bytes so that the total size of
    139 * the fixed header plus path name is a multiple of four. Likewise, the
    140 * file data is padded to a multiple of four bytes.</p>
    141 *
    142 * <p>This class uses mutable fields and is not considered to be
    143 * threadsafe.</p>
    144 *
    145 * <p>Based on code from the jRPM project (http://jrpm.sourceforge.net).</p>
    146 *
    147 * <p>The MAGIC numbers and other constants are defined in {@link CpioConstants}</p>
    148 *
    149 * <p>
    150 * N.B. does not handle the cpio "tar" format
    151 * </p>
    152 * @NotThreadSafe
    153 * @see <a href="https://people.freebsd.org/~kientzle/libarchive/man/cpio.5.txt">https://people.freebsd.org/~kientzle/libarchive/man/cpio.5.txt</a>
    154 */
    155public class CpioArchiveEntry implements CpioConstants, ArchiveEntry {
    156
    157    // Header description fields - should be same throughout an archive
    158
    159    /**
    160     * See {@link #CpioArchiveEntry(short)} for possible values.
    161     */
    162    private final short fileFormat;
    163
    164    /** The number of bytes in each header record; depends on the file format */
    165    private final int headerSize;
    166
    167    /** The boundary to which the header and data elements are aligned: 0, 2 or 4 bytes */
    168    private final int alignmentBoundary;
    169
    170    // Header fields
    171
    172    private long chksum;
    173
    174    /** Number of bytes in the file */
    175    private long filesize;
    176
    177    private long gid;
    178
    179    private long inode;
    180
    181    private long maj;
    182
    183    private long min;
    184
    185    private long mode;
    186
    187    private long mtime;
    188
    189    private String name;
    190
    191    private long nlink;
    192
    193    private long rmaj;
    194
    195    private long rmin;
    196
    197    private long uid;
    198
    199    /**
    200     * Creates a CpioArchiveEntry with a specified name for a
    201     * specified file. The format of this entry will be the new
    202     * format.
    203     *
    204     * @param inputFile
    205     *            The file to gather information from.
    206     * @param entryName
    207     *            The name of this entry.
    208     */
    209    public CpioArchiveEntry(final File inputFile, final String entryName) {
    210        this(FORMAT_NEW, inputFile, entryName);
    211    }
    212
    213    /**
    214     * Creates a CpioArchiveEntry with a specified name for a
    215     * specified file. The format of this entry will be the new
    216     * format.
    217     *
    218     * @param inputPath
    219     *            The file to gather information from.
    220     * @param entryName
    221     *            The name of this entry.
    222     * @param options options indicating how symbolic links are handled.
    223     * @throws IOException if an I/O error occurs
    224     * @since 1.21
    225     */
    226    public CpioArchiveEntry(final Path inputPath, final String entryName, final LinkOption... options) throws IOException {
    227        this(FORMAT_NEW, inputPath, entryName, options);
    228    }
    229
    230    /**
    231     * Creates a CpioArchiveEntry with a specified format.
    232     *
    233     * @param format
    234     *            The cpio format for this entry.
    235     * <p>
    236     * Possible format values are:
    237     * <pre>
    238     * CpioConstants.FORMAT_NEW
    239     * CpioConstants.FORMAT_NEW_CRC
    240     * CpioConstants.FORMAT_OLD_BINARY
    241     * CpioConstants.FORMAT_OLD_ASCII
    242     * </pre>
    243     */
    244    public CpioArchiveEntry(final short format) {
    245        switch (format) {
    246        case FORMAT_NEW:
    247            this.headerSize = 110;
    248            this.alignmentBoundary = 4;
    249            break;
    250        case FORMAT_NEW_CRC:
    251            this.headerSize = 110;
    252            this.alignmentBoundary = 4;
    253            break;
    254        case FORMAT_OLD_ASCII:
    255            this.headerSize = 76;
    256            this.alignmentBoundary = 0;
    257            break;
    258        case FORMAT_OLD_BINARY:
    259            this.headerSize = 26;
    260            this.alignmentBoundary = 2;
    261            break;
    262        default:
    263            throw new IllegalArgumentException("Unknown header type " + format);
    264        }
    265        this.fileFormat = format;
    266    }
    267
    268    /**
    269     * Creates a CpioArchiveEntry with a specified name for a
    270     * specified file.
    271     *
    272     * @param format
    273     *            The cpio format for this entry.
    274     * @param inputFile
    275     *            The file to gather information from.
    276     * @param entryName
    277     *            The name of this entry.
    278     * <p>
    279     * Possible format values are:
    280     * <pre>
    281     * CpioConstants.FORMAT_NEW
    282     * CpioConstants.FORMAT_NEW_CRC
    283     * CpioConstants.FORMAT_OLD_BINARY
    284     * CpioConstants.FORMAT_OLD_ASCII
    285     * </pre>
    286     *
    287     * @since 1.1
    288     */
    289    public CpioArchiveEntry(final short format, final File inputFile, final String entryName) {
    290        this(format, entryName, inputFile.isFile() ? inputFile.length() : 0);
    291        if (inputFile.isDirectory()) {
    292            setMode(C_ISDIR);
    293        } else if (inputFile.isFile()) {
    294            setMode(C_ISREG);
    295        } else {
    296            throw new IllegalArgumentException("Cannot determine type of file " + inputFile.getName());
    297        }
    298        // TODO set other fields as needed
    299        setTime(inputFile.lastModified() / 1000);
    300    }
    301
    302    /**
    303     * Creates a CpioArchiveEntry with a specified name for a
    304     * specified path.
    305     *
    306     * @param format
    307     *            The cpio format for this entry.
    308     * @param inputPath
    309     *            The file to gather information from.
    310     * @param entryName
    311     *            The name of this entry.
    312     * <p>
    313     * Possible format values are:
    314     * <pre>
    315     * CpioConstants.FORMAT_NEW
    316     * CpioConstants.FORMAT_NEW_CRC
    317     * CpioConstants.FORMAT_OLD_BINARY
    318     * CpioConstants.FORMAT_OLD_ASCII
    319     * </pre>
    320     * @param options options indicating how symbolic links are handled.
    321     *
    322     * @throws IOException if an I/O error occurs
    323     * @since 1.21
    324     */
    325    public CpioArchiveEntry(final short format, final Path inputPath, final String entryName, final LinkOption... options)
    326        throws IOException {
    327        this(format, entryName, Files.isRegularFile(inputPath, options) ? Files.size(inputPath) : 0);
    328        if (Files.isDirectory(inputPath, options)) {
    329            setMode(C_ISDIR);
    330        } else if (Files.isRegularFile(inputPath, options)) {
    331            setMode(C_ISREG);
    332        } else {
    333            throw new IllegalArgumentException("Cannot determine type of file " + inputPath);
    334        }
    335        // TODO set other fields as needed
    336        setTime(Files.getLastModifiedTime(inputPath, options));
    337    }
    338
    339    /**
    340     * Creates a CpioArchiveEntry with a specified name.
    341     *
    342     * @param format
    343     *            The cpio format for this entry.
    344     * @param name
    345     *            The name of this entry.
    346     * <p>
    347     * Possible format values are:
    348     * <pre>
    349     * CpioConstants.FORMAT_NEW
    350     * CpioConstants.FORMAT_NEW_CRC
    351     * CpioConstants.FORMAT_OLD_BINARY
    352     * CpioConstants.FORMAT_OLD_ASCII
    353     * </pre>
    354     *
    355     * @since 1.1
    356     */
    357    public CpioArchiveEntry(final short format, final String name) {
    358        this(format);
    359        this.name = name;
    360    }
    361
    362    /**
    363     * Creates a CpioArchiveEntry with a specified name.
    364     *
    365     * @param format
    366     *            The cpio format for this entry.
    367     * @param name
    368     *            The name of this entry.
    369     * @param size
    370     *            The size of this entry
    371     * <p>
    372     * Possible format values are:
    373     * <pre>
    374     * CpioConstants.FORMAT_NEW
    375     * CpioConstants.FORMAT_NEW_CRC
    376     * CpioConstants.FORMAT_OLD_BINARY
    377     * CpioConstants.FORMAT_OLD_ASCII
    378     * </pre>
    379     *
    380     * @since 1.1
    381     */
    382    public CpioArchiveEntry(final short format, final String name,
    383                            final long size) {
    384        this(format, name);
    385        this.setSize(size);
    386    }
    387
    388    /**
    389     * Creates a CpioArchiveEntry with a specified name. The format of
    390     * this entry will be the new format.
    391     *
    392     * @param name
    393     *            The name of this entry.
    394     */
    395    public CpioArchiveEntry(final String name) {
    396        this(FORMAT_NEW, name);
    397    }
    398
    399    /**
    400     * Creates a CpioArchiveEntry with a specified name. The format of
    401     * this entry will be the new format.
    402     *
    403     * @param name
    404     *            The name of this entry.
    405     * @param size
    406     *            The size of this entry
    407     */
    408    public CpioArchiveEntry(final String name, final long size) {
    409        this(name);
    410        this.setSize(size);
    411    }
    412
    413    /**
    414     * Checks if the method is allowed for the defined format.
    415     */
    416    private void checkNewFormat() {
    417        if ((this.fileFormat & FORMAT_NEW_MASK) == 0) {
    418            throw new UnsupportedOperationException();
    419        }
    420    }
    421
    422    /**
    423     * Checks if the method is allowed for the defined format.
    424     */
    425    private void checkOldFormat() {
    426        if ((this.fileFormat & FORMAT_OLD_MASK) == 0) {
    427            throw new UnsupportedOperationException();
    428        }
    429    }
    430
    431    /* (non-Javadoc)
    432     * @see Object#equals(Object)
    433     */
    434    @Override
    435    public boolean equals(final Object obj) {
    436        if (this == obj) {
    437            return true;
    438        }
    439        if (obj == null || getClass() != obj.getClass()) {
    440            return false;
    441        }
    442        final CpioArchiveEntry other = (CpioArchiveEntry) obj;
    443        if (name == null) {
    444            return other.name == null;
    445        }
    446        return name.equals(other.name);
    447    }
    448
    449    /**
    450     * Gets the alignment boundary for this CPIO format
    451     *
    452     * @return Returns the aligment boundary (0, 2, 4) in bytes
    453     */
    454    public int getAlignmentBoundary() {
    455        return this.alignmentBoundary;
    456    }
    457
    458    /**
    459     * Gets the checksum.
    460     * Only supported for the new formats.
    461     *
    462     * @return Returns the checksum.
    463     * @throws UnsupportedOperationException if the format is not a new format
    464     */
    465    public long getChksum() {
    466        checkNewFormat();
    467        return this.chksum & 0xFFFFFFFFL;
    468    }
    469
    470    /**
    471     * Gets the number of bytes needed to pad the data to the alignment boundary.
    472     *
    473     * @return the number of bytes needed to pad the data (0,1,2,3)
    474     */
    475    public int getDataPadCount() {
    476        if (this.alignmentBoundary == 0) {
    477            return 0;
    478        }
    479        final long size = this.filesize;
    480        final int remain = (int) (size % this.alignmentBoundary);
    481        if (remain > 0) {
    482            return this.alignmentBoundary - remain;
    483        }
    484        return 0;
    485    }
    486
    487    /**
    488     * Gets the device id.
    489     *
    490     * @return Returns the device id.
    491     * @throws UnsupportedOperationException
    492     *             if this method is called for a CpioArchiveEntry with a new
    493     *             format.
    494     */
    495    public long getDevice() {
    496        checkOldFormat();
    497        return this.min;
    498    }
    499
    500    /**
    501     * Gets the major device id.
    502     *
    503     * @return Returns the major device id.
    504     * @throws UnsupportedOperationException
    505     *             if this method is called for a CpioArchiveEntry with an old
    506     *             format.
    507     */
    508    public long getDeviceMaj() {
    509        checkNewFormat();
    510        return this.maj;
    511    }
    512
    513    /**
    514     * Gets the minor device id
    515     *
    516     * @return Returns the minor device id.
    517     * @throws UnsupportedOperationException if format is not a new format
    518     */
    519    public long getDeviceMin() {
    520        checkNewFormat();
    521        return this.min;
    522    }
    523
    524    /**
    525     * Gets the format for this entry.
    526     *
    527     * @return Returns the format.
    528     */
    529    public short getFormat() {
    530        return this.fileFormat;
    531    }
    532
    533    /**
    534     * Gets the group id.
    535     *
    536     * @return Returns the group id.
    537     */
    538    public long getGID() {
    539        return this.gid;
    540    }
    541
    542    /**
    543     * Gets the number of bytes needed to pad the header to the alignment boundary.
    544     *
    545     * @deprecated This method doesn't properly work for multi-byte encodings. And
    546     *             creates corrupt archives. Use {@link #getHeaderPadCount(Charset)}
    547     *             or {@link #getHeaderPadCount(long)} in any case.
    548     * @return the number of bytes needed to pad the header (0,1,2,3)
    549     */
    550    @Deprecated
    551    public int getHeaderPadCount(){
    552        return getHeaderPadCount(null);
    553    }
    554
    555    /**
    556     * Gets the number of bytes needed to pad the header to the alignment boundary.
    557     *
    558     * @param charset
    559     *             The character set used to encode the entry name in the stream.
    560     * @return the number of bytes needed to pad the header (0,1,2,3)
    561     * @since 1.18
    562     */
    563    public int getHeaderPadCount(final Charset charset) {
    564        if (name == null) {
    565            return 0;
    566        }
    567        if (charset == null) {
    568            return getHeaderPadCount(name.length());
    569        }
    570        return getHeaderPadCount(name.getBytes(charset).length);
    571    }
    572
    573    /**
    574     * Gets the number of bytes needed to pad the header to the alignment boundary.
    575     *
    576     * @param nameSize
    577     *            The length of the name in bytes, as read in the stream.
    578     *            Without the trailing zero byte.
    579     * @return the number of bytes needed to pad the header (0,1,2,3)
    580     *
    581     * @since 1.18
    582     */
    583    public int getHeaderPadCount(final long nameSize) {
    584        if (this.alignmentBoundary == 0) {
    585            return 0;
    586        }
    587        int size = this.headerSize + 1; // Name has terminating null
    588        if (name != null) {
    589            size = ExactMath.add(size, nameSize);
    590        }
    591        final int remain = size % this.alignmentBoundary;
    592        if (remain > 0) {
    593            return this.alignmentBoundary - remain;
    594        }
    595        return 0;
    596    }
    597
    598    /**
    599     * Gets the header size for this CPIO format
    600     *
    601     * @return Returns the header size in bytes.
    602     */
    603    public int getHeaderSize() {
    604        return this.headerSize;
    605    }
    606
    607    /**
    608     * Sets the inode.
    609     *
    610     * @return Returns the inode.
    611     */
    612    public long getInode() {
    613        return this.inode;
    614    }
    615
    616    @Override
    617    public Date getLastModifiedDate() {
    618        return new Date(1000 * getTime());
    619    }
    620
    621    /**
    622     * Gets the mode of this entry (e.g. directory, regular file).
    623     *
    624     * @return Returns the mode.
    625     */
    626    public long getMode() {
    627        return mode == 0 && !CPIO_TRAILER.equals(name) ? C_ISREG : mode;
    628    }
    629
    630    /**
    631     * Gets the name.
    632     *
    633     * <p>This method returns the raw name as it is stored inside of the archive.</p>
    634     *
    635     * @return Returns the name.
    636     */
    637    @Override
    638    public String getName() {
    639        return this.name;
    640    }
    641
    642    /**
    643     * Gets the number of links.
    644     *
    645     * @return Returns the number of links.
    646     */
    647    public long getNumberOfLinks() {
    648        return nlink == 0 ? isDirectory() ? 2 : 1 : nlink;
    649    }
    650
    651    /**
    652     * Gets the remote device id.
    653     *
    654     * @return Returns the remote device id.
    655     * @throws UnsupportedOperationException
    656     *             if this method is called for a CpioArchiveEntry with a new
    657     *             format.
    658     */
    659    public long getRemoteDevice() {
    660        checkOldFormat();
    661        return this.rmin;
    662    }
    663
    664    /**
    665     * Gets the remote major device id.
    666     *
    667     * @return Returns the remote major device id.
    668     * @throws UnsupportedOperationException
    669     *             if this method is called for a CpioArchiveEntry with an old
    670     *             format.
    671     */
    672    public long getRemoteDeviceMaj() {
    673        checkNewFormat();
    674        return this.rmaj;
    675    }
    676
    677    /**
    678     * Gets the remote minor device id.
    679     *
    680     * @return Returns the remote minor device id.
    681     * @throws UnsupportedOperationException
    682     *             if this method is called for a CpioArchiveEntry with an old
    683     *             format.
    684     */
    685    public long getRemoteDeviceMin() {
    686        checkNewFormat();
    687        return this.rmin;
    688    }
    689
    690    /**
    691     * Gets the filesize.
    692     *
    693     * @return Returns the filesize.
    694     * @see org.apache.commons.compress.archivers.ArchiveEntry#getSize()
    695     */
    696    @Override
    697    public long getSize() {
    698        return this.filesize;
    699    }
    700
    701    /**
    702     * Gets the time in seconds.
    703     *
    704     * @return Returns the time.
    705     */
    706    public long getTime() {
    707        return this.mtime;
    708    }
    709
    710    /**
    711     * Gets the user id.
    712     *
    713     * @return Returns the user id.
    714     */
    715    public long getUID() {
    716        return this.uid;
    717    }
    718
    719    /* (non-Javadoc)
    720     * @see Object#hashCode()
    721     */
    722    @Override
    723    public int hashCode() {
    724        return Objects.hash(name);
    725    }
    726
    727    /**
    728     * Checks if this entry represents a block device.
    729     *
    730     * @return TRUE if this entry is a block device.
    731     */
    732    public boolean isBlockDevice() {
    733        return CpioUtil.fileType(mode) == C_ISBLK;
    734    }
    735
    736    /**
    737     * Checks if this entry represents a character device.
    738     *
    739     * @return TRUE if this entry is a character device.
    740     */
    741    public boolean isCharacterDevice() {
    742        return CpioUtil.fileType(mode) == C_ISCHR;
    743    }
    744
    745    /**
    746     * Checks if this entry represents a directory.
    747     *
    748     * @return TRUE if this entry is a directory.
    749     */
    750    @Override
    751    public boolean isDirectory() {
    752        return CpioUtil.fileType(mode) == C_ISDIR;
    753    }
    754
    755    /**
    756     * Checks if this entry represents a network device.
    757     *
    758     * @return TRUE if this entry is a network device.
    759     */
    760    public boolean isNetwork() {
    761        return CpioUtil.fileType(mode) == C_ISNWK;
    762    }
    763
    764    /**
    765     * Checks if this entry represents a pipe.
    766     *
    767     * @return TRUE if this entry is a pipe.
    768     */
    769    public boolean isPipe() {
    770        return CpioUtil.fileType(mode) == C_ISFIFO;
    771    }
    772
    773    /**
    774     * Checks if this entry represents a regular file.
    775     *
    776     * @return TRUE if this entry is a regular file.
    777     */
    778    public boolean isRegularFile() {
    779        return CpioUtil.fileType(mode) == C_ISREG;
    780    }
    781
    782    /**
    783     * Checks if this entry represents a socket.
    784     *
    785     * @return TRUE if this entry is a socket.
    786     */
    787    public boolean isSocket() {
    788        return CpioUtil.fileType(mode) == C_ISSOCK;
    789    }
    790
    791    /**
    792     * Checks if this entry represents a symbolic link.
    793     *
    794     * @return TRUE if this entry is a symbolic link.
    795     */
    796    public boolean isSymbolicLink() {
    797        return CpioUtil.fileType(mode) == C_ISLNK;
    798    }
    799
    800    /**
    801     * Sets the checksum. The checksum is calculated by adding all bytes of a
    802     * file to transfer (crc += buf[pos] &amp; 0xFF).
    803     *
    804     * @param chksum
    805     *            The checksum to set.
    806     */
    807    public void setChksum(final long chksum) {
    808        checkNewFormat();
    809        this.chksum = chksum & 0xFFFFFFFFL;
    810    }
    811
    812    /**
    813     * Sets the device id.
    814     *
    815     * @param device
    816     *            The device id to set.
    817     * @throws UnsupportedOperationException
    818     *             if this method is called for a CpioArchiveEntry with a new
    819     *             format.
    820     */
    821    public void setDevice(final long device) {
    822        checkOldFormat();
    823        this.min = device;
    824    }
    825
    826    /**
    827     * Sets major device id.
    828     *
    829     * @param maj
    830     *            The major device id to set.
    831     */
    832    public void setDeviceMaj(final long maj) {
    833        checkNewFormat();
    834        this.maj = maj;
    835    }
    836
    837    /**
    838     * Sets the minor device id
    839     *
    840     * @param min
    841     *            The minor device id to set.
    842     */
    843    public void setDeviceMin(final long min) {
    844        checkNewFormat();
    845        this.min = min;
    846    }
    847
    848    /**
    849     * Sets the group id.
    850     *
    851     * @param gid
    852     *            The group id to set.
    853     */
    854    public void setGID(final long gid) {
    855        this.gid = gid;
    856    }
    857
    858    /**
    859     * Sets the inode.
    860     *
    861     * @param inode
    862     *            The inode to set.
    863     */
    864    public void setInode(final long inode) {
    865        this.inode = inode;
    866    }
    867
    868    /**
    869     * Sets the mode of this entry (e.g. directory, regular file).
    870     *
    871     * @param mode
    872     *            The mode to set.
    873     */
    874    public void setMode(final long mode) {
    875        final long maskedMode = mode & S_IFMT;
    876        switch ((int) maskedMode) {
    877        case C_ISDIR:
    878        case C_ISLNK:
    879        case C_ISREG:
    880        case C_ISFIFO:
    881        case C_ISCHR:
    882        case C_ISBLK:
    883        case C_ISSOCK:
    884        case C_ISNWK:
    885            break;
    886        default:
    887            throw new IllegalArgumentException("Unknown mode. " + "Full: " + Long.toHexString(mode) + " Masked: " + Long.toHexString(maskedMode));
    888        }
    889
    890        this.mode = mode;
    891    }
    892
    893    /**
    894     * Sets the name.
    895     *
    896     * @param name
    897     *            The name to set.
    898     */
    899    public void setName(final String name) {
    900        this.name = name;
    901    }
    902
    903    /**
    904     * Sets the number of links.
    905     *
    906     * @param nlink
    907     *            The number of links to set.
    908     */
    909    public void setNumberOfLinks(final long nlink) {
    910        this.nlink = nlink;
    911    }
    912
    913    /**
    914     * Sets the remote device id.
    915     *
    916     * @param device
    917     *            The remote device id to set.
    918     * @throws UnsupportedOperationException
    919     *             if this method is called for a CpioArchiveEntry with a new
    920     *             format.
    921     */
    922    public void setRemoteDevice(final long device) {
    923        checkOldFormat();
    924        this.rmin = device;
    925    }
    926
    927    /**
    928     * Sets the remote major device id.
    929     *
    930     * @param rmaj
    931     *            The remote major device id to set.
    932     * @throws UnsupportedOperationException
    933     *             if this method is called for a CpioArchiveEntry with an old
    934     *             format.
    935     */
    936    public void setRemoteDeviceMaj(final long rmaj) {
    937        checkNewFormat();
    938        this.rmaj = rmaj;
    939    }
    940
    941    /**
    942     * Sets the remote minor device id.
    943     *
    944     * @param rmin
    945     *            The remote minor device id to set.
    946     * @throws UnsupportedOperationException
    947     *             if this method is called for a CpioArchiveEntry with an old
    948     *             format.
    949     */
    950    public void setRemoteDeviceMin(final long rmin) {
    951        checkNewFormat();
    952        this.rmin = rmin;
    953    }
    954
    955    /**
    956     * Sets the filesize.
    957     *
    958     * @param size
    959     *            The filesize to set.
    960     */
    961    public void setSize(final long size) {
    962        if (size < 0 || size > 0xFFFFFFFFL) {
    963            throw new IllegalArgumentException("Invalid entry size <" + size + ">");
    964        }
    965        this.filesize = size;
    966    }
    967
    968    /**
    969     * Sets the time.
    970     *
    971     * @param time
    972     *            The time to set.
    973     */
    974    public void setTime(final FileTime time) {
    975        this.mtime = TimeUtils.toUnixTime(time);
    976    }
    977
    978    /**
    979     * Sets the time in seconds.
    980     *
    981     * @param time
    982     *            The time to set.
    983     */
    984    public void setTime(final long time) {
    985        this.mtime = time;
    986    }
    987
    988    /**
    989     * Sets the user id.
    990     *
    991     * @param uid
    992     *            The user id to set.
    993     */
    994    public void setUID(final long uid) {
    995        this.uid = uid;
    996    }
    997}