Замена функции readlink() в windows
readLink() присутствует в linux и определен в unistd.h, есть ли в Windows какая-либо подобная функция типа, пожалуйста, укажите, или же мы можем создать функцию с аналогичной функциональностью.Я хочу использовать ту же функциональность, что и readLink(), пожалуйста, предоставьте пользовательскую функцию для замены функции в случае, если нет предопределенной функции, которая предоставляет моментальный снимок кода
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
3 ответа
Окна не имеют readlink(2) эквивалент, но это действительно имеет Realpath(3) эквивалентны: GetFinalPathNameByHandleW()
.
См. Также: "Как получить информацию о цели символьной ссылки?" пользователя Ramond Chen.
Псевдокод выглядит следующим образом, без проверки ошибок:
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);
Обратите внимание, что realPathBuf
может быть "локальным UNC" путем, начиная с \\?\
.
Хорошо, как указано в комментариях, Windows не имеет api-ссылки readlink() как таковой. При этом код, приведенный в примере, выполняет то, что действительно не нужно обрабатывать непосредственно программой. Linux System API обрабатывает ссылки для вас. Кроме того, readlink не завершает null, он просто возвращает необработанные данные. При этом QFile предлагает независимый от платформы API для разрешения ссылок. QFile::symLinkTarget
предоставляет способ получить цель ссылки как в Windows, так и в Unix, и вашей программе не нужно связываться с этой частью ОС.
Процесс Windows для этого не однострочный, как в системах Linux/ Unix. На самом деле есть два разных типа ссылок на окнах. Я настоятельно рекомендую использовать такую среду, как Qt, при попытке кросс-платформенного ввода-вывода. Windows - это совсем другое животное, чем ваша типичная система linux/unix. Во-первых, это не система POSIX, а системы linux/unix.
Этот код в Windows работает как ссылка для чтения в Linux. Просто добавьте обработку ошибки и недостаточного размера буфера:
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;
}