From 6787de1b8157b7a64860c68be6fbba8d25bbb3a6 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 14 May 2025 10:30:04 +0200 Subject: [PATCH 1/4] Update bincode to 2.0.1 --- Cargo.toml | 4 ++-- src/lib.rs | 52 +++++++++++++++++++++++++++++----------------------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7ecb7a5..f5c7b3a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,10 +18,10 @@ categories = ["filesystem"] name = "gptman" [dependencies] -bincode = "1.3.1" +bincode = { version = "2.0.1", features = ["serde"] } serde = { version = "1.0.116", features = ["derive"] } crc = "3.0.0" -thiserror = "1.0" +thiserror = "2.0.12" [features] default = [ "nix" ] diff --git a/src/lib.rs b/src/lib.rs index 62304b7..1b29912 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -70,7 +70,9 @@ #![deny(missing_docs)] -use bincode::{deserialize_from, serialize, serialize_into}; +use bincode::config::legacy; +use bincode::error::{DecodeError, EncodeError}; +use bincode::serde::{decode_from_std_read, encode_into_std_write, encode_to_vec}; use crc::{Crc, CRC_32_ISO_HDLC}; use serde::de::{SeqAccess, Visitor}; use serde::ser::SerializeTuple; @@ -96,7 +98,10 @@ const MAX_ALIGN: u64 = 16384; pub enum Error { /// Derialization errors. #[error("deserialization failed")] - Deserialize(#[from] bincode::Error), + Deserialize(#[from] DecodeError), + /// Serialization errors. + #[error("seserialization failed")] + Seserialize(#[from] EncodeError), /// I/O errors. #[error("generic I/O error")] Io(#[from] io::Error), @@ -230,11 +235,11 @@ impl GPTHeader { /// /// The field `last_usable_lba` is not updated to reflect the actual size of the disk. You must /// do this yourself by calling `update_from`. - pub fn read_from(reader: &mut R) -> Result + pub fn read_from(mut reader: &mut R) -> Result where R: Read + Seek, { - let gpt: GPTHeader = deserialize_from(reader)?; + let gpt: GPTHeader = decode_from_std_read(&mut reader, legacy())?; if &gpt.signature != b"EFI PART" { return Err(Error::InvalidSignature); @@ -271,14 +276,14 @@ impl GPTHeader { self.update_crc32_checksum(); writer.seek(SeekFrom::Start(self.primary_lba * sector_size))?; - serialize_into(&mut writer, &self)?; + encode_into_std_write(&self, &mut writer, legacy())?; for i in 0..self.number_of_partition_entries { writer.seek(SeekFrom::Start( self.partition_entry_lba * sector_size + u64::from(i) * u64::from(self.size_of_partition_entry), ))?; - serialize_into(&mut writer, &partitions[i as usize])?; + encode_into_std_write(&partitions[i as usize], &mut writer, legacy())?; } Ok(()) @@ -288,7 +293,7 @@ impl GPTHeader { pub fn generate_crc32_checksum(&self) -> u32 { let mut clone = self.clone(); clone.crc32_checksum = 0; - let data = serialize(&clone).expect("could not serialize"); + let data = encode_to_vec(&clone, legacy()).expect("could not serialize"); assert_eq!(data.len() as u32, clone.header_size); Crc::::new(&CRC_32_ISO_HDLC).checksum(&data) @@ -307,7 +312,7 @@ impl GPTHeader { let mut digest = crc.digest(); let mut wrote = 0; for x in partitions { - let data = serialize(&x).expect("could not serialize"); + let data = encode_to_vec(&x, legacy()).expect("could not serialize"); digest.update(&data); wrote += data.len(); } @@ -527,11 +532,11 @@ impl GPTPartitionEntry { } /// Read a partition entry from the reader at the current position. - pub fn read_from(reader: &mut R) -> bincode::Result + pub fn read_from(mut reader: &mut R) -> std::result::Result where - R: Read, + R: Read + ?Sized, { - deserialize_from(reader) + decode_from_std_read(&mut reader, legacy()) } /// Returns `true` if the partition entry is not used (type GUID == `[0; 16]`) @@ -1260,13 +1265,13 @@ impl GPT { Self::write_protective_mbr_into_impl(&mut writer, sector_size, true) } - fn write_protective_mbr_into_impl( + fn write_protective_mbr_into_impl( mut writer: &mut W, sector_size: u64, bootable: bool, ) -> Result<()> where - W: Write + Seek, + W: Write + Seek + ?Sized, { let size = writer.seek(SeekFrom::End(0))? / sector_size - 1; writer.seek(SeekFrom::Start(446))?; @@ -1283,13 +1288,14 @@ impl GPT { 0x01, 0x00, 0x00, 0x00, // LBA of first absolute sector ])?; // number of sectors in partition 1 - serialize_into( - &mut writer, + encode_into_std_write( &(if size > u64::from(u32::max_value()) { u32::max_value() } else { size as u32 }), + &mut writer, + legacy(), )?; writer.write_all(&[0; 16])?; // partition 2 writer.write_all(&[0; 16])?; // partition 3 @@ -1382,7 +1388,7 @@ mod test { } // NOTE: testing that serializing the PartitionName (and the whole struct) works - let data1 = serialize(&partition).unwrap(); + let data1 = encode_to_vec(&partition, legacy()).unwrap(); f.seek(SeekFrom::Start( gpt.partition_entry_lba * ss + u64::from(i) * u64::from(gpt.size_of_partition_entry), @@ -1432,7 +1438,7 @@ mod test { assert_eq!(gpt.header.partition_entry_lba, 2); gpt.header.crc32_checksum = 1; cur.seek(SeekFrom::Start(gpt.sector_size)).unwrap(); - serialize_into(&mut cur, &gpt.header).unwrap(); + encode_into_std_write(&gpt.header, &mut cur, legacy()).unwrap(); let maybe_gpt = GPT::read_from(&mut cur, gpt.sector_size); assert!(maybe_gpt.is_ok()); let gpt = maybe_gpt.unwrap(); @@ -1587,7 +1593,7 @@ mod test { gpt.header.crc32_checksum = 1; cur.seek(SeekFrom::Start(ss)).unwrap(); - serialize_into(&mut cur, &gpt.header).unwrap(); + encode_into_std_write(&gpt.header, &mut cur, legacy()).unwrap(); let maybe_gpt = GPT::read_from(&mut cur, ss); assert!(maybe_gpt.is_ok()); let gpt = maybe_gpt.unwrap(); @@ -1608,7 +1614,7 @@ mod test { gpt.header.crc32_checksum = 1; let backup_lba = gpt.header.backup_lba; cur.seek(SeekFrom::Start(ss)).unwrap(); - serialize_into(&mut cur, &gpt.header).unwrap(); + encode_into_std_write(&gpt.header, &mut cur, legacy()).unwrap(); let mut gpt = GPT::read_from(&mut cur, ss).unwrap(); assert!(!gpt.is_primary()); assert!(gpt.is_backup()); @@ -1628,7 +1634,7 @@ mod test { gpt.header.crc32_checksum = 1; cur.seek(SeekFrom::Start(ss)).unwrap(); - serialize_into(&mut cur, &gpt.header).unwrap(); + encode_into_std_write(&gpt.header, &mut cur, legacy()).unwrap(); let maybe_gpt = GPT::read_from(&mut cur, ss); assert!(maybe_gpt.is_ok()); let gpt = maybe_gpt.unwrap(); @@ -1658,7 +1664,7 @@ mod test { gpt.header.crc32_checksum = 1; cur.seek(SeekFrom::Start(ss)).unwrap(); - serialize_into(&mut cur, &gpt.header).unwrap(); + encode_into_std_write(&gpt.header, &mut cur, legacy()).unwrap(); let maybe_gpt = GPT::read_from(&mut cur, ss); assert!(maybe_gpt.is_ok()); let gpt = maybe_gpt.unwrap(); @@ -1862,8 +1868,8 @@ mod test { } cur.seek(SeekFrom::Start(446 + 8)).unwrap(); - let first_lba: u32 = deserialize_from(&mut cur).unwrap(); - let sectors: u32 = deserialize_from(&mut cur).unwrap(); + let first_lba: u32 = decode_from_std_read(&mut cur, legacy()).unwrap(); + let sectors: u32 = decode_from_std_read(&mut cur, legacy()).unwrap(); assert_eq!(first_lba, 1); assert_eq!(sectors, 99); } From 42167e631d206c1831f6313989c4c8e6dfe68519 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 14 May 2025 10:32:35 +0200 Subject: [PATCH 2/4] Update nix dependency --- .github/workflows/rust.yml | 4 ---- Cargo.toml | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index bba3b5f..a087b3f 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -49,10 +49,6 @@ jobs: - uses: Swatinem/rust-cache@v2 - - name: Set nix to minimum version (0.24) - if: matrix.rust == 'msrv' - run: cargo update -p nix --precise 0.24.0 - - name: cargo test run: cargo test --workspace ${{ matrix.rust-args }} diff --git a/Cargo.toml b/Cargo.toml index f5c7b3a..02c5a25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "1.1.4" authors = ["Cecile Tonglet "] license = "MIT OR Apache-2.0" edition = "2021" -rust-version = "1.65" +rust-version = "1.85" description = "Pure Rust library to read and modify GUID partition tables" repository = "https://github.com/rust-disk-partition-management/gptman" homepage = "https://github.com/rust-disk-partition-management/gptman" @@ -27,4 +27,4 @@ thiserror = "2.0.12" default = [ "nix" ] [target.'cfg(target_os = "linux")'.dependencies] -nix = { version = ">= 0.24, < 0.28", default-features = false, features = ["ioctl"], optional = true } +nix = { version = "0.30", default-features = false, features = ["ioctl"], optional = true } From 1cb499d020b820f6e71ec7758438bebe1fcea2a6 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 14 May 2025 10:37:43 +0200 Subject: [PATCH 3/4] clippy --- src/lib.rs | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1b29912..56685d4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -235,9 +235,9 @@ impl GPTHeader { /// /// The field `last_usable_lba` is not updated to reflect the actual size of the disk. You must /// do this yourself by calling `update_from`. - pub fn read_from(mut reader: &mut R) -> Result + pub fn read_from(mut reader: &mut R) -> Result where - R: Read + Seek, + R: Read + Seek + ?Sized, { let gpt: GPTHeader = decode_from_std_read(&mut reader, legacy())?; @@ -263,14 +263,14 @@ impl GPTHeader { /// Write the GPT header into a writer. This operation will update the CRC32 checksums of the /// current struct and seek at the location `primary_lba` before trying to write to disk. - pub fn write_into( + pub fn write_into( &mut self, mut writer: &mut W, sector_size: u64, partitions: &[GPTPartitionEntry], ) -> Result<()> where - W: Write + Seek, + W: Write + Seek + ?Sized, { self.update_partition_entry_array_crc32(partitions); self.update_crc32_checksum(); @@ -312,7 +312,7 @@ impl GPTHeader { let mut digest = crc.digest(); let mut wrote = 0; for x in partitions { - let data = encode_to_vec(&x, legacy()).expect("could not serialize"); + let data = encode_to_vec(x, legacy()).expect("could not serialize"); digest.update(&data); wrote += data.len(); } @@ -332,9 +332,9 @@ impl GPTHeader { /// Updates the header to match the specifications of the seeker given in argument. /// `first_usable_lba`, `last_usable_lba`, `primary_lba`, `backup_lba`, `partition_entry_lba` /// will be updated after this operation. - pub fn update_from(&mut self, seeker: &mut S, sector_size: u64) -> Result<()> + pub fn update_from(&mut self, seeker: &mut S, sector_size: u64) -> Result<()> where - S: Seek, + S: Seek + ?Sized, { let partition_array_size = (u64::from(self.number_of_partition_entries) * u64::from(self.size_of_partition_entry) @@ -720,9 +720,9 @@ impl GPT { /// let gpt = gptman::GPT::read_from(&mut f, 512) /// .expect("could not read the partition table"); /// ``` - pub fn read_from(mut reader: &mut R, sector_size: u64) -> Result + pub fn read_from(mut reader: &mut R, sector_size: u64) -> Result where - R: Read + Seek, + R: Read + Seek + ?Sized, { use self::Error::*; @@ -784,9 +784,9 @@ impl GPT { /// let gpt_4096 = gptman::GPT::find_from(&mut f_4096) /// .expect("could not read the partition table"); /// ``` - pub fn find_from(mut reader: &mut R) -> Result + pub fn find_from(mut reader: &mut R) -> Result where - R: Read + Seek, + R: Read + Seek + ?Sized, { use self::Error::*; @@ -891,9 +891,9 @@ impl GPT { /// gpt.write_into(&mut cur) /// .expect("could not write GPT to disk"); /// ``` - pub fn write_into(&mut self, mut writer: &mut W) -> Result + pub fn write_into(&mut self, mut writer: &mut W) -> Result where - W: Write + Seek, + W: Write + Seek + ?Sized, { self.check_partition_guids()?; self.check_partition_boundaries()?; @@ -1238,9 +1238,9 @@ impl GPT { /// starting at byte 446 and ending at byte 511. Any existing data will be overwritten. /// /// See also: [`Self::write_bootable_protective_mbr_into`]. - pub fn write_protective_mbr_into(mut writer: &mut W, sector_size: u64) -> Result<()> + pub fn write_protective_mbr_into(mut writer: &mut W, sector_size: u64) -> Result<()> where - W: Write + Seek, + W: Write + Seek + ?Sized, { Self::write_protective_mbr_into_impl(&mut writer, sector_size, false) } @@ -1255,12 +1255,9 @@ impl GPT { ///
Some systems will not consider a disk to be bootable in UEFI mode /// if the pMBR is marked as bootable, so this should only be used if booting on legacy BIOS /// systems is a requirement.
- pub fn write_bootable_protective_mbr_into( - mut writer: &mut W, - sector_size: u64, - ) -> Result<()> + pub fn write_bootable_protective_mbr_into(mut writer: &mut W, sector_size: u64) -> Result<()> where - W: Write + Seek, + W: Write + Seek + ?Sized, { Self::write_protective_mbr_into_impl(&mut writer, sector_size, true) } @@ -1289,11 +1286,11 @@ impl GPT { ])?; // number of sectors in partition 1 encode_into_std_write( - &(if size > u64::from(u32::max_value()) { - u32::max_value() + if size > u64::from(u32::MAX) { + u32::MAX } else { size as u32 - }), + }, &mut writer, legacy(), )?; From ee306b2de60799c24cc307440ecb275acbf8badc Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 14 May 2025 10:38:33 +0200 Subject: [PATCH 4/4] CI: update workflow --- .github/workflows/rust.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index a087b3f..b57f396 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -13,6 +13,7 @@ env: jobs: test: strategy: + fail-fast: false matrix: os: - ubuntu-latest @@ -25,7 +26,7 @@ jobs: - os: ubuntu-latest rust: msrv lint: 1 - - rust: stable + - rust: msrv rust-args: --all-features runs-on: ${{ matrix.os }} steps: @@ -38,7 +39,7 @@ jobs: ver="${{ matrix.rust }}" if [ "$ver" = msrv ]; then ver=$(cargo metadata --format-version 1 --no-deps | \ - jq -r '.packages[0].rust_version') + jq -r 'first(.packages[] | select(.rust_version != null).rust_version)') extra=(-c rustfmt -c clippy) fi rustup toolchain install "$ver" --profile minimal --no-self-update "${extra[@]}" @@ -49,13 +50,10 @@ jobs: - uses: Swatinem/rust-cache@v2 - - name: cargo test - run: cargo test --workspace ${{ matrix.rust-args }} + - run: cargo test --workspace ${{ matrix.rust-args }} - - name: rustfmt + - run: cargo fmt --all -- --check if: github.event_name == 'pull_request' && matrix.lint - run: cargo fmt --all -- --check - - name: clippy + - run: cargo clippy --all --tests --all-features -- -D warnings if: github.event_name == 'pull_request' && matrix.lint - run: cargo clippy --all --tests --all-features -- -D warnings