Added Android Launcher and Disk Extration

This commit is contained in:
iChris4 committed 2026-09-17 18:32:04 +02:00
1 parent 1346e53cd6
commit 2f85207c39
74 files changed
+6153 -70

No files matched your search

+817
View File
@@ -0,0 +1,817 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "adler2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "aes"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8eb277bec05f56a0e0591f155a484cbd0f4f07ff2905051a48c72f004f7ed58"
dependencies = [
"cipher",
"cpubits",
"cpufeatures",
]
[[package]]
name = "allocator-api2"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "autocfg"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
[[package]]
name = "base16ct"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6"
[[package]]
name = "block-buffer"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
dependencies = [
"hybrid-array",
]
[[package]]
name = "block-padding"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "710f1dd022ef4e93f8a438b4ba958de7f64308434fa6a87104481645cc30068b"
dependencies = [
"hybrid-array",
]
[[package]]
name = "bytes"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
[[package]]
name = "bzip2-sys"
version = "0.1.13+1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14"
dependencies = [
"cc",
"pkg-config",
]
[[package]]
name = "cbc"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce2dc9ee5f88d11e0beb842c88b33c8a5cf0d1329c4b19494af42b07dbfe8896"
dependencies = [
"cipher",
]
[[package]]
name = "cc"
version = "1.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3eb0f42d6c360dc3f8a821f6bf2fdea7f72bfd36b3076eb0e6d1e9e0752fff4"
dependencies = [
"find-msvc-tools",
"jobserver",
"libc",
"shlex",
]
[[package]]
name = "cesu8"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]]
name = "cfg-if"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
[[package]]
name = "cipher"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c"
dependencies = [
"crypto-common",
"inout",
]
[[package]]
name = "combine"
version = "4.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e"
dependencies = [
"bytes",
"memchr",
]
[[package]]
name = "cpubits"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae"
[[package]]
name = "cpufeatures"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566"
dependencies = [
"libc",
]
[[package]]
name = "crc32fast"
version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6"
[[package]]
name = "crypto-common"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
dependencies = [
"hybrid-array",
]
[[package]]
name = "digest"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "dyn-clone"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
[[package]]
name = "either"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34"
[[package]]
name = "encoding_rs"
version = "0.8.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
dependencies = [
"cfg-if",
]
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "find-msvc-tools"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e0f1c7c3a72c66fd80abe965175f7523475c0489a87d3ff9d6e8c87d87a9d2d"
[[package]]
name = "foldhash"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
[[package]]
name = "getrandom"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
dependencies = [
"cfg-if",
"libc",
"r-efi",
]
[[package]]
name = "hashbrown"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
dependencies = [
"allocator-api2",
"equivalent",
"foldhash",
]
[[package]]
name = "higher-kinded-types"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e690f8474c6c5d8ff99656fcbc195a215acc3949481a8b0b3351c838972dc776"
dependencies = [
"macro_rules_attribute",
"never-say-never",
"paste",
]
[[package]]
name = "hybrid-array"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17"
dependencies = [
"typenum",
]
[[package]]
name = "inout"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7"
dependencies = [
"block-padding",
"hybrid-array",
]
[[package]]
name = "itertools"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
dependencies = [
"either",
]
[[package]]
name = "jni"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
dependencies = [
"cesu8",
"cfg-if",
"combine",
"jni-sys 0.3.1",
"log",
"thiserror 1.0.69",
"walkdir",
"windows-sys 0.45.0",
]
[[package]]
name = "jni-sys"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258"
dependencies = [
"jni-sys 0.4.1",
]
[[package]]
name = "jni-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2"
dependencies = [
"jni-sys-macros",
]
[[package]]
name = "jni-sys-macros"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
dependencies = [
"quote",
"syn 2.0.119",
]
[[package]]
name = "jobserver"
version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3"
dependencies = [
"getrandom",
"libc",
]
[[package]]
name = "libc"
version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]]
name = "liblzma-sys"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c7e3581f367a78d7b7e7ae948d023310556f0cfc13156c2e4e00e25616492b9"
dependencies = [
"cc",
"libc",
"pkg-config",
]
[[package]]
name = "libz-sys"
version = "1.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85bc9657773828b90eeb625adff10eeac83cc21bbfd8e23a03eaa8a33c9e28d9"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "log"
version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
[[package]]
name = "lru"
version = "0.16.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39"
dependencies = [
"hashbrown",
]
[[package]]
name = "macro_rules_attribute"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3ae8f6d608c795738406608304d30a2dfbdc8e58e44f7ba43236da5208ded3c"
dependencies = [
"macro_rules_attribute-proc_macro",
"pastey",
]
[[package]]
name = "macro_rules_attribute-proc_macro"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc04a4c58212d57930a24bf47d3fa87485264a3a054e9c10e042eb373573ad3c"
[[package]]
name = "md-5"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98"
dependencies = [
"cfg-if",
"digest",
]
[[package]]
name = "memchr"
version = "2.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
[[package]]
name = "never-say-never"
version = "6.6.666"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf5a574dadd7941adeaa71823ecba5e28331b8313fb2e1c6a5c7e5981ea53ad6"
[[package]]
name = "nod"
version = "2.0.0-alpha.10"
source = "git+https://github.com/encounter/nod?tag=v2.0.0-alpha.10#dc18d2ff129f05228b8510ea092d8b24c290a49a"
dependencies = [
"adler2",
"aes",
"base16ct",
"block-padding",
"bytes",
"bzip2-sys",
"cbc",
"crc32fast",
"crossbeam-channel",
"crossbeam-utils",
"crypto-common",
"digest",
"dyn-clone",
"encoding_rs",
"itertools",
"liblzma-sys",
"libz-sys",
"lru",
"md-5",
"polonius-the-crab",
"sha1",
"simple_moving_average",
"thiserror 2.0.20",
"tracing",
"xxhash-rust",
"zerocopy",
"zstd-sys",
]
[[package]]
name = "nod-jni"
version = "0.1.0"
dependencies = [
"jni",
"nod",
"zerocopy",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pastey"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4"
[[package]]
name = "pin-project-lite"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "pkg-config"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
[[package]]
name = "polonius-the-crab"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec242d7eccbb2fd8b3b5b6e3cf89f94a91a800f469005b44d154359609f8af72"
dependencies = [
"higher-kinded-types",
"never-say-never",
]
[[package]]
name = "proc-macro2"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
[[package]]
name = "r-efi"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "sha1"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "shlex"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
[[package]]
name = "simple_moving_average"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a4b144ad185430cd033299e2c93e465d5a7e65fbb858593dc57181fa13cd310"
dependencies = [
"num-traits",
]
[[package]]
name = "syn"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl 1.0.69",
]
[[package]]
name = "thiserror"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
dependencies = [
"thiserror-impl 2.0.20",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.119",
]
[[package]]
name = "thiserror-impl"
version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
dependencies = [
"proc-macro2",
"quote",
"syn 3.0.6",
]
[[package]]
name = "tracing"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.119",
]
[[package]]
name = "tracing-core"
version = "0.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
dependencies = [
"once_cell",
]
[[package]]
name = "typenum"
version = "1.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
[[package]]
name = "unicode-ident"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "walkdir"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "winapi-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-targets"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
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.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "xxhash-rust"
version = "0.8.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aee1b19627c7c60102ab80d3a9cbe18de90bfe03bfa6c3715447681f0e8c8af6"
[[package]]
name = "zerocopy"
version = "0.8.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d35102a9f36d089ccae9e4c6802bc118be4487b80aaffc0ab4e0cf5ce92d2873"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "146c01f5ab44258da43cf276c74a2763db2ff3969c9c652c3f2de07041d0b2bc"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.119",
]
[[package]]
name = "zstd-sys"
version = "2.1.0+zstd.1.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ef0a8027ec3ee71300ab3bcbcd0393f434aa72b91ca6d635a39941deae8eea0"
dependencies = [
"cc",
"pkg-config",
]
+33
View File
@@ -0,0 +1,33 @@
[package]
name = "nod-jni"
version = "0.1.0"
edition = "2024"
rust-version = "1.85"
license = "GPL-3.0-only"
publish = false
description = "JNI bridge from the Quest launcher to nod, the disc image library behind the PC installer's nodtool."
[lib]
name = "nod_jni"
crate-type = ["cdylib"]
# Built on its own, never as part of an outer workspace.
[workspace]
[dependencies]
jni = "0.21"
# The same nod release as Launcher/WiiCompiled.Setup.Common/NodToolProvider.cs, so the
# Quest and PC installers extract a disc identically. alpha.10 is only published on GitHub.
nod = { git = "https://github.com/encounter/nod", tag = "v2.0.0-alpha.10", default-features = false, features = [
"compress-bzip2-static",
"compress-lzma-static",
"compress-zlib-static",
"compress-zstd-static",
"threading",
] }
zerocopy = "0.8"
[profile.release]
codegen-units = 1
lto = "thin"
strip = true
+300
View File
@@ -0,0 +1,300 @@
//! JNI bridge from the Quest launcher (`org.wiicompiled.quest.launcher.NodDisc`) to nod.
//!
//! The PC installer validates and extracts the player's disc with nodtool. This library gives
//! the Quest launcher the same three operations on a file descriptor from Android's document
//! picker: read the disc header, read one file of the data partition (so the launcher can hash
//! main.dol and StaticR.rel before a long extraction), and extract the data partition.
//!
//! The extraction is nodtool's `extract` command (nodtool/src/cmd/extract.rs at
//! v2.0.0-alpha.10, MIT OR Apache-2.0) with progress reporting and cancellation added, so both
//! installers write the same `sys/`, `files/`, `disc/` and `*.bin` layout that the runtime's DVD
//! layer reads.
use std::{
fs::{self, File},
io::{self, BufRead, Read, Write},
os::{
fd::{BorrowedFd, RawFd},
unix::fs::FileExt,
},
panic::{AssertUnwindSafe, catch_unwind},
path::Path,
sync::Arc,
time::{Duration, Instant},
};
use jni::{
JNIEnv,
objects::{JObject, JString, JValue},
sys::{jbyteArray, jint, jstring},
};
use nod::{
common::PartitionKind,
disc::fst::Fst,
read::{DiscOptions, DiscReader, DiscStream, PartitionMeta, PartitionOptions, PartitionReader},
};
use zerocopy::IntoBytes;
/// Thrown instead of IOException when the listener asked to stop.
const CANCELLED_EXCEPTION: &str = "java/io/InterruptedIOException";
const PROGRESS_INTERVAL: Duration = Duration::from_millis(200);
enum Failure {
Error(String),
Cancelled,
}
impl<E: std::fmt::Display> From<E> for Failure {
fn from(error: E) -> Self { Failure::Error(error.to_string()) }
}
type Outcome<T> = Result<T, Failure>;
/// A disc image read with pread through its own duplicate of the picker's descriptor. pread
/// keeps no file position, so nod's preloader threads can each hold a clone.
#[derive(Clone)]
struct FdStream {
file: Arc<File>,
len: u64,
}
impl DiscStream for FdStream {
fn read_exact_at(&mut self, buf: &mut [u8], offset: u64) -> io::Result<()> {
self.file.read_exact_at(buf, offset)
}
fn stream_len(&mut self) -> io::Result<u64> { Ok(self.len) }
}
fn open_disc(fd: RawFd) -> Outcome<DiscReader> {
// SAFETY: the caller keeps the ParcelFileDescriptor open for the duration of the JNI call,
// and only a duplicate outlives this borrow.
let owned = unsafe { BorrowedFd::borrow_raw(fd) }.try_clone_to_owned()?;
let file = File::from(owned);
let len = file.metadata()?.len();
let options = DiscOptions { preloader_threads: 4, ..Default::default() };
Ok(DiscReader::new_stream(Box::new(FdStream { file: Arc::new(file), len }), &options)?)
}
fn open_data_partition(disc: &DiscReader) -> Outcome<Box<dyn PartitionReader>> {
Ok(disc.open_partition_kind(PartitionKind::Data, &PartitionOptions::default())?)
}
/// Bytes an extraction writes: the system files plus every file in the FST.
fn extracted_size(disc: &DiscReader, meta: &PartitionMeta) -> Outcome<u64> {
let mut total = (meta.raw_boot.len()
+ meta.raw_bi2.len()
+ meta.raw_apploader.len()
+ meta.raw_fst.len()
+ meta.raw_dol.len()) as u64;
if disc.header().is_wii() {
total += 0x100 + disc.region().map_or(0, |region| region.len()) as u64;
for part in [&meta.raw_ticket, &meta.raw_tmd, &meta.raw_cert_chain] {
total += part.as_ref().map_or(0, |bytes| bytes.len()) as u64;
}
total += meta.raw_h3_table.as_ref().map_or(0, |bytes| bytes.len()) as u64;
}
let fst = Fst::new(&meta.raw_fst)?;
for (_, node, _) in fst.iter() {
if node.is_file() {
total += u64::from(node.length());
}
}
Ok(total)
}
/// "<game id>\n<title>\n<bytes an extraction writes>"
fn header(fd: RawFd) -> Outcome<String> {
let disc = open_disc(fd)?;
let mut partition = open_data_partition(&disc)?;
let meta = partition.meta()?;
let total = extracted_size(&disc, &meta)?;
let header = disc.header();
Ok(format!("{}\n{}\n{}", header.game_id_str(), header.game_title_str(), total))
}
/// `sys/main.dol`, or a path below `files/`, of the data partition.
fn read_file(fd: RawFd, path: &str) -> Outcome<Vec<u8>> {
let disc = open_disc(fd)?;
let mut partition = open_data_partition(&disc)?;
let meta = partition.meta()?;
if path == "sys/main.dol" {
return Ok(meta.raw_dol.to_vec());
}
let Some(relative) = path.strip_prefix("files/") else {
return Err(Failure::Error(format!("Unsupported disc path {path}")));
};
let fst = Fst::new(&meta.raw_fst)?;
let Some((_, node)) = fst.find(relative) else {
return Err(Failure::Error(format!("{path} is not on this disc")));
};
let mut bytes = Vec::with_capacity(node.length() as usize);
partition.open_file(node)?.read_to_end(&mut bytes)?;
Ok(bytes)
}
struct Progress<'a> {
done: u64,
total: u64,
last: Instant,
report: &'a mut dyn FnMut(u64, u64) -> Outcome<bool>,
}
impl Progress<'_> {
fn advance(&mut self, bytes: usize) -> Outcome<()> {
self.done += bytes as u64;
if self.last.elapsed() >= PROGRESS_INTERVAL {
self.last = Instant::now();
self.check()?;
}
Ok(())
}
fn check(&mut self) -> Outcome<()> {
if (self.report)(self.done, self.total)? { Ok(()) } else { Err(Failure::Cancelled) }
}
}
fn extract(fd: RawFd, out_dir: &Path, report: &mut dyn FnMut(u64, u64) -> Outcome<bool>) -> Outcome<()> {
let disc = open_disc(fd)?;
let mut partition = open_data_partition(&disc)?;
let meta = partition.meta()?;
let total = extracted_size(&disc, &meta)?;
let mut progress = Progress { done: 0, total, last: Instant::now(), report };
progress.check()?;
extract_sys_files(&disc, &meta, out_dir, &mut progress)?;
let files_dir = out_dir.join("files");
fs::create_dir_all(&files_dir)?;
let is_wii = disc.header().is_wii();
let fst = Fst::new(&meta.raw_fst)?;
for (_, node, path) in fst.iter() {
let target = files_dir.join(&path);
if node.is_dir() {
fs::create_dir_all(&target).map_err(|e| format!("Creating directory {path}: {e}"))?;
continue;
}
let mut file = File::create(&target).map_err(|e| format!("Creating file {path}: {e}"))?;
let mut reader = partition.open_file(node).map_err(|e| {
format!("Opening {path} on the disc (offset {}, size {}): {e}", node.offset(is_wii), node.length())
})?;
loop {
let buf = reader.fill_buf().map_err(|e| format!("Reading {path}: {e}"))?;
let len = buf.len();
if len == 0 {
break;
}
file.write_all(buf).map_err(|e| format!("Writing {path}: {e}"))?;
reader.consume(len);
progress.advance(len)?;
}
file.flush().map_err(|e| format!("Writing {path}: {e}"))?;
}
progress.check()
}
fn extract_sys_files(disc: &DiscReader, meta: &PartitionMeta, out_dir: &Path, progress: &mut Progress) -> Outcome<()> {
let sys_dir = out_dir.join("sys");
fs::create_dir_all(&sys_dir)?;
write_file(meta.raw_boot.as_ref(), &sys_dir.join("boot.bin"), progress)?;
write_file(meta.raw_bi2.as_ref(), &sys_dir.join("bi2.bin"), progress)?;
write_file(meta.raw_apploader.as_ref(), &sys_dir.join("apploader.img"), progress)?;
write_file(meta.raw_fst.as_ref(), &sys_dir.join("fst.bin"), progress)?;
write_file(meta.raw_dol.as_ref(), &sys_dir.join("main.dol"), progress)?;
let header = disc.header();
if header.is_wii() {
let disc_dir = out_dir.join("disc");
fs::create_dir_all(&disc_dir)?;
write_file(&header.as_bytes()[..0x100], &disc_dir.join("header.bin"), progress)?;
if let Some(region) = disc.region() {
write_file(region, &disc_dir.join("region.bin"), progress)?;
}
if let Some(ticket) = meta.raw_ticket.as_deref() {
write_file(ticket, &out_dir.join("ticket.bin"), progress)?;
}
if let Some(tmd) = meta.raw_tmd.as_deref() {
write_file(tmd, &out_dir.join("tmd.bin"), progress)?;
}
if let Some(cert_chain) = meta.raw_cert_chain.as_deref() {
write_file(cert_chain, &out_dir.join("cert.bin"), progress)?;
}
if let Some(h3_table) = meta.raw_h3_table.as_deref() {
write_file(h3_table, &out_dir.join("h3.bin"), progress)?;
}
}
Ok(())
}
fn write_file(bytes: &[u8], path: &Path, progress: &mut Progress) -> Outcome<()> {
fs::write(path, bytes).map_err(|e| format!("Writing {}: {e}", path.display()))?;
progress.advance(bytes.len())
}
/// Runs `body`, turning a failure or a panic into a pending Java exception.
fn guarded<T>(env: &mut JNIEnv, fallback: T, body: impl FnOnce(&mut JNIEnv) -> Outcome<T>) -> T {
match catch_unwind(AssertUnwindSafe(|| body(env))) {
Ok(Ok(value)) => value,
Ok(Err(failure)) => {
// A Java exception raised inside a callback is already pending; keep it.
if !env.exception_check().unwrap_or(false) {
let _ = match failure {
Failure::Error(message) => env.throw_new("java/io/IOException", message),
Failure::Cancelled => env.throw_new(CANCELLED_EXCEPTION, "Extraction cancelled"),
};
}
fallback
}
Err(_) => {
let _ = env.throw_new("java/io/IOException", "nod-jni panicked; see logcat");
fallback
}
}
}
#[unsafe(no_mangle)]
pub extern "system" fn Java_org_wiicompiled_quest_launcher_NodDisc_header<'local>(
mut env: JNIEnv<'local>,
_this: JObject<'local>,
fd: jint,
) -> jstring {
guarded(&mut env, std::ptr::null_mut(), |env| Ok(env.new_string(header(fd)?)?.into_raw()))
}
#[unsafe(no_mangle)]
pub extern "system" fn Java_org_wiicompiled_quest_launcher_NodDisc_readFile<'local>(
mut env: JNIEnv<'local>,
_this: JObject<'local>,
fd: jint,
path: JString<'local>,
) -> jbyteArray {
guarded(&mut env, std::ptr::null_mut(), |env| {
let path: String = env.get_string(&path)?.into();
let bytes = read_file(fd, &path)?;
Ok(env.byte_array_from_slice(&bytes)?.into_raw())
})
}
#[unsafe(no_mangle)]
pub extern "system" fn Java_org_wiicompiled_quest_launcher_NodDisc_extract<'local>(
mut env: JNIEnv<'local>,
_this: JObject<'local>,
fd: jint,
out_dir: JString<'local>,
listener: JObject<'local>,
) {
guarded(&mut env, (), |env| {
let out_dir: String = env.get_string(&out_dir)?.into();
let mut report = |done: u64, total: u64| -> Outcome<bool> {
let result = env.call_method(
&listener,
"update",
"(JJ)Z",
&[JValue::Long(done as i64), JValue::Long(total as i64)],
);
Ok(result?.z()?)
};
extract(fd, Path::new(&out_dir), &mut report)
})
}