Question

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;
}
Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top