dbus-udisks2-0.3.0/.cargo_vcs_info.json0000644000000001360000000000100133530ustar { "git": { "sha1": "22742e0db693f347f082e83db2c3ec3342e5501c" }, "path_in_vcs": "" }dbus-udisks2-0.3.0/.gitignore000064400000000000000000000000361046102023000141320ustar 00000000000000/target **/*.rs.bk Cargo.lock dbus-udisks2-0.3.0/Cargo.lock0000644000000313160000000000100113320ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bytes" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "dbus" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f8bcdd56d2e5c4ed26a529c5a9029f5db8290d433497506f958eae3be148eb6" dependencies = [ "futures-channel", "futures-util", "libc", "libdbus-sys", "winapi", ] [[package]] name = "dbus-tokio" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12a1a74a0c53b22d7d994256cf3ecbeefa5eedce3cf9d362945ac523c4132180" dependencies = [ "dbus", "libc", "tokio", ] [[package]] name = "dbus-udisks2" version = "0.3.0" dependencies = [ "dbus", "dbus-tokio", "futures-util", "num_enum", "tokio", ] [[package]] name = "futures-channel" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" dependencies = [ "futures-core", ] [[package]] name = "futures-core" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" [[package]] name = "futures-macro" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "futures-task" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" [[package]] name = "futures-util" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ "futures-core", "futures-macro", "futures-task", "pin-project-lite", "pin-utils", "slab", ] [[package]] name = "hermit-abi" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "libc", ] [[package]] name = "libc" version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "libdbus-sys" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c185b5b7ad900923ef3a8ff594083d4d9b5aea80bb4f32b8342363138c0d456b" dependencies = [ "pkg-config", ] [[package]] name = "lock_api" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", ] [[package]] name = "log" version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "mio" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ "libc", "log", "wasi", "windows-sys", ] [[package]] name = "num_cpus" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", ] [[package]] name = "num_enum" version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", "syn", ] [[package]] name = "once_cell" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "parking_lot" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-sys", ] [[package]] name = "pin-project-lite" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "proc-macro-crate" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" dependencies = [ "once_cell", "thiserror", "toml", ] [[package]] name = "proc-macro2" version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" [[package]] name = "signal-hook-registry" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" dependencies = [ "libc", ] [[package]] name = "slab" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" dependencies = [ "autocfg", ] [[package]] name = "smallvec" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "socket2" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi", ] [[package]] name = "syn" version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "thiserror" version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tokio" version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" dependencies = [ "autocfg", "bytes", "libc", "memchr", "mio", "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", "winapi", ] [[package]] name = "tokio-macros" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "toml" version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] [[package]] name = "unicode-ident" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[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.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" [[package]] name = "windows_aarch64_msvc" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_i686_gnu" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_msvc" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" [[package]] name = "windows_x86_64_gnu" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" [[package]] name = "windows_x86_64_gnullvm" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_msvc" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" dbus-udisks2-0.3.0/Cargo.toml0000644000000022640000000000100113550ustar # 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 = "dbus-udisks2" version = "0.3.0" authors = ["Michael Aaron Murphy "] description = "UDisks2 DBus API" readme = "README.md" license = "MIT OR Apache-2.0" repository = "https://github.com/pop-os/dbus-udisks2" [package.metadata.docs.rs] all-features = true [dependencies.dbus] version = "0.9.6" [dependencies.futures-util] version = "0.3" features = ["async-await"] optional = true [dependencies.num_enum] version = "0.5.7" [dev-dependencies.dbus-tokio] version = "0.7.5" [dev-dependencies.futures-util] version = "0.3" features = ["async-await"] [dev-dependencies.tokio] version = "1.21.2" features = ["full"] [features] futures = [ "dbus/futures", "futures-util", ] dbus-udisks2-0.3.0/Cargo.toml.orig0000644000000011660000000000100123140ustar [package] name = "dbus-udisks2" version = "0.3.0" edition = "2021" description = "UDisks2 DBus API" repository = "https://github.com/pop-os/dbus-udisks2" authors = ["Michael Aaron Murphy "] license = "MIT OR Apache-2.0" [dependencies] dbus = "0.9.6" num_enum = "0.5.7" futures-util = { version = "0.3", features = ["async-await"], optional = true } [dev-dependencies] tokio = { version = "1.21.2", features = ["full"] } futures-util = { version = "0.3", features = ["async-await"]} dbus-tokio = "0.7.5" [features] futures = ["dbus/futures", "futures-util"] [package.metadata.docs.rs] all-features = true dbus-udisks2-0.3.0/Cargo.toml.orig000064400000000000000000000011661046102023000150360ustar 00000000000000[package] name = "dbus-udisks2" version = "0.3.0" edition = "2021" description = "UDisks2 DBus API" repository = "https://github.com/pop-os/dbus-udisks2" authors = ["Michael Aaron Murphy "] license = "MIT OR Apache-2.0" [dependencies] dbus = "0.9.6" num_enum = "0.5.7" futures-util = { version = "0.3", features = ["async-await"], optional = true } [dev-dependencies] tokio = { version = "1.21.2", features = ["full"] } futures-util = { version = "0.3", features = ["async-await"]} dbus-tokio = "0.7.5" [features] futures = ["dbus/futures", "futures-util"] [package.metadata.docs.rs] all-features = true dbus-udisks2-0.3.0/LICENSE-APACHE000064400000000000000000000261121046102023000140710ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2019 System76 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. dbus-udisks2-0.3.0/LICENSE-MIT000064400000000000000000000020511046102023000135750ustar 00000000000000MIT License Copyright (c) 2018 System76 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. dbus-udisks2-0.3.0/README.md000064400000000000000000000003301046102023000134160ustar 00000000000000# dbus-udisks2 A Rust API for interacting the UDisks2 DBus API. Currently provides access to information on blocks and drives, as well as [S.M.A.R.T. data][SMART]. [SMART]: https://en.wikipedia.org/wiki/S.M.A.R.T. dbus-udisks2-0.3.0/examples/example.rs000064400000000000000000000013131046102023000157600ustar 00000000000000use dbus_udisks2::{Disks, UDisks2}; use std::env::args; fn main() { match args().nth(1) { Some(ref device) => print_block(device), None => print(), } } fn print() { let udisks2 = UDisks2::new().unwrap(); let disks = Disks::new(&udisks2); for device in disks.devices { println!("{:#?}", device); if let Ok(smart_data) = udisks2.smart_attributes(&device.drive, true) { println!("{:#?}", smart_data); } } } fn print_block(block_name: &str) { let udisks2 = UDisks2::new().unwrap(); for block in udisks2.get_blocks() { if block.device.to_str().unwrap() == block_name { println!("{:#?}", block); } } } dbus-udisks2-0.3.0/src/block.rs000064400000000000000000000444601046102023000144020ustar 00000000000000use crate::utils::*; use crate::DbusObjects; use dbus::arg::RefArg; use std::path::PathBuf; #[derive(Clone, Debug, Default)] pub struct Block { pub crypto_backing_device: String, pub device_number: u64, pub device: PathBuf, pub drive: String, pub encrypted: Option, pub hint_auto: bool, pub hint_icon_name: Option, pub hint_ignore: bool, pub hint_name: Option, pub hint_partitionable: bool, pub hint_symbolic_icon_name: Option, pub hint_system: bool, pub id_label: Option, pub id_type: Option, pub id_usage: Option, pub id_uuid: Option, pub id_version: Option, pub id: String, pub loopback: bool, pub mdraid: PathBuf, pub mdraid_member: PathBuf, pub mount_points: Vec, pub partition: Option, pub path: String, pub preferred_device: PathBuf, pub read_only: bool, pub size: u64, pub swapspace: Option, pub symlinks: Vec, pub table: Option, pub userspace_mount_options: Vec, pub configuration: Option, } impl Block { /// This will be true if this block contains an encrypted volume. pub fn is_encrypted(&self) -> bool { self.encrypted.is_some() } /// If this block contains an encrypted volume, find the block associated with it. pub fn get_encrypted_block<'a>(&self, within: &'a [Block]) -> Option<&'a Block> { if self.encrypted.is_some() { within.iter().find(|b| b.crypto_backing_device == self.path) } else { None } } } impl ParseFrom for Block { fn parse_from(path: &str, objects: &DbusObjects) -> Option { if objects.get("org.freedesktop.UDisks2.Loop").is_some() { return None; } let mut block = Block::default(); block.path = path.to_owned(); match objects.get("org.freedesktop.UDisks2.Block") { Some(object) => { for (key, ref value) in object { match key.as_str() { "CryptoBackingDevice" => { block.crypto_backing_device = get_string(value).unwrap() } "Device" => block.device = PathBuf::from(get_byte_array(value).unwrap()), "DeviceNumber" => block.device_number = get_u64(value), "Drive" => block.drive = get_string(value).unwrap(), "HintAuto" => block.hint_auto = get_bool(value), "HintIconName" => block.hint_icon_name = get_string(value), "HintIgnore" => block.hint_ignore = get_bool(value), "HintName" => block.hint_name = get_string(value), "HintPartitionable" => block.hint_partitionable = get_bool(value), "HintSymbolicIconName" => block.hint_symbolic_icon_name = get_string(value), "HintSystem" => block.hint_system = get_bool(value), "Id" => block.id = get_string(value).unwrap_or_default(), "IdLabel" => block.id_label = get_string(value), "IdType" => block.id_type = get_string(value), "IdUsage" => block.id_usage = get_string(value), "IdUUID" => block.id_uuid = get_string(value), "IdVersion" => block.id_version = get_string(value), "MDRaid" => { block.mdraid = get_string(value).map(PathBuf::from).unwrap_or_default() } "MDRaidMember" => { block.mdraid_member = get_string(value).map(PathBuf::from).unwrap_or_default() } "PreferredDevice" => { block.preferred_device = PathBuf::from(get_byte_array(value).unwrap()) } "ReadOnly" => block.read_only = get_bool(value), "Size" => block.size = get_u64(value), "Symlinks" => { block.symlinks = get_array_of_byte_arrays(value) .map(|paths| { paths.into_iter().map(PathBuf::from).collect::>() }) .unwrap_or_default() } "UserspaceMountOptions" => { block.userspace_mount_options = get_string_array(value).unwrap_or_default() } "Configuration" => { let mut configuration = BlockConfiguration::default(); for value in value.as_iter().unwrap() { if let Some(mut iterator) = value.as_iter() { if let Some(mut iterator) = iterator.next().and_then(|i| i.as_iter()) { if let (Some(key), Some(mut array)) = ( iterator.next(), iterator.next().and_then(|i| i.as_iter()), ) { if let Some(key) = key.as_str() { if key == "fstab" { while let (Some(key), Some(value)) = (array.next(), array.next()) { if let Some(key) = key.as_str() { match key { "fsname" => { configuration.fstab.fsname = vva(value) .unwrap_or_default() } "dir" => { configuration.fstab.dir = vva(value) .unwrap_or_default() } "type" => { configuration.fstab.type_ = vva(value) .unwrap_or_default() } "opts" => { configuration.fstab.opts = vva(value) .unwrap_or_default() } "freq" => { configuration.fstab.freq = value .as_u64() .unwrap_or_default() as i32 } "passno" => { configuration.fstab.passno = value .as_u64() .unwrap_or_default() as i32 } _ => { eprintln!("unhandled block config fstab key: {:?}, {:?}", key, value); } } } } } else if key == "crypttab" { while let (Some(key), Some(value)) = (array.next(), array.next()) { if let Some(key) = key.as_str() { match key { "name" => { configuration.crypttab.name = vva(value) .unwrap_or_default() } "device" => { configuration.crypttab.device = vva(value) .unwrap_or_default() } "passphrase-path" => { configuration .crypttab .passphrase_path = vva(value) .unwrap_or_default() } "options" => { configuration.crypttab.options = vva(value) .unwrap_or_default() } _ => { eprintln!("unhandled block config crypttab key: {:?}, {:?}", key, value); } } } } } else { eprintln!("unknown block config key: {}", key); } } } } } } block.configuration = Some(configuration); } _ => { #[cfg(debug_assertions)] eprintln!("unhandled org.freedesktop.UDisks2.Block.{}", key); eprintln!("value: {:#?}", value); } } } } None => return None, } for (key, object) in objects { match key.as_str() { "org.freedesktop.UDisks2.Block" => (), "org.freedesktop.UDisks2.Swapspace" => { block.swapspace = Some(object.get("Active").map_or(false, get_bool)); } "org.freedesktop.UDisks2.PartitionTable" => { let mut table = PartitionTable::default(); for (key, ref value) in object { match key.as_str() { "Type" => table.type_ = get_string(value).unwrap_or_default(), "Partitions" => { table.partitions = get_string_array(value).unwrap_or_default(); table.partitions.sort_unstable(); } _ => { #[cfg(debug_assertions)] eprintln!( "unhandled org.freedesktop.UDisks2.PartitionTable.{}", key ); } } } block.table = Some(table); } "org.freedesktop.UDisks2.Partition" => { let mut partition = Partition::default(); for (key, value) in object { match key.as_str() { "Type" => partition.type_ = get_string(value).unwrap_or_default(), "Name" => partition.name = get_string(value).unwrap_or_default(), "UUID" => partition.uuid = get_string(value).unwrap_or_default(), "Table" => { partition.table = get_string(value).expect("partition is not part of a table") } "Flags" => partition.flags = get_u64(value), "Offset" => partition.offset = get_u64(value), "Size" => partition.size = get_u64(value), "Number" => partition.number = get_u64(value) as u32, "IsContained" => partition.is_contained = get_bool(value), "IsContainer" => partition.is_container = get_bool(value), _ => { #[cfg(debug_assertions)] eprintln!("unhandled org.freedesktop.UDisks2.Partition.{}", key); } } } block.partition = Some(partition); } "org.freedesktop.UDisks2.Filesystem" => { block.mount_points = object .get("MountPoints") .and_then(get_array_of_byte_arrays) .map(|paths| paths.into_iter().map(PathBuf::from).collect::>()) .unwrap_or_default() } "org.freedesktop.UDisks2.Encrypted" => { let mut encrypted = Encrypted::default(); for (key, ref value) in object { match key.as_str() { "HintEncryptionType" => { encrypted.hint_encryption_type = get_string(value).unwrap_or_default() } "MetadataSize" => encrypted.metadata_size = get_u64(value), "CleartextDevice" => { encrypted.cleartext_device = get_string(value).unwrap_or_default() } _ => { #[cfg(debug_assertions)] eprintln!("unhandled org.freedesktop.UDisks2.Encrypted.{}", key); } } } block.encrypted = Some(encrypted); } _ => { #[cfg(debug_assertions)] eprintln!("unhandled org.freedesktop.UDisks2.{}", key); } } } Some(block) } } #[derive(Clone, Debug, Default)] pub struct BlockConfiguration { pub fstab: BlockConfigurationFstab, pub crypttab: BlockConfigurationCrypttab, } #[derive(Clone, Debug, Default)] pub struct BlockConfigurationFstab { pub fsname: String, pub dir: String, pub type_: String, pub opts: String, pub freq: i32, pub passno: i32, } #[derive(Clone, Debug, Default)] pub struct BlockConfigurationCrypttab { pub name: String, pub device: String, pub passphrase_path: String, pub options: String, } #[derive(Clone, Debug, Default)] pub struct Encrypted { pub hint_encryption_type: String, pub metadata_size: u64, pub cleartext_device: String, } #[derive(Clone, Debug, Default)] pub struct PartitionTable { pub type_: String, // Partitions are listed by their dbus paths. pub partitions: Vec, } #[derive(Clone, Debug, Default)] pub struct Partition { // Defines the file system by a type UUID. pub type_: String, // An optional label that may be applied to a disk. pub name: String, // Points to the dbus path that this partition exists within. pub table: String, pub flags: u64, pub number: u32, pub offset: u64, pub size: u64, pub uuid: String, pub is_container: bool, pub is_contained: bool, } dbus-udisks2-0.3.0/src/disks.rs000064400000000000000000000037171046102023000144250ustar 00000000000000use super::*; /// All of UDisks2's disk information collected into a convenient wrapper. #[derive(Debug, Default, Clone)] pub struct Disks { pub devices: Vec, } /// A collection of UDisks2 drives and their associated blocks. /// /// # Implementation Details /// - Block partitions are sorted by their physical offsets. #[derive(Debug, Default, Clone)] pub struct DiskDevice { pub drive: Drive, pub parent: Block, pub partitions: Vec, } impl Disks { fn new_cache(udisks2: &DiskCache) -> Self { let mut devices = Vec::new(); let mut blocks = Vec::new(); for block in udisks2.get_blocks() { blocks.push(block); } for drive in udisks2.get_drives() { let mut partitions = Vec::new(); let mut parent = None; for block in blocks.iter().filter(|b| b.drive == drive.path) { if block.table.is_some() { parent = Some(block.to_owned()); } else { partitions.push(block.to_owned()); } } if let Some(parent) = parent { partitions.sort_unstable_by_key(|p| p.partition.as_ref().unwrap().offset); devices.push(DiskDevice { drive, parent, partitions, }); } else if partitions.len() == 1 { // An unpartitioned drive should have only one Block devices.push(DiskDevice { drive, parent: partitions.into_iter().next().unwrap(), partitions: vec![], }); } } Disks { devices } } pub fn new(udisks2: &UDisks2) -> Self { Disks::new_cache(&udisks2.cache) } #[cfg(feature = "futures")] pub fn new_async(udisks2: &crate::AsyncUDisks2) -> Self { Disks::new_cache(&udisks2.cache) } } dbus-udisks2-0.3.0/src/drive.rs000064400000000000000000000076311046102023000144200ustar 00000000000000use crate::utils::*; use crate::DbusObjects; #[derive(Clone, Debug, Default)] pub struct Drive { pub can_power_off: bool, pub connection_bus: String, pub ejectable: bool, pub id: String, pub media_available: bool, pub media_change_detected: bool, pub media_compatibility: Vec, pub media_removable: bool, pub media: Option, pub model: String, pub optical: bool, pub optical_blank: bool, pub optical_num_tracks: u64, pub optical_num_audio_tracks: u64, pub optical_num_data_tracks: u64, pub optical_num_sessions: u64, pub path: String, pub removable: bool, pub revision: String, pub rotation_rate: i64, pub seat: String, pub serial: String, pub sibling_id: String, pub size: u64, pub sort_key: String, pub time_detected: u64, pub time_media_detected: u64, pub vendor: String, pub wwn: String, } impl ParseFrom for Drive { fn parse_from(path: &str, objects: &DbusObjects) -> Option { if let Some(object) = objects.get("org.freedesktop.UDisks2.Drive") { let mut drive = Drive::default(); drive.path = path.to_owned(); drive.parse(object); Some(drive) } else { None } } } impl Drive { fn parse(&mut self, objects: &KeyVariant) { for (key, ref value) in objects { match key.as_str() { "CanPowerOff" => self.can_power_off = get_bool(value), "ConnectionBus" => self.connection_bus = get_string(value).unwrap_or_default(), "Ejectable" => self.ejectable = get_bool(value), "Id" => self.id = get_string(value).unwrap_or_default(), "Media" => self.media = get_string(value), "MediaAvailable" => self.media_available = get_bool(value), "MediaChangeDetected" => self.media_change_detected = get_bool(value), "MediaCompatibility" => { self.media_compatibility = get_string_array(value).unwrap_or_default() } "MediaRemovable" => self.media_removable = get_bool(value), "Model" => self.model = get_string(value).unwrap_or_default(), "Optical" => self.optical = get_bool(value), "OpticalBlank" => self.optical_blank = get_bool(value), "OpticalNumTracks" => self.optical_num_tracks = get_u64(value), "OpticalNumAudioTracks" => self.optical_num_audio_tracks = get_u64(value), "OpticalNumDataTracks" => self.optical_num_data_tracks = get_u64(value), "OpticalNumSessions" => self.optical_num_sessions = get_u64(value), "Removable" => self.removable = get_bool(value), "Revision" => self.revision = get_string(value).unwrap_or_default(), "RotationRate" => self.rotation_rate = get_u64(value) as i64, "Seat" => self.seat = get_string(value).unwrap_or_default(), "Serial" => self.serial = get_string(value).unwrap_or_default(), "SiblingId" => self.sibling_id = get_string(value).unwrap_or_default(), "Size" => self.size = get_u64(value), "SortKey" => self.sort_key = get_string(value).unwrap_or_default(), "TimeDetected" => self.time_detected = get_u64(value), "TimeMediaDetected" => self.time_media_detected = get_u64(value), "Vendor" => self.vendor = get_string(value).unwrap_or_default(), "WWN" => self.wwn = get_string(value).unwrap_or_default(), _ => { #[cfg(debug_assertions)] eprintln!("unhandled org.freedesktop.UDisks2.Drive::{}", key); } } } } } impl<'a> From<&'a Drive> for dbus::Path<'a> { fn from(drive: &'a Drive) -> Self { (&drive.path).into() } } dbus-udisks2-0.3.0/src/lib.rs000064400000000000000000000135071046102023000140540ustar 00000000000000//! You probably want to look at [`UDisks2`] or [`AsyncUDisks2`]. use std::collections::HashMap; use std::ops::Deref; use std::time::Duration; use dbus::arg::Variant; use dbus::blocking; use dbus::blocking::stdintf::org_freedesktop_dbus::{ObjectManager, Properties}; use crate::smart::{RawSmartAttribute, SmartData, SmartStatus, SmartValue}; pub use block::*; pub use disks::*; pub use drive::*; #[cfg(feature = "futures")] pub use nonblock::*; use utils::*; mod block; mod disks; mod drive; #[cfg(feature = "futures")] mod nonblock; pub mod smart; mod utils; const DEST: &str = "org.freedesktop.UDisks2"; const PATH: &str = "/org/freedesktop/UDisks2"; const NO_WAKEUP: &str = "nowakeup"; #[derive(Default)] struct DiskCache(HashMap, DbusObjects>); impl DiskCache { fn get_object(&self, path: &str) -> Option { self.0 .iter() .flat_map(|object| { if object.0.deref() == path { T::parse_from(&object.0, &object.1) } else { None } }) .next() } /// Find the drive that corresponds to the given dbus object path. fn get_drive(&self, path: &str) -> Option { self.get_object::(path) } /// An iterator of `Drive` objects fetched from the inner cached managed objects. fn get_drives<'a>(&'a self) -> impl Iterator + 'a { self.0 .iter() .flat_map(|object| Drive::parse_from(&object.0, &object.1)) } /// Find the block that corresponds to the given dbus object path. fn get_block(&self, path: &str) -> Option { self.get_object::(path) } /// An iterator of `Block` objects fetched from the inner cached managed objects. fn get_blocks<'a>(&'a self) -> impl Iterator + 'a { self.0 .iter() .flat_map(|object| Block::parse_from(&object.0, &object.1)) } } pub struct UDisks2 { conn: blocking::Connection, cache: DiskCache, } impl UDisks2 { pub fn new() -> Result { let mut udisks2 = Self { conn: blocking::Connection::new_system()?, cache: Default::default(), }; udisks2.update()?; Ok(udisks2) } fn proxy<'a>( &'a self, path: impl Into>, ) -> blocking::Proxy<&blocking::Connection> { blocking::Proxy::new(DEST, path, Duration::from_millis(3000), &self.conn) } /// Refresh the managed objects fetched from the DBus server. pub fn update(&mut self) -> Result<(), dbus::Error> { self.cache.0 = self.proxy(PATH).get_managed_objects()?; Ok(()) } /// Find the drive that corresponds to the given dbus object path. pub fn get_drive(&self, path: &str) -> Option { self.cache.get_drive(path) } /// An iterator of `Drive` objects fetched from the inner cached managed objects. pub fn get_drives<'a>(&'a self) -> impl Iterator + 'a { self.cache.get_drives() } /// Find the block that corresponds to the given dbus object path. pub fn get_block(&self, path: &str) -> Option { self.cache.get_block(path) } /// An iterator of `Block` objects fetched from the inner cached managed objects. pub fn get_blocks<'a>(&'a self) -> impl Iterator + 'a { self.cache.get_blocks() } /// Update the S.M.A.R.T. attributes of a drive. You may pass either a `&`[`Drive`] or `&str` /// which is a path to a drive, starting with `/org/freedesktop/UDisks2/drives/`. pub fn smart_update<'a>( &'a self, drive: impl Into>, allow_wakeup: bool, ) -> Result<(), dbus::Error> { let proxy = self.proxy(drive); let mut options = KeyVariant::<&str>::new(); if !allow_wakeup { options.insert(NO_WAKEUP, Variant(Box::new(true))); } proxy.method_call(smart::DEST, smart::UPDATE, (options,)) } /// Get the S.M.A.R.T. attributes of a drive. You may pass either a `&`[`Drive`] or `&str` which /// is a path to a drive, starting with `/org/freedesktop/UDisks2/drives/`. pub fn smart_attributes<'a>( &'a self, drive: impl Into>, allow_wakeup: bool, ) -> Result { let proxy = self.proxy(drive); if !proxy.get::(smart::DEST, smart::SUPPORTED)? { return Ok(SmartValue::NotSupported); } if !proxy.get::(smart::DEST, smart::ENABLED)? { return Ok(SmartValue::NotEnabled); } let updated: u64 = proxy.get(smart::DEST, smart::UPDATED)?; if updated == 0 { return Ok(SmartValue::NotUpdated); } let mut options = KeyVariant::<&str>::new(); if !allow_wakeup { options.insert(NO_WAKEUP, Variant(Box::new(true))); } let (attrs,): (Vec,) = proxy.method_call(smart::DEST, smart::GET_ATTRS, (options,))?; Ok(SmartValue::Enabled(SmartData { updated, failing: proxy.get(smart::DEST, smart::FAILING)?, time_powered_on: proxy.get(smart::DEST, smart::TIME_POWER_ON)?, temperature: proxy.get(smart::DEST, smart::TEMPERATURE)?, failing_attrs_count: proxy.get(smart::DEST, smart::FAILING_ATTRS_COUNT)?, past_failing_attrs_count: proxy.get(smart::DEST, smart::PAST_FAILING_ATTRS_COUNT)?, bad_sectors: proxy.get(smart::DEST, smart::BAD_SECTORS)?, status: proxy .get::(smart::DEST, smart::STATUS)? .parse() .unwrap_or(SmartStatus::Unknown), attributes: attrs.into_iter().map(Into::into).collect(), })) } } dbus-udisks2-0.3.0/src/nonblock.rs000064400000000000000000000130701046102023000151060ustar 00000000000000use crate::smart::{RawSmartAttribute, SmartData, SmartStatus, SmartValue}; use crate::utils::KeyVariant; use crate::{smart, Block, DiskCache, Drive, DEST, NO_WAKEUP, PATH}; use dbus::arg::Variant; use dbus::nonblock; use dbus::nonblock::stdintf::org_freedesktop_dbus::{ObjectManager, Properties}; use dbus::nonblock::NonblockReply; use futures_util::join; use std::ops::Deref; use std::time::Duration; /// Async version of [`UDisks2`][crate::UDisks2]. /// /// This requires enabling the `futures` feature flag: /// ```toml /// [dependencies] /// dbus-udisks2 = { version = "0.3", features = ["futures"] } /// ``` pub struct AsyncUDisks2 { conn: C, pub(crate) cache: DiskCache, } impl<'b, C, T> AsyncUDisks2 where T: NonblockReply + 'b, C: Deref, { /// ``` /// # tokio::runtime::Runtime::new().unwrap().block_on(async { /// // Connect to the D-Bus session bus (this is blocking, unfortunately). /// let (resource, conn) = dbus_tokio::connection::new_system_sync().unwrap(); /// /// // The resource is a task that should be spawned onto a tokio compatible /// // reactor ASAP. If the resource ever finishes, you lost connection to D-Bus. /// tokio::spawn(async { /// let err = resource.await; /// panic!("Lost connection to D-Bus: {}", err); /// }); /// /// let udisks2 = dbus_udisks2::AsyncUDisks2::new(conn).await.unwrap(); /// # }); /// ``` pub async fn new(conn: C) -> Result { let mut udisks2 = Self { conn, cache: Default::default(), }; udisks2.update().await?; Ok(udisks2) } fn proxy<'a>(&'a self, path: impl Into>) -> nonblock::Proxy<&T> { nonblock::Proxy::new(DEST, path, Duration::from_millis(3000), &self.conn) } /// Refresh the managed objects fetched from the DBus server. pub async fn update(&mut self) -> Result<(), dbus::Error> { self.cache.0 = self.proxy(PATH).get_managed_objects().await?; Ok(()) } /// Find the drive that corresponds to the given dbus object path. pub fn get_drive(&self, path: &str) -> Option { self.cache.get_drive(path) } /// An iterator of `Drive` objects fetched from the inner cached managed objects. pub fn get_drives<'a>(&'a self) -> impl Iterator + 'a { self.cache.get_drives() } /// Find the block that corresponds to the given dbus object path. pub fn get_block(&self, path: &str) -> Option { self.cache.get_block(path) } /// An iterator of `Block` objects fetched from the inner cached managed objects. pub fn get_blocks<'a>(&'a self) -> impl Iterator + 'a { self.cache.get_blocks() } /// Update the S.M.A.R.T. attributes of a drive. You may pass either a `&`[`Drive`] or `&str` /// which is a path to a drive, starting with `/org/freedesktop/UDisks2/drives/`. pub async fn smart_update( &'b self, drive: impl Into>, allow_wakeup: bool, ) -> Result<(), dbus::Error> { let proxy = self.proxy(drive); let mut options = KeyVariant::<&str>::new(); if !allow_wakeup { options.insert(NO_WAKEUP, Variant(Box::new(true))); } proxy .method_call(smart::DEST, smart::UPDATE, (options,)) .await } /// Get the S.M.A.R.T. attributes of a drive. You may pass either a `&`[`Drive`] or `&str` which /// is a path to a drive, starting with `/org/freedesktop/UDisks2/drives/`. pub async fn smart_attributes( &'b self, drive: impl Into>, allow_wakeup: bool, ) -> Result { let proxy = self.proxy(drive); if !proxy.get::(smart::DEST, smart::SUPPORTED).await? { return Ok(SmartValue::NotSupported); } if !proxy.get::(smart::DEST, smart::ENABLED).await? { return Ok(SmartValue::NotEnabled); } let updated: u64 = proxy.get(smart::DEST, smart::UPDATED).await?; if updated == 0 { return Ok(SmartValue::NotUpdated); } let mut options = KeyVariant::<&str>::new(); if !allow_wakeup { options.insert(NO_WAKEUP, Variant(Box::new(true))); } let (attrs,): (Vec,) = proxy .method_call(smart::DEST, smart::GET_ATTRS, (options,)) .await?; let ( failing, time_powered_on, temperature, failing_attrs_count, past_failing_attrs_count, bad_sectors, status, ) = join!( proxy.get(smart::DEST, smart::FAILING), proxy.get(smart::DEST, smart::TIME_POWER_ON), proxy.get(smart::DEST, smart::TEMPERATURE), proxy.get(smart::DEST, smart::FAILING_ATTRS_COUNT), proxy.get(smart::DEST, smart::PAST_FAILING_ATTRS_COUNT), proxy.get(smart::DEST, smart::BAD_SECTORS), proxy.get::(smart::DEST, smart::STATUS), ); Ok(SmartValue::Enabled(SmartData { updated, failing: failing?, time_powered_on: time_powered_on?, temperature: temperature?, failing_attrs_count: failing_attrs_count?, past_failing_attrs_count: past_failing_attrs_count?, bad_sectors: bad_sectors?, status: status?.parse().unwrap_or(SmartStatus::Unknown), attributes: attrs.into_iter().map(Into::into).collect(), })) } } dbus-udisks2-0.3.0/src/smart.rs000064400000000000000000000215271046102023000144350ustar 00000000000000//! Types related to the S.M.A.R.T. data of drives. use crate::utils::*; use num_enum::TryFromPrimitive; use std::convert::TryFrom; use std::fmt; use std::str::FromStr; use std::time::Duration; pub(crate) const DEST: &str = "org.freedesktop.UDisks2.Drive.Ata"; pub(crate) const UPDATE: &str = "SmartUpdate"; pub(crate) const GET_ATTRS: &str = "SmartGetAttributes"; pub(crate) const ENABLED: &str = "SmartEnabled"; pub(crate) const SUPPORTED: &str = "SmartSupported"; pub(crate) const UPDATED: &str = "SmartUpdated"; pub(crate) const FAILING: &str = "SmartFailing"; pub(crate) const TIME_POWER_ON: &str = "SmartPowerOnSeconds"; pub(crate) const TEMPERATURE: &str = "SmartTemperature"; pub(crate) const FAILING_ATTRS_COUNT: &str = "SmartNumAttributesFailing"; pub(crate) const PAST_FAILING_ATTRS_COUNT: &str = "SmartNumAttributesFailedInThePast"; pub(crate) const BAD_SECTORS: &str = "SmartNumBadSectors"; pub(crate) const STATUS: &str = "SmartSelftestStatus"; pub(crate) type RawSmartAttribute = (u8, String, u16, i32, i32, i32, i64, i32, KeyVariant); #[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)] #[non_exhaustive] /// The status of a S.M.A.R.T. test. pub enum SmartStatus { /// Last self-test was a success (or never ran). Success, /// Last self-test was aborted. Aborted, /// Last self-test was interrupted. Interrupted, /// Last self-test did not complete. Fatal, /// Last self-test failed (Unknown). UnknownError, /// Last self-test failed (Electrical). ElectricalError, /// Last self-test failed (Servo). ServoError, /// Last self-test failed (Read). ReadError, /// Last self-test failed (Damage). HandlingError, /// Self-test is currently in progress. InProgress, /// Unknown status Unknown, } impl FromStr for SmartStatus { type Err = (); fn from_str(s: &str) -> Result { match s { "success" => Ok(SmartStatus::Success), "aborted" => Ok(SmartStatus::Aborted), "interrupted" => Ok(SmartStatus::Interrupted), "fatal" => Ok(SmartStatus::Fatal), "error_unknown" => Ok(SmartStatus::UnknownError), "error_electrical" => Ok(SmartStatus::ElectricalError), "error_servo" => Ok(SmartStatus::ServoError), "error_read" => Ok(SmartStatus::ReadError), "error_handling" => Ok(SmartStatus::HandlingError), "inprogress" => Ok(SmartStatus::InProgress), _ => Err(()), } } } #[derive(Clone, Debug)] /// Whether a drive supports S.M.A.R.T. or not. pub enum SmartValue { /// The drive does not support S.M.A.R.T. NotSupported, /// The drive supports S.M.A.R.T., but it's not enabled. NotEnabled, /// S.M.A.R.T. is supported and enabled, but it's never been read. Call /// [`smart_update`][crate::UDisks2::smart_update] /// ([async version][crate::AsyncUDisks2::smart_update]). NotUpdated, Enabled(SmartData), } #[derive(Clone, Debug)] /// The S.M.A.R.T. data of a drive. pub struct SmartData { pub attributes: Vec, /// The point in time (seconds since the Unix Epoch) that the SMART status was updated. pub updated: u64, /// Set to `true` if disk is about to fail. /// /// This value is read from the disk itself and does not include any interpretation. pub failing: bool, /// The amount of time the disk has been powered on (according to SMART data) or 0 if unknown. pub time_powered_on: u64, /// The temperature (in Kelvin) of the disk according to SMART data or 0 if unknown. pub temperature: f64, /// The number of attributes failing right now or -1 if unknown. pub failing_attrs_count: i32, /// The number of attributes that have failed in the past or -1 if unknown. pub past_failing_attrs_count: i32, /// The number of bad sectors (ie. pending and reallocated) or -1 if unknown. pub bad_sectors: i64, /// The status of the last self-test. pub status: SmartStatus, } #[derive(Debug, Eq, PartialEq, TryFromPrimitive, Copy, Clone, Hash)] #[repr(u8)] #[non_exhaustive] pub enum PrettyUnit { Dimensionless = 1, Milliseconds, Sectors, Millikelvin, } #[derive(Eq, PartialEq, Copy, Clone, Hash)] pub struct PrettyValue { pub value: i64, pub unit: PrettyUnit, } impl fmt::Debug for PrettyValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} / ", self)?; f.debug_struct("PrettyValue") .field("value", &self.value) .field("unit", &self.unit) .finish() } } impl fmt::Display for PrettyValue { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.unit { PrettyUnit::Dimensionless => write!(f, "{}", self.value), PrettyUnit::Milliseconds => write!(f, "{:?}", Duration::from_millis(self.value as u64)), PrettyUnit::Sectors => write!(f, "{} sectors", self.value), PrettyUnit::Millikelvin => { write!(f, "{:.1} degrees C", self.value as f32 / 1000. - 273.15) } } } } #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum SmartAssessment { Failing, FailedInPast, Ok, } #[derive(Clone, Debug)] /// A S.M.A.R.T. attribute. pub struct SmartAttribute { /// Attribute Identifier pub id: u8, /// The identifier as a string. pub name: String, /// 16-bit attribute flags (bit 0 is prefail/oldage, bit 1 is online/offline). pub flags: u16, /// The current value or -1 if unknown. pub normalized: i32, /// The worst value of -1 if unknown. pub worst: i32, /// The threshold or -1 if unknown. pub threshold: i32, /// An interpretation of the value pub pretty: Option, } impl SmartAttribute { // from https://github.com/smartmontools/smartmontools/blob/ff9fbe7300064cc6ec45a78c162f0166c770c4b0/smartmontools/atacmds.h#L150 /// Whether this attribute determines if the drive is failing (`true`) or old (`false`). /// /// From SFF 8035i Revision 2 page 19: /// /// Bit 0 (pre-failure/advisory bit) - If the value of this bit equals zero, an attribute value /// less than or equal to its corresponding attribute threshold indicates an advisory condition /// where the usage or age of the device has exceeded its intended design life period. If the /// value of this bit equals one, an attribute value less than or equal to its corresponding /// attribute threshold indicates a prefailure condition where imminent loss of data is being /// predicted. /// /// --- /// /// From [SMART Attribute Overview](http://www.t13.org/Documents/UploadedDocuments/docs2005/e05171r0-ACS-SMARTAttributes_Overview.pdf): /// /// 0: Advisory: The usage of age of the device has exceeded its intended design life period \ /// 1: Pre-failure notification: Failure is predicted within 24 hours pub fn pre_fail(&self) -> bool { self.flags & 0x01 > 0 } /// From SFF 8035i Revision 2 page 19: /// /// Bit 1 (on-line data collection bit) - If the value of this bit equals zero, then the /// attribute value is updated only during off-line data collection activities. If the value of /// this bit equals one, then the attribute value is updated during normal operation of the /// device or during both normal operation and off-line testing. pub fn online(&self) -> bool { self.flags & 0x02 > 0 } /// `true`: speed/performance pub fn performance(&self) -> bool { self.flags & 0x04 > 0 } pub fn error_rate(&self) -> bool { self.flags & 0x08 > 0 } pub fn event_count(&self) -> bool { self.flags & 0x10 > 0 } pub fn self_preserving(&self) -> bool { self.flags & 0x20 > 0 } /// Assess the disk's state. /// /// From https://github.com/GNOME/gnome-disk-utility/blob/5baa52eff3036fc59648bc2e10c4d4ec69dec50b/src/disks/gduatasmartdialog.c#L678 pub fn assessment(&self) -> SmartAssessment { if self.normalized > 0 && self.threshold > 0 && self.normalized <= self.threshold { SmartAssessment::Failing } else if self.worst > 0 && self.threshold > 0 && self.worst <= self.threshold { SmartAssessment::FailedInPast } else { SmartAssessment::Ok } } } impl From for SmartAttribute { fn from( (id, name, flags, value, worst, threshold, pretty_value, pretty_unit, _expansion): RawSmartAttribute, ) -> Self { let pretty = PrettyUnit::try_from(pretty_unit as u8) .map(|unit| PrettyValue { value: pretty_value, unit, }) .ok(); SmartAttribute { id, name, flags, normalized: value, worst, threshold, pretty, } } } dbus-udisks2-0.3.0/src/utils.rs000064400000000000000000000042271046102023000144450ustar 00000000000000use dbus::arg::{RefArg, Variant}; use std::collections::HashMap; pub type KeyVariant = HashMap>>; pub type DbusObjects = HashMap; pub fn get_string(arg: &Variant>) -> Option { arg.0.as_str().and_then(|x| { if x.is_empty() { None } else { Some(x.to_owned()) } }) } pub fn get_u64(arg: &Variant>) -> u64 { arg.0.as_u64().unwrap_or(0) } pub fn get_bool(arg: &Variant>) -> bool { arg.0.as_u64().unwrap_or(0) != 0 } pub fn get_string_array(arg: &Variant>) -> Option> { arg.0.as_iter().and_then(|items| { let vector = items .flat_map(|item| item.as_str().map(String::from)) .collect::>(); if vector.is_empty() { None } else { Some(vector) } }) } pub fn get_byte_array(arg: &Variant>) -> Option { atostr(arg.0.as_iter()) } pub fn atostr<'a>(array: Option + 'a>>) -> Option { array.and_then(|bytes| { let mut inner_vec = bytes .flat_map(|byte| byte.as_u64().map(|x| x as u8)) .collect::>(); if inner_vec.last() == Some(&0) { inner_vec.pop(); } String::from_utf8(inner_vec).ok() }) } pub fn vva(value: &dyn RefArg) -> Option { let viter = value.as_iter().and_then(|mut i| { i.next().and_then(|i| { i.as_iter() .and_then(|mut i| i.next().and_then(|i| i.as_iter())) }) }); atostr(viter) } pub fn get_array_of_byte_arrays(arg: &Variant>) -> Option> { arg.0.as_iter().and_then(|items| { let vector = items .flat_map(|item| atostr(item.as_iter())) .collect::>(); if vector.is_empty() { None } else { Some(vector) } }) } pub(crate) trait ParseFrom { fn parse_from(path: &str, objects: &DbusObjects) -> Option where Self: Sized; }