Porting Unix to Windows- usage of pwd.h

c, mingw, posix-api, unix, windows

Solution

The purpose is to implement `~[username]/` remapping logic. This sort of code makes sense in Linux/UNIX environments, but the most common use is just to refer to the user's own home directory.

For expediency, I'd just add support for the common case - `~/` - i.e. the current user, and not bother supporting the more general case - have it fail with an obvious error in that case.

The function to get the current user's home directory is `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
}

In the case of a failed lookup of the user, the code you pasted does not try to replace that string, but simply returns `NULL`, so you could emulate that.

Problem

I'm trying to compile libUnihan code with MinGW, but have run into a function which requires porting. The purpose of the function is to get a canonical path representation. It uses `pwd.h` (which is POSIX, and MinGW isn't) so it can account for the use of '~' to mean the home directory by retrieving a `passwd` struct, which contains `pw_dir`. I did find a little information here, and a port of `realpath` here, but I am still entirely at a loss as to how to deal with this. With MinGW, I still have a home directory represented by `~` and located at `/home/nate`, but since it isn't POSIX, I don't have `pwd.h` to help me find where this home directory is. Q: How can I port the function below to work properly with 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; } ```

Original source