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 static final int NUMBER_OF_ENTRIES_IN_POSIXTEST_ZIP = 10;
  61 
  62     private int entries;
  63 
  64     private static FileSystemProvider getZipFSProvider() {
  65         for (FileSystemProvider provider : FileSystemProvider.installedProviders()) {
  66             if ("jar".equals(provider.getScheme()))
  67                 return provider;
  68         }
  69         return null;
  70     }
  71 
  72     private void checkPermissionsOfEntry(Path file, boolean directory, Set<PosixFilePermission> expected) {
  73         System.out.println("Checking " + file + "...");
  74         assertEquals(Files.isDirectory(file), directory, "Unexpected directory attribute.");
  75         try {
  76             System.out.println(Files.readAttributes(file, PosixFileAttributes.class).toString());
  77         } catch (IOException e) {
  78             fail("Failed to list file attributes (posix) for entry.", e);
  79         }
  80         try {
  81             Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(file);
  82             assertNotEquals(permissions, null, "No posix permissions associated with entry.");
  83             assertNotEquals(expected, null, "Got a set of " + permissions.size() +
  84                 " permissions but expected null/UnsupportedOperationException.");
  85             assertEquals(permissions.size(), expected.size(), "Unexpected number of permissions.");
  86             for (PosixFilePermission p : expected) {
  87                 assertTrue(permissions.contains(p), "Posix permission " + p + " missing.");
  88             }
  89         } catch (UnsupportedOperationException e) {
  90             if (expected != null) {
  91                 fail("Unexpected: No posix permissions associated with entry.");
  92             }
  93         } catch (IOException e) {
  94             fail("Caught unexpected exception obtaining posix file permissions.", e);
  95         }
  96     }
  97 
  98     private void putFile(FileSystem fs, String name, Set<PosixFilePermission> perms) throws IOException {
  99         if (perms == null) {
 100             Files.createFile(fs.getPath(name));
 101         } else {
 102             Files.createFile(fs.getPath(name), PosixFilePermissions.asFileAttribute(perms));
 103         }
 104         entries++;
 105     }
 106 
 107     private void putDirectory(FileSystem fs, String name, Set<PosixFilePermission> perms) throws IOException {
 108         if (perms == null) {
 109             Files.createDirectory(fs.getPath(name));
 110         } else {
 111             Files.createDirectory(fs.getPath(name), PosixFilePermissions.asFileAttribute(perms));
 112         }
 113         entries++;
 114     }
 115 
 116     @Test
 117     public void readCheckedInArchiveWithPosixPerms() throws Exception {
 118         FileSystemProvider provider = getZipFSProvider();
 119         assertNotNull(provider, "ZIP filesystem provider is not installed");
 120         try (FileSystem fs = provider.newFileSystem(Paths.get(System.getProperty("test.src", "."), "posixtest.zip"),
 121                                                     Collections.<String, Object>emptyMap())) {
 122             System.out.println("Testing " + fs + "...");
 123             entries = 0;
 124             try (DirectoryStream<Path> paths = Files.newDirectoryStream(fs.getPath("/"))) {
 125                 paths.forEach((file)->{
 126                     entries++;
 127                     String name = file.getFileName().toString();
 128                     if (name.startsWith("dir")) {
 129                         checkPermissionsOfEntry(file, true, Set.of(
 130                             OWNER_READ, OWNER_WRITE, OWNER_EXECUTE,
 131                             GROUP_READ, GROUP_WRITE, GROUP_EXECUTE,
 132                             OTHERS_READ, OTHERS_WRITE, OTHERS_EXECUTE));
 133                     } else if (name.equals("uread")) {
 134                         checkPermissionsOfEntry(file, false, Set.of(OWNER_READ));
 135                     } else if (name.equals("uwrite")) {
 136                         checkPermissionsOfEntry(file, false, Set.of(OWNER_WRITE));
 137                     } else if (name.equals("uexec")) {
 138                         checkPermissionsOfEntry(file, false, Set.of(OWNER_EXECUTE));
 139                     } else if (name.equals("gread")) {
 140                         checkPermissionsOfEntry(file, false, Set.of(GROUP_READ));
 141                     } else if (name.equals("gwrite")) {
 142                         checkPermissionsOfEntry(file, false, Set.of(GROUP_WRITE));
 143                     } else if (name.equals("gexec")) {
 144                         checkPermissionsOfEntry(file, false, Set.of(GROUP_EXECUTE));
 145                     } else if (name.equals("oread")) {
 146                         checkPermissionsOfEntry(file, false, Set.of(OTHERS_READ));
 147                     } else if (name.equals("owrite")) {
 148                         checkPermissionsOfEntry(file, false, Set.of(OTHERS_WRITE));
 149                     } else if (name.equals("oexec")) {
 150                         checkPermissionsOfEntry(file, false, Set.of(OTHERS_EXECUTE));
 151                     } else {
 152                         fail("Found unknown entry " + name + ".");
 153                     }
 154                 });
 155             }
 156             System.out.println("Number of entries: " + entries + ".");
 157             assertEquals(entries, NUMBER_OF_ENTRIES_IN_POSIXTEST_ZIP, "File contained wrong number of entries.");
 158         }
 159     }
 160 
 161     @Test
 162     public void testWriteAndReadArchiveWithPosixPerms() throws Exception {
 163         FileSystemProvider provider = getZipFSProvider();
 164         assertNotNull(provider, "ZIP filesystem provider is not installed");
 165         Path zpath = Paths.get(System.getProperty("test.dir", "."), "testPosixPerms.zip");
 166         System.out.println("Create " + zpath + "...");
 167         if (Files.exists(zpath)) {
 168             Files.delete(zpath);
 169         }
 170         Map<String, Object> env = new HashMap<>();
 171         env.put("create", "true");
 172         try (FileSystem fs = provider.newFileSystem(zpath, env)) {
 173             entries = 0;
 174             putDirectory(fs, "dir", Set.of(
 175                 OWNER_READ, OWNER_WRITE, OWNER_EXECUTE,
 176                 GROUP_READ, GROUP_WRITE, GROUP_EXECUTE,
 177                 OTHERS_READ, OTHERS_WRITE, OTHERS_EXECUTE));
 178             putFile(fs, "uread", Set.of(OWNER_READ));
 179             putFile(fs, "uwrite", Set.of(OWNER_WRITE));
 180             putFile(fs, "uexec", Set.of(OWNER_EXECUTE));
 181             putFile(fs, "gread", Set.of(GROUP_READ));
 182             putFile(fs, "gwrite", Set.of(GROUP_WRITE));
 183             putFile(fs, "gexec", Set.of(GROUP_EXECUTE));
 184             putFile(fs, "oread", Set.of(OTHERS_READ));
 185             putFile(fs, "owrite", Set.of(OTHERS_WRITE));
 186             putFile(fs, "oexec", Set.of(OTHERS_EXECUTE));
 187             putFile(fs, "emptyperms", Collections.<PosixFilePermission>emptySet());
 188             putFile(fs, "noperms", null);
 189             putFile(fs, "permsaddedlater", null);
 190             Files.setPosixFilePermissions(fs.getPath("permsaddedlater"), Set.of(OWNER_READ));
 191         }
 192         int entriesCreated = entries;
 193 
 194         System.out.println("Test reading " + zpath + "...");
 195         env.clear();
 196         try (FileSystem fs = provider.newFileSystem(zpath, env)) {
 197             entries = 0;
 198             try (DirectoryStream<Path> paths = Files.newDirectoryStream(fs.getPath("/"))) {
 199                 paths.forEach((file)->{
 200                     entries++;
 201                     String name = file.getFileName().toString();
 202                     if (name.startsWith("dir")) {
 203                         checkPermissionsOfEntry(file, true, Set.of(
 204                             OWNER_READ, OWNER_WRITE, OWNER_EXECUTE,
 205                             GROUP_READ, GROUP_WRITE, GROUP_EXECUTE,
 206                             OTHERS_READ, OTHERS_WRITE, OTHERS_EXECUTE));
 207                     } else if (name.equals("uread")) {
 208                         checkPermissionsOfEntry(file, false, Set.of(OWNER_READ));
 209                     } else if (name.equals("uwrite")) {
 210                         checkPermissionsOfEntry(file, false, Set.of(OWNER_WRITE));
 211                     } else if (name.equals("uexec")) {
 212                         checkPermissionsOfEntry(file, false, Set.of(OWNER_EXECUTE));
 213                     } else if (name.equals("gread")) {
 214                         checkPermissionsOfEntry(file, false, Set.of(GROUP_READ));
 215                     } else if (name.equals("gwrite")) {
 216                         checkPermissionsOfEntry(file, false, Set.of(GROUP_WRITE));
 217                     } else if (name.equals("gexec")) {
 218                         checkPermissionsOfEntry(file, false, Set.of(GROUP_EXECUTE));
 219                     } else if (name.equals("oread")) {
 220                         checkPermissionsOfEntry(file, false, Set.of(OTHERS_READ));
 221                     } else if (name.equals("owrite")) {
 222                         checkPermissionsOfEntry(file, false, Set.of(OTHERS_WRITE));
 223                     } else if (name.equals("oexec")) {
 224                         checkPermissionsOfEntry(file, false, Set.of(OTHERS_EXECUTE));
 225                     } else if (name.equals("emptyperms")) {
 226                         checkPermissionsOfEntry(file, false, Collections.<PosixFilePermission>emptySet());
 227                     } else if (name.equals("noperms")) {
 228                         checkPermissionsOfEntry(file, false, null);
 229                     } else if (name.equals("permsaddedlater")) {
 230                         checkPermissionsOfEntry(file, false, Set.of(OWNER_READ));
 231                     } else {
 232                         fail("Found unknown entry " + name + ".");
 233                     }
 234                 });
 235             }
 236         }
 237         System.out.println("Number of entries: " + entries + ".");
 238         assertEquals(entries, entriesCreated, "File contained wrong number of entries.");
 239     }
 240 }