Greg Jung
2015-01-14 17:33:35 UTC
Hi Folks,
I've been trying to program a recognition of NTFS symbolic link files;
What I;ve gleaned
from MSDN procedures don't seem to work. Below are coded three methods
1) (untested) open file and call GetFileInformationByHandleEx. I can't get
winbase.h header definitions recognized
2) GetFileAttributes() works ok for Junctions doesn't recognize symlink
files
3) FindFirstEx . same result as 2)
There must be a way, since cygwin 'ls -a' and msys2 'ls -a' commands will
show links.
in the calling routine, I modify result of stat() with system calls:
#ifdef _WIN32
int addlink = 0;
fstat_win32(filename.c_str(), addlink);
int actStat = stat(filename.c_str(), &statStruct);
if( addlink != 0) cout << " addlink came back " << endl;
statStruct.st_mode |= addlink;
#else
int actStat = lstat( testDir.c_str(), &statStruct);
#endif
where fstat_win32 now has a graveyard full of attempts: ( When a directory
link is encountered, however, the test succeeeds.)
void fstat_win32(const string& filepath, int& st_mode)
{
DWORD dwattrib, reparsetag;
DString st;
st=filepath;
#if 1
//
// This method has not been tested: it will not compile -
GetFileInformationByHandleEx
// does not get through from the winbase.h header
//
HANDLE hFile;
BOOL success;
DWORD fattrib[2];
hFile = CreateFile( (TCHAR *)st.c_str(),
FILE_GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT,
0);
if (hFile == INVALID_HANDLE_VALUE) {
CloseHandle(hFile);
cout << " stat_win32: could not open " + st << endl;
return;
}
else {
success = GetFileInformationByHandleEx( hFile,
FileAttributeTagInfo,
&fattrib,
sizeof(fattrib));
dwattrib = fattrib[0];
reparsetag = fattrib[1];
}
CloseHandle(hFile);
// dwattrib = GetFileAttributes( (TCHAR *)st.c_str()); // This doesn't
work to find symlinks
if( (dwattrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0 ) {
st_mode |= S_IFLNK;
cout << " fstat_win32: symbolic link detected and flagged!! " <<
filepath ;
}
else st_mode=0;
#elif 0
DWORD dwlen;
HANDLE hFind;
BOOL foundnext;
WIN32_FIND_DATA FindFileData;
// This doesn't work to find symlinks
hFind = FindFirstFileEx( (TCHAR *) st.c_str(),
FindExInfoStandard,
&FindFileData,
FindExSearchNameMatch, NULL, 0);
if (hFind == INVALID_HANDLE_VALUE)
return;
dwattrib = FindFileData.dwFileAttributes;
if( (dwattrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0 ) {
st_mode |= S_IFLNK;
cout << " fstat_win32: symbolic link detected and flagged!! " <<
filepath ;
dwattrib = FindFileData.dwReserved0;
// IO_REPARSE_TAG_SYMLINK _MOUNT_POINT etc.
}
FindClose(hFind);
#endif
return;
}
I've been trying to program a recognition of NTFS symbolic link files;
What I;ve gleaned
from MSDN procedures don't seem to work. Below are coded three methods
1) (untested) open file and call GetFileInformationByHandleEx. I can't get
winbase.h header definitions recognized
2) GetFileAttributes() works ok for Junctions doesn't recognize symlink
files
3) FindFirstEx . same result as 2)
There must be a way, since cygwin 'ls -a' and msys2 'ls -a' commands will
show links.
in the calling routine, I modify result of stat() with system calls:
#ifdef _WIN32
int addlink = 0;
fstat_win32(filename.c_str(), addlink);
int actStat = stat(filename.c_str(), &statStruct);
if( addlink != 0) cout << " addlink came back " << endl;
statStruct.st_mode |= addlink;
#else
int actStat = lstat( testDir.c_str(), &statStruct);
#endif
where fstat_win32 now has a graveyard full of attempts: ( When a directory
link is encountered, however, the test succeeeds.)
void fstat_win32(const string& filepath, int& st_mode)
{
DWORD dwattrib, reparsetag;
DString st;
st=filepath;
#if 1
//
// This method has not been tested: it will not compile -
GetFileInformationByHandleEx
// does not get through from the winbase.h header
//
HANDLE hFile;
BOOL success;
DWORD fattrib[2];
hFile = CreateFile( (TCHAR *)st.c_str(),
FILE_GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT,
0);
if (hFile == INVALID_HANDLE_VALUE) {
CloseHandle(hFile);
cout << " stat_win32: could not open " + st << endl;
return;
}
else {
success = GetFileInformationByHandleEx( hFile,
FileAttributeTagInfo,
&fattrib,
sizeof(fattrib));
dwattrib = fattrib[0];
reparsetag = fattrib[1];
}
CloseHandle(hFile);
// dwattrib = GetFileAttributes( (TCHAR *)st.c_str()); // This doesn't
work to find symlinks
if( (dwattrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0 ) {
st_mode |= S_IFLNK;
cout << " fstat_win32: symbolic link detected and flagged!! " <<
filepath ;
}
else st_mode=0;
#elif 0
DWORD dwlen;
HANDLE hFind;
BOOL foundnext;
WIN32_FIND_DATA FindFileData;
// This doesn't work to find symlinks
hFind = FindFirstFileEx( (TCHAR *) st.c_str(),
FindExInfoStandard,
&FindFileData,
FindExSearchNameMatch, NULL, 0);
if (hFind == INVALID_HANDLE_VALUE)
return;
dwattrib = FindFileData.dwFileAttributes;
if( (dwattrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0 ) {
st_mode |= S_IFLNK;
cout << " fstat_win32: symbolic link detected and flagged!! " <<
filepath ;
dwattrib = FindFileData.dwReserved0;
// IO_REPARSE_TAG_SYMLINK _MOUNT_POINT etc.
}
FindClose(hFind);
#endif
return;
}