[glib: 2/5] Straighten up the GFileType vs symlinks on Windows situation



commit 19608e36d2a6f57237505eec19363ef210d7501d
Author: Руслан Ижбулатов <lrn1986 gmail com>
Date:   Fri Aug 24 08:57:20 2018 +0000

    Straighten up the GFileType vs symlinks on Windows situation
    
    On Windows NTFS symlinks are implemented as reparse points,
    which are special kinds of files *or directories*. A directory
    symlink should link to a directory. A file symlink should link
    to a file. Mismatching (such as a file symlink pointing to a
    directory) produces symlinks that simply do not function.
    
    Therefore GFileType file vs directory vs symlink distinction is
    too simplistic to correctly represent a NTFS filesystem object type.
    
    Since we can't turn back time and choose a better way of representing
    file types, make GFileType reflect the file vs directory type on
    Windows, meaning that all FS objects are either files or
    directories (or shortcuts, which are also files), but never symlinks.
    
    A test for symlinkiness will have to be made via GFileInfo - it
    tracks symlinkiness separately from file/directory/whatever.

 gio/gfileinfo.h         | 1 +
 gio/gioenums.h          | 9 +++++++++
 gio/glocalfileinfo.c    | 4 ++--
 gio/tests/g-file-info.c | 4 ++--
 4 files changed, 14 insertions(+), 4 deletions(-)
---
diff --git a/gio/gfileinfo.h b/gio/gfileinfo.h
index 2ca623c3a..622c2b611 100644
--- a/gio/gfileinfo.h
+++ b/gio/gfileinfo.h
@@ -76,6 +76,7 @@ typedef struct _GFileInfoClass   GFileInfoClass;
  * A key in the "standard" namespace for checking if the file is a symlink.
  * Typically the actual type is something else, if we followed the symlink
  * to get the type.
+ * On Windows NTFS mountpoints are considered to be symlinks as well.
  * Corresponding #GFileAttributeType is %G_FILE_ATTRIBUTE_TYPE_BOOLEAN.
  **/
 #define G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK "standard::is-symlink"         /* boolean */
diff --git a/gio/gioenums.h b/gio/gioenums.h
index a83fa71f1..f1d71515f 100644
--- a/gio/gioenums.h
+++ b/gio/gioenums.h
@@ -361,6 +361,15 @@ typedef enum {
  * @G_FILE_TYPE_MOUNTABLE: File is a mountable location.
  *
  * Indicates the file's on-disk type.
+ *
+ * On Windows systems a file will never have %G_FILE_TYPE_SYMBOLIC_LINK type;
+ * use #GFileInfo and %G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK to determine
+ * whether a file is a symlink or not. This is due to the fact that NTFS does
+ * not have a single filesystem object type for symbolic links - it has
+ * files that symlink to files, and directories that symlink to directories.
+ * #GFileType enumeration cannot precisely represent this important distinction,
+ * which is why all Windows symlinks will continue to be reported as
+ * %G_FILE_TYPE_REGULAR or %G_FILE_TYPE_DIRECTORY.
  **/
 typedef enum {
   G_FILE_TYPE_UNKNOWN = 0,
diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c
index e2f38c880..1387dc077 100644
--- a/gio/glocalfileinfo.c
+++ b/gio/glocalfileinfo.c
@@ -957,8 +957,8 @@ set_info_from_stat (GFileInfo             *info,
   else if (S_ISLNK (statbuf->st_mode))
     file_type = G_FILE_TYPE_SYMBOLIC_LINK;
 #elif defined (G_OS_WIN32)
-  if (statbuf->reparse_tag == IO_REPARSE_TAG_SYMLINK ||
-      statbuf->reparse_tag == IO_REPARSE_TAG_MOUNT_POINT)
+  else if (statbuf->reparse_tag == IO_REPARSE_TAG_SYMLINK ||
+           statbuf->reparse_tag == IO_REPARSE_TAG_MOUNT_POINT)
     file_type = G_FILE_TYPE_SYMBOLIC_LINK;
 #endif
 
diff --git a/gio/tests/g-file-info.c b/gio/tests/g-file-info.c
index 28a2426a8..f21d1b7e2 100644
--- a/gio/tests/g-file-info.c
+++ b/gio/tests/g-file-info.c
@@ -291,10 +291,10 @@ test_internal_enhanced_stdio (void)
       ft_programdata = g_file_info_get_file_type (fi_programdata);
       ft_commondata = g_file_info_get_file_type (fi_commondata);
 
-      g_assert_cmpint (ft_allusers, ==, G_FILE_TYPE_SYMBOLIC_LINK);
+      g_assert_cmpint (ft_allusers, ==, G_FILE_TYPE_DIRECTORY);
       g_assert_cmpint (ft_allusers_target, ==, G_FILE_TYPE_DIRECTORY);
       g_assert_cmpint (ft_programdata, ==, G_FILE_TYPE_DIRECTORY);
-      g_assert_cmpint (ft_commondata, ==, G_FILE_TYPE_SYMBOLIC_LINK);
+      g_assert_cmpint (ft_commondata, ==, G_FILE_TYPE_DIRECTORY);
 
       allusers_is_symlink = g_file_info_get_attribute_boolean (fi_allusers, 
G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK);
       allusers_reparse_tag = g_file_info_get_attribute_uint32 (fi_allusers, 
G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]