KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > zip > AsiExtraField


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18
19 package org.apache.tools.zip;
20
21 import java.util.zip.CRC32 JavaDoc;
22 import java.util.zip.ZipException JavaDoc;
23
24 /**
25  * Adds Unix file permission and UID/GID fields as well as symbolic
26  * link handling.
27  *
28  * <p>This class uses the ASi extra field in the format:
29  * <pre>
30  * Value Size Description
31  * ----- ---- -----------
32  * (Unix3) 0x756e Short tag for this extra block type
33  * TSize Short total data size for this block
34  * CRC Long CRC-32 of the remaining data
35  * Mode Short file permissions
36  * SizDev Long symlink'd size OR major/minor dev num
37  * UID Short user ID
38  * GID Short group ID
39  * (var.) variable symbolic link filename
40  * </pre>
41  * taken from appnote.iz (Info-ZIP note, 981119) found at <a
42  * HREF="ftp://ftp.uu.net/pub/archiving/zip/doc/">ftp://ftp.uu.net/pub/archiving/zip/doc/</a></p>
43
44  *
45  * <p>Short is two bytes and Long is four bytes in big endian byte and
46  * word order, device numbers are currently not supported.</p>
47  *
48  */

49 public class AsiExtraField implements ZipExtraField, UnixStat, Cloneable JavaDoc {
50
51     private static final ZipShort HEADER_ID = new ZipShort(0x756E);
52
53     /**
54      * Standard Unix stat(2) file mode.
55      *
56      * @since 1.1
57      */

58     private int mode = 0;
59     /**
60      * User ID.
61      *
62      * @since 1.1
63      */

64     private int uid = 0;
65     /**
66      * Group ID.
67      *
68      * @since 1.1
69      */

70     private int gid = 0;
71     /**
72      * File this entry points to, if it is a symbolic link.
73      *
74      * <p>empty string - if entry is not a symbolic link.</p>
75      *
76      * @since 1.1
77      */

78     private String JavaDoc link = "";
79     /**
80      * Is this an entry for a directory?
81      *
82      * @since 1.1
83      */

84     private boolean dirFlag = false;
85
86     /**
87      * Instance used to calculate checksums.
88      *
89      * @since 1.1
90      */

91     private CRC32 JavaDoc crc = new CRC32 JavaDoc();
92
93     /** Constructor for AsiExtraField. */
94     public AsiExtraField() {
95     }
96
97     /**
98      * The Header-ID.
99      * @return the value for the header id for this extrafield
100      * @since 1.1
101      */

102     public ZipShort getHeaderId() {
103         return HEADER_ID;
104     }
105
106     /**
107      * Length of the extra field in the local file data - without
108      * Header-ID or length specifier.
109      * @return a <code>ZipShort</code> for the length of the data of this extra field
110      * @since 1.1
111      */

112     public ZipShort getLocalFileDataLength() {
113         return new ZipShort(4 // CRC
114
+ 2 // Mode
115
+ 4 // SizDev
116
+ 2 // UID
117
+ 2 // GID
118
+ getLinkedFile().getBytes().length);
119     }
120
121     /**
122      * Delegate to local file data.
123      * @return the centralDirectory length
124      * @since 1.1
125      */

126     public ZipShort getCentralDirectoryLength() {
127         return getLocalFileDataLength();
128     }
129
130     /**
131      * The actual data to put into local file data - without Header-ID
132      * or length specifier.
133      * @return get the data
134      * @since 1.1
135      */

136     public byte[] getLocalFileDataData() {
137         // CRC will be added later
138
byte[] data = new byte[getLocalFileDataLength().getValue() - 4];
139         System.arraycopy(ZipShort.getBytes(getMode()), 0, data, 0, 2);
140
141         byte[] linkArray = getLinkedFile().getBytes();
142         System.arraycopy(ZipLong.getBytes(linkArray.length),
143                          0, data, 2, 4);
144
145         System.arraycopy(ZipShort.getBytes(getUserId()),
146                          0, data, 6, 2);
147         System.arraycopy(ZipShort.getBytes(getGroupId()),
148                          0, data, 8, 2);
149
150         System.arraycopy(linkArray, 0, data, 10, linkArray.length);
151
152         crc.reset();
153         crc.update(data);
154         long checksum = crc.getValue();
155
156         byte[] result = new byte[data.length + 4];
157         System.arraycopy(ZipLong.getBytes(checksum), 0, result, 0, 4);
158         System.arraycopy(data, 0, result, 4, data.length);
159         return result;
160     }
161
162     /**
163      * Delegate to local file data.
164      * @return the local file data
165      * @since 1.1
166      */

167     public byte[] getCentralDirectoryData() {
168         return getLocalFileDataData();
169     }
170
171     /**
172      * Set the user id.
173      * @param uid the user id
174      * @since 1.1
175      */

176     public void setUserId(int uid) {
177         this.uid = uid;
178     }
179
180     /**
181      * Get the user id.
182      * @return the user id
183      * @since 1.1
184      */

185     public int getUserId() {
186         return uid;
187     }
188
189     /**
190      * Set the group id.
191      * @param gid the group id
192      * @since 1.1
193      */

194     public void setGroupId(int gid) {
195         this.gid = gid;
196     }
197
198     /**
199      * Get the group id.
200      * @return the group id
201      * @since 1.1
202      */

203     public int getGroupId() {
204         return gid;
205     }
206
207     /**
208      * Indicate that this entry is a symbolic link to the given filename.
209      *
210      * @param name Name of the file this entry links to, empty String
211      * if it is not a symbolic link.
212      *
213      * @since 1.1
214      */

215     public void setLinkedFile(String JavaDoc name) {
216         link = name;
217         mode = getMode(mode);
218     }
219
220     /**
221      * Name of linked file
222      *
223      * @return name of the file this entry links to if it is a
224      * symbolic link, the empty string otherwise.
225      *
226      * @since 1.1
227      */

228     public String JavaDoc getLinkedFile() {
229         return link;
230     }
231
232     /**
233      * Is this entry a symbolic link?
234      * @return true if this is a symbolic link
235      * @since 1.1
236      */

237     public boolean isLink() {
238         return getLinkedFile().length() != 0;
239     }
240
241     /**
242      * File mode of this file.
243      * @param mode the file mode
244      * @since 1.1
245      */

246     public void setMode(int mode) {
247         this.mode = getMode(mode);
248     }
249
250     /**
251      * File mode of this file.
252      * @return the file mode
253      * @since 1.1
254      */

255     public int getMode() {
256         return mode;
257     }
258
259     /**
260      * Indicate whether this entry is a directory.
261      * @param dirFlag if true, this entry is a directory
262      * @since 1.1
263      */

264     public void setDirectory(boolean dirFlag) {
265         this.dirFlag = dirFlag;
266         mode = getMode(mode);
267     }
268
269     /**
270      * Is this entry a directory?
271      * @return true if this entry is a directory
272      * @since 1.1
273      */

274     public boolean isDirectory() {
275         return dirFlag && !isLink();
276     }
277
278     /**
279      * Populate data from this array as if it was in local file data.
280      * @param data an array of bytes
281      * @param offset the start offset
282      * @param length the number of bytes in the array from offset
283      * @since 1.1
284      * @throws ZipException on error
285      */

286     public void parseFromLocalFileData(byte[] data, int offset, int length)
287         throws ZipException JavaDoc {
288
289         long givenChecksum = ZipLong.getValue(data, offset);
290         byte[] tmp = new byte[length - 4];
291         System.arraycopy(data, offset + 4, tmp, 0, length - 4);
292         crc.reset();
293         crc.update(tmp);
294         long realChecksum = crc.getValue();
295         if (givenChecksum != realChecksum) {
296             throw new ZipException JavaDoc("bad CRC checksum "
297                                    + Long.toHexString(givenChecksum)
298                                    + " instead of "
299                                    + Long.toHexString(realChecksum));
300         }
301
302         int newMode = ZipShort.getValue(tmp, 0);
303         byte[] linkArray = new byte[(int) ZipLong.getValue(tmp, 2)];
304         uid = ZipShort.getValue(tmp, 6);
305         gid = ZipShort.getValue(tmp, 8);
306
307         if (linkArray.length == 0) {
308             link = "";
309         } else {
310             System.arraycopy(tmp, 10, linkArray, 0, linkArray.length);
311             link = new String JavaDoc(linkArray);
312         }
313         setDirectory((newMode & DIR_FLAG) != 0);
314         setMode(newMode);
315     }
316
317     /**
318      * Get the file mode for given permissions with the correct file type.
319      * @param mode the mode
320      * @return the type with the mode
321      * @since 1.1
322      */

323     protected int getMode(int mode) {
324         int type = FILE_FLAG;
325         if (isLink()) {
326             type = LINK_FLAG;
327         } else if (isDirectory()) {
328             type = DIR_FLAG;
329         }
330         return type | (mode & PERM_MASK);
331     }
332
333 }
334
Popular Tags