'replacement for readlink() function in windows

readLink() is present in linux and is defined in unistd.h,is there any similar type function in windows please provide or else if we can make a function with similar functionality.I want to use the same functionality as readLink() please provide a user defined function for the replacement of the function in case no predefined function is there provided snap of the code

        char buffer[2048];

        readlink("/proc/self/exe", buffer, 2048);

        std::stringstream ss;
        ss << buffer;
        std::string exeFile = ss.str();
        std::string directory;

        const size_t last_slash_idx = exeFile.rfind('/');
        if (std::string::npos != last_slash_idx)
        {
            directory = exeFile.substr(0, last_slash_idx);
        }
        return directory;
    #endif 


Solution 1:[1]

Ok as stated in the comments Windows does not have a readlink() link api as such. That said the code given in the sample is doing something that really doesn't needed to handled directly by the program. Linux system api handles links for you. Also readlink does not null terminate it just returns raw data. That said QFile offers a platform independent api to resolve links. QFile::symLinkTarget provides a way to get the link target on both windows and unix without your program needing to mess with the OS specific side of this.

The windows process for doing this is not a one liner as it is on linux/unix systems. In fact there are actually two different types of links on windows. I highly recommend going through a framework such as Qt when trying to do cross platform I/O. Windows is a very different animal that your typical linux/unix system. For one thing it is not of POSIX system must linux/unix systems are.

Solution 2:[2]

Windows doesn't have a readlink(2) equivalent, but it does have a realpath(3) equivalent: GetFinalPathNameByHandleW().

See also: "How do I get information about the target of a symbolic link?" by Ramond Chen.

Pseudo-code is as follows, error checking omitted:

HANDLE hPath = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
DWORD len = GetFinalPathNameByHandleW(hPath, NULL, 0, FILE_NAME_OPENED);
WCHAR* realPathBuf = new WCHAR[len+1];
GetFinalPathNameByHandleW(hPath, realPathBuf, len, FILE_NAME_OPENED);

Note that realPathBuf may be a "local UNC" path, starting with \\?\.

Solution 3:[3]

This code on Windows works as readlink on Linux. Just add error and insufficient size buffer handling:

int readlink(const char* pathname, char* link, size_t linksize)
{
    HANDLE h = CreateFileA(pathname, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, NULL);
    char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
    DWORD dwBytesReturned = 0;
    DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer, sizeof(buffer), &dwBytesReturned, 0);
    typedef struct
    {
        ULONG ReparseTag;
        USHORT ReparseDataLength;
        USHORT Reserved;
        union
        {
            struct
            {
                USHORT SubstituteNameOffset;
                USHORT SubstituteNameLength;
                USHORT PrintNameOffset;
                USHORT PrintNameLength;
                ULONG Flags;
                WCHAR PathBuffer[1];
            } SymbolicLinkReparseBuffer;
            struct
            {
                USHORT SubstituteNameOffset;
                USHORT SubstituteNameLength;
                USHORT PrintNameOffset;
                USHORT PrintNameLength;
                WCHAR PathBuffer[1];
            } MountPointReparseBuffer;
            struct
            {
                UCHAR  DataBuffer[1];
            } GenericReparseBuffer;
        };
    } REPARSE_DATA_BUFFER;
    REPARSE_DATA_BUFFER* pRDB = reinterpret_cast<REPARSE_DATA_BUFFER*>(buffer);
    if (pRDB->ReparseTag == IO_REPARSE_TAG_SYMLINK)
    {
        int nameLength = pRDB->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
        wchar_t* pName = (wchar_t*)((char*)pRDB->SymbolicLinkReparseBuffer.PathBuffer + pRDB->SymbolicLinkReparseBuffer.SubstituteNameOffset);
        int bytesWritten = WideCharToMultiByte(CP_UTF8, 0, pName, nameLength, link, linksize, NULL, NULL);
        return bytesWritten;
    }
    CloseHandle(h);
    return -1;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 jonp
Solution 3 Igor