summaryrefslogtreecommitdiff
path: root/Kernel/FileSystem
diff options
context:
space:
mode:
authorTaj Morton <tajmorton@gmail.com>2022-12-31 13:01:26 -0800
committerSam Atkins <atkinssj@gmail.com>2023-01-04 09:02:13 +0000
commit31eeea08baac69377357cc8f801af180a4ef141d (patch)
treedad416cc3482d7658738df143aa22c8f717dfcab /Kernel/FileSystem
parentf2253d11e5ddfebcc1b626343c741e44f5666b49 (diff)
downloadserenity-31eeea08baac69377357cc8f801af180a4ef141d.zip
Kernel/FileSystem: Fix handling of FAT names that don't fill an entry
* Fix bug where last character of a filename or extension would be truncated (HELLO.TXT -> HELL.TX). * Fix bug where additional NULL characters would be added to long filenames that did not completely fill one of the Long Filename Entry character fields.
Diffstat (limited to 'Kernel/FileSystem')
-rw-r--r--Kernel/FileSystem/FATFS/Inode.cpp17
-rw-r--r--Kernel/FileSystem/FATFS/Inode.h3
2 files changed, 17 insertions, 3 deletions
diff --git a/Kernel/FileSystem/FATFS/Inode.cpp b/Kernel/FileSystem/FATFS/Inode.cpp
index d2abf7bf18..65358de119 100644
--- a/Kernel/FileSystem/FATFS/Inode.cpp
+++ b/Kernel/FileSystem/FATFS/Inode.cpp
@@ -167,7 +167,20 @@ ErrorOr<NonnullOwnPtr<KString>> FATInode::compute_filename(FATEntry& entry, Vect
filename.append(lfn_entry.characters3[1]);
}
- return TRY(KString::try_create(byte_terminated_string(filename.string_view(), lfn_entry_text_termination)));
+ // Long Filenames have two terminators:
+ // 1. Completely unused "entries" (the `characterN` fields of
+ // `lfn_entry`) are filled with 0xFF (`lfn_entry_unused_byte`).
+ // 2. Partially used entries (within `characterN`) are null-padded.
+ //
+ // `filename` is truncated first to eliminate unused entries, and
+ // then further truncated to remove any existing null padding characters.
+ //
+ // Page 8 of the Long Filename Specification
+ // (http://www.osdever.net/documents/LongFileName.pdf)
+ // details this encoding ("If the long name does not fill...").
+ return TRY(KString::try_create(
+ byte_terminated_string(
+ byte_terminated_string(filename.string_view(), lfn_entry_unused_byte), lfn_entry_character_termination)));
}
VERIFY_NOT_REACHED();
@@ -184,7 +197,7 @@ Time FATInode::fat_date_time(FATPackedDate date, FATPackedTime time)
StringView FATInode::byte_terminated_string(StringView string, u8 fill_byte)
{
if (auto index = string.find_last_not(fill_byte); index.has_value())
- return string.substring_view(0, index.value());
+ return string.substring_view(0, index.value() + 1);
return string;
}
diff --git a/Kernel/FileSystem/FATFS/Inode.h b/Kernel/FileSystem/FATFS/Inode.h
index 23b1a2974c..699df808bb 100644
--- a/Kernel/FileSystem/FATFS/Inode.h
+++ b/Kernel/FileSystem/FATFS/Inode.h
@@ -36,7 +36,8 @@ private:
static constexpr u8 end_entry_byte = 0x00;
static constexpr u8 unused_entry_byte = 0xE5;
- static constexpr u8 lfn_entry_text_termination = 0xFF;
+ static constexpr u8 lfn_entry_character_termination = 0x00;
+ static constexpr u8 lfn_entry_unused_byte = 0xFF;
static constexpr u16 first_fat_year = 1980;