]>
Commit | Line | Data |
---|---|---|
ee9dd372 TT |
1 | // File.java - File name |
2 | ||
2ba5f774 | 3 | /* Copyright (C) 1998, 1999, 2000 Free Software Foundation |
ee9dd372 TT |
4 | |
5 | This file is part of libgcj. | |
6 | ||
7 | This software is copyrighted work licensed under the terms of the | |
8 | Libgcj License. Please consult the file "LIBGCJ_LICENSE" for | |
9 | details. */ | |
10 | ||
11 | package java.io; | |
12 | ||
13 | /** | |
14 | * @author Tom Tromey <tromey@cygnus.com> | |
15 | * @date September 24, 1998 | |
16 | */ | |
17 | ||
18 | /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 | |
19 | * "The Java Language Specification", ISBN 0-201-63451-1 | |
20 | * Status: Complete to version 1.1; 1.2 functionality missing. | |
21 | * A known bug: most calls to the security manager can generate | |
22 | * IOException since we use the canonical path. | |
23 | */ | |
24 | ||
25 | public class File implements Serializable | |
26 | { | |
27 | public boolean canRead () | |
28 | { | |
29 | return access (checkRead (), READ); | |
30 | } | |
31 | ||
32 | public boolean canWrite () | |
33 | { | |
34 | SecurityManager s = System.getSecurityManager(); | |
35 | String p = safeCanonicalPath (); | |
36 | // FIXME: it isn't entirely clear what to do if we can't find the | |
37 | // canonical path. | |
38 | if (p == null) | |
39 | return false; | |
40 | if (s != null) | |
41 | s.checkWrite(p); | |
42 | return access (p, WRITE); | |
43 | } | |
44 | ||
45 | private final native boolean performDelete (String canon); | |
46 | public boolean delete () | |
47 | { | |
48 | SecurityManager s = System.getSecurityManager(); | |
49 | String p = safeCanonicalPath (); | |
50 | // FIXME: what is right? | |
51 | if (p == null) | |
52 | return false; | |
53 | if (s != null) | |
54 | s.checkDelete(p); | |
55 | return performDelete (p); | |
56 | } | |
57 | ||
58 | public boolean equals (Object obj) | |
59 | { | |
60 | if (! (obj instanceof File)) | |
61 | return false; | |
62 | File other = (File) obj; | |
63 | return path.compareTo(other.path) == 0; | |
64 | } | |
65 | ||
66 | public boolean exists () | |
67 | { | |
68 | return access (checkRead (), EXISTS); | |
69 | } | |
70 | ||
71 | public File (String p) | |
72 | { | |
73 | if (p == null) | |
74 | throw new NullPointerException (); | |
75 | path = p; | |
76 | } | |
77 | ||
78 | public File (String dirPath, String name) | |
79 | { | |
80 | if (name == null) | |
81 | throw new NullPointerException (); | |
91da35db | 82 | if (dirPath != null && dirPath.length() > 0) |
ee9dd372 TT |
83 | { |
84 | // Try to be smart about the number of separator characters. | |
85 | if (dirPath.charAt(dirPath.length() - 1) == separatorChar) | |
86 | path = dirPath + name; | |
87 | else | |
88 | path = dirPath + separatorChar + name; | |
89 | } | |
90 | else | |
91 | path = name; | |
92 | } | |
93 | ||
94 | public File (File dir, String name) | |
95 | { | |
96 | this (dir == null ? null : dir.path, name); | |
97 | } | |
98 | ||
99 | public String getAbsolutePath () | |
100 | { | |
101 | if (isAbsolute ()) | |
102 | return path; | |
103 | return System.getProperty("user.dir") + separatorChar + path; | |
104 | } | |
105 | ||
106 | public native String getCanonicalPath () throws IOException; | |
107 | ||
108 | public String getName () | |
109 | { | |
110 | int last = path.lastIndexOf(separatorChar); | |
41296e2a | 111 | return path.substring(last + 1); |
ee9dd372 TT |
112 | } |
113 | ||
114 | public String getParent () | |
115 | { | |
116 | int last = path.lastIndexOf(separatorChar); | |
117 | if (last == -1) | |
118 | return null; | |
119 | return path.substring(0, last); | |
120 | } | |
121 | ||
122 | public String getPath () | |
123 | { | |
124 | return path; | |
125 | } | |
126 | ||
127 | public int hashCode () | |
128 | { | |
129 | // FIXME: test. | |
130 | return path.hashCode(); | |
131 | } | |
132 | ||
133 | public native boolean isAbsolute (); | |
134 | ||
135 | public boolean isDirectory () | |
136 | { | |
137 | return stat (checkRead (), DIRECTORY); | |
138 | } | |
139 | ||
140 | public boolean isFile () | |
141 | { | |
142 | return stat (checkRead (), ISFILE); | |
143 | } | |
144 | ||
145 | public long lastModified () | |
146 | { | |
147 | return attr (checkRead (), MODIFIED); | |
148 | } | |
149 | ||
150 | public long length () | |
151 | { | |
152 | return attr (checkRead (), LENGTH); | |
153 | } | |
154 | ||
155 | private final native String[] performList (String canon, | |
156 | FilenameFilter filter); | |
157 | public String[] list (FilenameFilter filter) | |
158 | { | |
159 | return performList (checkRead (), filter); | |
160 | } | |
161 | ||
162 | public String[] list () | |
163 | { | |
164 | return performList (checkRead (), null); | |
165 | } | |
166 | ||
167 | public String toString () | |
168 | { | |
169 | return path; | |
170 | } | |
171 | ||
172 | private final native boolean performMkdir (); | |
173 | public boolean mkdir () | |
174 | { | |
175 | SecurityManager s = System.getSecurityManager(); | |
176 | if (s != null) | |
177 | { | |
178 | // NOTE: in theory we should use the canonical path. In | |
179 | // practice, we can't compute the canonical path until we've | |
180 | // made this completely. Lame. | |
181 | s.checkWrite(path); | |
182 | } | |
183 | return performMkdir (); | |
184 | } | |
185 | ||
186 | private static boolean mkdirs (File x) | |
187 | { | |
188 | if (x.isDirectory()) | |
189 | return true; | |
190 | String p = x.getPath(); | |
7f8e55a0 PB |
191 | String parent = x.getParent(); |
192 | if (parent != null) | |
193 | { | |
194 | x.setPath(parent); | |
195 | if (! mkdirs (x)) | |
196 | return false; | |
197 | x.setPath(p); | |
198 | } | |
ee9dd372 TT |
199 | return x.mkdir(); |
200 | } | |
201 | ||
202 | public boolean mkdirs () | |
203 | { | |
204 | SecurityManager s = System.getSecurityManager(); | |
205 | if (s != null) | |
206 | { | |
207 | // NOTE: in theory we should use the canonical path. In | |
208 | // practice, we can't compute the canonical path until we've | |
209 | // made this completely. Lame. | |
210 | s.checkWrite(path); | |
211 | } | |
212 | ||
213 | if (isDirectory ()) | |
214 | return false; | |
215 | return mkdirs (new File (path)); | |
216 | } | |
217 | ||
9d381124 | 218 | private static synchronized String nextValue () |
304ccb10 TT |
219 | { |
220 | return Long.toString(counter++, Character.MAX_RADIX); | |
221 | } | |
222 | ||
223 | public static File createTempFile (String prefix, String suffix, | |
224 | File directory) | |
225 | throws IOException | |
226 | { | |
227 | FileDescriptor desc = new FileDescriptor (); | |
228 | ||
229 | SecurityManager s = System.getSecurityManager(); | |
230 | if (s != null) | |
231 | s.checkWrite (desc); | |
232 | ||
233 | if (prefix.length () < 3) | |
234 | throw new IllegalArgumentException (); | |
235 | if (suffix == null) | |
236 | suffix = ".tmp"; | |
237 | ||
238 | // FIXME: filename length varies by architecture and filesystem. | |
239 | int max_length = 255; | |
240 | ||
241 | // Truncation rules. | |
242 | // `6' is the number of characters we generate. | |
243 | if (prefix.length () + 6 + suffix.length () > max_length) | |
244 | { | |
245 | int suf_len = 0; | |
246 | if (suffix.charAt(0) == '.') | |
247 | suf_len = 4; | |
248 | suffix = suffix.substring(0, suf_len); | |
249 | if (prefix.length () + 6 + suf_len > max_length) | |
250 | prefix = prefix.substring(0, max_length - 6 - suf_len); | |
251 | } | |
252 | ||
253 | // We don't care about the name because we set it later. | |
254 | File ret = new File (""); | |
255 | // How many times should we try? We choose 100. | |
256 | for (int i = 0; i < 100; ++i) | |
257 | { | |
258 | // This is ugly. | |
dd168666 TT |
259 | String t = "ZZZZZZ" + nextValue (); |
260 | String l = prefix + t.substring(t.length() - 6) + suffix; | |
304ccb10 TT |
261 | try |
262 | { | |
263 | desc.open (l, FileDescriptor.WRITE | FileDescriptor.EXCL); | |
264 | ret.setPath(l); | |
265 | return ret; | |
266 | } | |
267 | catch (IOException _) | |
268 | { | |
269 | } | |
270 | } | |
271 | ||
272 | throw new IOException ("couldn't make temp file"); | |
273 | } | |
274 | ||
275 | public static File createTempFile (String prefix, String suffix) | |
276 | throws IOException | |
277 | { | |
278 | return createTempFile (prefix, suffix, null); | |
279 | } | |
280 | ||
ee9dd372 TT |
281 | private final native boolean performRenameTo (File dest); |
282 | public boolean renameTo (File dest) | |
283 | { | |
284 | SecurityManager s = System.getSecurityManager(); | |
285 | if (s != null) | |
286 | { | |
287 | // FIXME: JCL doesn't specify which path to check. We check the | |
288 | // source since we can canonicalize it. | |
289 | s.checkWrite(safeCanonicalPath()); | |
290 | } | |
291 | return performRenameTo (dest); | |
292 | } | |
293 | ||
294 | public static final String pathSeparator | |
295 | = System.getProperty("path.separator"); | |
296 | public static final char pathSeparatorChar = pathSeparator.charAt(0); | |
297 | public static final String separator = System.getProperty("file.separator"); | |
298 | public static final char separatorChar = separator.charAt(0); | |
299 | ||
304ccb10 | 300 | private static final String tmpdir = System.getProperty("java.io.tmpdir"); |
ee9dd372 TT |
301 | |
302 | // The path. | |
303 | private String path; | |
304 | ||
304ccb10 TT |
305 | // We keep a counter for use by createTempFile. We choose the first |
306 | // value randomly to try to avoid clashes with other VMs. | |
307 | private static long counter = Double.doubleToLongBits (Math.random ()); | |
308 | ||
ee9dd372 TT |
309 | // mkdirs() uses this to avoid repeated allocations. |
310 | private final void setPath (String n) | |
311 | { | |
312 | path = n; | |
313 | } | |
314 | ||
315 | ||
316 | private final String checkRead () | |
317 | { | |
318 | SecurityManager s = System.getSecurityManager(); | |
319 | String p = safeCanonicalPath (); | |
320 | if (p == null) | |
321 | return null; | |
322 | if (s != null) | |
323 | s.checkRead(p); | |
324 | return p; | |
325 | } | |
326 | ||
327 | // Return canonical path, or null. | |
328 | private final String safeCanonicalPath () | |
329 | { | |
330 | String p = null; | |
331 | try | |
332 | { | |
333 | p = getCanonicalPath (); | |
334 | } | |
335 | catch (IOException x) | |
336 | { | |
337 | // Nothing. | |
338 | } | |
339 | return p; | |
340 | } | |
341 | ||
342 | // QUERY arguments to access function. | |
343 | private final static int READ = 0; | |
344 | private final static int WRITE = 1; | |
345 | private final static int EXISTS = 2; | |
346 | ||
347 | // QUERY arguments to stat function. | |
348 | private final static int DIRECTORY = 0; | |
349 | private final static int ISFILE = 1; | |
350 | ||
351 | // QUERY arguments to attr function. | |
352 | private final static int MODIFIED = 0; | |
353 | private final static int LENGTH = 1; | |
354 | ||
355 | private final native long attr (String p, int query); | |
356 | private final native boolean access (String p, int query); | |
357 | private final native boolean stat (String p, int query); | |
358 | } |