mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-09 19:06:15 +01:00
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:
parent
622806d5cf
commit
60eefd4de9
@ -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 "," \
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
||||
|
17
meson.build
17
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)
|
||||
|
Loading…
Reference in New Issue
Block a user