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 }