+2008-01-17 Alexander Larsson <alexl@redhat.com>
+
+ * gfile.c:
+ (g_file_copy):
+ (g_file_move):
+ Allow calls to implementation of copy and write
+ even if the type of the file implementations is
+ different. This can be used to implement native
+ upload and download calls in a vfs.
+
+ * glocalfile.c:
+ (g_local_file_move):
+ Protect against the case where move is called
+ with one file not being local.
+
+ Make sure we call the progress callback once
+ in the native move operation so that the caller
+ knows how many bytes were copied.
+
2008-01-16 Murray Cumming <murrayc@murrayc.com>
* gappinfo.c:
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
- if (G_OBJECT_TYPE (source) == G_OBJECT_TYPE (destination))
+ iface = G_FILE_GET_IFACE (destination);
+ if (iface->copy)
{
- iface = G_FILE_GET_IFACE (source);
+ my_error = NULL;
+ res = (* iface->copy) (source, destination,
+ flags, cancellable,
+ progress_callback, progress_callback_data,
+ &my_error);
+
+ if (res)
+ return TRUE;
+
+ if (my_error->domain != G_IO_ERROR || my_error->code != G_IO_ERROR_NOT_SUPPORTED)
+ {
+ g_propagate_error (error, my_error);
+ return FALSE;
+ }
+ }
+ /* If the types are different, and the destination method failed
+ also try the source method */
+ if (G_OBJECT_TYPE (source) != G_OBJECT_TYPE (destination))
+ {
+ iface = G_FILE_GET_IFACE (source);
+
if (iface->copy)
{
my_error = NULL;
- res = (* iface->copy) (source, destination, flags, cancellable, progress_callback, progress_callback_data, &my_error);
+ res = (* iface->copy) (source, destination,
+ flags, cancellable,
+ progress_callback, progress_callback_data,
+ &my_error);
if (res)
return TRUE;
}
}
}
-
+
return file_copy_fallback (source, destination, flags, cancellable,
progress_callback, progress_callback_data,
error);
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
- if (G_OBJECT_TYPE (source) == G_OBJECT_TYPE (destination))
+ iface = G_FILE_GET_IFACE (destination);
+ if (iface->move)
{
- iface = G_FILE_GET_IFACE (source);
+ my_error = NULL;
+ res = (* iface->move) (source, destination,
+ flags, cancellable,
+ progress_callback, progress_callback_data,
+ &my_error);
+
+ if (res)
+ return TRUE;
+
+ if (my_error->domain != G_IO_ERROR || my_error->code != G_IO_ERROR_NOT_SUPPORTED)
+ {
+ g_propagate_error (error, my_error);
+ return FALSE;
+ }
+ }
+ /* If the types are different, and the destination method failed
+ also try the source method */
+ if (G_OBJECT_TYPE (source) != G_OBJECT_TYPE (destination))
+ {
+ iface = G_FILE_GET_IFACE (source);
+
if (iface->move)
{
my_error = NULL;
- res = (* iface->move) (source, destination, flags, cancellable, progress_callback, progress_callback_data, &my_error);
+ res = (* iface->move) (source, destination,
+ flags, cancellable,
+ progress_callback, progress_callback_data,
+ &my_error);
if (res)
return TRUE;
}
}
}
-
+
if (flags & G_FILE_COPY_NO_FALLBACK_FOR_MOVE)
{
g_set_error (error, G_IO_ERROR,
gpointer progress_callback_data,
GError **error)
{
- GLocalFile *local_source = G_LOCAL_FILE (source);
+ GLocalFile *local_source;
GLocalFile *local_destination = G_LOCAL_FILE (destination);
struct stat statbuf;
gboolean destination_exist, source_is_dir;
char *backup_name;
int res;
-
+ off_t source_size;
+
+ if (!G_IS_LOCAL_FILE (source) ||
+ !G_IS_LOCAL_FILE (destination))
+ {
+ /* Fall back to default move */
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Move not supported");
+ return FALSE;
+ }
+
+ local_source = G_LOCAL_FILE (source);
+
res = g_lstat (local_source->filename, &statbuf);
if (res == -1)
{
}
else
source_is_dir = S_ISDIR (statbuf.st_mode);
+
+ source_size = statbuf.st_size;
destination_exist = FALSE;
res = g_lstat (local_destination->filename, &statbuf);
_("Error moving file: %s"),
g_strerror (errsv));
return FALSE;
-
}
+
+ /* Make sure we send full copied size */
+ if (progress_callback)
+ progress_callback (source_size, source_size, progress_callback_data);
+
return TRUE;
}