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 */
019 package org.apache.commons.compress.archivers.ar;
020
021 import java.io.File;
022
023 import org.apache.commons.compress.archivers.ArchiveEntry;
024
025 /**
026 * Represents an archive entry in the "ar" format.
027 *
028 * Each AR archive starts with "!<arch>" followed by a LF. After these 8 bytes
029 * the archive entries are listed. The format of an entry header is as it follows:
030 *
031 * <pre>
032 * START BYTE END BYTE NAME FORMAT LENGTH
033 * 0 15 File name ASCII 16
034 * 16 27 Modification timestamp Decimal 12
035 * 28 33 Owner ID Decimal 6
036 * 34 39 Group ID Decimal 6
037 * 40 47 File mode Octal 8
038 * 48 57 File size (bytes) Decimal 10
039 * 58 59 File magic \140\012 2
040 * </pre>
041 *
042 * This specifies that an ar archive entry header contains 60 bytes.
043 *
044 * Due to the limitation of the file name length to 16 bytes GNU and BSD has
045 * their own variants of this format. This formats are currently not supported
046 * and file names with a bigger size than 16 bytes are not possible at the
047 * moment.
048 *
049 * @Immutable
050 */
051 public class ArArchiveEntry implements ArchiveEntry {
052
053 /** The header for each entry */
054 public static final String HEADER = "!<arch>\n";
055
056 /** The trailer for each entry */
057 public static final String TRAILER = "`\012";
058
059 /**
060 * SVR4/GNU adds a trailing / to names; BSD does not.
061 * They also vary in how names longer than 16 characters are represented.
062 * (Not yet supported by this implementation)
063 */
064 private final String name;
065 private final int userId;
066 private final int groupId;
067 private final int mode;
068 private static final int DEFAULT_MODE = 33188; // = (octal) 0100644
069 private final long lastModified;
070 private final long length;
071
072 public ArArchiveEntry(String name, long length) {
073 this(name, length, 0, 0, DEFAULT_MODE, System.currentTimeMillis());
074 }
075
076 public ArArchiveEntry(String name, long length, int userId, int groupId, int mode, long lastModified) {
077 this.name = name;
078 this.length = length;
079 this.userId = userId;
080 this.groupId = groupId;
081 this.mode = mode;
082 this.lastModified = lastModified;
083 }
084
085 public ArArchiveEntry(File inputFile, String entryName) {
086 // TODO sort out mode
087 this(entryName, inputFile.isFile() ? inputFile.length() : 0, 0, 0, 0, inputFile.lastModified());
088 }
089
090 public long getSize() {
091 return this.getLength();
092 }
093
094 public String getName() {
095 return name;
096 }
097
098 public int getUserId() {
099 return userId;
100 }
101
102 public int getGroupId() {
103 return groupId;
104 }
105
106 public int getMode() {
107 return mode;
108 }
109
110 public long getLastModified() {
111 return lastModified;
112 }
113
114 public long getLength() {
115 return length;
116 }
117
118 public boolean isDirectory() {
119 return false;
120 }
121
122 /* (non-Javadoc)
123 * @see java.lang.Object#hashCode()
124 */
125 public int hashCode() {
126 final int prime = 31;
127 int result = 1;
128 result = prime * result + ((name == null) ? 0 : name.hashCode());
129 return result;
130 }
131
132 /* (non-Javadoc)
133 * @see java.lang.Object#equals(java.lang.Object)
134 */
135 public boolean equals(Object obj) {
136 if (this == obj) {
137 return true;
138 }
139 if (obj == null || getClass() != obj.getClass()) {
140 return false;
141 }
142 ArArchiveEntry other = (ArArchiveEntry) obj;
143 if (name == null) {
144 if (other.name != null) {
145 return false;
146 }
147 } else if (!name.equals(other.name)) {
148 return false;
149 }
150 return true;
151 }
152 }