Mercurial > cgi-bin > hgweb.cgi > JpegWasher
comparison lib/mod/src/de/masters_of_disaster/ant/tasks/ar/ArEntry.java @ 33:3d86f0391168
Work on improving the build system.
author | David Barts <davidb@stashtea.com> |
---|---|
date | Fri, 24 Apr 2020 19:45:57 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
32:c06edc56669b | 33:3d86f0391168 |
---|---|
1 package de.masters_of_disaster.ant.tasks.ar; | |
2 | |
3 import java.io.File; | |
4 import java.util.Date; | |
5 | |
6 /** | |
7 * This class represents an entry in an Ar archive. It consists | |
8 * of the entry's header, as well as the entry's File. Entries | |
9 * can be instantiated in one of three ways, depending on how | |
10 * they are to be used. | |
11 * <p> | |
12 * ArEntries that are created from the header bytes read from | |
13 * an archive are instantiated with the ArEntry( byte[] ) | |
14 * constructor. These entries will be used when extracting from | |
15 * or listing the contents of an archive. These entries have their | |
16 * header filled in using the header bytes. They also set the File | |
17 * to null, since they reference an archive entry not a file. | |
18 * <p> | |
19 * ArEntries that are created from Files that are to be written | |
20 * into an archive are instantiated with the ArEntry( File ) | |
21 * constructor. These entries have their header filled in using | |
22 * the File's information. They also keep a reference to the File | |
23 * for convenience when writing entries. | |
24 * <p> | |
25 * Finally, ArEntries can be constructed from nothing but a name. | |
26 * This allows the programmer to construct the entry by hand, for | |
27 * instance when only an InputStream is available for writing to | |
28 * the archive, and the header information is constructed from | |
29 * other information. In this case the header fields are set to | |
30 * defaults and the File is set to null. | |
31 * | |
32 * <p> | |
33 * The C structure for an Ar Entry's header is: | |
34 * <pre> | |
35 * struct header { | |
36 * char filename[16]; | |
37 * char filedate[12]; | |
38 * char uid[6]; | |
39 * char gid[6]; | |
40 * char mode[8]; | |
41 * char size[10]; | |
42 * char magic[2]; | |
43 * } header; | |
44 * </pre> | |
45 * | |
46 */ | |
47 | |
48 public class ArEntry implements ArConstants { | |
49 /** The entry's filename. */ | |
50 private StringBuffer filename; | |
51 | |
52 /** The entry's file date. */ | |
53 private long fileDate; | |
54 | |
55 /** The entry's user id. */ | |
56 private int userId; | |
57 | |
58 /** The entry's group id. */ | |
59 private int groupId; | |
60 | |
61 /** The entry's permission mode. */ | |
62 private int mode; | |
63 | |
64 /** The entry's size. */ | |
65 private long size; | |
66 | |
67 /** The entry's magic tag. */ | |
68 private StringBuffer magic; | |
69 | |
70 /** The entry's file reference */ | |
71 private File file; | |
72 | |
73 /** Default permissions bits for files */ | |
74 public static final int DEFAULT_FILE_MODE = 0100644; | |
75 | |
76 /** Convert millis to seconds */ | |
77 public static final int MILLIS_PER_SECOND = 1000; | |
78 | |
79 /** | |
80 * Construct an empty entry and prepares the header values. | |
81 */ | |
82 private ArEntry () { | |
83 this.magic = new StringBuffer(HEADERMAGIC); | |
84 this.filename = new StringBuffer(); | |
85 this.userId = 0; | |
86 this.groupId = 0; | |
87 this.file = null; | |
88 } | |
89 | |
90 /** | |
91 * Construct an entry with only a name. This allows the programmer | |
92 * to construct the entry's header "by hand". File is set to null. | |
93 * | |
94 * @param name the entry name | |
95 */ | |
96 public ArEntry(String name) { | |
97 this(); | |
98 if (name.endsWith("/")) { | |
99 throw new IllegalArgumentException("ar archives can only contain files"); | |
100 } | |
101 this.filename = new StringBuffer(name); | |
102 this.mode = DEFAULT_FILE_MODE; | |
103 this.userId = 0; | |
104 this.groupId = 0; | |
105 this.size = 0; | |
106 this.fileDate = (new Date()).getTime() / MILLIS_PER_SECOND; | |
107 } | |
108 | |
109 /** | |
110 * Construct an entry for a file. File is set to file, and the | |
111 * header is constructed from information from the file. | |
112 * | |
113 * @param file The file that the entry represents. | |
114 */ | |
115 public ArEntry(File file) { | |
116 this(); | |
117 if (file.isDirectory()) { | |
118 throw new IllegalArgumentException("ar archives can only contain files"); | |
119 } | |
120 this.file = file; | |
121 this.filename = new StringBuffer(file.getName()); | |
122 this.fileDate = file.lastModified() / MILLIS_PER_SECOND; | |
123 this.mode = DEFAULT_FILE_MODE; | |
124 this.size = file.length(); | |
125 } | |
126 | |
127 /** | |
128 * Construct an entry from an archive's header bytes. File is set | |
129 * to null. | |
130 * | |
131 * @param headerBuf The header bytes from an ar archive entry. | |
132 */ | |
133 public ArEntry(byte[] headerBuf) { | |
134 this(); | |
135 this.parseArHeader(headerBuf); | |
136 } | |
137 | |
138 /** | |
139 * Determine if the two entries are equal. Equality is determined | |
140 * by the header names being equal. | |
141 * | |
142 * @param it Entry to be checked for equality. | |
143 * @return True if the entries are equal. | |
144 */ | |
145 public boolean equals(ArEntry it) { | |
146 return this.getFilename().equals(it.getFilename()); | |
147 } | |
148 | |
149 /** | |
150 * Determine if the two entries are equal. Equality is determined | |
151 * by the header names being equal. | |
152 * | |
153 * @param it Entry to be checked for equality. | |
154 * @return True if the entries are equal. | |
155 */ | |
156 public boolean equals(Object it) { | |
157 if (it == null || getClass() != it.getClass()) { | |
158 return false; | |
159 } | |
160 return equals((ArEntry) it); | |
161 } | |
162 | |
163 /** | |
164 * Hashcodes are based on entry names. | |
165 * | |
166 * @return the entry hashcode | |
167 */ | |
168 public int hashCode() { | |
169 return getFilename().hashCode(); | |
170 } | |
171 | |
172 /** | |
173 * Get this entry's name. | |
174 * | |
175 * @return This entry's name. | |
176 */ | |
177 public String getFilename() { | |
178 return this.filename.toString(); | |
179 } | |
180 | |
181 /** | |
182 * Set this entry's name. | |
183 * | |
184 * @param name This entry's new name. | |
185 */ | |
186 public void setFilename(String filename) { | |
187 this.filename = new StringBuffer(filename); | |
188 } | |
189 | |
190 /** | |
191 * Set the mode for this entry | |
192 * | |
193 * @param mode the mode for this entry | |
194 */ | |
195 public void setMode(int mode) { | |
196 this.mode = mode; | |
197 } | |
198 | |
199 /** | |
200 * Get this entry's user id. | |
201 * | |
202 * @return This entry's user id. | |
203 */ | |
204 public int getUserId() { | |
205 return this.userId; | |
206 } | |
207 | |
208 /** | |
209 * Set this entry's user id. | |
210 * | |
211 * @param userId This entry's new user id. | |
212 */ | |
213 public void setUserId(int userId) { | |
214 this.userId = userId; | |
215 } | |
216 | |
217 /** | |
218 * Get this entry's group id. | |
219 * | |
220 * @return This entry's group id. | |
221 */ | |
222 public int getGroupId() { | |
223 return this.groupId; | |
224 } | |
225 | |
226 /** | |
227 * Set this entry's group id. | |
228 * | |
229 * @param groupId This entry's new group id. | |
230 */ | |
231 public void setGroupId(int groupId) { | |
232 this.groupId = groupId; | |
233 } | |
234 | |
235 /** | |
236 * Convenience method to set this entry's group and user ids. | |
237 * | |
238 * @param userId This entry's new user id. | |
239 * @param groupId This entry's new group id. | |
240 */ | |
241 public void setIds(int userId, int groupId) { | |
242 this.setUserId(userId); | |
243 this.setGroupId(groupId); | |
244 } | |
245 | |
246 /** | |
247 * Set this entry's modification time. The parameter passed | |
248 * to this method is in "Java time". | |
249 * | |
250 * @param time This entry's new modification time. | |
251 */ | |
252 public void setFileDate(long time) { | |
253 this.fileDate = time / MILLIS_PER_SECOND; | |
254 } | |
255 | |
256 /** | |
257 * Set this entry's modification time. | |
258 * | |
259 * @param time This entry's new modification time. | |
260 */ | |
261 public void setFileDate(Date time) { | |
262 this.fileDate = time.getTime() / MILLIS_PER_SECOND; | |
263 } | |
264 | |
265 /** | |
266 * Get this entry's modification time. | |
267 * | |
268 * @return time This entry's new modification time. | |
269 */ | |
270 public Date getFileDate() { | |
271 return new Date(this.fileDate * MILLIS_PER_SECOND); | |
272 } | |
273 | |
274 /** | |
275 * Get this entry's file. | |
276 * | |
277 * @return This entry's file. | |
278 */ | |
279 public File getFile() { | |
280 return this.file; | |
281 } | |
282 | |
283 /** | |
284 * Get this entry's mode. | |
285 * | |
286 * @return This entry's mode. | |
287 */ | |
288 public int getMode() { | |
289 return this.mode; | |
290 } | |
291 | |
292 /** | |
293 * Get this entry's file size. | |
294 * | |
295 * @return This entry's file size. | |
296 */ | |
297 public long getSize() { | |
298 return this.size; | |
299 } | |
300 | |
301 /** | |
302 * Set this entry's file size. | |
303 * | |
304 * @param size This entry's new file size. | |
305 */ | |
306 public void setSize(long size) { | |
307 this.size = size; | |
308 } | |
309 | |
310 /** | |
311 * Write an entry's header information to a header buffer. | |
312 * | |
313 * @param outbuf The tar entry header buffer to fill in. | |
314 */ | |
315 public void writeEntryHeader(byte[] outbuf) { | |
316 int offset = 0; | |
317 | |
318 offset = ArUtils.getNameBytes(this.filename, outbuf, offset, NAMELEN); | |
319 offset = ArUtils.getLongBytes(this.fileDate, outbuf, offset, FILEDATELEN); | |
320 offset = ArUtils.getIntegerBytes(this.userId, outbuf, offset, UIDLEN); | |
321 offset = ArUtils.getIntegerBytes(this.groupId, outbuf, offset, GIDLEN); | |
322 offset = ArUtils.getOctalBytes(this.mode, outbuf, offset, MODELEN); | |
323 offset = ArUtils.getLongBytes(this.size, outbuf, offset, SIZELEN); | |
324 offset = ArUtils.getNameBytes(this.magic, outbuf, offset, MAGICLEN); | |
325 | |
326 while (offset < outbuf.length) { | |
327 outbuf[offset++] = 0; | |
328 } | |
329 } | |
330 | |
331 /** | |
332 * Parse an entry's header information from a header buffer. | |
333 * | |
334 * @param header The ar entry header buffer to get information from. | |
335 */ | |
336 public void parseArHeader(byte[] header) { | |
337 throw new UnsupportedOperationException("parseArHeader(byte[]) not yet implmented"); | |
338 // int offset = 0; | |
339 // | |
340 // this.filename = TarUtils.parseName(header, offset, NAMELEN); | |
341 // offset += NAMELEN; | |
342 // this.fileDate = TarUtils.parseOctal(header, offset, FILEDATELEN); | |
343 // offset += FILEDATELEN; | |
344 // this.userId = (int) TarUtils.parseOctal(header, offset, UIDLEN); | |
345 // offset += UIDLEN; | |
346 // this.groupId = (int) TarUtils.parseOctal(header, offset, GIDLEN); | |
347 // offset += GIDLEN; | |
348 // this.mode = (int) TarUtils.parseOctal(header, offset, MODELEN); | |
349 // offset += MODELEN; | |
350 // this.size = TarUtils.parseOctal(header, offset, SIZELEN); | |
351 // offset += SIZELEN; | |
352 // this.magic = TarUtils.parseName(header, offset, MAGICLEN); | |
353 // offset += MAGICLEN; | |
354 } | |
355 } |