'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 |