【问题标题】:Porting Unix to Windows- usage of pwd.h将 Unix 移植到 Windows - pwd.h 的使用
【发布时间】:2013-02-28 13:52:58
【问题描述】:

我正在尝试使用 MinGW 编译 libUnihan 代码,但遇到了需要移植的函数。该函数的目的是获得规范的路径表示。它使用pwd.h(这是POSIX,而MinGW不是),因此它可以通过检索包含pw_dirpasswd结构来解释使用'~'来表示主目录。我确实找到了一些信息here,以及realpathhere的端口,但我仍然完全不知道如何处理这个问题。使用 MinGW,我仍然有一个由 ~ 表示并位于 /home/nate 的主目录,但由于它不是 POSIX,我没有 pwd.h 来帮助我找到这个主目录的位置。

问:如何移植下面的函数以与 MinGW 正常工作?

/**
 * Return the canonicalized absolute pathname.
 *
 * It works exactly the same with realpath(3), except this function can handle the path with ~,
 * where realpath cannot.
 *
 * @param path The path to be resolved.
 * @param resolved_path Buffer for holding the resolved_path.
 * @return resolved path, NULL is the resolution is not sucessful.
 */
gchar*
truepath(const gchar *path, gchar *resolved_path){
    gchar workingPath[PATH_MAX];
    gchar fullPath[PATH_MAX];
    gchar *result=NULL;
    g_strlcpy(workingPath,path,PATH_MAX);

//     printf("*** path=%s \n",path);

    if ( workingPath[0] != '~' ){
        result = realpath(workingPath, resolved_path);
    }else{
        gchar *firstSlash, *suffix, *homeDirStr;
        struct passwd *pw;

        // initialize variables
        firstSlash = suffix = homeDirStr = NULL;

    firstSlash = strchr(workingPath, DIRECTORY_SEPARATOR);
        if (firstSlash == NULL)
            suffix = "";
        else
        {
            *firstSlash = 0;    // so userName is null terminated
            suffix = firstSlash + 1;
        }

        if (workingPath[1] == '\0')
            pw = getpwuid( getuid() );
        else
            pw = getpwnam( &workingPath[1] );

        if (pw != NULL)
            homeDirStr = pw->pw_dir;

        if (homeDirStr != NULL){
        gint ret=g_sprintf(fullPath, "%s%c%s", homeDirStr, DIRECTORY_SEPARATOR, suffix);
        if (ret>0){
        result = realpath(fullPath, resolved_path);
        }

    }
    }
    return result;
}

【问题讨论】:

  • 请注意,~ 本身表示$HOME 环境变量的值,通常但不一定与当前用户的~user 相同。后者是来自密码文件的信息。

标签: c windows unix mingw posix-api


【解决方案1】:

目的是实现~[username]/重映射逻辑。这种代码在 Linux/UNIX 环境中是有意义的,但最常见的用途只是引用用户自己的主目录。

为方便起见,我只是添加对常见情况的支持 - ~/ - 即当前用户,而不是支持更一般的情况 - 在这种情况下让它失败并出现明显错误。

获取当前用户主目录的函数是SHGetFolderPath

#include <windows.h>

char homeDirStr[MAX_PATH];
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, homeDirStr))) {
    // Do something with the path
} else {
    // Do something else
}

在用户查找失败的情况下,您粘贴的代码不会尝试替换该字符串,而只是返回 NULL,因此您可以进行模拟。

【讨论】:

  • 抛出一些编译错误;我应该传入什么而不是 CSIDL_PERSONAL?
  • 该变量 IIRC 也应该是 #include &lt;Shlobj.h&gt;。返回的路径是windows路径,我认为需要转换(不是在windows系统上检查是否有效)
  • 除非我遗漏了什么,realpath 也不在 mingw 中。
  • 忽略我对需要转换的路径的评论 - mingw 在内部使用 Windows 路径,因此无需额外更改即可工作