Repository: pop-os/popsicle (language: rust)

Issue:
Doesn't even work?
Running popsicle on Pop!_OS and arch results in the same outcome.

When it says Select Drives it lists my hard drive name, but says 0B: Device too small and doesn't list anything else, balena etcher finds my USB just fine.... 

No matter the ISO it just refuses to find my USB...

Using the one preinstalled on Pop! and the appimage on Arch.


Discussion / hints:
Odd, particularly if you're having this issue with the Pop! package. (The AppImage should work too, but has been tested less.)

Is it just a normal USB flash drive? (Rather than a hard drive, SD card reader, or anything like that.)
it is an sd card usb thing
Ah, then that's probably the issue. I suppose this test in [usb-disk-probe](https://github.com/pop-os/usb-disk-probe/blob/master/src/stream.rs) (on filenames in `/dev/disk/by-path/`) must be returning `false`:

```rust
fn is_usb(filename: &str) -> bool {
    filename.starts_with("pci-") && filename.contains("-usb-") && filename.ends_with("-0:0:0:0")
}
```

Not sure what format that string has for such a device. But it seems it should probably be listed.

Popsicle was semi-recently (https://github.com/pop-os/popsicle/pull/94) updated to use UDisks2 for gaining write access to the drive. It should probably use that for finding USB devices as well.

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index 0409412..eb470fb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -316,13 +316,32 @@ dependencies = [
 
 [[package]]
 name = "dbus"
-version = "0.8.4"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
  "libdbus-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "dbus-udisks2"
+version = "0.3.0"
+source = "git+https://github.com/pop-os/dbus-udisks2#15c4e70f029c6546e96f8c5b2fb78c9504cf9f28"
+dependencies = [
+ "dbus 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_enum 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "derivative"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "derive-new"
 version = "0.5.8"
@@ -351,19 +370,6 @@ name = "encode_unicode"
 version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "err-derive"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "errno"
 version = "0.2.4"
@@ -953,13 +959,28 @@ dependencies = [
 ]
 
 [[package]]
-name = "numtoa"
-version = "0.1.0"
+name = "num_enum"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "derivative 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_enum_derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num_enum_derive"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro-crate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "numtoa"
-version = "0.2.3"
+version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1019,14 +1040,6 @@ dependencies = [
  "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "partition-identity"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "err-derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "pbr"
 version = "1.0.2"
@@ -1073,7 +1086,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "popsicle"
-version = "1.2.0"
+version = "1.3.0"
 dependencies = [
  "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "as-result 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1094,7 +1107,7 @@ dependencies = [
 
 [[package]]
 name = "popsicle_cli"
-version = "1.2.0"
+version = "1.3.0"
 dependencies = [
  "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "async-std 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1107,12 +1120,12 @@ dependencies = [
  "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
  "pbr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "popsicle 1.2.0",
+ "popsicle 1.3.0",
 ]
 
 [[package]]
 name = "popsicle_gtk"
-version = "1.2.0"
+version = "1.3.0"
 dependencies = [
  "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "async-std 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1120,7 +1133,8 @@ dependencies = [
  "bytesize 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cascade 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "dbus 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dbus 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dbus-udisks2 0.3.0 (git+https://github.com/pop-os/dbus-udisks2)",
  "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gdk 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1132,12 +1146,10 @@ dependencies = [
  "md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "pango 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "popsicle 1.2.0",
- "proc-mounts 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "popsicle 1.3.0",
  "pwd 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "sys-mount 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "sysfs-class 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1148,16 +1160,6 @@ dependencies = [
  "toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "proc-macro-error"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "proc-macro-error"
 version = "1.0.3"
@@ -1205,15 +1207,6 @@ dependencies = [
  "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "proc-mounts"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "partition-identity 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "pwd"
 version = "1.3.0"
@@ -1421,14 +1414,6 @@ dependencies = [
  "loopdev 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "sysfs-class"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "numtoa 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "system-deps"
 version = "1.3.2"
@@ -1626,12 +1611,13 @@ dependencies = [
 "checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac"
 "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
 "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
-"checksum dbus 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5cd9e78c210146a1860f897db03412fd5091fd73100778e43ee255cca252cf32"
+"checksum dbus 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22c08adfeb70c940c14d8af988fa854dcb5529e6141f2397e4e0fa4c9375d094"
+"checksum dbus-udisks2 0.3.0 (git+https://github.com/pop-os/dbus-udisks2)" = "<none>"
+"checksum derivative 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f"
 "checksum derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9"
 "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
 "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
 "checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
-"checksum err-derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b41487fadaa500d02a819eefcde5f713599a01dd51626ef25d2d72d87115667b"
 "checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e"
 "checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067"
 "checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9"
@@ -1691,15 +1677,15 @@ dependencies = [
 "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
 "checksum nom 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
 "checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72"
+"checksum num_enum 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "226b45a5c2ac4dd696ed30fa6b94b057ad909c7b7fc2e0d0808192bced894066"
+"checksum num_enum_derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1c0fd9eba1d5db0994a239e09c1be402d35622277e35468ba891aa5e3188ce7e"
 "checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
-"checksum numtoa 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e521b6adefa0b2c1fa5d2abdf9a5216288686fe6146249215d884c0e5ab320b0"
 "checksum once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891f486f630e5c5a4916c7e16c4b24a53e78c860b646e9f8e005e4f16847bfed"
 "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
 "checksum pango 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "460dbe5ad850c46780ba61f142e966beacf5eebb09822830f796c91d7d4fec31"
 "checksum pango-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24d2650c8b62d116c020abd0cea26a4ed96526afda89b1c4ea567131fdefc890"
 "checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc"
 "checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1"
-"checksum partition-identity 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b33909267193c7babe396e0570d0a12ba997b539edfdb2aea1e767e0ea728f05"
 "checksum pbr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4403eb718d70c03ee279e51737782902c68cca01e870a33b6a2f9dfb50b9cd83"
 "checksum pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "94b90146c7216e4cb534069fb91366de4ea0ea353105ee45ed297e2d1619e469"
 "checksum pin-project-internal 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "44ca92f893f0656d3cba8158dd0f2b99b94de256a4a54e870bd6922fcc6c8355"
@@ -1707,13 +1693,11 @@ dependencies = [
 "checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
 "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
 "checksum proc-macro-crate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
-"checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097"
 "checksum proc-macro-error 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fc175e9777c3116627248584e8f8b3e2987405cabe1c0adf7d1dd28f09dc7880"
 "checksum proc-macro-error-attr 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3cc9795ca17eb581285ec44936da7fc2335a3f34f2ddd13118b6f4d515435c50"
 "checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5"
 "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e"
 "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
-"checksum proc-mounts 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "eaa1472134431dd27fcb4477d702d14cf5571a32ad92f2902522d354de42adda"
 "checksum pwd 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5dd32d8bece608e144ca20251e714ed107cdecdabb20c2d383cfc687825106a5"
 "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
 "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
@@ -1741,7 +1725,6 @@ dependencies = [
 "checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
 "checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
 "checksum sys-mount 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "62f5703caf67c45ad3450104001b4620a605e9def0cef13dde3c9add23f73cee"
-"checksum sysfs-class 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "718e4a5d0e144ff01e05bb8618a4997d8901cdec74cf25826bca2535ef406f3e"
 "checksum system-deps 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b"
 "checksum termion 1.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "818ef3700c2a7b447dca1a1dd28341fe635e6ee103c806c636bb9c929991b2cd"
 "checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625"
diff --git a/Cargo.toml b/Cargo.toml
index 20940c0..71e12d1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "popsicle"
 description = "USB Flasher"
-version = "1.2.0"
+version = "1.3.0"
 authors = [
     "Jeremy Soller <jeremy@system76.com>",
     "Michael Aaron Murphy <michael@system76.com>",
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index 2d88f45..ed71e00 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "popsicle_cli"
 description = "USB Flasher"
-version = "1.2.0"
+version = "1.3.0"
 authors = ["Jeremy Soller <jeremy@system76.com>"]
 license = "MIT"
 readme = "README.md"
diff --git a/cli/src/main.rs b/cli/src/main.rs
index 327da30..fa3bf7d 100644
--- a/cli/src/main.rs
+++ b/cli/src/main.rs
@@ -194,7 +194,9 @@ pub struct MachineProgress {
 }
 
 impl Progress for MachineProgress {
-    fn message(&mut self, _path: &Path, kind: &str, message: &str) {
+    type Device = Box<Path>;
+
+    fn message(&mut self, _path: &Box<Path>, kind: &str, message: &str) {
         let _ = self.handle.unbounded_send(Event::Message(
             self.id,
             if message.is_empty() { kind.into() } else { [kind, " ", message].concat().into() },
@@ -216,7 +218,9 @@ pub struct InteractiveProgress {
 }
 
 impl Progress for InteractiveProgress {
-    fn message(&mut self, path: &Path, kind: &str, message: &str) {
+    type Device = Box<Path>;
+
+    fn message(&mut self, path: &Box<Path>, kind: &str, message: &str) {
         self.pipe.message(&format!("{} {}: {}", kind, path.display(), message));
     }
 
diff --git a/debian/changelog b/debian/changelog
index d3e822f..715d4c1 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+popsicle (1.3.0) groovy; urgency=medium
+
+  * 1.3.0 release
+
+ -- Ian Douglas Scott <idscott@system76.com>  Thu, 05 Nov 2020 09:40:32 -0800
+
 popsicle (1.2.0) groovy; urgency=medium
 
   * 1.2.0 Release 
diff --git a/gtk/Cargo.toml b/gtk/Cargo.toml
index 5236a80..a6df612 100644
--- a/gtk/Cargo.toml
+++ b/gtk/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "popsicle_gtk"
 description = "USB Flasher"
-version = "1.2.0"
+version = "1.3.0"
 authors = [ "Michael Aaron Murphy <michael@system76.com>" ]
 license = "MIT"
 readme = "README.md"
@@ -17,7 +17,8 @@ anyhow = "1"
 bytesize = "1.0.1"
 cascade = "0.1"
 crossbeam-channel = "0.4"
-dbus = "0.8"
+dbus = "0.9"
+dbus-udisks2 = { git = "https://github.com/pop-os/dbus-udisks2" }
 digest = "0.8"
 futures = "0.3"
 gdk = "0.13"
@@ -30,9 +31,7 @@ md-5 = "0.8"
 pango = "0.9"
 parking_lot = "0.10"
 popsicle = { path = ".." }
-proc-mounts = "0.2"
 pwd = "1"
 sha2 = "0.8"
 sys-mount = "1"
-sysfs-class = "0.1"
 async-std = "1.3.0"
diff --git a/gtk/assets/com.system76.Popsicle.appdata.xml b/gtk/assets/com.system76.Popsicle.appdata.xml
index d1d7405..4fe5fb4 100644
--- a/gtk/assets/com.system76.Popsicle.appdata.xml
+++ b/gtk/assets/com.system76.Popsicle.appdata.xml
@@ -54,6 +54,7 @@
 	<project_group>Pop!_OS</project_group>
 	<content_rating type="oars-1.0" />
 	<releases>
+		<release version="1.3.0" date="2020-11-05" />
 		<release version="1.2.0" date="2020-10-27" />
 		<release version="1.1.0" date="2020-08-03" />
 	</releases>
diff --git a/gtk/src/app/events/mod.rs b/gtk/src/app/events/mod.rs
index 43dc434..1f0cecd 100644
--- a/gtk/src/app/events/mod.rs
+++ b/gtk/src/app/events/mod.rs
@@ -1,22 +1,19 @@
-use crate::block::BlockDevice;
 use crate::flash::{FlashError, FlashRequest};
 use crate::hash::hasher;
 
-use async_std::path::Path as AsyncPath;
 use crossbeam_channel::{Receiver, Sender};
+use dbus_udisks2::{DiskDevice, Disks, UDisks2};
 use md5::Md5;
-use popsicle;
 use sha2::Sha256;
 use std::collections::HashMap;
 use std::io;
-use std::mem;
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
+use std::sync::Arc;
 use std::thread::{self, JoinHandle};
-use std::time::Instant;
 
 pub enum UiEvent {
     SetImageLabel(PathBuf),
-    RefreshDevices(Box<[BlockDevice]>),
+    RefreshDevices(Box<[Arc<DiskDevice>]>),
     SetHash(io::Result<String>),
     Flash(JoinHandle<anyhow::Result<(anyhow::Result<()>, Vec<Result<(), FlashError>>)>>),
     Reset,
@@ -32,8 +29,7 @@ pub fn background_thread(events_tx: Sender<UiEvent>, events_rx: Receiver<Backgro
     thread::spawn(move || {
         let mut hashed: HashMap<(PathBuf, &'static str), String> = HashMap::new();
 
-        let mut devices = Vec::new();
-        let mut devices_cmp = Vec::new();
+        let mut device_paths = Vec::new();
 
         loop {
             match events_rx.recv() {
@@ -64,23 +60,13 @@ pub fn background_thread(events_tx: Sender<UiEvent>, events_rx: Receiver<Backgro
                 }
                 Ok(BackgroundEvent::RefreshDevices) => {
                     // Fetch the current list of USB devices from popsicle.
-                    match popsicle::get_disk_args(&mut devices_cmp) {
-                        Ok(()) => {
-                            if devices_cmp != devices {
-                                // If they differed, the new device vec is the current device vec.
-                                mem::swap(&mut devices_cmp, &mut devices);
-
-                                // Attempt to fetch more detailed information on the block devices.
-                                match fetch_block_devices(&devices) {
-                                    Ok(devices) => {
-                                        // Signal to the UI to refresh the list.
-                                        let _ = events_tx.send(UiEvent::RefreshDevices(devices));
-                                    }
-                                    Err(why) => eprintln!("failed to fetch block info: {}", why),
-                                }
+                    match refresh_devices() {
+                        Ok(devices) => {
+                            let new_device_paths: Vec<_> = devices.iter().map(|d| d.drive.path.clone()).collect();
+                            if new_device_paths != device_paths {
+                                device_paths = new_device_paths;
+                                let _ = events_tx.send(UiEvent::RefreshDevices(devices));
                             }
-
-                            devices_cmp.clear();
                         }
                         Err(why) => eprintln!("failed to refresh devices: {}", why),
                     }
@@ -99,24 +85,16 @@ pub fn background_thread(events_tx: Sender<UiEvent>, events_rx: Receiver<Backgro
     });
 }
 
-fn fetch_block_devices(devices: &[Box<AsyncPath>]) -> io::Result<Box<[BlockDevice]>> {
-    let mut output = Vec::new();
-    let start = Instant::now();
-
-    for device in devices {
-        if let Ok(ref device) = Path::new(device.as_os_str()).canonicalize() {
-            let mut block = BlockDevice::new_from(device)?;
-
-            // In the case of a device with a sector count of 0, it will be polled again.
-            // The polling will stop if there is no change after 5 seconds since this function
-            // began execution.
-            while block.sectors == 0 && Instant::now().duration_since(start).as_secs() < 5 {
-                block.recheck_size();
-            }
-
-            output.push(block);
-        }
-    }
-
-    Ok(output.into_boxed_slice())
+fn refresh_devices() -> anyhow::Result<Box<[Arc<DiskDevice>]>> {
+    let udisks = UDisks2::new()?;
+    let devices = Disks::new(&udisks).devices;
+    let mut devices = devices
+        .into_iter()
+        .filter(|d| d.drive.connection_bus == "usb" || d.drive.connection_bus == "sdio")
+        .filter(|d| d.parent.size != 0)
+        .map(Arc::new)
+        .collect::<Vec<_>>()
+        .into_boxed_slice();
+    devices.sort_by_key(|d| d.drive.id.clone());
+    Ok(devices)
 }
diff --git a/gtk/src/app/signals/mod.rs b/gtk/src/app/signals/mod.rs
index 29abf97..30b30aa 100644
--- a/gtk/src/app/signals/mod.rs
+++ b/gtk/src/app/signals/mod.rs
@@ -5,6 +5,7 @@ use crate::app::events::{BackgroundEvent, UiEvent};
 use crate::app::state::ActiveView;
 use crate::app::App;
 use crate::flash::{FlashRequest, FlashStatus, FlashTask};
+use crate::misc;
 use atomic::Atomic;
 use crossbeam_channel::TryRecvError;
 use gtk::{self, prelude::*};
@@ -142,7 +143,7 @@ impl App {
                             };
 
                             let label = cascade! {
-                                gtk::Label::new(Some(device.label().as_str()));
+                                gtk::Label::new(Some(&misc::device_label(&device)));
                                 ..set_justify(gtk::Justification::Right);
                                 ..get_style_context().add_class("bold");
                             };
@@ -162,7 +163,7 @@ impl App {
                             summary_grid.attach(&bar_container, 1, id, 1, 1);
 
                             flashing_devices.push((pbar, bar_label));
-                            destinations.push(device.path.clone());
+                            destinations.push(device.clone());
                         }
 
                         summary_grid.show_all();
@@ -305,7 +306,7 @@ impl App {
                                     description.set_markup(&desc);
 
                                     for (device, why) in errors {
-                                        let device = gtk::Label::new(Some(device.label().as_str()));
+                                        let device = gtk::Label::new(Some(&misc::device_label(&device)));
                                         let why = gtk::Label::new(Some(format!("{}", why).as_str()));
                                         why.get_style_context().add_class("bold");
 
@@ -337,4 +338,4 @@ fn is_windows_iso(file: &File) -> bool {
         return fs.publisher_identifier() == "MICROSOFT CORPORATION";
     }
     false
-}
\ No newline at end of file
+}
diff --git a/gtk/src/app/state/mod.rs b/gtk/src/app/state/mod.rs
index eb2d419..7570434 100644
--- a/gtk/src/app/state/mod.rs
+++ b/gtk/src/app/state/mod.rs
@@ -1,7 +1,7 @@
 use crate::app::events::{self, BackgroundEvent, UiEvent};
-use crate::block::BlockDevice;
 use atomic::Atomic;
 use crossbeam_channel::{unbounded, Receiver, Sender};
+use dbus_udisks2::DiskDevice;
 use libc;
 use std::cell::{Cell, RefCell};
 use std::env;
@@ -29,8 +29,8 @@ pub struct State {
     pub image_path: RefCell<PathBuf>,
     pub image_size: Arc<Atomic<u64>>,
 
-    pub available_devices: RefCell<Box<[BlockDevice]>>,
-    pub selected_devices: RefCell<Vec<BlockDevice>>,
+    pub available_devices: RefCell<Box<[Arc<DiskDevice>]>>,
+    pub selected_devices: RefCell<Vec<Arc<DiskDevice>>>,
 }
 
 impl State {
diff --git a/gtk/src/app/views/devices.rs b/gtk/src/app/views/devices.rs
index 6a6fb68..193ce29 100644
--- a/gtk/src/app/views/devices.rs
+++ b/gtk/src/app/views/devices.rs
@@ -1,9 +1,11 @@
+use crate::misc;
 use super::View;
-use crate::block::BlockDevice;
+use dbus_udisks2::DiskDevice;
 use gtk;
 use gtk::prelude::*;
 use std::cell::{Cell, RefCell};
 use std::rc::Rc;
+use std::sync::Arc;
 
 use bytesize;
 
@@ -86,19 +88,21 @@ impl DevicesView {
             .filter_map(|(id, button)| if button.get_active() { Some(id) } else { None })
     }
 
-    pub fn refresh(&self, devices: &[BlockDevice], image_size: u64) {
+    pub fn refresh(&self, devices: &[Arc<DiskDevice>], image_size: u64) {
         self.list.foreach(|w| self.list.remove(w));
 
         let nselected = Rc::new(Cell::new(0));
 
         for device in devices {
-            let valid_size = device.size_in_bytes() >= image_size;
+            let valid_size = device.parent.size >= image_size;
 
-            let size_str = bytesize::to_string(device.size_in_bytes(), true);
+            let label = &misc::device_label(&device);
+
+            let size_str = bytesize::to_string(device.parent.size, true);
             let name = if valid_size {
-                format!("<b>{}</b>\n{}", device.label(), size_str)
+                format!("<b>{}</b>\n{}", label, size_str)
             } else {
-                format!("<b>{}</b>\n{}: <b>Device too small</b>", device.label(), size_str)
+                format!("<b>{}</b>\n{}: <b>Device too small</b>", label, size_str)
             };
 
             let view_ready = self.view_ready.clone();
diff --git a/gtk/src/block.rs b/gtk/src/block.rs
deleted file mode 100644
index 4536b07..0000000
--- a/gtk/src/block.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-use std::io;
-use std::path::{Path, PathBuf};
-use sysfs_class::{Block, SysClass};
-
-#[derive(Clone)]
-pub struct BlockDevice {
-    block: Block,
-    pub path: PathBuf,
-    pub vendor: String,
-    pub model: String,
-    pub sectors: u64,
-    pub sector_size: u64,
-}
-
-impl BlockDevice {
-    pub fn new_from<P: AsRef<Path>>(path: P) -> io::Result<BlockDevice> {
-        let path = path.as_ref();
-
-        let file_name = path.file_name().ok_or_else(|| {
-            io::Error::new(
-                io::ErrorKind::InvalidInput,
-                "BlockDevice::new_from path does not have a file name",
-            )
-        })?;
-
-        let file_name = file_name.to_str().ok_or_else(|| {
-            io::Error::new(io::ErrorKind::InvalidData, "BlockDevice::new_from path is not UTF-8")
-        })?;
-
-        let block = Block::new(file_name)?;
-
-        let device = BlockDevice {
-            path: path.to_path_buf(),
-            vendor: block.device_vendor()?.trim().to_owned(),
-            model: block.device_model()?.trim().to_owned(),
-            sectors: block.size()?,
-            sector_size: block.queue_hw_sector_size()?,
-            block,
-        };
-
-        Ok(device)
-    }
-
-    pub fn recheck_size(&mut self) {
-        if self.sector_size == 0 {
-            if let Ok(size) = self.block.queue_hw_sector_size() {
-                self.sector_size = size;
-            }
-        }
-
-        if let Ok(size) = self.block.size() {
-            self.sectors = size;
-        }
-    }
-
-    pub fn size_in_bytes(&self) -> u64 {
-        self.sectors * self.sector_size
-    }
-
-    pub fn label(&self) -> String {
-        if self.vendor.is_empty() {
-            format!("{} ({})", self.model, self.path.display())
-        } else {
-            format!("{} {} ({})", self.vendor, self.model, self.path.display())
-        }
-    }
-}
diff --git a/gtk/src/flash.rs b/gtk/src/flash.rs
index 96a0d09..20f5cff 100644
--- a/gtk/src/flash.rs
+++ b/gtk/src/flash.rs
@@ -1,17 +1,16 @@
 use atomic::Atomic;
 use dbus::arg::{OwnedFd, RefArg, Variant};
 use dbus::blocking::{Connection, Proxy};
+use dbus_udisks2::DiskDevice;
 use futures::executor;
 use libc;
 use popsicle::{Progress, Task};
-use proc_mounts::MountList;
 use std::cell::Cell;
 use std::collections::HashMap;
 use std::fmt::{self, Debug, Display, Formatter};
 use std::fs::File;
 use std::os::unix::io::FromRawFd;
-use std::os::unix::ffi::OsStrExt;
-use std::path::{Path, PathBuf};
+use std::str;
 use std::sync::atomic::Ordering;
 use std::sync::{Arc, Mutex};
 use std::time::Duration;
@@ -27,7 +26,7 @@ pub enum FlashStatus {
 
 pub struct FlashRequest {
     source: Option<File>,
-    destinations: Vec<PathBuf>,
+    destinations: Vec<Arc<DiskDevice>>,
     status: Arc<Atomic<FlashStatus>>,
     progress: Arc<Vec<Atomic<u64>>>,
     finished: Arc<Vec<Atomic<bool>>>,
@@ -60,7 +59,9 @@ impl Display for FlashError {
 impl std::error::Error for FlashError {}
 
 impl<'a> Progress for FlashProgress<'a> {
-    fn message(&mut self, _path: &async_std::path::Path, kind: &str, message: &str) {
+    type Device = ();
+
+    fn message(&mut self, _device: &(), kind: &str, message: &str) {
         self.errors[self.id].set(Err(FlashError {
             kind: kind.to_string(),
             message: message.to_string(),
@@ -79,7 +80,7 @@ impl<'a> Progress for FlashProgress<'a> {
 impl FlashRequest {
     pub fn new(
         source: File,
-        destinations: Vec<PathBuf>,
+        destinations: Vec<Arc<DiskDevice>>,
         status: Arc<Atomic<FlashStatus>>,
         progress: Arc<Vec<Atomic<u64>>>,
         finished: Arc<Vec<Atomic<bool>>>,
@@ -104,18 +105,17 @@ impl FlashRequest {
 
     fn write_inner<'a>(&'a self, source: File) -> anyhow::Result<(anyhow::Result<()>, Vec<Result<(), FlashError>>)> {
         // Unmount the devices beforehand.
-        if let Ok(mounts) = MountList::new() {
-            for file in &self.destinations {
-                for mount in mounts.source_starts_with(file) {
-                    let _ = udisks_unmount(&mount.source);
-                }
+        for device in &self.destinations {
+            let _ = udisks_unmount(&device.parent.path);
+            for partition in &device.partitions {
+                let _ = udisks_unmount(&partition.path);
             }
         }
 
         // Then open them for writing to.
         let mut files = Vec::new();
-        for file in &self.destinations {
-            let file = udisks_open(file)?;
+        for device in &self.destinations {
+            let file = udisks_open(&device.parent.path)?;
             files.push(file);
         }
 
@@ -128,8 +128,7 @@ impl FlashRequest {
         let mut task = Task::new(source.into(), false);
         for (i, file) in files.into_iter().enumerate() {
             let progress = FlashProgress {request: &self, errors: errors_cells, id: i};
-            let destination = async_std::path::PathBuf::from(self.destinations[i].clone()).into_boxed_path();
-            task.subscribe(file.into(), destination, progress);
+            task.subscribe(file.into(), (), progress);
         }
 
         let res = executor::block_on(task.process(&mut bucket));
@@ -138,11 +137,9 @@ impl FlashRequest {
     }
 }
 
-fn udisks_unmount(block_device: &Path) -> anyhow::Result<()> {
+fn udisks_unmount(dbus_path: &str) -> anyhow::Result<()> {
     let connection = Connection::new_system()?;
 
-    let mut dbus_path = b"/org/freedesktop/UDisks2/block_devices/".to_vec();
-    dbus_path.extend_from_slice(block_device.strip_prefix("/dev")?.as_os_str().as_bytes());
     let dbus_path = ::dbus::strings::Path::new(dbus_path).map_err(anyhow::Error::msg)?;
 
     let proxy = Proxy::new(
@@ -169,11 +166,9 @@ fn udisks_unmount(block_device: &Path) -> anyhow::Result<()> {
     Ok(())
 }
 
-fn udisks_open(block_device: &Path) -> anyhow::Result<File> {
+fn udisks_open(dbus_path: &str) -> anyhow::Result<File> {
     let connection = Connection::new_system()?;
 
-    let mut dbus_path = b"/org/freedesktop/UDisks2/block_devices/".to_vec();
-    dbus_path.extend_from_slice(block_device.strip_prefix("/dev")?.as_os_str().as_bytes());
     let dbus_path = ::dbus::strings::Path::new(dbus_path).map_err(anyhow::Error::msg)?;
 
     let proxy = Proxy::new(
@@ -192,4 +187,4 @@ fn udisks_open(block_device: &Path) -> anyhow::Result<File> {
     )?;
 
     Ok(unsafe { File::from_raw_fd(res.0.into_fd()) })
-}
\ No newline at end of file
+}
diff --git a/gtk/src/main.rs b/gtk/src/main.rs
index 91b4f5f..6c6ee0e 100644
--- a/gtk/src/main.rs
+++ b/gtk/src/main.rs
@@ -4,7 +4,6 @@
 extern crate cascade;
 
 mod app;
-mod block;
 mod flash;
 mod hash;
 mod misc;
diff --git a/gtk/src/misc.rs b/gtk/src/misc.rs
index 805c215..e3066bc 100644
--- a/gtk/src/misc.rs
+++ b/gtk/src/misc.rs
@@ -1,3 +1,4 @@
+use dbus_udisks2::DiskDevice;
 use gdk;
 use gtk::{self, prelude::*, SelectionData};
 
@@ -27,3 +28,11 @@ where
     // Then handle the dropped data, setting the image if the dropped data is valid.
     widget.connect_drag_data_received(move |_view, _ctx, _x, _y, data, _info, _time| action(data));
 }
+
+pub fn device_label(device: &DiskDevice) -> String {
+    if device.drive.vendor.is_empty() {
+        format!("{} ({})", device.drive.model, device.parent.preferred_device.display())
+    } else {
+        format!("{} {} ({})", device.drive.vendor, device.drive.model, device.parent.preferred_device.display())
+    }
+}
diff --git a/src/task.rs b/src/task.rs
index 2997166..a7211e2 100644
--- a/src/task.rs
+++ b/src/task.rs
@@ -1,23 +1,24 @@
 use anyhow::Context;
-use async_std::{fs::File, path::Path, prelude::*};
+use async_std::{fs::File, prelude::*};
 use srmw::*;
 use std::{collections::HashMap, io::SeekFrom, time::Instant};
 
 pub trait Progress {
-    fn message(&mut self, path: &Path, kind: &str, message: &str);
+    type Device;
+    fn message(&mut self, device: &Self::Device, kind: &str, message: &str);
     fn finish(&mut self);
     fn set(&mut self, value: u64);
 }
 
 #[derive(new)]
-pub struct Task<P> {
+pub struct Task<P: Progress> {
     image: File,
 
     #[new(default)]
     pub writer: MultiWriter<File>,
 
     #[new(default)]
-    pub state: HashMap<usize, (Box<Path>, P)>,
+    pub state: HashMap<usize, (P::Device, P)>,
 
     #[new(value = "125")]
     pub millis_between: u64,
@@ -42,9 +43,9 @@ impl<P: Progress> Task<P> {
         Ok(())
     }
 
-    pub fn subscribe(&mut self, file: File, path: Box<Path>, progress: P) -> &mut Self {
+    pub fn subscribe(&mut self, file: File, device: P::Device, progress: P) -> &mut Self {
         let entity = self.writer.insert(file);
-        self.state.insert(entity, (path, progress));
+        self.state.insert(entity, (device, progress));
         self
     }
 
@@ -65,13 +66,13 @@ impl<P: Progress> Task<P> {
                     }
                 }
                 CopyEvent::Failure(entity, why) => {
-                    let (path, mut pb) = self.state.remove(&entity).expect("missing entity");
-                    pb.message(&path, "E", &format!("{}", why));
+                    let (device, mut pb) = self.state.remove(&entity).expect("missing entity");
+                    pb.message(&device, "E", &format!("{}", why));
                     pb.finish();
                 }
                 CopyEvent::SourceFailure(why) => {
-                    for (path, pb) in self.state.values_mut() {
-                        pb.message(&path, "E", &format!("{}", why));
+                    for (device, pb) in self.state.values_mut() {
+                        pb.message(&device, "E", &format!("{}", why));
                         pb.finish();
                     }
 


Test patch: