diff --git a/gio/ChangeLog b/gio/ChangeLog index c884a237c..605750e85 100644 --- a/gio/ChangeLog +++ b/gio/ChangeLog @@ -1,3 +1,22 @@ +2008-01-17 Alexander Larsson + + * 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 * gappinfo.c: diff --git a/gio/gfile.c b/gio/gfile.c index 303915907..12b148c29 100644 --- a/gio/gfile.c +++ b/gio/gfile.c @@ -2115,14 +2115,38 @@ g_file_copy (GFile *source, 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) + { + 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; @@ -2134,7 +2158,7 @@ g_file_copy (GFile *source, } } } - + return file_copy_fallback (source, destination, flags, cancellable, progress_callback, progress_callback_data, error); @@ -2209,14 +2233,38 @@ g_file_move (GFile *source, 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) + { + 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; @@ -2228,7 +2276,7 @@ g_file_move (GFile *source, } } } - + if (flags & G_FILE_COPY_NO_FALLBACK_FOR_MOVE) { g_set_error (error, G_IO_ERROR, diff --git a/gio/glocalfile.c b/gio/glocalfile.c index 2b4b35e70..d6bbec805 100644 --- a/gio/glocalfile.c +++ b/gio/glocalfile.c @@ -1753,13 +1753,24 @@ g_local_file_move (GFile *source, 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) { @@ -1771,6 +1782,8 @@ g_local_file_move (GFile *source, } else source_is_dir = S_ISDIR (statbuf.st_mode); + + source_size = statbuf.st_size; destination_exist = FALSE; res = g_lstat (local_destination->filename, &statbuf); @@ -1853,8 +1866,12 @@ g_local_file_move (GFile *source, _("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; }