From 75bb9d129376cc1e5c2b13b0ba497b3803f7fb05 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Harabie=C5=84?= <rafalh92@outlook.com>
Date: Sat, 9 Oct 2021 23:12:16 +0200
Subject: [PATCH] Create volume label dir entry when formatting

Fixes #41
---
 CHANGELOG.md    |  5 +++++
 src/fs.rs       |  8 +++++++-
 tests/format.rs | 24 ++++++++++++++++++++++++
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fb991d2..a63eb4a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,11 @@
 Changelog
 =========
 
+0.3.6 (not released yet)
+------------------------
+Bug fixes:
+* Create directory entry with `VOLUME_ID` attribute when formatting if volume label was set in `FormatVolumeOptions`.
+
 0.3.5 (2021-01-23)
 ------------------------
 Bug fixes:
diff --git a/src/fs.rs b/src/fs.rs
index a5ee63f..cd51c4c 100644
--- a/src/fs.rs
+++ b/src/fs.rs
@@ -15,6 +15,7 @@ use byteorder_ext::{ReadBytesExt, WriteBytesExt};
 
 use boot_sector::{format_boot_sector, BiosParameterBlock, BootSector};
 use dir::{Dir, DirRawStream};
+use dir_entry::{DirFileEntryData, FileAttributes};
 use file::File;
 use table::{alloc_cluster, count_free_clusters, format_fat, read_fat_flags, ClusterIterator, RESERVED_FAT_ENTRIES};
 use time::{TimeProvider, DEFAULT_TIME_PROVIDER};
@@ -997,7 +998,12 @@ pub fn format_volume<T: ReadWriteSeek>(mut disk: T, options: FormatVolumeOptions
         write_zeros(&mut disk, boot.bpb.cluster_size() as u64)?;
     }
 
-    // TODO: create volume label dir entry if volume label is set
+    // Create volume label directory entry if volume label is specified in options
+    if let Some(volume_label) = options.volume_label {
+        disk.seek(SeekFrom::Start(root_dir_pos))?;
+        let volume_entry = DirFileEntryData::new(volume_label, FileAttributes::VOLUME_ID);
+        volume_entry.serialize(&mut disk)?;
+    }
 
     disk.seek(SeekFrom::Start(0))?;
     trace!("format_volume end");
diff --git a/tests/format.rs b/tests/format.rs
index b596532..5e2bf26 100644
--- a/tests/format.rs
+++ b/tests/format.rs
@@ -108,3 +108,27 @@ fn test_format_512mb_4096sec() {
     let fs = test_format_fs(opts, total_bytes);
     assert_eq!(fs.fat_type(), fatfs::FatType::Fat32);
 }
+
+#[test]
+fn test_format_empty_volume_label() {
+    let total_bytes = 2 * 1024 * MB;
+    let opts = fatfs::FormatVolumeOptions::new();
+    let fs = test_format_fs(opts, total_bytes);
+    assert_eq!(fs.volume_label(), "NO NAME");
+    assert_eq!(fs.read_volume_label_from_root_dir().unwrap(), None);
+}
+
+#[test]
+fn test_format_volume_label_and_id() {
+    let total_bytes = 2 * 1024 * MB;
+    let opts = fatfs::FormatVolumeOptions::new()
+        .volume_id(1234)
+        .volume_label(*b"VOLUMELABEL");
+    let fs = test_format_fs(opts, total_bytes);
+    assert_eq!(fs.volume_label(), "VOLUMELABEL");
+    assert_eq!(
+        fs.read_volume_label_from_root_dir().unwrap(),
+        Some("VOLUMELABEL".to_string())
+    );
+    assert_eq!(fs.volume_id(), 1234);
+}