summaryrefslogtreecommitdiff
path: root/glib/gfileutils.c
diff options
context:
space:
mode:
authorРуслан Ижбулатов <lrn1986@gmail.com>2018-08-24 09:16:46 +0000
committerРуслан Ижбулатов <lrn1986@gmail.com>2018-10-10 19:19:18 +0000
commit62d387151dfd7c3f807370844d9a936d6d42699c (patch)
treebe76298c43f358192ed685ad0f26138518cd719a /glib/gfileutils.c
parent19608e36d2a6f57237505eec19363ef210d7501d (diff)
downloadglib-62d387151dfd7c3f807370844d9a936d6d42699c.tar.gz
W32: significant symlink code changes
Put the core readlink() code into a separate _g_win32_readlink_handle_raw() function that takes a file handle, can optionally ensure NUL-terminatedness of its output (for cases where we need a NUL-terminator and do *not* need to get the exact contents of the symlink as it is stored in FS) and can either fill a caller-provided buffer *or* allocate its own buffer, and can also read the reparse tag. Put the rest of readlink() code into separate functions that do UTF-16<->UTF-8, strip inconvenient prefix and open/close the symlink file handle as needed. Split _g_win32_stat_utf16_no_trailing_slashes() into two functions - the one that takes a filename and the one that takes a file descriptor. The part of these functions that would have been duplicate is now split into the _g_win32_fill_privatestat() funcion. Add more comments explaining what each function does. Only g_win32_readlink_utf8(), which is callable from outside via private function interface, gets a real doc-comment, the rest get normal, non-doc comments. Change all callers to use the new version of the private g_win32_readlink_utf8() function, which can now NUL-terminate and allocate on demand - no need to call it in a loop. Also, the new code should correctly get reparse tag when the caller does fstat() on a symlink. Do note that this requires the caller to get a FD for the symlink, not the target. Figuring out how to do that is up to the caller. Since symlink info (target path and reparse tag) are now always read directly, via DeviceIoControl(), we don't need to use FindFirstFileW() anymore.
Diffstat (limited to 'glib/gfileutils.c')
-rw-r--r--glib/gfileutils.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/glib/gfileutils.c b/glib/gfileutils.c
index 1e7a771a9..b39d3d478 100644
--- a/glib/gfileutils.c
+++ b/glib/gfileutils.c
@@ -2090,7 +2090,7 @@ gchar *
g_file_read_link (const gchar *filename,
GError **error)
{
-#if defined (HAVE_READLINK) || defined (G_OS_WIN32)
+#if defined (HAVE_READLINK)
gchar *buffer;
size_t size;
gssize read_size;
@@ -2103,11 +2103,7 @@ g_file_read_link (const gchar *filename,
while (TRUE)
{
-#ifndef G_OS_WIN32
read_size = readlink (filename, buffer, size);
-#else
- read_size = g_win32_readlink_utf8 (filename, buffer, size);
-#endif
if (read_size < 0)
{
int saved_errno = errno;
@@ -2128,6 +2124,27 @@ g_file_read_link (const gchar *filename,
size *= 2;
buffer = g_realloc (buffer, size);
}
+#elif defined (G_OS_WIN32)
+ gchar *buffer;
+ gssize read_size;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ read_size = g_win32_readlink_utf8 (filename, NULL, 0, &buffer, TRUE);
+ if (read_size < 0)
+ {
+ int saved_errno = errno;
+ set_file_error (error,
+ filename,
+ _("Failed to read the symbolic link “%s”: %s"),
+ saved_errno);
+ return NULL;
+ }
+ else if (read_size == 0)
+ return strdup ("");
+ else
+ return buffer;
#else
g_return_val_if_fail (filename != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);