/* * Copyright (c) 2019, 2022, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
staticclass ZipFileEntryInfo { // permissions to set initially privatefinal Set<PosixFilePermission> intialPerms; // permissions to set in a later call privatefinal Set<PosixFilePermission> laterPerms; // permissions that should be effective in the zip file privatefinal Set<PosixFilePermission> permsInZip; // permissions that should be returned by zipfs w/Posix support privatefinal Set<PosixFilePermission> permsPosix; // entry is a directory privatefinalboolean isDir; // need additional read flag in copy test privatefinalboolean setReadFlag;
static {
ENTRIES.put("dir", new ZipFileEntryInfo(ALLPERMS, null, ALLPERMS, ALLPERMS, true, false));
ENTRIES.put("uread", new ZipFileEntryInfo(UR, null, UR, UR, false, false));
ENTRIES.put("uwrite", new ZipFileEntryInfo(UW, null, UW, UW, false, true));
ENTRIES.put("uexec", new ZipFileEntryInfo(UE, null, UE, UE, false, true));
ENTRIES.put("gread", new ZipFileEntryInfo(GR, null, GR, GR, false, true));
ENTRIES.put("gwrite", new ZipFileEntryInfo(GW, null, GW, GW, false, true));
ENTRIES.put("gexec", new ZipFileEntryInfo(GE, null, GE, GE, false, true));
ENTRIES.put("oread", new ZipFileEntryInfo(OR, null, OR, OR, false, true));
ENTRIES.put("owrite", new ZipFileEntryInfo(OW, null, OW, OW, false, true));
ENTRIES.put("oexec", new ZipFileEntryInfo(OE, null, OE, OE, false, true));
ENTRIES.put("emptyperms", new ZipFileEntryInfo(EMPTYPERMS, null, EMPTYPERMS, EMPTYPERMS, false, true));
ENTRIES.put("noperms", new ZipFileEntryInfo(null, null, null, ALLPERMS, false, false));
ENTRIES.put("permslater", new ZipFileEntryInfo(null, UR, UR, UR, false, false));
}
privatestatic String expectedDefaultOwner(Path zf) { try { try {
PrivilegedExceptionAction<String> pa = ()->Files.getOwner(zf).getName(); return AccessController.doPrivileged(pa);
} catch (UnsupportedOperationException e) { // if we can't get the owner of the file, we fall back to system property user.name
PrivilegedAction<String> pa = ()->System.getProperty("user.name"); return AccessController.doPrivileged(pa);
}
} catch (PrivilegedActionException | SecurityException e) {
System.out.println("Caught " + e.getClass().getName() + "(" + e.getMessage() + ") when running a privileged operation to get the default owner."); returnnull;
}
}
privatestatic String expectedDefaultGroup(Path zf, String defaultOwner) { try { try {
PosixFileAttributeView zfpv = Files.getFileAttributeView(zf, PosixFileAttributeView.class); if (zfpv == null) { return defaultOwner;
}
PrivilegedExceptionAction<String> pa = ()->zfpv.readAttributes().group().getName(); return AccessController.doPrivileged(pa);
} catch (UnsupportedOperationException e) { return defaultOwner;
}
} catch (PrivilegedActionException | SecurityException e) {
System.out.println("Caught an exception when running a privileged operation to get the default group.");
e.printStackTrace(); returnnull;
}
}
privatevoid comparePermissions(Set<PosixFilePermission> expected, Set<PosixFilePermission> actual) { if (expected == null) {
assertNull(actual, "Permissions are not null");
} else {
assertNotNull(actual, "Permissions are null.");
assertEquals(actual.size(), expected.size(), "Unexpected number of permissions (" +
actual.size() + " received vs " + expected.size() + " expected)."); for (PosixFilePermission p : expected) {
assertTrue(actual.contains(p), "Posix permission " + p + " missing.");
}
}
}
/** * This tests whether the entries in a zip file created w/o * Posix support are correct. * * @throws IOException
*/
@Test publicvoid testDefault() throws IOException { // create zip file using zipfs with default options
createTestZipFile(ZIP_FILE, ENV_DEFAULT).close(); // check entries on zipfs with default options try (FileSystem zip = FileSystems.newFileSystem(ZIP_FILE, ENV_DEFAULT)) {
checkEntries(zip, checkExpects.permsInZip);
} // check entries on zipfs with posix options try (FileSystem zip = FileSystems.newFileSystem(ZIP_FILE, ENV_POSIX)) {
checkEntries(zip, checkExpects.permsPosix);
}
}
/** * This tests whether the entries in a zip file created w/ * Posix support are correct. * * @throws IOException
*/
@Test publicvoid testPosix() throws IOException { // create zip file using zipfs with posix option
createTestZipFile(ZIP_FILE, ENV_POSIX).close(); // check entries on zipfs with default options try (FileSystem zip = FileSystems.newFileSystem(ZIP_FILE, ENV_DEFAULT)) {
checkEntries(zip, checkExpects.permsInZip);
} // check entries on zipfs with posix options try (FileSystem zip = FileSystems.newFileSystem(ZIP_FILE, ENV_POSIX)) {
checkEntries(zip, checkExpects.permsPosix);
}
}
/** * This tests whether the entries in a zip file copied from another * are correct. * * @throws IOException
*/
@Test publicvoid testCopy() throws IOException { // copy zip to zip with default options try (FileSystem zipIn = createTestZipFile(ZIP_FILE, ENV_DEFAULT);
FileSystem zipOut = createEmptyZipFile(ZIP_FILE_COPY, ENV_DEFAULT)) {
Path from = zipIn.getPath("/");
Files.walkFileTree(from, new CopyVisitor(from, zipOut.getPath("/")));
} // check entries on copied zipfs with default options try (FileSystem zip = FileSystems.newFileSystem(ZIP_FILE_COPY, ENV_DEFAULT)) {
checkEntries(zip, checkExpects.permsInZip);
} // check entries on copied zipfs with posix options try (FileSystem zip = FileSystems.newFileSystem(ZIP_FILE_COPY, ENV_POSIX)) {
checkEntries(zip, checkExpects.permsPosix);
}
}
/** * This tests whether the entries of a zip file look correct after extraction * and re-packing. When not using zipfs with Posix support, we expect the * effective permissions in the resulting zip file to be empty. * * @throws IOException
*/
@Test publicvoid testUnzipDefault() throws IOException {
delTree(UNZIP_DIR);
Files.createDirectory(UNZIP_DIR);
try (FileSystem srcZip = createTestZipFile(ZIP_FILE, ENV_DEFAULT)) {
Path from = srcZip.getPath("/");
Files.walkFileTree(from, new CopyVisitor(from, UNZIP_DIR));
}
// we just check that the entries got extracted to file system
checkEntries(UNZIP_DIR, checkExpects.contentOnly);
// the target zip file is opened with Posix support // but we expect no permission data to be copied using the default copy method try (FileSystem tgtZip = createEmptyZipFile(ZIP_FILE_COPY, ENV_POSIX)) {
Files.walkFileTree(UNZIP_DIR, new CopyVisitor(UNZIP_DIR, tgtZip.getPath("/")));
}
// check entries on copied zipfs - no permission data should exist if (System.getProperty("os.name").toLowerCase().contains("windows")) try (FileSystem zip = FileSystems.newFileSystem(ZIP_FILE_COPY,
ENV_DEFAULT)) {
checkEntries(zip, checkExpects.noPermDataInZip);
}
}
/** * This tests whether the entries of a zip file look correct after extraction * and re-packing. If the default file system supports Posix, we test whether we * correctly carry the Posix permissions. Otherwise there's not much to test in * this method. * * @throws IOException
*/
@Test publicvoid testUnzipPosix() throws IOException {
delTree(UNZIP_DIR);
Files.createDirectory(UNZIP_DIR);
try {
Files.getPosixFilePermissions(UNZIP_DIR);
} catch (Exception e) { // if we run into any exception here, be it because of the fact that the file system // is not Posix or if we have insufficient security permissions, we can't do this test.
System.out.println("This can't be tested here because of " + e); return;
}
try (FileSystem srcZip = createTestZipFile(ZIP_FILE, ENV_POSIX)) {
Path from = srcZip.getPath("/"); // copy permissions as well
Files.walkFileTree(from, new CopyVisitor(from, UNZIP_DIR, true));
}
// permissions should have been propagated to file system
checkEntries(UNZIP_DIR, checkExpects.permsPosix);
try (FileSystem tgtZip = createEmptyZipFile(ZIP_FILE_COPY, ENV_POSIX)) { // Make some files owner readable to be able to copy them into the zipfs
addOwnerRead(UNZIP_DIR);
// copy permissions as well
Files.walkFileTree(UNZIP_DIR, new CopyVisitor(UNZIP_DIR, tgtZip.getPath("/"), true));
// Fix back all the files in the target zip file which have been made readable before
removeOwnerRead(tgtZip.getPath("/"));
}
// check entries on copied zipfs - permission data should have been propagated try (FileSystem zip = FileSystems.newFileSystem(ZIP_FILE_COPY, ENV_POSIX)) {
checkEntries(zip, checkExpects.permsPosix);
}
}
// test with posix = true -> default values try (FileSystem zipIn = FileSystems.newFileSystem(ZIP_FILE, ENV_POSIX)) {
String defaultOwner = expectedDefaultOwner(ZIP_FILE);
String defaultGroup = expectedDefaultGroup(ZIP_FILE, defaultOwner); var entry = zipIn.getPath("/noperms");
comparePermissions(ALLPERMS, Files.getPosixFilePermissions(entry)); var owner = Files.getOwner(entry);
assertNotNull(owner, "owner should not be null"); if (defaultOwner != null) {
assertEquals(owner.getName(), defaultOwner);
}
Files.setOwner(entry, DUMMY_USER);
assertEquals(Files.getOwner(entry), DUMMY_USER); var view = Files.getFileAttributeView(entry, PosixFileAttributeView.class); var group = view.readAttributes().group();
assertNotNull(group, "group must not be null"); if (defaultGroup != null) {
assertEquals(group.getName(), defaultGroup);
}
view.setGroup(DUMMY_GROUP);
assertEquals(view.readAttributes().group(), DUMMY_GROUP);
entry = zipIn.getPath("/uexec");
Files.setPosixFilePermissions(entry, GR); // will be persisted
comparePermissions(GR, Files.getPosixFilePermissions(entry));
}
// test with posix = true + custom defaults of type String try (FileSystem zipIn = FileSystems.newFileSystem(ZIP_FILE, Map.of("enablePosixFileAttributes", true, "defaultOwner", "auser", "defaultGroup", "agroup", "defaultPermissions", "r--------")))
{ var entry = zipIn.getPath("/noperms");
comparePermissions(UR, Files.getPosixFilePermissions(entry));
assertEquals(Files.getOwner(entry).getName(), "auser"); var view = Files.getFileAttributeView(entry, PosixFileAttributeView.class);
assertEquals(view.readAttributes().group().getName(), "agroup"); // check if the change to permissions of /uexec was persisted
comparePermissions(GR, Files.getPosixFilePermissions(zipIn.getPath("/uexec")));
}
// test with posix = true + custom defaults as Objects try (FileSystem zipIn = FileSystems.newFileSystem(ZIP_FILE, Map.of("enablePosixFileAttributes", true, "defaultOwner", DUMMY_USER, "defaultGroup", DUMMY_GROUP, "defaultPermissions", UR)))
{ var entry = zipIn.getPath("/noperms");
comparePermissions(UR, Files.getPosixFilePermissions(entry));
assertEquals(Files.getOwner(entry), DUMMY_USER); var view = Files.getFileAttributeView(entry, PosixFileAttributeView.class);
assertEquals(view.readAttributes().group(), DUMMY_GROUP);
}
}
/** * Sanity check to test whether the zip file can be unzipped with the java.util.zip API. * * @throws IOException
*/
@Test publicvoid testUnzipWithJavaUtilZip() throws IOException {
createTestZipFile(ZIP_FILE, ENV_DEFAULT).close();
delTree(UNZIP_DIR);
Files.createDirectory(UNZIP_DIR);
File targetDir = UNZIP_DIR.toFile(); try (ZipFile zf = new ZipFile(ZIP_FILE.toFile())) {
Enumeration<? extends ZipEntry> zenum = zf.entries(); while (zenum.hasMoreElements()) {
ZipEntry ze = zenum.nextElement();
File target = new File(targetDir + File.separator + ze.getName()); if (ze.isDirectory()) {
target.mkdir(); continue;
} try (InputStream is = zf.getInputStream(ze);
FileOutputStream fos = new FileOutputStream(target))
{ while (is.available() > 0) {
fos.write(is.read());
}
}
}
}
}
/** * Sanity check to test whether a jar file created with zipfs can be * extracted with the java.util.jar API. * * @throws IOException
*/
@Test publicvoid testJarFile() throws IOException { // create jar file using zipfs with default options
createTestZipFile(JAR_FILE, ENV_DEFAULT).close();
// extract it using java.util.jar.JarFile
delTree(UNZIP_DIR);
Files.createDirectory(UNZIP_DIR);
File targetDir = UNZIP_DIR.toFile(); try (JarFile jf = new JarFile(ZIP_FILE.toFile())) {
Enumeration<? extends JarEntry> zenum = jf.entries(); while (zenum.hasMoreElements()) {
JarEntry ze = zenum.nextElement();
File target = new File(targetDir + File.separator + ze.getName()); if (ze.isDirectory()) {
target.mkdir(); continue;
} try (InputStream is = jf.getInputStream(ze);
FileOutputStream fos = new FileOutputStream(target))
{ while (is.available() > 0) {
fos.write(is.read());
}
}
}
}
// extract it using the jar tool
delTree(UNZIP_DIR);
System.out.println("jar xvf " + JAR_FILE);
// the run method catches IOExceptions, we need to expose them int rc = JAR_TOOL.run(System.out, System.err, "xvf", JAR_FILE.toString());
assertEquals(rc, 0, "Return code of jar call is " + rc + " but expected 0");
}
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.3 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.