mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 23:16:14 +01:00
Merge branch 'statx' into 'master'
Add support for Linux statx stx_btime Closes #1970 See merge request GNOME/glib!1310
This commit is contained in:
commit
a396fa9027
@ -540,7 +540,8 @@ typedef struct _GFileInfoClass GFileInfoClass;
|
||||
* and contains the time since the file was created, in seconds since the UNIX
|
||||
* epoch.
|
||||
*
|
||||
* This corresponds to the NTFS ctime.
|
||||
* This may correspond to Linux stx_btime, FreeBSD st_birthtim, NetBSD
|
||||
* st_birthtime or NTFS ctime.
|
||||
**/
|
||||
#define G_FILE_ATTRIBUTE_TIME_CREATED "time::created" /* uint64 */
|
||||
|
||||
|
@ -1352,13 +1352,9 @@ g_local_file_read (GFile *file,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
ret = GLIB_PRIVATE_CALL (g_win32_fstat) (fd, &buf);
|
||||
#else
|
||||
ret = fstat (fd, &buf);
|
||||
#endif
|
||||
ret = g_local_file_fstat (fd, G_LOCAL_FILE_STAT_FIELD_TYPE, G_LOCAL_FILE_STAT_FIELD_ALL, &buf);
|
||||
|
||||
if (ret == 0 && S_ISDIR (buf.st_mode))
|
||||
if (ret == 0 && S_ISDIR (_g_stat_mode (&buf)))
|
||||
{
|
||||
(void) g_close (fd, NULL);
|
||||
g_set_io_error (error,
|
||||
@ -2706,7 +2702,9 @@ g_local_file_measure_size_of_file (gint parent_fd,
|
||||
return FALSE;
|
||||
|
||||
#if defined (AT_FDCWD)
|
||||
if (fstatat (parent_fd, name->data, &buf, AT_SYMLINK_NOFOLLOW) != 0)
|
||||
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,
|
||||
&buf) != 0)
|
||||
{
|
||||
int errsv = errno;
|
||||
return g_local_file_measure_size_error (state->flags, errsv, name, error);
|
||||
@ -2730,7 +2728,7 @@ g_local_file_measure_size_of_file (gint parent_fd,
|
||||
/* If not at the toplevel, check for a device boundary. */
|
||||
|
||||
if (state->flags & G_FILE_MEASURE_NO_XDEV)
|
||||
if (state->contained_on != buf.st_dev)
|
||||
if (state->contained_on != _g_stat_dev (&buf))
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
@ -2738,7 +2736,7 @@ g_local_file_measure_size_of_file (gint parent_fd,
|
||||
/* If, however, this is the toplevel, set the device number so
|
||||
* that recursive invocations can compare against it.
|
||||
*/
|
||||
state->contained_on = buf.st_dev;
|
||||
state->contained_on = _g_stat_dev (&buf);
|
||||
}
|
||||
|
||||
#if defined (G_OS_WIN32)
|
||||
@ -2747,12 +2745,12 @@ g_local_file_measure_size_of_file (gint parent_fd,
|
||||
else
|
||||
#elif defined (HAVE_STRUCT_STAT_ST_BLOCKS)
|
||||
if (~state->flags & G_FILE_MEASURE_APPARENT_SIZE)
|
||||
state->disk_usage += buf.st_blocks * G_GUINT64_CONSTANT (512);
|
||||
state->disk_usage += _g_stat_blocks (&buf) * G_GUINT64_CONSTANT (512);
|
||||
else
|
||||
#endif
|
||||
state->disk_usage += buf.st_size;
|
||||
state->disk_usage += _g_stat_size (&buf);
|
||||
|
||||
if (S_ISDIR (buf.st_mode))
|
||||
if (S_ISDIR (_g_stat_mode (&buf)))
|
||||
state->num_dirs++;
|
||||
else
|
||||
state->num_files++;
|
||||
@ -2787,7 +2785,7 @@ g_local_file_measure_size_of_file (gint parent_fd,
|
||||
}
|
||||
}
|
||||
|
||||
if (S_ISDIR (buf.st_mode))
|
||||
if (S_ISDIR (_g_stat_mode (&buf)))
|
||||
{
|
||||
int dir_fd = -1;
|
||||
#ifdef AT_FDCWD
|
||||
|
@ -123,15 +123,17 @@ _g_local_file_info_create_etag (GLocalFileStat *statbuf)
|
||||
{
|
||||
glong sec, usec;
|
||||
|
||||
g_return_val_if_fail (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_MTIME), NULL);
|
||||
|
||||
#if defined (G_OS_WIN32)
|
||||
sec = statbuf->st_mtim.tv_sec;
|
||||
usec = statbuf->st_mtim.tv_nsec / 1000;
|
||||
#else
|
||||
sec = statbuf->st_mtime;
|
||||
sec = _g_stat_mtime (statbuf);
|
||||
#if defined (HAVE_STRUCT_STAT_ST_MTIMENSEC)
|
||||
usec = statbuf->st_mtimensec / 1000;
|
||||
#elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
|
||||
usec = statbuf->st_mtim.tv_nsec / 1000;
|
||||
usec = _g_stat_mtim_nsec (statbuf) / 1000;
|
||||
#else
|
||||
usec = 0;
|
||||
#endif
|
||||
@ -147,10 +149,10 @@ _g_local_file_info_create_file_id (GLocalFileStat *statbuf)
|
||||
#ifdef G_OS_WIN32
|
||||
ino = statbuf->file_index;
|
||||
#else
|
||||
ino = statbuf->st_ino;
|
||||
ino = _g_stat_ino (statbuf);
|
||||
#endif
|
||||
return g_strdup_printf ("l%" G_GUINT64_FORMAT ":%" G_GUINT64_FORMAT,
|
||||
(guint64) statbuf->st_dev,
|
||||
(guint64) _g_stat_dev (statbuf),
|
||||
ino);
|
||||
}
|
||||
|
||||
@ -158,7 +160,7 @@ static char *
|
||||
_g_local_file_info_create_fs_id (GLocalFileStat *statbuf)
|
||||
{
|
||||
return g_strdup_printf ("l%" G_GUINT64_FORMAT,
|
||||
(guint64) statbuf->st_dev);
|
||||
(guint64) _g_stat_dev (statbuf));
|
||||
}
|
||||
|
||||
#if defined (S_ISLNK) || defined (G_OS_WIN32)
|
||||
@ -926,7 +928,7 @@ get_access_rights (GFileAttributeMatcher *attribute_matcher,
|
||||
{
|
||||
uid_t uid = geteuid ();
|
||||
|
||||
if (uid == statbuf->st_uid ||
|
||||
if (uid == _g_stat_uid (statbuf) ||
|
||||
uid == parent_info->owner ||
|
||||
uid == 0)
|
||||
writable = TRUE;
|
||||
@ -959,22 +961,22 @@ set_info_from_stat (GFileInfo *info,
|
||||
|
||||
file_type = G_FILE_TYPE_UNKNOWN;
|
||||
|
||||
if (S_ISREG (statbuf->st_mode))
|
||||
if (S_ISREG (_g_stat_mode (statbuf)))
|
||||
file_type = G_FILE_TYPE_REGULAR;
|
||||
else if (S_ISDIR (statbuf->st_mode))
|
||||
else if (S_ISDIR (_g_stat_mode (statbuf)))
|
||||
file_type = G_FILE_TYPE_DIRECTORY;
|
||||
#ifndef G_OS_WIN32
|
||||
else if (S_ISCHR (statbuf->st_mode) ||
|
||||
S_ISBLK (statbuf->st_mode) ||
|
||||
S_ISFIFO (statbuf->st_mode)
|
||||
else if (S_ISCHR (_g_stat_mode (statbuf)) ||
|
||||
S_ISBLK (_g_stat_mode (statbuf)) ||
|
||||
S_ISFIFO (_g_stat_mode (statbuf))
|
||||
#ifdef S_ISSOCK
|
||||
|| S_ISSOCK (statbuf->st_mode)
|
||||
|| S_ISSOCK (_g_stat_mode (statbuf))
|
||||
#endif
|
||||
)
|
||||
file_type = G_FILE_TYPE_SPECIAL;
|
||||
#endif
|
||||
#ifdef S_ISLNK
|
||||
else if (S_ISLNK (statbuf->st_mode))
|
||||
else if (S_ISLNK (_g_stat_mode (statbuf)))
|
||||
file_type = G_FILE_TYPE_SYMBOLIC_LINK;
|
||||
#elif defined (G_OS_WIN32)
|
||||
else if (statbuf->reparse_tag == IO_REPARSE_TAG_SYMLINK ||
|
||||
@ -983,28 +985,28 @@ set_info_from_stat (GFileInfo *info,
|
||||
#endif
|
||||
|
||||
g_file_info_set_file_type (info, file_type);
|
||||
g_file_info_set_size (info, statbuf->st_size);
|
||||
g_file_info_set_size (info, _g_stat_size (statbuf));
|
||||
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_DEVICE, statbuf->st_dev);
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_NLINK, statbuf->st_nlink);
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_DEVICE, _g_stat_dev (statbuf));
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_NLINK, _g_stat_nlink (statbuf));
|
||||
#ifndef G_OS_WIN32
|
||||
/* Pointless setting these on Windows even if they exist in the struct */
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_INODE, statbuf->st_ino);
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_UID, statbuf->st_uid);
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_GID, statbuf->st_gid);
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_RDEV, statbuf->st_rdev);
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_INODE, _g_stat_ino (statbuf));
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_UID, _g_stat_uid (statbuf));
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_GID, _g_stat_gid (statbuf));
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_RDEV, _g_stat_rdev (statbuf));
|
||||
#endif
|
||||
/* Mostly pointless on Windows.
|
||||
* Still, it allows for S_ISREG/S_ISDIR and IWRITE (read-only) checks.
|
||||
*/
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_MODE, statbuf->st_mode);
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_MODE, _g_stat_mode (statbuf));
|
||||
#if defined (HAVE_STRUCT_STAT_ST_BLKSIZE)
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_BLOCK_SIZE, statbuf->st_blksize);
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_BLOCK_SIZE, _g_stat_blksize (statbuf));
|
||||
#endif
|
||||
#if defined (HAVE_STRUCT_STAT_ST_BLOCKS)
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_BLOCKS, statbuf->st_blocks);
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_BLOCKS, _g_stat_blocks (statbuf));
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_ALLOCATED_SIZE,
|
||||
statbuf->st_blocks * G_GUINT64_CONSTANT (512));
|
||||
_g_stat_blocks (statbuf) * G_GUINT64_CONSTANT (512));
|
||||
#elif defined (G_OS_WIN32)
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_ALLOCATED_SIZE,
|
||||
statbuf->allocated_size);
|
||||
@ -1017,18 +1019,18 @@ set_info_from_stat (GFileInfo *info,
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS, statbuf->st_atim.tv_sec);
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC, statbuf->st_atim.tv_nsec / 1000);
|
||||
#else
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED, statbuf->st_mtime);
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED, _g_stat_mtime (statbuf));
|
||||
#if defined (HAVE_STRUCT_STAT_ST_MTIMENSEC)
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC, statbuf->st_mtimensec / 1000);
|
||||
#elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC, statbuf->st_mtim.tv_nsec / 1000);
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC, _g_stat_mtim_nsec (statbuf) / 1000);
|
||||
#endif
|
||||
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS, statbuf->st_atime);
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS, _g_stat_atime (statbuf));
|
||||
#if defined (HAVE_STRUCT_STAT_ST_ATIMENSEC)
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC, statbuf->st_atimensec / 1000);
|
||||
#elif defined (HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC)
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC, statbuf->st_atim.tv_nsec / 1000);
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC, _g_stat_atim_nsec (statbuf) / 1000);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -1038,15 +1040,21 @@ set_info_from_stat (GFileInfo *info,
|
||||
* https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/stat-functions#generic-text-routine-mappings
|
||||
* Thank you, Microsoft!
|
||||
*/
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED, statbuf->st_ctime);
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED, _g_stat_ctime (statbuf));
|
||||
#if defined (HAVE_STRUCT_STAT_ST_CTIMENSEC)
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED_USEC, statbuf->st_ctimensec / 1000);
|
||||
#elif defined (HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC)
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED_USEC, statbuf->st_ctim.tv_nsec / 1000);
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED_USEC, _g_stat_ctim_nsec (statbuf) / 1000);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_STRUCT_STAT_ST_BIRTHTIME) && defined (HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
|
||||
#if defined (HAVE_STATX)
|
||||
if (_g_stat_has_field (statbuf, G_LOCAL_FILE_STAT_FIELD_BTIME))
|
||||
{
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED, statbuf->stx_btime.tv_sec);
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED_USEC, statbuf->stx_btime.tv_nsec / 1000);
|
||||
}
|
||||
#elif defined (HAVE_STRUCT_STAT_ST_BIRTHTIME) && defined (HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
|
||||
_g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED, statbuf->st_birthtime);
|
||||
_g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CREATED_USEC, statbuf->st_birthtimensec / 1000);
|
||||
#elif defined (HAVE_STRUCT_STAT_ST_BIRTHTIM) && defined (HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC)
|
||||
@ -1306,16 +1314,16 @@ get_content_type (const char *basename,
|
||||
if (is_symlink &&
|
||||
(symlink_broken || (flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)))
|
||||
return g_content_type_from_mime_type ("inode/symlink");
|
||||
else if (statbuf != NULL && S_ISDIR(statbuf->st_mode))
|
||||
else if (statbuf != NULL && S_ISDIR(_g_stat_mode (statbuf)))
|
||||
return g_content_type_from_mime_type ("inode/directory");
|
||||
#ifndef G_OS_WIN32
|
||||
else if (statbuf != NULL && S_ISCHR(statbuf->st_mode))
|
||||
else if (statbuf != NULL && S_ISCHR(_g_stat_mode (statbuf)))
|
||||
return g_content_type_from_mime_type ("inode/chardevice");
|
||||
else if (statbuf != NULL && S_ISBLK(statbuf->st_mode))
|
||||
else if (statbuf != NULL && S_ISBLK(_g_stat_mode (statbuf)))
|
||||
return g_content_type_from_mime_type ("inode/blockdevice");
|
||||
else if (statbuf != NULL && S_ISFIFO(statbuf->st_mode))
|
||||
else if (statbuf != NULL && S_ISFIFO(_g_stat_mode (statbuf)))
|
||||
return g_content_type_from_mime_type ("inode/fifo");
|
||||
else if (statbuf != NULL && S_ISREG(statbuf->st_mode) && statbuf->st_size == 0)
|
||||
else if (statbuf != NULL && S_ISREG(_g_stat_mode (statbuf)) && _g_stat_size (statbuf) == 0)
|
||||
{
|
||||
/* Don't sniff zero-length files in order to avoid reading files
|
||||
* that appear normal but are not (eg: files in /proc and /sys)
|
||||
@ -1328,7 +1336,7 @@ get_content_type (const char *basename,
|
||||
}
|
||||
#endif
|
||||
#ifdef S_ISSOCK
|
||||
else if (statbuf != NULL && S_ISSOCK(statbuf->st_mode))
|
||||
else if (statbuf != NULL && S_ISSOCK(_g_stat_mode (statbuf)))
|
||||
return g_content_type_from_mime_type ("inode/socket");
|
||||
#endif
|
||||
else
|
||||
@ -1773,11 +1781,7 @@ _g_local_file_info_get (const char *basename,
|
||||
{
|
||||
GFileInfo *info;
|
||||
GLocalFileStat statbuf;
|
||||
#ifdef S_ISLNK
|
||||
struct stat statbuf2;
|
||||
#elif defined (G_OS_WIN32)
|
||||
GWin32PrivateStat statbuf2;
|
||||
#endif
|
||||
GLocalFileStat statbuf2;
|
||||
int res;
|
||||
gboolean stat_ok;
|
||||
gboolean is_symlink, symlink_broken;
|
||||
@ -1799,11 +1803,10 @@ _g_local_file_info_get (const char *basename,
|
||||
return info;
|
||||
}
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
res = g_lstat (path, &statbuf);
|
||||
#else
|
||||
res = GLIB_PRIVATE_CALL (g_win32_lstat_utf8) (path, &statbuf);
|
||||
#endif
|
||||
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),
|
||||
&statbuf);
|
||||
|
||||
if (res == -1)
|
||||
{
|
||||
@ -1827,12 +1830,12 @@ _g_local_file_info_get (const char *basename,
|
||||
stat_ok = res != -1;
|
||||
|
||||
if (stat_ok)
|
||||
device = statbuf.st_dev;
|
||||
device = _g_stat_dev (&statbuf);
|
||||
else
|
||||
device = 0;
|
||||
|
||||
#ifdef S_ISLNK
|
||||
is_symlink = stat_ok && S_ISLNK (statbuf.st_mode);
|
||||
is_symlink = stat_ok && S_ISLNK (_g_stat_mode (&statbuf));
|
||||
#elif defined (G_OS_WIN32)
|
||||
/* glib already checked the FILE_ATTRIBUTE_REPARSE_POINT for us */
|
||||
is_symlink = stat_ok &&
|
||||
@ -1850,11 +1853,10 @@ _g_local_file_info_get (const char *basename,
|
||||
/* Unless NOFOLLOW was set we default to following symlinks */
|
||||
if (!(flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS))
|
||||
{
|
||||
#ifndef G_OS_WIN32
|
||||
res = stat (path, &statbuf2);
|
||||
#else
|
||||
res = GLIB_PRIVATE_CALL (g_win32_stat_utf8) (path, &statbuf2);
|
||||
#endif
|
||||
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),
|
||||
&statbuf2);
|
||||
|
||||
/* Report broken links as symlinks */
|
||||
if (res != -1)
|
||||
@ -1871,7 +1873,7 @@ _g_local_file_info_get (const char *basename,
|
||||
set_info_from_stat (info, &statbuf, attribute_matcher);
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
if (stat_ok && _g_local_file_is_lost_found_dir (path, statbuf.st_dev))
|
||||
if (stat_ok && _g_local_file_is_lost_found_dir (path, _g_stat_dev (&statbuf)))
|
||||
g_file_info_set_is_hidden (info, TRUE);
|
||||
#endif
|
||||
|
||||
@ -1886,7 +1888,7 @@ _g_local_file_info_get (const char *basename,
|
||||
}
|
||||
|
||||
if (basename != NULL && basename[strlen (basename) -1] == '~' &&
|
||||
(stat_ok && S_ISREG (statbuf.st_mode)))
|
||||
(stat_ok && S_ISREG (_g_stat_mode (&statbuf))))
|
||||
_g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_IS_BACKUP, TRUE);
|
||||
#else
|
||||
if (statbuf.attributes & FILE_ATTRIBUTE_HIDDEN)
|
||||
@ -1980,7 +1982,7 @@ _g_local_file_info_get (const char *basename,
|
||||
win32_get_file_user_info (path, NULL, &name, NULL);
|
||||
#else
|
||||
if (stat_ok)
|
||||
name = get_username_from_uid (statbuf.st_uid);
|
||||
name = get_username_from_uid (_g_stat_uid (&statbuf));
|
||||
#endif
|
||||
if (name)
|
||||
_g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_OWNER_USER, name);
|
||||
@ -1995,7 +1997,7 @@ _g_local_file_info_get (const char *basename,
|
||||
win32_get_file_user_info (path, NULL, NULL, &name);
|
||||
#else
|
||||
if (stat_ok)
|
||||
name = get_realname_from_uid (statbuf.st_uid);
|
||||
name = get_realname_from_uid (_g_stat_uid (&statbuf));
|
||||
#endif
|
||||
if (name)
|
||||
_g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_OWNER_USER_REAL, name);
|
||||
@ -2010,7 +2012,7 @@ _g_local_file_info_get (const char *basename,
|
||||
win32_get_file_user_info (path, &name, NULL, NULL);
|
||||
#else
|
||||
if (stat_ok)
|
||||
name = get_groupname_from_gid (statbuf.st_gid);
|
||||
name = get_groupname_from_gid (_g_stat_gid (&statbuf));
|
||||
#endif
|
||||
if (name)
|
||||
_g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_OWNER_GROUP, name);
|
||||
@ -2019,7 +2021,7 @@ _g_local_file_info_get (const char *basename,
|
||||
|
||||
if (stat_ok && parent_info && parent_info->device != 0 &&
|
||||
_g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_UNIX_IS_MOUNTPOINT) &&
|
||||
(statbuf.st_dev != parent_info->device || statbuf.st_ino == parent_info->inode))
|
||||
(_g_stat_dev (&statbuf) != parent_info->device || _g_stat_ino (&statbuf) == parent_info->inode))
|
||||
_g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_IS_MOUNTPOINT, TRUE);
|
||||
|
||||
if (stat_ok)
|
||||
@ -2073,14 +2075,11 @@ _g_local_file_info_get_from_fd (int fd,
|
||||
GLocalFileStat stat_buf;
|
||||
GFileAttributeMatcher *matcher;
|
||||
GFileInfo *info;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#define FSTAT GLIB_PRIVATE_CALL (g_win32_fstat)
|
||||
#else
|
||||
#define FSTAT fstat
|
||||
#endif
|
||||
|
||||
if (FSTAT (fd, &stat_buf) == -1)
|
||||
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),
|
||||
&stat_buf) == -1)
|
||||
{
|
||||
int errsv = errno;
|
||||
|
||||
|
@ -21,12 +21,24 @@
|
||||
#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>
|
||||
#include <glib/glib-private.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <glib/gstdioprivate.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_STATX
|
||||
#include <sys/sysmacros.h>
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct
|
||||
@ -41,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
|
||||
@ -48,6 +173,158 @@ typedef struct
|
||||
#define GLocalFileStat struct stat
|
||||
#endif
|
||||
|
||||
/* If the system doesn’t have statx() support, emulate it using traditional
|
||||
* stat(). It supports fields %G_LOCAL_FILE_STAT_FIELD_BASIC_STATS only, and
|
||||
* always returns all of them. */
|
||||
typedef enum
|
||||
{
|
||||
G_LOCAL_FILE_STAT_FIELD_TYPE = (1 << 0),
|
||||
G_LOCAL_FILE_STAT_FIELD_MODE = (1 << 1),
|
||||
G_LOCAL_FILE_STAT_FIELD_NLINK = (1 << 2),
|
||||
G_LOCAL_FILE_STAT_FIELD_UID = (1 << 3),
|
||||
G_LOCAL_FILE_STAT_FIELD_GID = (1 << 4),
|
||||
G_LOCAL_FILE_STAT_FIELD_ATIME = (1 << 5),
|
||||
G_LOCAL_FILE_STAT_FIELD_MTIME = (1 << 6),
|
||||
G_LOCAL_FILE_STAT_FIELD_CTIME = (1 << 7),
|
||||
G_LOCAL_FILE_STAT_FIELD_INO = (1 << 8),
|
||||
G_LOCAL_FILE_STAT_FIELD_SIZE = (1 << 9),
|
||||
G_LOCAL_FILE_STAT_FIELD_BLOCKS = (1 << 10),
|
||||
G_LOCAL_FILE_STAT_FIELD_BTIME = (1 << 11),
|
||||
} GLocalFileStatField;
|
||||
|
||||
#define G_LOCAL_FILE_STAT_FIELD_BASIC_STATS \
|
||||
(G_LOCAL_FILE_STAT_FIELD_TYPE | G_LOCAL_FILE_STAT_FIELD_MODE | \
|
||||
G_LOCAL_FILE_STAT_FIELD_NLINK | G_LOCAL_FILE_STAT_FIELD_UID | \
|
||||
G_LOCAL_FILE_STAT_FIELD_GID | G_LOCAL_FILE_STAT_FIELD_ATIME | \
|
||||
G_LOCAL_FILE_STAT_FIELD_MTIME | G_LOCAL_FILE_STAT_FIELD_CTIME | \
|
||||
G_LOCAL_FILE_STAT_FIELD_INO | G_LOCAL_FILE_STAT_FIELD_SIZE | \
|
||||
G_LOCAL_FILE_STAT_FIELD_BLOCKS)
|
||||
#define G_LOCAL_FILE_STAT_FIELD_ALL (G_LOCAL_FILE_STAT_FIELD_BASIC_STATS | G_LOCAL_FILE_STAT_FIELD_BTIME)
|
||||
|
||||
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
|
||||
return fstat (fd, stat_buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int
|
||||
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;
|
||||
return -1;
|
||||
#else
|
||||
return fstatat (fd, path, stat_buf, flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
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
|
||||
return g_lstat (path, stat_buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
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
|
||||
return stat (path, stat_buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline static gboolean _g_stat_has_field (const GLocalFileStat *buf, GLocalFileStatField field) { return (G_LOCAL_FILE_STAT_FIELD_BASIC_STATS & field) == field; }
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
inline static mode_t _g_stat_mode (const GLocalFileStat *buf) { return buf->st_mode; }
|
||||
inline static nlink_t _g_stat_nlink (const GLocalFileStat *buf) { return buf->st_nlink; }
|
||||
#else
|
||||
inline static guint16 _g_stat_mode (const GLocalFileStat *buf) { return buf->st_mode; }
|
||||
inline static guint32 _g_stat_nlink (const GLocalFileStat *buf) { return buf->st_nlink; }
|
||||
#endif
|
||||
inline static dev_t _g_stat_dev (const GLocalFileStat *buf) { return buf->st_dev; }
|
||||
inline static ino_t _g_stat_ino (const GLocalFileStat *buf) { return buf->st_ino; }
|
||||
inline static off_t _g_stat_size (const GLocalFileStat *buf) { return buf->st_size; }
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
inline static uid_t _g_stat_uid (const GLocalFileStat *buf) { return buf->st_uid; }
|
||||
inline static gid_t _g_stat_gid (const GLocalFileStat *buf) { return buf->st_gid; }
|
||||
inline static dev_t _g_stat_rdev (const GLocalFileStat *buf) { return buf->st_rdev; }
|
||||
inline static blksize_t _g_stat_blksize (const GLocalFileStat *buf) { return buf->st_blksize; }
|
||||
#else
|
||||
inline static guint16 _g_stat_uid (const GLocalFileStat *buf) { return buf->st_uid; }
|
||||
inline static guint16 _g_stat_gid (const GLocalFileStat *buf) { return buf->st_gid; }
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
|
||||
inline static blkcnt_t _g_stat_blocks (const GLocalFileStat *buf) { return buf->st_blocks; }
|
||||
#endif
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
inline static time_t _g_stat_atime (const GLocalFileStat *buf) { return buf->st_atime; }
|
||||
inline static time_t _g_stat_ctime (const GLocalFileStat *buf) { return buf->st_ctime; }
|
||||
inline static time_t _g_stat_mtime (const GLocalFileStat *buf) { return buf->st_mtime; }
|
||||
#endif
|
||||
#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
|
||||
inline static guint32 _g_stat_atim_nsec (const GLocalFileStat *buf) { return buf->st_atim.tv_nsec; }
|
||||
inline static guint32 _g_stat_ctim_nsec (const GLocalFileStat *buf) { return buf->st_ctim.tv_nsec; }
|
||||
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>
|
||||
@ -424,7 +429,7 @@ _g_local_file_output_stream_really_close (GLocalFileOutputStream *file,
|
||||
|
||||
#ifndef G_OS_WIN32 /* Already did the fstat() and close() above on Win32 */
|
||||
|
||||
if (fstat (file->priv->fd, &final_stat) == 0)
|
||||
if (g_local_file_fstat (file->priv->fd, G_LOCAL_FILE_STAT_FIELD_MTIME, G_LOCAL_FILE_STAT_FIELD_ALL, &final_stat) == 0)
|
||||
file->priv->etag = _g_local_file_info_create_etag (&final_stat);
|
||||
|
||||
if (!g_close (file->priv->fd, NULL))
|
||||
@ -891,12 +896,15 @@ handle_overwrite_open (const char *filename,
|
||||
g_free (display_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
res = GLIB_PRIVATE_CALL (g_win32_fstat) (fd, &original_stat);
|
||||
#else
|
||||
res = fstat (fd, &original_stat);
|
||||
#endif
|
||||
|
||||
res = g_local_file_fstat (fd,
|
||||
G_LOCAL_FILE_STAT_FIELD_TYPE |
|
||||
G_LOCAL_FILE_STAT_FIELD_MODE |
|
||||
G_LOCAL_FILE_STAT_FIELD_UID |
|
||||
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);
|
||||
errsv = errno;
|
||||
|
||||
if (res != 0)
|
||||
@ -911,9 +919,9 @@ handle_overwrite_open (const char *filename,
|
||||
}
|
||||
|
||||
/* not a regular file */
|
||||
if (!S_ISREG (original_stat.st_mode))
|
||||
if (!S_ISREG (_g_stat_mode (&original_stat)))
|
||||
{
|
||||
if (S_ISDIR (original_stat.st_mode))
|
||||
if (S_ISDIR (_g_stat_mode (&original_stat)))
|
||||
g_set_error_literal (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_IS_DIRECTORY,
|
||||
@ -953,7 +961,7 @@ handle_overwrite_open (const char *filename,
|
||||
*/
|
||||
|
||||
if ((flags & G_FILE_CREATE_REPLACE_DESTINATION) ||
|
||||
(!(original_stat.st_nlink > 1) && !is_symlink))
|
||||
(!(_g_stat_nlink (&original_stat) > 1) && !is_symlink))
|
||||
{
|
||||
char *dirname, *tmp_filename;
|
||||
int tmpfd;
|
||||
@ -974,10 +982,10 @@ handle_overwrite_open (const char *filename,
|
||||
if ( ! (flags & G_FILE_CREATE_REPLACE_DESTINATION) &&
|
||||
(
|
||||
#ifdef HAVE_FCHOWN
|
||||
fchown (tmpfd, original_stat.st_uid, original_stat.st_gid) == -1 ||
|
||||
fchown (tmpfd, _g_stat_uid (&original_stat), _g_stat_gid (&original_stat)) == -1 ||
|
||||
#endif
|
||||
#ifdef HAVE_FCHMOD
|
||||
fchmod (tmpfd, original_stat.st_mode & ~S_IFMT) == -1 ||
|
||||
fchmod (tmpfd, _g_stat_mode (&original_stat) & ~S_IFMT) == -1 ||
|
||||
#endif
|
||||
0
|
||||
)
|
||||
@ -986,16 +994,18 @@ handle_overwrite_open (const char *filename,
|
||||
GLocalFileStat tmp_statbuf;
|
||||
int tres;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
tres = GLIB_PRIVATE_CALL (g_win32_fstat) (tmpfd, &tmp_statbuf);
|
||||
#else
|
||||
tres = fstat (tmpfd, &tmp_statbuf);
|
||||
#endif
|
||||
tres = g_local_file_fstat (tmpfd,
|
||||
G_LOCAL_FILE_STAT_FIELD_TYPE |
|
||||
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);
|
||||
|
||||
/* Check that we really needed to change something */
|
||||
if (tres != 0 ||
|
||||
original_stat.st_uid != tmp_statbuf.st_uid ||
|
||||
original_stat.st_gid != tmp_statbuf.st_gid ||
|
||||
original_stat.st_mode != tmp_statbuf.st_mode)
|
||||
_g_stat_uid (&original_stat) != _g_stat_uid (&tmp_statbuf) ||
|
||||
_g_stat_gid (&original_stat) != _g_stat_gid (&tmp_statbuf) ||
|
||||
_g_stat_mode (&original_stat) != _g_stat_mode (&tmp_statbuf))
|
||||
{
|
||||
g_close (tmpfd, NULL);
|
||||
g_unlink (tmp_filename);
|
||||
@ -1014,7 +1024,7 @@ handle_overwrite_open (const char *filename,
|
||||
if (create_backup)
|
||||
{
|
||||
#if defined(HAVE_FCHOWN) && defined(HAVE_FCHMOD)
|
||||
struct stat tmp_statbuf;
|
||||
GLocalFileStat tmp_statbuf;
|
||||
#endif
|
||||
char *backup_filename;
|
||||
int bfd;
|
||||
@ -1033,7 +1043,7 @@ handle_overwrite_open (const char *filename,
|
||||
|
||||
bfd = g_open (backup_filename,
|
||||
O_WRONLY | O_CREAT | O_EXCL | O_BINARY,
|
||||
original_stat.st_mode & 0777);
|
||||
_g_stat_mode (&original_stat) & 0777);
|
||||
|
||||
if (bfd == -1)
|
||||
{
|
||||
@ -1050,7 +1060,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 (fstat (bfd, &tmp_statbuf) != 0)
|
||||
if (g_local_file_fstat (bfd, G_LOCAL_FILE_STAT_FIELD_GID, G_LOCAL_FILE_STAT_FIELD_ALL, &tmp_statbuf) != 0)
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
G_IO_ERROR,
|
||||
@ -1062,12 +1072,12 @@ handle_overwrite_open (const char *filename,
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if ((original_stat.st_gid != tmp_statbuf.st_gid) &&
|
||||
fchown (bfd, (uid_t) -1, original_stat.st_gid) != 0)
|
||||
if ((_g_stat_gid (&original_stat) != _g_stat_gid (&tmp_statbuf)) &&
|
||||
fchown (bfd, (uid_t) -1, _g_stat_gid (&original_stat)) != 0)
|
||||
{
|
||||
if (fchmod (bfd,
|
||||
(original_stat.st_mode & 0707) |
|
||||
((original_stat.st_mode & 07) << 3)) != 0)
|
||||
(_g_stat_mode (&original_stat) & 0707) |
|
||||
((_g_stat_mode (&original_stat) & 07) << 3)) != 0)
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
G_IO_ERROR,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -235,9 +235,9 @@ thumbnail_verify (const char *thumbnail_path,
|
||||
#ifdef G_OS_WIN32
|
||||
expected_info.mtime = (guint64) file_stat_buf->st_mtim.tv_sec;
|
||||
#else
|
||||
expected_info.mtime = (guint64) file_stat_buf->st_mtime;
|
||||
expected_info.mtime = _g_stat_mtime (file_stat_buf);
|
||||
#endif
|
||||
expected_info.size = file_stat_buf->st_size;
|
||||
expected_info.size = _g_stat_size (file_stat_buf);
|
||||
|
||||
file = g_mapped_file_new (thumbnail_path, FALSE, NULL);
|
||||
if (file)
|
||||
|
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