fix: disconnect VPN when sleep/shutdown

This commit is contained in:
Kevin Yue 2025-01-12 14:41:03 +08:00
parent ec85e857bc
commit 9740231910
No known key found for this signature in database
GPG Key ID: 4D3A6EE977B15AC4
18 changed files with 285 additions and 172 deletions

294
Cargo.lock generated
View File

@ -141,7 +141,7 @@ checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -205,14 +205,14 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "axum"
version = "0.7.9"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
checksum = "6d6fd624c75e18b3b4c6b9caf42b1afe24437daaee904069137d8bab077be8b8"
dependencies = [
"async-trait",
"axum-core",
"base64 0.22.1",
"bytes",
"form_urlencoded",
"futures-util",
"http",
"http-body",
@ -242,11 +242,10 @@ dependencies = [
[[package]]
name = "axum-core"
version = "0.4.5"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
checksum = "df1362f362fd16024ae199c1970ce98f9661bf5ef94b9808fee734bc3698b733"
dependencies = [
"async-trait",
"bytes",
"futures-util",
"http",
@ -296,9 +295,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.6.0"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be"
dependencies = [
"serde",
]
@ -381,7 +380,7 @@ version = "0.18.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"cairo-sys-rs",
"glib",
"libc",
@ -429,24 +428,24 @@ dependencies = [
"semver",
"serde",
"serde_json",
"thiserror 2.0.10",
"thiserror 2.0.11",
]
[[package]]
name = "cargo_toml"
version = "0.17.2"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a969e13a7589e9e3e4207e153bae624ade2b5622fb4684a4923b23ec3d57719"
checksum = "5fbd1fe9db3ebf71b89060adaf7b0504c2d6a425cf061313099547e382c2e472"
dependencies = [
"serde",
"toml 0.8.2",
"toml 0.8.19",
]
[[package]]
name = "cc"
version = "1.2.7"
version = "1.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7"
checksum = "ad0cf6e91fde44c773c6ee7ec6bba798504641a8bc2eb7e37a04ffbf4dfaa55a"
dependencies = [
"shlex",
]
@ -546,9 +545,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.25"
version = "4.5.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b95dca1b68188a08ca6af9d96a6576150f598824bdb528c1190460c2940a0b48"
checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783"
dependencies = [
"clap_builder",
"clap_derive",
@ -566,9 +565,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.25"
version = "4.5.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ab52925392148efd3f7562f2136a81ffb778076bcc85727c6e020d6dd57cf15"
checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121"
dependencies = [
"anstream",
"anstyle",
@ -585,7 +584,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -600,7 +599,7 @@ version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f79398230a6e2c08f5c9760610eb6924b52aa9e7950a619602baba59dcbbdbb2"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"block",
"cocoa-foundation",
"core-foundation 0.10.0",
@ -616,7 +615,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14045fb83be07b5acf1c0884b2180461635b433455fa35d1cd6f17f1450679d"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"block",
"core-foundation 0.10.0",
"core-graphics-types",
@ -709,7 +708,7 @@ version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"core-foundation 0.10.0",
"core-graphics-types",
"foreign-types 0.5.0",
@ -722,7 +721,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"core-foundation 0.10.0",
"libc",
]
@ -839,7 +838,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
dependencies = [
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -849,7 +848,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501"
dependencies = [
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -873,7 +872,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -884,7 +883,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -913,7 +912,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustc_version",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -970,7 +969,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -993,7 +992,7 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -1059,7 +1058,7 @@ dependencies = [
"cc",
"memchr",
"rustc_version",
"toml 0.8.2",
"toml 0.8.19",
"vswhom",
"winreg",
]
@ -1214,7 +1213,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -1304,7 +1303,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -1530,7 +1529,7 @@ version = "0.18.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"futures-channel",
"futures-core",
"futures-executor",
@ -1554,11 +1553,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc"
dependencies = [
"heck 0.4.1",
"proc-macro-crate 2.0.2",
"proc-macro-crate 2.0.0",
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -1615,7 +1614,7 @@ dependencies = [
"specta",
"tauri",
"tempfile",
"thiserror 2.0.10",
"thiserror 2.0.11",
"tokio",
"url",
"urlencoding",
@ -1753,7 +1752,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -2110,7 +2109,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -2186,7 +2185,7 @@ version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fddf93031af70e75410a2511ec04d49e758ed2f26dad3404a934e0fb45cc12a"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"crossterm",
"dyn-clone",
"fuzzy-matcher",
@ -2332,7 +2331,7 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"serde",
"unicode-segmentation",
]
@ -2402,7 +2401,7 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"libc",
"redox_syscall",
]
@ -2493,9 +2492,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
[[package]]
name = "matchit"
version = "0.7.3"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
[[package]]
name = "md5"
@ -2600,7 +2599,7 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"jni-sys",
"log",
"ndk-sys",
@ -2684,10 +2683,10 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
dependencies = [
"proc-macro-crate 2.0.2",
"proc-macro-crate 3.2.0",
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -2724,7 +2723,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"block2",
"libc",
"objc2",
@ -2740,7 +2739,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"block2",
"objc2",
"objc2-core-location",
@ -2764,7 +2763,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"block2",
"objc2",
"objc2-foundation",
@ -2806,7 +2805,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"block2",
"libc",
"objc2",
@ -2830,7 +2829,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"block2",
"objc2",
"objc2-foundation",
@ -2842,7 +2841,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"block2",
"objc2",
"objc2-foundation",
@ -2865,7 +2864,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"block2",
"objc2",
"objc2-cloud-kit",
@ -2897,7 +2896,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"block2",
"objc2",
"objc2-core-location",
@ -2910,7 +2909,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68bc69301064cebefc6c4c90ce9cba69225239e4b8ff99d445a2b5563797da65"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"block2",
"objc2",
"objc2-app-kit",
@ -2964,7 +2963,7 @@ version = "0.10.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"cfg-if",
"foreign-types 0.3.2",
"libc",
@ -2981,7 +2980,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -3182,7 +3181,7 @@ dependencies = [
"phf_shared 0.11.3",
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -3300,12 +3299,20 @@ dependencies = [
[[package]]
name = "proc-macro-crate"
version = "2.0.2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24"
checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8"
dependencies = [
"toml_datetime",
"toml_edit 0.20.2",
"toml_edit 0.20.7",
]
[[package]]
name = "proc-macro-crate"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
dependencies = [
"toml_edit 0.22.22",
]
[[package]]
@ -3340,9 +3347,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]]
name = "proc-macro2"
version = "1.0.92"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
dependencies = [
"unicode-ident",
]
@ -3492,7 +3499,7 @@ version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
]
[[package]]
@ -3623,7 +3630,7 @@ version = "0.38.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"errno",
"libc",
"linux-raw-sys",
@ -3632,9 +3639,9 @@ dependencies = [
[[package]]
name = "rustls"
version = "0.23.20"
version = "0.23.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b"
checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8"
dependencies = [
"once_cell",
"rustls-pki-types",
@ -3723,7 +3730,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -3738,7 +3745,7 @@ version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"core-foundation 0.9.4",
"core-foundation-sys",
"libc",
@ -3812,7 +3819,7 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -3823,7 +3830,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -3866,7 +3873,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -3917,7 +3924,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -4133,7 +4140,7 @@ dependencies = [
"Inflector",
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -4210,9 +4217,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.95"
version = "2.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a"
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
dependencies = [
"proc-macro2",
"quote",
@ -4236,7 +4243,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -4259,7 +4266,7 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"core-foundation 0.9.4",
"system-configuration-sys",
]
@ -4283,7 +4290,7 @@ dependencies = [
"cfg-expr",
"heck 0.5.0",
"pkg-config",
"toml 0.8.2",
"toml 0.8.19",
"version-compare",
]
@ -4293,7 +4300,7 @@ version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3731d04d4ac210cd5f344087733943b9bfb1a32654387dad4d1c70de21aee2c9"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.7.0",
"cocoa",
"core-foundation 0.10.0",
"core-graphics",
@ -4333,7 +4340,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -4355,9 +4362,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]]
name = "tauri"
version = "2.2.0"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e2e3349fbb2be7af9fad1b43d61ac83ba55ab48d47fbe1b2732f0c8211610a9"
checksum = "b2133243fd7dc4932bac10ad18d45043e5cdb69e1bbd1df6f57336ad2c372cca"
dependencies = [
"anyhow",
"bytes",
@ -4392,7 +4399,7 @@ dependencies = [
"tauri-runtime",
"tauri-runtime-wry",
"tauri-utils",
"thiserror 2.0.10",
"thiserror 2.0.11",
"tokio",
"tray-icon",
"url",
@ -4405,9 +4412,9 @@ dependencies = [
[[package]]
name = "tauri-build"
version = "2.0.4"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b274ec7239ada504deb615f1c8abd7ba99631e879709e6f10e5d17217058d976"
checksum = "8e950124f6779c6cf98e3260c7a6c8488a74aa6350dd54c6950fdaa349bca2df"
dependencies = [
"anyhow",
"cargo_toml",
@ -4421,7 +4428,7 @@ dependencies = [
"serde_json",
"tauri-utils",
"tauri-winres",
"toml 0.8.2",
"toml 0.8.19",
"walkdir",
]
@ -4443,9 +4450,9 @@ dependencies = [
"serde",
"serde_json",
"sha2",
"syn 2.0.95",
"syn 2.0.96",
"tauri-utils",
"thiserror 2.0.10",
"thiserror 2.0.11",
"time",
"url",
"uuid",
@ -4461,7 +4468,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
"tauri-codegen",
"tauri-utils",
]
@ -4480,7 +4487,7 @@ dependencies = [
"serde",
"serde_json",
"tauri-utils",
"thiserror 2.0.10",
"thiserror 2.0.11",
"url",
"windows 0.58.0",
]
@ -4540,8 +4547,8 @@ dependencies = [
"serde_json",
"serde_with",
"swift-rs",
"thiserror 2.0.10",
"toml 0.8.2",
"thiserror 2.0.11",
"toml 0.8.19",
"url",
"urlpattern",
"uuid",
@ -4600,11 +4607,11 @@ dependencies = [
[[package]]
name = "thiserror"
version = "2.0.10"
version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3ac7f54ca534db81081ef1c1e7f6ea8a3ef428d2fc069097c079443d24124d3"
checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
dependencies = [
"thiserror-impl 2.0.10",
"thiserror-impl 2.0.11",
]
[[package]]
@ -4615,18 +4622,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
name = "thiserror-impl"
version = "2.0.10"
version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e9465d30713b56a37ede7185763c3492a91be2f5fa68d958c44e41ab9248beb"
checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -4702,7 +4709,6 @@ dependencies = [
"bytes",
"libc",
"mio 1.0.3",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
@ -4718,7 +4724,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -4743,9 +4749,9 @@ dependencies = [
[[package]]
name = "tokio-tungstenite"
version = "0.24.0"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9"
checksum = "be4bf6fecd69fcdede0ec680aaf474cdab988f9de6bc73d3758f0160e3b7025a"
dependencies = [
"futures-util",
"log",
@ -4780,21 +4786,21 @@ dependencies = [
[[package]]
name = "toml"
version = "0.8.2"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d"
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit 0.20.2",
"toml_edit 0.22.22",
]
[[package]]
name = "toml_datetime"
version = "0.6.3"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
dependencies = [
"serde",
]
@ -4809,20 +4815,31 @@ dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
"winnow 0.5.40",
]
[[package]]
name = "toml_edit"
version = "0.20.2"
version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338"
checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81"
dependencies = [
"indexmap 2.7.0",
"toml_datetime",
"winnow 0.5.40",
]
[[package]]
name = "toml_edit"
version = "0.22.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
dependencies = [
"indexmap 2.7.0",
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
"winnow 0.6.24",
]
[[package]]
@ -4902,9 +4919,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "tungstenite"
version = "0.24.0"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a"
checksum = "413083a99c579593656008130e29255e54dcaae495be556cc26888f211648c24"
dependencies = [
"byteorder",
"bytes",
@ -4914,7 +4931,7 @@ dependencies = [
"log",
"rand 0.8.5",
"sha1",
"thiserror 1.0.69",
"thiserror 2.0.11",
"utf-8",
]
@ -5067,9 +5084,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.11.0"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a"
checksum = "b913a3b5fe84142e269d63cc62b64319ccaf89b748fc31fe025177f767a756c4"
dependencies = [
"getrandom 0.2.15",
"serde",
@ -5181,7 +5198,7 @@ dependencies = [
"log",
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
"wasm-bindgen-shared",
]
@ -5216,7 +5233,7 @@ checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -5334,7 +5351,7 @@ checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -5478,7 +5495,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -5489,7 +5506,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -5500,7 +5517,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -5511,7 +5528,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -5849,6 +5866,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "winnow"
version = "0.6.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a"
dependencies = [
"memchr",
]
[[package]]
name = "winreg"
version = "0.52.0"
@ -5909,7 +5935,7 @@ dependencies = [
"sha2",
"soup3",
"tao-macros",
"thiserror 2.0.10",
"thiserror 2.0.11",
"url",
"webkit2gtk",
"webkit2gtk-sys",
@ -5981,7 +6007,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
"synstructure",
]
@ -6003,7 +6029,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]
[[package]]
@ -6023,7 +6049,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
"synstructure",
]
@ -6052,5 +6078,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.95",
"syn 2.0.96",
]

View File

@ -1,7 +1,13 @@
[workspace]
resolver = "2"
members = ["crates/*", "apps/gpclient", "apps/gpservice", "apps/gpauth", "apps/gpgui-helper/src-tauri"]
members = [
"crates/*",
"apps/gpclient",
"apps/gpservice",
"apps/gpauth",
"apps/gpgui-helper/src-tauri",
]
[workspace.package]
rust-version = "1.80"
@ -31,11 +37,11 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
sysinfo = "0.33"
tempfile = "3.8"
tokio = { version = "1", features = ["full"] }
tokio = { version = "1" }
tokio-util = "0.7"
url = "2.4"
urlencoding = "2.1.3"
axum = "0.7"
axum = "0.8"
futures = "0.3"
futures-util = "0.3"
uzers = "0.12"

View File

@ -130,6 +130,10 @@ install:
install -Dm755 .build/gpgui/gpgui_*/gpgui $(DESTDIR)/usr/bin/gpgui; \
fi
# Install the sleep/shutdown scripts
install -Dm755 packaging/files/usr/lib/systemd/system-sleep/gpclient $(DESTDIR)/usr/lib/systemd/system-sleep/gpclient
install -Dm755 packaging/files/usr/lib/systemd/system-shutdown/gpclient $(DESTDIR)/usr/lib/systemd/system-shutdown/gpclient
install -Dm644 packaging/files/usr/share/applications/gpgui.desktop $(DESTDIR)/usr/share/applications/gpgui.desktop
install -Dm644 packaging/files/usr/share/icons/hicolor/scalable/apps/gpgui.svg $(DESTDIR)/usr/share/icons/hicolor/scalable/apps/gpgui.svg
install -Dm644 packaging/files/usr/share/icons/hicolor/32x32/apps/gpgui.png $(DESTDIR)/usr/share/icons/hicolor/32x32/apps/gpgui.png
@ -146,6 +150,9 @@ uninstall:
rm -f $(DESTDIR)/usr/bin/gpgui-helper
rm -f $(DESTDIR)/usr/bin/gpgui
rm -f $(DESTDIR)/usr/lib/systemd/system-sleep/gpclient
rm -f $(DESTDIR)/usr/lib/systemd/system-shutdown/gpclient
rm -f $(DESTDIR)/usr/share/applications/gpgui.desktop
rm -f $(DESTDIR)/usr/share/icons/hicolor/scalable/apps/gpgui.svg
rm -f $(DESTDIR)/usr/share/icons/hicolor/32x32/apps/gpgui.png

View File

@ -16,7 +16,7 @@ clap.workspace = true
env_logger.workspace = true
inquire = "0.7"
log.workspace = true
tokio.workspace = true
tokio = { workspace = true, features = ["rt-multi-thread"] }
sysinfo.workspace = true
serde_json.workspace = true
whoami.workspace = true

View File

@ -1,6 +1,7 @@
use crate::GP_CLIENT_LOCK_FILE;
use gpapi::GP_SERVICE_LOCK_FILE;
use log::{info, warn};
use std::fs;
use std::{fs, str::FromStr, thread, time::Duration};
use sysinfo::{Pid, Signal, System};
pub(crate) struct DisconnectHandler;
@ -11,21 +12,40 @@ impl DisconnectHandler {
}
pub(crate) fn handle(&self) -> anyhow::Result<()> {
if fs::metadata(GP_CLIENT_LOCK_FILE).is_err() {
warn!("PID file not found, maybe the client is not running");
return Ok(());
if let Ok(c) = fs::read_to_string(GP_CLIENT_LOCK_FILE) {
send_signal(c.trim(), Signal::Interrupt).unwrap_or_else(|err| {
warn!("Failed to send signal to client: {}", err);
});
};
if let Ok(c) = fs::read_to_string(GP_SERVICE_LOCK_FILE) {
c.split(':').next().map_or_else(
|| info!("Failed to extract PID from: {}", c),
|pid| {
send_signal(pid, Signal::User1).unwrap_or_else(|err| {
warn!("Failed to send signal to service: {}", err);
});
},
);
};
// sleep for 3 seconds to give the client and service time to shut down
thread::sleep(Duration::from_secs(3));
Ok(())
}
}
let pid = fs::read_to_string(GP_CLIENT_LOCK_FILE)?;
let pid = pid.trim().parse::<usize>()?;
fn send_signal(pid: &str, signal: Signal) -> anyhow::Result<()> {
let s = System::new_all();
let pid = Pid::from_str(pid)?;
if let Some(process) = s.process(Pid::from(pid)) {
info!("Found process {}, killing...", pid);
if process.kill_with(Signal::Interrupt).is_none() {
if let Some(process) = s.process(pid) {
info!("Found process {}, sending signal...", pid);
if process.kill_with(signal).is_none() {
warn!("Failed to kill process {}", pid);
}
}
Ok(())
}
}

View File

@ -9,7 +9,7 @@ gpapi = { path = "../../crates/gpapi", features = ["clap", "logger"] }
openconnect = { path = "../../crates/openconnect" }
clap.workspace = true
anyhow.workspace = true
tokio.workspace = true
tokio = { workspace = true, features = ["rt-multi-thread"] }
tokio-util.workspace = true
axum = { workspace = true, features = ["ws"] }
futures.workspace = true

View File

@ -38,7 +38,8 @@ impl Cli {
let redaction = self.init_logger();
info!("gpservice started: {}", VERSION);
let lock_file = Arc::new(LockFile::new(GP_SERVICE_LOCK_FILE));
let pid = std::process::id();
let lock_file = Arc::new(LockFile::new(GP_SERVICE_LOCK_FILE, pid));
if lock_file.check_health().await {
bail!("Another instance of the service is already running");
@ -56,9 +57,10 @@ impl Cli {
let (shutdown_tx, mut shutdown_rx) = mpsc::channel::<()>(4);
let shutdown_tx_clone = shutdown_tx.clone();
let vpn_task_token = vpn_task.cancel_token();
let vpn_task_cancel_token = vpn_task.cancel_token();
let server_token = ws_server.cancel_token();
let vpn_cxt = vpn_task.context();
let vpn_task_handle = tokio::spawn(async move { vpn_task.start(server_token).await });
let ws_server_handle = tokio::spawn(async move { ws_server.start(shutdown_tx_clone).await });
@ -81,6 +83,26 @@ impl Cli {
});
}
// Handle SIGUSR1 signal to disconnect the VPN
#[cfg(unix)]
tokio::spawn(async move {
use tokio::signal::unix::{signal, SignalKind};
let mut sig = match signal(SignalKind::user_defined1()) {
Ok(sig) => sig,
Err(err) => {
warn!("Failed to create signal: {}", err);
return;
}
};
loop {
sig.recv().await;
info!("Received SIGUSR1 signal");
vpn_cxt.disconnect().await;
}
});
tokio::select! {
_ = shutdown_signal() => {
info!("Shutdown signal received");
@ -90,7 +112,7 @@ impl Cli {
}
}
vpn_task_token.cancel();
vpn_task_cancel_token.cancel();
let _ = tokio::join!(vpn_task_handle, ws_server_handle);
lock_file.unlock()?;

View File

@ -1,5 +1,4 @@
use std::{
borrow::Cow,
fs::{File, Permissions},
io::BufReader,
ops::ControlFlow,
@ -12,7 +11,7 @@ use anyhow::bail;
use axum::{
body::Bytes,
extract::{
ws::{self, CloseFrame, Message, WebSocket},
ws::{self, CloseFrame, Message, Utf8Bytes, WebSocket},
State, WebSocketUpgrade,
},
http::StatusCode,
@ -133,7 +132,7 @@ async fn handle_socket(mut socket: WebSocket, ctx: Arc<WsServerContext>) {
let close_msg = Message::Close(Some(CloseFrame {
code: ws::close_code::NORMAL,
reason: Cow::from("Goodbye"),
reason: Utf8Bytes::from("Goodbye"),
}));
if let Err(err) = sender.send(close_msg).await {

View File

@ -146,6 +146,10 @@ impl VpnTask {
server_cancel_token.cancel();
}
pub fn context(&self) -> Arc<VpnTaskContext> {
return Arc::clone(&self.ctx);
}
async fn recv(&mut self) {
while let Some(req) = self.ws_req_rx.recv().await {
tokio::spawn(process_ws_req(req, self.ctx.clone()));

View File

@ -20,7 +20,7 @@ impl WsConnection {
pub async fn send_event(&self, event: &WsEvent) -> anyhow::Result<()> {
let encrypted = self.crypto.encrypt(event)?;
let msg = Message::Binary(encrypted);
let msg = Message::Binary(encrypted.into());
self.tx.send(msg).await?;
@ -29,7 +29,7 @@ impl WsConnection {
pub fn recv_msg(&self, msg: Message) -> ControlFlow<(), WsRequest> {
match msg {
Message::Binary(data) => match self.crypto.decrypt(data) {
Message::Binary(data) => match self.crypto.decrypt(data.into()) {
Ok(ws_req) => ControlFlow::Continue(ws_req),
Err(err) => {
info!("Failed to decrypt message: {}", err);

View File

@ -124,7 +124,7 @@ impl WsServer {
warn!("Failed to start WS server: {}", err);
let _ = shutdown_tx.send(()).await;
return;
},
}
};
tokio::select! {
@ -149,7 +149,7 @@ impl WsServer {
info!("WS server listening on port: {}", port);
self.lock_file.lock(port.to_string())?;
self.lock_file.lock(&port.to_string())?;
Ok(listener)
}

View File

@ -18,7 +18,7 @@ roxmltree.workspace = true
serde.workspace = true
specta = { workspace = true, features = ["derive"] }
urlencoding.workspace = true
tokio.workspace = true
tokio = { workspace = true, features = ["process", "signal", "macros"] }
serde_json.workspace = true
whoami.workspace = true
tempfile.workspace = true

View File

@ -3,8 +3,13 @@ use tokio::fs;
use crate::GP_SERVICE_LOCK_FILE;
async fn read_port() -> anyhow::Result<String> {
let port = fs::read_to_string(GP_SERVICE_LOCK_FILE).await?;
Ok(port.trim().to_string())
// PID:PORT
let lock_content = fs::read_to_string(GP_SERVICE_LOCK_FILE).await?;
let port = lock_content
.split(':')
.last()
.ok_or_else(|| anyhow::anyhow!("Invalid lock file content"))?;
Ok(port.to_string())
}
pub async fn http_endpoint() -> anyhow::Result<String> {

View File

@ -2,18 +2,20 @@ use std::path::PathBuf;
pub struct LockFile {
path: PathBuf,
pid: u32,
}
impl LockFile {
pub fn new<P: Into<PathBuf>>(path: P) -> Self {
Self { path: path.into() }
pub fn new<P: Into<PathBuf>>(path: P, pid: u32) -> Self {
Self { path: path.into(), pid }
}
pub fn exists(&self) -> bool {
self.path.exists()
}
pub fn lock(&self, content: impl AsRef<[u8]>) -> anyhow::Result<()> {
pub fn lock(&self, content: &str) -> anyhow::Result<()> {
let content = format!("{}:{}", self.pid, content);
std::fs::write(&self.path, content)?;
Ok(())
}

View File

@ -10,6 +10,10 @@ install:
install -Dm755 artifacts/usr/bin/gpgui $(DESTDIR)/usr/bin/gpgui; \
fi
# Install the sleep/shutdown scripts
install -Dm755 artifacts/usr/lib/systemd/system-sleep/gpclient $(DESTDIR)/usr/lib/systemd/system-sleep/gpclient
install -Dm755 artifacts/usr/lib/systemd/system-shutdown/gpclient $(DESTDIR)/usr/lib/systemd/system-shutdown/gpclient
install -Dm644 artifacts/usr/share/applications/gpgui.desktop $(DESTDIR)/usr/share/applications/gpgui.desktop
install -Dm644 artifacts/usr/share/icons/hicolor/scalable/apps/gpgui.svg $(DESTDIR)/usr/share/icons/hicolor/scalable/apps/gpgui.svg
install -Dm644 artifacts/usr/share/icons/hicolor/32x32/apps/gpgui.png $(DESTDIR)/usr/share/icons/hicolor/32x32/apps/gpgui.png
@ -26,6 +30,9 @@ uninstall:
rm -f $(DESTDIR)/usr/bin/gpgui-helper
rm -f $(DESTDIR)/usr/bin/gpgui
rm -f $(DESTDIR)/usr/lib/systemd/system-sleep/gpclient
rm -f $(DESTDIR)/usr/lib/systemd/system-shutdown/gpclient
rm -f $(DESTDIR)/usr/share/applications/gpgui.desktop
rm -f $(DESTDIR)/usr/share/icons/hicolor/scalable/apps/gpgui.svg
rm -f $(DESTDIR)/usr/share/icons/hicolor/32x32/apps/gpgui.png

View File

@ -0,0 +1,3 @@
#!/bin/sh
/usr/bin/gpclient disconnect

View File

@ -0,0 +1,5 @@
#!/bin/sh
if [ "${1}" == "pre" ]; then
/usr/bin/gpclient disconnect
fi

View File

@ -60,6 +60,13 @@ make build OFFLINE=@OFFLINE@ BUILD_FE=0
%{_datadir}/icons/hicolor/scalable/apps/gpgui.svg
%{_datadir}/polkit-1/actions/com.yuezk.gpgui.policy
%dir /usr/lib/systemd
%dir /usr/lib/systemd/system-sleep
%dir /usr/lib/systemd/system-shutdown
/usr/lib/systemd/system-sleep/gpclient
/usr/lib/systemd/system-shutdown/gpclient
%dir %{_datadir}/icons/hicolor
%dir %{_datadir}/icons/hicolor/32x32
%dir %{_datadir}/icons/hicolor/32x32/apps