    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        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        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        return Objects.equals(name, other.name);
    432    }
    433
    434    /**
    435     * Gets the alignment boundary for this CPIO format
    436     *
    437     * @return the alignment boundary (0, 2, 4) in bytes
    438     */
    439    public int getAlignmentBoundary() {
    440        return this.alignmentBoundary;
    441    }
    442
    443    /**
    444     * Gets the checksum. Only supported for the new formats.
    445     *
    446     * @return the checksum.
    447     * @throws UnsupportedOperationException if the format is not a new format
    448     */
    449    public long getChksum() {
    450        checkNewFormat();
    451        return this.chksum & 0xFFFFFFFFL;
    452    }
    453
    454    /**
    455     * Gets the number of bytes needed to pad the data to the alignment boundary.
    456     *
    457     * @return the number of bytes needed to pad the data (0,1,2,3)
    458     */
    459    public int getDataPadCount() {
    460        if (this.alignmentBoundary == 0) {
    461            return 0;
    462        }
    463        final long size = this.filesize;
    464        final int remain = (int) (size % this.alignmentBoundary);
    465        if (remain > 0) {
    466            return this.alignmentBoundary - remain;
    467        }
    468        return 0;
    469    }
    470
    471    /**
    472     * Gets the device id.
    473     *
    474     * @return the device id.
    475     * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with a new format.
    476     */
    477    public long getDevice() {
    478        checkOldFormat();
    479        return this.min;
    480    }
    481
    482    /**
    483     * Gets the major device id.
    484     *
    485     * @return the major device id.
    486     * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with an old format.
    487     */
    488    public long getDeviceMaj() {
    489        checkNewFormat();
    490        return this.maj;
    491    }
    492
    493    /**
    494     * Gets the minor device id
    495     *
    496     * @return the minor device id.
    497     * @throws UnsupportedOperationException if format is not a new format
    498     */
    499    public long getDeviceMin() {
    500        checkNewFormat();
    501        return this.min;
    502    }
    503
    504    /**
    505     * Gets the format for this entry.
    506     *
    507     * @return the format.
    508     */
    509    public short getFormat() {
    510        return this.fileFormat;
    511    }
    512
    513    /**
    514     * Gets the group id.
    515     *
    516     * @return the group id.
    517     */
    518    public long getGID() {
    519        return this.gid;
    520    }
    521
    522    /**
    523     * Gets the number of bytes needed to pad the header to the alignment boundary.
    524     *
    525     * @deprecated This method doesn't properly work for multi-byte encodings. And creates corrupt archives. Use {@link #getHeaderPadCount(Charset)} or
    526     *             {@link #getHeaderPadCount(long)} in any case.
    527     * @return the number of bytes needed to pad the header (0,1,2,3)
    528     */
    529    @Deprecated
    530    public int getHeaderPadCount() {
    531        return getHeaderPadCount(null);
    532    }
    533
    534    /**
    535     * Gets the number of bytes needed to pad the header to the alignment boundary.
    536     *
    537     * @param charset The character set used to encode the entry name in the stream.
    538     * @return the number of bytes needed to pad the header (0,1,2,3)
    539     * @since 1.18
    540     */
    541    public int getHeaderPadCount(final Charset charset) {
    542        if (name == null) {
    543            return 0;
    544        }
    545        if (charset == null) {
    546            return getHeaderPadCount(name.length());
    547        }
    548        return getHeaderPadCount(name.getBytes(charset).length);
    549    }
    550
    551    /**
    552     * Gets the number of bytes needed to pad the header to the alignment boundary.
    553     *
    554     * @param nameSize The length of the name in bytes, as read in the stream. Without the trailing zero byte.
    555     * @return the number of bytes needed to pad the header (0,1,2,3)
    556     *
    557     * @since 1.18
    558     */
    559    public int getHeaderPadCount(final long nameSize) {
    560        if (this.alignmentBoundary == 0) {
    561            return 0;
    562        }
    563        int size = this.headerSize + 1; // Name has terminating null
    564        if (name != null) {
    565            size = ExactMath.add(size, nameSize);
    566        }
    567        final int remain = size % this.alignmentBoundary;
    568        if (remain > 0) {
    569            return this.alignmentBoundary - remain;
    570        }
    571        return 0;
    572    }
    573
    574    /**
    575     * Gets the header size for this CPIO format
    576     *
    577     * @return the header size in bytes.
    578     */
    579    public int getHeaderSize() {
    580        return this.headerSize;
    581    }
    582
    583    /**
    584     * Sets the inode.
    585     *
    586     * @return the inode.
    587     */
    588    public long getInode() {
    589        return this.inode;
    590    }
    591
    592    @Override
    593    public Date getLastModifiedDate() {
    594        return new Date(1000 * getTime());
    595    }
    596
    597    /**
    598     * Gets the mode of this entry (e.g. directory, regular file).
    599     *
    600     * @return the mode.
    601     */
    602    public long getMode() {
    603        return mode == 0 && !CPIO_TRAILER.equals(name) ? C_ISREG : mode;
    604    }
    605
    606    /**
    607     * Gets the name.
    608     *
    609     * <p>
    610     * This method returns the raw name as it is stored inside of the archive.
    611     * </p>
    612     *
    613     * @return the name.
    614     */
    615    @Override
    616    public String getName() {
    617        return this.name;
    618    }
    619
    620    /**
    621     * Gets the number of links.
    622     *
    623     * @return the number of links.
    624     */
    625    public long getNumberOfLinks() {
    626        return nlink == 0 ? isDirectory() ? 2 : 1 : nlink;
    627    }
    628
    629    /**
    630     * Gets the remote device id.
    631     *
    632     * @return the remote device id.
    633     * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with a new format.
    634     */
    635    public long getRemoteDevice() {
    636        checkOldFormat();
    637        return this.rmin;
    638    }
    639
    640    /**
    641     * Gets the remote major device id.
    642     *
    643     * @return the remote major device id.
    644     * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with an old format.
    645     */
    646    public long getRemoteDeviceMaj() {
    647        checkNewFormat();
    648        return this.rmaj;
    649    }
    650
    651    /**
    652     * Gets the remote minor device id.
    653     *
    654     * @return the remote minor device id.
    655     * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with an old format.
    656     */
    657    public long getRemoteDeviceMin() {
    658        checkNewFormat();
    659        return this.rmin;
    660    }
    661
    662    /**
    663     * Gets the filesize.
    664     *
    665     * @return the filesize.
    666     * @see org.apache.commons.compress.archivers.ArchiveEntry#getSize()
    667     */
    668    @Override
    669    public long getSize() {
    670        return this.filesize;
    671    }
    672
    673    /**
    674     * Gets the time in seconds.
    675     *
    676     * @return the time.
    677     */
    678    public long getTime() {
    679        return this.mtime;
    680    }
    681
    682    /**
    683     * Gets the user id.
    684     *
    685     * @return the user id.
    686     */
    687    public long getUID() {
    688        return this.uid;
    689    }
    690
    691    /*
    692     * (non-Javadoc)
    693     *
    694     * @see Object#hashCode()
    695     */
    696    @Override
    697    public int hashCode() {
    698        return Objects.hash(name);
    699    }
    700
    701    /**
    702     * Checks if this entry represents a block device.
    703     *
    704     * @return TRUE if this entry is a block device.
    705     */
    706    public boolean isBlockDevice() {
    707        return CpioUtil.fileType(mode) == C_ISBLK;
    708    }
    709
    710    /**
    711     * Checks if this entry represents a character device.
    712     *
    713     * @return TRUE if this entry is a character device.
    714     */
    715    public boolean isCharacterDevice() {
    716        return CpioUtil.fileType(mode) == C_ISCHR;
    717    }
    718
    719    /**
    720     * Checks if this entry represents a directory.
    721     *
    722     * @return TRUE if this entry is a directory.
    723     */
    724    @Override
    725    public boolean isDirectory() {
    726        return CpioUtil.fileType(mode) == C_ISDIR;
    727    }
    728
    729    /**
    730     * Checks if this entry represents a network device.
    731     *
    732     * @return TRUE if this entry is a network device.
    733     */
    734    public boolean isNetwork() {
    735        return CpioUtil.fileType(mode) == C_ISNWK;
    736    }
    737
    738    /**
    739     * Checks if this entry represents a pipe.
    740     *
    741     * @return TRUE if this entry is a pipe.
    742     */
    743    public boolean isPipe() {
    744        return CpioUtil.fileType(mode) == C_ISFIFO;
    745    }
    746
    747    /**
    748     * Checks if this entry represents a regular file.
    749     *
    750     * @return TRUE if this entry is a regular file.
    751     */
    752    public boolean isRegularFile() {
    753        return CpioUtil.fileType(mode) == C_ISREG;
    754    }
    755
    756    /**
    757     * Checks if this entry represents a socket.
    758     *
    759     * @return TRUE if this entry is a socket.
    760     */
    761    public boolean isSocket() {
    762        return CpioUtil.fileType(mode) == C_ISSOCK;
    763    }
    764
    765    /**
    766     * Checks if this entry represents a symbolic link.
    767     *
    768     * @return TRUE if this entry is a symbolic link.
    769     */
    770    public boolean isSymbolicLink() {
    771        return CpioUtil.fileType(mode) == C_ISLNK;
    772    }
    773
    774    /**
    775     * Sets the checksum. The checksum is calculated by adding all bytes of a file to transfer (crc += buf[pos] &amp; 0xFF).
    776     *
    777     * @param chksum The checksum to set.
    778     */
    779    public void setChksum(final long chksum) {
    780        checkNewFormat();
    781        this.chksum = chksum & 0xFFFFFFFFL;
    782    }
    783
    784    /**
    785     * Sets the device id.
    786     *
    787     * @param device The device id to set.
    788     * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with a new format.
    789     */
    790    public void setDevice(final long device) {
    791        checkOldFormat();
    792        this.min = device;
    793    }
    794
    795    /**
    796     * Sets major device id.
    797     *
    798     * @param maj The major device id to set.
    799     */
    800    public void setDeviceMaj(final long maj) {
    801        checkNewFormat();
    802        this.maj = maj;
    803    }
    804
    805    /**
    806     * Sets the minor device id
    807     *
    808     * @param min The minor device id to set.
    809     */
    810    public void setDeviceMin(final long min) {
    811        checkNewFormat();
    812        this.min = min;
    813    }
    814
    815    /**
    816     * Sets the group id.
    817     *
    818     * @param gid The group id to set.
    819     */
    820    public void setGID(final long gid) {
    821        this.gid = gid;
    822    }
    823
    824    /**
    825     * Sets the inode.
    826     *
    827     * @param inode The inode to set.
    828     */
    829    public void setInode(final long inode) {
    830        this.inode = inode;
    831    }
    832
    833    /**
    834     * Sets the mode of this entry (e.g. directory, regular file).
    835     *
    836     * @param mode The mode to set.
    837     */
    838    public void setMode(final long mode) {
    839        final long maskedMode = mode & S_IFMT;
    840        switch ((int) maskedMode) {
    841        case C_ISDIR:
    842        case C_ISLNK:
    843        case C_ISREG:
    844        case C_ISFIFO:
    845        case C_ISCHR:
    846        case C_ISBLK:
    847        case C_ISSOCK:
    848        case C_ISNWK:
    849            break;
    850        default:
    851            throw new IllegalArgumentException("Unknown mode. " + "Full: " + Long.toHexString(mode) + " Masked: " + Long.toHexString(maskedMode));
    852        }
    853
    854        this.mode = mode;
    855    }
    856
    857    /**
    858     * Sets the name.
    859     *
    860     * @param name The name to set.
    861     */
    862    public void setName(final String name) {
    863        this.name = name;
    864    }
    865
    866    /**
    867     * Sets the number of links.
    868     *
    869     * @param nlink The number of links to set.
    870     */
    871    public void setNumberOfLinks(final long nlink) {
    872        this.nlink = nlink;
    873    }
    874
    875    /**
    876     * Sets the remote device id.
    877     *
    878     * @param device The remote device id to set.
    879     * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with a new format.
    880     */
    881    public void setRemoteDevice(final long device) {
    882        checkOldFormat();
    883        this.rmin = device;
    884    }
    885
    886    /**
    887     * Sets the remote major device id.
    888     *
    889     * @param rmaj The remote major device id to set.
    890     * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with an old format.
    891     */
    892    public void setRemoteDeviceMaj(final long rmaj) {
    893        checkNewFormat();
    894        this.rmaj = rmaj;
    895    }
    896
    897    /**
    898     * Sets the remote minor device id.
    899     *
    900     * @param rmin The remote minor device id to set.
    901     * @throws UnsupportedOperationException if this method is called for a CpioArchiveEntry with an old format.
    902     */
    903    public void setRemoteDeviceMin(final long rmin) {
    904        checkNewFormat();
    905        this.rmin = rmin;
    906    }
    907
    908    /**
    909     * Sets the filesize.
    910     *
    911     * @param size The filesize to set.
    912     */
    913    public void setSize(final long size) {
    914        if (size < 0 || size > 0xFFFFFFFFL) {
    915            throw new IllegalArgumentException("Invalid entry size <" + size + ">");
    916        }
    917        this.filesize = size;
    918    }
    919
    920    /**
    921     * Sets the time.
    922     *
    923     * @param time The time to set.
    924     */
    925    public void setTime(final FileTime time) {
    926        this.mtime = TimeUtils.toUnixTime(time);
    927    }
    928
    929    /**
    930     * Sets the time in seconds.
    931     *
    932     * @param time The time to set.
    933     */
    934    public void setTime(final long time) {
    935        this.mtime = time;
    936    }
    937
    938    /**
    939     * Sets the user id.
    940     *
    941     * @param uid The user id to set.
    942     */
    943    public void setUID(final long uid) {
    944        this.uid = uid;
    945    }
    946}