1 /*
   2  * Copyright (c) 2018, SAP SE. All rights reserved.
   3  *
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.  Oracle designates this
   9  * particular file as subject to the "Classpath" exception as provided
  10  * by Oracle in the LICENSE file that accompanied this code.
  11  *
  12  * This code is distributed in the hope that it will be useful, but WITHOUT
  13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15  * version 2 for more details (a copy is included in the LICENSE file that
  16  * accompanied this code).
  17  *
  18  * You should have received a copy of the GNU General Public License version
  19  * 2 along with this work; if not, write to the Free Software Foundation,
  20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  21  *
  22  * Please contact SAP SE, Dietmar-Hopp-Allee 16, 69190 Walldorf, Germany
  23  * or visit www.sap.com if you need additional information or have any
  24  * questions.
  25  */
  26 
  27 /**
  28  * @test
  29  * @modules jdk.zipfs
  30  * @run testng TestPosixPerms
  31  * @summary Test zip file operations handling posix permissions.
  32  */
  33 
  34 import static java.nio.file.attribute.PosixFilePermission.*;
  35 import static org.testng.Assert.assertEquals;
  36 import static org.testng.Assert.assertNotEquals;
  37 import static org.testng.Assert.assertNotNull;
  38 import static org.testng.Assert.assertTrue;
  39 import static org.testng.Assert.fail;
  40 
  41 import java.io.IOException;
  42 import java.nio.file.DirectoryStream;
  43 import java.nio.file.FileSystem;
  44 import java.nio.file.Files;
  45 import java.nio.file.Path;
  46 import java.nio.file.Paths;
  47 import java.nio.file.attribute.PosixFileAttributes;
  48 import java.nio.file.attribute.PosixFilePermission;
  49 import java.nio.file.attribute.PosixFilePermissions;
  50 import java.nio.file.spi.FileSystemProvider;
  51 import java.util.Collections;
  52 import java.util.HashMap;
  53 import java.util.Map;
  54 import java.util.Set;
  55 
  56 import org.testng.annotations.Test;
  57 
  58 public class TestPosixPerms {
  59 
  60     private int entries;
  61 
  62     private static FileSystemProvider getZipFSProvider() {
  63         for (FileSystemProvider provider : FileSystemProvider.installedProviders()) {
  64             if ("jar".equals(provider.getScheme()))
  65                 return provider;
  66         }
  67         return null;
  68     }
  69 
  70     private void checkPermissionsOfEntry(Path file, boolean directory, Set<PosixFilePermission> expected) {
  71         System.out.println("Checking " + file + "...");
  72         assertEquals(Files.isDirectory(file), directory, "Unexpected directory attribute.");
  73         try {
  74             System.out.println(Files.readAttributes(file, PosixFileAttributes.class).toString());
  75         } catch (IOException e) {
  76             fail("Failed to list file attributes (posix) for entry.", e);
  77         }
  78         try {
  79             Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(file);
  80             assertNotEquals(permissions, null, "No posix permissions associated with entry.");
  81             assertNotEquals(expected, null, "Got a set of " + permissions.size() +
  82                 " permissions but expected null/UnsupportedOperationException.");
  83             assertEquals(permissions.size(), expected.size(), "Unexpected number of permissions.");
  84             for (PosixFilePermission p : expected) {
  85                 assertTrue(permissions.contains(p), "Posix permission " + p + " missing.");
  86             }
  87         } catch (UnsupportedOperationException e) {
  88             if (expected != null) {
  89                 fail("Unexpected: No posix permissions associated with entry.");
  90             }
  91         } catch (IOException e) {
  92             fail("Caught unexpected exception obtaining posix file permissions.", e);
  93         }
  94     }
  95 
  96     private void putFile(FileSystem fs, String name, Set<PosixFilePermission> perms) throws IOException {
  97         if (perms == null) {
  98             Files.createFile(fs.getPath(name));
  99         } else {
 100             Files.createFile(fs.getPath(name), PosixFilePermissions.asFileAttribute(perms));
 101         }
 102         entries++;
 103     }
 104 
 105     private void putDirectory(FileSystem fs, String name, Set<PosixFilePermission> perms) throws IOException {
 106         if (perms == null) {
 107             Files.createDirectory(fs.getPath(name));
 108         } else {
 109             Files.createDirectory(fs.getPath(name), PosixFilePermissions.asFileAttribute(perms));
 110         }
 111         entries++;
 112     }
 113 
 114     @Test
 115     public void testWriteAndReadArchiveWithPosixPerms() throws Exception {
 116         FileSystemProvider provider = getZipFSProvider();
 117         assertNotNull(provider, "ZIP filesystem provider is not installed");
 118         Path zpath = Paths.get(System.getProperty("test.dir", "."), "testPosixPerms.zip");
 119         System.out.println("Create " + zpath + "...");
 120         if (Files.exists(zpath)) {
 121             Files.delete(zpath);
 122         }
 123         Map<String, Object> env = new HashMap<>();
 124         env.put("create", "true");
 125         try (FileSystem fs = provider.newFileSystem(zpath, env)) {
 126             entries = 0;
 127             putDirectory(fs, "dir", Set.of(
 128                 OWNER_READ, OWNER_WRITE, OWNER_EXECUTE,
 129                 GROUP_READ, GROUP_WRITE, GROUP_EXECUTE,
 130                 OTHERS_READ, OTHERS_WRITE, OTHERS_EXECUTE));
 131             putFile(fs, "uread", Set.of(OWNER_READ));
 132             putFile(fs, "uwrite", Set.of(OWNER_WRITE));
 133             putFile(fs, "uexec", Set.of(OWNER_EXECUTE));
 134             putFile(fs, "gread", Set.of(GROUP_READ));
 135             putFile(fs, "gwrite", Set.of(GROUP_WRITE));
 136             putFile(fs, "gexec", Set.of(GROUP_EXECUTE));
 137             putFile(fs, "oread", Set.of(OTHERS_READ));
 138             putFile(fs, "owrite", Set.of(OTHERS_WRITE));
 139             putFile(fs, "oexec", Set.of(OTHERS_EXECUTE));
 140             putFile(fs, "emptyperms", Collections.<PosixFilePermission>emptySet());
 141             putFile(fs, "noperms", null);
 142             putFile(fs, "permsaddedlater", null);
 143             Files.setPosixFilePermissions(fs.getPath("permsaddedlater"), Set.of(OWNER_READ));
 144         }
 145         int entriesCreated = entries;
 146 
 147         System.out.println("Test reading " + zpath + "...");
 148         env.clear();
 149         try (FileSystem fs = provider.newFileSystem(zpath, env)) {
 150             entries = 0;
 151             try (DirectoryStream<Path> paths = Files.newDirectoryStream(fs.getPath("/"))) {
 152                 paths.forEach(file->{
 153                     entries++;
 154                     String name = file.getFileName().toString();
 155                     if (name.startsWith("dir")) {
 156                         checkPermissionsOfEntry(file, true, Set.of(
 157                             OWNER_READ, OWNER_WRITE, OWNER_EXECUTE,
 158                             GROUP_READ, GROUP_WRITE, GROUP_EXECUTE,
 159                             OTHERS_READ, OTHERS_WRITE, OTHERS_EXECUTE));
 160                     } else if (name.equals("uread")) {
 161                         checkPermissionsOfEntry(file, false, Set.of(OWNER_READ));
 162                     } else if (name.equals("uwrite")) {
 163                         checkPermissionsOfEntry(file, false, Set.of(OWNER_WRITE));
 164                     } else if (name.equals("uexec")) {
 165                         checkPermissionsOfEntry(file, false, Set.of(OWNER_EXECUTE));
 166                     } else if (name.equals("gread")) {
 167                         checkPermissionsOfEntry(file, false, Set.of(GROUP_READ));
 168                     } else if (name.equals("gwrite")) {
 169                         checkPermissionsOfEntry(file, false, Set.of(GROUP_WRITE));
 170                     } else if (name.equals("gexec")) {
 171                         checkPermissionsOfEntry(file, false, Set.of(GROUP_EXECUTE));
 172                     } else if (name.equals("oread")) {
 173                         checkPermissionsOfEntry(file, false, Set.of(OTHERS_READ));
 174                     } else if (name.equals("owrite")) {
 175                         checkPermissionsOfEntry(file, false, Set.of(OTHERS_WRITE));
 176                     } else if (name.equals("oexec")) {
 177                         checkPermissionsOfEntry(file, false, Set.of(OTHERS_EXECUTE));
 178                     } else if (name.equals("emptyperms")) {
 179                         checkPermissionsOfEntry(file, false, Collections.<PosixFilePermission>emptySet());
 180                     } else if (name.equals("noperms")) {
 181                         checkPermissionsOfEntry(file, false, null);
 182                     } else if (name.equals("permsaddedlater")) {
 183                         checkPermissionsOfEntry(file, false, Set.of(OWNER_READ));
 184                     } else {
 185                         fail("Found unknown entry " + name + ".");
 186                     }
 187                 });
 188             }
 189         }
 190         System.out.println("Number of entries: " + entries + ".");
 191         assertEquals(entries, entriesCreated, "File contained wrong number of entries.");
 192     }
 193 }