diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..d535664 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,23 @@ +[target.aarch64-unknown-linux-gnu] +rustflags = ["-C", "target-feature=+crt-static"] +linker = "aarch64-linux-gnu-gcc" + +[target.mips-unknown-linux-gnu] +rustflags = ["-C", "target-feature=+crt-static"] +linker = "mips-linux-gnu-gcc" + +[target.mipsel-unknown-linux-gnu] +rustflags = ["-C", "target-feature=+crt-static"] +linker = "mipsel-linux-gnu-gcc" + +[target.mips64-unknown-linux-gnuabi64] +rustflags = ["-C", "target-feature=+crt-static"] +linker = "mips64-linux-gnuabi64-gcc" + +[target.mips64el-unknown-linux-gnuabi64] +rustflags = ["-C", "target-feature=+crt-static"] +linker = "mips64el-linux-gnuabi64-gcc" + +[target.riscv64gc-unknown-linux-gnu] +rustflags = ["-C", "target-feature=+crt-static"] +linker = "riscv64-linux-gnu-gcc" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..5023fdc --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,54 @@ +on: [push, pull_request] + +name: Continuous integration + +jobs: + check: + name: Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - run: cargo check + + test: + name: Test Suite + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - run: cargo test + + fmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - run: rustup component add rustfmt + - run: cargo fmt --all -- --check + + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - run: rustup component add clippy + - run: cargo clippy -- -D warnings diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..08344eb --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,104 @@ +name: release +on: + release: + types: [published] +permissions: + contents: write +jobs: + deploy: + name: deploy + runs-on: ${{ matrix.os }} + strategy: + matrix: + build: [linux,aarch64-linux,mips-linux,mipsel-linux,mips64-linux,mips64el-linux,riscv64,macos,macos-arm64,windows] + include: + - build: linux + os: ubuntu-latest + rust: nightly + target: x86_64-unknown-linux-musl + linker: musl-tools + - build: aarch64-linux + os: ubuntu-latest + rust: nightly + target: aarch64-unknown-linux-gnu + linker: gcc-aarch64-linux-gnu + - build: mips-linux + os: ubuntu-latest + rust: stable + target: mips-unknown-linux-gnu + linker: gcc-mips-linux-gnu + - build: mipsel-linux + os: ubuntu-latest + rust: stable + target: mipsel-unknown-linux-gnu + linker: gcc-mipsel-linux-gnu + - build: mips64-linux + os: ubuntu-latest + rust: stable + target: mips64-unknown-linux-gnuabi64 + linker: gcc-mips64-linux-gnuabi64 + - build: mips64el-linux + os: ubuntu-latest + rust: stable + target: mips64el-unknown-linux-gnuabi64 + linker: gcc-mips64el-linux-gnuabi64 + - build: riscv64 + os: ubuntu-latest + rust: stable + target: riscv64gc-unknown-linux-gnu + linker: gcc-riscv64-linux-gnu + - build: macos + os: macos-latest + rust: nightly + target: x86_64-apple-darwin + - build: macos-arm64 + os: macos-latest + rust: nightly + target: aarch64-apple-darwin + - build: windows + os: windows-2019 + rust: nightly-x86_64-msvc + target: x86_64-pc-windows-msvc + fail-fast: false + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Install linker + if: matrix.build == 'linux' || matrix.build == 'aarch64-linux' || matrix.build == 'mips-linux' || matrix.build == 'mipsel-linux' ||matrix.build == 'mips64el-linux' || matrix.build == 'mips64-linux' || matrix.build == 'riscv64' + run: sudo apt-get update && sudo apt-get install ${{ matrix.linker }} -y + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + profile: minimal + override: true + target: ${{ matrix.target }} + - name: Build binary + run: cargo build --verbose --release --target ${{ matrix.target }} + env: + RUST_BACKTRACE: 1 + + - name: Strip binary (linux and macos) + if: matrix.build == 'linux' || matrix.build == 'macos' + run: strip "target/${{ matrix.target }}/release/wakeonlan" + + - name: rename binary + shell: bash + run: | + mkdir -p binary + if [ "${{ matrix.build }}" = "windows" ]; then + cp "./target/${{ matrix.target }}/release/wakeonlan.exe" ./binary/wakeonlan-${{ matrix.target }}.exe + else + cp "./target/${{ matrix.target }}/release/wakeonlan" ./binary/wakeonlan-${{ matrix.target }} + fi + - name: Upload binary + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ./binary/wakeonlan* + file_glob: true + tag: ${{ github.ref }} + overwrite: true diff --git a/.gitignore b/.gitignore index 4c1a6d6..f9fd1a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +mountpoint/ + ### JetBrains template # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..ea3eee4 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,49 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'duefuse'", + "cargo": { + "args": [ + "build", + "--bin=duefuse", + "--package=duefuse" + ], + "filter": { + "name": "duefuse", + "kind": "bin" + } + }, + "args": [ + "mountpoint", + "--auto_unmount", + "true" + ], + "cwd": "${workspaceFolder}", + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in executable 'duefuse'", + "cargo": { + "args": [ + "test", + "--no-run", + "--bin=duefuse", + "--package=duefuse" + ], + "filter": { + "name": "duefuse", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + } + ] +} diff --git a/DEVELOP.md b/CONTRIBUTING.md similarity index 100% rename from DEVELOP.md rename to CONTRIBUTING.md diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..5b46e98 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,537 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" + +[[package]] +name = "anstyle-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d5f1946157a96594eb2d2c10eb7ad9a2b27518cb3000209dec700c35df9197d" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78116e32a042dd73c2901f0dc30790d20ff3447f3e3472fad359e8c3d282bcd6" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "once_cell", + "strsim", +] + +[[package]] +name = "clap_lex" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "duefuse" +version = "0.1.0" +dependencies = [ + "bincode", + "clap", + "env_logger", + "fuser", + "libc", + "serde", + "tempfile", +] + +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "errno" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fastrand" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + +[[package]] +name = "fuser" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21370f84640642c8ea36dfb2a6bfc4c55941f476fcf431f6fef25a5ddcf0169b" +dependencies = [ + "libc", + "log", + "memchr", + "page_size", + "pkg-config", + "smallvec", + "zerocopy", +] + +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi", + "rustix", + "windows-sys", +] + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "linux-raw-sys" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "page_size" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b7663cbd190cfd818d08efa8497f6cd383076688c49a391ef7c0d03cd12b561" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "rustix" +version = "0.38.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bfe0f2582b4931a45d1fa608f8a8722e8b3c7ac54dd6d5f3b3212791fedef49" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "serde" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "smallvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "2.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "zerocopy" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3b9c234616391070b0b173963ebc65a9195068e7ed3731c6edac2ec45ebe106" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f7f3a471f98d0a61c34322fbbfd10c384b07687f680d4119813713f72308d91" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d75ac3d --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "duefuse" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +env_logger = "0.10.0" +clap = { version = "4.4.0", features = ["cargo"] } +bincode = "1.3.1" +serde = { version = "1.0.102", features = ["std", "derive"] } +tempfile = "3" +fuser = "0.13.0" +libc = "0.2.147" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..ef05134 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,146 @@ +use clap::{crate_version, Arg, Command}; +use fuser::{ + FileAttr, FileType, Filesystem, MountOption, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry, + Request, +}; +use libc::ENOENT; +use std::ffi::OsStr; +use std::time::{Duration, UNIX_EPOCH}; + +const TTL: Duration = Duration::from_secs(1); // 1 second + +const HELLO_DIR_ATTR: FileAttr = FileAttr { + ino: 1, + size: 0, + blocks: 0, + atime: UNIX_EPOCH, // 1970-01-01 00:00:00 + mtime: UNIX_EPOCH, + ctime: UNIX_EPOCH, + crtime: UNIX_EPOCH, + kind: FileType::Directory, + perm: 0o755, + nlink: 2, + uid: 501, + gid: 20, + rdev: 0, + flags: 0, + blksize: 512, +}; + +const HELLO_TXT_CONTENT: &str = "Hello World!\n"; + +const HELLO_TXT_ATTR: FileAttr = FileAttr { + ino: 2, + size: 13, + blocks: 1, + atime: UNIX_EPOCH, // 1970-01-01 00:00:00 + mtime: UNIX_EPOCH, + ctime: UNIX_EPOCH, + crtime: UNIX_EPOCH, + kind: FileType::RegularFile, + perm: 0o644, + nlink: 1, + uid: 501, + gid: 20, + rdev: 0, + flags: 0, + blksize: 512, +}; + +struct HelloFS; + +impl Filesystem for HelloFS { + fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) { + if parent == 1 && name.to_str() == Some("hello.txt") { + reply.entry(&TTL, &HELLO_TXT_ATTR, 0); + } else { + reply.error(ENOENT); + } + } + + fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) { + match ino { + 1 => reply.attr(&TTL, &HELLO_DIR_ATTR), + 2 => reply.attr(&TTL, &HELLO_TXT_ATTR), + _ => reply.error(ENOENT), + } + } + + fn read( + &mut self, + _req: &Request, + ino: u64, + _fh: u64, + offset: i64, + _size: u32, + _flags: i32, + _lock: Option, + reply: ReplyData, + ) { + if ino == 2 { + reply.data(&HELLO_TXT_CONTENT.as_bytes()[offset as usize..]); + } else { + reply.error(ENOENT); + } + } + + fn readdir( + &mut self, + _req: &Request, + ino: u64, + _fh: u64, + offset: i64, + mut reply: ReplyDirectory, + ) { + if ino != 1 { + reply.error(ENOENT); + return; + } + + let entries = vec![ + (1, FileType::Directory, "."), + (1, FileType::Directory, ".."), + (2, FileType::RegularFile, "hello.txt"), + ]; + + for (i, entry) in entries.into_iter().enumerate().skip(offset as usize) { + // i + 1 means the index of the next entry + if reply.add(entry.0, (i + 1) as i64, entry.1, entry.2) { + break; + } + } + reply.ok(); + } +} + +fn main() { + let matches = Command::new("duefuse") + .version(crate_version!()) + .arg( + Arg::new("MOUNT_POINT") + .required(true) + .index(1) + .help("Act as a client, and mount FUSE at given path"), + ) + .arg( + Arg::new("auto_unmount") + .long("auto_unmount") + .help("Automatically unmount on process exit") + ) + .arg( + Arg::new("allow-root") + .long("allow-root") + .help("Allow root user to access filesystem"), + ) + .get_matches(); + env_logger::init(); + let mountpoint = matches.get_one::("MOUNT_POINT").unwrap(); + let mut options = vec![MountOption::RO, MountOption::FSName("duefuse".to_string())]; + if matches.contains_id("auto_unmount") { + options.push(MountOption::AutoUnmount); + } + if matches.contains_id("allow-root") { + options.push(MountOption::AllowRoot); + } + fuser::mount2(HelloFS, mountpoint, &options).unwrap(); +}