1 /*
   2  * Copyright (c) 2008, 2018, 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 8005566 8032220 8202285
  26  * @summary Unit test for miscellenous methods in java.nio.file.Files
  27  * @library ..
  28  */
  29 
  30 import java.nio.file.*;
  31 import static java.nio.file.Files.*;
  32 import static java.nio.file.LinkOption.*;
  33 import java.nio.file.attribute.*;
  34 import java.io.IOException;
  35 import java.util.*;
  36 
  37 
  38 public class Misc {
  39     // used for random byte content
  40     private static Random RAND = new Random();
  41 
  42     public static void main(String[] args) throws IOException {
  43         Path dir = TestUtil.createTemporaryDirectory();
  44         try {
  45             testCreateDirectories(dir);
  46             testIsHidden(dir);
  47             testIsSameFile(dir);
  48             testIsSameContent(dir);
  49             testFileTypeMethods(dir);
  50             testAccessMethods(dir);
  51         } finally {
  52              TestUtil.removeAll(dir);
  53         }
  54     }
  55 
  56     /**
  57      * Tests createDirectories
  58      */
  59     static void testCreateDirectories(Path tmpdir) throws IOException {
  60         // a no-op
  61         createDirectories(tmpdir);
  62 
  63         // create one directory
  64         Path subdir = tmpdir.resolve("a");
  65         createDirectories(subdir);
  66         assertTrue(exists(subdir));
  67 
  68         // create parents
  69         subdir = subdir.resolve("b/c/d");
  70         createDirectories(subdir);
  71         assertTrue(exists(subdir));
  72 
  73         // existing file is not a directory
  74         Path file = createFile(tmpdir.resolve("x"));
  75         try {
  76             createDirectories(file);
  77             throw new RuntimeException("failure expected");
  78         } catch (FileAlreadyExistsException x) { }
  79         try {
  80             createDirectories(file.resolve("y"));
  81             throw new RuntimeException("failure expected");
  82         } catch (IOException x) { }
  83 
  84         // the root directory always exists
  85         Path root = Paths.get("/");
  86         Files.createDirectories(root);
  87         Files.createDirectories(root.toAbsolutePath());
  88     }
  89 
  90     /**
  91      * Tests isHidden
  92      */
  93     static void testIsHidden(Path tmpdir) throws IOException {
  94         assertTrue(!isHidden(tmpdir));
  95 
  96         Path file = tmpdir.resolve(".foo");
  97         if (System.getProperty("os.name").startsWith("Windows")) {
  98             createFile(file);
  99             try {
 100                 setAttribute(file, "dos:hidden", true);
 101                 try {
 102                     assertTrue(isHidden(file));
 103                 } finally {
 104                     setAttribute(file, "dos:hidden", false);
 105                 }
 106             } finally {
 107                 delete(file);
 108             }
 109         } else {
 110             assertTrue(isHidden(file));
 111         }
 112     }
 113 
 114     /**
 115      * Tests isSameFile
 116      */
 117     static void testIsSameFile(Path tmpdir) throws IOException {
 118         Path thisFile = tmpdir.resolve("thisFile");
 119         Path thatFile = tmpdir.resolve("thatFile");
 120 
 121         /**
 122          * Test: isSameFile for self
 123          */
 124         assertTrue(isSameFile(thisFile, thisFile));
 125 
 126         /**
 127          * Test: Neither files exist
 128          */
 129         try {
 130             isSameFile(thisFile, thatFile);
 131             throw new RuntimeException("IOException not thrown");
 132         } catch (IOException x) {
 133         }
 134         try {
 135             isSameFile(thatFile, thisFile);
 136             throw new RuntimeException("IOException not thrown");
 137         } catch (IOException x) {
 138         }
 139 
 140         createFile(thisFile);
 141         try {
 142             /**
 143              * Test: One file exists
 144              */
 145             try {
 146                 isSameFile(thisFile, thatFile);
 147                 throw new RuntimeException("IOException not thrown");
 148             } catch (IOException x) {
 149             }
 150             try {
 151                 isSameFile(thatFile, thisFile);
 152                 throw new RuntimeException("IOException not thrown");
 153             } catch (IOException x) {
 154             }
 155 
 156             /**
 157              * Test: Both file exists
 158              */
 159             createFile(thatFile);
 160             try {
 161                 assertTrue(!isSameFile(thisFile, thatFile));
 162                 assertTrue(!isSameFile(thatFile, thisFile));
 163             } finally {
 164                 delete(thatFile);
 165             }
 166 
 167             /**
 168              * Test: Symbolic links
 169              */
 170             if (TestUtil.supportsLinks(tmpdir)) {
 171                 createSymbolicLink(thatFile, thisFile);
 172                 try {
 173                     assertTrue(isSameFile(thisFile, thatFile));
 174                     assertTrue(isSameFile(thatFile, thisFile));
 175                 } finally {
 176                     TestUtil.deleteUnchecked(thatFile);
 177                 }
 178             }
 179         } finally {
 180             delete(thisFile);
 181         }
 182 
 183         // nulls
 184         try {
 185             isSameFile(thisFile, null);
 186             throw new RuntimeException("NullPointerException expected");
 187         } catch (NullPointerException ignore) { }
 188         try {
 189             isSameFile(null, thatFile);
 190             throw new RuntimeException("NullPointerException expected");
 191         } catch (NullPointerException ignore) { }
 192     }
 193 
 194     /**
 195      * Tests isSameContent. The isSameContent is an extension to isSameFile, the
 196      * test therefore is a copy of the testIsSameFile until the last section that
 197      * compares the content.
 198      */
 199     static void testIsSameContent(Path tmpdir) throws IOException {
 200         Path thisFile = tmpdir.resolve("thisFile1");
 201         Path thatFile = tmpdir.resolve("thatFile1");
 202 
 203         /**
 204          * Test: isSameContent for self
 205          */
 206         assertTrue(isSameContent(thisFile, thisFile));
 207 
 208         /**
 209          * Test: Neither files exist
 210          */
 211         try {
 212             isSameContent(thisFile, thatFile);
 213             throw new RuntimeException("IOException not thrown");
 214         } catch (IOException x) {
 215         }
 216         try {
 217             isSameContent(thatFile, thisFile);
 218             throw new RuntimeException("IOException not thrown");
 219         } catch (IOException x) {
 220         }
 221 
 222         createFile(thisFile);
 223         try {
 224             /**
 225              * Test: One file exists
 226              */
 227             try {
 228                 isSameContent(thisFile, thatFile);
 229                 throw new RuntimeException("IOException not thrown");
 230             } catch (IOException x) {
 231             }
 232             try {
 233                 isSameContent(thatFile, thisFile);
 234                 throw new RuntimeException("IOException not thrown");
 235             } catch (IOException x) {
 236             }
 237 
 238             /**
 239              * Test: Both file exists
 240              */
 241             createFile(thatFile);
 242             try {
 243                 assertTrue(!isSameContent(thisFile, thatFile));
 244                 assertTrue(!isSameContent(thatFile, thisFile));
 245             } finally {
 246                 delete(thatFile);
 247             }
 248 
 249             /**
 250              * Test: Symbolic links
 251              */
 252             if (TestUtil.supportsLinks(tmpdir)) {
 253                 createSymbolicLink(thatFile, thisFile);
 254                 try {
 255                     assertTrue(isSameContent(thisFile, thatFile));
 256                     assertTrue(isSameContent(thatFile, thisFile));
 257                 } finally {
 258                     TestUtil.deleteUnchecked(thatFile);
 259                 }
 260             }
 261         } finally {
 262             delete(thisFile);
 263         }
 264 
 265         // nulls
 266         try {
 267             isSameContent(thisFile, null);
 268             throw new RuntimeException("NullPointerException expected");
 269         } catch (NullPointerException ignore) { }
 270         try {
 271             isSameContent(null, thatFile);
 272             throw new RuntimeException("NullPointerException expected");
 273         } catch (NullPointerException ignore) { }
 274 
 275         // compares the contents
 276         byte[] bytes = genBytes(512);
 277         Files.write(thisFile, bytes, StandardOpenOption.CREATE);
 278         Files.write(thatFile, bytes, StandardOpenOption.CREATE);
 279         assertTrue(isSameContent(thisFile, thatFile));
 280     }
 281 
 282     /**
 283      * Returns a byte[] of the given size with random content
 284      */
 285     static private byte[] genBytes(int size) {
 286         byte[] arr = new byte[size];
 287         RAND.nextBytes(arr);
 288         return arr;
 289     }
 290 
 291     /**
 292      * Exercise isRegularFile, isDirectory, isSymbolicLink
 293      */
 294     static void testFileTypeMethods(Path tmpdir) throws IOException {
 295         assertTrue(!isRegularFile(tmpdir));
 296         assertTrue(!isRegularFile(tmpdir, NOFOLLOW_LINKS));
 297         assertTrue(isDirectory(tmpdir));
 298         assertTrue(isDirectory(tmpdir, NOFOLLOW_LINKS));
 299         assertTrue(!isSymbolicLink(tmpdir));
 300 
 301         Path file = createFile(tmpdir.resolve("foo"));
 302         try {
 303             assertTrue(isRegularFile(file));
 304             assertTrue(isRegularFile(file, NOFOLLOW_LINKS));
 305             assertTrue(!isDirectory(file));
 306             assertTrue(!isDirectory(file, NOFOLLOW_LINKS));
 307             assertTrue(!isSymbolicLink(file));
 308 
 309             if (TestUtil.supportsLinks(tmpdir)) {
 310                 Path link = tmpdir.resolve("link");
 311 
 312                 createSymbolicLink(link, tmpdir);
 313                 try {
 314                     assertTrue(!isRegularFile(link));
 315                     assertTrue(!isRegularFile(link, NOFOLLOW_LINKS));
 316                     assertTrue(isDirectory(link));
 317                     assertTrue(!isDirectory(link, NOFOLLOW_LINKS));
 318                     assertTrue(isSymbolicLink(link));
 319                 } finally {
 320                     delete(link);
 321                 }
 322 
 323                 createSymbolicLink(link, file);
 324                 try {
 325                     assertTrue(isRegularFile(link));
 326                     assertTrue(!isRegularFile(link, NOFOLLOW_LINKS));
 327                     assertTrue(!isDirectory(link));
 328                     assertTrue(!isDirectory(link, NOFOLLOW_LINKS));
 329                     assertTrue(isSymbolicLink(link));
 330                 } finally {
 331                     delete(link);
 332                 }
 333 
 334                 createLink(link, file);
 335                 try {
 336                     assertTrue(isRegularFile(link));
 337                     assertTrue(isRegularFile(link, NOFOLLOW_LINKS));
 338                     assertTrue(!isDirectory(link));
 339                     assertTrue(!isDirectory(link, NOFOLLOW_LINKS));
 340                     assertTrue(!isSymbolicLink(link));
 341                 } finally {
 342                     delete(link);
 343                 }
 344             }
 345 
 346         } finally {
 347             delete(file);
 348         }
 349     }
 350 
 351     /**
 352      * Exercise isReadbale, isWritable, isExecutable, exists, notExists
 353      */
 354     static void testAccessMethods(Path tmpdir) throws IOException {
 355         // should return false when file does not exist
 356         Path doesNotExist = tmpdir.resolve("doesNotExist");
 357         assertTrue(!isReadable(doesNotExist));
 358         assertTrue(!isWritable(doesNotExist));
 359         assertTrue(!isExecutable(doesNotExist));
 360         assertTrue(!exists(doesNotExist));
 361         assertTrue(notExists(doesNotExist));
 362 
 363         Path file = createFile(tmpdir.resolve("foo"));
 364         try {
 365             // files exist
 366             assertTrue(isReadable(file));
 367             assertTrue(isWritable(file));
 368             assertTrue(exists(file));
 369             assertTrue(!notExists(file));
 370             assertTrue(isReadable(tmpdir));
 371             assertTrue(isWritable(tmpdir));
 372             assertTrue(exists(tmpdir));
 373             assertTrue(!notExists(tmpdir));
 374 
 375 
 376             // sym link exists
 377             if (TestUtil.supportsLinks(tmpdir)) {
 378                 Path link = tmpdir.resolve("link");
 379 
 380                 createSymbolicLink(link, file);
 381                 try {
 382                     assertTrue(isReadable(link));
 383                     assertTrue(isWritable(link));
 384                     assertTrue(exists(link));
 385                     assertTrue(!notExists(link));
 386                 } finally {
 387                     delete(link);
 388                 }
 389 
 390                 createSymbolicLink(link, doesNotExist);
 391                 try {
 392                     assertTrue(!isReadable(link));
 393                     assertTrue(!isWritable(link));
 394                     assertTrue(!exists(link));
 395                     assertTrue(exists(link, NOFOLLOW_LINKS));
 396                     assertTrue(notExists(link));
 397                     assertTrue(!notExists(link, NOFOLLOW_LINKS));
 398                 } finally {
 399                     delete(link);
 400                 }
 401             }
 402 
 403             /**
 404              * Test: Edit ACL to deny WRITE and EXECUTE
 405              */
 406             if (getFileStore(file).supportsFileAttributeView("acl")) {
 407                 AclFileAttributeView view =
 408                     getFileAttributeView(file, AclFileAttributeView.class);
 409                 UserPrincipal owner = view.getOwner();
 410                 List<AclEntry> acl = view.getAcl();
 411 
 412                 // Insert entry to deny WRITE and EXECUTE
 413                 AclEntry entry = AclEntry.newBuilder()
 414                     .setType(AclEntryType.DENY)
 415                     .setPrincipal(owner)
 416                     .setPermissions(AclEntryPermission.WRITE_DATA,
 417                                     AclEntryPermission.EXECUTE)
 418                     .build();
 419                 acl.add(0, entry);
 420                 view.setAcl(acl);
 421                 try {
 422                     if (isRoot()) {
 423                         // root has all permissions
 424                         assertTrue(isWritable(file));
 425                         assertTrue(isExecutable(file));
 426                     } else {
 427                         assertTrue(!isWritable(file));
 428                         assertTrue(!isExecutable(file));
 429                     }
 430                 } finally {
 431                     // Restore ACL
 432                     acl.remove(0);
 433                     view.setAcl(acl);
 434                 }
 435             }
 436 
 437             /**
 438              * Test: Windows DOS read-only attribute
 439              */
 440             if (System.getProperty("os.name").startsWith("Windows")) {
 441                 setAttribute(file, "dos:readonly", true);
 442                 try {
 443                     assertTrue(!isWritable(file));
 444                 } finally {
 445                     setAttribute(file, "dos:readonly", false);
 446                 }
 447 
 448                 // Read-only attribute does not make direcory read-only
 449                 DosFileAttributeView view =
 450                     getFileAttributeView(tmpdir, DosFileAttributeView.class);
 451                 boolean save = view.readAttributes().isReadOnly();
 452                 view.setReadOnly(true);
 453                 try {
 454                     assertTrue(isWritable(file));
 455                 } finally {
 456                     view.setReadOnly(save);
 457                 }
 458             }
 459         } finally {
 460             delete(file);
 461         }
 462     }
 463 
 464     static void assertTrue(boolean okay) {
 465         if (!okay)
 466             throw new RuntimeException("Assertion Failed");
 467     }
 468 
 469     private static boolean isRoot() {
 470         if (System.getProperty("os.name").startsWith("Windows"))
 471             return false;
 472 
 473         Path passwd = Paths.get("/etc/passwd");
 474         return Files.isWritable(passwd);
 475     }
 476 }