_wstat 表示以 MINGW64 中 \\?\ 为前缀的扩展长度路径

_wstat for extended-length path prefixed with \\?\ in MINGW64

提问人:AnHeuermann 提问时间:7/4/2023 更新时间:7/5/2023 访问量:67

问:

描述

我有一个 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.
C WinAPI mingw MSYS2 统计

评论

0赞 RbMm 7/4/2023
要检查文件是否存在,请使用 或 。“_wstat”在多个不同的库中实现,并且可以有不同的实现。GetFileAttributesWRtlDoesFileExists_U
0赞 AnHeuermann 7/4/2023
谢谢@RbMm。有了有多个版本的信息,我猜能够找到 MSVC 版本链接到通用 C 运行时,而 MING64 版本链接到哪个版本是为了向后兼容。对我来说,从 MSYS2/MINGW64 切换到 MSYS2/UCRT64 是完全可以的,并且解决了这个问题。使用 GetFileAttributesW 可以解决这个问题,但我的程序也需要支持 stat,并且为 Windows 和 Linux 提供相同的界面可以极大地简化事情。_wstatC:\WINDOWS\System32\ucrtbase.dllC:\WINDOWS\System32\msvcrt.dll
0赞 RbMm 7/4/2023
是的,不同的 crt 链接到不同的 dll 或静态库,以及 msvsrt.dll 和 ucrtbase.dll 中的实现是不同的。导出的函数相同,但代码不同

答:

0赞 AnHeuermann 7/5/2023 #1

问题是 Windows 上有两种 C 运行时变体。两者都实现了该功能,但它们的功能不同。_wstat

虽然 Visual Studio 链接到较新的 UCRT(通用 C 运行时),但MINGW64环境链接到较旧的 MSVCRT(Microsoft Visual C++ 运行时),后者较旧且缺少处理所需的功能。\\?\

但我想我最初问题的答案是,不可能在MINGW64中使用。 可以使用其他函数来测试文件是否存在(建议@RbMm和 )。 针对我的特定情况,解决方案是切换到链接到 UCRT 的 MSYS2 的 UCRT64 环境。\\?\_wstatGetFileAttributesWRtlDoesFileExists_U