summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <smcv@collabora.com>2020-09-15 10:46:05 +0100
committerSimon McVittie <smcv@collabora.com>2020-09-15 11:06:57 +0100
commit95cc49c595829d1008b06b7ab0de507510ea478b (patch)
treeff7c5bb4ec3f510a632c5240506cfeaf43cc0346
parente6355aee0c0e1fb255ee203b2c00ba8833bf2f13 (diff)
downloadglib-wip/smcv/statx-no-required-mask.tar.gz
glocalfile: Only copy meaningful fields from struct statx to GFileInfowip/smcv/statx-no-required-mask
At least in theory, the Linux kernel can now tell us which fields in struct statx have meaningful values (although in practice it doesn't seem to unset any of the STATX_BASIC_STATS bits except STATX_ATIME, even on FAT filesystems where the uid and gid are not meaningful). Signed-off-by: Simon McVittie <smcv@collabora.com>
-rw-r--r--gio/glocalfileinfo.c80
1 files changed, 50 insertions, 30 deletions
diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c
index b9c099cac..4afdb464c 100644
--- a/gio/glocalfileinfo.c
+++ b/gio/glocalfileinfo.c
@@ -961,52 +961,66 @@ set_info_from_stat (GFileInfo *info,
file_type = G_FILE_TYPE_UNKNOWN;
- if (S_ISREG (_g_stat_mode (statbuf)))
- file_type = G_FILE_TYPE_REGULAR;
- else if (S_ISDIR (_g_stat_mode (statbuf)))
- file_type = G_FILE_TYPE_DIRECTORY;
+ if (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_TYPE))
+ {
+ if (S_ISREG (_g_stat_mode (statbuf)))
+ file_type = G_FILE_TYPE_REGULAR;
+ else if (S_ISDIR (_g_stat_mode (statbuf)))
+ file_type = G_FILE_TYPE_DIRECTORY;
#ifndef G_OS_WIN32
- else if (S_ISCHR (_g_stat_mode (statbuf)) ||
- S_ISBLK (_g_stat_mode (statbuf)) ||
- S_ISFIFO (_g_stat_mode (statbuf))
+ else if (S_ISCHR (_g_stat_mode (statbuf)) ||
+ S_ISBLK (_g_stat_mode (statbuf)) ||
+ S_ISFIFO (_g_stat_mode (statbuf))
#ifdef S_ISSOCK
- || S_ISSOCK (_g_stat_mode (statbuf))
+ || S_ISSOCK (_g_stat_mode (statbuf))
#endif
- )
- file_type = G_FILE_TYPE_SPECIAL;
+ )
+ file_type = G_FILE_TYPE_SPECIAL;
#endif
#ifdef S_ISLNK
- else if (S_ISLNK (_g_stat_mode (statbuf)))
- file_type = G_FILE_TYPE_SYMBOLIC_LINK;
+ else if (S_ISLNK (_g_stat_mode (statbuf)))
+ file_type = G_FILE_TYPE_SYMBOLIC_LINK;
#elif defined (G_OS_WIN32)
- else if (statbuf->reparse_tag == IO_REPARSE_TAG_SYMLINK ||
- statbuf->reparse_tag == IO_REPARSE_TAG_MOUNT_POINT)
- file_type = G_FILE_TYPE_SYMBOLIC_LINK;
+ 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
+ }
g_file_info_set_file_type (info, file_type);
- g_file_info_set_size (info, _g_stat_size (statbuf));
+ if (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_SIZE))
+ g_file_info_set_size (info, _g_stat_size (statbuf));
+ /* There doesn't seem to be a STATX_FOO bit for dev or rdev, so set those
+ * unconditionally */
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_DEVICE, _g_stat_dev (statbuf));
- _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_NLINK, _g_stat_nlink (statbuf));
+ if (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_NLINK))
+ _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_NLINK, _g_stat_nlink (statbuf));
#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, _g_stat_ino (statbuf));
- _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_UID, _g_stat_uid (statbuf));
- _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_GID, _g_stat_gid (statbuf));
+ if (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_INO))
+ _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_INODE, _g_stat_ino (statbuf));
+ if (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_UID))
+ _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_UID, _g_stat_uid (statbuf));
+ if (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_GID))
+ _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_GID, _g_stat_gid (statbuf));
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_RDEV, _g_stat_rdev (statbuf));
#endif
/* 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, _g_stat_mode (statbuf));
+ if (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_MODE))
+ _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_MODE, _g_stat_mode (statbuf));
#if defined (HAVE_STRUCT_STAT_ST_BLKSIZE)
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_BLOCK_SIZE, _g_stat_blksize (statbuf));
#endif
#if defined (HAVE_STRUCT_STAT_ST_BLOCKS)
- _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_BLOCKS, _g_stat_blocks (statbuf));
- _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_ALLOCATED_SIZE,
- _g_stat_blocks (statbuf) * G_GUINT64_CONSTANT (512));
+ if (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_BLOCKS))
+ {
+ _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_BLOCKS, _g_stat_blocks (statbuf));
+ _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_ALLOCATED_SIZE,
+ _g_stat_blocks (statbuf) * G_GUINT64_CONSTANT (512));
+ }
#elif defined (G_OS_WIN32)
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_ALLOCATED_SIZE,
statbuf->allocated_size);
@@ -1019,12 +1033,15 @@ set_info_from_stat (GFileInfo *info,
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS, statbuf->st_atim.tv_sec);
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC, statbuf->st_atim.tv_nsec / 1000);
#else
- _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED, _g_stat_mtime (statbuf));
+ if (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_MTIME))
+ {
+ _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED, _g_stat_mtime (statbuf));
#if defined (HAVE_STRUCT_STAT_ST_MTIMENSEC)
- _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC, statbuf->st_mtimensec / 1000);
+ _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC, statbuf->st_mtimensec / 1000);
#elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
- _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC, _g_stat_mtim_nsec (statbuf) / 1000);
+ _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC, _g_stat_mtim_nsec (statbuf) / 1000);
#endif
+ }
if (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_ATIME))
{
@@ -1043,12 +1060,15 @@ set_info_from_stat (GFileInfo *info,
* https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/stat-functions#generic-text-routine-mappings
* Thank you, Microsoft!
*/
- _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED, _g_stat_ctime (statbuf));
+ if (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_CTIME))
+ {
+ _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED, _g_stat_ctime (statbuf));
#if defined (HAVE_STRUCT_STAT_ST_CTIMENSEC)
- _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED_USEC, statbuf->st_ctimensec / 1000);
+ _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED_USEC, statbuf->st_ctimensec / 1000);
#elif defined (HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC)
- _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED_USEC, _g_stat_ctim_nsec (statbuf) / 1000);
+ _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED_USEC, _g_stat_ctim_nsec (statbuf) / 1000);
#endif
+ }
#endif
#if defined (HAVE_STATX)