The function is called a lot, I believe something like this would improve its performance in general.
-- v2: ntdll: Lookup extension from the end in hash_short_file_name. ntdll: Use invalid char lookup table in lookup_unix_name. ntdll: Use invalid char lookup table in nt_to_unix_file_name_no_root. ntdll: Use invalid char lookup table in is_legal_8dot3_name. ntdll: Use invalid char lookup table in is_invalid_dos_char.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/ntdll/unix/file.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 957d9f3b801..b1b09e80e5a 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -250,9 +250,12 @@ static pthread_mutex_t mnt_mutex = PTHREAD_MUTEX_INITIALIZER; /* check if a given Unicode char is OK in a DOS short name */ static inline BOOL is_invalid_dos_char( WCHAR ch ) { - static const WCHAR invalid_chars[] = { INVALID_DOS_CHARS,'~','.',0 }; - if (ch > 0x7f) return TRUE; - return wcschr( invalid_chars, ch ) != NULL; + static const char is_invalid[0x7f] = + { + ['*'] = 1, ['?'] = 1, ['<'] = 1, ['>'] = 1, ['|'] = 1, ['"'] = 1, ['+'] = 1, ['='] = 1, + [','] = 1, [';'] = 1, ['['] = 1, [']'] = 1, [' '] = 1, ['~'] = 1, ['.'] = 1, + }; + return ch <= 0x7f ? is_invalid[ch] : TRUE; }
/* check if the device can be a mounted volume */
From: Rémi Bernon rbernon@codeweavers.com
Instead of costly wcschr. --- dlls/ntdll/unix/file.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index b1b09e80e5a..d3c7e7d6751 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -169,7 +169,6 @@ typedef struct #define IS_SEPARATOR(ch) ((ch) == '\' || (ch) == '/')
#define INVALID_NT_CHARS '*','?','<','>','|','"' -#define INVALID_DOS_CHARS INVALID_NT_CHARS,'+','=',',',';','[',']',' ','\345'
#define MAX_DIR_ENTRY_LEN 255 /* max length of a directory entry in chars */
@@ -258,6 +257,16 @@ static inline BOOL is_invalid_dos_char( WCHAR ch ) return ch <= 0x7f ? is_invalid[ch] : TRUE; }
+static inline BOOL is_invalid_8dot3_char( WCHAR ch ) +{ + static const char is_invalid[0x7f] = + { + ['*'] = 1, ['?'] = 1, ['<'] = 1, ['>'] = 1, ['|'] = 1, ['"'] = 1, ['+'] = 1, ['='] = 1, + [','] = 1, [';'] = 1, ['['] = 1, [']'] = 1, [' '] = 1, [':'] = 1, ['/'] = 1, ['\'] = 1, + }; + return ch <= 0x7f ? is_invalid[ch] : TRUE; +} + /* check if the device can be a mounted volume */ static inline BOOL is_valid_mounted_device( const struct stat *st ) { @@ -1461,7 +1470,6 @@ static BOOLEAN match_filename( const WCHAR *name, int length, const UNICODE_STRI */ static BOOLEAN is_legal_8dot3_name( const WCHAR *name, int len ) { - static const WCHAR invalid_chars[] = { INVALID_DOS_CHARS,':','/','\',0 }; int i, dot = -1;
if (len > 12) return FALSE; @@ -1471,8 +1479,7 @@ static BOOLEAN is_legal_8dot3_name( const WCHAR *name, int len )
for (i = 0; i < len; i++) { - if (name[i] > 0x7f) return FALSE; - if (wcschr( invalid_chars, name[i] )) return FALSE; + if (is_invalid_8dot3_char( name[i] )) return FALSE; if (name[i] == '.') { if (dot != -1) return FALSE;
From: Rémi Bernon rbernon@codeweavers.com
To lookup invalid NT chars, instead of costly wcschr. --- dlls/ntdll/unix/file.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index d3c7e7d6751..e41a7c214f1 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -267,6 +267,16 @@ static inline BOOL is_invalid_8dot3_char( WCHAR ch ) return ch <= 0x7f ? is_invalid[ch] : TRUE; }
+static inline BOOL is_invalid_nt_char( WCHAR ch ) +{ + static const char is_invalid[0x7f] = + { + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + ['*'] = 1, ['?'] = 1, ['<'] = 1, ['>'] = 1, ['|'] = 1, ['"'] = 1, + }; + return ch <= 0x7f ? is_invalid[ch] : FALSE; +} + /* check if the device can be a mounted volume */ static inline BOOL is_valid_mounted_device( const struct stat *st ) { @@ -3473,7 +3483,6 @@ static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char UINT disposition ) { static const WCHAR unixW[] = {'u','n','i','x'}; - static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, 0 };
NTSTATUS status = STATUS_SUCCESS; const WCHAR *name; @@ -3500,8 +3509,7 @@ static NTSTATUS nt_to_unix_file_name_no_root( const UNICODE_STRING *nameW, char for (pos = 0; pos < name_len && pos <= MAX_DIR_ENTRY_LEN; pos++) { if (name[pos] == '\') break; - if (name[pos] < 32 || wcschr( invalid_charsW, name[pos] )) - return STATUS_OBJECT_NAME_INVALID; + if (is_invalid_nt_char( name[pos] )) return STATUS_OBJECT_NAME_INVALID; prefix[pos] = (name[pos] >= 'A' && name[pos] <= 'Z') ? name[pos] + 'a' - 'A' : name[pos]; } if (pos > MAX_DIR_ENTRY_LEN) return STATUS_OBJECT_NAME_INVALID;
From: Rémi Bernon rbernon@codeweavers.com
To lookup invalid unix chars, instead of costly wcschr. --- dlls/ntdll/unix/file.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index e41a7c214f1..09370508a3f 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -168,8 +168,6 @@ typedef struct
#define IS_SEPARATOR(ch) ((ch) == '\' || (ch) == '/')
-#define INVALID_NT_CHARS '*','?','<','>','|','"' - #define MAX_DIR_ENTRY_LEN 255 /* max length of a directory entry in chars */
#define MAX_IGNORED_FILES 4 @@ -277,6 +275,12 @@ static inline BOOL is_invalid_nt_char( WCHAR ch ) return ch <= 0x7f ? is_invalid[ch] : FALSE; }
+static inline BOOL is_invalid_unix_char( WCHAR ch ) +{ + if (ch == '/') return TRUE; + return is_invalid_nt_char( ch ); +} + /* check if the device can be a mounted volume */ static inline BOOL is_valid_mounted_device( const struct stat *st ) { @@ -3363,7 +3367,6 @@ done: static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer, int unix_len, int pos, UINT disposition, BOOL is_unix ) { - static const WCHAR invalid_charsW[] = { INVALID_NT_CHARS, '/', 0 }; NTSTATUS status; int ret; struct stat st; @@ -3390,7 +3393,7 @@ static NTSTATUS lookup_unix_name( const WCHAR *name, int name_len, char **buffer { if (!*ptr) return STATUS_OBJECT_NAME_INVALID; if (is_unix) continue; - if (*ptr < 32 || wcschr( invalid_charsW, *ptr )) return STATUS_OBJECT_NAME_INVALID; + if (is_invalid_unix_char( *ptr )) return STATUS_OBJECT_NAME_INVALID; } }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/ntdll/unix/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 09370508a3f..002ff6ccf94 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -1367,7 +1367,8 @@ static ULONG hash_short_file_name( const WCHAR *name, int length, LPWSTR buffer }
/* Find last dot for start of the extension */ - for (p = name + 1, ext = NULL; p < end - 1; p++) if (*p == '.') ext = p; + for (ext = end - 2; ext > name; ext--) if (*ext == '.') break; + if (ext == name) ext = NULL;
/* Copy first 4 chars, replacing invalid chars with '_' */ for (i = 4, p = name, dst = buffer; i > 0; i--, p++)
v2: Remove unnecessary define, rebase on some older revision to make sure the Gitlab CI test suite runs.
This merge request was closed by Rémi Bernon.