1 /*
   2  * Copyright (c) 2008, 2011, 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
  26  * @summary Unit test for java.nio.file.attribute.PosixFileAttributeView
  27  * @library ../..
  28  */
  29 
  30 import java.nio.file.*;
  31 import static java.nio.file.LinkOption.*;
  32 import java.nio.file.attribute.*;
  33 import java.io.IOException;
  34 import java.util.*;
  35 
  36 /**
  37  * Unit test for PosixFileAttributeView, passing silently if this attribute
  38  * view is not available.
  39  */
  40 
  41 public class Basic {
  42 
  43     /**
  44      * Use view to update permission to the given mode and check that the
  45      * permissions have been updated.
  46      */
  47     static void testPermissions(Path file, String mode) throws IOException {
  48         System.out.format("change mode: %s\n", mode);
  49         Set<PosixFilePermission> perms = PosixFilePermissions.fromString(mode);
  50 
  51         // change permissions and re-read them.
  52         Files.setPosixFilePermissions(file, perms);
  53         Set<PosixFilePermission> current = Files.getPosixFilePermissions(file);
  54         if (!current.equals(perms)) {
  55             throw new RuntimeException("Actual permissions: " +
  56                 PosixFilePermissions.toString(current) + ", expected: " +
  57                 PosixFilePermissions.toString(perms));
  58         }
  59 
  60         // repeat test using setAttribute/getAttribute
  61         Files.setAttribute(file, "posix:permissions", perms);
  62         current = (Set<PosixFilePermission>)Files.getAttribute(file, "posix:permissions");
  63         if (!current.equals(perms)) {
  64             throw new RuntimeException("Actual permissions: " +
  65                 PosixFilePermissions.toString(current) + ", expected: " +
  66                 PosixFilePermissions.toString(perms));
  67         }
  68     }
  69 
  70     /**
  71      * Check that the actual permissions of a file match or make it more
  72      * secure than requested
  73      */
  74     static void checkSecure(Set<PosixFilePermission> requested,
  75                             Set<PosixFilePermission> actual)
  76     {
  77         for (PosixFilePermission perm: actual) {
  78             if (!requested.contains(perm)) {
  79                 throw new RuntimeException("Actual permissions: " +
  80                     PosixFilePermissions.toString(actual) + ", requested: " +
  81                     PosixFilePermissions.toString(requested) +
  82                     " - file is less secure than requested");
  83             }
  84         }
  85     }
  86 
  87     /**
  88      * Create file with given mode and check that the file is created with a
  89      * mode that is not less secure
  90      */
  91     static void createWithPermissions(Path file,
  92                                       String mode)
  93         throws IOException
  94     {
  95         Set<PosixFilePermission> requested = PosixFilePermissions.fromString(mode);
  96         FileAttribute<Set<PosixFilePermission>> attr =
  97             PosixFilePermissions.asFileAttribute(requested);
  98         System.out.format("create file with mode: %s\n", mode);
  99         Files.createFile(file, attr);
 100         try {
 101             checkSecure(requested,
 102                 Files.getFileAttributeView(file, PosixFileAttributeView.class)
 103                      .readAttributes()
 104                      .permissions());
 105         } finally {
 106             Files.delete(file);
 107         }
 108 
 109         System.out.format("create directory with mode: %s\n", mode);
 110         Files.createDirectory(file, attr);
 111         try {
 112             checkSecure(requested,
 113                 Files.getFileAttributeView(file, PosixFileAttributeView.class)
 114                      .readAttributes()
 115                      .permissions());
 116         } finally {
 117             Files.delete(file);
 118         }
 119     }
 120 
 121     /**
 122      * Test the setPermissions/permissions methods.
 123      */
 124     static void permissionTests(Path dir)
 125         throws IOException
 126     {
 127         System.out.println("-- Permission Tests  --");
 128 
 129         // create file and test updating and reading its permissions
 130         Path file = dir.resolve("foo");
 131         System.out.format("create %s\n", file);
 132         Files.createFile(file);
 133         try {
 134             // get initial permissions so that we can restore them later
 135             PosixFileAttributeView view =
 136                 Files.getFileAttributeView(file, PosixFileAttributeView.class);
 137             Set<PosixFilePermission> save = view.readAttributes()
 138                 .permissions();
 139 
 140             // test various modes
 141             try {
 142                 testPermissions(file, "---------");
 143                 testPermissions(file, "r--------");
 144                 testPermissions(file, "-w-------");
 145                 testPermissions(file, "--x------");
 146                 testPermissions(file, "rwx------");
 147                 testPermissions(file, "---r-----");
 148                 testPermissions(file, "----w----");
 149                 testPermissions(file, "-----x---");
 150                 testPermissions(file, "---rwx---");
 151                 testPermissions(file, "------r--");
 152                 testPermissions(file, "-------w-");
 153                 testPermissions(file, "--------x");
 154                 testPermissions(file, "------rwx");
 155                 testPermissions(file, "r--r-----");
 156                 testPermissions(file, "r--r--r--");
 157                 testPermissions(file, "rw-rw----");
 158                 testPermissions(file, "rwxrwx---");
 159                 testPermissions(file, "rw-rw-r--");
 160                 testPermissions(file, "r-xr-x---");
 161                 testPermissions(file, "r-xr-xr-x");
 162                 testPermissions(file, "rwxrwxrwx");
 163             } finally {
 164                 view.setPermissions(save);
 165             }
 166         } finally {
 167             Files.delete(file);
 168         }
 169 
 170         // create link (to file that doesn't exist) and test reading of
 171         // permissions
 172         if (TestUtil.supportsLinks(dir)) {
 173             Path link = dir.resolve("link");
 174             System.out.format("create link %s\n", link);
 175             Files.createSymbolicLink(link, file);
 176             try {
 177                 PosixFileAttributes attrs =
 178                     Files.getFileAttributeView(link,
 179                                                PosixFileAttributeView.class,
 180                                                NOFOLLOW_LINKS)
 181                          .readAttributes();
 182                 if (!attrs.isSymbolicLink()) {
 183                     throw new RuntimeException("not a link");
 184                 }
 185             } finally {
 186                 Files.delete(link);
 187             }
 188         }
 189 
 190         System.out.println("OKAY");
 191     }
 192 
 193     /**
 194      * Test creating a file and directory with initial permissios
 195      */
 196     static void createTests(Path dir)
 197         throws IOException
 198     {
 199         System.out.println("-- Create Tests  --");
 200 
 201         Path file = dir.resolve("foo");
 202 
 203         createWithPermissions(file, "---------");
 204         createWithPermissions(file, "r--------");
 205         createWithPermissions(file, "-w-------");
 206         createWithPermissions(file, "--x------");
 207         createWithPermissions(file, "rwx------");
 208         createWithPermissions(file, "---r-----");
 209         createWithPermissions(file, "----w----");
 210         createWithPermissions(file, "-----x---");
 211         createWithPermissions(file, "---rwx---");
 212         createWithPermissions(file, "------r--");
 213         createWithPermissions(file, "-------w-");
 214         createWithPermissions(file, "--------x");
 215         createWithPermissions(file, "------rwx");
 216         createWithPermissions(file, "r--r-----");
 217         createWithPermissions(file, "r--r--r--");
 218         createWithPermissions(file, "rw-rw----");
 219         createWithPermissions(file, "rwxrwx---");
 220         createWithPermissions(file, "rw-rw-r--");
 221         createWithPermissions(file, "r-xr-x---");
 222         createWithPermissions(file, "r-xr-xr-x");
 223         createWithPermissions(file, "rwxrwxrwx");
 224 
 225         System.out.println("OKAY");
 226     }
 227 
 228     /**
 229      * Test setOwner/setGroup methods - this test simply exercises the
 230      * methods to avoid configuration.
 231      */
 232     static void ownerTests(Path dir)
 233         throws IOException
 234     {
 235         System.out.println("-- Owner Tests  --");
 236 
 237         Path file = dir.resolve("gus");
 238         System.out.format("create %s\n", file);
 239 
 240         Files.createFile(file);
 241         try {
 242 
 243             // read attributes of directory to get owner/group
 244             PosixFileAttributeView view =
 245                 Files.getFileAttributeView(file, PosixFileAttributeView.class);
 246             PosixFileAttributes attrs = view.readAttributes();
 247 
 248             // set to existing owner/group
 249             view.setOwner(attrs.owner());
 250             view.setGroup(attrs.group());
 251 
 252             // repeat test using set/getAttribute
 253             UserPrincipal owner = (UserPrincipal)Files.getAttribute(file, "posix:owner");
 254             Files.setAttribute(file, "posix:owner", owner);
 255             UserPrincipal group = (UserPrincipal)Files.getAttribute(file, "posix:group");
 256             Files.setAttribute(file, "posix:group", group);
 257 
 258         } finally {
 259             Files.delete(file);
 260         }
 261 
 262         System.out.println("OKAY");
 263     }
 264 
 265     /**
 266      * Test the lookupPrincipalByName/lookupPrincipalByGroupName methods
 267      */
 268     static void lookupPrincipalTests(Path dir)
 269         throws IOException
 270     {
 271         System.out.println("-- Lookup UserPrincipal Tests --");
 272 
 273         UserPrincipalLookupService lookupService = dir.getFileSystem()
 274             .getUserPrincipalLookupService();
 275 
 276         // read attributes of directory to get owner/group
 277         PosixFileAttributes attrs = Files.readAttributes(dir, PosixFileAttributes.class);
 278 
 279         // lookup owner and check it matches file's owner
 280         System.out.format("lookup: %s\n", attrs.owner().getName());
 281         try {
 282             UserPrincipal owner = lookupService.lookupPrincipalByName(attrs.owner().getName());
 283             if (owner instanceof GroupPrincipal)
 284                 throw new RuntimeException("owner is a group?");
 285             if (!owner.equals(attrs.owner()))
 286                 throw new RuntimeException("owner different from file owner");
 287         } catch (UserPrincipalNotFoundException x) {
 288             System.out.println("user not found - test skipped");
 289         }
 290 
 291         // lookup group and check it matches file's group-owner
 292         System.out.format("lookup group: %s\n", attrs.group().getName());
 293         try {
 294             GroupPrincipal group = lookupService.lookupPrincipalByGroupName(attrs.group().getName());
 295             if (!group.equals(attrs.group()))
 296                 throw new RuntimeException("group different from file group-owner");
 297         } catch (UserPrincipalNotFoundException x) {
 298             System.out.println("group not found - test skipped");
 299         }
 300 
 301         // test that UserPrincipalNotFoundException is thrown
 302         String invalidPrincipal = "scumbag99";
 303         try {
 304             System.out.format("lookup: %s\n", invalidPrincipal);
 305             lookupService.lookupPrincipalByName(invalidPrincipal);
 306             throw new RuntimeException("'" + invalidPrincipal + "' is a valid user?");
 307         } catch (UserPrincipalNotFoundException x) {
 308         }
 309         try {
 310             System.out.format("lookup group: %s\n", invalidPrincipal);
 311             lookupService.lookupPrincipalByGroupName("idonotexist");
 312             throw new RuntimeException("'" + invalidPrincipal + "' is a valid group?");
 313         } catch (UserPrincipalNotFoundException x) {
 314         }
 315         System.out.println("OKAY");
 316     }
 317 
 318     /**
 319      * Test various exceptions are thrown as expected
 320      */
 321     @SuppressWarnings("unchecked")
 322     static void exceptionsTests(Path dir)
 323         throws IOException
 324     {
 325         System.out.println("-- Exceptions --");
 326 
 327         PosixFileAttributeView view =
 328             Files.getFileAttributeView(dir,PosixFileAttributeView.class);
 329 
 330         // NullPointerException
 331         try {
 332             view.setOwner(null);
 333             throw new RuntimeException("NullPointerException not thrown");
 334         } catch (NullPointerException x) {
 335         }
 336         try {
 337             view.setGroup(null);
 338             throw new RuntimeException("NullPointerException not thrown");
 339         } catch (NullPointerException x) {
 340         }
 341 
 342         UserPrincipalLookupService lookupService = dir.getFileSystem()
 343             .getUserPrincipalLookupService();
 344         try {
 345             lookupService.lookupPrincipalByName(null);
 346             throw new RuntimeException("NullPointerException not thrown");
 347         } catch (NullPointerException x) {
 348         }
 349         try {
 350             lookupService.lookupPrincipalByGroupName(null);
 351             throw new RuntimeException("NullPointerException not thrown");
 352         } catch (NullPointerException x) {
 353         }
 354         try {
 355             view.setPermissions(null);
 356             throw new RuntimeException("NullPointerException not thrown");
 357         } catch (NullPointerException x) {
 358         }
 359         try {
 360             Set<PosixFilePermission> perms = new HashSet<>();
 361             perms.add(null);
 362             view.setPermissions(perms);
 363             throw new RuntimeException("NullPointerException not thrown");
 364         }  catch (NullPointerException x) {
 365         }
 366 
 367         // ClassCastException
 368         try {
 369             Set perms = new HashSet();  // raw type
 370             perms.add(new Object());
 371             view.setPermissions(perms);
 372             throw new RuntimeException("ClassCastException not thrown");
 373         }  catch (ClassCastException x) {
 374         }
 375 
 376         System.out.println("OKAY");
 377     }
 378 
 379     public static void main(String[] args) throws IOException {
 380         Path dir = TestUtil.createTemporaryDirectory();
 381         try {
 382             if (!Files.getFileStore(dir).supportsFileAttributeView("posix")) {
 383                 System.out.println("PosixFileAttributeView not supported");
 384                 return;
 385             }
 386 
 387             permissionTests(dir);
 388             createTests(dir);
 389             ownerTests(dir);
 390             lookupPrincipalTests(dir);
 391             exceptionsTests(dir);
 392 
 393         } finally {
 394             TestUtil.removeAll(dir);
 395         }
 396     }
 397 }