GFile: `g_file_replace_contents()` reports `G_IO_ERROR_WRONG_ETAG` when saving a removed file through a symlink
Follow-up to #2417 (comment 1251766).
Here is a use case:
#include <glib.h>
#include <gio/gio.h>
gint main (gint argc, gchar **argv)
{
GFile *target, *link;
GFileIOStream *ios;
GError *error = NULL;
const gchar *target_path;
gchar *link_path, *contents, *etag;
gsize size;
target = g_file_new_tmp (NULL, &ios, NULL);
target_path = g_file_peek_path (target);
link_path = g_strconcat (target_path, "-link", NULL);
link = g_file_new_for_path (link_path);
g_file_make_symbolic_link (link, target_path, NULL, NULL);
/* load contents via the symlink, etag as output */
g_file_load_contents (link, NULL, &contents, &size, &etag, NULL);
/* delete the target: in practice, it comes from outside */
g_file_delete (target, NULL, NULL);
/* replace contents via the symlink, etag as input */
g_file_replace_contents (link, contents, size, etag, FALSE, G_FILE_CREATE_NONE, NULL, NULL, &error);
/* check error */
if (error != NULL)
{
g_printerr ("G_IO_ERROR_WRONG_ETAG? %d\n",
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WRONG_ETAG));
g_error_free (error);
}
else
g_printerr ("%s\n", "No error");
g_file_delete (link, NULL, NULL);
g_object_unref (target);
g_object_unref (link);
g_object_unref (ios);
g_free (link_path);
g_free (contents);
g_free (etag);
}
I don't think the input etag should be compared to the symbolic link etag, because the flag is G_FILE_CREATE_NONE
, not G_FILE_CREATE_REPLACE_DESTINATION
, so we are supposed to follow links.
It is certainly possible to set etag to NULL
for the operation to succeed, but it is not necessary when you are in the same situation with a regular file (deleted from the outside, etag != NULL
).
It seems to me that the behavior should be the same here: ignore the etag, which was the etag of the target, if the target no longer exists.