summaryrefslogtreecommitdiff
path: root/gio
diff options
context:
space:
mode:
authorAndre Miranda <andre42m@gmail.com>2020-08-14 16:04:37 +0100
committerPhilip Withnall <withnall@endlessm.com>2020-08-17 12:33:05 +0100
commit60eefd4de9f71064a75823f38136af86ee0d04ea (patch)
treeee7f950f5148c5920fc7d2523c97d4bac38bcbab /gio
parent622806d5cf18c9eba6438789ba552cee8f3ab712 (diff)
downloadglib-60eefd4de9f71064a75823f38136af86ee0d04ea.tar.gz
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
Diffstat (limited to 'gio')
-rw-r--r--gio/glocalfileinfo.h124
-rw-r--r--gio/glocalfileoutputstream.c5
-rw-r--r--gio/tests/thumbnail-verification.c5
3 files changed, 134 insertions, 0 deletions
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..f34c3e439 100644
--- a/gio/glocalfileoutputstream.c
+++ b/gio/glocalfileoutputstream.c
@@ -18,6 +18,11 @@
* Author: Alexander Larsson <alexl@redhat.com>
*/
+/* Needed for the statx() calls in inline functions in glocalfileinfo.h */
+#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);