From 08021a3beb04e4d6ce44d4c47b8d4ce2e61e2351 Mon Sep 17 00:00:00 2001 From: Matej Horvat Date: Thu, 12 Jul 2018 17:14:15 +0200 Subject: [PATCH] fat: correctly read lowercase 8.3 filenames Historically, FAT stored filenames as uppercase. Modern windows versions will however be case-preserving. As a special case, all-uppercase files from old FAT filesystems will be converted to all-lowercase. There are two flags (one for filename and one for extension) indicating that this should be done. We did not make the distinction between these two flags when reading a filename. We still don't set the flags properly when writing files, but we always provide a long file name (even if the name would fit in the 8.3 pattern for a short one, so when reading back our own entries, we should always use the long filename and be safe. Change-Id: I1618a5be22705de3a06534442b62074445069764 --- .../kernel/file_systems/fat/encodings.cpp | 31 ++++++++++++------- .../kernel/file_systems/fat/encodings.h | 3 +- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/add-ons/kernel/file_systems/fat/encodings.cpp b/src/add-ons/kernel/file_systems/fat/encodings.cpp index 1076e0b99b..bfebd66e82 100644 --- a/src/add-ons/kernel/file_systems/fat/encodings.cpp +++ b/src/add-ons/kernel/file_systems/fat/encodings.cpp @@ -1507,7 +1507,7 @@ status_t generate_short_name(const uchar *name, const uchar *uni, /* called to convert a short ms-dos filename to utf8. XXX: encoding is assumed to be standard US code page, never shift-JIS */ -status_t msdos_to_utf8(uchar *msdos, uchar *utf8, uint32 utf8len, bool toLower) +status_t msdos_to_utf8(uchar *msdos, uchar *utf8, uint32 utf8len, uint8 toLower) { uchar normalized[8+1+3+1]; int32 i, pos; @@ -1516,16 +1516,19 @@ status_t msdos_to_utf8(uchar *msdos, uchar *utf8, uint32 utf8len, bool toLower) pos = 0; for (i=0;i<8;i++) { - if (msdos[i] == ' ') break; + if (msdos[i] == ' ') + break; normalized[pos++] = ((i == 0) && (msdos[i] == 5)) ? 0xe5 : - (toLower ? tolower(msdos[i]) : msdos[i]); + ((toLower & 0x08) ? tolower(msdos[i]) : msdos[i]); } if (msdos[8] != ' ') { normalized[pos++] = '.'; for (i=8;i<11;i++) { - if (msdos[i] == ' ') break; - normalized[pos++] = (toLower ? tolower(msdos[i]) : msdos[i]); + if (msdos[i] == ' ') + break; + normalized[pos++] + = ((toLower & 0x10) ? tolower(msdos[i]) : msdos[i]); } } @@ -1535,20 +1538,26 @@ status_t msdos_to_utf8(uchar *msdos, uchar *utf8, uint32 utf8len, bool toLower) (char *)utf8, (int32 *)&utf8len); } -bool requires_munged_short_name(const uchar *utf8name, const uchar nshort[11], int encoding) +bool requires_munged_short_name(const uchar *utf8name, const uchar nshort[11], + int encoding) { int leading = 0; int trailing = 0; int i, len; - if (encoding != MS_DOS_CONVERSION) return true; + if (encoding != MS_DOS_CONVERSION) + return true; for ( ; *utf8name != 0; utf8name++) { - if (!BEGINS_UTF8CHAR(*utf8name)) continue; - if (*utf8name == '.') break; + if (!BEGINS_UTF8CHAR(*utf8name)) + continue; + if (*utf8name == '.') + break; leading++; - if (leading > 8) return true; - if ((nshort[leading - 1] == '_') && (*utf8name != '_')) return true; + if (leading > 8) + return true; + if ((nshort[leading - 1] == '_') && (*utf8name != '_')) + return true; } if (*utf8name != 0) { diff --git a/src/add-ons/kernel/file_systems/fat/encodings.h b/src/add-ons/kernel/file_systems/fat/encodings.h index 782c4922ac..c902736cab 100644 --- a/src/add-ons/kernel/file_systems/fat/encodings.h +++ b/src/add-ons/kernel/file_systems/fat/encodings.h @@ -22,7 +22,8 @@ status_t munge_short_name1(uchar nshort[11], int iteration, int encoding); status_t generate_short_name(const uchar *name, const uchar *uni, uint32 unilen, uchar nshort[11], int *encoding); -status_t msdos_to_utf8(uchar *msdos, uchar *utf8, uint32 utf8len, bool toLower); +status_t msdos_to_utf8(uchar *msdos, uchar *utf8, uint32 utf8len, + uint8 toLower); #ifdef __cplusplus }