diff --git a/Cargo.lock b/Cargo.lock index 6a2bfbe..080ae12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,12 +26,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - [[package]] name = "anstream" version = "0.6.18" @@ -73,26 +67,26 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.8" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", - "once_cell_polyfill", + "once_cell", "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" dependencies = [ "proc-macro2", "quote", @@ -107,9 +101,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.75" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", "cfg-if", @@ -122,15 +116,15 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.9.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "bstr" -version = "1.12.0" +version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" +checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" dependencies = [ "memchr", "serde", @@ -138,15 +132,9 @@ dependencies = [ [[package]] name = "bytes" -version = "1.10.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" - -[[package]] -name = "bytesize" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3c8f83209414aacf0eeae3cf730b18d6981697fba62f200fcfb92b9f082acba" +checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" [[package]] name = "cfg-if" @@ -162,9 +150,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "clap" -version = "4.5.39" +version = "4.5.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" +checksum = "92b7b18d71fad5313a1e320fa9897994228ce274b60faa4d694fe0ea89cd9e6d" dependencies = [ "clap_builder", "clap_derive", @@ -172,9 +160,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.39" +version = "4.5.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" +checksum = "a35db2071778a7344791a4fb4f95308b5673d219dee3ae348b86642574ecc90c" dependencies = [ "anstream", "anstyle", @@ -184,9 +172,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.32" +version = "4.5.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" dependencies = [ "heck", "proc-macro2", @@ -243,14 +231,14 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.8" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" dependencies = [ "anstream", "anstyle", "env_filter", - "jiff", + "humantime", "log", ] @@ -266,12 +254,6 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - [[package]] name = "gimli" version = "0.31.1" @@ -280,9 +262,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "globset" -version = "0.4.16" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" dependencies = [ "aho-corasick", "bstr", @@ -293,9 +275,9 @@ dependencies = [ [[package]] name = "goblin" -version = "0.10.0" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e961b33649994dcf69303af6b3a332c1228549e604d455d61ec5d2ab5e68d3a" +checksum = "daa0a64d21a7eb230583b4c5f4e23b7e4e57974f96620f42a7e75e08ae66d745" dependencies = [ "log", "plain", @@ -304,14 +286,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.3" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", -] +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -319,6 +296,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "ignore" version = "0.4.23" @@ -337,9 +320,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown", @@ -347,9 +330,9 @@ dependencies = [ [[package]] name = "indoc" -version = "2.0.6" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "is_terminal_polyfill" @@ -357,41 +340,17 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" -[[package]] -name = "jiff" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93" -dependencies = [ - "jiff-static", - "log", - "portable-atomic", - "portable-atomic-util", - "serde", -] - -[[package]] -name = "jiff-static" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "libc" -version = "0.2.172" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -399,9 +358,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.27" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "memchr" @@ -420,29 +379,29 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.8" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +checksum = "b3b1c9bd4fe1f0f8b387f6eb9eb3b4a1aa26185e5750efb9140301703f62cd1b" dependencies = [ "adler2", ] [[package]] name = "mio" -version = "1.0.4" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "wasi", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] name = "nix" -version = "0.30.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ "bitflags", "cfg-if", @@ -460,16 +419,16 @@ dependencies = [ ] [[package]] -name = "once_cell_polyfill" -version = "1.70.1" +name = "once_cell" +version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -477,9 +436,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", @@ -490,14 +449,12 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.8.1" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a98c6720655620a521dcc722d0ad66cd8afd5d86e34a89ef691c50b7b24de06" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset", - "hashbrown", "indexmap", - "serde", ] [[package]] @@ -512,44 +469,29 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" -[[package]] -name = "portable-atomic" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" - -[[package]] -name = "portable-atomic-util" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" -dependencies = [ - "portable-atomic", -] - [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" -version = "0.5.12" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags", ] @@ -606,18 +548,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "scroll" -version = "0.13.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1257cd4248b4132760d6524d6dda4e053bc648c9070b960929bf50cfb1e7add" +checksum = "6ab8598aa408498679922eff7fa985c25d58a90771bd6be794434c5277eab1a6" dependencies = [ "scroll_derive", ] [[package]] name = "scroll_derive" -version = "0.13.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22fc4f90c27b57691bbaf11d8ecc7cfbfe98a4da6dbe60226115d322aa80c06e" +checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932" dependencies = [ "proc-macro2", "quote", @@ -626,18 +568,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -646,24 +588,24 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.5" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] [[package]] name = "smallvec" -version = "1.15.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" [[package]] name = "socket2" -version = "0.5.10" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -677,9 +619,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.101" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -688,11 +630,10 @@ dependencies = [ [[package]] name = "sysroot-cleaner" -version = "0.9.0" +version = "0.1.0" dependencies = [ "anyhow", "async-trait", - "bytesize", "clap", "env_logger", "goblin", @@ -708,9 +649,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.45.1" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", @@ -737,9 +678,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" [[package]] name = "utf8parse" diff --git a/Cargo.toml b/Cargo.toml index 6c0af43..53bc72a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "sysroot-cleaner" authors = ["Matteo Settenvini "] -version = "0.9.0" +version = "0.1.0" edition = "2024" license = "EUPL-1.2" readme = "README.md" @@ -16,11 +16,10 @@ clap = { version = "4.5", features = ["derive"] } env_logger = { version = "0.11" } ignore = { version = "0.4" } indoc = { version = "2.0" } -goblin = { version = "0.10" } +goblin = { version = "0.9" } log = { version = "0.4" } memmap2 = { version = "0.9" } -nix = { version = "0.30", features = ["fs"] } -petgraph = { version = "0.8" } +nix = { version = "0.29", features = ["fs"] } +petgraph = { version = "0.7" } tokio = { version = "1", features = ["full"] } walkdir = { version = "2" } -bytesize = { version = "2.0" } diff --git a/src/args.rs b/src/args.rs index aa4d8ac..af165ae 100644 --- a/src/args.rs +++ b/src/args.rs @@ -3,30 +3,7 @@ use std::path::PathBuf; -use clap::{ - builder::{PathBufValueParser, TypedValueParser}, - Parser, -}; - -#[derive(Clone, Default)] -struct AbsolutePathBufValueParser; - -impl TypedValueParser for AbsolutePathBufValueParser { - type Value = PathBuf; - - fn parse_ref( - &self, - cmd: &clap::Command, - arg: Option<&clap::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - let pathbuf_parser = PathBufValueParser::new(); - let v = pathbuf_parser.parse_ref(cmd, arg, value)?; - - v.canonicalize() - .map_err(|e| clap::Error::raw(clap::error::ErrorKind::Io, e)) - } -} +use clap::Parser; /// A tool to clean up sysroots for Linux embedded devices to save storage space. #[derive(Parser, Debug)] @@ -42,15 +19,13 @@ pub struct Args { pub split_to: Option, /// An allowlist of files to keep, in .gitignore format. - /// Can be passed multiple times. /// Note: this will take precedence over all other removal decisions. - #[arg(long, value_parser = AbsolutePathBufValueParser::default())] - pub allowlist: Vec, + #[arg(long)] + pub allowlist: Option, /// A blocklist of files to remove, in .gitignore format. - /// Can be passed multiple times. #[arg(long)] - pub blocklist: Vec, + pub blocklist: Option, /// An optional path to save the file graph of the DSO cleaner /// in GraphViz format. Useful for debugging. @@ -59,20 +34,4 @@ pub struct Args { /// The location of the sysroot to clean up pub sysroot_location: PathBuf, - - /// An additional path to consider when resolving - /// libraries, relative to the sysroot. - /// Their behavior is similar of the one of the - /// `LD_LIBRARY_PATH` environment variable when - /// specified to the dynamic linker. - #[arg(long = "ld-path", value_parser = relativize_path)] - pub extra_library_paths: Vec, -} - -fn relativize_path(arg: &str) -> anyhow::Result { - let mut p = PathBuf::from(arg); - if p.is_absolute() { - p = p.strip_prefix("/")?.into(); - } - Ok(p) } diff --git a/src/cleaners.rs b/src/cleaners.rs index 124f6e5..925937e 100644 --- a/src/cleaners.rs +++ b/src/cleaners.rs @@ -10,11 +10,10 @@ use crate::{ }; use anyhow::{Error, Result}; use async_trait::async_trait; -use bytesize::ByteSize; use dso::DsoCleaner; use list::ListCleaner; use nix::libc::EXDEV; -use std::{collections::HashMap, fmt, io, ops::AddAssign, path::Path}; +use std::{collections::HashMap, io, path::Path}; use tokio::{sync::mpsc, task::JoinSet}; use walkdir::{DirEntry, WalkDir}; @@ -27,22 +26,8 @@ pub trait Cleaner { ) -> Result<()>; } -struct FileSize(u64); - -impl fmt::Display for FileSize { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", ByteSize(self.0)) - } -} - -impl AddAssign for FileSize { - fn add_assign(&mut self, rhs: Self) { - self.0.add_assign(rhs.0); - } -} - type Cleaners = Vec>; -type RemovalFn = Box io::Result>; +type RemovalFn = Box io::Result<()>>; pub struct Runner { cleaners: Cleaners, @@ -56,18 +41,15 @@ impl Runner { let removal_fn = Self::new_removal_fn(&args); let mut cleaners: Cleaners = vec![]; - for wl in args.allowlist { + if let Some(wl) = args.allowlist { cleaners.push(Box::new(ListCleaner::new(list::ListType::Allow, wl))); } - for bl in args.blocklist { + if let Some(bl) = args.blocklist { cleaners.push(Box::new(ListCleaner::new(list::ListType::Block, bl))); } - cleaners.push(Box::new(DsoCleaner::new( - args.extra_library_paths, - args.output_dotfile, - ))); + cleaners.push(Box::new(DsoCleaner::new(args.output_dotfile))); Self { cleaners, @@ -147,8 +129,6 @@ impl Runner { async fn final_decision(removal_fn: RemovalFn, mut output_rx: mpsc::Receiver) { let mut final_decisions = HashMap::new(); - let mut total_removed_size = FileSize(0); - while let Some(input_decision) = output_rx.recv().await { if input_decision.action == Action::Undecided { continue; @@ -167,76 +147,48 @@ impl Runner { for (file, action) in final_decisions { if action == Action::Remove { - let removed_size = match (removal_fn)(&file) { - Ok(size) => size, - Err(err) => { - log::error!("{}: {}", file.display(), err); - FileSize(0) - } - }; - total_removed_size += removed_size; + if let Err(err) = (removal_fn)(&file) { + log::error!("{}: {}", file.display(), err); + } } } - log::info!("Total space removed: {}", total_removed_size); } fn new_removal_fn(args: &Args) -> RemovalFn { if let Some(dest) = args.split_to.clone() { if args.dry_run { Box::new(move |path| { - let size = Self::get_file_size(path)?; log::info!( - "(dry-run) would move {} to {} ({})", + "(dry-run) would move {} to {}", path.display(), - dest.display(), - size + dest.display() ); - Ok(size) + Ok(()) }) } else { Box::new(move |path| { - let size = Self::get_file_size(path)?; - log::info!("moving {} to {} ({})", path.display(), dest.display(), size); - Self::move_preserve(path, &dest)?; - Ok(size) + log::info!("moving {} to {}", path.display(), dest.display()); + Self::move_preserve(&path, &dest) }) } - } else if args.dry_run { - Box::new(|path| { - let ty = if path.is_symlink() { - "symlink" - } else { - "regular file" - }; - let size = Self::get_file_size(path)?; - log::info!( - "(dry-run) would remove {} {} ({})", - ty, - path.display(), - size - ); - Ok(size) - }) } else { - Box::new(move |path| { - let size = Self::get_file_size(path)?; - log::info!("removing {} ({})", path.display(), size); - std::fs::remove_file(path)?; - Ok(size) - }) - } - } - - fn get_file_size(file: &Path) -> io::Result { - let lstat = nix::sys::stat::lstat(file); - let size = match lstat { - Err(err) => { - log::error!("failed to get metadata from: {}, {}", file.display(), err); - FileSize(0) + if args.dry_run { + Box::new(|path| { + let ty = if path.is_symlink() { + "symlink" + } else { + "regular file" + }; + log::info!("(dry-run) would remove {} {}", ty, path.display()); + Ok(()) + }) + } else { + Box::new(move |path| { + log::info!("removing {}", path.display()); + std::fs::remove_file(&path) + }) } - Ok(lstat) => FileSize(lstat.st_size as u64), - }; - Ok(size) + } } fn move_preserve(src: &Path, dest: &Path) -> io::Result<()> { @@ -245,7 +197,7 @@ impl Runner { if let Some(parent) = abs_dest.parent() { std::fs::create_dir_all(parent)?; } - match std::fs::rename(src, &abs_dest) { + match std::fs::rename(&src, &abs_dest) { Err(err) if err.raw_os_error() == Some(EXDEV) => { log::trace!( "different filesystems, falling back to copying {} to {}", diff --git a/src/cleaners/dso.rs b/src/cleaners/dso.rs index 87b8b9f..7aea0fe 100644 --- a/src/cleaners/dso.rs +++ b/src/cleaners/dso.rs @@ -27,22 +27,17 @@ type InodeGraph = DiGraphMap; /// Cleans up unused shared libraries /// and warns about broken dependencies as well pub struct DsoCleaner { - extra_library_paths: Vec, output_dot: Option, } struct State { - ld_library_path: Vec, paths_map: InodeMap, graph: InodeGraph, } impl DsoCleaner { - pub fn new(extra_library_paths: Vec, output_dot: Option) -> Self { - Self { - extra_library_paths, - output_dot, - } + pub fn new(output_dot: Option) -> Self { + Self { output_dot } } } @@ -57,11 +52,6 @@ impl Cleaner for DsoCleaner { output: mpsc::Sender, ) -> Result<()> { let mut state = State::default(); - state.ld_library_path = self - .extra_library_paths - .iter() - .map(|p| p.to_str().unwrap().to_owned()) - .collect(); let mut inodes_to_keep = HashSet::new(); inodes_to_keep.insert(ROOT_NODE); @@ -72,7 +62,7 @@ impl Cleaner for DsoCleaner { // that also its dependencies will not be kept. if decision.action != Action::Remove { state.process_path(&decision.path).unwrap_or_else(|e| { - log::error!( + log::warn!( "{}: {} (this might produce wrong results!)", decision.path.display(), e @@ -102,12 +92,12 @@ impl Cleaner for DsoCleaner { } if let Some(dot) = &self.output_dot { - state.debug_print_graph(dot)?; + state.debug_print_graph(&dot)?; } let mut dfs = Dfs::empty(&state.graph); dfs.stack = inodes_to_keep.into_iter().collect(); - while dfs.next(&state.graph).is_some() {} + while let Some(_) = dfs.next(&state.graph) {} for (inode, paths) in state.paths_map.into_iter() { let action = if !dfs.discovered.contains(&inode) { @@ -137,11 +127,7 @@ impl Default for State { paths_map.insert(ROOT_NODE, HashSet::from([fake_root_node])); graph.add_node(ROOT_NODE); - Self { - ld_library_path: vec![], - paths_map, - graph, - } + Self { paths_map, graph } } } @@ -173,7 +159,7 @@ impl State { } let current_dir = std::env::current_dir()?; - let mut dst_path = fs::read_link(path)?; + let mut dst_path = std::fs::read_link(path)?; if dst_path.is_absolute() { dst_path = dst_path.strip_prefix("/")?.into(); } else { @@ -210,13 +196,11 @@ impl State { self.update_graph("".into(), ROOT_NODE, path.to_owned(), src.st_ino); } - let search_paths = self.determine_lib_search_paths(path, elf)?; - log::trace!("determined search paths {:#?}", search_paths); + let search_paths = determine_lib_search_paths(path, elf)?; 'next_lib: for &library in elf.libraries.iter() { for lib_path in search_paths.iter() { - assert!(Path::new(&lib_path).is_relative()); - let tentative_path = PathBuf::from(lib_path).join(library); + let tentative_path = PathBuf::from(lib_path).strip_prefix("/")?.join(library); let dst = match nix::sys::stat::lstat(&tentative_path) { Ok(dst) => dst, Err(Errno::ENOENT) => continue, @@ -235,11 +219,7 @@ impl State { continue 'next_lib; } - log::warn!( - "{}: unable to find library {}, ignoring (this might produce wrong results)!", - path.display(), - library - ); + anyhow::bail!("{}: unable to find library {}", path.display(), library); } Ok(()) @@ -277,7 +257,7 @@ impl State { {:?} }}" }, - dot::Dot::with_attr_getters( + petgraph::dot::Dot::with_attr_getters( &self.graph, &[ dot::Config::NodeNoLabel, @@ -287,12 +267,10 @@ impl State { &|_, _| { String::new() }, &|_, n| { let paths = self.paths_map.get(&n.id()).unwrap(); - let first_path = paths.iter().next().unwrap_or_else(|| { - panic!( - "dso: you have a path map with an empty entry for inode {}", - n.id() - ) - }); + let first_path = paths.iter().next().expect(&format!( + "dso: you have a path map with an empty entry for inode {}", + n.id() + )); format!( "label = \"({}, {})\"", n.weight(), @@ -306,45 +284,60 @@ impl State { )?; Ok(()) } - - // Contract: only relative paths starting from the sysroot dir should be returned from this function - fn determine_lib_search_paths(&self, path: &Path, elf: &Elf<'_>) -> Result> { - log::trace!( - "{}: elf.runpaths = {:#?}, elf.rpaths = {:#?}", - path.display(), - elf.runpaths, - elf.rpaths - ); - - let current_dir = std::env::current_dir()?; - let origin = fs::canonicalize(path)? - .parent() - .unwrap() - .strip_prefix(current_dir)? - .to_path_buf() - .into_os_string() - .into_string() - .map_err(|s| anyhow::anyhow!("cannot represent {:?} as a UTF-8 string", s))?; - - let mut search_paths = vec![]; - if elf.runpaths.is_empty() { - search_paths.extend(collect_paths(&elf.rpaths, &origin)); - } - - search_paths.extend(self.ld_library_path.clone()); - search_paths.extend(collect_paths(&elf.runpaths, &origin)); - search_paths.extend(["usr/local/lib".into(), "lib".into(), "usr/lib".into()]); - Ok(search_paths) - } } -fn collect_paths(elf_paths: &Vec<&str>, origin: &str) -> impl Iterator { - elf_paths - .iter() - .flat_map(|&p| p.split(':')) // Split multiple elements in r(un)?path separated by ':' - .filter(|&p| !p.is_empty()) // ignore empty items - .map(|p| p.replace("$ORIGIN", origin)) // replace $ORIGIN with path rel to sysroot - .map(|p| p.trim_start_matches('/').to_string()) // relativize paths from sysroot +fn determine_lib_search_paths(path: &Path, elf: &Elf<'_>) -> Result> { + let mut search_paths = vec![]; + + let current_dir = std::env::current_dir()?; + let origin = std::fs::canonicalize(path)? + .parent() + .unwrap() + .strip_prefix(current_dir)? + .to_path_buf() + .into_os_string() + .into_string() + .map_err(|s| anyhow::anyhow!("cannot represent {:?} as a UTF-8 string", s))?; + + if elf.rpaths != vec![""] { + if elf.runpaths != vec![""] { + let mut rpaths = elf + .rpaths + .iter() + .map(|p| p.replace("$ORIGIN", &origin)) + .collect::>(); + search_paths.append(&mut rpaths); + } + + search_paths.append(&mut get_env_library_paths()); + } + + if elf.runpaths != vec![""] { + let mut runpaths = elf + .runpaths + .iter() + .map(|p| p.replace("$ORIGIN", &origin)) + .collect::>(); + search_paths.append(&mut runpaths); + } + + search_paths.push("/usr/local/lib".into()); + search_paths.push("/lib".into()); + search_paths.push("/usr/lib".into()); + Ok(search_paths) +} + +fn get_env_library_paths() -> Vec { + let ld_config_path = std::env::var("LD_LIBRARY_PATH"); + ld_config_path + .as_ref() + .map(|env| { + env.split(':') + .filter(|s| s.is_empty()) + .map(|s| s.into()) + .collect() + }) + .unwrap_or_default() } fn is_elf(f: &mut File) -> Result {