diff options
author | Simon McVittie <smcv@collabora.com> | 2020-09-15 10:46:05 +0100 |
---|---|---|
committer | Simon McVittie <smcv@collabora.com> | 2020-09-15 11:06:57 +0100 |
commit | 95cc49c595829d1008b06b7ab0de507510ea478b (patch) | |
tree | ff7c5bb4ec3f510a632c5240506cfeaf43cc0346 | |
parent | e6355aee0c0e1fb255ee203b2c00ba8833bf2f13 (diff) | |
download | glib-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.c | 80 |
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) |