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
This commit is contained in:
Andre Miranda 2020-08-14 16:04:37 +01:00 committed by Philip Withnall
parent 622806d5cf
commit 60eefd4de9
4 changed files with 151 additions and 0 deletions

View File

@ -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 its 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 "," \

View File

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

View File

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

View File

@ -328,6 +328,23 @@ if cc.has_header('linux/netlink.h')
glib_conf.set('HAVE_NETLINK', 1)
endif
# Is statx() supported? Android systems dont 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)