1 /*
   2  * Copyright (c) 2008, 2009, Oracle and/or its affiliates. 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 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.
  22  */
  23 
  24 /* @test
  25  * @bug 4313887 6838333 6863864
  26  * @summary Unit test for java.nio.file.Files createSymbolicLink,
  27  *     readSymbolicLink, and createLink methods
  28  * @library ..
  29  * @build Links
  30  * @run main/othervm Links
  31  */
  32 
  33 import java.nio.file.*;
  34 import java.nio.file.attribute.*;
  35 import java.io.*;
  36 
  37 public class Links {
  38 
  39     static final boolean isWindows =
  40         System.getProperty("os.name").startsWith("Windows");
  41 
  42     static void assertTrue(boolean okay) {
  43         if (!okay)
  44             throw new RuntimeException("Assertion failed");
  45     }
  46 
  47     /**
  48      * Exercise createSymbolicLink and readLink methods
  49      */
  50     static void testSymLinks(Path dir) throws IOException {
  51         final Path link = dir.resolve("link");
  52 
  53         // Check if sym links are supported
  54         try {
  55             Files.createSymbolicLink(link, Paths.get("foo"));
  56             Files.delete(link);
  57         } catch (UnsupportedOperationException x) {
  58             // sym links not supported
  59             return;
  60         } catch (IOException x) {
  61             // probably insufficient privileges to create sym links (Windows)
  62             return;
  63         }
  64 
  65         // Test links to various targets
  66         String[] windowsTargets =
  67             { "foo", "C:\\foo", "\\foo", "\\\\server\\share\\foo" };
  68         String[] otherTargets = { "relative", "/absolute" };
  69 
  70         String[] targets = (isWindows) ? windowsTargets : otherTargets;
  71         for (String s: targets) {
  72             Path target = Paths.get(s);
  73             Files.createSymbolicLink(link, target);
  74             try {
  75                 assertTrue(Files.readSymbolicLink(link).equals(target));
  76             } finally {
  77                 Files.delete(link);
  78             }
  79         }
  80 
  81         // Test links to directory
  82         Path mydir = dir.resolve("mydir");
  83         Path myfile = mydir.resolve("myfile");
  84         try {
  85             Files.createDirectory(mydir);
  86             Files.createFile(myfile);
  87 
  88             // link -> "mydir"
  89             Files.createSymbolicLink(link, mydir.getFileName());
  90             assertTrue(Files.readSymbolicLink(link).equals(mydir.getFileName()));
  91 
  92             // Test access to directory via link
  93             try (DirectoryStream<Path> stream = Files.newDirectoryStream(link)) {
  94                 boolean found = false;
  95                 for (Path entry: stream) {
  96                     if (entry.getFileName().equals(myfile.getFileName())) {
  97                         found = true;
  98                         break;
  99                     }
 100                 }
 101                 assertTrue(found);
 102             }
 103 
 104             // Test link2 -> link -> mydir
 105             final Path link2 = dir.resolve("link2");
 106             Path target2 = link.getFileName();
 107             Files.createSymbolicLink(link2, target2);
 108             try {
 109                 assertTrue(Files.readSymbolicLink(link2).equals(target2));
 110                 Files.newDirectoryStream(link2).close();
 111             } finally {
 112                 Files.delete(link2);
 113             }
 114 
 115             // Remove mydir and re-create link2 before re-creating mydir
 116             // (This is a useful test on Windows to ensure that creating a
 117             // sym link to a directory sym link creates the right type of link).
 118             Files.delete(myfile);
 119             Files.delete(mydir);
 120             Files.createSymbolicLink(link2, target2);
 121             try {
 122                 assertTrue(Files.readSymbolicLink(link2).equals(target2));
 123                 Files.createDirectory(mydir);
 124                 Files.newDirectoryStream(link2).close();
 125             } finally {
 126                 Files.delete(link2);
 127             }
 128 
 129         } finally {
 130             Files.deleteIfExists(myfile);
 131             Files.deleteIfExists(mydir);
 132             Files.deleteIfExists(link);
 133         }
 134     }
 135 
 136     /**
 137      * Exercise createLink method
 138      */
 139     static void testHardLinks(Path dir) throws IOException {
 140         Path foo = dir.resolve("foo");
 141         Files.createFile(foo);
 142         try {
 143             Path bar = dir.resolve("bar");
 144             try {
 145                 Files.createLink(bar, foo);
 146             } catch (UnsupportedOperationException x) {
 147                 return;
 148             } catch (IOException x) {
 149                 // probably insufficient privileges (Windows)
 150                 return;
 151             }
 152             try {
 153                 Object key1 = Files.readAttributes(foo, BasicFileAttributes.class).fileKey();
 154                 Object key2 = Files.readAttributes(bar, BasicFileAttributes.class).fileKey();
 155                 assertTrue((key1 == null) || (key1.equals(key2)));
 156             } finally {
 157                 Files.delete(bar);
 158             }
 159 
 160 
 161         } finally {
 162             Files.delete(foo);
 163         }
 164     }
 165 
 166     public static void main(String[] args) throws IOException {
 167         Path dir = TestUtil.createTemporaryDirectory();
 168         try {
 169             testSymLinks(dir);
 170             testHardLinks(dir);
 171 
 172             // repeat tests on Windows with long path
 173             if (isWindows) {
 174                 Path dirWithLongPath = null;
 175                 try {
 176                     dirWithLongPath = TestUtil.createDirectoryWithLongPath(dir);
 177                 } catch (IOException x) {
 178                     System.out.println("Unable to create long path: " + x);
 179                 }
 180                 if (dirWithLongPath != null) {
 181                     System.out.println("");
 182                     System.out.println("** REPEAT TESTS WITH LONG PATH **");
 183                     testSymLinks(dirWithLongPath);
 184                     testHardLinks(dirWithLongPath);
 185                 }
 186             }
 187         } finally {
 188             TestUtil.removeAll(dir);
 189         }
 190     }
 191 }