mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-01 15:03:39 +02:00
W32: Add a stat() implementation for private use
This commit adds new W32-only functions to gstdio.c, and a new header file, gstdioprivate.h. These functions are: g_win32_stat_utf8() g_win32_lstat_utf8() g_win32_fstat() and they fill a private structure, GWin32PrivateStat, which has all the fields that normal stat has, as well as some extras. These functions are then used throughout glib and gio to get better data about the system. Specifically: * Full, 64-bit size, guaranteed (g_stat() is forced to use 32-bit st_size) * Full, 64-bit file identifier (st_ino is 0 when normal stat() is used, and still is) * W32 File attributes (which stat() doesn't report); in particular, this allows symlinks to be correctly identified * Full, 64-bit time, guaranteed (g_stat() uses 32-bit st_*time on 32-bit Windows) * Allocated file size (as a W32 replacement for the missing st_blocks) st_mode remains unchanged (thus, no S_ISLNK), so when these are given back to glib users (via g_stat(), for example, which is now implemented by calling g_win32_stat_utf8), this field does not contain anything unexpected. g_lstat() now calls g_win32_lstat_utf8(), which works on symlinks the way it's supposed to. Also adds the g_win32_readlink_utf8() function, which behaves like readlink() (including its inability to return 0-terminated strings and inability to say how large the output buffer should be; these limitations are purely for compatibility with existing glib code). Thus, symlink support should now be much better, although far from being complete. A new W32-only test in gio/tests/file.c highlights the following features: * allocated size * 64-bit time * unique file IDs https://bugzilla.gnome.org/show_bug.cgi?id=788180
This commit is contained in:
committed by
Philip Withnall
parent
c74ab4a1db
commit
53bd6a359f
@@ -62,11 +62,11 @@
|
||||
#include "gunixmounts.h"
|
||||
#include "gioerror.h"
|
||||
#include <glib/gstdio.h>
|
||||
#include <glib/gstdioprivate.h>
|
||||
#include "glibintl.h"
|
||||
#ifdef G_OS_UNIX
|
||||
#include "glib-unix.h"
|
||||
#endif
|
||||
#include "glib-private.h"
|
||||
|
||||
#include "glib-private.h"
|
||||
|
||||
@@ -1395,7 +1395,8 @@ g_local_file_read (GFile *file,
|
||||
#ifdef G_OS_WIN32
|
||||
if (errsv == EACCES)
|
||||
{
|
||||
ret = _stati64 (local->filename, &buf);
|
||||
/* Exploit the fact that on W32 the glib filename encoding is UTF8 */
|
||||
ret = GLIB_PRIVATE_CALL (g_win32_stat_utf8) (local->filename, &buf);
|
||||
if (ret == 0 && S_ISDIR (buf.st_mode))
|
||||
errsv = EISDIR;
|
||||
}
|
||||
@@ -1407,7 +1408,7 @@ g_local_file_read (GFile *file,
|
||||
}
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
ret = _fstati64 (fd, &buf);
|
||||
ret = GLIB_PRIVATE_CALL (g_win32_fstat) (fd, &buf);
|
||||
#else
|
||||
ret = fstat (fd, &buf);
|
||||
#endif
|
||||
@@ -2677,33 +2678,12 @@ g_local_file_measure_size_of_file (gint parent_fd,
|
||||
int errsv = errno;
|
||||
return g_local_file_measure_size_error (state->flags, errsv, name, error);
|
||||
}
|
||||
#else
|
||||
{
|
||||
const char *filename = (const gchar *) name->data;
|
||||
wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
|
||||
int retval;
|
||||
int save_errno;
|
||||
int len;
|
||||
|
||||
if (wfilename == NULL)
|
||||
return g_local_file_measure_size_error (state->flags, errno, name, error);
|
||||
|
||||
len = wcslen (wfilename);
|
||||
while (len > 0 && G_IS_DIR_SEPARATOR (wfilename[len-1]))
|
||||
len--;
|
||||
if (len > 0 &&
|
||||
(!g_path_is_absolute (filename) || len > g_path_skip_root (filename) - filename))
|
||||
wfilename[len] = '\0';
|
||||
|
||||
retval = _wstati64 (wfilename, &buf);
|
||||
save_errno = errno;
|
||||
|
||||
g_free (wfilename);
|
||||
|
||||
errno = save_errno;
|
||||
if (retval != 0)
|
||||
return g_local_file_measure_size_error (state->flags, errno, name, error);
|
||||
}
|
||||
#else /* !AT_FDCWD && !HAVE_LSTAT && G_OS_WIN32 */
|
||||
if (GLIB_PRIVATE_CALL (g_win32_lstat_utf8) (name->data, &buf) != 0)
|
||||
{
|
||||
int errsv = errno;
|
||||
return g_local_file_measure_size_error (state->flags, errsv, name, error);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (name->next)
|
||||
@@ -2722,7 +2702,11 @@ g_local_file_measure_size_of_file (gint parent_fd,
|
||||
state->contained_on = buf.st_dev;
|
||||
}
|
||||
|
||||
#if defined (HAVE_STRUCT_STAT_ST_BLOCKS)
|
||||
#if defined (G_OS_WIN32)
|
||||
if (~state->flags & G_FILE_MEASURE_APPARENT_SIZE)
|
||||
state->disk_usage += buf.allocated_size;
|
||||
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);
|
||||
else
|
||||
|
Reference in New Issue
Block a user