summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/gdaemonfile.c22
-rw-r--r--common/gvfsdaemonprotocol.h1
-rw-r--r--daemon/Makefile.am1
-rw-r--r--daemon/gvfsbackend.c5
-rw-r--r--daemon/gvfsbackend.h15
-rw-r--r--daemon/gvfsbackendsmb.c23
-rw-r--r--daemon/gvfsjobmakedirectory.c134
-rw-r--r--daemon/gvfsjobmakedirectory.h41
8 files changed, 237 insertions, 5 deletions
diff --git a/client/gdaemonfile.c b/client/gdaemonfile.c
index 10d0c84a..ba53290b 100644
--- a/client/gdaemonfile.c
+++ b/client/gdaemonfile.c
@@ -1202,6 +1202,27 @@ g_daemon_file_trash (GFile *file,
return TRUE;
}
+static gboolean
+g_daemon_file_make_directory (GFile *file,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDaemonFile *daemon_file;
+ DBusMessage *reply;
+
+ daemon_file = G_DAEMON_FILE (file);
+
+ reply = do_sync_path_call (file,
+ G_VFS_DBUS_MOUNT_OP_MAKE_DIRECTORY,
+ NULL, cancellable, error,
+ 0);
+ if (reply == NULL)
+ return FALSE;
+
+ dbus_message_unref (reply);
+ return TRUE;
+}
+
static void
g_daemon_file_file_iface_init (GFileIface *iface)
{
@@ -1231,4 +1252,5 @@ g_daemon_file_file_iface_init (GFileIface *iface)
iface->set_display_name = g_daemon_file_set_display_name;
iface->delete_file = g_daemon_file_delete;
iface->trash = g_daemon_file_trash;
+ iface->make_directory = g_daemon_file_make_directory;
}
diff --git a/common/gvfsdaemonprotocol.h b/common/gvfsdaemonprotocol.h
index 5c72b33b..c4a543da 100644
--- a/common/gvfsdaemonprotocol.h
+++ b/common/gvfsdaemonprotocol.h
@@ -30,6 +30,7 @@ G_BEGIN_DECLS
#define G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME "SetDisplayName"
#define G_VFS_DBUS_MOUNT_OP_DELETE "Delete"
#define G_VFS_DBUS_MOUNT_OP_TRASH "Trash"
+#define G_VFS_DBUS_MOUNT_OP_MAKE_DIRECTORY "MakeDirectory"
/* mount daemons that support mounting more mounts implement this,
and set the dbus name in the mountable description file */
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 2165e893..ce905245 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -74,6 +74,7 @@ libdaemon_la_SOURCES = \
gvfsjobsetdisplayname.c gvfsjobsetdisplayname.h \
gvfsjobtrash.c gvfsjobtrash.h \
gvfsjobdelete.c gvfsjobdelete.h \
+ gvfsjobmakedirectory.c gvfsjobmakedirectory.h \
gvfsdaemonprotocol.c \
dbus-gmain.h dbus-gmain.c \
$(NULL)
diff --git a/daemon/gvfsbackend.c b/daemon/gvfsbackend.c
index 1802077d..52a1df14 100644
--- a/daemon/gvfsbackend.c
+++ b/daemon/gvfsbackend.c
@@ -21,6 +21,7 @@
#include <gvfsjobdelete.h>
#include <gvfsjobtrash.h>
#include <gvfsjobmountmountable.h>
+#include <gvfsjobmakedirectory.h>
#include <gdbusutils.h>
enum {
@@ -292,6 +293,10 @@ backend_dbus_handler (DBusConnection *connection,
G_VFS_DBUS_MOUNT_INTERFACE,
G_VFS_DBUS_MOUNT_OP_TRASH))
job = g_vfs_job_trash_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_MAKE_DIRECTORY))
+ job = g_vfs_job_make_directory_new (connection, message, backend);
if (job)
{
diff --git a/daemon/gvfsbackend.h b/daemon/gvfsbackend.h
index bb5ef9c7..225911a3 100644
--- a/daemon/gvfsbackend.h
+++ b/daemon/gvfsbackend.h
@@ -39,6 +39,7 @@ typedef struct _GVfsJobEnumerate GVfsJobEnumerate;
typedef struct _GVfsJobSetDisplayName GVfsJobSetDisplayName;
typedef struct _GVfsJobTrash GVfsJobTrash;
typedef struct _GVfsJobDelete GVfsJobDelete;
+typedef struct _GVfsJobMakeDirectory GVfsJobMakeDirectory;
typedef gpointer GVfsBackendHandle;
@@ -198,17 +199,23 @@ struct _GVfsBackendClass
const char *filename,
const char *display_name);
void (*delete) (GVfsBackend *backend,
- GVfsJobSetDisplayName *job,
+ GVfsJobDelete *job,
const char *filename);
gboolean (*try_delete) (GVfsBackend *backend,
- GVfsJobSetDisplayName *job,
+ GVfsJobDelete *job,
const char *filename);
void (*trash) (GVfsBackend *backend,
- GVfsJobSetDisplayName *job,
+ GVfsJobTrash *job,
const char *filename);
gboolean (*try_trash) (GVfsBackend *backend,
- GVfsJobSetDisplayName *job,
+ GVfsJobTrash *job,
+ const char *filename);
+ void (*make_directory) (GVfsBackend *backend,
+ GVfsJobMakeDirectory *make_directory,
const char *filename);
+ gboolean (*try_make_directory) (GVfsBackend *backend,
+ GVfsJobMakeDirectory *make_directory,
+ const char *filename);
};
GType g_vfs_backend_get_type (void) G_GNUC_CONST;
diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c
index f03d9c52..7cfb6860 100644
--- a/daemon/gvfsbackendsmb.c
+++ b/daemon/gvfsbackendsmb.c
@@ -1360,7 +1360,7 @@ do_set_display_name (GVfsBackend *backend,
static void
do_delete (GVfsBackend *backend,
- GVfsJobSetDisplayName *job,
+ GVfsJobDelete *job,
const char *filename)
{
GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
@@ -1379,6 +1379,26 @@ do_delete (GVfsBackend *backend,
}
static void
+do_make_directory (GVfsBackend *backend,
+ GVfsJobMakeDirectory *job,
+ const char *filename)
+{
+ GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
+ char *uri;
+ int errsv, res;
+
+ uri = create_smb_uri (op_backend->server, op_backend->share, filename);
+ res = op_backend->smb_context->mkdir (op_backend->smb_context, uri, 0666);
+ errsv = errno;
+ g_free (uri);
+
+ if (res != 0)
+ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errsv);
+ else
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
g_vfs_backend_smb_class_init (GVfsBackendSmbClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
@@ -1403,4 +1423,5 @@ g_vfs_backend_smb_class_init (GVfsBackendSmbClass *klass)
backend_class->enumerate = do_enumerate;
backend_class->set_display_name = do_set_display_name;
backend_class->delete = do_delete;
+ backend_class->make_directory = do_make_directory;
}
diff --git a/daemon/gvfsjobmakedirectory.c b/daemon/gvfsjobmakedirectory.c
new file mode 100644
index 00000000..0a4a107e
--- /dev/null
+++ b/daemon/gvfsjobmakedirectory.c
@@ -0,0 +1,134 @@
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobmakedirectory.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+
+G_DEFINE_TYPE (GVfsJobMakeDirectory, g_vfs_job_make_directory, G_VFS_TYPE_JOB_DBUS);
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_make_directory_finalize (GObject *object)
+{
+ GVfsJobMakeDirectory *job;
+
+ job = G_VFS_JOB_MAKE_DIRECTORY (object);
+
+ g_free (job->filename);
+
+ if (G_OBJECT_CLASS (g_vfs_job_make_directory_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_make_directory_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_make_directory_class_init (GVfsJobMakeDirectoryClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
+ GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
+
+ gobject_class->finalize = g_vfs_job_make_directory_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_make_directory_init (GVfsJobMakeDirectory *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_make_directory_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobMakeDirectory *job;
+ DBusMessage *reply;
+ DBusError derror;
+ int path_len;
+ const char *path_data;
+
+ dbus_error_init (&derror);
+ if (!dbus_message_get_args (message, &derror,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &path_data, &path_len,
+ 0))
+ {
+ reply = dbus_message_new_error (message,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_MAKE_DIRECTORY,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->filename = g_strndup (path_data, path_len);
+ job->backend = backend;
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobMakeDirectory *op_job = G_VFS_JOB_MAKE_DIRECTORY (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->delete == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->make_directory (op_job->backend,
+ op_job,
+ op_job->filename);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobMakeDirectory *op_job = G_VFS_JOB_MAKE_DIRECTORY (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_delete == NULL)
+ return FALSE;
+
+ return class->try_make_directory (op_job->backend,
+ op_job,
+ op_job->filename);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ return reply;
+}
diff --git a/daemon/gvfsjobmakedirectory.h b/daemon/gvfsjobmakedirectory.h
new file mode 100644
index 00000000..55915d63
--- /dev/null
+++ b/daemon/gvfsjobmakedirectory.h
@@ -0,0 +1,41 @@
+#ifndef __G_VFS_JOB_MAKE_DIRECTORY_H__
+#define __G_VFS_JOB_MAKE_DIRECTORY_H__
+
+#include <gio/gfileinfo.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_MAKE_DIRECTORY (g_vfs_job_make_directory_get_type ())
+#define G_VFS_JOB_MAKE_DIRECTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_MAKE_DIRECTORY, GVfsJobMakeDirectory))
+#define G_VFS_JOB_MAKE_DIRECTORY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_MAKE_DIRECTORY, GVfsJobMakeDirectoryClass))
+#define G_VFS_IS_JOB_MAKE_DIRECTORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_MAKE_DIRECTORY))
+#define G_VFS_IS_JOB_MAKE_DIRECTORY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_MAKE_DIRECTORY))
+#define G_VFS_JOB_MAKE_DIRECTORY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_MAKE_DIRECTORY, GVfsJobMakeDirectoryClass))
+
+typedef struct _GVfsJobMakeDirectoryClass GVfsJobMakeDirectoryClass;
+
+struct _GVfsJobMakeDirectory
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+ char *filename;
+};
+
+struct _GVfsJobMakeDirectoryClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_make_directory_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_make_directory_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_MAKE_DIRECTORY_H__ */