Source code: com/neuron/jaffer/AppleDouble.java
1 /*
2 * Copyright (c) 2003 Stewart Allen <stewart@neuron.com>. All rights reserved.
3 * This program is free software. See the 'License' file for details.
4 */
5
6 package com.neuron.jaffer;
7
8 import java.io.*;
9 import java.net.*;
10 import java.util.*;
11
12 class AppleDouble extends RandomAccessFile
13 {
14 public final static int MAGIC = 0x51607;
15 public final static int VERSION = 0x20000;
16 public final static int ENTRIES = 0x02;
17 public final static int OFF_MAGIC = 0x00;
18 public final static int OFF_VERSION = 0x04;
19 public final static int OFF_ENTRIES = 0x18;
20 public final static int OFF_FINDER = 0x32;
21 public final static int OFF_RESOURCE = 0x52;
22 public final static int OFF_RES_LEN = 0x2e;
23 public final static int LEN_FINDER = 0x20;
24 public final static int ID_FINDER = 0x09;
25 public final static int ID_RESOURCE = 0x02;
26
27 AppleDouble(File file, String mode)
28 throws IOException
29 {
30 super(file, mode);
31 if (realLength() > 0)
32 {
33 int val = -1;
34 realSeek(OFF_MAGIC);
35 if ((val=readInt()) != MAGIC)
36 {
37 throw new IOException("Not a valid AppleDouble file");
38 }
39 realSeek(OFF_VERSION);
40 if (readInt() != VERSION)
41 {
42 throw new IOException("AppleDouble version not supported");
43 }
44 realSeek(OFF_ENTRIES);
45 if (readUnsignedShort() != ENTRIES)
46 {
47 throw new IOException("Expected two AppleDouble entries");
48 }
49 }
50 if (mode.equalsIgnoreCase("r"))
51 {
52 return;
53 }
54 // magic + version
55 realSeek(OFF_MAGIC);
56 writeInt(MAGIC);
57 writeInt(VERSION);
58 realSeek(OFF_ENTRIES);
59 // number of entries
60 writeShort(ENTRIES);
61 // finder info entry
62 writeInt(ID_FINDER);
63 writeInt(OFF_FINDER);
64 writeInt(LEN_FINDER);
65 // resource fork entry
66 writeInt(ID_RESOURCE);
67 writeInt(OFF_RESOURCE);
68 // length must extend to at least resource fork offset
69 if (length() < 0)
70 {
71 writeInt(0);
72 setLength(0);
73 }
74 }
75
76 public void writeFinderInfo(byte b[])
77 throws IOException
78 {
79 super.seek(OFF_FINDER);
80 write(b);
81 }
82
83 public void readFinderInfo(byte b[])
84 throws IOException
85 {
86 super.seek(OFF_FINDER);
87 readFully(b);
88 }
89
90 public void realSeek(long off)
91 throws IOException
92 {
93 super.seek(off);
94 }
95
96 public long realLength()
97 throws IOException
98 {
99 return super.length();
100 }
101
102 public void seek(long off)
103 throws IOException
104 {
105 super.seek(OFF_RESOURCE + off);
106 }
107
108 public long length()
109 throws IOException
110 {
111 return super.length() - OFF_RESOURCE;
112 }
113
114 public void write(byte data[], int off, int len)
115 throws IOException
116 {
117 super.write(data, off, len);
118 }
119
120 public void setLength(long len)
121 throws IOException
122 {
123 long opos = getFilePointer();
124 super.seek(OFF_RES_LEN);
125 writeInt((int)len);
126 super.setLength(OFF_RESOURCE + len);
127 super.seek(opos);
128 }
129
130 public void close()
131 throws IOException
132 {
133 try
134 {
135 super.seek(OFF_RES_LEN);
136 writeInt((int)length());
137 }
138 catch (Exception ex) { }
139 super.close();
140 }
141 }
142