blob: 04ac95eaed9fa7cf616c7e3a4379d3af038691f3 [file] [log] [blame]
alanb772679f2009-08-20 08:39:18 +01001/*
robm79e61cc2012-08-15 22:46:35 +01002 * Copyright (c) 2009, 2012, 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
robm79e61cc2012-08-15 22:46:35 +010027 * @build SymLinks Util
28 * @run main SymLinks
alanb772679f2009-08-20 08:39:18 +010029 */
30
31import java.io.*;
alanbb75d5382011-01-28 09:28:43 +000032import java.nio.file.*;
alanb772679f2009-08-20 08:39:18 +010033import java.nio.file.attribute.*;
34import static java.nio.file.LinkOption.*;
35
36public class SymLinks {
37 final static PrintStream out = System.out;
38
39 final static File top = new File(System.getProperty("test.dir", "."));
40
41 // files used by the test
42
43 final static File file = new File(top, "foofile");
44 final static File link2file = new File(top, "link2file");
45 final static File link2link2file = new File(top, "link2link2file");
46
47 final static File dir = new File(top, "foodir");
48 final static File link2dir = new File(top, "link2dir");
49 final static File link2link2dir = new File(top, "link2link2dir");
50
51 final static File link2nobody = new File(top, "link2nobody");
52 final static File link2link2nobody = new File(top, "link2link2nobody");
53
54 /**
55 * Setup files, directories, and sym links used by test.
56 */
57 static void setup() throws IOException {
58 // link2link2file -> link2file -> foofile
59 FileOutputStream fos = new FileOutputStream(file);
60 try {
61 fos.write(new byte[16*1024]);
62 } finally {
63 fos.close();
64 }
65 mklink(link2file, file);
66 mklink(link2link2file, link2file);
67
68 // link2link2dir -> link2dir -> dir
69 assertTrue(dir.mkdir());
70 mklink(link2dir, dir);
71 mklink(link2link2dir, link2dir);
72
73 // link2link2nobody -> link2nobody -> <does-not-exist>
74 mklink(link2nobody, new File(top, "DoesNotExist"));
75 mklink(link2link2nobody, link2nobody);
76 }
77
78 /**
79 * Remove files, directories, and sym links used by test.
80 */
81 static void cleanup() throws IOException {
82 if (file != null)
83 file.delete();
84 if (link2file != null)
alanbb75d5382011-01-28 09:28:43 +000085 Files.deleteIfExists(link2file.toPath());
alanb772679f2009-08-20 08:39:18 +010086 if (link2link2file != null)
alanbb75d5382011-01-28 09:28:43 +000087 Files.deleteIfExists(link2link2file.toPath());
alanb772679f2009-08-20 08:39:18 +010088 if (dir != null)
89 dir.delete();
90 if (link2dir != null)
alanbb75d5382011-01-28 09:28:43 +000091 Files.deleteIfExists(link2dir.toPath());
alanb772679f2009-08-20 08:39:18 +010092 if (link2link2dir != null)
alanbb75d5382011-01-28 09:28:43 +000093 Files.deleteIfExists(link2link2dir.toPath());
alanb772679f2009-08-20 08:39:18 +010094 if (link2nobody != null)
alanbb75d5382011-01-28 09:28:43 +000095 Files.deleteIfExists(link2nobody.toPath());
alanb772679f2009-08-20 08:39:18 +010096 if (link2link2nobody != null)
alanbb75d5382011-01-28 09:28:43 +000097 Files.deleteIfExists(link2link2nobody.toPath());
alanb772679f2009-08-20 08:39:18 +010098 }
99
100 /**
101 * Creates a sym link source->target
102 */
103 static void mklink(File source, File target) throws IOException {
alanbb75d5382011-01-28 09:28:43 +0000104 Files.createSymbolicLink(source.toPath(), target.toPath());
alanb772679f2009-08-20 08:39:18 +0100105 }
106
107 /**
108 * Returns true if the "link" exists and is a sym link.
109 */
110 static boolean isSymLink(File link) {
alanbb75d5382011-01-28 09:28:43 +0000111 return Files.isSymbolicLink(link.toPath());
alanb772679f2009-08-20 08:39:18 +0100112 }
113
114 /**
115 * Returns the last modified time of a sym link.
116 */
117 static long lastModifiedOfSymLink(File link) throws IOException {
118 BasicFileAttributes attrs =
alanbb75d5382011-01-28 09:28:43 +0000119 Files.readAttributes(link.toPath(), BasicFileAttributes.class, NOFOLLOW_LINKS);
alanb772679f2009-08-20 08:39:18 +0100120 assertTrue(attrs.isSymbolicLink());
121 return attrs.lastModifiedTime().toMillis();
122 }
123
124 /**
125 * Returns true if sym links are supported on the file system where
126 * "dir" exists.
127 */
128 static boolean supportsSymLinks(File dir) {
129 Path link = dir.toPath().resolve("link");
130 Path target = dir.toPath().resolve("target");
131 try {
alanbb75d5382011-01-28 09:28:43 +0000132 Files.createSymbolicLink(link, target);
133 Files.delete(link);
alanb772679f2009-08-20 08:39:18 +0100134 return true;
135 } catch (UnsupportedOperationException x) {
136 return false;
137 } catch (IOException x) {
138 return false;
139 }
140 }
141
142 static void assertTrue(boolean v) {
143 if (!v) throw new RuntimeException("Test failed");
144 }
145
146 static void assertFalse(boolean v) {
147 assertTrue(!v);
148 }
149
150 static void header(String h) {
151 out.println();
152 out.println();
153 out.println("-- " + h + " --");
154 }
155
156 /**
157 * Tests go here.
158 */
159 static void go() throws IOException {
160
161 // check setup
162 assertTrue(file.isFile());
163 assertTrue(isSymLink(link2file));
164 assertTrue(isSymLink(link2link2file));
165 assertTrue(dir.isDirectory());
166 assertTrue(isSymLink(link2dir));
167 assertTrue(isSymLink(link2link2dir));
168 assertTrue(isSymLink(link2nobody));
169 assertTrue(isSymLink(link2link2nobody));
170
171 header("createNewFile");
172
173 assertFalse(file.createNewFile());
174 assertFalse(link2file.createNewFile());
175 assertFalse(link2link2file.createNewFile());
176 assertFalse(dir.createNewFile());
177 assertFalse(link2dir.createNewFile());
178 assertFalse(link2link2dir.createNewFile());
179 assertFalse(link2nobody.createNewFile());
180 assertFalse(link2link2nobody.createNewFile());
181
182 header("mkdir");
183
184 assertFalse(file.mkdir());
185 assertFalse(link2file.mkdir());
186 assertFalse(link2link2file.mkdir());
187 assertFalse(dir.mkdir());
188 assertFalse(link2dir.mkdir());
189 assertFalse(link2link2dir.mkdir());
190 assertFalse(link2nobody.mkdir());
191 assertFalse(link2link2nobody.mkdir());
192
193 header("delete");
194
195 File link = new File(top, "mylink");
196 try {
197 mklink(link, file);
198 assertTrue(link.delete());
199 assertTrue(!isSymLink(link));
200 assertTrue(file.exists());
201
202 mklink(link, link2file);
203 assertTrue(link.delete());
204 assertTrue(!isSymLink(link));
205 assertTrue(link2file.exists());
206
207 mklink(link, dir);
208 assertTrue(link.delete());
209 assertTrue(!isSymLink(link));
210 assertTrue(dir.exists());
211
212 mklink(link, link2dir);
213 assertTrue(link.delete());
214 assertTrue(!isSymLink(link));
215 assertTrue(link2dir.exists());
216
217 mklink(link, link2nobody);
218 assertTrue(link.delete());
219 assertTrue(!isSymLink(link));
220 assertTrue(isSymLink(link2nobody));
221
222 } finally {
alanbb75d5382011-01-28 09:28:43 +0000223 Files.deleteIfExists(link.toPath());
alanb772679f2009-08-20 08:39:18 +0100224 }
225
226 header("renameTo");
227
228 File newlink = new File(top, "newlink");
229 assertTrue(link2file.renameTo(newlink));
230 try {
231 assertTrue(file.exists());
232 assertTrue(isSymLink(newlink));
233 assertTrue(!isSymLink(link2file));
234 } finally {
235 newlink.renameTo(link2file); // restore link
236 }
237
238 assertTrue(link2dir.renameTo(newlink));
239 try {
240 assertTrue(dir.exists());
241 assertTrue(isSymLink(newlink));
242 assertTrue(!isSymLink(link2dir));
243 } finally {
244 newlink.renameTo(link2dir); // restore link
245 }
246
247 header("list");
248
249 final String name = "entry";
250 File entry = new File(dir, name);
251 try {
252 assertTrue(dir.list().length == 0); // directory should be empty
253 assertTrue(link2dir.list().length == 0);
254 assertTrue(link2link2dir.list().length == 0);
255
256 assertTrue(entry.createNewFile());
257 assertTrue(dir.list().length == 1);
258 assertTrue(dir.list()[0].equals(name));
259
260 // access directory by following links
261 assertTrue(link2dir.list().length == 1);
262 assertTrue(link2dir.list()[0].equals(name));
263 assertTrue(link2link2dir.list().length == 1);
264 assertTrue(link2link2dir.list()[0].equals(name));
265
266 // files that are not directories
267 assertTrue(link2file.list() == null);
268 assertTrue(link2nobody.list() == null);
269
270 } finally {
271 entry.delete();
272 }
273
274 header("isXXX");
275
276 assertTrue(file.isFile());
277 assertTrue(link2file.isFile());
278 assertTrue(link2link2file.isFile());
279
280 assertTrue(dir.isDirectory());
281 assertTrue(link2dir.isDirectory());
282 assertTrue(link2link2dir.isDirectory());
283
284 // on Windows we test with the DOS hidden attribute set
285 if (System.getProperty("os.name").startsWith("Windows")) {
alanbb75d5382011-01-28 09:28:43 +0000286 DosFileAttributeView view = Files
287 .getFileAttributeView(file.toPath(), DosFileAttributeView.class);
alanb772679f2009-08-20 08:39:18 +0100288 view.setHidden(true);
289 try {
290 assertTrue(file.isHidden());
291 assertTrue(link2file.isHidden());
292 assertTrue(link2link2file.isHidden());
293 } finally {
294 view.setHidden(false);
295 }
296 assertFalse(file.isHidden());
297 assertFalse(link2file.isHidden());
298 assertFalse(link2link2file.isHidden());
299 }
300
301 header("length");
302
303 long len = file.length();
304 assertTrue(len > 0L);
305 // these tests should follow links
306 assertTrue(link2file.length() == len);
307 assertTrue(link2link2file.length() == len);
308 assertTrue(link2nobody.length() == 0L);
309
310 header("lastModified / setLastModified");
311
312 // need time to diff between link and file
313 long origLastModified = file.lastModified();
314 assertTrue(origLastModified != 0L);
315 try { Thread.sleep(2000); } catch (InterruptedException x) { }
316 file.setLastModified(System.currentTimeMillis());
317
318 long lastModified = file.lastModified();
319 assertTrue(lastModified != origLastModified);
320 assertTrue(lastModifiedOfSymLink(link2file) != lastModified);
321 assertTrue(lastModifiedOfSymLink(link2link2file) != lastModified);
322 assertTrue(link2file.lastModified() == lastModified);
323 assertTrue(link2link2file.lastModified() == lastModified);
324 assertTrue(link2nobody.lastModified() == 0L);
325
326 origLastModified = dir.lastModified();
327 assertTrue(origLastModified != 0L);
328 dir.setLastModified(0L);
329 assertTrue(dir.lastModified() == 0L);
330 assertTrue(link2dir.lastModified() == 0L);
331 assertTrue(link2link2dir.lastModified() == 0L);
332 dir.setLastModified(origLastModified);
333
334 header("setXXX / canXXX");
335
336 assertTrue(file.canRead());
337 assertTrue(file.canWrite());
338 assertTrue(link2file.canRead());
339 assertTrue(link2file.canWrite());
340 assertTrue(link2link2file.canRead());
341 assertTrue(link2link2file.canWrite());
342
robm79e61cc2012-08-15 22:46:35 +0100343 if (!Util.isPrivileged() && file.setReadOnly()) {
alanb772679f2009-08-20 08:39:18 +0100344 assertFalse(file.canWrite());
345 assertFalse(link2file.canWrite());
346 assertFalse(link2link2file.canWrite());
347
348 assertTrue(file.setWritable(true)); // make writable
349 assertTrue(file.canWrite());
350 assertTrue(link2file.canWrite());
351 assertTrue(link2link2file.canWrite());
352
353 assertTrue(link2file.setReadOnly()); // make read only
354 assertFalse(file.canWrite());
355 assertFalse(link2file.canWrite());
356 assertFalse(link2link2file.canWrite());
357
358 assertTrue(link2link2file.setWritable(true)); // make writable
359 assertTrue(file.canWrite());
360 assertTrue(link2file.canWrite());
361 assertTrue(link2link2file.canWrite());
362 }
363 }
364
365 public static void main(String[] args) throws IOException {
366 if (supportsSymLinks(top)) {
367 try {
368 setup();
369 go();
370 } finally {
371 cleanup();
372 }
373 }
374 }
375
376}