[glib/wip/pwithnall/statx: 3/4] glocalfileinfo: Add statx() support
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/pwithnall/statx: 3/4] glocalfileinfo: Add statx() support
- Date: Fri, 14 Aug 2020 16:39:39 +0000 (UTC)
commit 614edc6b0a67cef7a5d159e5d16547be890d91f8
Author: Andre Miranda <andre42m gmail com>
Date: Fri Aug 14 16:04:37 2020 +0100
glocalfileinfo: Add statx() support
This currently just implements the same functionality as the existing
`stat()`/`fstat()`/`fstatat()`/`lstat()` calls, although where a reduced
field set is requested it may return faster.
Helps: #1970
gio/glocalfileinfo.h | 124 +++++++++++++++++++++++++++++++++++++
gio/glocalfileoutputstream.c | 5 ++
gio/tests/thumbnail-verification.c | 5 ++
meson.build | 17 +++++
4 files changed, 151 insertions(+)
---
diff --git a/gio/glocalfileinfo.h b/gio/glocalfileinfo.h
index 9d744d6d4..f2beb70cd 100644
--- a/gio/glocalfileinfo.h
+++ b/gio/glocalfileinfo.h
@@ -21,6 +21,11 @@
#ifndef __G_LOCAL_FILE_INFO_H__
#define __G_LOCAL_FILE_INFO_H__
+/* Needed for statx() */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
#include <fcntl.h>
#include <gio/gfileinfo.h>
#include <gio/gfile.h>
@@ -30,6 +35,10 @@
#include <sys/stat.h>
#include <sys/types.h>
+#ifdef HAVE_STATX
+#include <sys/sysmacros.h>
+#endif
+
G_BEGIN_DECLS
typedef struct
@@ -44,6 +53,119 @@ typedef struct
GDestroyNotify free_extra_data;
} GLocalParentFileInfo;
+#ifdef HAVE_STATX
+#define GLocalFileStat struct statx
+
+typedef enum
+{
+ G_LOCAL_FILE_STAT_FIELD_TYPE = STATX_TYPE,
+ G_LOCAL_FILE_STAT_FIELD_MODE = STATX_MODE,
+ G_LOCAL_FILE_STAT_FIELD_NLINK = STATX_NLINK,
+ G_LOCAL_FILE_STAT_FIELD_UID = STATX_UID,
+ G_LOCAL_FILE_STAT_FIELD_GID = STATX_GID,
+ G_LOCAL_FILE_STAT_FIELD_ATIME = STATX_ATIME,
+ G_LOCAL_FILE_STAT_FIELD_MTIME = STATX_MTIME,
+ G_LOCAL_FILE_STAT_FIELD_CTIME = STATX_CTIME,
+ G_LOCAL_FILE_STAT_FIELD_INO = STATX_INO,
+ G_LOCAL_FILE_STAT_FIELD_SIZE = STATX_SIZE,
+ G_LOCAL_FILE_STAT_FIELD_BLOCKS = STATX_BLOCKS,
+ G_LOCAL_FILE_STAT_FIELD_BTIME = STATX_BTIME,
+} GLocalFileStatField;
+
+#define G_LOCAL_FILE_STAT_FIELD_BASIC_STATS STATX_BASIC_STATS
+#define G_LOCAL_FILE_STAT_FIELD_ALL STATX_ALL
+
+static inline int
+g_local_file_statx (int dirfd,
+ const char *pathname,
+ int flags,
+ GLocalFileStatField mask,
+ GLocalFileStatField mask_required,
+ GLocalFileStat *stat_buf)
+{
+ int retval;
+
+ /* Allow the caller to set mask_required==G_LOCAL_FILE_STAT_FIELD_ALL as a
+ * shortcut for saying it’s equal to @mask. */
+ mask_required &= mask;
+
+ retval = statx (dirfd, pathname, flags, mask, stat_buf);
+ if (retval == 0 && (stat_buf->stx_mask & mask_required) != mask_required)
+ {
+ /* Not all required fields could be returned. */
+ errno = ERANGE;
+ return -1;
+ }
+
+ return retval;
+}
+
+static inline int
+g_local_file_fstat (int fd,
+ GLocalFileStatField mask,
+ GLocalFileStatField mask_required,
+ GLocalFileStat *stat_buf)
+{
+ return g_local_file_statx (fd, "", AT_EMPTY_PATH, mask, mask_required, stat_buf);
+}
+
+static inline int
+g_local_file_fstatat (int fd,
+ const char *path,
+ int flags,
+ GLocalFileStatField mask,
+ GLocalFileStatField mask_required,
+ GLocalFileStat *stat_buf)
+{
+ return g_local_file_statx (fd, path, flags, mask, mask_required, stat_buf);
+}
+
+static inline int
+g_local_file_lstat (const char *path,
+ GLocalFileStatField mask,
+ GLocalFileStatField mask_required,
+ GLocalFileStat *stat_buf)
+{
+ return g_local_file_statx (AT_FDCWD, path,
+ AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | AT_STATX_SYNC_AS_STAT,
+ mask, mask_required, stat_buf);
+}
+
+static inline int
+g_local_file_stat (const char *path,
+ GLocalFileStatField mask,
+ GLocalFileStatField mask_required,
+ GLocalFileStat *stat_buf)
+{
+ return g_local_file_statx (AT_FDCWD, path,
+ AT_NO_AUTOMOUNT | AT_STATX_SYNC_AS_STAT,
+ mask, mask_required, stat_buf);
+}
+
+inline static gboolean _g_stat_has_field (const GLocalFileStat *buf, GLocalFileStatField field) { return
buf->stx_mask & field; }
+
+inline static guint16 _g_stat_mode (const GLocalFileStat *buf) { return buf->stx_mode; }
+inline static guint32 _g_stat_nlink (const GLocalFileStat *buf) { return buf->stx_nlink; }
+inline static dev_t _g_stat_dev (const GLocalFileStat *buf) { return makedev (buf->stx_dev_major,
buf->stx_dev_minor); }
+inline static guint64 _g_stat_ino (const GLocalFileStat *buf) { return buf->stx_ino; }
+inline static guint64 _g_stat_size (const GLocalFileStat *buf) { return buf->stx_size; }
+
+inline static guint32 _g_stat_uid (const GLocalFileStat *buf) { return buf->stx_uid; }
+inline static guint32 _g_stat_gid (const GLocalFileStat *buf) { return buf->stx_gid; }
+inline static dev_t _g_stat_rdev (const GLocalFileStat *buf) { return makedev (buf->stx_rdev_major,
buf->stx_rdev_minor); }
+inline static guint32 _g_stat_blksize (const GLocalFileStat *buf) { return buf->stx_blksize; }
+
+inline static guint64 _g_stat_blocks (const GLocalFileStat *buf) { return buf->stx_blocks; }
+
+inline static gint64 _g_stat_atime (const GLocalFileStat *buf) { return buf->stx_atime.tv_sec; }
+inline static gint64 _g_stat_ctime (const GLocalFileStat *buf) { return buf->stx_ctime.tv_sec; }
+inline static gint64 _g_stat_mtime (const GLocalFileStat *buf) { return buf->stx_mtime.tv_sec; }
+inline static guint32 _g_stat_atim_nsec (const GLocalFileStat *buf) { return buf->stx_atime.tv_nsec; }
+inline static guint32 _g_stat_ctim_nsec (const GLocalFileStat *buf) { return buf->stx_ctime.tv_nsec; }
+inline static guint32 _g_stat_mtim_nsec (const GLocalFileStat *buf) { return buf->stx_mtime.tv_nsec; }
+
+#else /* if !HAVE_STATX */
+
#ifdef G_OS_WIN32
/* We want 64-bit file size, file ID and symlink support */
#define GLocalFileStat GWin32PrivateStat
@@ -201,6 +323,8 @@ inline static guint32 _g_stat_ctim_nsec (const GLocalFileStat *buf) { return b
inline static guint32 _g_stat_mtim_nsec (const GLocalFileStat *buf) { return buf->st_mtim.tv_nsec; }
#endif
+#endif /* !HAVE_STATX */
+
#define G_LOCAL_FILE_INFO_NOSTAT_ATTRIBUTES \
G_FILE_ATTRIBUTE_STANDARD_NAME "," \
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," \
diff --git a/gio/glocalfileoutputstream.c b/gio/glocalfileoutputstream.c
index aa018a062..a09ee0805 100644
--- a/gio/glocalfileoutputstream.c
+++ b/gio/glocalfileoutputstream.c
@@ -18,6 +18,11 @@
* Author: Alexander Larsson <alexl redhat com>
*/
+/* Needed for statx() */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
#include "config.h"
#include <sys/types.h>
diff --git a/gio/tests/thumbnail-verification.c b/gio/tests/thumbnail-verification.c
index d50638fe7..f439c8b06 100644
--- a/gio/tests/thumbnail-verification.c
+++ b/gio/tests/thumbnail-verification.c
@@ -99,12 +99,17 @@ test_validity (void)
thumbnail_path = g_test_get_filename (G_TEST_DIST, "thumbnails",
tests[i].filename, NULL);
file_uri = g_strconcat ("file:///tmp/", tests[i].filename, NULL);
+#ifdef HAVE_STATX
+ stat_buf.stx_mtime.tv_sec = tests[i].mtime;
+ stat_buf.stx_size = tests[i].size;
+#else
#ifdef G_OS_WIN32
stat_buf.st_mtim.tv_sec = tests[i].mtime;
#else
stat_buf.st_mtime = tests[i].mtime;
#endif
stat_buf.st_size = tests[i].size;
+#endif
result = thumbnail_verify (thumbnail_path, file_uri, &stat_buf);
diff --git a/meson.build b/meson.build
index 9a0293120..19ac186e6 100644
--- a/meson.build
+++ b/meson.build
@@ -328,6 +328,23 @@ if cc.has_header('linux/netlink.h')
glib_conf.set('HAVE_NETLINK', 1)
endif
+# Is statx() supported? Android systems don’t reliably support it as of August 2020.
+statx_code = '''
+ #ifndef _GNU_SOURCE
+ #define _GNU_SOURCE
+ #endif
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ int main (void)
+ {
+ struct statx stat_buf;
+ return statx (AT_FDCWD, "/", AT_SYMLINK_NOFOLLOW, STATX_BASIC_STATS | STATX_BTIME, &stat_buf);
+ }
+ '''
+if host_system != 'android' and cc.compiles(statx_code, name : 'statx() test')
+ glib_conf.set('HAVE_STATX', 1)
+endif
+
if glib_conf.has('HAVE_LOCALE_H')
if cc.has_header_symbol('locale.h', 'LC_MESSAGES')
glib_conf.set('HAVE_LC_MESSAGES', 1)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]