droid-juicer-0.2.1/.cargo_vcs_info.json0000644000000001360000000000100134140ustar { "git": { "sha1": "c4f754de9c1d6d2e39921aba67fe8d5f3553f8b9" }, "path_in_vcs": "" }droid-juicer-0.2.1/.gitignore000064400000000000000000000000101046102023000141630ustar 00000000000000/target droid-juicer-0.2.1/Cargo.lock0000644000000463240000000000100114000ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "aho-corasick" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] [[package]] name = "anstream" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", "utf8parse", ] [[package]] name = "anstyle" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", "windows-sys 0.52.0", ] [[package]] name = "bindgen" version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885" dependencies = [ "bitflags 1.3.2", "cexpr", "clang-sys", "lazy_static", "lazycell", "peeking_take_while", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", "syn 1.0.109", ] [[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.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "libc", ] [[package]] name = "cexpr" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ "nom", ] [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clang-sys" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" dependencies = [ "glob", "libc", "libloading", ] [[package]] name = "clap" version = "4.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c12ed66a79a555082f595f7eb980d08669de95009dd4b3d61168c573ebe38fc9" dependencies = [ "clap_builder", "clap_derive", ] [[package]] name = "clap_builder" version = "4.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f4645eab3431e5a8403a96bea02506a8b35d28cd0f0330977dd5d22f9c84f43" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim", ] [[package]] name = "clap_derive" version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "clap_lex" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "colorchoice" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "droid-juicer" version = "0.2.1" dependencies = [ "clap", "goblin", "serde", "serde_json", "sys-mount", "toml", "uname", ] [[package]] name = "errno" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" dependencies = [ "errno-dragonfly", "libc", "winapi", ] [[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 = "glob" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "goblin" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27c1b4369c2cd341b5de549380158b105a04c331be5db9110eef7b6d2742134" dependencies = [ "log", "plain", "scroll", ] [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "itoa" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lazycell" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libloading" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", "windows-sys 0.48.0", ] [[package]] name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "loopdev-erikh" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac18afc683a3326b4ba3a7c783ae6613095c8ce49e0d7bce41a2bd58da319b8d" dependencies = [ "bindgen", "errno", "libc", ] [[package]] name = "memchr" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", ] [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "peeking_take_while" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "pin-project-lite" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "plain" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "proc-macro2" version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "regex" version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "ryu" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "scroll" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" dependencies = [ "scroll_derive", ] [[package]] name = "scroll_derive" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "serde" version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "serde_json" version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ "itoa", "ryu", "serde", ] [[package]] name = "shlex" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" [[package]] name = "smart-default" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "syn" version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "sys-mount" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65a290d26aaf4d91fc55cf2afde5079c14e5e4ebffebe8f847234b0dc0df8742" dependencies = [ "bitflags 2.4.1", "libc", "loopdev-erikh", "smart-default", "thiserror", "tracing", ] [[package]] name = "thiserror" version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "toml" version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] [[package]] name = "tracing" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", "tracing-attributes", "tracing-core", ] [[package]] name = "tracing-attributes" version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "tracing-core" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", ] [[package]] name = "uname" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b72f89f0ca32e4db1c04e2a72f5345d59796d4866a1ee0609084569f73683dc8" dependencies = [ "libc", ] [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[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-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 0.48.5", ] [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets 0.52.0", ] [[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm 0.48.5", "windows_aarch64_msvc 0.48.5", "windows_i686_gnu 0.48.5", "windows_i686_msvc 0.48.5", "windows_x86_64_gnu 0.48.5", "windows_x86_64_gnullvm 0.48.5", "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows-targets" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" dependencies = [ "windows_aarch64_gnullvm 0.52.0", "windows_aarch64_msvc 0.52.0", "windows_i686_gnu 0.52.0", "windows_i686_msvc 0.52.0", "windows_x86_64_gnu 0.52.0", "windows_x86_64_gnullvm 0.52.0", "windows_x86_64_msvc 0.52.0", ] [[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_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[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_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[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_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[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_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" droid-juicer-0.2.1/Cargo.toml0000644000000020430000000000100114110ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "droid-juicer" version = "0.2.1" authors = ["Arnaud Ferraris "] description = "Extract firmware from Android vendor partitions" homepage = "https://gitlab.com/mobian1/droid-juicer" readme = "README.md" license = "MIT" [dependencies.clap] version = "4.0" features = ["derive"] [dependencies.goblin] version = "0.7" [dependencies.serde] version = "1.0" features = ["derive"] [dependencies.serde_json] version = "1.0" [dependencies.sys-mount] version = "2.0" [dependencies.toml] version = "0.5" [dependencies.uname] version = "0.1" droid-juicer-0.2.1/Cargo.toml.orig000064400000000000000000000007031046102023000150730ustar 00000000000000[package] name = "droid-juicer" homepage = "https://gitlab.com/mobian1/droid-juicer" description = "Extract firmware from Android vendor partitions" authors = [ "Arnaud Ferraris " ] version = "0.2.1" license = "MIT" edition = "2021" [dependencies] clap = { version = "4.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" toml = "0.5" goblin = "0.7" sys-mount = "2.0" uname = "0.1" droid-juicer-0.2.1/LICENSE000064400000000000000000000020721046102023000132120ustar 00000000000000The MIT License (MIT) Copyright (c) 2023 Arnaud Ferraris Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. droid-juicer-0.2.1/README.md000064400000000000000000000047311046102023000134700ustar 00000000000000Droid Juicer ============ `droid-juicer` is a tool for extracting binary firmware files from vendor partitions on Android devices. It allows importing the needed firmware into the Linux system's `/lib/firmware` folder, avoiding the need to distribute such firmware and the corresponding legal issues. ## Configuration A global `/etc/droid-juicer/config.toml` configuration file can be used to set device-independent options. This file currently only allows to configure post-processing commands, written as an array of strings. Those commands can include the special `%k` argument, which will be substituted at runtime with the revision (value of `uname -r`) for the currently running kernel. An example config (used on Debian systems) can be found in the [config.toml.sample](config.toml.sample) file. ## Device configurations `droid-juicer` relies on per-device TOML config files named after the device's DT `compatible` property. The config files contain a single section named `juicer` with a single `firmware` key. The expected value for this key is an array of "objects" with the following attributes: * `partition`: the name of the vendor partition containing the firmware files as it appears under `/dev/disk/by-partlabel/`. * `origin`: the folder of the vendor partition containing the firmware files * `destination`: the `/lib/firmware` subfolder under which the firmware files must be copied; this folder will be created if it doesn't exist * `files`: those are the firmware files to be copied by `droid-juicer`, stored as simple objects with the following attributes: * `name`: original file name * `rename` (optional): name to rename the file to Example configurations can be found in the [configs](configs) folder. ## Usage `droid-juicer` is started during the device's first boot by a systemd service. It copies the firmware files according to the corresponding configuration file, then updates the initramfs and the Android boot image so extracted firmware are available on subsequent boots. Finally, it reboots the device. `droid-juicer` can also be executed manually (as `root`). In such cases, it is however recommended to first run `droid-juicer --cleanup` so the existing files and diversions are removed before the new run. ## License `droid-juicer` is licensed under the terms of the [MIT license](https://spdx.org/licenses/MIT.html). ## Contributing Feel free to open issues and/or merge requests on the project's [gitlab](https://gitlab.com/mobian1/droid-juicer) repo. droid-juicer-0.2.1/config.toml.sample000064400000000000000000000001711046102023000156250ustar 00000000000000[postprocess] commands = [ "/usr/sbin/update-initramfs -u -k %k", "/etc/kernel/postinst.d/zz-qcom-bootimg %k", ] droid-juicer-0.2.1/configs/fairphone,fp4.toml000064400000000000000000000021051046102023000171700ustar 00000000000000[juicer] firmware = [ { partition = "vendor", origin = "firmware", destination = "qcom", files = [ { name = "a619_gmu.bin" }, { name = "a630_sqe.fw" }, ] }, { partition = "vendor", origin = "firmware", destination = "qcom/sm7225/fairphone4", files = [ { name = "a615_zap.mdt" }, { name = "lagoon_ipa_fws.mdt", rename = "ipa_fws.mdt" }, ] }, { partition = "modem", origin = "image", destination = "qcom/sm7225/fairphone4", files = [ { name = "adsp.mdt" }, { name = "adspr.jsn" }, { name = "adsps.jsn" }, { name = "adspua.jsn" }, { name = "cdsp.mdt" }, { name = "cdspr.jsn" }, { name = "modem.mdt" }, { name = "modemr.jsn" }, { name = "modemuw.jsn" }, { name = "venus.mdt" }, { name = "wlanmdsp.mbn" }, ] }, { partition = "bluetooth", origin = "image", destination = "qca", files = [ { name = "apnv11.bin" }, { name = "apbtfw11.tlv" }, ] }, ] droid-juicer-0.2.1/configs/fairphone,fp5.toml000064400000000000000000000016601046102023000171760ustar 00000000000000[juicer] firmware = [ { partition = "vendor", origin = "firmware", destination = "qcom/qcm6490/fairphone5", files = [ { name = "a660_zap.mdt" }, { name = "vpu20_1v.mdt", rename = "venus.mdt" }, { name = "yupik_ipa_fws.mdt", rename = "ipa_fws.mdt" }, ] }, { partition = "modem", origin = "image", destination = "qcom/qcm6490/fairphone5", files = [ { name = "adsp.mdt" }, { name = "adspr.jsn" }, { name = "adsps.jsn" }, { name = "adspua.jsn" }, { name = "battmgr.jsn" }, { name = "cdsp.mdt" }, { name = "cdspr.jsn" }, { name = "modem.mdt" }, { name = "modemr.jsn" }, { name = "wpss.mdt" }, ] }, { partition = "bluetooth", origin = "image", destination = "qca", files = [ { name = "msbtfw11.mbn" }, { name = "msnv11.bin" }, ] }, ] droid-juicer-0.2.1/configs/google,blueline.toml000064400000000000000000000021701046102023000176010ustar 00000000000000[juicer] firmware = [ { partition = "vendor", origin = "firmware", destination = "qcom/sdm845/pixel3", files = [ { name = "a630_zap.mdt" }, { name = "adsp.mdt" }, { name = "adspr.jsn" }, { name = "adspua.jsn" }, { name = "cdsp.mdt" }, { name = "cdspr.jsn" }, { name = "ipa_fws.mdt" }, { name = "modemuw.jsn" }, { name = "slpi.mdt" }, { name = "venus.mdt" }, { name = "wlanmdsp.mbn" }, ] }, { partition = "vendor", origin = "firmware", destination = "qca/pixel3", files = [ { name = "crnv21.bin" }, ] }, { partition = "vendor", origin = "firmware", destination = "qca", files = [ { name = "crbtfw21.tlv" }, ] }, { partition = "vendor", origin = "firmware", destination = "", files = [ { name = "ftm5_fw.ftb" }, ] }, { partition = "modem", origin = "image", destination = "qcom/sdm845/pixel3", files = [ { name = "mba.mbn" }, { name = "modem.mdt" }, { name = "modemr.jsn" }, ] }, ] droid-juicer-0.2.1/configs/oneplus,enchilada.toml000064400000000000000000000021071046102023000201230ustar 00000000000000[juicer] firmware = [ { partition = "vendor", origin = "firmware", destination = "qcom/sdm845/oneplus6", files = [ { name = "a630_zap.mdt" }, { name = "ipa_fws.mdt" }, ] }, { partition = "modem", origin = "image", destination = "qcom/sdm845/oneplus6", files = [ { name = "adsp.mdt" }, { name = "adspr.jsn" }, { name = "adspua.jsn" }, { name = "cdsp.mdt" }, { name = "cdspr.jsn" }, { name = "mba.mbn" }, { name = "modem.mdt" }, { name = "modemr.jsn" }, { name = "modemuw.jsn" }, { name = "slpi.mdt" }, { name = "slpir.jsn" }, { name = "slpius.jsn" }, { name = "venus.mdt" }, { name = "wlanmdsp.mbn" }, ] }, { partition = "bluetooth", origin = "image", destination = "qca/oneplus6", files = [ { name = "crnv21.bin" }, ] }, { partition = "bluetooth", origin = "image", destination = "qca", files = [ { name = "crbtfw21.tlv" }, ] }, ] droid-juicer-0.2.1/configs/oneplus,fajita.toml000064400000000000000000000023131046102023000174500ustar 00000000000000[juicer] firmware = [ { partition = "vendor", origin = "firmware", destination = "qcom/sdm845/oneplus6", files = [ { name = "a630_zap.mdt" }, { name = "ipa_fws.mdt" }, ] }, { partition = "vendor", origin = "etc/firmware", destination = "", files = [ { name = "tfa98xx.cnt" }, ] }, { partition = "modem", origin = "image", destination = "qcom/sdm845/oneplus6", files = [ { name = "adsp.mdt" }, { name = "adspr.jsn" }, { name = "adspua.jsn" }, { name = "cdsp.mdt" }, { name = "cdspr.jsn" }, { name = "mba.mbn" }, { name = "modem.mdt" }, { name = "modemr.jsn" }, { name = "modemuw.jsn" }, { name = "slpi.mdt" }, { name = "slpir.jsn" }, { name = "slpius.jsn" }, { name = "venus.mdt" }, { name = "wlanmdsp.mbn" }, ] }, { partition = "bluetooth", origin = "image", destination = "qca/oneplus6", files = [ { name = "crnv21.bin" }, ] }, { partition = "bluetooth", origin = "image", destination = "qca", files = [ { name = "crbtfw21.tlv" }, ] }, ] droid-juicer-0.2.1/configs/shift,axolotl.toml000064400000000000000000000021041046102023000173220ustar 00000000000000[juicer] firmware = [ { partition = "vendor", origin = "firmware", destination = "qcom/sdm845/axolotl", files = [ { name = "a630_zap.mdt" }, { name = "ipa_fws.mdt" }, ] }, { partition = "modem", origin = "image", destination = "qcom/sdm845/axolotl", files = [ { name = "adsp.mdt" }, { name = "adspr.jsn" }, { name = "adspua.jsn" }, { name = "cdsp.mdt" }, { name = "cdspr.jsn" }, { name = "mba.mbn" }, { name = "modem.mdt" }, { name = "modemr.jsn" }, { name = "modemuw.jsn" }, { name = "slpi.mdt" }, { name = "slpir.jsn" }, { name = "slpius.jsn" }, { name = "venus.mdt" }, { name = "wlanmdsp.mbn" }, ] }, { partition = "bluetooth", origin = "image", destination = "qca/axolotl", files = [ { name = "crnv21.bin" }, ] }, { partition = "bluetooth", origin = "image", destination = "qca", files = [ { name = "crbtfw21.tlv" }, ] }, ] droid-juicer-0.2.1/configs/xiaomi,beryllium-ebbg.toml000064400000000000000000000023201046102023000207120ustar 00000000000000[juicer] firmware = [ { partition = "vendor", origin = "firmware", destination = "qcom/sdm845/beryllium", files = [ { name = "a630_zap.mdt" }, { name = "ipa_fws.mdt" }, ] }, { partition = "vendor", origin = "firmware", destination = "", files = [ { name = "tas2559_uCDSP.bin" }, ] }, { partition = "modem", origin = "image", destination = "qcom/sdm845/beryllium", files = [ { name = "adsp.mdt" }, { name = "adspr.jsn" }, { name = "adspua.jsn" }, { name = "cdsp.mdt" }, { name = "cdspr.jsn" }, { name = "mba.mbn" }, { name = "modem.mdt" }, { name = "modemr.jsn" }, { name = "modemuw.jsn" }, { name = "slpi.mdt" }, { name = "slpir.jsn" }, { name = "slpius.jsn" }, { name = "venus.mdt" }, { name = "wlanmdsp.mbn" }, ] }, { partition = "bluetooth", origin = "image", destination = "qca/beryllium", files = [ { name = "crnv21.bin" }, ] }, { partition = "bluetooth", origin = "image", destination = "qca", files = [ { name = "crbtfw21.tlv" }, ] }, ] droid-juicer-0.2.1/configs/xiaomi,beryllium.toml000064400000000000000000000023201046102023000200150ustar 00000000000000[juicer] firmware = [ { partition = "vendor", origin = "firmware", destination = "qcom/sdm845/beryllium", files = [ { name = "a630_zap.mdt" }, { name = "ipa_fws.mdt" }, ] }, { partition = "vendor", origin = "firmware", destination = "", files = [ { name = "tas2559_uCDSP.bin" }, ] }, { partition = "modem", origin = "image", destination = "qcom/sdm845/beryllium", files = [ { name = "adsp.mdt" }, { name = "adspr.jsn" }, { name = "adspua.jsn" }, { name = "cdsp.mdt" }, { name = "cdspr.jsn" }, { name = "mba.mbn" }, { name = "modem.mdt" }, { name = "modemr.jsn" }, { name = "modemuw.jsn" }, { name = "slpi.mdt" }, { name = "slpir.jsn" }, { name = "slpius.jsn" }, { name = "venus.mdt" }, { name = "wlanmdsp.mbn" }, ] }, { partition = "bluetooth", origin = "image", destination = "qca/beryllium", files = [ { name = "crnv21.bin" }, ] }, { partition = "bluetooth", origin = "image", destination = "qca", files = [ { name = "crbtfw21.tlv" }, ] }, ] droid-juicer-0.2.1/configs/xiaomi,polaris.toml000064400000000000000000000023121046102023000174630ustar 00000000000000[juicer] firmware = [ { partition = "vendor", origin = "firmware", destination = "qcom/sdm845/polaris", files = [ { name = "a630_zap.mdt" }, { name = "ipa_fws.mdt" }, ] }, { partition = "vendor", origin = "firmware", destination = "", files = [ { name = "tas2559_uCDSP.bin" }, ] }, { partition = "modem", origin = "image", destination = "qcom/sdm845/polaris", files = [ { name = "adsp.mdt" }, { name = "adspr.jsn" }, { name = "adspua.jsn" }, { name = "cdsp.mdt" }, { name = "cdspr.jsn" }, { name = "mba.mbn" }, { name = "modem.mdt" }, { name = "modemr.jsn" }, { name = "modemuw.jsn" }, { name = "slpi.mdt" }, { name = "slpir.jsn" }, { name = "slpius.jsn" }, { name = "venus.mdt" }, { name = "wlanmdsp.mbn" }, ] }, { partition = "bluetooth", origin = "image", destination = "qca/polaris", files = [ { name = "crnv21.bin" }, ] }, { partition = "bluetooth", origin = "image", destination = "qca", files = [ { name = "crbtfw21.tlv" }, ] }, ] droid-juicer-0.2.1/droid-juicer.service000064400000000000000000000007611046102023000161520ustar 00000000000000[Unit] Description=Android vendor firmware extraction Wants=sysinit.target make-dynpart-mappings@super.service After=-.mount tmp.mount boot.mount make-dynpart-mappings@super.service Before=plymouth-quit.service display-manager.service ConditionPathExists=!/var/lib/droid-juicer/status.json [Service] Type=oneshot ExecStartPre=-/usr/bin/plymouth display-message --text="Extracting binary firmware..." ExecStart=/usr/bin/droid-juicer ExecStartPost=/usr/sbin/reboot [Install] WantedBy=basic.target droid-juicer-0.2.1/src/firmware.rs000064400000000000000000000174151046102023000151650ustar 00000000000000/* * Heavily based on https://github.com/andersson/pil-squasher/, and as such: * * Copyright (c) 2019, Linaro Ltd. * Copyright (c) 2022, Arnaud Ferraris. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ use std::{ fs, os::unix::prelude::FileExt, path::PathBuf }; use std::io::{ Error, ErrorKind, Read, Seek, SeekFrom }; use goblin::elf::Elf; use serde::{ Serialize, Deserialize }; use sys_mount::{Mount, MountFlags, Unmount, UnmountFlags}; const FLAGS_READ_MASK: u32 = 0x07000000; const FLAGS_MDT_VALUE: u32 = 0x02000000; #[derive(Deserialize)] pub struct FwFile { name: String, rename: Option, } #[derive(Deserialize)] pub struct FwConfig { partition: String, origin: String, destination: String, files: Vec, } #[derive(Deserialize)] pub struct Config { firmware: Vec } #[derive(Serialize, Deserialize)] pub struct Status { pub files: Vec, } #[derive(Serialize, Deserialize)] pub struct OldStatus { pub files: Vec, pub diversions: Option>, } fn mount_part(part: &str, mountpath: &PathBuf) -> Result { let _res = fs::DirBuilder::new().recursive(true).create(mountpath); let flags = MountFlags::RDONLY; let mut srcpath = PathBuf::from("/dev/mapper"); srcpath.push(part); if !srcpath.exists() { srcpath.set_file_name(format!("{}_a", part)); } if !srcpath.exists() { srcpath = PathBuf::from("/dev/disk/by-partlabel"); srcpath.push(part); } if !srcpath.exists() { srcpath.set_file_name(format!("{}_a", part)); } match Mount::builder().flags(flags).mount(&srcpath, mountpath) { Ok(m) => Ok(m), Err(e) => { if srcpath.ends_with("_a") { eprintln!("Unable to mount {} on {}: {}", srcpath.display(), mountpath.display(), e); srcpath.set_file_name(format!("{}_b", part)); println!("Mounting {} on {}", srcpath.display(), mountpath.display()); Mount::builder().flags(flags).mount(&srcpath, mountpath) } else { Err(e) } } } } fn squash_file(inpath: &PathBuf, outpath: &PathBuf) -> Result<(), Error> { let buffer = match fs::read(&inpath) { Ok(buf) => buf, Err(e) => { eprintln!("Unable to read {}: {}", inpath.display(), e); return Err(e); } }; let elf = match Elf::parse(buffer.as_slice()) { Ok(value) => value, Err(e) => { eprintln!("Unable to parse {}: {}", inpath.display(), e); return Err(Error::new(ErrorKind::InvalidData, e)); } }; let mut count = 0; let mut hashoffset = 0; let mut mdt_fd = fs::File::open(&inpath).unwrap(); let mbn_fd = fs::File::create(outpath).unwrap(); for ref phdr in elf.program_headers { if count == 0 { hashoffset = phdr.p_filesz; } count += 1; if phdr.p_filesz == 0 { continue; } let mut buffer: Vec = Vec::new(); if (phdr.p_flags & FLAGS_READ_MASK) == FLAGS_MDT_VALUE { let res = mdt_fd.seek(SeekFrom::Start(hashoffset)); if let Ok(_seek) = res { buffer.resize(phdr.p_filesz as usize, Default::default()); let _res = mdt_fd.read_exact(buffer.as_mut_slice()); } } if buffer.len() == 0 { let mut bxx_name = inpath.clone(); bxx_name.set_extension(format!("b{:#02}", count - 1)); let mut bxx_fd = fs::File::open(&bxx_name).unwrap(); bxx_fd.read_to_end(&mut buffer).unwrap(); } if buffer.len() != phdr.p_filesz as usize { let err_str = format!("Read {} bytes (!= {})", buffer.len(), phdr.p_filesz); return Err(Error::new(ErrorKind::UnexpectedEof, err_str)); } mbn_fd.write_at(buffer.as_slice(), phdr.p_offset).unwrap(); } Ok(()) } pub fn process(config: Config) -> Result { let mut files: Vec = Vec::new(); for entry in config.firmware { let mut destpath = PathBuf::from("/lib/firmware/updates"); destpath.push(entry.destination); if let Err(e) = fs::create_dir_all(&destpath) { eprintln!("Warning: unable to create folder {}: {}", destpath.display(), e); continue; } let mut mntpath = PathBuf::from("/tmp"); mntpath.push(entry.partition.as_str()); match mount_part(entry.partition.as_str(), &mntpath) { Ok(m) => { for file in entry.files { let mut origin = PathBuf::from(&mntpath); origin.push(&entry.origin); origin.push(&file.name); if !origin.exists() { eprintln!("Warning: unable to find {} on partition {}", file.name, entry.partition); continue; } let mut destination = PathBuf::from(&destpath); if let Some(new_name) = file.rename { destination.push(&new_name); } else { destination.push(&file.name); } if file.name.ends_with(".mdt") { destination.set_extension("mbn"); if let Err(e) = squash_file(&origin, &destination) { eprintln!("Warning: unable to squash {} to {}: {}", origin.display(), destination.display(), e); continue; } } else { if let Err(e) = fs::copy(&origin, &destination) { eprintln!("Warning: unable to copy {} to {}: {}", origin.display(), destination.display(), e); continue; } } files.push(format!("{}", destination.display())); } let _res = m.unmount(UnmountFlags::empty()); }, Err(e) => return Err(e), } let _r = fs::remove_dir(mntpath); } Ok(Status { files }) } droid-juicer-0.2.1/src/main.rs000064400000000000000000000122441046102023000142700ustar 00000000000000mod firmware; mod utils; use std::{ fs, path::PathBuf }; use std::io::{ Error, ErrorKind}; use clap::Parser; use serde::Deserialize; use uname; const STATUS_FILE_PATH: &str = "/var/lib/droid-juicer/status.json"; const CONFIG_DIR_PATH: &str = "/usr/share/droid-juicer/configs"; const CONFIG_FILE_PATH: &str = "/etc/droid-juicer/config.toml"; #[derive(Parser)] #[command(about = "Extract firmware from Android vendor partitions")] struct Opt { /// Device type (default: auto-detect) #[arg(short, long)] device: Option, /// Remove previously extracted files #[arg(short, long)] cleanup: bool, } #[derive(Deserialize)] struct Config { juicer: firmware::Config, } #[derive(Deserialize, Default)] struct PostProcessConfig { commands: Vec, } #[derive(Deserialize, Default)] struct MainConfig { postprocess: PostProcessConfig, } fn detect_device() -> Result { let contents = match fs::read_to_string("/proc/device-tree/compatible") { Ok(str) => str, _ => Default::default(), }; let compatibles: Vec<&str> = contents.split("\0").filter(|s| s.len() > 0).collect(); for entry in fs::read_dir(CONFIG_DIR_PATH) { for file in entry { let fname = match file { Ok(dirent) => dirent.file_name(), _ => continue, }; for value in compatibles.clone() { let full_name = String::from(value) + ".toml"; if &fname == full_name.as_str() { return Ok(value.to_string()); } } } } Err(Error::new(ErrorKind::NotFound, "Unable to detect device!")) } fn main() -> Result<(), Error> { let opt = Opt::parse(); let mut main_config = MainConfig::default(); let device = match opt.device { Some(str) => str, _ => match detect_device() { Ok(s) => s, Err(e) => return Err(e) }, }; let krel = match uname::uname() { Ok(u) => u.release, _ => { eprintln!("Warning: unable to detect running kernel release!"); String::from("all") }, }; if PathBuf::from(CONFIG_FILE_PATH).exists() { match fs::read_to_string(CONFIG_FILE_PATH) { Ok(contents) => main_config = toml::from_str(contents.as_str()).unwrap(), _ => (), } } if opt.cleanup { println!("Cleaning up files for device {}", device); if let Ok(f) = fs::File::open(STATUS_FILE_PATH) { let old_status: Option = match serde_json::from_reader(&f) { Ok(s) => Some(s), Err(_) => None }; let status: firmware::Status = match old_status { Some(s) => { if let Some(d) = s.diversions { for diversion in d { if let Err(e) = utils::undivert(&PathBuf::from(&diversion)) { eprintln!("Warning: unable to remove diversion for {}: {}", diversion, e); } } } firmware::Status { files: s.files } }, _ => match serde_json::from_reader(f) { Ok(s) => s, Err(e) => return Err(Error::new(ErrorKind::Other, e)) }, }; for file in status.files { if let Err(e) = fs::remove_file(&file) { eprintln!("Warning: unable to remove {}: {}", file, e); } } if let Err(e) = fs::remove_file(STATUS_FILE_PATH) { eprintln!("Warning: unable to remove {}: {}", STATUS_FILE_PATH, e); } } } else { println!("Starting processing for device {}", device); let mut cfg_path = PathBuf::from(CONFIG_DIR_PATH); cfg_path.push(&device); cfg_path.set_extension("toml"); let contents = match fs::read_to_string(cfg_path) { Ok(str) => str, _ => "".to_string(), }; let config: Config = toml::from_str(contents.as_str()).unwrap(); let status = match firmware::process(config.juicer) { Ok(s) => s, Err(e) => return Err(e) }; if let Err(e) = fs::create_dir_all("/var/lib/droid-juicer/") { return Err(e); } if let Ok(f) = fs::File::create(STATUS_FILE_PATH) { if let Err(e) = serde_json::to_writer_pretty(f, &status) { return Err(Error::new(ErrorKind::Other, e)); } } } for cmdline in main_config.postprocess.commands { let full_cmd = cmdline.replace("%k", krel.as_str()); let mut cmd = full_cmd.split(" ").collect::>(); if cmd.is_empty() { continue; } let args_list = cmd.split_off(1); let args = match args_list.is_empty() { true => None, _ => Some(args_list), }; if let Err(e) = utils::execute(cmd[0], args) { return Err(e); } } Ok(()) } droid-juicer-0.2.1/src/utils.rs000064400000000000000000000020501046102023000144760ustar 00000000000000use std::{ process::Command, path::PathBuf }; use std::io::{ Error, ErrorKind, Write }; pub fn execute(command: &str, arguments: Option>) -> Result<(), Error> { let mut exe = Command::new(&command); if let Some(args) = arguments { exe.args(args); } let res = exe.output(); if let Ok(out) = res { std::io::stdout().write_all(&out.stdout).unwrap(); if out.status.success() { Ok(()) } else { std::io::stderr().write_all(&out.stderr).unwrap(); let err_str = format!("{} returned with exit code {}", command, out.status); Err(Error::new(ErrorKind::Other, err_str)) } } else { let err_str = format!("{}: unable to execute command!", command); Err(Error::new(ErrorKind::Other, err_str)) } } pub fn undivert(file: &PathBuf) -> Result<(), Error> { let orig = format!("{}", file.display()); let args = vec!["--package", "droid-juicer", "--rename", "--remove", &orig ]; execute("/usr/bin/dpkg-divert", Some(args)) }