提问人:AnHeuermann 提问时间:7/4/2023 更新时间:7/5/2023 访问量:67
_wstat 表示以 MINGW64 中 \\?\ 为前缀的扩展长度路径
_wstat for extended-length path prefixed with \\?\ in MINGW64
问:
描述
我有一个 C 程序,需要使用 stat 检查文件是否存在。该文件的路径长度可以超过 (260 个字符),因此以 为前缀,请参阅 Windows 文档。
也允许使用特殊字符,因此它使用宽字符而不是 .MAX_PATH
\\?\
wchar_t*
char*
使用 MSVC 19 编译 C 程序时,可以找到该文件(空文本文件)。
但是当使用 MING64 编译相同的程序时失败并且找不到文件。_wstat
\\?\D:\path\to\test.txt
_wstat
如何重现
主.c
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <wchar.h>
int main(void) {
//wchar_t* unicodeLongFileName = L"D:\\path\\to\\test.txt"; // Works fine
wchar_t* unicodeLongFileName = L"\\\\?\\D:\\path\\to\\test.txt"; // Broken in MSYS2
struct _stat statbuf;
int res = _wstat(unicodeLongFileName, &statbuf);
if (res != 0) {
perror( "Problem getting information" );
switch (errno)
{
case ENOENT:
wprintf(L"File \n%ls\n not found.\n", unicodeLongFileName);
break;
case EINVAL:
printf("Invalid parameter to _stat.\n");
break;
default:
/* Should never be reached. */
printf("Unexpected error in _stat.\n");
}
return -1;
}
wprintf(L"Found file \n%ls\n.\n", unicodeLongFileName);
return 0;
}
CMake列表:.txt
cmake_minimum_required(VERSION 3.20)
project(Test_wstat)
add_executable(Test_wstat main.c)
使用以下命令编译 MSVC 版本:
cmake -S . -B build_msvc
cmake --build build_msvc/ --config Release
以及具有以下功能的 MSYS2 版本:
$ cmake -S . -B build_mingw -G "MSYS Makefiles" -DCMAKE_C_COMPILER=gcc -Wno-dev
$ make -C build_mingw/ all -Oline
这是在 Windows 12.2 上使用 MINGW64_NT MINGW64 的 gcc 10.0-22621 版本 3.3.4-341.x86_64)。
运行代码
创建新的文本文件
$ touch /d/path/to/test.txt
然后运行程序
> ./build_msvc/Release/Test_wstat.exe
Found file
\\?\D:\workspace\Testitesttest\issue-10898\test_c_program\test.txt
$ ./build_mingw/Test_wstat.exe
Problem getting information: No such file or directory
File
\\?\D:\path\to\test.txt
not found.
答:
0赞
AnHeuermann
7/5/2023
#1
问题是 Windows 上有两种 C 运行时变体。两者都实现了该功能,但它们的功能不同。_wstat
虽然 Visual Studio 链接到较新的 UCRT(通用 C 运行时),但MINGW64环境链接到较旧的 MSVCRT(Microsoft Visual C++ 运行时),后者较旧且缺少处理所需的功能。\\?\
但我想我最初问题的答案是,不可能在MINGW64中使用。
可以使用其他函数来测试文件是否存在(建议@RbMm和 )。
针对我的特定情况,解决方案是切换到链接到 UCRT 的 MSYS2 的 UCRT64 环境。\\?\
_wstat
GetFileAttributesW
RtlDoesFileExists_U
评论
GetFileAttributesW
RtlDoesFileExists_U
_wstat
C:\WINDOWS\System32\ucrtbase.dll
C:\WINDOWS\System32\msvcrt.dll