[phodav: 12/18] wip: move method movecopy
- From: Marc-Andre Lureau <malureau src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [phodav: 12/18] wip: move method movecopy
- Date: Thu, 10 Apr 2014 17:52:05 +0000 (UTC)
commit 632bb2581d913af132692e1adf4f25b61891ee9b
Author: Marc-André Lureau <marcandre lureau gmail com>
Date: Thu Apr 10 19:06:23 2014 +0200
wip: move method movecopy
Makefile.am | 1 +
libphodav/phodav-method-movecopy.c | 197 ++++++++++++++++++++++++++++++++++++
libphodav/phodav-priv.h | 2 +
libphodav/phodav-server.c | 178 +--------------------------------
4 files changed, 201 insertions(+), 177 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 4e63829..fb90999 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -37,6 +37,7 @@ libphodav_1_0_la_SOURCES = \
libphodav/phodav-method-delete.c \
libphodav/phodav-method-get.c \
libphodav/phodav-method-mkcol.c \
+ libphodav/phodav-method-movecopy.c \
libphodav/phodav-method-propfind.c \
libphodav/phodav-method-proppatch.c \
libphodav/phodav-multistatus.c \
diff --git a/libphodav/phodav-method-movecopy.c b/libphodav/phodav-method-movecopy.c
new file mode 100644
index 0000000..b01cc7b
--- /dev/null
+++ b/libphodav/phodav-method-movecopy.c
@@ -0,0 +1,197 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/*
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "phodav-priv.h"
+#include "phodav-utils.h"
+#include "phodav-lock.h"
+
+static gboolean
+do_copy_r (GFile *src, GFile *dest, GFileCopyFlags flags,
+ GCancellable *cancellable, GError **err)
+{
+ GFileEnumerator *e = NULL;
+ gboolean success = FALSE;
+ GFile *src_child = NULL;
+ GFile *dest_child = NULL;
+
+ if (!g_file_make_directory_with_parents (dest, cancellable, err))
+ goto end;
+
+ e = g_file_enumerate_children (src, "standard::*", G_FILE_QUERY_INFO_NONE,
+ cancellable, err);
+ if (!e)
+ goto end;
+
+ while (1)
+ {
+ GFileInfo *info = g_file_enumerator_next_file (e, cancellable, err);
+ if (!info)
+ break;
+
+ src_child = g_file_get_child (src, g_file_info_get_name (info));
+ dest_child = g_file_get_child (dest, g_file_info_get_name (info));
+ gboolean isdir = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
+ g_object_unref (info);
+
+ if (isdir)
+ {
+ if (!do_copy_r (src_child, dest_child, flags, cancellable, err))
+ goto end;
+ }
+ else if (!g_file_copy (src_child, dest_child, flags, cancellable, NULL, NULL, err))
+ goto end;
+
+ g_clear_object (&src_child);
+ g_clear_object (&dest_child);
+ }
+
+ success = TRUE;
+
+end:
+ g_clear_object (&e);
+ g_clear_object (&src_child);
+ g_clear_object (&dest_child);
+
+ return success;
+}
+
+static gint
+do_movecopy_file (SoupMessage *msg, GFile *file,
+ GFile *dest, const gchar *dest_path,
+ GCancellable *cancellable, GError **err)
+{
+ GError *error = NULL;
+ gboolean overwrite;
+ DepthType depth;
+ gint status = SOUP_STATUS_PRECONDITION_FAILED;
+ gboolean copy = msg->method == SOUP_METHOD_COPY;
+ GFileCopyFlags flags = G_FILE_COPY_ALL_METADATA;
+ gboolean retry = FALSE;
+ gboolean exists;
+
+ depth = depth_from_string (soup_message_headers_get_one (msg->request_headers, "Depth"));
+ overwrite = !!g_strcmp0 (
+ soup_message_headers_get_one (msg->request_headers, "Overwrite"), "F");
+ if (overwrite)
+ flags |= G_FILE_COPY_OVERWRITE;
+ exists = g_file_query_exists (dest, cancellable);
+
+again:
+ switch (depth)
+ {
+ case DEPTH_INFINITY:
+ case DEPTH_ZERO: {
+ copy
+ ? g_file_copy (file, dest, flags, cancellable, NULL, NULL, &error)
+ : g_file_move (file, dest, flags, cancellable, NULL, NULL, &error);
+
+ if (overwrite && !retry &&
+ (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY) ||
+ g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_MERGE)) &&
+ phodav_delete_file (dest_path, dest, NULL, cancellable) == SOUP_STATUS_NO_CONTENT)
+ {
+ g_clear_error (&error);
+ retry = TRUE;
+ goto again;
+ }
+ else if (!overwrite &&
+ g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+ {
+ g_clear_error (&error);
+ goto end;
+ }
+ else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE))
+ {
+ g_clear_error (&error);
+ if (copy)
+ {
+ if (depth == DEPTH_INFINITY)
+ do_copy_r (file, dest, flags, cancellable, &error);
+ else
+ g_file_make_directory_with_parents (dest, cancellable, &error);
+ }
+ }
+ else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ {
+ status = SOUP_STATUS_CONFLICT;
+ g_clear_error (&error);
+ goto end;
+ }
+
+ break;
+ }
+
+ default:
+ g_warn_if_reached ();
+ }
+
+ if (error)
+ g_propagate_error (err, error);
+ else
+ status = exists ? SOUP_STATUS_NO_CONTENT : SOUP_STATUS_CREATED;
+
+end:
+ return status;
+}
+
+gint
+phodav_method_movecopy (PathHandler *handler, SoupMessage *msg,
+ const char *path, GError **err)
+{
+ GFile *file = NULL, *dest_file = NULL;
+ GCancellable *cancellable = handler_get_cancellable (handler);
+ SoupURI *dest_uri = NULL;
+ gint status = SOUP_STATUS_NOT_FOUND;
+ const gchar *dest;
+ gchar *udest;
+ GList *submitted = NULL;
+
+ dest = soup_message_headers_get_one (msg->request_headers, "Destination");
+ if (!dest)
+ goto end;
+ dest_uri = soup_uri_new (dest);
+ dest = soup_uri_get_path (dest_uri);
+ if (!dest || !*dest)
+ goto end;
+
+ status = phodav_check_if (handler, msg, path, &submitted);
+ if (status != SOUP_STATUS_OK)
+ goto end;
+
+ if (server_path_has_other_locks (handler_get_server (handler), dest, submitted))
+ {
+ status = SOUP_STATUS_LOCKED;
+ goto end;
+ }
+
+ udest = g_uri_unescape_string (dest + 1, NULL);
+ dest_file = g_file_get_child (handler_get_file (handler), udest);
+ g_free (udest);
+
+ file = g_file_get_child (handler_get_file (handler), path + 1);
+ status = do_movecopy_file (msg, file, dest_file, dest,
+ cancellable, err);
+
+end:
+ if (dest_uri)
+ soup_uri_free (dest_uri);
+ g_clear_object (&file);
+ g_clear_object (&dest_file);
+ g_list_free_full (submitted, (GDestroyNotify) lock_submitted_free);
+ return status;
+}
diff --git a/libphodav/phodav-priv.h b/libphodav/phodav-priv.h
index d8c4e2f..e96f0f7 100644
--- a/libphodav/phodav-priv.h
+++ b/libphodav/phodav-priv.h
@@ -113,6 +113,8 @@ gint phodav_method_mkcol (PathHandler *handl
const char *path, GError **err);
gint phodav_method_delete (PathHandler *handler, SoupMessage *msg,
const char *path, GError **err);
+gint phodav_method_movecopy (PathHandler *handler, SoupMessage *msg,
+ const char *path, GError **err);
G_END_DECLS
diff --git a/libphodav/phodav-server.c b/libphodav/phodav-server.c
index 13cb969..9b82120 100644
--- a/libphodav/phodav-server.c
+++ b/libphodav/phodav-server.c
@@ -461,182 +461,6 @@ server_path_has_other_locks (PhodavServer *self, const gchar *path, GList *locks
return !server_foreach_parent_path (self, path, other_lock_exists, locks);
}
-static gboolean
-do_copy_r (GFile *src, GFile *dest, GFileCopyFlags flags,
- GCancellable *cancellable, GError **err)
-{
- GFileEnumerator *e = NULL;
- gboolean success = FALSE;
- GFile *src_child = NULL;
- GFile *dest_child = NULL;
-
- if (!g_file_make_directory_with_parents (dest, cancellable, err))
- goto end;
-
- e = g_file_enumerate_children (src, "standard::*", G_FILE_QUERY_INFO_NONE,
- cancellable, err);
- if (!e)
- goto end;
-
- while (1)
- {
- GFileInfo *info = g_file_enumerator_next_file (e, cancellable, err);
- if (!info)
- break;
-
- src_child = g_file_get_child (src, g_file_info_get_name (info));
- dest_child = g_file_get_child (dest, g_file_info_get_name (info));
- gboolean isdir = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
- g_object_unref (info);
-
- if (isdir)
- {
- if (!do_copy_r (src_child, dest_child, flags, cancellable, err))
- goto end;
- }
- else if (!g_file_copy (src_child, dest_child, flags, cancellable, NULL, NULL, err))
- goto end;
-
- g_clear_object (&src_child);
- g_clear_object (&dest_child);
- }
-
- success = TRUE;
-
-end:
- g_clear_object (&e);
- g_clear_object (&src_child);
- g_clear_object (&dest_child);
-
- return success;
-}
-
-static gint
-do_movecopy_file (SoupMessage *msg, GFile *file,
- GFile *dest, const gchar *dest_path,
- GCancellable *cancellable, GError **err)
-{
- GError *error = NULL;
- gboolean overwrite;
- DepthType depth;
- gint status = SOUP_STATUS_PRECONDITION_FAILED;
- gboolean copy = msg->method == SOUP_METHOD_COPY;
- GFileCopyFlags flags = G_FILE_COPY_ALL_METADATA;
- gboolean retry = FALSE;
- gboolean exists;
-
- depth = depth_from_string (soup_message_headers_get_one (msg->request_headers, "Depth"));
- overwrite = !!g_strcmp0 (
- soup_message_headers_get_one (msg->request_headers, "Overwrite"), "F");
- if (overwrite)
- flags |= G_FILE_COPY_OVERWRITE;
- exists = g_file_query_exists (dest, cancellable);
-
-again:
- switch (depth)
- {
- case DEPTH_INFINITY:
- case DEPTH_ZERO: {
- copy
- ? g_file_copy (file, dest, flags, cancellable, NULL, NULL, &error)
- : g_file_move (file, dest, flags, cancellable, NULL, NULL, &error);
-
- if (overwrite && !retry &&
- (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY) ||
- g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_MERGE)) &&
- phodav_delete_file (dest_path, dest, NULL, cancellable) == SOUP_STATUS_NO_CONTENT)
- {
- g_clear_error (&error);
- retry = TRUE;
- goto again;
- }
- else if (!overwrite &&
- g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
- {
- g_clear_error (&error);
- goto end;
- }
- else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE))
- {
- g_clear_error (&error);
- if (copy)
- {
- if (depth == DEPTH_INFINITY)
- do_copy_r (file, dest, flags, cancellable, &error);
- else
- g_file_make_directory_with_parents (dest, cancellable, &error);
- }
- }
- else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
- {
- status = SOUP_STATUS_CONFLICT;
- g_clear_error (&error);
- goto end;
- }
-
- break;
- }
-
- default:
- g_warn_if_reached ();
- }
-
- if (error)
- g_propagate_error (err, error);
- else
- status = exists ? SOUP_STATUS_NO_CONTENT : SOUP_STATUS_CREATED;
-
-end:
- return status;
-}
-
-static gint
-method_movecopy (PathHandler *handler, SoupMessage *msg,
- const char *path, GError **err)
-{
- GFile *file = NULL, *dest_file = NULL;
- PhodavServer *self = handler->self;
- SoupURI *dest_uri = NULL;
- gint status = SOUP_STATUS_NOT_FOUND;
- const gchar *dest;
- gchar *udest;
- GList *submitted = NULL;
-
- dest = soup_message_headers_get_one (msg->request_headers, "Destination");
- if (!dest)
- goto end;
- dest_uri = soup_uri_new (dest);
- dest = soup_uri_get_path (dest_uri);
- if (!dest || !*dest)
- goto end;
-
- status = phodav_check_if (handler, msg, path, &submitted);
- if (status != SOUP_STATUS_OK)
- goto end;
-
- if (server_path_has_other_locks (self, dest, submitted))
- {
- status = SOUP_STATUS_LOCKED;
- goto end;
- }
-
- udest = g_uri_unescape_string (dest + 1, NULL);
- dest_file = g_file_get_child (handler->file, udest);
- g_free (udest);
-
- file = g_file_get_child (handler->file, path + 1);
- status = do_movecopy_file (msg, file, dest_file, dest,
- self->cancellable, err);
-
-end:
- if (dest_uri)
- soup_uri_free (dest_uri);
- g_clear_object (&file);
- g_clear_object (&dest_file);
- g_list_free_full (submitted, (GDestroyNotify) lock_submitted_free);
- return status;
-}
-
static gboolean G_GNUC_PURE
check_lock (const gchar *key, Path *path, gpointer data)
{
@@ -1011,7 +835,7 @@ server_callback (SoupServer *server, SoupMessage *msg,
status = phodav_method_delete (handler, msg, path, &err);
else if (msg->method == SOUP_METHOD_MOVE ||
msg->method == SOUP_METHOD_COPY)
- status = method_movecopy (handler, msg, path, &err);
+ status = phodav_method_movecopy (handler, msg, path, &err);
else if (msg->method == SOUP_METHOD_LOCK)
status = method_lock (handler, msg, path, &err);
else if (msg->method == SOUP_METHOD_UNLOCK)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]