From 9af599504d06f881e8fa340f2b64933ae839c7ac Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 31 Mar 2007 23:44:42 +0000 Subject: [PATCH] Symlink support for Windows Vista. Untested code. --- CHANGELOG.txt | 3 ++- platform/windows.c | 49 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 4d3fbfb5..78de178d 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -5,7 +5,8 @@ 03312007 - Added a quick'n'dirty unpack utility to the extras directory. Moved DIR archiver to start of the list, so we don't have to have every other archiver fail to open a directory as a file before mounting - it. Fixed typos in makeos2.cmd and the Doxygen comments. + it. Fixed typos in makeos2.cmd and the Doxygen comments. Added + symlink support to windows.c for use on Vista-based systems. 03282007 - Logic bug in MVL/HOG/GRP archivers: only enumerated files when looking in a directory other than the root, instead of enumerating only for the root (thanks, Chris!). Minor fix for compilers that diff --git a/platform/windows.c b/platform/windows.c index 88085595..302e7dd4 100644 --- a/platform/windows.c +++ b/platform/windows.c @@ -578,10 +578,43 @@ int __PHYSFS_platformExists(const char *fname) } /* __PHYSFS_platformExists */ +static int isSymlinkAttrs(DWORD attr, DWORD tag) +{ + return ( (attr & FILE_ATTRIBUTE_REPARSE_POINT) && + ((tag & IO_REPARSE_TAG_SYMLINK) == IO_REPARSE_TAG_SYMLINK) ); +} /* isSymlinkAttrs */ + + int __PHYSFS_platformIsSymLink(const char *fname) { - /* !!! FIXME: Vista has symlinks. Recheck this. */ - return(0); /* no symlinks on win32. */ + /* !!! FIXME: + * Windows Vista can have NTFS symlinks. Can older Windows releases have + * them when talking to a network file server? What happens when you + * mount a NTFS partition on XP that was plugged into a Vista install + * that made a symlink? + */ + + int retval = 0; + LPWSTR wpath; + HANDLE dir; + WIN32_FIND_DATAW entw; + + /* no unicode entry points? Probably no symlinks. */ + BAIL_IF_MACRO(pFindFirstFileW == NULL, NULL, 0); + + UTF8_TO_UNICODE_STACK_MACRO(wpath, fname); + BAIL_IF_MACRO(wpath == NULL, ERR_OUT_OF_MEMORY, 0); + + /* !!! FIXME: filter wildcard chars? */ + dir = pFindFirstFileW(wpath, &entw); + if (dir != INVALID_HANDLE_VALUE) + { + retval = isSymlinkAttrs(entw.dwFileAttributes, entw.dwReserved0); + FindClose(dir); + } /* if */ + + __PHYSFS_smallFree(wpath); + return(retval); } /* __PHYSFS_platformIsSymlink */ @@ -686,13 +719,17 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname, { do { + const DWORD attrs = entw.dwFileAttributes; + const DWORD tag = entw.dwReserved0; const WCHAR *fn = entw.cFileName; if ((fn[0] == '.') && (fn[1] == '\0')) continue; if ((fn[0] == '.') && (fn[1] == '.') && (fn[2] == '\0')) continue; + if ((omitSymLinks) && (isSymlinkAttrs(attr, tag))) + continue; - utf8 = unicodeToUtf8Heap(entw.cFileName); + utf8 = unicodeToUtf8Heap(fn); if (utf8 != NULL) { callback(callbackdata, origdir, utf8); @@ -705,13 +742,17 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname, { do { + const DWORD attrs = ent.dwFileAttributes; + const DWORD tag = ent.dwReserved0; const char *fn = ent.cFileName; if ((fn[0] == '.') && (fn[1] == '\0')) continue; if ((fn[0] == '.') && (fn[1] == '.') && (fn[2] == '\0')) continue; + if ((omitSymLinks) && (isSymlinkAttrs(attr, tag))) + continue; - utf8 = codepageToUtf8Heap(ent.cFileName); + utf8 = codepageToUtf8Heap(fn); if (utf8 != NULL) { callback(callbackdata, origdir, utf8);