blob: df78f15529bf5412e0d12bae846477cf75be54a3 [file] [log] [blame]
alanb772679f2009-08-20 08:39:18 +01001/*
ohairbf91ea12011-04-06 22:06:11 -07002 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
alanb772679f2009-08-20 08:39:18 +01003 * 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 *
ohair2283b9d2010-05-25 15:58:33 -070019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
alanb772679f2009-08-20 08:39:18 +010022 */
23
24/* @test
25 * @bug 6595866
26 * @summary Test java.io.File operations with sym links
27 */
28
29import java.io.*;
alanbb75d5382011-01-28 09:28:43 +000030import java.nio.file.*;
alanb772679f2009-08-20 08:39:18 +010031import 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)
alanbb75d5382011-01-28 09:28:43 +000083 Files.deleteIfExists(link2file.toPath());
alanb772679f2009-08-20 08:39:18 +010084 if (link2link2file != null)
alanbb75d5382011-01-28 09:28:43 +000085 Files.deleteIfExists(link2link2file.toPath());
alanb772679f2009-08-20 08:39:18 +010086 if (dir != null)
87 dir.delete();
88 if (link2dir != null)
alanbb75d5382011-01-28 09:28:43 +000089 Files.deleteIfExists(link2dir.toPath());
alanb772679f2009-08-20 08:39:18 +010090 if (link2link2dir != null)
alanbb75d5382011-01-28 09:28:43 +000091 Files.deleteIfExists(link2link2dir.toPath());
alanb772679f2009-08-20 08:39:18 +010092 if (link2nobody != null)
alanbb75d5382011-01-28 09:28:43 +000093 Files.deleteIfExists(link2nobody.toPath());
alanb772679f2009-08-20 08:39:18 +010094 if (link2link2nobody != null)
alanbb75d5382011-01-28 09:28:43 +000095 Files.deleteIfExists(link2link2nobody.toPath());
alanb772679f2009-08-20 08:39:18 +010096 }
97
98 /**
99 * Creates a sym link source->target
100 */
101 static void mklink(File source, File target) throws IOException {
alanbb75d5382011-01-28 09:28:43 +0000102 Files.createSymbolicLink(source.toPath(), target.toPath());
alanb772679f2009-08-20 08:39:18 +0100103 }
104
105 /**
106 * Returns true if the "link" exists and is a sym link.
107 */
108 static boolean isSymLink(File link) {
alanbb75d5382011-01-28 09:28:43 +0000109 return Files.isSymbolicLink(link.toPath());
alanb772679f2009-08-20 08:39:18 +0100110 }
111
112 /**
113 * Returns the last modified time of a sym link.
114 */
115 static long lastModifiedOfSymLink(File link) throws IOException {
116 BasicFileAttributes attrs =
alanbb75d5382011-01-28 09:28:43 +0000117 Files.readAttributes(link.toPath(), BasicFileAttributes.class, NOFOLLOW_LINKS);
alanb772679f2009-08-20 08:39:18 +0100118 assertTrue(attrs.isSymbolicLink());
119 return attrs.lastModifiedTime().toMillis();
120 }
121
122 /**
123 * Returns true if sym links are supported on the file system where
124 * "dir" exists.
125 */
126 static boolean supportsSymLinks(File dir) {
127 Path link = dir.toPath().resolve("link");
128 Path target = dir.toPath().resolve("target");
129 try {
alanbb75d5382011-01-28 09:28:43 +0000130 Files.createSymbolicLink(link, target);
131 Files.delete(link);
alanb772679f2009-08-20 08:39:18 +0100132 return true;
133 } catch (UnsupportedOperationException x) {
134 return false;
135 } catch (IOException x) {
136 return false;
137 }
138 }
139
140 static void assertTrue(boolean v) {
141 if (!v) throw new RuntimeException("Test failed");
142 }
143
144 static void assertFalse(boolean v) {
145 assertTrue(!v);
146 }
147
148 static void header(String h) {
149 out.println();
150 out.println();
151 out.println("-- " + h + " --");
152 }
153
154 /**
155 * Tests go here.
156 */
157 static void go() throws IOException {
158
159 // check setup
160 assertTrue(file.isFile());
161 assertTrue(isSymLink(link2file));
162 assertTrue(isSymLink(link2link2file));
163 assertTrue(dir.isDirectory());
164 assertTrue(isSymLink(link2dir));
165 assertTrue(isSymLink(link2link2dir));
166 assertTrue(isSymLink(link2nobody));
167 assertTrue(isSymLink(link2link2nobody));
168
169 header("createNewFile");
170
171 assertFalse(file.createNewFile());
172 assertFalse(link2file.createNewFile());
173 assertFalse(link2link2file.createNewFile());
174 assertFalse(dir.createNewFile());
175 assertFalse(link2dir.createNewFile());
176 assertFalse(link2link2dir.createNewFile());
177 assertFalse(link2nobody.createNewFile());
178 assertFalse(link2link2nobody.createNewFile());
179
180 header("mkdir");
181
182 assertFalse(file.mkdir());
183 assertFalse(link2file.mkdir());
184 assertFalse(link2link2file.mkdir());
185 assertFalse(dir.mkdir());
186 assertFalse(link2dir.mkdir());
187 assertFalse(link2link2dir.mkdir());
188 assertFalse(link2nobody.mkdir());
189 assertFalse(link2link2nobody.mkdir());
190
191 header("delete");
192
193 File link = new File(top, "mylink");
194 try {
195 mklink(link, file);
196 assertTrue(link.delete());
197 assertTrue(!isSymLink(link));
198 assertTrue(file.exists());
199
200 mklink(link, link2file);
201 assertTrue(link.delete());
202 assertTrue(!isSymLink(link));
203 assertTrue(link2file.exists());
204
205 mklink(link, dir);
206 assertTrue(link.delete());
207 assertTrue(!isSymLink(link));
208 assertTrue(dir.exists());
209
210 mklink(link, link2dir);
211 assertTrue(link.delete());
212 assertTrue(!isSymLink(link));
213 assertTrue(link2dir.exists());
214
215 mklink(link, link2nobody);
216 assertTrue(link.delete());
217 assertTrue(!isSymLink(link));
218 assertTrue(isSymLink(link2nobody));
219
220 } finally {
alanbb75d5382011-01-28 09:28:43 +0000221 Files.deleteIfExists(link.toPath());
alanb772679f2009-08-20 08:39:18 +0100222 }
223
224 header("renameTo");
225
226 File newlink = new File(top, "newlink");
227 assertTrue(link2file.renameTo(newlink));
228 try {
229 assertTrue(file.exists());
230 assertTrue(isSymLink(newlink));
231 assertTrue(!isSymLink(link2file));
232 } finally {
233 newlink.renameTo(link2file); // restore link
234 }
235
236 assertTrue(link2dir.renameTo(newlink));
237 try {
238 assertTrue(dir.exists());
239 assertTrue(isSymLink(newlink));
240 assertTrue(!isSymLink(link2dir));
241 } finally {
242 newlink.renameTo(link2dir); // restore link
243 }
244
245 header("list");
246
247 final String name = "entry";
248 File entry = new File(dir, name);
249 try {
250 assertTrue(dir.list().length == 0); // directory should be empty
251 assertTrue(link2dir.list().length == 0);
252 assertTrue(link2link2dir.list().length == 0);
253
254 assertTrue(entry.createNewFile());
255 assertTrue(dir.list().length == 1);
256 assertTrue(dir.list()[0].equals(name));
257
258 // access directory by following links
259 assertTrue(link2dir.list().length == 1);
260 assertTrue(link2dir.list()[0].equals(name));
261 assertTrue(link2link2dir.list().length == 1);
262 assertTrue(link2link2dir.list()[0].equals(name));
263
264 // files that are not directories
265 assertTrue(link2file.list() == null);
266 assertTrue(link2nobody.list() == null);
267
268 } finally {
269 entry.delete();
270 }
271
272 header("isXXX");
273
274 assertTrue(file.isFile());
275 assertTrue(link2file.isFile());
276 assertTrue(link2link2file.isFile());
277
278 assertTrue(dir.isDirectory());
279 assertTrue(link2dir.isDirectory());
280 assertTrue(link2link2dir.isDirectory());
281
282 // on Windows we test with the DOS hidden attribute set
283 if (System.getProperty("os.name").startsWith("Windows")) {
alanbb75d5382011-01-28 09:28:43 +0000284 DosFileAttributeView view = Files
285 .getFileAttributeView(file.toPath(), DosFileAttributeView.class);
alanb772679f2009-08-20 08:39:18 +0100286 view.setHidden(true);
287 try {
288 assertTrue(file.isHidden());
289 assertTrue(link2file.isHidden());
290 assertTrue(link2link2file.isHidden());
291 } finally {
292 view.setHidden(false);
293 }
294 assertFalse(file.isHidden());
295 assertFalse(link2file.isHidden());
296 assertFalse(link2link2file.isHidden());
297 }
298
299 header("length");
300
301 long len = file.length();
302 assertTrue(len > 0L);
303 // these tests should follow links
304 assertTrue(link2file.length() == len);
305 assertTrue(link2link2file.length() == len);
306 assertTrue(link2nobody.length() == 0L);
307
308 header("lastModified / setLastModified");
309
310 // need time to diff between link and file
311 long origLastModified = file.lastModified();
312 assertTrue(origLastModified != 0L);
313 try { Thread.sleep(2000); } catch (InterruptedException x) { }
314 file.setLastModified(System.currentTimeMillis());
315
316 long lastModified = file.lastModified();
317 assertTrue(lastModified != origLastModified);
318 assertTrue(lastModifiedOfSymLink(link2file) != lastModified);
319 assertTrue(lastModifiedOfSymLink(link2link2file) != lastModified);
320 assertTrue(link2file.lastModified() == lastModified);
321 assertTrue(link2link2file.lastModified() == lastModified);
322 assertTrue(link2nobody.lastModified() == 0L);
323
324 origLastModified = dir.lastModified();
325 assertTrue(origLastModified != 0L);
326 dir.setLastModified(0L);
327 assertTrue(dir.lastModified() == 0L);
328 assertTrue(link2dir.lastModified() == 0L);
329 assertTrue(link2link2dir.lastModified() == 0L);
330 dir.setLastModified(origLastModified);
331
332 header("setXXX / canXXX");
333
334 assertTrue(file.canRead());
335 assertTrue(file.canWrite());
336 assertTrue(link2file.canRead());
337 assertTrue(link2file.canWrite());
338 assertTrue(link2link2file.canRead());
339 assertTrue(link2link2file.canWrite());
340
341 if (file.setReadOnly()) {
342 assertFalse(file.canWrite());
343 assertFalse(link2file.canWrite());
344 assertFalse(link2link2file.canWrite());
345
346 assertTrue(file.setWritable(true)); // make writable
347 assertTrue(file.canWrite());
348 assertTrue(link2file.canWrite());
349 assertTrue(link2link2file.canWrite());
350
351 assertTrue(link2file.setReadOnly()); // make read only
352 assertFalse(file.canWrite());
353 assertFalse(link2file.canWrite());
354 assertFalse(link2link2file.canWrite());
355
356 assertTrue(link2link2file.setWritable(true)); // make writable
357 assertTrue(file.canWrite());
358 assertTrue(link2file.canWrite());
359 assertTrue(link2link2file.canWrite());
360 }
361 }
362
363 public static void main(String[] args) throws IOException {
364 if (supportsSymLinks(top)) {
365 try {
366 setup();
367 go();
368 } finally {
369 cleanup();
370 }
371 }
372 }
373
374}