diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..9765dbd --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,66 @@ +name: Build + +on: + [push] + +jobs: + build: + name: Build and Test + runs-on: ubuntu-latest + #This check is case insensitive + if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')" + outputs: + # Get from step "setversion" + artifact-version: ${{ steps.setversion.outputs.version }} + env: + BUILD_VERSION: SNAPSHOT + # Name of the project; used in multiple steps (e.g. for upload) + PROJECT_NAME: fuse-nio-adapter + steps: + # Foreign Action: Checkout the current commit + - uses: actions/checkout@v2 + # Foreign Action: Setup Java Runtime Environment + - uses: actions/setup-java@v1 + with: + java-version: 11 + server-id: bintray-jcenter + server-username: BINTRAY_USERNAME # Defined in step "deploytojcenter" + server-password: BINTRAY_API_KEY # See above + - uses: actions/cache@v1 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + - name: Ensure to use tagged version + id: taggedVersion + run: mvn versions:set --file ./pom.xml -DnewVersion=${GITHUB_REF##*/} + if: startsWith(github.ref, 'refs/tags/') # Run if ref is tagged (e.g. "v.1.4") + - name: Export the project version to the job environment and fix it as an ouput of this step + id: setVersion # Output used above (outputs.artifact-version) + run: | + v=$(mvn help:evaluate "-Dexpression=project.version" -q -DforceStdout) + echo "BUILD_VERSION=${v}" >> $GITHUB_ENV + echo "::set-output name=version::${v}" + - name: Build and Test + id: buildAndTest + run: mvn -B clean install jacoco:report -Pcoverage,dependency-check + - name: Upload code coverage report + id: codacyCoverageReporter + run: bash <(curl -Ls https://coverage.codacy.com/get.sh) + env: + CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }} + continue-on-error: true + - name: Upload snapshot artifact ${{ env.PROJECT_NAME }}-${{ env.BUILD_VERSION }}.jar + id: uploadSnapshot + uses: actions/upload-artifact@v2 + with: + name: ${{ env.PROJECT_NAME }}-${{ env.BUILD_VERSION }}.jar + path: target/${{ env.PROJECT_NAME }}-*.jar + - name: Deploy to jcenter + id: deployToJcenter + run: mvn -B deploy -Prelease -DskipTests + if: startsWith(github.ref, 'refs/tags/') # Run if ref is tagged (e.g. "v.1.4") + env: + BINTRAY_USERNAME: cryptobot + BINTRAY_API_KEY: ${{ secrets.BINTRAY_API_KEY }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b0818aa..0000000 --- a/.travis.yml +++ /dev/null @@ -1,28 +0,0 @@ -language: java -sudo: false -jdk: -- openjdk11 -env: - global: - - secure: "SvqhJ7cFF4Uir0rvngiZAsxhgYAFCdw1bVHfKtA2MAV5taAuGsN0Uij+kLUP0oxHmrKwbSoOlHmTOG6m6GYOmX9ALAgfVRI41vnZxzhhR6zdHq4Kx84rhIxGHAXhxY8GPJiN+ClyeEr/qf6Jb60XyydU7w1wO8a1y+AYSW/CK0HZ4qORVgHOmfMmP7sCmgaPwCCcNoq/5mW873XHbJUbVh4d0wNn6Pej9oKRgsShWCqb/ihQ4IqNQjSQO+nF9FAuqMVzFJhnoNempuHG6R98QUlHXZ4IERlYfWfwjg6OtXk369QMAbQQ3k8bheozgM7R1mRq/cfIyIWzqY29UjqGVChy918QvXLDpLtVeU8ThF5cPgsle8K2NdaHZutfYXFo7qVosIAAMwkory5WN+RX7W2DqXAFwZjn5SfHvPMTz3tFgvAfVkV3qQg/bdOI6vA1cLghd/ZPRiCoJVJ/EdxwDor/FH5wRW2XFPIkqSWjlv4TnAd8YoAUZ44iO0DyUgyrB6oVdNYhW+0ei0M181rkSLdg5yfDykQF324lIwMwoalDMK4LcTxcgFVdyLSZr0xVtJr9vmr3w2xoJfB18hufHKkqMZQ+kDlhAmAjZApmrAIRR22gqhJJNctTEbX4O2s2BbD93TuKhBQMMDYzfoM8s62NCQ3qUbPtQUECW5HbF+k=" # CODACY_PROJECT_TOKEN - - secure: "JrrO+ToZ5UPkT95mNnzX9XmunVO3zIc8s6c7MMDFpBciA/hyaYmK1R4vsyCudiZtuu7VvSmK31YRoxphwWfAD+eEsvjWMMgT0MDz3eOMkI+0/XrFf2Lh9cJ4Ow0OfHvu3w51FGAuf59ZCuA6KlYhJEThRXf8Sp31ecuZRu0CWHDRfXp5+tyARu7Ly0XScy/DNnjSbKOeKKZ28PH6/ZxIptWMk5GLQtnaUCesv4Z3Lg31WsPGkqlDPyXH4P4TF9ttOKpk6Nw4rTzgprOe30ULlT7AuQRQ1KFbHBJe8vKD0mCIPlfir0yr1fFjX8S+wwEDVuCnLRiNUH+HWLOkcUlAlE+Oif0a7bjHNcQH0Y26aLQoOMhzR8lAj0HTk0fIDXXA9JGVOdDetGxHkjxY87Op4gh54WO3HheNO4Tw7RoBGdKy1qSa9bafKr2aGeQrACCMKqZxj0ZepdmfPIuo1uiYPFec3/hXeMMx2a0Qaj5wRrtYvWgrp8UVgT2MJ1L16/dsc77xv815CSoco83Z4cEhILOTAXrQxCzc5B6h725NpfLkoBJSjjbW1JQplWohbYYUvQfwLRIuvlH5ickCpwWNofgXsZBOViXeea6zaJwhezgfUfOR3sXEblQS65gFIOOUcz+BOL2ZYpjmPZ3h7ZPOPM8nXVc1M/zlwCb2BIeD3L0=" # BINTRAY_API_KEY -install: -- curl -o $HOME/.m2/settings.xml https://gist.githubusercontent.com/cryptobot/cf5fbd909c4782aaeeeb7c7f4a1a43da/raw/fb3fe9a6db00cdac09788285b108a3645193a45b/settings.xml -- mvn dependency:go-offline -Pdependency-check,coverage,release -script: -- mvn clean test jacoco:report verify -Dsurefire.useFile=false -Pcoverage -after_success: -- curl -o ~/codacy-coverage-reporter.jar https://repo.maven.apache.org/maven2/com/codacy/codacy-coverage-reporter/7.1.0/codacy-coverage-reporter-7.1.0-assembly.jar -- $JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar report -l Java -r target/site/jacoco/jacoco.xml -cache: - directories: - - $HOME/.m2 -deploy: -- provider: script # RELEASES - script: mvn clean versions:set -DnewVersion=${TRAVIS_TAG} deploy -DskipTests -Prelease - skip_cleanup: true - on: - repo: cryptomator/fuse-nio-adapter - tags: true -after_deploy: - - "echo '{\"close\": \"1\"}' | curl --max-time 10 -X POST -u cryptobot:${BINTRAY_API_KEY} https://api.bintray.com/maven_central_sync/cryptomator/maven/fuse-nio-adapter/versions/${TRAVIS_TAG}" diff --git a/pom.xml b/pom.xml index 0cf3059..0553f4c 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.cryptomator fuse-nio-adapter - 1.2.5 + 1.2.6 FUSE-NIO-Adapter Access resources at a given NIO path via FUSE. https://github.com/cryptomator/fuse-nio-adapter @@ -15,9 +15,11 @@ + 11 + 0.5.4 2.27 - 29.0-jre + 30.0-jre 1.7.30 5.6.2 @@ -125,7 +127,6 @@ maven-compiler-plugin 3.8.1 - 9 true @@ -151,7 +152,7 @@ org.owasp dependency-check-maven - 5.3.2 + 6.0.2 24 0 diff --git a/src/main/java/org/cryptomator/frontend/fuse/locks/LockManager.java b/src/main/java/org/cryptomator/frontend/fuse/locks/LockManager.java index be739e8..853960c 100644 --- a/src/main/java/org/cryptomator/frontend/fuse/locks/LockManager.java +++ b/src/main/java/org/cryptomator/frontend/fuse/locks/LockManager.java @@ -1,5 +1,6 @@ package org.cryptomator.frontend.fuse.locks; +import com.google.common.base.Supplier; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @@ -50,10 +51,10 @@ public class LockManager { public LockManager() { CacheBuilder cacheBuilder = CacheBuilder.newBuilder().weakValues(); if (LOG.isDebugEnabled()) { - cacheBuilder.removalListener(this::onLockRemoval); + cacheBuilder.removalListener(this::removedReadWriteLock); } - this.pathLocks = cacheBuilder.build(new LockLoader()); - this.dataLocks = cacheBuilder.build(new LockLoader()); + this.pathLocks = cacheBuilder.build(CacheLoader.from(this::createReadWriteLock)); + this.dataLocks = cacheBuilder.build(CacheLoader.from(this::createReadWriteLock)); } public PathLockBuilder createPathLock(String path) { @@ -73,17 +74,13 @@ private PathLockBuilder createPathLock(List pathComponents) { return new PathLockBuilderImpl(pathComponents, Optional.ofNullable(parentLockBuilder), lock, dataLocks::getUnchecked); } - private void onLockRemoval(RemovalNotification notification) { - LOG.trace("Deleting ReadWriteLock for {}", notification.getKey()); + private ReadWriteLock createReadWriteLock(List key) { + LOG.trace("Creating ReadWriteLock for {}", key); + return new ReentrantReadWriteLock(); } - private static class LockLoader extends CacheLoader, ReadWriteLock> { - - @Override - public ReadWriteLock load(List key) { - LOG.trace("Creating ReadWriteLock for {}", key); - return new ReentrantReadWriteLock(); - } + private void removedReadWriteLock(RemovalNotification, ReentrantReadWriteLock> notification) { + LOG.trace("Deleting ReadWriteLock for {}", notification.getKey()); } /* diff --git a/src/main/java/org/cryptomator/frontend/fuse/mount/AbstractMount.java b/src/main/java/org/cryptomator/frontend/fuse/mount/AbstractMount.java index 3717bbb..bb7d890 100644 --- a/src/main/java/org/cryptomator/frontend/fuse/mount/AbstractMount.java +++ b/src/main/java/org/cryptomator/frontend/fuse/mount/AbstractMount.java @@ -3,7 +3,7 @@ import com.google.common.base.Preconditions; import org.cryptomator.frontend.fuse.FuseNioAdapter; -import java.awt.*; +import java.awt.Desktop; import java.io.IOException; import java.nio.file.Path; @@ -26,9 +26,9 @@ public Path getMountPoint() { @Override public void revealInFileManager() throws CommandFailedException { - if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.OPEN)) { try { - Desktop.getDesktop().browse(mountPoint.toUri()); + Desktop.getDesktop().open(mountPoint.toFile()); } catch (IOException e) { throw new CommandFailedException(e); } diff --git a/src/main/java/org/cryptomator/frontend/fuse/mount/MacMounter.java b/src/main/java/org/cryptomator/frontend/fuse/mount/MacMounter.java index edf0d26..564400b 100644 --- a/src/main/java/org/cryptomator/frontend/fuse/mount/MacMounter.java +++ b/src/main/java/org/cryptomator/frontend/fuse/mount/MacMounter.java @@ -74,7 +74,8 @@ public String[] defaultMountFlags() { */ @Override public boolean isApplicable() { - return IS_MAC && Files.exists(Paths.get("/usr/local/lib/libosxfuse.2.dylib")) && installedVersionSupported(); + return IS_MAC && Files.exists(Paths.get("/usr/local/lib/libosxfuse.2.dylib")); // +// && installedVersionSupported(); // FIXME: #52 } public boolean installedVersionSupported() { diff --git a/src/test/java/org/cryptomator/frontend/fuse/locks/LockManagerTest.java b/src/test/java/org/cryptomator/frontend/fuse/locks/LockManagerTest.java index c9b2ccc..634f3cf 100644 --- a/src/test/java/org/cryptomator/frontend/fuse/locks/LockManagerTest.java +++ b/src/test/java/org/cryptomator/frontend/fuse/locks/LockManagerTest.java @@ -1,7 +1,6 @@ package org.cryptomator.frontend.fuse.locks; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -9,13 +8,15 @@ import org.slf4j.LoggerFactory; import java.time.Duration; +import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; -@Disabled //TODO: https://travis-ci.org/github/cryptomator/fuse-nio-adapter/builds/735702459 public class LockManagerTest { static { @@ -70,31 +71,26 @@ public void testMultipleReadLocks() { LockManager lockManager = new LockManager(); int numThreads = 8; ExecutorService threadPool = Executors.newFixedThreadPool(numThreads); + CyclicBarrier ready = new CyclicBarrier(8); CountDownLatch done = new CountDownLatch(numThreads); - AtomicInteger counter = new AtomicInteger(); - AtomicInteger maxCounter = new AtomicInteger(); for (int i = 0; i < numThreads; i++) { int threadnum = i; threadPool.submit(() -> { try (PathLock lock = lockManager.createPathLock("/foo/bar/baz").forReading()) { LOG.trace("ENTER thread {}", threadnum); - counter.incrementAndGet(); - Thread.sleep(200); - maxCounter.set(Math.max(counter.get(), maxCounter.get())); - counter.decrementAndGet(); + ready.await(); + done.countDown(); LOG.trace("LEAVE thread {}", threadnum); - } catch (InterruptedException e) { + } catch (InterruptedException | BrokenBarrierException e) { LOG.error("thread interrupted", e); } - done.countDown(); }); } Assertions.assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { // deadlock protection done.await(); }); - Assertions.assertEquals(numThreads, maxCounter.get()); } @Test @@ -104,18 +100,20 @@ public void testMultipleWriteLocks() { int numThreads = 8; ExecutorService threadPool = Executors.newFixedThreadPool(numThreads); CountDownLatch done = new CountDownLatch(numThreads); - AtomicInteger counter = new AtomicInteger(); - AtomicInteger maxCounter = new AtomicInteger(); + AtomicBoolean occupied = new AtomicBoolean(false); + AtomicBoolean success = new AtomicBoolean(true); for (int i = 0; i < numThreads; i++) { int threadnum = i; threadPool.submit(() -> { try (PathLock lock = lockManager.createPathLock("/foo/bar/baz").forWriting()) { LOG.trace("ENTER thread {}", threadnum); - counter.incrementAndGet(); - Thread.sleep(10); - maxCounter.set(Math.max(counter.get(), maxCounter.get())); - counter.decrementAndGet(); + boolean wasFree = occupied.compareAndSet(false, true); + Thread.sleep(50); // give other threads the chance to reach this point + if (!wasFree) { + success.set(false); + } + occupied.set(false); LOG.trace("LEAVE thread {}", threadnum); } catch (InterruptedException e) { LOG.error("thread interrupted", e); @@ -127,7 +125,7 @@ public void testMultipleWriteLocks() { Assertions.assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { // deadlock protection done.await(); }); - Assertions.assertEquals(1, maxCounter.get()); + Assertions.assertTrue(success.get()); } @Test @@ -203,13 +201,12 @@ class DataLockTests { @Test @DisplayName("read locks are shared") - public void testMultipleReadLocks() throws InterruptedException { + public void testMultipleReadLocks() { LockManager lockManager = new LockManager(); int numThreads = 8; ExecutorService threadPool = Executors.newFixedThreadPool(numThreads); + CyclicBarrier ready = new CyclicBarrier(8); CountDownLatch done = new CountDownLatch(numThreads); - AtomicInteger counter = new AtomicInteger(); - AtomicInteger maxCounter = new AtomicInteger(); for (int i = 0; i < numThreads; i++) { int threadnum = i; @@ -217,33 +214,29 @@ public void testMultipleReadLocks() throws InterruptedException { try (PathLock pathLock = lockManager.createPathLock("/foo/bar/baz").forReading(); // DataLock dataLock = pathLock.lockDataForReading()) { LOG.trace("ENTER thread {}", threadnum); - counter.incrementAndGet(); - Thread.sleep(50); - maxCounter.set(Math.max(counter.get(), maxCounter.get())); - counter.decrementAndGet(); + ready.await(); + done.countDown(); LOG.trace("LEAVE thread {}", threadnum); - } catch (InterruptedException e) { + } catch (InterruptedException | BrokenBarrierException e) { LOG.error("thread interrupted", e); } - done.countDown(); }); } Assertions.assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { // deadlock protection done.await(); }); - Assertions.assertEquals(numThreads, maxCounter.get()); } @Test @DisplayName("write locks are exclusive") - public void testMultipleWriteLocks() throws InterruptedException { + public void testMultipleWriteLocks() { LockManager lockManager = new LockManager(); int numThreads = 8; ExecutorService threadPool = Executors.newFixedThreadPool(numThreads); CountDownLatch done = new CountDownLatch(numThreads); - AtomicInteger counter = new AtomicInteger(); - AtomicInteger maxCounter = new AtomicInteger(); + AtomicBoolean occupied = new AtomicBoolean(false); + AtomicBoolean success = new AtomicBoolean(true); for (int i = 0; i < numThreads; i++) { int threadnum = i; @@ -251,10 +244,12 @@ public void testMultipleWriteLocks() throws InterruptedException { try (PathLock pathLock = lockManager.createPathLock("/foo/bar/baz").forReading(); // DataLock dataLock = pathLock.lockDataForWriting()) { LOG.trace("ENTER thread {}", threadnum); - counter.incrementAndGet(); - Thread.sleep(10); - maxCounter.set(Math.max(counter.get(), maxCounter.get())); - counter.decrementAndGet(); + boolean wasFree = occupied.compareAndSet(false, true); + Thread.sleep(50); // give other threads the chance to reach this point + if (!wasFree) { + success.set(false); + } + occupied.set(false); LOG.trace("LEAVE thread {}", threadnum); } catch (InterruptedException e) { LOG.error("thread interrupted", e); @@ -266,7 +261,7 @@ public void testMultipleWriteLocks() throws InterruptedException { Assertions.assertTimeoutPreemptively(Duration.ofSeconds(10), () -> { // deadlock protection done.await(); }); - Assertions.assertEquals(1, maxCounter.get()); + Assertions.assertTrue(success.get()); } } diff --git a/suppression.xml b/suppression.xml index cd8ad48..e855d9d 100644 --- a/suppression.xml +++ b/suppression.xml @@ -1,11 +1,44 @@ - - - com.github.serceman:jnr-fuse:0.5.1 - cpe:/a:fuse:fuse - cpe:/a:fuse_project:fuse - + + + + ^com\.github\.serceman:jnr-fuse:.*$ + + + + + + CVE-2010-3879 + + + + + + CVE-2011-0541 + + + + + + CVE-2011-0542 + + + + + + CVE-2011-0543 + + + + + + CVE-2015-3202 + + + + + + CVE-2018-10906 + \ No newline at end of file