mirror of
https://git.savannah.gnu.org/git/gnulib.git
synced 2026-10-24 00:48:56 +03:00
stat, fstat: Optimize on native Windows.
* lib/stat-w32.c: Include <wchar.h>. (GetFinalPathNameByHandleFuncType, GetFinalPathNameByHandleFunc): Remove, along with the GetFinalPathNameByHandle and VOLUME_NAME_NONE macros. (GetFileInformationByHandleExFuncType, GetFileInformationByHandleExFunc): Declare regardless of _GL_WINDOWS_STAT_INODES, as the file name lookup needs them too. (initialize): Do not resolve GetFinalPathNameByHandleA. (_gl_fstat_by_handle): Get the name from GetFileInformationByHandleEx, since it is faster than GetFinalPathNameByHandle and still operates on the target of symbolic links. Copyright-paperwork-exempt: Yes
This commit is contained in:
committed by
Bruno Haible
parent
806bd058e1
commit
0f83f0223b
15
ChangeLog
15
ChangeLog
@@ -1,3 +1,18 @@
|
||||
2026-09-05 Oleg Tolmatcev <oleg.tolmatcev@gmail.com>
|
||||
|
||||
stat, fstat: Optimize on native Windows.
|
||||
* lib/stat-w32.c: Include <wchar.h>.
|
||||
(GetFinalPathNameByHandleFuncType, GetFinalPathNameByHandleFunc):
|
||||
Remove, along with the GetFinalPathNameByHandle and VOLUME_NAME_NONE
|
||||
macros.
|
||||
(GetFileInformationByHandleExFuncType,
|
||||
GetFileInformationByHandleExFunc): Declare regardless of
|
||||
_GL_WINDOWS_STAT_INODES, as the file name lookup needs them too.
|
||||
(initialize): Do not resolve GetFinalPathNameByHandleA.
|
||||
(_gl_fstat_by_handle): Get the name from GetFileInformationByHandleEx,
|
||||
since it is faster than GetFinalPathNameByHandle and still operates
|
||||
on the target of symbolic links.
|
||||
|
||||
2026-09-05 Oleg Tolmatcev <oleg.tolmatcev@gmail.com>
|
||||
|
||||
stat: Fix handling of symbolic links on native Windows.
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <wchar.h>
|
||||
#include <windows.h>
|
||||
|
||||
/* Specification. */
|
||||
@@ -54,13 +55,6 @@
|
||||
/* Don't assume that UNICODE is not defined. */
|
||||
#undef LoadLibrary
|
||||
#define LoadLibrary LoadLibraryA
|
||||
#undef GetFinalPathNameByHandle
|
||||
#define GetFinalPathNameByHandle GetFinalPathNameByHandleA
|
||||
|
||||
/* Older mingw headers do not define VOLUME_NAME_NONE. */
|
||||
#ifndef VOLUME_NAME_NONE
|
||||
# define VOLUME_NAME_NONE 4
|
||||
#endif
|
||||
|
||||
#if !WIN32_ASSUME_VISTA
|
||||
|
||||
@@ -68,20 +62,12 @@
|
||||
# define GetProcAddress \
|
||||
(void *) GetProcAddress
|
||||
|
||||
# if _GL_WINDOWS_STAT_INODES == 2
|
||||
/* GetFileInformationByHandleEx was introduced only in Windows Vista. */
|
||||
typedef DWORD (WINAPI * GetFileInformationByHandleExFuncType) (HANDLE hFile,
|
||||
FILE_INFO_BY_HANDLE_CLASS fiClass,
|
||||
LPVOID lpBuffer,
|
||||
DWORD dwBufferSize);
|
||||
static GetFileInformationByHandleExFuncType GetFileInformationByHandleExFunc = NULL;
|
||||
# endif
|
||||
/* GetFinalPathNameByHandle was introduced only in Windows Vista. */
|
||||
typedef DWORD (WINAPI * GetFinalPathNameByHandleFuncType) (HANDLE hFile,
|
||||
LPSTR lpFilePath,
|
||||
DWORD lenFilePath,
|
||||
DWORD dwFlags);
|
||||
static GetFinalPathNameByHandleFuncType GetFinalPathNameByHandleFunc = NULL;
|
||||
static BOOL initialized = FALSE;
|
||||
|
||||
static void
|
||||
@@ -89,21 +75,14 @@ initialize (void)
|
||||
{
|
||||
HMODULE kernel32 = LoadLibrary ("kernel32.dll");
|
||||
if (kernel32 != NULL)
|
||||
{
|
||||
# if _GL_WINDOWS_STAT_INODES == 2
|
||||
GetFileInformationByHandleExFunc =
|
||||
(GetFileInformationByHandleExFuncType) GetProcAddress (kernel32, "GetFileInformationByHandleEx");
|
||||
# endif
|
||||
GetFinalPathNameByHandleFunc =
|
||||
(GetFinalPathNameByHandleFuncType) GetProcAddress (kernel32, "GetFinalPathNameByHandleA");
|
||||
}
|
||||
GetFileInformationByHandleExFunc =
|
||||
(GetFileInformationByHandleExFuncType) GetProcAddress (kernel32, "GetFileInformationByHandleEx");
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# define GetFileInformationByHandleExFunc GetFileInformationByHandleEx
|
||||
# define GetFinalPathNameByHandleFunc GetFinalPathNameByHandle
|
||||
|
||||
#endif
|
||||
|
||||
@@ -272,28 +251,33 @@ _gl_fstat_by_handle (HANDLE h, const char *path, struct stat *buf)
|
||||
name suffix.
|
||||
If the file name is already known, use it. Otherwise, for
|
||||
non-empty files, it can be determined through
|
||||
GetFinalPathNameByHandle
|
||||
<https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfinalpathnamebyhandlea>
|
||||
or through
|
||||
GetFileInformationByHandleEx with argument FileNameInfo
|
||||
<https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getfileinformationbyhandleex>
|
||||
<https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_file_name_info>
|
||||
Both require -D_WIN32_WINNT=_WIN32_WINNT_VISTA or higher. */
|
||||
This requires -D_WIN32_WINNT=_WIN32_WINNT_VISTA or higher. */
|
||||
if (info.nFileSizeHigh > 0 || info.nFileSizeLow > 0)
|
||||
{
|
||||
char fpath[PATH_MAX];
|
||||
if (GetFinalPathNameByHandleFunc != NULL
|
||||
&& GetFinalPathNameByHandleFunc (h, fpath, sizeof (fpath), VOLUME_NAME_NONE)
|
||||
< sizeof (fpath))
|
||||
/* Room for the header and for the file name. */
|
||||
union
|
||||
{
|
||||
size_t length = strlen (fpath);
|
||||
if (length >= 4 && fpath[length - 4] == '.')
|
||||
FILE_NAME_INFO info;
|
||||
char storage[sizeof (FILE_NAME_INFO)
|
||||
+ PATH_MAX * sizeof (WCHAR)];
|
||||
} fni;
|
||||
if (GetFileInformationByHandleExFunc != NULL
|
||||
&& GetFileInformationByHandleExFunc (h, FileNameInfo,
|
||||
&fni.info,
|
||||
sizeof (fni)))
|
||||
{
|
||||
size_t length = fni.info.FileNameLength / sizeof (WCHAR);
|
||||
const WCHAR *name = fni.info.FileName;
|
||||
if (length >= 4 && name[length - 4] == L'.')
|
||||
{
|
||||
const char *suffix = fpath + length - 3;
|
||||
if (_stricmp (suffix, "exe", 3) == 0
|
||||
|| _stricmp (suffix, "bat", 3) == 0
|
||||
|| _stricmp (suffix, "cmd", 3) == 0
|
||||
|| _stricmp (suffix, "com", 3) == 0)
|
||||
const WCHAR *suffix = name + length - 3;
|
||||
if (_wcsnicmp (suffix, L"exe", 3) == 0
|
||||
|| _wcsnicmp (suffix, L"bat", 3) == 0
|
||||
|| _wcsnicmp (suffix, L"cmd", 3) == 0
|
||||
|| _wcsnicmp (suffix, L"com", 3) == 0)
|
||||
mode |= S_IEXEC_UGO;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user