Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to read a symbolic link? Is there a POSIX readlink() equivalent?

504 views
Skip to first unread message

Beman Dawes

unread,
Dec 9, 2009, 6:45:03 PM12/9/09
to
POSIX has readlink() - read the contents of a symbolic link. In other
words, if "foo" is a symlink to "baz/bar", the result is the string
"baz/bar"

What is the Win32 (Vista and later) equivalent? Presumably there is
one, since from the command line, dir displays the desired information
for symbolic links.

TIA,

--Beman

Kerem Gümrükcü

unread,
Dec 9, 2009, 9:33:39 PM12/9/09
to

Hi Bernan,

[Symbolic Link Effects on File Systems Functions]
http://msdn.microsoft.com/en-us/library/aa365682(VS.85).aspx

[Symbolic Links]
http://msdn.microsoft.com/en-us/library/aa365680(VS.85).aspx

Read about "Hard Links", "Junktions",...also have a look at IOCTL's
like FSCTL_GET_REPARSE_POINT and familiar for more information.
You should also pass the symbolic link handle opened with CreateFile(...)
to GetFinalPathNameByHandle(...) to get the target file, that works Vista
and
upper only. AFAIK this also works for UNC Paths (local only!),...

Good Luck!

Regards

Kerem

--
-----------------------
Beste Gr�sse / Best regards / Votre bien devoue
Kerem G�mr�kc�
Latest Project: http://www.pro-it-education.de/software/deviceremover
Latest Open-Source Projects: http://entwicklung.junetz.de
-----------------------

"Beman Dawes" <beman...@gmail.com> schrieb im Newsbeitrag
news:d87675af-86d1-4977...@z41g2000yqz.googlegroups.com...

Beman Dawes

unread,
Dec 11, 2009, 9:52:35 AM12/11/09
to
On Dec 9, 9:33 pm, Kerem Gümrükcü <kareem...@hotmail.com> wrote:

> [Symbolic Link Effects on File Systems Functions]http://msdn.microsoft.com/en-us/library/aa365682(VS.85).aspx
>
> [Symbolic Links]http://msdn.microsoft.com/en-us/library/aa365680(VS.85).aspx
>
> Read about "Hard Links", "Junktions",...also have a look at IOCTL's
> like FSCTL_GET_REPARSE_POINT and familiar for more information.

Ah! I'd missed that. Works well. See sample program below.

> You should also pass the symbolic link handle opened with CreateFile(...)
> to GetFinalPathNameByHandle(...) to get the target file, that works Vista
> and
> upper only. AFAIK this also works for UNC Paths (local only!),...

The reported hangs with GetFinalPathNameByHandle(...) scared me off
from that approach.

See http://www.codeproject.com/Articles/35202/GetFinalPathNameByHandle-API-Hangs.aspx

Thanks for the sugestions! Very helpful!

--Beman

------------

#include <windows.h>
#include <string>
#include <iostream>

// REPARSE_DATA_BUFFER related definitions are found in ntifs.h,
// which is part of the Device Driver Kit rather than the SDK.
// See http://msdn.microsoft.com/en-us/library/ms791514.aspx

#define SYMLINK_FLAG_RELATIVE 1

typedef struct _REPARSE_DATA_BUFFER {
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union {
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
/* Example of distinction between substitute and print names:
mklink /d ldrive c:\
SubstituteName: c:\\??\
PrintName: c:\
*/
} SymbolicLinkReparseBuffer;
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct {
UCHAR DataBuffer[1];
} GenericReparseBuffer;
};
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;

#define REPARSE_DATA_BUFFER_HEADER_SIZE \
FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer)

#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 )

int main(int argc, char * argv[])
{
union info_t
{
char buf[REPARSE_DATA_BUFFER_HEADER_SIZE
+MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
REPARSE_DATA_BUFFER rdb;
} info;

HANDLE h = ::CreateFile(argv[1], GENERIC_READ, 0, 0,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS
| FILE_FLAG_OPEN_REPARSE_POINT, 0);

if (h == INVALID_HANDLE_VALUE)
{
std::cout << "INVALID_HANDLE_VALUE\n";
return 1;
}

DWORD sz;

if (::DeviceIoControl(
h, // file or directory handle
FSCTL_GET_REPARSE_POINT, // dwIoControlCode
0, // lpInBuffer
0, // nInBufferSize
info.buf, // output buffer
sizeof(info), // size of output buffer
&sz, // number of bytes returned
0 // OVERLAPPED structure
) == 0)
{
std::cout << "Error: " << ::GetLastError() << "\n";
if (::GetLastError() == 4390L) std::cout <<
"ERROR_NOT_A_REPARSE_POINT\n";
return 1;
}

std::cout
<< "REPARSE_DATA_BUFFER_HEADER_SIZE: "
<< REPARSE_DATA_BUFFER_HEADER_SIZE << '\n'
<< "info.rdb.ReparseDataLength: "
<< info.rdb.ReparseDataLength << '\n'
<< "info.rdb.SymbolicLinkReparseBuffer.SubstituteNameOffset: "
<< info.rdb.SymbolicLinkReparseBuffer.SubstituteNameOffset << '\n'
<< "info.rdb.SymbolicLinkReparseBuffer.SubstituteNameLength: "
<< info.rdb.SymbolicLinkReparseBuffer.SubstituteNameLength << '\n'
<< "info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset: "
<< info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset << '\n'
<< "info.rdb.SymbolicLinkReparseBuffer.PrintNameLength: "
<< info.rdb.SymbolicLinkReparseBuffer.PrintNameLength << '\n'
<< "info.rdb.SymbolicLinkReparseBuffer.Flags: "
<< info.rdb.SymbolicLinkReparseBuffer.Flags << std::endl;

std::wstring subname(
(wchar_t*)info.rdb.SymbolicLinkReparseBuffer.PathBuffer
+ info.rdb.SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof
(wchar_t),
(wchar_t*)info.rdb.SymbolicLinkReparseBuffer.PathBuffer
+ info.rdb.SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof
(wchar_t)
+ info.rdb.SymbolicLinkReparseBuffer.SubstituteNameLength/sizeof
(wchar_t));
std::wstring prtname(
(wchar_t*)info.rdb.SymbolicLinkReparseBuffer.PathBuffer
+ info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset/sizeof
(wchar_t),
(wchar_t*)info.rdb.SymbolicLinkReparseBuffer.PathBuffer
+ info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset/sizeof
(wchar_t)
+ info.rdb.SymbolicLinkReparseBuffer.PrintNameLength/sizeof
(wchar_t));

std::wcout
<< L"SubstituteName: " << subname
<< L", PrintName: " << prtname << std::endl;

return 0;
}

Kerem Gümrükcü

unread,
Dec 11, 2009, 11:53:31 AM12/11/09
to
Hi,

you are welcome Bernan and thanks for posting the
sample here, always good if someone needs one!

Regards

Kerem

--
-----------------------
Beste Gr�sse / Best regards / Votre bien devoue
Kerem G�mr�kc�
Latest Project: http://www.pro-it-education.de/software/deviceremover
Latest Open-Source Projects: http://entwicklung.junetz.de
-----------------------

"Beman Dawes" <beman...@gmail.com> schrieb im Newsbeitrag

news:9cb182b8-4fff-49e4...@m25g2000yqc.googlegroups.com...

0 new messages