1 /* 2 * Copyright (c) 2018, 2019 SAP SE. 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 SAP SE, Dietmar-Hopp-Allee 16, 69190 Walldorf, Germany 20 * or visit www.sap.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.io.IOException; 25 import java.nio.file.CopyOption; 26 import java.nio.file.DirectoryStream; 27 import java.nio.file.FileSystem; 28 import java.nio.file.FileVisitResult; 29 import java.nio.file.Files; 30 import java.nio.file.Path; 31 import java.nio.file.Paths; 32 import java.nio.file.SimpleFileVisitor; 33 import java.nio.file.StandardCopyOption; 34 import java.nio.file.attribute.BasicFileAttributes; 35 import java.nio.file.attribute.GroupPrincipal; 36 import java.nio.file.attribute.PosixFileAttributeView; 37 import java.nio.file.attribute.PosixFileAttributes; 38 import java.nio.file.attribute.PosixFilePermission; 39 import java.nio.file.attribute.PosixFilePermissions; 40 import java.nio.file.attribute.UserPrincipal; 41 import java.nio.file.spi.FileSystemProvider; 42 import java.security.AccessController; 43 import java.security.PrivilegedAction; 44 import java.util.Collections; 45 import java.util.HashMap; 46 import java.util.Map; 47 import java.util.Set; 48 import java.util.concurrent.atomic.AtomicInteger; 49 50 import org.testng.annotations.Test; 51 52 import static java.nio.file.attribute.PosixFilePermission.GROUP_EXECUTE; 53 import static java.nio.file.attribute.PosixFilePermission.GROUP_READ; 54 import static java.nio.file.attribute.PosixFilePermission.GROUP_WRITE; 55 import static java.nio.file.attribute.PosixFilePermission.OTHERS_EXECUTE; 56 import static java.nio.file.attribute.PosixFilePermission.OTHERS_READ; 57 import static java.nio.file.attribute.PosixFilePermission.OTHERS_WRITE; 58 import static java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE; 59 import static java.nio.file.attribute.PosixFilePermission.OWNER_READ; 60 import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE; 61 import static org.testng.Assert.assertEquals; 62 import static org.testng.Assert.assertNotNull; 63 import static org.testng.Assert.assertNull; 64 import static org.testng.Assert.assertTrue; 65 import static org.testng.Assert.fail; 66 67 /** 68 * @test 69 * @bug 8213031 70 * @modules jdk.zipfs 71 * @run testng TestPosix 72 * @run testng/othervm/java.security.policy=test.policy TestPosix 73 * @summary Test POSIX zip file operations. 74 */ 75 public class TestPosix { 76 // files and directories 77 private static final Path ZIP_FILE = Paths.get("testPosix.zip"); 78 private static final Path ZIP_FILE_COPY = Paths.get("testPosixCopy.zip"); 79 private static final Path UNZIP_DIR = Paths.get("unzip/"); 80 81 // permission sets 82 private static final Set<PosixFilePermission> ALLPERMS = 83 PosixFilePermissions.fromString("rwxrwxrwx"); 84 private static final Set<PosixFilePermission> EMPTYPERMS = 85 Collections.<PosixFilePermission>emptySet(); 86 private static final Set<PosixFilePermission> UR = Set.of(OWNER_READ); 87 private static final Set<PosixFilePermission> UW = Set.of(OWNER_WRITE); 88 private static final Set<PosixFilePermission> UE = Set.of(OWNER_EXECUTE); 89 private static final Set<PosixFilePermission> GR = Set.of(GROUP_READ); 90 private static final Set<PosixFilePermission> GW = Set.of(GROUP_WRITE); 91 private static final Set<PosixFilePermission> GE = Set.of(GROUP_EXECUTE); 92 private static final Set<PosixFilePermission> OR = Set.of(OTHERS_READ); 93 private static final Set<PosixFilePermission> OW = Set.of(OTHERS_WRITE); 94 private static final Set<PosixFilePermission> OE = Set.of(OTHERS_EXECUTE); 95 96 // principals 97 private static final UserPrincipal DUMMY_USER = ()->"defusr"; 98 private static final GroupPrincipal DUMMY_GROUP = ()->"defgrp"; 99 100 // FS open options 101 private static final Map<String, Object> ENV_DEFAULT = Collections.<String, Object>emptyMap(); 102 private static final Map<String, Object> ENV_POSIX = Map.of("enablePosixFileAttributes", true); 103 104 // misc 105 private static final FileSystemProvider zipFSP; 106 private static final CopyOption[] COPY_ATTRIBUTES = {StandardCopyOption.COPY_ATTRIBUTES}; 107 private static final Map<String, ZipFileEntryInfo> ENTRIES = new HashMap<>(); 108 109 private int entriesCreated; 110 111 static enum checkExpects { 112 contentOnly, 113 noPermDataInZip, 114 permsInZip, 115 permsPosix 116 } 117 118 static class ZipFileEntryInfo { 119 // permissions to set initially 120 private final Set<PosixFilePermission> intialPerms; 121 // permissions to set in a later call 122 private final Set<PosixFilePermission> laterPerms; 123 // permissions that should be effective in the zip file 124 private final Set<PosixFilePermission> permsInZip; 125 // permissions that should be returned by zipfs w/Posix support 126 private final Set<PosixFilePermission> permsPosix; 127 // entry is a directory 128 private final boolean isDir; 129 // need additional read flag in copy test 130 private final boolean setReadFlag; 131 132 private ZipFileEntryInfo(Set<PosixFilePermission> initialPerms, Set<PosixFilePermission> laterPerms, 133 Set<PosixFilePermission> permsInZip, Set<PosixFilePermission> permsZipPosix, boolean isDir, boolean setReadFlag) 134 { 135 this.intialPerms = initialPerms; 136 this.laterPerms = laterPerms; 137 this.permsInZip = permsInZip; 138 this.permsPosix = permsZipPosix; 139 this.isDir = isDir; 140 this.setReadFlag = setReadFlag; 141 } 142 } 143 144 static class CopyVisitor extends SimpleFileVisitor<Path> { 145 private Path from, to; 146 private boolean copyPerms; 147 148 CopyVisitor(Path from, Path to) { 149 this.from = from; 150 this.to = to; 151 } 152 153 CopyVisitor(Path from, Path to, boolean copyPerms) { 154 this.from = from; 155 this.to = to; 156 this.copyPerms = copyPerms; 157 } 158 159 @Override 160 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { 161 FileVisitResult rc = super.preVisitDirectory(dir, attrs); 162 Path target = to.resolve(from.relativize(dir).toString()); 163 if (!Files.exists(target)) { 164 Files.copy(dir, target, COPY_ATTRIBUTES); 165 if (copyPerms) { 166 Files.setPosixFilePermissions(target, Files.getPosixFilePermissions(dir)); 167 } 168 } 169 return rc; 170 } 171 172 @Override 173 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 174 FileVisitResult rc = super.visitFile(file, attrs); 175 Path target = to.resolve(from.relativize(file).toString()); 176 Files.copy(file, target, COPY_ATTRIBUTES); 177 if (copyPerms) { 178 Files.setPosixFilePermissions(target, Files.getPosixFilePermissions(file)); 179 } 180 return rc; 181 } 182 } 183 184 static class DeleteVisitor extends SimpleFileVisitor<Path> { 185 @Override 186 public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { 187 FileVisitResult rc = super.postVisitDirectory(dir, exc); 188 Files.delete(dir); 189 return rc; 190 } 191 192 @Override 193 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 194 FileVisitResult rc = super.visitFile(file, attrs); 195 Files.delete(file); 196 return rc; 197 } 198 } 199 200 @FunctionalInterface 201 static interface Executor { 202 void doIt() throws IOException; 203 } 204 205 static { 206 zipFSP = getZipFSProvider(); 207 assertNotNull(zipFSP, "ZIP filesystem provider is not installed"); 208 ENTRIES.put("dir", new ZipFileEntryInfo(ALLPERMS, null, ALLPERMS, ALLPERMS, true, false)); 209 ENTRIES.put("uread", new ZipFileEntryInfo(UR, null, UR, UR, false, false)); 210 ENTRIES.put("uwrite", new ZipFileEntryInfo(UW, null, UW, UW, false, true)); 211 ENTRIES.put("uexec", new ZipFileEntryInfo(UE, null, UE, UE, false, true)); 212 ENTRIES.put("gread", new ZipFileEntryInfo(GR, null, GR, GR, false, true)); 213 ENTRIES.put("gwrite", new ZipFileEntryInfo(GW, null, GW, GW, false, true)); 214 ENTRIES.put("gexec", new ZipFileEntryInfo(GE, null, GE, GE, false, true)); 215 ENTRIES.put("oread", new ZipFileEntryInfo(OR, null, OR, OR, false, true)); 216 ENTRIES.put("owrite", new ZipFileEntryInfo(OW, null, OW, OW, false, true)); 217 ENTRIES.put("oexec", new ZipFileEntryInfo(OE, null, OE, OE, false, true)); 218 ENTRIES.put("emptyperms", new ZipFileEntryInfo(EMPTYPERMS, null, EMPTYPERMS, EMPTYPERMS, false, true)); 219 ENTRIES.put("noperms", new ZipFileEntryInfo(null, null, null, ALLPERMS, false, false)); 220 ENTRIES.put("permslater", new ZipFileEntryInfo(null, UR, UR, UR, false, false)); 221 } 222 223 private static String expectedDefaultOwner(Path zf) { 224 try { 225 return Files.getOwner(zf).getName(); 226 } catch (Exception e) { 227 // if we can't get the owner of the file, we fall back to system property user.name 228 } 229 try { 230 return AccessController.doPrivileged( 231 (PrivilegedAction<String>)()->System.getProperty("user.name")); 232 } catch (Exception e) { 233 // then we fall back to a generic default string 234 } 235 return "<zipfs_default>"; 236 } 237 238 private static FileSystemProvider getZipFSProvider() { 239 for (FileSystemProvider provider : FileSystemProvider.installedProviders()) { 240 if ("jar".equals(provider.getScheme())) 241 return provider; 242 } 243 return null; 244 } 245 246 private void putEntry(FileSystem fs, String name, ZipFileEntryInfo entry) throws IOException { 247 if (entry.isDir) { 248 if (entry.intialPerms == null) { 249 Files.createDirectory(fs.getPath(name)); 250 } else { 251 Files.createDirectory(fs.getPath(name), PosixFilePermissions.asFileAttribute(entry.intialPerms)); 252 } 253 254 } else { 255 if (entry.intialPerms == null) { 256 Files.createFile(fs.getPath(name)); 257 } else { 258 Files.createFile(fs.getPath(name), PosixFilePermissions.asFileAttribute(entry.intialPerms)); 259 } 260 } 261 if (entry.laterPerms != null) { 262 Files.setAttribute(fs.getPath(name), "zip:storedPermissions", entry.laterPerms); 263 } 264 entriesCreated++; 265 } 266 267 private FileSystem createTestZipFile(Path zpath, Map<String, Object> env) throws IOException { 268 if (Files.exists(zpath)) { 269 System.out.println("Deleting old " + zpath + "..."); 270 Files.delete(zpath); 271 } 272 System.out.println("Creating " + zpath + "..."); 273 entriesCreated = 0; 274 var opts = new HashMap<String, Object>(); 275 opts.putAll(env); 276 opts.put("create", true); 277 FileSystem fs = zipFSP.newFileSystem(zpath, opts); 278 for (String name : ENTRIES.keySet()) { 279 putEntry(fs, name, ENTRIES.get(name)); 280 } 281 return fs; 282 } 283 284 private FileSystem createEmptyZipFile(Path zpath, Map<String, Object> env) throws IOException { 285 if (Files.exists(zpath)) { 286 System.out.println("Deleting old " + zpath + "..."); 287 Files.delete(zpath); 288 } 289 System.out.println("Creating " + zpath + "..."); 290 var opts = new HashMap<String, Object>(); 291 opts.putAll(env); 292 opts.put("create", true); 293 return zipFSP.newFileSystem(zpath, opts); 294 } 295 296 private void delTree(Path p) throws IOException { 297 if (Files.exists(p)) { 298 Files.walkFileTree(p, new DeleteVisitor()); 299 } 300 } 301 302 private void addOwnerRead(Path root) throws IOException { 303 for (String name : ENTRIES.keySet()) { 304 ZipFileEntryInfo ei = ENTRIES.get(name); 305 if (!ei.setReadFlag) { 306 continue; 307 } 308 Path setReadOn = root.resolve(name); 309 Set<PosixFilePermission> perms = Files.getPosixFilePermissions(setReadOn); 310 perms.add(OWNER_READ); 311 Files.setPosixFilePermissions(setReadOn, perms); 312 } 313 } 314 315 private void removeOwnerRead(Path root) throws IOException { 316 for (String name : ENTRIES.keySet()) { 317 ZipFileEntryInfo ei = ENTRIES.get(name); 318 if (!ei.setReadFlag) { 319 continue; 320 } 321 Path removeReadFrom = root.resolve(name); 322 Set<PosixFilePermission> perms = Files.getPosixFilePermissions(removeReadFrom); 323 perms.remove(OWNER_READ); 324 Files.setPosixFilePermissions(removeReadFrom, perms); 325 } 326 } 327 328 @SuppressWarnings("unchecked") 329 private void checkEntry(Path file, checkExpects expected) { 330 System.out.println("Checking " + file + "..."); 331 String name = file.getFileName().toString(); 332 ZipFileEntryInfo ei = ENTRIES.get(name); 333 assertNotNull(ei, "Found unknown entry " + name + "."); 334 BasicFileAttributes attrs = null; 335 if (expected == checkExpects.permsPosix) { 336 try { 337 attrs = Files.readAttributes(file, PosixFileAttributes.class); 338 } catch (IOException e) { 339 e.printStackTrace(); 340 fail("Caught IOException reading file attributes (posix) for " + name + ": " + e.getMessage()); 341 } 342 } else { 343 try { 344 attrs = Files.readAttributes(file, BasicFileAttributes.class); 345 } catch (IOException e) { 346 e.printStackTrace(); 347 fail("Caught IOException reading file attributes (basic) " + name + ": " + e.getMessage()); 348 } 349 } 350 assertEquals(Files.isDirectory(file), ei.isDir, "Unexpected directory attribute for:" + System.lineSeparator() + attrs); 351 352 if (expected == checkExpects.contentOnly) { 353 return; 354 } 355 356 Set<PosixFilePermission> permissions; 357 if (expected == checkExpects.permsPosix) { 358 try { 359 permissions = Files.getPosixFilePermissions(file); 360 } catch (IOException e) { 361 e.printStackTrace(); 362 fail("Caught IOException getting permission attribute for:" + System.lineSeparator() + attrs); 363 return; 364 } 365 comparePermissions(ei.permsPosix, permissions); 366 } else if (expected == checkExpects.permsInZip || expected == checkExpects.noPermDataInZip) { 367 try { 368 permissions = (Set<PosixFilePermission>)Files.getAttribute(file, "zip:storedPermissions"); 369 } catch (IOException e) { 370 e.printStackTrace(); 371 fail("Caught IOException getting permission attribute for:" + System.lineSeparator() + attrs); 372 return; 373 } 374 comparePermissions(expected == checkExpects.noPermDataInZip ? null : ei.permsInZip, permissions); 375 } 376 } 377 378 private void doCheckEntries(Path path, checkExpects expected) throws IOException { 379 AtomicInteger entries = new AtomicInteger(); 380 381 try (DirectoryStream<Path> paths = Files.newDirectoryStream(path)) { 382 paths.forEach(file -> { 383 entries.getAndIncrement(); 384 checkEntry(file, expected); 385 }); 386 } 387 System.out.println("Number of entries: " + entries.get() + "."); 388 assertEquals(entries.get(), entriesCreated, "File contained wrong number of entries."); 389 } 390 391 private void checkEntries(FileSystem fs, checkExpects expected) throws IOException { 392 System.out.println("Checking permissions on file system " + fs + "..."); 393 doCheckEntries(fs.getPath("/"), expected); 394 } 395 396 private void checkEntries(Path path, checkExpects expected) throws IOException { 397 System.out.println("Checking permissions on path " + path + "..."); 398 doCheckEntries(path, expected); 399 } 400 401 private boolean throwsUOE(Executor e) throws IOException { 402 try { 403 e.doIt(); 404 return false; 405 } catch (UnsupportedOperationException exc) { 406 return true; 407 } 408 } 409 410 private void comparePermissions(Set<PosixFilePermission> expected, Set<PosixFilePermission> actual) { 411 if (expected == null) { 412 assertNull(actual, "Permissions are not null"); 413 } else { 414 assertNotNull(actual, "Permissions are null."); 415 assertEquals(actual.size(), expected.size(), "Unexpected number of permissions (" + 416 actual.size() + " received vs " + expected.size() + " expected)."); 417 for (PosixFilePermission p : expected) { 418 assertTrue(actual.contains(p), "Posix permission " + p + " missing."); 419 } 420 } 421 } 422 423 /** 424 * This tests whether the entries in a zip file created w/o 425 * Posix support are correct. 426 * 427 * @throws IOException 428 */ 429 @Test 430 public void testDefault() throws IOException { 431 // create zip file using zipfs with default options 432 createTestZipFile(ZIP_FILE, ENV_DEFAULT).close(); 433 // check entries on zipfs with default options 434 try (FileSystem zip = zipFSP.newFileSystem(ZIP_FILE, ENV_DEFAULT)) { 435 checkEntries(zip, checkExpects.permsInZip); 436 } 437 // check entries on zipfs with posix options 438 try (FileSystem zip = zipFSP.newFileSystem(ZIP_FILE, ENV_POSIX)) { 439 checkEntries(zip, checkExpects.permsPosix); 440 } 441 } 442 443 /** 444 * This tests whether the entries in a zip file created w/ 445 * Posix support are correct. 446 * 447 * @throws IOException 448 */ 449 @Test 450 public void testPosix() throws IOException { 451 // create zip file using zipfs with posix option 452 createTestZipFile(ZIP_FILE, ENV_POSIX).close(); 453 // check entries on zipfs with default options 454 try (FileSystem zip = zipFSP.newFileSystem(ZIP_FILE, ENV_DEFAULT)) { 455 checkEntries(zip, checkExpects.permsInZip); 456 } 457 // check entries on zipfs with posix options 458 try (FileSystem zip = zipFSP.newFileSystem(ZIP_FILE, ENV_POSIX)) { 459 checkEntries(zip, checkExpects.permsPosix); 460 } 461 } 462 463 /** 464 * This tests whether the entries in a zip file copied from another 465 * are correct. 466 * 467 * @throws IOException 468 */ 469 @Test 470 public void testCopy() throws IOException { 471 // copy zip to zip with default options 472 try (FileSystem zipIn = createTestZipFile(ZIP_FILE, ENV_DEFAULT); 473 FileSystem zipOut = createEmptyZipFile(ZIP_FILE_COPY, ENV_DEFAULT)) { 474 Path from = zipIn.getPath("/"); 475 Files.walkFileTree(from, new CopyVisitor(from, zipOut.getPath("/"))); 476 } 477 // check entries on copied zipfs with default options 478 try (FileSystem zip = zipFSP.newFileSystem(ZIP_FILE_COPY, ENV_DEFAULT)) { 479 checkEntries(zip, checkExpects.permsInZip); 480 } 481 // check entries on copied zipfs with posix options 482 try (FileSystem zip = zipFSP.newFileSystem(ZIP_FILE_COPY, ENV_POSIX)) { 483 checkEntries(zip, checkExpects.permsPosix); 484 } 485 } 486 487 /** 488 * This tests whether the entries of a zip file look correct after extraction 489 * and re-packing. When not using zipfs with Posix support, we expect the 490 * effective permissions in the resulting zip file to be empty. 491 * 492 * @throws IOException 493 */ 494 @Test 495 public void testUnzipDefault() throws IOException { 496 delTree(UNZIP_DIR); 497 Files.createDirectory(UNZIP_DIR); 498 499 try (FileSystem srcZip = createTestZipFile(ZIP_FILE, ENV_DEFAULT)) { 500 Path from = srcZip.getPath("/"); 501 Files.walkFileTree(from, new CopyVisitor(from, UNZIP_DIR)); 502 } 503 504 // we just check that the entries got extracted to file system 505 checkEntries(UNZIP_DIR, checkExpects.contentOnly); 506 507 // the target zip file is opened with Posix support 508 // but we expect no permission data to be copied using the default copy method 509 try (FileSystem tgtZip = createEmptyZipFile(ZIP_FILE_COPY, ENV_POSIX)) { 510 Files.walkFileTree(UNZIP_DIR, new CopyVisitor(UNZIP_DIR, tgtZip.getPath("/"))); 511 } 512 513 // check entries on copied zipfs - no permission data should exist 514 try (FileSystem zip = zipFSP.newFileSystem(ZIP_FILE_COPY, ENV_DEFAULT)) { 515 checkEntries(zip, checkExpects.noPermDataInZip); 516 } 517 } 518 519 /** 520 * This tests whether the entries of a zip file look correct after extraction 521 * and re-packing. If the default file system supports Posix, we test whether we 522 * correctly carry the Posix permissions. Otherwise there's not much to test in 523 * this method. 524 * 525 * @throws IOException 526 */ 527 @Test 528 public void testUnzipPosix() throws IOException { 529 delTree(UNZIP_DIR); 530 Files.createDirectory(UNZIP_DIR); 531 532 try { 533 Files.getPosixFilePermissions(UNZIP_DIR); 534 } catch (Exception e) { 535 // if we run into any exception here, be it because of the fact that the file system 536 // is not Posix or if we have insufficient security permissions, we can't do this test. 537 System.out.println("This can't be tested here because of " + e); 538 return; 539 } 540 541 try (FileSystem srcZip = createTestZipFile(ZIP_FILE, ENV_POSIX)) { 542 Path from = srcZip.getPath("/"); 543 // copy permissions as well 544 Files.walkFileTree(from, new CopyVisitor(from, UNZIP_DIR, true)); 545 } 546 547 // permissions should have been propagated to file system 548 checkEntries(UNZIP_DIR, checkExpects.permsPosix); 549 550 try (FileSystem tgtZip = createEmptyZipFile(ZIP_FILE_COPY, ENV_POSIX)) { 551 // Make some files owner readable to be able to copy them into the zipfs 552 addOwnerRead(UNZIP_DIR); 553 554 // copy permissions as well 555 Files.walkFileTree(UNZIP_DIR, new CopyVisitor(UNZIP_DIR, tgtZip.getPath("/"), true)); 556 557 // Fix back all the files in the target zip file which have been made readable before 558 removeOwnerRead(tgtZip.getPath("/")); 559 } 560 561 // check entries on copied zipfs - permission data should have been propagated 562 try (FileSystem zip = zipFSP.newFileSystem(ZIP_FILE_COPY, ENV_POSIX)) { 563 checkEntries(zip, checkExpects.permsPosix); 564 } 565 } 566 567 /** 568 * Tests POSIX default behavior. 569 * 570 * @throws IOException 571 */ 572 @Test 573 public void testPosixDefaults() throws IOException { 574 // test with posix = false, expect UnsupportedOperationException 575 try (FileSystem zipIn = createTestZipFile(ZIP_FILE, ENV_DEFAULT)) { 576 var entry = zipIn.getPath("/dir"); 577 assertTrue(throwsUOE(()->Files.getPosixFilePermissions(entry))); 578 assertTrue(throwsUOE(()->Files.setPosixFilePermissions(entry, UW))); 579 assertTrue(throwsUOE(()->Files.getOwner(entry))); 580 assertTrue(throwsUOE(()->Files.setOwner(entry, DUMMY_USER))); 581 assertTrue(throwsUOE(()->Files.getFileAttributeView(entry, PosixFileAttributeView.class))); 582 } 583 584 // test with posix = true -> default values 585 try (FileSystem zipIn = zipFSP.newFileSystem(ZIP_FILE, ENV_POSIX)) { 586 String defaultOwner = expectedDefaultOwner(ZIP_FILE); 587 var entry = zipIn.getPath("/noperms"); 588 comparePermissions(ALLPERMS, Files.getPosixFilePermissions(entry)); 589 var owner = Files.getOwner(entry); 590 assertNotNull(owner, "owner should not be null"); 591 assertEquals(owner.getName(), defaultOwner); 592 Files.setOwner(entry, DUMMY_USER); 593 assertEquals(Files.getOwner(entry), DUMMY_USER); 594 var view = Files.getFileAttributeView(entry, PosixFileAttributeView.class); 595 var group = view.readAttributes().group(); 596 assertNotNull(group, "group must not be null"); 597 assertEquals(group.getName(), defaultOwner); 598 view.setGroup(DUMMY_GROUP); 599 assertEquals(view.readAttributes().group(), DUMMY_GROUP); 600 entry = zipIn.getPath("/uexec"); 601 Files.setPosixFilePermissions(entry, GR); // will be persisted 602 comparePermissions(GR, Files.getPosixFilePermissions(entry)); 603 } 604 605 // test with posix = true + custom defaults of type String 606 try (FileSystem zipIn = zipFSP.newFileSystem(ZIP_FILE, Map.of("enablePosixFileAttributes", true, 607 "defaultOwner", "auser", "defaultGroup", "agroup", "defaultPermissions", "r--------"))) 608 { 609 var entry = zipIn.getPath("/noperms"); 610 comparePermissions(UR, Files.getPosixFilePermissions(entry)); 611 assertEquals(Files.getOwner(entry).getName(), "auser"); 612 var view = Files.getFileAttributeView(entry, PosixFileAttributeView.class); 613 assertEquals(view.readAttributes().group().getName(), "agroup"); 614 // check if the change to permissions of /uexec was persisted 615 comparePermissions(GR, Files.getPosixFilePermissions(zipIn.getPath("/uexec"))); 616 } 617 618 // test with posix = true + custom defaults as Objects 619 try (FileSystem zipIn = zipFSP.newFileSystem(ZIP_FILE, Map.of("enablePosixFileAttributes", true, 620 "defaultOwner", DUMMY_USER, "defaultGroup", DUMMY_GROUP, "defaultPermissions", UR))) 621 { 622 var entry = zipIn.getPath("/noperms"); 623 comparePermissions(UR, Files.getPosixFilePermissions(entry)); 624 assertEquals(Files.getOwner(entry), DUMMY_USER); 625 var view = Files.getFileAttributeView(entry, PosixFileAttributeView.class); 626 assertEquals(view.readAttributes().group(), DUMMY_GROUP); 627 } 628 } 629 }