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  * @run testng TestPosixPerms
  30  * @summary Test zip file operations handling posix permissions.
  31  */
  32 
  33 import static java.nio.file.attribute.PosixFilePermission.*;
  34 import static org.testng.Assert.assertEquals;
  35 import static org.testng.Assert.assertNotEquals;
  36 import static org.testng.Assert.assertTrue;
  37 import static org.testng.Assert.fail;
  38 
  39 import java.io.File;
  40 import java.io.FileOutputStream;
  41 import java.io.IOException;
  42 import java.nio.file.Files;
  43 import java.nio.file.Path;
  44 import java.nio.file.Paths;
  45 import java.nio.file.attribute.PosixFilePermission;
  46 import java.nio.file.attribute.PosixFilePermissions;
  47 import java.util.Collections;
  48 import java.util.Set;
  49 import java.util.zip.ZipEntry;
  50 import java.util.zip.ZipFile;
  51 import java.util.zip.ZipOutputStream;
  52 
  53 import org.testng.annotations.Test;
  54 
  55 public class TestPosixPerms {
  56     private static final int NUMBER_OF_ENTRIES_IN_POSIXTEST_ZIP = 10;
  57 
  58     private int entries;
  59 
  60     private static void checkPermissionsOfEntry(String name, ZipEntry ze, boolean directory, Set<PosixFilePermission> expected) {
  61         System.out.print("Checking " + name + "...");
  62         assertEquals(ze.isDirectory(), directory, "Unexpected directory attribute.");
  63         Set<PosixFilePermission> permissions = ze.getPosixPermissions().orElse(null);
  64         if (expected == null) {
  65             assertEquals(permissions, null, "Nonempty posix permissions associated with entry.");
  66             System.out.println();
  67         } else {
  68             assertNotEquals(permissions, null, "No posix permissions associated with entry.");
  69             System.out.println("[" + PosixFilePermissions.toString(permissions) + "]");
  70             assertEquals(permissions.size(), expected.size(), "Unexpected number of permissions.");
  71             for (PosixFilePermission p : expected) {
  72                 assertTrue(permissions.contains(p), "Posix permission " + p + " missing.");
  73             }
  74         }
  75     }
  76 
  77     private void putEntry(ZipOutputStream zos, String name, Set<PosixFilePermission> perms) throws IOException {
  78         ZipEntry e = new ZipEntry(name);
  79         if (perms != null) {
  80             e.setPosixPermissions(perms);
  81         }
  82         zos.putNextEntry(e);
  83         entries++;
  84     }
  85 
  86     @Test
  87     public void readCheckedInArchiveWithPosixPerms() throws Exception {
  88         File zipFile =
  89             new File(System.getProperty("test.src", "."), "posixtest.zip");
  90         System.out.println("Testing " + zipFile.getAbsolutePath() + "...");
  91         try (ZipFile zf = new ZipFile(zipFile)) {
  92             int size = zf.size();
  93             System.out.println("Number of entries: " + size + "...");
  94             assertEquals(size, NUMBER_OF_ENTRIES_IN_POSIXTEST_ZIP, "File contained wrong number of entries.");
  95             zf.stream().forEach((ze)->{
  96                 String name = ze.getName();
  97                 if (name.startsWith("dir")) {
  98                     checkPermissionsOfEntry(name, ze, true, Set.of(
  99                         OWNER_READ, OWNER_WRITE, OWNER_EXECUTE,
 100                         GROUP_READ, GROUP_WRITE, GROUP_EXECUTE,
 101                         OTHERS_READ, OTHERS_WRITE, OTHERS_EXECUTE));
 102                 } else if (name.equals("uread")) {
 103                     checkPermissionsOfEntry(name, ze, false, Set.of(OWNER_READ));
 104                 } else if (name.equals("uwrite")) {
 105                     checkPermissionsOfEntry(name, ze, false, Set.of(OWNER_WRITE));
 106                 } else if (name.equals("uexec")) {
 107                     checkPermissionsOfEntry(name, ze, false, Set.of(OWNER_EXECUTE));
 108                 } else if (name.equals("gread")) {
 109                     checkPermissionsOfEntry(name, ze, false, Set.of(GROUP_READ));
 110                 } else if (name.equals("gwrite")) {
 111                     checkPermissionsOfEntry(name, ze, false, Set.of(GROUP_WRITE));
 112                 } else if (name.equals("gexec")) {
 113                     checkPermissionsOfEntry(name, ze, false, Set.of(GROUP_EXECUTE));
 114                 } else if (name.equals("oread")) {
 115                     checkPermissionsOfEntry(name, ze, false, Set.of(OTHERS_READ));
 116                 } else if (name.equals("owrite")) {
 117                     checkPermissionsOfEntry(name, ze, false, Set.of(OTHERS_WRITE));
 118                 } else if (name.equals("oexec")) {
 119                     checkPermissionsOfEntry(name, ze, false, Set.of(OTHERS_EXECUTE));
 120                 } else {
 121                     fail("Found unknown entry " + name + ".");
 122                 }
 123             });
 124         }
 125     }
 126 
 127     @Test
 128     public void testWriteAndReadArchiveWithPosixPerms() throws Exception {
 129         File zfile = Paths.get(System.getProperty("test.dir", "."), "testPosixPerms.zip").toFile();
 130         System.out.println("Create " + zfile.getAbsolutePath() + "...");
 131         if (zfile.exists()) {
 132             zfile.delete();
 133         }
 134         ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zfile));
 135         entries = 0;
 136         putEntry(zos, "dir/", Set.of(
 137                  OWNER_READ, OWNER_WRITE, OWNER_EXECUTE,
 138                  GROUP_READ, GROUP_WRITE, GROUP_EXECUTE,
 139                  OTHERS_READ, OTHERS_WRITE, OTHERS_EXECUTE));
 140         putEntry(zos, "uread", Set.of(OWNER_READ));
 141         putEntry(zos, "uwrite", Set.of(OWNER_WRITE));
 142         putEntry(zos, "uexec", Set.of(OWNER_EXECUTE));
 143         putEntry(zos, "gread", Set.of(GROUP_READ));
 144         putEntry(zos, "gwrite", Set.of(GROUP_WRITE));
 145         putEntry(zos, "gexec", Set.of(GROUP_EXECUTE));
 146         putEntry(zos, "oread", Set.of(OTHERS_READ));
 147         putEntry(zos, "owrite", Set.of(OTHERS_WRITE));
 148         putEntry(zos, "oexec", Set.of(OTHERS_EXECUTE));
 149         putEntry(zos, "emptyperms", Collections.<PosixFilePermission>emptySet());
 150         putEntry(zos, "noperms", null);
 151         zos.close();
 152 
 153         System.out.println("Test reading " + zfile.getAbsolutePath() + "...");
 154         try (ZipFile zf = new ZipFile(zfile)) {
 155             int size = zf.size();
 156             System.out.println("Number of entries: " + size + "...");
 157             assertEquals(size, entries, "File contained wrong number of entries.");
 158             zf.stream().forEach((ze)->{
 159                 String name = ze.getName();
 160                 if (name.startsWith("dir")) {
 161                     checkPermissionsOfEntry(name, ze, true, Set.of(
 162                         OWNER_READ, OWNER_WRITE, OWNER_EXECUTE,
 163                         GROUP_READ, GROUP_WRITE, GROUP_EXECUTE,
 164                         OTHERS_READ, OTHERS_WRITE, OTHERS_EXECUTE));
 165                 } else if (name.equals("uread")) {
 166                     checkPermissionsOfEntry(name, ze, false, Set.of(OWNER_READ));
 167                 } else if (name.equals("uwrite")) {
 168                     checkPermissionsOfEntry(name, ze, false, Set.of(OWNER_WRITE));
 169                 } else if (name.equals("uexec")) {
 170                     checkPermissionsOfEntry(name, ze, false, Set.of(OWNER_EXECUTE));
 171                 } else if (name.equals("gread")) {
 172                     checkPermissionsOfEntry(name, ze, false, Set.of(GROUP_READ));
 173                 } else if (name.equals("gwrite")) {
 174                     checkPermissionsOfEntry(name, ze, false, Set.of(GROUP_WRITE));
 175                 } else if (name.equals("gexec")) {
 176                     checkPermissionsOfEntry(name, ze, false, Set.of(GROUP_EXECUTE));
 177                 } else if (name.equals("oread")) {
 178                     checkPermissionsOfEntry(name, ze, false, Set.of(OTHERS_READ));
 179                 } else if (name.equals("owrite")) {
 180                     checkPermissionsOfEntry(name, ze, false, Set.of(OTHERS_WRITE));
 181                 } else if (name.equals("oexec")) {
 182                     checkPermissionsOfEntry(name, ze, false, Set.of(OTHERS_EXECUTE));
 183                 } else if (name.equals("emptyperms")) {
 184                     checkPermissionsOfEntry(name, ze, false, Collections.<PosixFilePermission>emptySet());
 185                 } else if (name.equals("noperms")) {
 186                     checkPermissionsOfEntry(name, ze, false, null);
 187                 } else {
 188                     fail("Found unknown entry " + name + ".");
 189                 }
 190             });
 191         }
 192     }
 193 }