1
2
3
4
5 package com.jguild.jrpm.io.cpio;
6
7 /***
8 * A cpio archive consists of a sequence of files.
9 * There are several types of headers defided in two
10 * categories of new and old format.
11 * The headers are recognized by magic numbers:
12 * "070701" ascii for "new" portable format
13 * "070702" ascii for "new" portable format with CRC format
14 * "070707" ascii for old ascii
15 * "070707" short for old binary
16 * CPIO 2.5 knows also about tar, but it is not recognized here.
17 *
18 * OLD FORMAT:
19 * Each file has a 76(ascii)/26(binary) byte header,
20 * a variable length, NUL terminated filename,
21 * and variable length file data.
22 * A header for a filename "TRAILER!!!" indicates the end of the archive.
23 *
24 * All the fields in the header are ISO 646 (approximately ASCII) strings
25 * of octal numbers, left padded, not NUL terminated.
26 *
27 * Field Name Length in Bytes Notes
28 * ASCII / BINARY
29 * c_magic 6 / 2
30 * c_dev 6 / 2 Device that contains a directory entry for this file
31 * c_ino 6 / 2 I-node number that identifies the input file to the file system
32 * c_mode 6 / 2 Mode of the input file
33 * c_uid 6 / 2 User ID of the owner of the input file
34 * c_gid 6 / 2 Group ID of the owner of the input file
35 * c_nlink 6 / 2 Number of links that are connected to the input file
36 * c_rdev 6 / 2 ID of the remote device from which the input file is taken
37 * only valid for chr and blk special files
38 * c_mtime 11 / 4 Time when data was last modified. For remote files,
39 * this field contains the time at the server
40 * c_namesize 6 / 2 Length of the path name, including the terminating null byte
41 * c_filesize 11 / 4 Length of the file in bytes. This is the length of the data
42 * section that follows the header structure. Must be 0 for
43 * FIFOs and directories
44 *
45 * Special files, directories, and the trailer are recorded with the h_filesize field equal to 0.
46 *
47 * NEW FORMAT:
48 * Each file has a 110 byte header,
49 * a variable length, NUL terminated filename,
50 * and variable length file data.
51 * A header for a filename "TRAILER!!!" indicates the end of the archive.
52 * All the fields in the header are ISO 646 (approximately ASCII) strings
53 * of hexadecimal numbers, left padded, not NUL terminated.
54 *
55 * Field Name Length in Bytes Notes
56 * c_magic 6
57 * c_ino 8
58 * c_mode 8
59 * c_uid 8
60 * c_gid 8
61 * c_nlink 8
62 * c_mtime 8
63 * c_filesize 8 must be 0 for FIFOs and directories
64 * c_maj 8
65 * c_min 8
66 * c_rmaj 8 only valid for chr and blk special files
67 * c_rmin 8 only valid for chr and blk special files
68 * c_namesize 8 count includes terminating NUL in pathname
69 * c_chksum 8 0 for "new" portable format; for CRC format
70 * the sum of all the bytes in the file
71 *
72 * @author Michael Kuss
73 */
74 public class CPIOEntry implements CPIOConstants {
75 private long chksum = 0;
76 private short fileFormat = -1;
77 private long filesize = 0;
78 private long gid = 0;
79 private long headerSize = -1;
80 private long inode = 0;
81 private long maj = 0;
82 private long min = 0;
83 private long mode = -1;
84 private long mtime = -1;
85 private String name;
86 private long nlink = 0;
87 private long rmaj = 0;
88 private long rmin = 0;
89 private long uid = 0;
90
91 /***
92 * Ceates a CPIOEntry without a cpio format.
93 */
94 public CPIOEntry() {
95 }
96
97 /***
98 * Ceates a CPIOEntry with a specified format.
99 *
100 * @param format The cpio format for this entry.
101 */
102 public CPIOEntry(short format) {
103 setFormat(format);
104 }
105
106 /***
107 * Ceates a CPIOEntry with a specified name.
108 * The format of this entry will be the new format.
109 *
110 * @param name The name of this entry.
111 */
112 public CPIOEntry(String name) {
113 this(FORMAT_NEW);
114 this.name = name;
115 }
116
117 /***
118 * Check if the method is allowed for the defined format.
119 */
120 private void checkNewFormat() {
121 if ((fileFormat & FORMAT_NEW_MASK) == 0)
122 throw new UnsupportedOperationException();
123 }
124
125 /***
126 * Check if the method is allowed for the defined format.
127 */
128 private void checkOldFormat() {
129 if ((fileFormat & FORMAT_OLD_MASK) == 0)
130 throw new UnsupportedOperationException();
131 }
132
133 /***
134 * Get the checksum.
135 *
136 * @return Returns the checksum.
137 */
138 public long getChksum() {
139 checkNewFormat();
140 return chksum;
141 }
142
143 /***
144 * Get the device id.
145 *
146 * @return Returns the device id.
147 * @throws UnsupportedOperationException if this method is called
148 * for a CPIOEntry with a new format.
149 */
150 public long getDevice() {
151 checkOldFormat();
152 return min;
153 }
154
155 /***
156 * Get the major device id.
157 *
158 * @return Returns the major device id.
159 * @throws UnsupportedOperationException if this method is called
160 * for a CPIOEntry with an old format.
161 */
162 public long getDeviceMaj() {
163 checkNewFormat();
164 return maj;
165 }
166
167 /***
168 * Get the minor device id
169 *
170 * @return Returns the minor device id.
171 */
172 public long getDeviceMin() {
173 checkNewFormat();
174 return min;
175 }
176
177 /***
178 * Get the filesize.
179 *
180 * @return Returns the filesize.
181 */
182 public long getFileSize() {
183 return filesize;
184 }
185
186 /***
187 * Get the format for this entry.
188 *
189 * @return Returns the format.
190 */
191 public short getFormat() {
192 return fileFormat;
193 }
194
195 /***
196 * Get the group id.
197 *
198 * @return Returns the group id.
199 */
200 public long getGID() {
201 return gid;
202 }
203
204 /***
205 * Get the size of this entry on the stream
206 *
207 * @return Returns the size.
208 */
209 public long getHeaderSize() {
210 return headerSize;
211 }
212
213 /***
214 * Set the inode.
215 *
216 * @return Returns the inode.
217 */
218 public long getInode() {
219 return inode;
220 }
221
222 /***
223 * Get the mode of this entry (e.g. directory, regular file).
224 *
225 * @return Returns the mode.
226 */
227 public long getMode() {
228 return mode;
229 }
230
231 /***
232 * Get the name.
233 *
234 * @return Returns the name.
235 */
236 public String getName() {
237 return name;
238 }
239
240 /***
241 * Get the number of links.
242 *
243 * @return Returns the number of links.
244 */
245 public long getNumberOfLinks() {
246 return nlink;
247 }
248
249 /***
250 * Get the remote device id.
251 *
252 * @return Returns the remote device id.
253 * @throws UnsupportedOperationException if this method is called
254 * for a CPIOEntry with a new format.
255 */
256 public long getRemoteDevice() {
257 checkOldFormat();
258 return rmin;
259 }
260
261 /***
262 * Get the remote major device id.
263 *
264 * @return Returns the remote major device id.
265 * @throws UnsupportedOperationException if this method is called
266 * for a CPIOEntry with an old format.
267 */
268 public long getRemoteDeviceMaj() {
269 checkNewFormat();
270 return rmaj;
271 }
272
273 /***
274 * Get the remote minor device id.
275 *
276 * @return Returns the remote minor device id.
277 * @throws UnsupportedOperationException if this method is called
278 * for a CPIOEntry with an old format.
279 */
280 public long getRemoteDeviceMin() {
281 checkNewFormat();
282 return rmin;
283 }
284
285 /***
286 * Get the time in seconds.
287 *
288 * @return Returns the time.
289 */
290 public long getTime() {
291 return mtime;
292 }
293
294 /***
295 * Get the user id.
296 *
297 * @return Returns the user id.
298 */
299 public long getUID() {
300 return uid;
301 }
302
303 /***
304 * Check if this entry represents a block device.
305 *
306 * @return TRUE if this entry is a block device.
307 */
308 public boolean isBlockDevice() {
309 return (mode & S_IFMT) == C_ISBLK;
310 }
311
312 /***
313 * Check if this entry represents a character device.
314 *
315 * @return TRUE if this entry is a character device.
316 */
317 public boolean isCharacterDevice() {
318 return (mode & S_IFMT) == C_ISCHR;
319 }
320
321 /***
322 * Check if this entry represents a directory.
323 *
324 * @return TRUE if this entry is a directory.
325 */
326 public boolean isDirectory() {
327 return (mode & S_IFMT) == C_ISDIR;
328 }
329
330 /***
331 * Check if this entry represents a network device.
332 *
333 * @return TRUE if this entry is a network device.
334 */
335 public boolean isNetwork() {
336 return (mode & S_IFMT) == C_ISNWK;
337 }
338
339 /***
340 * Check if this entry represents a pipe.
341 *
342 * @return TRUE if this entry is a pipe.
343 */
344 public boolean isPipe() {
345 return (mode & S_IFMT) == C_ISFIFO;
346 }
347
348 /***
349 * Check if this entry represents a regular file.
350 *
351 * @return TRUE if this entry is a regular file.
352 */
353 public boolean isRegularFile() {
354 return (mode & S_IFMT) == C_ISREG;
355 }
356
357 /***
358 * Check if this entry represents a socket.
359 *
360 * @return TRUE if this entry is a socket.
361 */
362 public boolean isSocket() {
363 return (mode & S_IFMT) == C_ISSOCK;
364 }
365
366 /***
367 * Check if this entry represents a symbolic link.
368 *
369 * @return TRUE if this entry is a symbolic link.
370 */
371 public boolean isSymbolicLink() {
372 return (mode & S_IFMT) == C_ISLNK;
373 }
374
375 /***
376 * Set the checksum.
377 * The checksum is calculated by adding all bytes of a
378 * file to transfer (crc += buf[pos] & 0xFF).
379 *
380 * @param chksum The checksum to set.
381 */
382 public void setChksum(long chksum) {
383 checkNewFormat();
384 this.chksum = chksum;
385 }
386
387 /***
388 * Set the device id.
389 *
390 * @param device The device id to set.
391 * @throws UnsupportedOperationException if this method is called
392 * for a CPIOEntry with a new format.
393 */
394 public void setDevice(long device) {
395 checkOldFormat();
396 this.min = device;
397 }
398
399 /***
400 * Set major device id.
401 *
402 * @param maj The major device id to set.
403 */
404 public void setDeviceMaj(long maj) {
405 checkNewFormat();
406 this.maj = maj;
407 }
408
409 /***
410 * Set the minor device id
411 *
412 * @param min The minor device id to set.
413 */
414 public void setDeviceMin(long min) {
415 checkNewFormat();
416 this.min = min;
417 }
418
419 /***
420 * Set the filesize.
421 *
422 * @param size The filesize to set.
423 */
424 public void setFileSize(long size) {
425 if (size < 0 || size > 0xFFFFFFFFL) { throw new IllegalArgumentException(
426 "invalid entry size <" + size + ">"); }
427 filesize = size;
428 }
429
430 /***
431 * Set the format for this entry.
432 * Possible values are:
433 * CPIOConstants.FORMAT_NEW, CPIOConstants.FORMAT_NEW_CRC,
434 * CPIOConstants.FORMAT_OLD_BINARY, CPIOConstants.FORMAT_OLD_ASCII
435 *
436 * @param format The format to set.
437 */
438 void setFormat(short format) {
439 switch (format) {
440 case FORMAT_NEW:
441 fileFormat = FORMAT_NEW;
442 headerSize = 110;
443 break;
444 case FORMAT_NEW_CRC:
445 fileFormat = FORMAT_NEW_CRC;
446 headerSize = 110;
447 break;
448 case FORMAT_OLD_ASCII:
449 fileFormat = FORMAT_OLD_ASCII;
450 headerSize = 76;
451 break;
452 case FORMAT_OLD_BINARY:
453 fileFormat = FORMAT_OLD_BINARY;
454 headerSize = 26;
455 break;
456 default:
457 throw new IllegalArgumentException("Unknown header type");
458 }
459 }
460
461 /***
462 * Set the group id.
463 *
464 * @param gid The group id to set.
465 */
466 public void setGID(long gid) {
467 this.gid = gid;
468 }
469
470 /***
471 * Set the inode.
472 *
473 * @param inode The inode to set.
474 */
475 public void setInode(long inode) {
476 this.inode = inode;
477 }
478
479 /***
480 * Set the mode of this entry (e.g. directory, regular file).
481 *
482 * @param mode The mode to set.
483 */
484 public void setMode(long mode) {
485 switch ((int) (mode & S_IFMT)) {
486 case C_ISDIR:
487 case C_ISLNK:
488 case C_ISREG:
489 case C_ISFIFO:
490 case C_ISCHR:
491 case C_ISBLK:
492 case C_ISSOCK:
493 case C_ISNWK:
494 break;
495 default:
496 new IllegalArgumentException("Unknown mode");
497 }
498
499 this.mode = mode;
500 }
501
502 /***
503 * Set the name.
504 *
505 * @param name The name to set.
506 */
507 public void setName(String name) {
508 this.name = name;
509 }
510
511 /***
512 * Set the number of links.
513 *
514 * @param nlink The number of links to set.
515 */
516 public void setNumberOfLinks(long nlink) {
517 this.nlink = nlink;
518 }
519
520 /***
521 * Set the remote device id.
522 *
523 * @param device The remote device id to set.
524 * @throws UnsupportedOperationException if this method is called
525 * for a CPIOEntry with a new format.
526 */
527 public void setRemoteDevice(long device) {
528 checkOldFormat();
529 this.rmin = device;
530 }
531
532 /***
533 * Set the remote major device id.
534 *
535 * @param rmaj The remote major device id to set.
536 * @throws UnsupportedOperationException if this method is called
537 * for a CPIOEntry with an old format.
538 */
539 public void setRemoteDeviceMaj(long rmaj) {
540 checkNewFormat();
541 this.rmaj = rmaj;
542 }
543
544 /***
545 * Set the remote minor device id.
546 *
547 * @param rmin The remote minor device id to set.
548 * @throws UnsupportedOperationException if this method is called
549 * for a CPIOEntry with an old format.
550 */
551 public void setRemoteDeviceMin(long rmin) {
552 checkNewFormat();
553 this.rmin = rmin;
554 }
555
556 /***
557 * Set the time in seconds.
558 *
559 * @param time The time to set.
560 */
561 public void setTime(long time) {
562 this.mtime = time;
563 }
564
565 /***
566 * Set the user id.
567 *
568 * @param uid The user id to set.
569 */
570 public void setUID(long uid) {
571 this.uid = uid;
572 }
573 }