ArArchiveEntry.java
- /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- package org.apache.commons.compress.archivers.ar;
- import java.io.File;
- import java.io.IOException;
- import java.nio.file.Files;
- import java.nio.file.LinkOption;
- import java.nio.file.Path;
- import java.util.Date;
- import java.util.Objects;
- import org.apache.commons.compress.archivers.ArchiveEntry;
- /**
- * Represents an archive entry in the "ar" format.
- * <p>
- * Each AR archive starts with "!<arch>" followed by a LF. After these 8 bytes the archive entries are listed. The format of an entry header is as it
- * follows:
- * </p>
- *
- * <pre>
- * START BYTE END BYTE NAME FORMAT LENGTH
- * 0 15 File name ASCII 16
- * 16 27 Modification timestamp Decimal 12
- * 28 33 Owner ID Decimal 6
- * 34 39 Group ID Decimal 6
- * 40 47 File mode Octal 8
- * 48 57 File size (bytes) Decimal 10
- * 58 59 File magic \140\012 2
- * </pre>
- * <p>
- * This specifies that an ar archive entry header contains 60 bytes.
- * </p>
- * <p>
- * Due to the limitation of the file name length to 16 bytes GNU and BSD has their own variants of this format. Currently Commons Compress can read but not
- * write the GNU variant. It fully supports the BSD variant.
- * </p>
- *
- * @see <a href="https://www.freebsd.org/cgi/man.cgi?query=ar&sektion=5">ar man page</a>
- * @Immutable
- */
- public class ArArchiveEntry implements ArchiveEntry {
- /** The header for each entry */
- public static final String HEADER = "!<arch>\n";
- /** The trailer for each entry {@code 0x60 0x0A} */
- public static final String TRAILER = "`\012";
- private static final int DEFAULT_MODE = 33188; // = (octal) 0100644
- /**
- * SVR4/GNU adds a trailing / to names; BSD does not. They also vary in how names longer than 16 characters are represented. (Not yet fully supported by
- * this implementation)
- */
- private final String name;
- private final int userId;
- private final int groupId;
- private final int mode;
- private final long lastModified;
- private final long length;
- /**
- * Creates a new instance using the attributes of the given file
- *
- * @param inputFile the file to create an entry from
- * @param entryName the name of the entry
- */
- public ArArchiveEntry(final File inputFile, final String entryName) {
- // TODO sort out mode
- this(entryName, inputFile.isFile() ? inputFile.length() : 0, 0, 0, DEFAULT_MODE, inputFile.lastModified() / 1000);
- }
- /**
- * Creates a new instance using the attributes of the given file
- *
- * @param inputPath the file to create an entry from
- * @param entryName the name of the entry
- * @param options options indicating how symbolic links are handled.
- * @throws IOException if an I/O error occurs.
- * @since 1.21
- */
- public ArArchiveEntry(final Path inputPath, final String entryName, final LinkOption... options) throws IOException {
- this(entryName, Files.isRegularFile(inputPath, options) ? Files.size(inputPath) : 0, 0, 0, DEFAULT_MODE,
- Files.getLastModifiedTime(inputPath, options).toMillis() / 1000);
- }
- /**
- * Constructs a new instance using a couple of default values.
- *
- * <p>
- * Sets userId and groupId to 0, the octal file mode to 644 and the last modified time to the current time.
- * </p>
- *
- * @param name name of the entry
- * @param length length of the entry in bytes
- */
- public ArArchiveEntry(final String name, final long length) {
- this(name, length, 0, 0, DEFAULT_MODE, System.currentTimeMillis() / 1000);
- }
- /**
- * Constructs a new instance.
- *
- * @param name name of the entry
- * @param length length of the entry in bytes
- * @param userId numeric user id
- * @param groupId numeric group id
- * @param mode file mode
- * @param lastModified last modified time in seconds since the epoch
- */
- public ArArchiveEntry(final String name, final long length, final int userId, final int groupId, final int mode, final long lastModified) {
- this.name = name;
- if (length < 0) {
- throw new IllegalArgumentException("length must not be negative");
- }
- this.length = length;
- this.userId = userId;
- this.groupId = groupId;
- this.mode = mode;
- this.lastModified = lastModified;
- }
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
- final ArArchiveEntry other = (ArArchiveEntry) obj;
- return Objects.equals(name, other.name);
- }
- /**
- * Gets the group ID.
- *
- * @return the group ID.
- */
- public int getGroupId() {
- return groupId;
- }
- /**
- * Gets the last modified time in seconds since the epoch.
- *
- * @return the last modified date.
- */
- public long getLastModified() {
- return lastModified;
- }
- @Override
- public Date getLastModifiedDate() {
- return new Date(1000 * getLastModified());
- }
- /**
- * Gets the length.
- *
- * @return the length.
- */
- public long getLength() {
- return length;
- }
- /**
- * Gets the mode.
- *
- * @return the mode.
- */
- public int getMode() {
- return mode;
- }
- @Override
- public String getName() {
- return name;
- }
- @Override
- public long getSize() {
- return getLength();
- }
- /**
- * Gets the user ID.
- *
- * @return the user ID.
- */
- public int getUserId() {
- return userId;
- }
- @Override
- public int hashCode() {
- return Objects.hash(name);
- }
- @Override
- public boolean isDirectory() {
- return false;
- }
- }