1
0
Эх сурвалжийг харах

Symlink support for Windows Vista. Untested code.

Ryan C. Gordon 19 жил өмнө
parent
commit
9af599504d
2 өөрчлөгдсөн 47 нэмэгдсэн , 5 устгасан
  1. 2 1
      CHANGELOG.txt
  2. 45 4
      platform/windows.c

+ 2 - 1
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

+ 45 - 4
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);