diff --git a/.github/workflows/dockerfiles/alpine b/.github/workflows/dockerfiles/alpine index 992a7f392..88770bab6 100644 --- a/.github/workflows/dockerfiles/alpine +++ b/.github/workflows/dockerfiles/alpine @@ -1,6 +1,7 @@ FROM alpine:3.14.0 -RUN apk add m4 g++ make pkgconf git tar xz gmp-dev re2-dev sqlite-dev fuse-dev ncurses-dev dash sqlite-static ncurses-static linux-headers jq +RUN apk add m4 g++ make pkgconf git tar xz gmp-dev re2-dev sqlite-dev fuse-dev ncurses-dev bash dash sqlite-static ncurses-static linux-headers jq + # Squashfuse build dependences RUN apk add fuse3-dev attr-dev zstd-dev lz4-dev xz-dev lzo-dev zlib-dev diff --git a/README.md b/README.md index 47ca2d205..295145ebd 100644 --- a/README.md +++ b/README.md @@ -57,13 +57,14 @@ or that your colleagues already built, you might appreciate wake. On Debian/Ubuntu (wheezy or later): - sudo apt-get install makedev fuse libfuse-dev libsqlite3-dev libgmp-dev libncurses5-dev pkg-config git g++ gcc libre2-dev dash + sudo apt-get install makedev fuse libfuse-dev libsqlite3-dev libgmp-dev libncurses5-dev pkg-config git g++ gcc libre2-dev dash fuse3 libfuse3-dev libattr1-dev libzstd-dev liblz4-dev liblzma-dev liblzo2-dev zlib1g-dev On Redhat (6.6 or later): sudo yum install epel-release epel-release centos-release-scl # On RHEL6: sudo yum install devtoolset-6-gcc devtoolset-6-gcc-c++ - sudo yum install makedev fuse fuse-devel sqlite-devel gmp-devel ncurses-devel pkgconfig git gcc gcc-c++ re2-devel dash + sudo yum install makedev fuse fuse-devel sqlite-devel gmp-devel ncurses-devel pkgconfig git gcc gcc-c++ re2-devel dash fuse3 fuse3-devel libattr-devel libzstd-devel lz4-devel xz-devel lzo-devel zlib-devel zstd lz4 xz lzo zlib + On FreeBSD (12 or later): @@ -75,7 +76,7 @@ On FreeBSD (12 or later): On Alpine Linux (3.14.0 or later): - apk add g++ make pkgconf git gmp-dev re2-dev sqlite-dev fuse-dev ncurses-dev dash + apk add m4 g++ make pkgconf git tar xz gmp-dev re2-dev sqlite-dev fuse-dev ncurses-dev bash dash sqlite-static ncurses-static linux-headers Alpine releases as old as 3.11.5 may work depending on the use case, but due to a limitation in older musl versions some jobs may be rebuilt unnecessarily. @@ -116,26 +117,34 @@ Give FUSE permission to run as stated in the instructions and you should be good ./bin/wake install $HOME/stuff # or wherever -| Name | Version | License | -| -------------------------------------------------------- | ------- | ------------- | -| **External dependencies** | | | -| [c++ 11](https://www.gnu.org/software/gcc/) | >= 4.7 | GPLv3 | -| [dash](http://gondor.apana.org.au/~herbert/dash/) | >= 0.5 | BSD 3-clause | -| [sqlite3-dev](https://www.sqlite.org/) | >= 3.6 | public domain | -| [libgmp-dev](https://gmplib.org) | >= 4.3 | LGPL v3 | -| [libfuse-dev](https://github.com/libfuse/libfuse) | >= 2.8 | LGPL v2.1 | -| [libre2-dev](https://github.com/google/re2) | >= 2013 | BSD 3-clause | -| [libncurses5-dev](https://www.gnu.org/software/ncurses/) | >= 5.7 | MIT | -| [m4](https://www.gnu.org/software/m4/) | >= 1.4 | GPLv3 | -| **Optional dependencies** | | | -| [re2c](http://re2c.org) | >= 1.0 | public domain | -| [utf8proc](https://juliastrings.github.io/utf8proc/) | >= 2.0 | MIT | -| **Internal dependencies** | | | -| [lemon](https://www.sqlite.org/lemon.html) | 2021-09 | public domain | -| [gopt](http://www.purposeful.co.uk/software/gopt/) | 10.0 | TFL | -| [SipHash](https://github.com/veorq/SipHash) | 2017-02 | CC0 | -| [BLAKE2](https://github.com/BLAKE2/libb2) | 2018-07 | CC0 | -| [whereami](https://github.com/gpakosz/whereami) | 2018-09 | WTFPLV2 | +| Name | Version | License | +| -------------------------------------------------------- | ------- | ------------- | +| **External dependencies** | | | +| [c++ 11](https://www.gnu.org/software/gcc/) | >= 4.7 | GPLv3 | +| [dash](http://gondor.apana.org.au/~herbert/dash/) | >= 0.5 | BSD 3-clause | +| [sqlite3-dev](https://www.sqlite.org/) | >= 3.6 | public domain | +| [libattr1-dev](https://savannah.nongnu.org/projects/attr)| >= 2.4.46 | GPLv2 | +| [libgmp-dev](https://gmplib.org) | >= 4.3 | LGPL v3 | +| [libfuse-dev](https://github.com/libfuse/libfuse) | >= 2.8 | LGPL v2.1 | +| [libfuse3-dev](https://github.com/libfuse/libfuse) | >= 2.8 | LGPL v2.1 | +| [libre2-dev](https://github.com/google/re2) | >= 2013 | BSD 3-clause | +| [libncurses5-dev](https://www.gnu.org/software/ncurses/) | >= 5.7 | MIT | +| [m4](https://www.gnu.org/software/m4/) | >= 1.4 | GPLv3 | +| [libzstd-dev](https://facebook.github.io/zstd/) | >= 1.5.5 | GPLv2+ and BSD | +| [liblz4-dev](https://lz4.github.io/lz4/) | >= 1.8.3 | GPLv2+ and BSD | +| [liblzma-dev/xz-devel](https://tukaani.org/xz/) | >= 5.2.2 | Depends | +| [liblzo2-dev](http://www.oberhumer.com/opensource/lzo/) | >= 2.06 | GPLv2+ | +| [zlib1g-dev](https://zlib.net/) | >= 1.2.7 | zlib and Boost | +| **Optional dependencies** | | | +| [re2c](http://re2c.org) | >= 1.0 | public domain | +| [utf8proc](https://juliastrings.github.io/utf8proc/) | >= 2.0 | MIT | +| **Internal dependencies** | | | +| [lemon](https://www.sqlite.org/lemon.html) | 2021-09 | public domain | +| [gopt](http://www.purposeful.co.uk/software/gopt/) | 10.0 | TFL | +| [SipHash](https://github.com/veorq/SipHash) | 2017-02 | CC0 | +| [BLAKE2](https://github.com/BLAKE2/libb2) | 2018-07 | CC0 | +| [whereami](https://github.com/gpakosz/whereami) | 2018-09 | WTFPLV2 | +| [squashfuse](https://github.com/vasi/squashfuse) | >= 0.5.0 | BSD 2-clause | # Configuring wake diff --git a/src/wakefs/namespace.cpp b/src/wakefs/namespace.cpp index 8d38ccffe..611ed4031 100644 --- a/src/wakefs/namespace.cpp +++ b/src/wakefs/namespace.cpp @@ -206,13 +206,16 @@ static bool do_squashfuse_mount(const std::string &source, const std::string &mo if (pid == 0) { // kernel to send SIGKILL to squashfuse when wakebox terminates if (prctl(PR_SET_PDEATHSIG, SIGKILL) == -1) { - std::cerr << "squashfuse_ll prctl: " << strerror(errno) << std::endl; + std::cerr << "wake_squashfuse_ll prctl: " << strerror(errno) << std::endl; unlink(fifo_path_result->c_str()); exit(1); } - execlp("squashfuse_ll", "squashfuse_ll", "-o", "notify_pipe", fifo_path_result->c_str(), "-f", + + auto notify_pipe_arg = std::string("notify_pipe=") + *fifo_path_result; + + execlp("wake_squashfuse_ll", "wake_squashfuse_ll", "-o", notify_pipe_arg.c_str(), "-f", source.c_str(), mountpoint.c_str(), NULL); - std::cerr << "execlp squashfuse: " << strerror(errno) << std::endl; + std::cerr << "execlp wake_squashfuse_ll: " << strerror(errno) << std::endl; unlink(fifo_path_result->c_str()); exit(1); } @@ -226,20 +229,16 @@ static bool do_squashfuse_mount(const std::string &source, const std::string &mo std::cerr << "Could not open fifo: " << strerror(wait_for_mount_opt->posix_error) << std::endl; return false; - break; case SquashFuseMountWaitErrorType::FailureToReadFifo: std::cerr << "Error reading fifo: " << strerror(wait_for_mount_opt->posix_error) << std::endl; return false; - break; case SquashFuseMountWaitErrorType::ReceivedZeroBytes: std::cerr << "Zero bytes read from fifo." << std::endl; return false; - break; case SquashFuseMountWaitErrorType::MountFailed: std::cerr << "Squashfuse wrote 'f' meaning it failed to mount." << std::endl; return false; - break; default: break; } diff --git a/src/wakefs/squashfuse_helper.cpp b/src/wakefs/squashfuse_helper.cpp index af70aadb5..bbfb950b4 100644 --- a/src/wakefs/squashfuse_helper.cpp +++ b/src/wakefs/squashfuse_helper.cpp @@ -1,3 +1,22 @@ +/* Squashfuse mount helper fuctions + * + * Copyright 2023 SiFive, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You should have received a copy of LICENSE.Apache2 along with + * this software. If not, you may obtain a copy at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Open Group Base Specifications Issue 7 #define _XOPEN_SOURCE 700 #define _POSIX_C_SOURCE 200809L @@ -42,12 +61,12 @@ wcl::optional wait_for_squashfuse_mount( auto defer = wcl::make_defer([&]() { unlink(squashfuse_fifo_path.c_str()); }); char squashfuse_notify_result = '\0'; - ssize_t bytesRead = read(squashfuse_notify_pipe_fd->get(), &squashfuse_notify_result, - sizeof(squashfuse_notify_result)); - if (bytesRead == -1) { + ssize_t bytes_read = read(squashfuse_notify_pipe_fd->get(), &squashfuse_notify_result, + sizeof(squashfuse_notify_result)); + if (bytes_read == -1) { return wcl::some( SquashFuseMountWaitError{SquashFuseMountWaitErrorType::FailureToReadFifo, errno}); - } else if (bytesRead == 0) { + } else if (bytes_read == 0) { return wcl::some(SquashFuseMountWaitError{SquashFuseMountWaitErrorType::ReceivedZeroBytes, -1}); } diff --git a/tests/tests.wake b/tests/tests.wake index f72703698..3013dd3e5 100644 --- a/tests/tests.wake +++ b/tests/tests.wake @@ -247,6 +247,9 @@ def runTest (testScript: Path): Result Unit Error = True True -> Pass Unit False False -> Pass Unit True False -> + def _ = println jobStderr + def _ = println jobStdout + Fail (makeError "Test failed ({format testJob.getJobStatus}) with '{replace `\n.*` "" jobStderr}'") False True -> Fail (makeError "Test should not have passed with '{replace `\n.*` "" jobStderr}'") diff --git a/tests/wakebox/squashfuse/.wakeroot b/tests/wakebox/squashfuse/.wakeroot new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/tests/wakebox/squashfuse/.wakeroot @@ -0,0 +1 @@ + diff --git a/tests/wakebox/squashfuse/input.json b/tests/wakebox/squashfuse/input.json new file mode 100644 index 000000000..de588b048 --- /dev/null +++ b/tests/wakebox/squashfuse/input.json @@ -0,0 +1,23 @@ +{ + "command": [ + "/bin/bash", + "/tmp/squashfs/foo.sh" + ], + "foo": 97, + "environment": [ + "USER=root", + "HOME=/root", + "PATH=/usr/bin:/bin:/usr/sbin:/sbin" + ], + "directory": ".", + "stdin": "", + "user-id": 0, + "group-id": 0, + "mount-ops": [ + { + "type": "squashfs", + "source": "tmp/pass.squashfs" + } + ], + "visible": [] +} diff --git a/tests/wakebox/squashfuse/pass.sh b/tests/wakebox/squashfuse/pass.sh new file mode 100755 index 000000000..f1e86b8c5 --- /dev/null +++ b/tests/wakebox/squashfuse/pass.sh @@ -0,0 +1,47 @@ +#!/bin/bash +WAKE_BIN_DIR="$1" + +# It's not valid to call wakebox with an empty PATH. +# So we fill PATH with some typical values. +export PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:$WAKE_BIN_DIR" + +set -ex + +# Preserve original directory location +INPUT_JSON="input.json" +RESULT_JSON="result.json" +TMPDIR="tmp" +mkdir tmp + +# Remove temp build dir on error or exit. +cleanup () { + # Sleep in hopes that fuse will close the session in time + sleep 3 + rm -rf "$TMPDIR" + echo "?: $?" +} +trap cleanup EXIT + +# Populate and create the test squashfs file +SQUASH_ROOT_DIR="$TMPDIR/squashfs-root" +SQUASHFS_FILENAME="$TMPDIR/pass.squashfs" + +mkdir -p "$SQUASH_ROOT_DIR/.wakebox" +printf '#!/bin/sh\nexit 97\n' > "$SQUASH_ROOT_DIR/foo.sh" +chmod +x "$SQUASH_ROOT_DIR/foo.sh" +echo "/tmp/squashfs" > "$SQUASH_ROOT_DIR/.wakebox/mountpoint" + +mksquashfs "$SQUASH_ROOT_DIR" "$SQUASHFS_FILENAME" -comp xz -all-root -noappend -no-xattrs + +tree + +# Run the test +"$WAKE_BIN_DIR/wakebox" -p "$INPUT_JSON" -o "$RESULT_JSON" --isolate-retcode + +# Check result +[ "$(jq .usage.status "$RESULT_JSON")" -ne 97 ] && exit 98 + +# Cleanup +rm $RESULT_JSON + +exit 0