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