[glib/wip/smcv/statx-no-required-mask: 1/2] glocalfile: Remove the concept of the required mask
- From: Simon McVittie <smcv src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/smcv/statx-no-required-mask: 1/2] glocalfile: Remove the concept of the required mask
- Date: Tue, 15 Sep 2020 10:03:37 +0000 (UTC)
commit b6ec6f786872306facdd1817879dbf1c5d5be696
Author: Simon McVittie <smcv collabora com>
Date: Tue Sep 15 10:35:08 2020 +0100
glocalfile: Remove the concept of the required mask
It is not actually guaranteed that *any* of the flags in the
returned stx_mask will be set by statx(): for example, if the
filesystem has no concept of POSIX user and group IDs (like FAT),
the kernel could validly clear the STATX_UID and STATX_GID bits in
the returned stx_mask. Linux 5.8 does not appear to do this in practice,
even for FAT, but the statx(2) man page suggests that it perhaps should.
However, what *is* guaranteed is that for the STATX_BASIC_STATS (those
that correspond to what is in the traditional struct stat), even if the
bit in stx_mask is cleared, there will be *something* in the
corresponding struct field (in practice the same harmless value that
traditional stat() would have placed in the struct stat). Rely on those
compatibility values being reasonable, and don't second-guess the kernel.
Signed-off-by: Simon McVittie <smcv collabora com>
gio/glocalfile.c | 6 ++---
gio/glocalfileinfo.c | 3 ---
gio/glocalfileinfo.h | 61 ++++----------------------------------------
gio/glocalfileoutputstream.c | 30 ++++++++++++++++------
4 files changed, 29 insertions(+), 71 deletions(-)
---
diff --git a/gio/glocalfile.c b/gio/glocalfile.c
index a87de9cc4..fe1fc9ef7 100644
--- a/gio/glocalfile.c
+++ b/gio/glocalfile.c
@@ -1352,7 +1352,7 @@ g_local_file_read (GFile *file,
return NULL;
}
- ret = g_local_file_fstat (fd, G_LOCAL_FILE_STAT_FIELD_TYPE, G_LOCAL_FILE_STAT_FIELD_ALL, &buf);
+ ret = g_local_file_fstat (fd, G_LOCAL_FILE_STAT_FIELD_TYPE, &buf);
if (ret == 0 && S_ISDIR (_g_stat_mode (&buf)))
{
@@ -2703,9 +2703,7 @@ g_local_file_measure_size_of_file (gint parent_fd,
#if defined (AT_FDCWD)
if (g_local_file_fstatat (parent_fd, name->data, AT_SYMLINK_NOFOLLOW,
- G_LOCAL_FILE_STAT_FIELD_BASIC_STATS,
- G_LOCAL_FILE_STAT_FIELD_ALL & (~G_LOCAL_FILE_STAT_FIELD_ATIME),
- &buf) != 0)
+ G_LOCAL_FILE_STAT_FIELD_BASIC_STATS, &buf) != 0)
{
int errsv = errno;
return g_local_file_measure_size_error (state->flags, errsv, name, error);
diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c
index 90fcb3336..b9c099cac 100644
--- a/gio/glocalfileinfo.c
+++ b/gio/glocalfileinfo.c
@@ -1808,7 +1808,6 @@ _g_local_file_info_get (const char *basename,
res = g_local_file_lstat (path,
G_LOCAL_FILE_STAT_FIELD_BASIC_STATS | G_LOCAL_FILE_STAT_FIELD_BTIME,
- G_LOCAL_FILE_STAT_FIELD_ALL & (~G_LOCAL_FILE_STAT_FIELD_BTIME) &
(~G_LOCAL_FILE_STAT_FIELD_ATIME),
&statbuf);
if (res == -1)
@@ -1858,7 +1857,6 @@ _g_local_file_info_get (const char *basename,
{
res = g_local_file_stat (path,
G_LOCAL_FILE_STAT_FIELD_BASIC_STATS | G_LOCAL_FILE_STAT_FIELD_BTIME,
- G_LOCAL_FILE_STAT_FIELD_ALL & (~G_LOCAL_FILE_STAT_FIELD_BTIME) &
(~G_LOCAL_FILE_STAT_FIELD_ATIME),
&statbuf2);
/* Report broken links as symlinks */
@@ -2081,7 +2079,6 @@ _g_local_file_info_get_from_fd (int fd,
if (g_local_file_fstat (fd,
G_LOCAL_FILE_STAT_FIELD_BASIC_STATS | G_LOCAL_FILE_STAT_FIELD_BTIME,
- G_LOCAL_FILE_STAT_FIELD_ALL & (~G_LOCAL_FILE_STAT_FIELD_BTIME) &
(~G_LOCAL_FILE_STAT_FIELD_ATIME),
&stat_buf) == -1)
{
int errsv = errno;
diff --git a/gio/glocalfileinfo.h b/gio/glocalfileinfo.h
index f2beb70cd..53ccd7a84 100644
--- a/gio/glocalfileinfo.h
+++ b/gio/glocalfileinfo.h
@@ -80,33 +80,17 @@ 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;
+ return statx (dirfd, pathname, flags, mask, stat_buf);
}
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);
+ return g_local_file_statx (fd, "", AT_EMPTY_PATH, mask, stat_buf);
}
static inline int
@@ -114,32 +98,29 @@ 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);
+ return g_local_file_statx (fd, path, flags, mask, 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);
+ mask, 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);
+ mask, stat_buf);
}
inline static gboolean _g_stat_has_field (const GLocalFileStat *buf, GLocalFileStatField field) { return
buf->stx_mask & field; }
@@ -204,16 +185,8 @@ typedef enum
static inline int
g_local_file_fstat (int fd,
GLocalFileStatField mask,
- GLocalFileStatField mask_required,
GLocalFileStat *stat_buf)
{
- if ((G_LOCAL_FILE_STAT_FIELD_BASIC_STATS & (mask_required & mask)) != (mask_required & mask))
- {
- /* Only G_LOCAL_FILE_STAT_FIELD_BASIC_STATS are supported. */
- errno = ERANGE;
- return -1;
- }
-
#ifdef G_OS_WIN32
return GLIB_PRIVATE_CALL (g_win32_fstat) (fd, stat_buf);
#else
@@ -226,16 +199,8 @@ g_local_file_fstatat (int fd,
const char *path,
int flags,
GLocalFileStatField mask,
- GLocalFileStatField mask_required,
GLocalFileStat *stat_buf)
{
- if ((G_LOCAL_FILE_STAT_FIELD_BASIC_STATS & (mask_required & mask)) != (mask_required & mask))
- {
- /* Only G_LOCAL_FILE_STAT_FIELD_BASIC_STATS are supported. */
- errno = ERANGE;
- return -1;
- }
-
#ifdef G_OS_WIN32
/* Currently not supported on Windows */
errno = ENOSYS;
@@ -248,16 +213,8 @@ g_local_file_fstatat (int fd,
static inline int
g_local_file_lstat (const char *path,
GLocalFileStatField mask,
- GLocalFileStatField mask_required,
GLocalFileStat *stat_buf)
{
- if ((G_LOCAL_FILE_STAT_FIELD_BASIC_STATS & (mask_required & mask)) != (mask_required & mask))
- {
- /* Only G_LOCAL_FILE_STAT_FIELD_BASIC_STATS are supported. */
- errno = ERANGE;
- return -1;
- }
-
#ifdef G_OS_WIN32
return GLIB_PRIVATE_CALL (g_win32_lstat_utf8) (path, stat_buf);
#else
@@ -268,16 +225,8 @@ g_local_file_lstat (const char *path,
static inline int
g_local_file_stat (const char *path,
GLocalFileStatField mask,
- GLocalFileStatField mask_required,
GLocalFileStat *stat_buf)
{
- if ((G_LOCAL_FILE_STAT_FIELD_BASIC_STATS & (mask_required & mask)) != (mask_required & mask))
- {
- /* Only G_LOCAL_FILE_STAT_FIELD_BASIC_STATS are supported. */
- errno = ERANGE;
- return -1;
- }
-
#ifdef G_OS_WIN32
return GLIB_PRIVATE_CALL (g_win32_stat_utf8) (path, stat_buf);
#else
diff --git a/gio/glocalfileoutputstream.c b/gio/glocalfileoutputstream.c
index f34c3e439..a28ac332c 100644
--- a/gio/glocalfileoutputstream.c
+++ b/gio/glocalfileoutputstream.c
@@ -429,7 +429,8 @@ _g_local_file_output_stream_really_close (GLocalFileOutputStream *file,
#ifndef G_OS_WIN32 /* Already did the fstat() and close() above on Win32 */
- if (g_local_file_fstat (file->priv->fd, G_LOCAL_FILE_STAT_FIELD_MTIME, G_LOCAL_FILE_STAT_FIELD_ALL,
&final_stat) == 0)
+ if (g_local_file_fstat (file->priv->fd, G_LOCAL_FILE_STAT_FIELD_MTIME, &final_stat) == 0 &&
+ _g_stat_has_field (&final_stat, G_LOCAL_FILE_STAT_FIELD_MTIME))
file->priv->etag = _g_local_file_info_create_etag (&final_stat);
if (!g_close (file->priv->fd, NULL))
@@ -904,7 +905,7 @@ handle_overwrite_open (const char *filename,
G_LOCAL_FILE_STAT_FIELD_GID |
G_LOCAL_FILE_STAT_FIELD_MTIME |
G_LOCAL_FILE_STAT_FIELD_NLINK,
- G_LOCAL_FILE_STAT_FIELD_ALL, &original_stat);
+ &original_stat);
errsv = errno;
if (res != 0)
@@ -919,9 +920,11 @@ handle_overwrite_open (const char *filename,
}
/* not a regular file */
- if (!S_ISREG (_g_stat_mode (&original_stat)))
+ if (!_g_stat_has_field (&original_stat, G_LOCAL_FILE_STAT_FIELD_TYPE) ||
+ !S_ISREG (_g_stat_mode (&original_stat)))
{
- if (S_ISDIR (_g_stat_mode (&original_stat)))
+ if (_g_stat_has_field (&original_stat, G_LOCAL_FILE_STAT_FIELD_TYPE) &&
+ S_ISDIR (_g_stat_mode (&original_stat)))
g_set_error_literal (error,
G_IO_ERROR,
G_IO_ERROR_IS_DIRECTORY,
@@ -936,6 +939,8 @@ handle_overwrite_open (const char *filename,
if (etag != NULL)
{
+ /* TODO: What if original_stat doesn't have the mtime, or whatever
+ * other information goes into the etag? */
current_etag = _g_local_file_info_create_etag (&original_stat);
if (strcmp (etag, current_etag) != 0)
{
@@ -961,7 +966,8 @@ handle_overwrite_open (const char *filename,
*/
if ((flags & G_FILE_CREATE_REPLACE_DESTINATION) ||
- (!(_g_stat_nlink (&original_stat) > 1) && !is_symlink))
+ (!(_g_stat_has_field (&original_stat, G_LOCAL_FILE_STAT_FIELD_NLINK) &&
+ _g_stat_nlink (&original_stat) > 1) && !is_symlink))
{
char *dirname, *tmp_filename;
int tmpfd;
@@ -979,6 +985,7 @@ handle_overwrite_open (const char *filename,
/* try to keep permissions (unless replacing) */
+ /* TODO: Check for G_LOCAL_FILE_STAT_FIELD_UID, _GID, _MODE */
if ( ! (flags & G_FILE_CREATE_REPLACE_DESTINATION) &&
(
#ifdef HAVE_FCHOWN
@@ -999,9 +1006,10 @@ handle_overwrite_open (const char *filename,
G_LOCAL_FILE_STAT_FIELD_MODE |
G_LOCAL_FILE_STAT_FIELD_UID |
G_LOCAL_FILE_STAT_FIELD_GID,
- G_LOCAL_FILE_STAT_FIELD_ALL, &tmp_statbuf);
+ &tmp_statbuf);
/* Check that we really needed to change something */
+ /* TODO: Check for G_LOCAL_FILE_STAT_FIELD_UID, _GID, _MODE */
if (tres != 0 ||
_g_stat_uid (&original_stat) != _g_stat_uid (&tmp_statbuf) ||
_g_stat_gid (&original_stat) != _g_stat_gid (&tmp_statbuf) ||
@@ -1041,6 +1049,9 @@ handle_overwrite_open (const char *filename,
goto err_out;
}
+ /* TODO: Check for G_LOCAL_FILE_STAT_FIELD_MODE? (But if it's
+ * unset, we have to specify *something*: will our fallback be
+ * any better than the kernel's?) */
bfd = g_open (backup_filename,
O_WRONLY | O_CREAT | O_EXCL | O_BINARY,
_g_stat_mode (&original_stat) & 0777);
@@ -1060,7 +1071,7 @@ handle_overwrite_open (const char *filename,
* bits for the group same as the protection bits for
* others. */
#if defined(HAVE_FCHOWN) && defined(HAVE_FCHMOD)
- if (g_local_file_fstat (bfd, G_LOCAL_FILE_STAT_FIELD_GID, G_LOCAL_FILE_STAT_FIELD_ALL, &tmp_statbuf)
!= 0)
+ if (g_local_file_fstat (bfd, G_LOCAL_FILE_STAT_FIELD_GID, &tmp_statbuf) != 0)
{
g_set_error_literal (error,
G_IO_ERROR,
@@ -1072,9 +1083,12 @@ handle_overwrite_open (const char *filename,
goto err_out;
}
- if ((_g_stat_gid (&original_stat) != _g_stat_gid (&tmp_statbuf)) &&
+ if (_g_stat_has_field (&tmp_statbuf, G_LOCAL_FILE_STAT_FIELD_GID) &&
+ _g_stat_has_field (&original_stat, G_LOCAL_FILE_STAT_FIELD_GID) &&
+ (_g_stat_gid (&original_stat) != _g_stat_gid (&tmp_statbuf)) &&
fchown (bfd, (uid_t) -1, _g_stat_gid (&original_stat)) != 0)
{
+ /* TODO: Check for G_LOCAL_FILE_STAT_FIELD_MODE? */
if (fchmod (bfd,
(_g_stat_mode (&original_stat) & 0707) |
((_g_stat_mode (&original_stat) & 07) << 3)) != 0)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]