Merge branch 'win32-symlink-refactoring' into 'master'

Win32 symlink code refactoring

See merge request GNOME/glib!269
This commit is contained in:
Philip Withnall
2019-03-13 11:55:27 +00:00
10 changed files with 880 additions and 413 deletions

View File

@@ -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 */

View File

@@ -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,

View File

@@ -161,7 +161,7 @@ _g_local_file_info_create_fs_id (GLocalFileStat *statbuf)
static gchar *
read_link (const gchar *full_name)
{
#if defined (HAVE_READLINK) || defined (G_OS_WIN32)
#if defined (HAVE_READLINK)
gchar *buffer;
guint size;
@@ -171,12 +171,8 @@ read_link (const gchar *full_name)
while (1)
{
int read_size;
#ifndef G_OS_WIN32
read_size = readlink (full_name, buffer, size);
#else
read_size = GLIB_PRIVATE_CALL (g_win32_readlink_utf8) (full_name, buffer, size);
#endif
if (read_size < 0)
{
g_free (buffer);
@@ -190,6 +186,17 @@ read_link (const gchar *full_name)
size *= 2;
buffer = g_realloc (buffer, size);
}
#elif defined (G_OS_WIN32)
gchar *buffer;
int read_size;
read_size = GLIB_PRIVATE_CALL (g_win32_readlink_utf8) (full_name, NULL, 0, &buffer, TRUE);
if (read_size < 0)
return NULL;
else if (read_size == 0)
return strdup ("");
else
return buffer;
#else
return NULL;
#endif
@@ -957,8 +964,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
@@ -966,15 +973,17 @@ set_info_from_stat (GFileInfo *info,
g_file_info_set_size (info, statbuf->st_size);
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_DEVICE, statbuf->st_dev);
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_NLINK, statbuf->st_nlink);
#ifndef G_OS_WIN32
/* Pointless setting these on Windows even if they exist in the struct */
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_INODE, statbuf->st_ino);
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_NLINK, statbuf->st_nlink);
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_UID, statbuf->st_uid);
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_GID, statbuf->st_gid);
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_RDEV, statbuf->st_rdev);
#endif
/* FIXME: st_mode is mostly pointless on Windows, too. Set the attribute or not? */
/* Mostly pointless on Windows.
* Still, it allows for S_ISREG/S_ISDIR and IWRITE (read-only) checks.
*/
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_MODE, statbuf->st_mode);
#if defined (HAVE_STRUCT_STAT_ST_BLKSIZE)
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_BLOCK_SIZE, statbuf->st_blksize);

View File

@@ -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);