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