blob: 748f2086bd17dc5352c330f46fafb78f56291e53 [file] [log] [blame]
alanb772679f2009-08-20 08:39:18 +01001/*
2 * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/* @test
25 * @bug 6595866
26 * @summary Test java.io.File operations with sym links
27 */
28
29import java.io.*;
30import java.nio.file.Path;
31import java.nio.file.attribute.*;
32import static java.nio.file.LinkOption.*;
33
34public class SymLinks {
35 final static PrintStream out = System.out;
36
37 final static File top = new File(System.getProperty("test.dir", "."));
38
39 // files used by the test
40
41 final static File file = new File(top, "foofile");
42 final static File link2file = new File(top, "link2file");
43 final static File link2link2file = new File(top, "link2link2file");
44
45 final static File dir = new File(top, "foodir");
46 final static File link2dir = new File(top, "link2dir");
47 final static File link2link2dir = new File(top, "link2link2dir");
48
49 final static File link2nobody = new File(top, "link2nobody");
50 final static File link2link2nobody = new File(top, "link2link2nobody");
51
52 /**
53 * Setup files, directories, and sym links used by test.
54 */
55 static void setup() throws IOException {
56 // link2link2file -> link2file -> foofile
57 FileOutputStream fos = new FileOutputStream(file);
58 try {
59 fos.write(new byte[16*1024]);
60 } finally {
61 fos.close();
62 }
63 mklink(link2file, file);
64 mklink(link2link2file, link2file);
65
66 // link2link2dir -> link2dir -> dir
67 assertTrue(dir.mkdir());
68 mklink(link2dir, dir);
69 mklink(link2link2dir, link2dir);
70
71 // link2link2nobody -> link2nobody -> <does-not-exist>
72 mklink(link2nobody, new File(top, "DoesNotExist"));
73 mklink(link2link2nobody, link2nobody);
74 }
75
76 /**
77 * Remove files, directories, and sym links used by test.
78 */
79 static void cleanup() throws IOException {
80 if (file != null)
81 file.delete();
82 if (link2file != null)
83 link2file.toPath().deleteIfExists();
84 if (link2link2file != null)
85 link2link2file.toPath().deleteIfExists();
86 if (dir != null)
87 dir.delete();
88 if (link2dir != null)
89 link2dir.toPath().deleteIfExists();
90 if (link2link2dir != null)
91 link2link2dir.toPath().deleteIfExists();
92 if (link2nobody != null)
93 link2nobody.toPath().deleteIfExists();
94 if (link2link2nobody != null)
95 link2link2nobody.toPath().deleteIfExists();
96 }
97
98 /**
99 * Creates a sym link source->target
100 */
101 static void mklink(File source, File target) throws IOException {
102 source.toPath().createSymbolicLink(target.toPath());
103 }
104
105 /**
106 * Returns true if the "link" exists and is a sym link.
107 */
108 static boolean isSymLink(File link) {
109 try {
110 BasicFileAttributes attrs =
111 Attributes.readBasicFileAttributes(link.toPath(), NOFOLLOW_LINKS);
112 return attrs.isSymbolicLink();
113 } catch (IOException x) {
114 return false;
115 }
116 }
117
118 /**
119 * Returns the last modified time of a sym link.
120 */
121 static long lastModifiedOfSymLink(File link) throws IOException {
122 BasicFileAttributes attrs =
123 Attributes.readBasicFileAttributes(link.toPath(), NOFOLLOW_LINKS);
124 assertTrue(attrs.isSymbolicLink());
125 return attrs.lastModifiedTime().toMillis();
126 }
127
128 /**
129 * Returns true if sym links are supported on the file system where
130 * "dir" exists.
131 */
132 static boolean supportsSymLinks(File dir) {
133 Path link = dir.toPath().resolve("link");
134 Path target = dir.toPath().resolve("target");
135 try {
136 link.createSymbolicLink(target);
137 link.delete();
138 return true;
139 } catch (UnsupportedOperationException x) {
140 return false;
141 } catch (IOException x) {
142 return false;
143 }
144 }
145
146 static void assertTrue(boolean v) {
147 if (!v) throw new RuntimeException("Test failed");
148 }
149
150 static void assertFalse(boolean v) {
151 assertTrue(!v);
152 }
153
154 static void header(String h) {
155 out.println();
156 out.println();
157 out.println("-- " + h + " --");
158 }
159
160 /**
161 * Tests go here.
162 */
163 static void go() throws IOException {
164
165 // check setup
166 assertTrue(file.isFile());
167 assertTrue(isSymLink(link2file));
168 assertTrue(isSymLink(link2link2file));
169 assertTrue(dir.isDirectory());
170 assertTrue(isSymLink(link2dir));
171 assertTrue(isSymLink(link2link2dir));
172 assertTrue(isSymLink(link2nobody));
173 assertTrue(isSymLink(link2link2nobody));
174
175 header("createNewFile");
176
177 assertFalse(file.createNewFile());
178 assertFalse(link2file.createNewFile());
179 assertFalse(link2link2file.createNewFile());
180 assertFalse(dir.createNewFile());
181 assertFalse(link2dir.createNewFile());
182 assertFalse(link2link2dir.createNewFile());
183 assertFalse(link2nobody.createNewFile());
184 assertFalse(link2link2nobody.createNewFile());
185
186 header("mkdir");
187
188 assertFalse(file.mkdir());
189 assertFalse(link2file.mkdir());
190 assertFalse(link2link2file.mkdir());
191 assertFalse(dir.mkdir());
192 assertFalse(link2dir.mkdir());
193 assertFalse(link2link2dir.mkdir());
194 assertFalse(link2nobody.mkdir());
195 assertFalse(link2link2nobody.mkdir());
196
197 header("delete");
198
199 File link = new File(top, "mylink");
200 try {
201 mklink(link, file);
202 assertTrue(link.delete());
203 assertTrue(!isSymLink(link));
204 assertTrue(file.exists());
205
206 mklink(link, link2file);
207 assertTrue(link.delete());
208 assertTrue(!isSymLink(link));
209 assertTrue(link2file.exists());
210
211 mklink(link, dir);
212 assertTrue(link.delete());
213 assertTrue(!isSymLink(link));
214 assertTrue(dir.exists());
215
216 mklink(link, link2dir);
217 assertTrue(link.delete());
218 assertTrue(!isSymLink(link));
219 assertTrue(link2dir.exists());
220
221 mklink(link, link2nobody);
222 assertTrue(link.delete());
223 assertTrue(!isSymLink(link));
224 assertTrue(isSymLink(link2nobody));
225
226 } finally {
227 link.toPath().deleteIfExists();
228 }
229
230 header("renameTo");
231
232 File newlink = new File(top, "newlink");
233 assertTrue(link2file.renameTo(newlink));
234 try {
235 assertTrue(file.exists());
236 assertTrue(isSymLink(newlink));
237 assertTrue(!isSymLink(link2file));
238 } finally {
239 newlink.renameTo(link2file); // restore link
240 }
241
242 assertTrue(link2dir.renameTo(newlink));
243 try {
244 assertTrue(dir.exists());
245 assertTrue(isSymLink(newlink));
246 assertTrue(!isSymLink(link2dir));
247 } finally {
248 newlink.renameTo(link2dir); // restore link
249 }
250
251 header("list");
252
253 final String name = "entry";
254 File entry = new File(dir, name);
255 try {
256 assertTrue(dir.list().length == 0); // directory should be empty
257 assertTrue(link2dir.list().length == 0);
258 assertTrue(link2link2dir.list().length == 0);
259
260 assertTrue(entry.createNewFile());
261 assertTrue(dir.list().length == 1);
262 assertTrue(dir.list()[0].equals(name));
263
264 // access directory by following links
265 assertTrue(link2dir.list().length == 1);
266 assertTrue(link2dir.list()[0].equals(name));
267 assertTrue(link2link2dir.list().length == 1);
268 assertTrue(link2link2dir.list()[0].equals(name));
269
270 // files that are not directories
271 assertTrue(link2file.list() == null);
272 assertTrue(link2nobody.list() == null);
273
274 } finally {
275 entry.delete();
276 }
277
278 header("isXXX");
279
280 assertTrue(file.isFile());
281 assertTrue(link2file.isFile());
282 assertTrue(link2link2file.isFile());
283
284 assertTrue(dir.isDirectory());
285 assertTrue(link2dir.isDirectory());
286 assertTrue(link2link2dir.isDirectory());
287
288 // on Windows we test with the DOS hidden attribute set
289 if (System.getProperty("os.name").startsWith("Windows")) {
290 DosFileAttributeView view = file.toPath()
291 .getFileAttributeView(DosFileAttributeView.class);
292 view.setHidden(true);
293 try {
294 assertTrue(file.isHidden());
295 assertTrue(link2file.isHidden());
296 assertTrue(link2link2file.isHidden());
297 } finally {
298 view.setHidden(false);
299 }
300 assertFalse(file.isHidden());
301 assertFalse(link2file.isHidden());
302 assertFalse(link2link2file.isHidden());
303 }
304
305 header("length");
306
307 long len = file.length();
308 assertTrue(len > 0L);
309 // these tests should follow links
310 assertTrue(link2file.length() == len);
311 assertTrue(link2link2file.length() == len);
312 assertTrue(link2nobody.length() == 0L);
313
314 header("lastModified / setLastModified");
315
316 // need time to diff between link and file
317 long origLastModified = file.lastModified();
318 assertTrue(origLastModified != 0L);
319 try { Thread.sleep(2000); } catch (InterruptedException x) { }
320 file.setLastModified(System.currentTimeMillis());
321
322 long lastModified = file.lastModified();
323 assertTrue(lastModified != origLastModified);
324 assertTrue(lastModifiedOfSymLink(link2file) != lastModified);
325 assertTrue(lastModifiedOfSymLink(link2link2file) != lastModified);
326 assertTrue(link2file.lastModified() == lastModified);
327 assertTrue(link2link2file.lastModified() == lastModified);
328 assertTrue(link2nobody.lastModified() == 0L);
329
330 origLastModified = dir.lastModified();
331 assertTrue(origLastModified != 0L);
332 dir.setLastModified(0L);
333 assertTrue(dir.lastModified() == 0L);
334 assertTrue(link2dir.lastModified() == 0L);
335 assertTrue(link2link2dir.lastModified() == 0L);
336 dir.setLastModified(origLastModified);
337
338 header("setXXX / canXXX");
339
340 assertTrue(file.canRead());
341 assertTrue(file.canWrite());
342 assertTrue(link2file.canRead());
343 assertTrue(link2file.canWrite());
344 assertTrue(link2link2file.canRead());
345 assertTrue(link2link2file.canWrite());
346
347 if (file.setReadOnly()) {
348 assertFalse(file.canWrite());
349 assertFalse(link2file.canWrite());
350 assertFalse(link2link2file.canWrite());
351
352 assertTrue(file.setWritable(true)); // make writable
353 assertTrue(file.canWrite());
354 assertTrue(link2file.canWrite());
355 assertTrue(link2link2file.canWrite());
356
357 assertTrue(link2file.setReadOnly()); // make read only
358 assertFalse(file.canWrite());
359 assertFalse(link2file.canWrite());
360 assertFalse(link2link2file.canWrite());
361
362 assertTrue(link2link2file.setWritable(true)); // make writable
363 assertTrue(file.canWrite());
364 assertTrue(link2file.canWrite());
365 assertTrue(link2link2file.canWrite());
366 }
367 }
368
369 public static void main(String[] args) throws IOException {
370 if (supportsSymLinks(top)) {
371 try {
372 setup();
373 go();
374 } finally {
375 cleanup();
376 }
377 }
378 }
379
380}