1550 lines
46 KiB
Diff
1550 lines
46 KiB
Diff
Index: configure.ac
|
|
===================================================================
|
|
--- configure.ac (revision 1810)
|
|
+++ configure.ac (working copy)
|
|
@@ -53,6 +53,10 @@
|
|
AC_SUBST(DBUS_CFLAGS)
|
|
AC_SUBST(DBUS_LIBS)
|
|
|
|
+PKG_CHECK_MODULES(DBUS_GLIB, dbus-glib-1)
|
|
+AC_SUBST(DBUS_GLIB_CFLAGS)
|
|
+AC_SUBST(DBUS_GLIB_LIBS)
|
|
+
|
|
AC_ARG_WITH(dbus_service_dir, [ --with-dbus-service-dir=PATH choose directory for dbus service files, [default=PREFIX/share/dbus-1/services]], with_dbus_service_dir="$withval", with_dbus_service_dir=$datadir/dbus-1/services)
|
|
DBUS_SERVICE_DIR=$with_dbus_service_dir
|
|
AC_SUBST(DBUS_SERVICE_DIR)
|
|
Index: daemon/gvfsbackenddice.c
|
|
===================================================================
|
|
--- daemon/gvfsbackenddice.c (revision 0)
|
|
+++ daemon/gvfsbackenddice.c (revision 0)
|
|
@@ -0,0 +1,1394 @@
|
|
+/* Novell IceDesktop Backend for GVfs
|
|
+ *
|
|
+ * Copyright (C) 2008 Novell, 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 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, write to the
|
|
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
+ * Boston, MA 02111-1307, USA.
|
|
+ *
|
|
+ * Author: Boyd Timothy <btimothy@novell.com>
|
|
+ */
|
|
+
|
|
+
|
|
+#include <config.h>
|
|
+
|
|
+#include <sys/types.h>
|
|
+#include <sys/stat.h>
|
|
+#include <sys/wait.h>
|
|
+#include <errno.h>
|
|
+#include <unistd.h>
|
|
+#include <fcntl.h>
|
|
+#include <string.h>
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+
|
|
+#include <glib/gstdio.h>
|
|
+#include <glib/gi18n.h>
|
|
+#include <glib/gprintf.h>
|
|
+#include <gio/gio.h>
|
|
+#include <gio/gunixmounts.h>
|
|
+#include <glib/gurifuncs.h>
|
|
+
|
|
+#include <dbus/dbus-glib.h>
|
|
+
|
|
+#include <time.h>
|
|
+
|
|
+#include "gvfsbackenddice.h"
|
|
+#include "gvfsmonitor.h"
|
|
+#include "gvfsjobopenforread.h"
|
|
+#include "gvfsjobread.h"
|
|
+#include "gvfsjobseekread.h"
|
|
+#include "gvfsjobopenforwrite.h"
|
|
+#include "gvfsjobwrite.h"
|
|
+#include "gvfsjobclosewrite.h"
|
|
+#include "gvfsjobseekwrite.h"
|
|
+#include "gvfsjobsetdisplayname.h"
|
|
+#include "gvfsjobqueryinfo.h"
|
|
+#include "gvfsjobdelete.h"
|
|
+#include "gvfsjobqueryfsinfo.h"
|
|
+#include "gvfsjobqueryattributes.h"
|
|
+#include "gvfsjobenumerate.h"
|
|
+#include "gvfsjobcreatemonitor.h"
|
|
+#include "gvfsdaemonprotocol.h"
|
|
+#include "gvfsdaemonutils.h"
|
|
+
|
|
+//#define kIceDesktopRootPath "/home/boyd/.deskice"
|
|
+
|
|
+#define G_FILE_ATTRIBUTE_DICE_LOCAL_PATH "dice::local-path"
|
|
+
|
|
+static void lose (const char *fmt, ...) G_GNUC_NORETURN G_GNUC_PRINTF (1, 2);
|
|
+static void lose_gerror (const char *prefix, GError *error) G_GNUC_NORETURN;
|
|
+static GFileInfo *create_file_info_from_dbus_array(GValueArray *array_obj);
|
|
+
|
|
+struct _GVfsBackendDice
|
|
+{
|
|
+ GVfsBackend parent_instance;
|
|
+ DBusGConnection *dbus_connection;
|
|
+ DBusGProxy *ice_daemon;
|
|
+
|
|
+ GMountSpec *mount_spec;
|
|
+ GList *top_files; /* Files in toplevel dir */
|
|
+ guint num_top_files;
|
|
+};
|
|
+
|
|
+struct IceOutputStream
|
|
+{
|
|
+ char *file_path;
|
|
+ GFileOutputStream *stream;
|
|
+};
|
|
+
|
|
+struct IceInputStream
|
|
+{
|
|
+ char *file_path;
|
|
+ GFileInputStream *stream;
|
|
+};
|
|
+
|
|
+G_DEFINE_TYPE (GVfsBackendDice, g_vfs_backend_dice, G_VFS_TYPE_BACKEND)
|
|
+
|
|
+#define DBUS_STRUCT_STRING_STRING_STRING (dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID))
|
|
+
|
|
+static void
|
|
+g_vfs_backend_dice_init (GVfsBackendDice *ice_backend)
|
|
+{
|
|
+ g_print ("(ice) g_vfs_backend_dice_init \n");
|
|
+ GVfsBackendDice *backend = G_VFS_BACKEND_DICE (ice_backend);
|
|
+ backend->dbus_connection = NULL;
|
|
+
|
|
+ DBusGConnection *connection;
|
|
+ GError *error;
|
|
+ DBusGProxy *ice_daemon_proxy;
|
|
+
|
|
+ //
|
|
+ // Attempt to connect to the DICE Daemon. If it's not
|
|
+ // running, kick it in the pants so it will start up.
|
|
+
|
|
+ g_printf(" (ice) connecting to the ICE Daemon via DBus...\n");
|
|
+
|
|
+ error = NULL;
|
|
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
|
|
+ if (connection == NULL)
|
|
+ {
|
|
+ g_printerr ("Failed to open connection to bus: %s\n",
|
|
+ error->message);
|
|
+ g_error_free (error);
|
|
+ exit (1);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_printf(" (ice) got a connection to the session bus\n");
|
|
+ }
|
|
+
|
|
+ backend->dbus_connection = connection;
|
|
+
|
|
+ // This call will not trigger activation
|
|
+ ice_daemon_proxy = dbus_g_proxy_new_for_name (backend->dbus_connection,
|
|
+ "Novell.ICEDesktop.Daemon",
|
|
+ "/Novell/ICEDesktop/Daemon",
|
|
+ "Novell.ICEDesktop.Daemon");
|
|
+
|
|
+ gboolean ping_successful;
|
|
+ error = NULL;
|
|
+ // This method should trigger activation
|
|
+ if (!dbus_g_proxy_call (ice_daemon_proxy, "Ping", &error,
|
|
+ G_TYPE_INVALID, // Input params
|
|
+ G_TYPE_BOOLEAN, &ping_successful, // Output params
|
|
+ G_TYPE_INVALID))
|
|
+ {
|
|
+// lose_gerror ("Could not ping the ICE Daemon, but it should start up soon!", error);
|
|
+ g_printf("Could not ping the DICE Daemon, but it should start up soon!\n");
|
|
+ g_error_free (error);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_printf(" (ice) connected to the ICE Daemon.\n");
|
|
+ }
|
|
+
|
|
+ backend->ice_daemon = ice_daemon_proxy;
|
|
+}
|
|
+
|
|
+static void
|
|
+g_vfs_backend_dice_finalize (GObject *object)
|
|
+{
|
|
+ GVfsBackendDice *backend;
|
|
+
|
|
+ backend = G_VFS_BACKEND_DICE (object);
|
|
+
|
|
+ g_mount_spec_unref (backend->mount_spec);
|
|
+
|
|
+ if (G_OBJECT_CLASS (g_vfs_backend_dice_parent_class)->finalize)
|
|
+ (*G_OBJECT_CLASS (g_vfs_backend_dice_parent_class)->finalize) (object);
|
|
+}
|
|
+
|
|
+/*********************
|
|
+ * Utility Functions *
|
|
+ *********************/
|
|
+
|
|
+
|
|
+static void
|
|
+lose (const char *str, ...)
|
|
+{
|
|
+ va_list args;
|
|
+
|
|
+ va_start (args, str);
|
|
+
|
|
+ vfprintf (stderr, str, args);
|
|
+ fputc ('\n', stderr);
|
|
+
|
|
+ va_end (args);
|
|
+
|
|
+// exit (1);
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+lose_gerror (const char *prefix, GError *error)
|
|
+{
|
|
+ lose ("%s: %s", prefix, error->message);
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ * Caller must free using g_free () if not NULL return.
|
|
+ */
|
|
+/*
|
|
+static char *
|
|
+get_last_path_component (const char *path)
|
|
+{
|
|
+ if (path == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ g_printf (" (ice) get_last_path_component (%s)\n", path);
|
|
+ char *parsable_path = g_strdup (path);
|
|
+ char *path_component = NULL;
|
|
+ char *last_component = strtok (parsable_path, "/");
|
|
+ if (last_component != NULL)
|
|
+ {
|
|
+ while ((path_component = strtok (NULL, "/")) != NULL)
|
|
+ {
|
|
+ // Intentionally blank. Tokenize until we've reached
|
|
+ // the last token.
|
|
+ last_component = path_component;
|
|
+ }
|
|
+
|
|
+ // Make a copy of the last component
|
|
+ last_component = g_strdup (last_component);
|
|
+ }
|
|
+
|
|
+ g_free (parsable_path);
|
|
+
|
|
+ g_printf(" (ice) get_last_path_component () returning -> '%s'\n", last_component == NULL ? "(null)" : last_component);
|
|
+
|
|
+ return last_component;
|
|
+}
|
|
+*/
|
|
+
|
|
+static GFileInfo *
|
|
+create_file_info_from_dbus_array(GValueArray *array_obj)
|
|
+{
|
|
+ g_printf (" *** create_file_info_from_dbus_array () ***\n");
|
|
+ GFileInfo *info;
|
|
+
|
|
+ if (array_obj == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ info = g_file_info_new ();
|
|
+
|
|
+ GValue *file_id = g_value_array_get_nth (array_obj, 0);
|
|
+ GValue *file_display_name = g_value_array_get_nth (array_obj, 1);
|
|
+ GValue *file_path = g_value_array_get_nth (array_obj, 2);
|
|
+ GValue *file_local_path = g_value_array_get_nth (array_obj, 3);
|
|
+ GValue *file_type = g_value_array_get_nth (array_obj, 4);
|
|
+ GValue *mime_type = g_value_array_get_nth (array_obj, 5);
|
|
+ GValue *file_access_mask = g_value_array_get_nth (array_obj, 6);
|
|
+ GValue *creation_time = g_value_array_get_nth (array_obj, 7);
|
|
+ GValue *last_access_time = g_value_array_get_nth (array_obj, 8);
|
|
+ GValue *last_modified_time = g_value_array_get_nth (array_obj, 9);
|
|
+ GValue *size = g_value_array_get_nth (array_obj, 10);
|
|
+ GValue *hidden = g_value_array_get_nth (array_obj, 11);
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+ g_printf (" *** read a file info ***\n");
|
|
+ g_printf ("\t ID: %s\n", g_value_get_string (file_id));
|
|
+ g_printf ("\t Display Name: %s\n", g_value_get_string (file_display_name));
|
|
+ g_printf ("\t Path: %s\n", g_value_get_string (file_path));
|
|
+ g_printf ("\t Local Path: %s\n", g_value_get_string (file_local_path));
|
|
+ struct tm *tmp;
|
|
+ gint64 creationDateInSecondsFromEpoch = g_value_get_int64 (creation_time);
|
|
+ g_printf("timestamp: %lld\n", creationDateInSecondsFromEpoch);
|
|
+ tmp = localtime((time_t *)&creationDateInSecondsFromEpoch);
|
|
+ char timestr[200];
|
|
+
|
|
+ if (strftime(timestr, sizeof (timestr), "%F %T", tmp) != 0)
|
|
+ {
|
|
+ g_printf ("\tCreation Time: %s\n", timestr);
|
|
+ }
|
|
+ g_printf ("\t Mime Type: %s\n", g_value_get_string (mime_type));
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+ g_file_info_set_name (info, g_value_get_string (file_path));
|
|
+ g_file_info_set_display_name (info, g_value_get_string (file_display_name));
|
|
+ switch (g_value_get_int (file_type))
|
|
+ {
|
|
+ case 2:
|
|
+ case 3:
|
|
+ g_printf ("\t Type: Directory\n");
|
|
+ gvfs_file_info_populate_content_types (info, g_value_get_string (file_path), G_FILE_TYPE_DIRECTORY);
|
|
+ break;
|
|
+ case 4:
|
|
+ g_printf ("\t Type: Regular\n");
|
|
+ gvfs_file_info_populate_content_types (info, g_value_get_string (file_path), G_FILE_TYPE_REGULAR);
|
|
+
|
|
+ // Store the local path in the file info
|
|
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_DICE_LOCAL_PATH, g_value_get_string (file_local_path));
|
|
+ break;
|
|
+ default:
|
|
+ g_printf ("\t Type: Unknown\n");
|
|
+ gvfs_file_info_populate_content_types (info, g_value_get_string (file_path), G_FILE_TYPE_UNKNOWN);
|
|
+ break;
|
|
+ }
|
|
+ g_file_info_set_content_type (info, g_value_get_string (mime_type));
|
|
+
|
|
+ // File Access
|
|
+ uint access_mask = g_value_get_uint (file_access_mask);
|
|
+ if (access_mask & 1) // Read
|
|
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE);
|
|
+ if (access_mask & 2) // Write
|
|
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, TRUE);
|
|
+ if (access_mask & 4) // Execute
|
|
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE, TRUE);
|
|
+ if (access_mask & 8) // CanDelete
|
|
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, TRUE);
|
|
+ if (access_mask & 16) // CanTrash
|
|
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, TRUE);
|
|
+ if (access_mask && 32) // CanRename
|
|
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, TRUE);
|
|
+
|
|
+ g_file_info_set_attribute_int64 (info, G_FILE_ATTRIBUTE_TIME_CREATED, g_value_get_int64 (creation_time));
|
|
+ g_file_info_set_attribute_int64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS, g_value_get_int64 (last_access_time));
|
|
+ g_file_info_set_attribute_int64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED, g_value_get_int64 (last_modified_time));
|
|
+
|
|
+ g_file_info_set_size (info, g_value_get_uint64 (size));
|
|
+
|
|
+ g_file_info_set_is_hidden (info, g_value_get_boolean (hidden));
|
|
+
|
|
+ return info;
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ * ???
|
|
+ *
|
|
+ * Note: The returned object should be freed by the caller.
|
|
+ */
|
|
+static GFileInfo*
|
|
+get_g_file_info_from_deskice (GVfsBackendDice *ice_backend,
|
|
+ const char *filename,// GFile *file,
|
|
+ const char *attributes, GFileQueryInfoFlags flags,
|
|
+ GVfsJob *job)
|
|
+{
|
|
+ g_printf("*** get_g_file_info_from_deskice ()\n");
|
|
+ g_printf("\tfilename: %s\n", filename);
|
|
+ GFileInfo *info = NULL;
|
|
+
|
|
+ if (strlen (filename) == 1 && filename [0] == '/')
|
|
+ {
|
|
+ // This is the top-level item that will appear in
|
|
+ // Nautilus' sidebar as one of the "Places".
|
|
+ info = g_file_info_new ();
|
|
+ g_file_info_set_name (info, "/");
|
|
+ g_file_info_set_display_name (info, _("Workspaces"));
|
|
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
|
|
+ return info;
|
|
+ }
|
|
+
|
|
+ // If we make it this far, we're dealing with either a
|
|
+ // workspace, a directory, or a file. Communicate via DBus
|
|
+ // to the DICE Daemon to determine the information for the
|
|
+ // given path.
|
|
+ GError *error;
|
|
+ if (ice_backend->ice_daemon == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ GValueArray *dbus_file_info;
|
|
+
|
|
+ error = NULL;
|
|
+ if (!dbus_g_proxy_call (ice_backend->ice_daemon,
|
|
+ "GetFileByPath",
|
|
+ &error,
|
|
+ // Input Params
|
|
+ G_TYPE_STRING, filename, G_TYPE_INVALID,
|
|
+ // Output Params (struct of items)
|
|
+ dbus_g_type_get_struct (
|
|
+ "GValueArray",
|
|
+ G_TYPE_STRING, // Id
|
|
+ G_TYPE_STRING, // Display Name
|
|
+ G_TYPE_STRING, // Path
|
|
+ G_TYPE_STRING, // Local Path
|
|
+ G_TYPE_INT, // File Type
|
|
+ G_TYPE_STRING, // Mime Type
|
|
+ G_TYPE_UINT, // Access Mask
|
|
+ G_TYPE_INT64, // Creation Time
|
|
+ G_TYPE_INT64, // Last Access Time
|
|
+ G_TYPE_INT64, // Last Modified Time
|
|
+ G_TYPE_UINT64, // Size
|
|
+ G_TYPE_BOOLEAN, // Hidden
|
|
+ G_TYPE_INVALID),
|
|
+ &dbus_file_info,
|
|
+ G_TYPE_INVALID))
|
|
+ {
|
|
+ if (strstr(error->message, "Exception") != NULL)
|
|
+ {
|
|
+ g_printf ("No files for path: %s\n", error->message);
|
|
+ dbus_file_info = NULL;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+// lose_gerror ("Could not call DICE Daemon's GetFileByPath ()", error);
|
|
+// exit(-2);
|
|
+ g_printf("Could not call the DICE Daemon's GetFileByPath ()\n");
|
|
+ g_error_free (error);
|
|
+ return NULL;
|
|
+ }
|
|
+ g_error_free (error);
|
|
+ error = NULL;
|
|
+ }
|
|
+
|
|
+ if (dbus_file_info != NULL)
|
|
+ {
|
|
+ info = create_file_info_from_dbus_array(dbus_file_info);
|
|
+
|
|
+ g_value_array_free (dbus_file_info);
|
|
+ }
|
|
+
|
|
+ g_printf(" returning from get_g_file_info_from_deskice\n");
|
|
+
|
|
+ return info;
|
|
+}
|
|
+
|
|
+// Caller must free the returned GFileInfo on success
|
|
+static GFileInfo*
|
|
+create_g_file_info_in_deskice(GVfsBackendDice *ice_backend,
|
|
+ const char *filename)
|
|
+{
|
|
+ g_printf("*** create_g_file_info_in_deskice ()\n");
|
|
+ g_printf("\tfilename: %s\n", filename);
|
|
+ GFileInfo *info = NULL;
|
|
+
|
|
+ GError *error;
|
|
+ if (ice_backend->ice_daemon == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ GValueArray *dbus_file_info = NULL;
|
|
+
|
|
+ error = NULL;
|
|
+ if (!dbus_g_proxy_call (ice_backend->ice_daemon,
|
|
+ "CreateLocalFile",
|
|
+ &error,
|
|
+ // Input Params
|
|
+ G_TYPE_STRING, filename, G_TYPE_INVALID,
|
|
+ // Output Params (struct of items)
|
|
+ dbus_g_type_get_struct (
|
|
+ "GValueArray",
|
|
+ G_TYPE_STRING, // Id
|
|
+ G_TYPE_STRING, // Display Name
|
|
+ G_TYPE_STRING, // Path
|
|
+ G_TYPE_STRING, // Local Path
|
|
+ G_TYPE_INT, // File Type
|
|
+ G_TYPE_STRING, // Mime Type
|
|
+ G_TYPE_UINT, // Access Mask
|
|
+ G_TYPE_INT64, // Creation Time
|
|
+ G_TYPE_INT64, // Last Access Time
|
|
+ G_TYPE_INT64, // Last Modified Time
|
|
+ G_TYPE_UINT64, // Size
|
|
+ G_TYPE_BOOLEAN, // Hidden
|
|
+ G_TYPE_INVALID),
|
|
+ &dbus_file_info,
|
|
+ G_TYPE_INVALID))
|
|
+ {
|
|
+ if (strstr(error->message, "Exception") != NULL)
|
|
+ {
|
|
+ g_printf ("Could not create file '%s': %s\n", filename, error->message);
|
|
+ dbus_file_info = NULL;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+// lose_gerror ("Could not call DICE Daemon's CreateLocalFile ()", error);
|
|
+// exit(-2);
|
|
+ g_printf("Could not call the DICE Daemon's CreateLocalFile ()\n");
|
|
+ g_error_free (error);
|
|
+ return NULL;
|
|
+ }
|
|
+ g_error_free (error);
|
|
+ error = NULL;
|
|
+ }
|
|
+
|
|
+ if (dbus_file_info != NULL)
|
|
+ {
|
|
+ info = create_file_info_from_dbus_array(dbus_file_info);
|
|
+
|
|
+ g_value_array_free (dbus_file_info);
|
|
+ }
|
|
+
|
|
+ g_printf(" returning from create_g_file_info_in_deskice ()\n");
|
|
+
|
|
+ return info;
|
|
+}
|
|
+
|
|
+
|
|
+// Returns TRUE if the file was updated successfully.
|
|
+// If FALSE, the caller must free the GError that may be set.
|
|
+static gboolean
|
|
+delete_local_file_from_deskice(GVfsBackendDice *ice_backend,
|
|
+ const char *filename,
|
|
+ GError **error)
|
|
+{
|
|
+ GError *anError;
|
|
+ g_printf("*** delete_local_file_from_deskice ()\n");
|
|
+ g_printf("\tfilename: %s\n", filename);
|
|
+
|
|
+ if (ice_backend->ice_daemon == NULL)
|
|
+ return FALSE; // TODO: Fix this with a real error
|
|
+
|
|
+ if (error != NULL)
|
|
+ *error = NULL;
|
|
+ anError = NULL;
|
|
+ if (!dbus_g_proxy_call (ice_backend->ice_daemon,
|
|
+ "DeleteLocalFile",
|
|
+ &anError,
|
|
+ // Input Params
|
|
+ G_TYPE_STRING, filename, G_TYPE_INVALID,
|
|
+ G_TYPE_INVALID)) // Output Params (none)
|
|
+ {
|
|
+ if (strstr(anError->message, "Exception") != NULL)
|
|
+ {
|
|
+ g_printf ("Could not delete file '%s': %s\n", filename, anError->message);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+// lose_gerror ("Could not call DICE Daemon's DeleteLocalFile ()", anError);
|
|
+// exit(-2);
|
|
+ g_printf("Could not call the DICE Daemon's DeleteLocalFile ()\n");
|
|
+ g_error_free (anError);
|
|
+ return FALSE;
|
|
+ }
|
|
+ if (error != NULL)
|
|
+ *error = anError;
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ g_printf(" returning from delete_local_file_from_deskice ()\n");
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+
|
|
+// This should be called any time our provider modifies a
|
|
+// file. Basically any time we close a file handle. Returns
|
|
+// TRUE if the file was updated successfully. If FALSE, the
|
|
+// caller must free the GError that may be set.
|
|
+static gboolean
|
|
+update_local_file_in_deskice(GVfsBackendDice *ice_backend,
|
|
+ const char *filename,
|
|
+ GError **error)
|
|
+{
|
|
+ GError *anError;
|
|
+ g_printf("*** update_local_file_in_deskice ()\n");
|
|
+ g_printf("\tfilename: %s\n", filename);
|
|
+
|
|
+ if (ice_backend->ice_daemon == NULL)
|
|
+ return FALSE; // TODO: Fix this with a real error
|
|
+
|
|
+ if (error != NULL)
|
|
+ *error = NULL;
|
|
+ anError = NULL;
|
|
+ if (!dbus_g_proxy_call (ice_backend->ice_daemon,
|
|
+ "UpdateLocalFile",
|
|
+ &anError,
|
|
+ // Input Params
|
|
+ G_TYPE_STRING, filename, G_TYPE_INVALID,
|
|
+ G_TYPE_INVALID)) // Output Params (none)
|
|
+ {
|
|
+ if (strstr(anError->message, "Exception") != NULL)
|
|
+ {
|
|
+ g_printf ("Could not update file '%s': %s\n", filename, anError->message);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+// lose_gerror ("Could not call DICE Daemon's UpdateLocalFile ()", anError);
|
|
+// exit(-2);
|
|
+ g_printf("Could not call the DICE Daemon's UpdateLocalFile ()\n");
|
|
+ g_error_free (anError);
|
|
+ return FALSE;
|
|
+ }
|
|
+ if (error != NULL)
|
|
+ *error = anError;
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ g_printf(" returning from update_local_file_in_deskice ()\n");
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+
|
|
+// Caller must free the returned GFileInfo!
|
|
+static GFileInfo *
|
|
+get_g_filesystem_info_from_deskice (
|
|
+ GFile *file,
|
|
+ const char *attributes,
|
|
+ GCancellable *cancellable,
|
|
+ GError **error)
|
|
+{
|
|
+ GFileInfo *info = g_file_info_new ();
|
|
+
|
|
+ // TODO: Implement get_g_filesystem_info_from_deskice
|
|
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, FALSE);
|
|
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE, 262144000);
|
|
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE, 524288000);
|
|
+
|
|
+ return info;
|
|
+}
|
|
+
|
|
+
|
|
+/* returned object should be freed in user's function */
|
|
+static GFile*
|
|
+get_g_file_from_local (const char *filename, GVfsJob *job)
|
|
+{
|
|
+ GVfs *local_vfs;
|
|
+ GFile *file = NULL;
|
|
+
|
|
+ local_vfs = g_vfs_get_local ();
|
|
+ if (! local_vfs) {
|
|
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
+ "Cannot get local vfs");
|
|
+ g_print (" (EE) get_g_file_from_local (filename = '%s'): local_vfs == NULL \n", filename);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ file = g_vfs_get_file_for_path (local_vfs, filename);
|
|
+ if (! file) {
|
|
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
+ "Cannot get file from local vfs");
|
|
+ g_print (" (EE) get_g_file_from_local (filename = '%s'): file == NULL \n", filename);
|
|
+ return NULL;
|
|
+ }
|
|
+ return file;
|
|
+}
|
|
+
|
|
+
|
|
+/************
|
|
+ * Mounting *
|
|
+ ************/
|
|
+
|
|
+static void
|
|
+do_mount (GVfsBackend *backend,
|
|
+ GVfsJobMount *job,
|
|
+ GMountSpec *mount_spec,
|
|
+ GMountSource *mount_source,
|
|
+ gboolean is_automount)
|
|
+{
|
|
+ GVfsBackendDice *ice_backend = G_VFS_BACKEND_DICE (backend);
|
|
+
|
|
+ g_print ("(ice) do_mount \n");
|
|
+
|
|
+ g_vfs_backend_set_display_name (backend, _("Workspaces"));
|
|
+
|
|
+ ice_backend->mount_spec = g_mount_spec_new ("dice");
|
|
+ g_vfs_backend_set_mount_spec (backend, ice_backend->mount_spec);
|
|
+
|
|
+ g_vfs_backend_set_icon_name (backend, "network-server");
|
|
+
|
|
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
+}
|
|
+
|
|
+static void
|
|
+do_unmount (GVfsBackend *backend, GVfsJobUnmount *job)
|
|
+{
|
|
+ GVfsBackendDice *ice_backend;
|
|
+
|
|
+ g_print ("(ice) do_umount \n");
|
|
+
|
|
+ ice_backend = G_VFS_BACKEND_DICE (backend);
|
|
+ g_mount_spec_unref (ice_backend->mount_spec);
|
|
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
+}
|
|
+
|
|
+
|
|
+/*******************
|
|
+ * Query Functions *
|
|
+ *******************/
|
|
+
|
|
+
|
|
+static void
|
|
+do_query_info (GVfsBackend *backend,
|
|
+ GVfsJobQueryInfo *job,
|
|
+ const char *filename,
|
|
+ GFileQueryInfoFlags flags,
|
|
+ GFileInfo *info,
|
|
+ GFileAttributeMatcher *matcher)
|
|
+{
|
|
+ GVfsBackendDice *ice_backend = G_VFS_BACKEND_DICE (backend);
|
|
+ GFileInfo *info2;
|
|
+
|
|
+ g_print ("(ice) do_query_info (filename = %s)\n", filename);
|
|
+
|
|
+ info2 = get_g_file_info_from_deskice (ice_backend, filename, /*file,*/ "*", flags, G_VFS_JOB (job));
|
|
+
|
|
+ if (info2) {
|
|
+ g_file_info_copy_into (info2, info);
|
|
+ g_object_unref (info2);
|
|
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
+ g_print ("(ice) do_query_info success. \n");
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_print ("(ice) do_query_info failed. \n");
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+do_query_fs_info (GVfsBackend *backend,
|
|
+ GVfsJobQueryFsInfo *job,
|
|
+ const char *filename,
|
|
+ GFileInfo *info,
|
|
+ GFileAttributeMatcher *attribute_matcher)
|
|
+{
|
|
+ GFile *file;
|
|
+ GFileInfo *info2;
|
|
+ GError *error;
|
|
+
|
|
+ g_print ("(ice) do_query_fs_info (filename = %s) \n", filename);
|
|
+ file = g_file_new_for_path (filename);
|
|
+ if (file)
|
|
+ {
|
|
+ error = NULL;
|
|
+ info2 = get_g_filesystem_info_from_deskice (file, "fs:*", G_VFS_JOB (job)->cancellable, &error);
|
|
+ if ((error) || (! info2) )
|
|
+ {
|
|
+ g_print (" (ice) do_query_fs_info (filename = '%s'): g_file_query_filesystem_info failed: %s \n", filename, error->message);
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_error_free (error);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_file_info_copy_into (info2, info);
|
|
+ g_object_unref (info2);
|
|
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
+ g_print ("(ice) do_query_fs_info success. \n");
|
|
+ }
|
|
+
|
|
+ g_object_unref (file);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_print ("(ice) do_query_fs_info failed. \n");
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+do_enumerate (GVfsBackend *backend,
|
|
+ GVfsJobEnumerate *job,
|
|
+ const char *filename,
|
|
+ GFileAttributeMatcher *attribute_matcher,
|
|
+ GFileQueryInfoFlags flags)
|
|
+{
|
|
+ GVfsBackendDice *ice_backend = G_VFS_BACKEND_DICE (backend);
|
|
+ GPtrArray *files = NULL;
|
|
+ GFileInfo *info;
|
|
+ GError *error;
|
|
+
|
|
+ g_print ("(ice) do_enumerate (filename = %s) \n", filename);
|
|
+
|
|
+ if (strlen (filename) == 1 && filename [0] == '/')
|
|
+ {
|
|
+ g_print(" ---> calling EnumerateWorkspaces ()\n");
|
|
+ // Read in all the workspaces
|
|
+ error = NULL;
|
|
+ if (!dbus_g_proxy_call (ice_backend->ice_daemon, "EnumerateWorkspaces", &error,
|
|
+ // Input params (none)
|
|
+ G_TYPE_INVALID,
|
|
+ // Output params
|
|
+ dbus_g_type_get_collection ("GPtrArray", dbus_g_type_get_struct ("GValueArray",
|
|
+ G_TYPE_STRING, // Id
|
|
+ G_TYPE_STRING, // Display Name
|
|
+ G_TYPE_STRING, // Path
|
|
+ G_TYPE_STRING, // Local Path
|
|
+ G_TYPE_INT, // File Type
|
|
+ G_TYPE_STRING, // Mime Type
|
|
+ G_TYPE_UINT, // Access Mask
|
|
+ G_TYPE_INT64, // Creation Time
|
|
+ G_TYPE_INT64, // Last Access Time
|
|
+ G_TYPE_INT64, // Last Modified Time
|
|
+ G_TYPE_UINT64, // Size
|
|
+ G_TYPE_BOOLEAN, // Hidden
|
|
+ G_TYPE_INVALID)),
|
|
+ &files,
|
|
+ G_TYPE_INVALID))
|
|
+ {
|
|
+ if (strstr(error->message, "Exception") != NULL)
|
|
+ {
|
|
+ g_printf ("No files for path: %s\n", error->message);
|
|
+ files = NULL;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+// lose_gerror ("Could not enumerate the workspaces", error);
|
|
+// exit(-2);
|
|
+ g_printf("Could not enumerate the workspaces\n");
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_error_free (error);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ g_error_free (error);
|
|
+ error = NULL;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_print(" ---> calling EnumerateFiles ()\n");
|
|
+ // Read in the files contained in a specific directory
|
|
+ error = NULL;
|
|
+ if (!dbus_g_proxy_call (ice_backend->ice_daemon, "EnumerateFiles", &error,
|
|
+ // Input params
|
|
+ G_TYPE_STRING, filename,
|
|
+ G_TYPE_INVALID,
|
|
+ // Output params
|
|
+ dbus_g_type_get_collection ("GPtrArray", dbus_g_type_get_struct ("GValueArray",
|
|
+ G_TYPE_STRING, // Id
|
|
+ G_TYPE_STRING, // Display Name
|
|
+ G_TYPE_STRING, // Path
|
|
+ G_TYPE_STRING, // Local Path
|
|
+ G_TYPE_INT, // File Type
|
|
+ G_TYPE_STRING, // Mime Type
|
|
+ G_TYPE_UINT, // Access Mask
|
|
+ G_TYPE_INT64, // Creation Time
|
|
+ G_TYPE_INT64, // Last Access Time
|
|
+ G_TYPE_INT64, // Last Modified Time
|
|
+ G_TYPE_UINT64, // Size
|
|
+ G_TYPE_BOOLEAN, // Hidden
|
|
+ G_TYPE_INVALID)),
|
|
+ &files,
|
|
+ G_TYPE_INVALID))
|
|
+ {
|
|
+ g_print(" <--- calling EnumerateFiles () in failure case\n");
|
|
+ if (strstr(error->message, "Exception") != NULL)
|
|
+ {
|
|
+ g_printf ("No files for path: %s\n", error->message);
|
|
+ files = NULL;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+// lose_gerror ("Could not enumerate the directory", error);
|
|
+// exit(-2);
|
|
+ g_printf("Could not enumerate the directory\n");
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_error_free (error);
|
|
+ return;
|
|
+ }
|
|
+ g_error_free (error);
|
|
+ error = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ g_print(" ---- EnumerateFiles () out of dbus call\n");
|
|
+ // Enumerate the files and create GFileInfos to add and publish
|
|
+ // over DBus.
|
|
+
|
|
+ // You have to say succeeded before doing anything else
|
|
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
+
|
|
+ if (files != NULL)
|
|
+ {
|
|
+ int i;
|
|
+ for (i = 0; i < files->len; i++)
|
|
+ {
|
|
+ GValueArray *dbus_array_obj = g_ptr_array_index (files, i);
|
|
+ if (dbus_array_obj != NULL)
|
|
+ {
|
|
+ info = create_file_info_from_dbus_array(dbus_array_obj);
|
|
+ g_vfs_job_enumerate_add_info (job, info);
|
|
+ g_object_unref (info);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ g_ptr_array_free (files, TRUE);
|
|
+ }
|
|
+
|
|
+ g_vfs_job_enumerate_done (job);
|
|
+ g_print ("(ice) do_enumerate done. \n");
|
|
+}
|
|
+
|
|
+
|
|
+/******************
|
|
+ * Read Functions *
|
|
+ ******************/
|
|
+
|
|
+
|
|
+static void
|
|
+do_open_for_read (GVfsBackend *backend,
|
|
+ GVfsJobOpenForRead *job,
|
|
+ const char *filename)
|
|
+{
|
|
+ GVfsBackendDice *ice_backend = G_VFS_BACKEND_DICE (backend);
|
|
+ struct IceInputStream *ice_stream;
|
|
+ GFileInputStream *stream;
|
|
+ GError *error;
|
|
+ GFile *file;
|
|
+ GFileInfo *info;
|
|
+
|
|
+ g_print ("(II) do_open_for_read (filename = '%s') \n", filename);
|
|
+
|
|
+ info = get_g_file_info_from_deskice (ice_backend,
|
|
+ filename,
|
|
+ "*",
|
|
+ G_FILE_QUERY_INFO_NONE,
|
|
+ G_VFS_JOB (job));
|
|
+
|
|
+ g_assert (info != NULL);
|
|
+
|
|
+ // Get the local path of the file
|
|
+ const char *local_path = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_DICE_LOCAL_PATH);
|
|
+ g_assert (local_path != NULL);
|
|
+
|
|
+ file = get_g_file_from_local (local_path, G_VFS_JOB (job));
|
|
+ g_object_unref (info);
|
|
+
|
|
+ if (file)
|
|
+ {
|
|
+ error = NULL;
|
|
+ stream = g_file_read (file, G_VFS_JOB (job)->cancellable, &error);
|
|
+ if (stream)
|
|
+ {
|
|
+ ice_stream = malloc (sizeof (struct IceInputStream));
|
|
+ ice_stream->stream = stream;
|
|
+ ice_stream->file_path = strdup (filename);
|
|
+ g_vfs_job_open_for_read_set_can_seek (job, g_seekable_can_seek (G_SEEKABLE (stream)));
|
|
+ g_vfs_job_open_for_read_set_handle (job, ice_stream);
|
|
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
+ g_print ("(II) do_open_for_read success. \n");
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_print (" (EE) do_open_for_read: stream == NULL, error: %s \n", error->message);
|
|
+ g_error_free (error);
|
|
+ }
|
|
+ g_object_unref (file);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_print (" (EE) do_open_for_read: file == NULL \n");
|
|
+ g_vfs_job_failed (G_VFS_JOB (job),
|
|
+ G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
+ _("Unable to create GFile, file == NULL"));
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+do_read (GVfsBackend *backend,
|
|
+ GVfsJobRead *job,
|
|
+ GVfsBackendHandle _handle,
|
|
+ char *buffer,
|
|
+ gsize bytes_requested)
|
|
+{
|
|
+ GError *error;
|
|
+ struct IceInputStream *ice_stream = (struct IceInputStream *)_handle;
|
|
+// GFileInputStream *stream = _handle;
|
|
+ gssize s;
|
|
+
|
|
+ g_print ("(II) do_read (handle = '%lx', buffer = '%lx', bytes_requested = %ld) \n",
|
|
+ (long int)ice_stream->stream, (long int)buffer, (long int)bytes_requested);
|
|
+
|
|
+ g_assert (ice_stream != NULL);
|
|
+
|
|
+ error = NULL;
|
|
+ s = g_input_stream_read (G_INPUT_STREAM (ice_stream->stream), buffer, bytes_requested,
|
|
+ G_VFS_JOB (job)->cancellable, &error);
|
|
+ if (s >= 0) {
|
|
+ g_vfs_job_read_set_size (job, s);
|
|
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
+ g_print ("(II) do_read success. \n");
|
|
+ } else {
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_print (" (EE) do_read: g_input_stream_read() failed, error: %s \n", error->message);
|
|
+ g_error_free (error);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+do_seek_on_read (GVfsBackend *backend,
|
|
+ GVfsJobSeekRead *job,
|
|
+ GVfsBackendHandle _handle,
|
|
+ goffset offset,
|
|
+ GSeekType type)
|
|
+{
|
|
+ GError *error;
|
|
+ struct IceInputStream *ice_stream = (struct IceInputStream *)_handle;
|
|
+// GFileInputStream *stream = _handle;
|
|
+
|
|
+ g_print ("(II) do_seek_on_read (handle = '%lx', offset = %ld) \n", (long int)ice_stream->stream, (long int)offset);
|
|
+
|
|
+ g_assert (ice_stream != NULL);
|
|
+
|
|
+ error = NULL;
|
|
+ if (g_seekable_seek (G_SEEKABLE (ice_stream->stream), offset, type, G_VFS_JOB (job)->cancellable, &error)) {
|
|
+ g_vfs_job_seek_read_set_offset (job, g_seekable_tell (G_SEEKABLE (ice_stream->stream)));
|
|
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
+ g_print ("(II) do_seek_on_read success. \n");
|
|
+ } else {
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_print (" (EE) do_seek_on_read: g_file_input_stream_seek() failed, error: %s \n", error->message);
|
|
+ g_error_free (error);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+do_close_read (GVfsBackend *backend,
|
|
+ GVfsJobCloseRead *job,
|
|
+ GVfsBackendHandle _handle)
|
|
+{
|
|
+ GError *error;
|
|
+ struct IceInputStream *ice_stream = (struct IceInputStream *)_handle;
|
|
+// GFileInputStream *stream = _handle;
|
|
+
|
|
+ g_print ("(II) try_close_read (handle = '%lx') \n", (long int)ice_stream->stream);
|
|
+
|
|
+ g_assert (ice_stream != NULL);
|
|
+
|
|
+ error = NULL;
|
|
+ if (g_input_stream_close (G_INPUT_STREAM (ice_stream->stream), G_VFS_JOB (job)->cancellable, &error)) {
|
|
+ free (ice_stream->file_path);
|
|
+ g_object_unref (ice_stream->stream);
|
|
+ free (ice_stream);
|
|
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
+ g_print ("(II) try_close_read success. \n");
|
|
+ } else {
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_print (" (EE) try_close_read: g_input_stream_close() failed, error: %s \n", error->message);
|
|
+ g_error_free (error);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+/*******************
|
|
+ * Write Functions *
|
|
+ *******************/
|
|
+
|
|
+
|
|
+static void
|
|
+do_create (GVfsBackend *backend,
|
|
+ GVfsJobOpenForWrite *job,
|
|
+ const char *filename,
|
|
+ GFileCreateFlags flags)
|
|
+{
|
|
+ GVfsBackendDice *ice_backend = G_VFS_BACKEND_DICE (backend);
|
|
+ GError *error;
|
|
+ GFileInfo *info;
|
|
+ GFile *file;
|
|
+ struct IceOutputStream *ice_stream;
|
|
+
|
|
+ info = get_g_file_info_from_deskice (ice_backend,
|
|
+ filename,
|
|
+ "*",
|
|
+ G_FILE_QUERY_INFO_NONE,
|
|
+ G_VFS_JOB (job));
|
|
+
|
|
+// g_file_new_for_path (filename);
|
|
+ if (info)
|
|
+ {
|
|
+ g_object_unref (info);
|
|
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_EXISTS, _("Target file already exists"));
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_error_free (error);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // Actually create the file in deskice
|
|
+ info = create_g_file_info_in_deskice(ice_backend, filename);
|
|
+
|
|
+ if (info == NULL)
|
|
+ {
|
|
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, _("Error creating the file in deskice"));
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_error_free (error);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // Open the real local file file!
|
|
+ const char *local_path = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_DICE_LOCAL_PATH);
|
|
+ g_assert (local_path != NULL);
|
|
+
|
|
+ file = get_g_file_from_local (local_path, G_VFS_JOB (job));
|
|
+ g_object_unref (info);
|
|
+
|
|
+ error = NULL;
|
|
+ GFileOutputStream *stream = g_file_create (file, flags, G_VFS_JOB (job)->cancellable, &error);
|
|
+ if (stream == NULL)
|
|
+ {
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_error_free (error);
|
|
+ return;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ // Wrap the GFileOutputStream into an IceOutputStream so we can
|
|
+ // keep track of the original file path.
|
|
+ ice_stream = malloc (sizeof (struct IceOutputStream));
|
|
+ ice_stream->file_path = strdup (filename);
|
|
+ ice_stream->stream = stream;
|
|
+
|
|
+ g_vfs_job_open_for_write_set_handle (G_VFS_JOB_OPEN_FOR_WRITE (job), ice_stream);
|
|
+ g_vfs_job_open_for_write_set_can_seek (G_VFS_JOB_OPEN_FOR_WRITE (job), g_seekable_can_seek (G_SEEKABLE (stream)));
|
|
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
+ }
|
|
+ g_object_unref (file);
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+do_close_write (GVfsBackend *backend,
|
|
+ GVfsJobCloseWrite *job,
|
|
+ GVfsBackendHandle handle)
|
|
+{
|
|
+ GVfsBackendDice *ice_backend = G_VFS_BACKEND_DICE (backend);
|
|
+ GError *error;
|
|
+ struct IceOutputStream *ice_stream = (struct IceOutputStream *)handle;
|
|
+ //GFileOutputStream *stream = (GFileOutputStream *)handle;
|
|
+
|
|
+ g_print ("(II) do_close_write (handle = '%lx') \n", (long int)handle);
|
|
+
|
|
+ g_assert (ice_stream != NULL);
|
|
+
|
|
+ error = NULL;
|
|
+ if (g_output_stream_close (G_OUTPUT_STREAM(ice_stream->stream), G_VFS_JOB (job)->cancellable, &error))
|
|
+ {
|
|
+ // Notify DICE Daemon that the file has been closed/changed
|
|
+ error = NULL;
|
|
+ if (update_local_file_in_deskice(ice_backend,
|
|
+ ice_stream->file_path,
|
|
+ &error) == FALSE)
|
|
+ {
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_print (" (EE) do_close_write: g_input_stream_close() failed, error: %s \n", error->message);
|
|
+ g_error_free (error);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ g_object_unref (ice_stream->stream);
|
|
+ free (ice_stream->file_path);
|
|
+ free (ice_stream);
|
|
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
+ g_print ("(II) do_close_write success. \n");
|
|
+ } else {
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_print (" (EE) do_close_write: g_input_stream_close() failed, error: %s \n", error->message);
|
|
+ g_error_free (error);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+do_write (GVfsBackend *backend,
|
|
+ GVfsJobWrite *job,
|
|
+ GVfsBackendHandle handle,
|
|
+ char *buffer,
|
|
+ gsize buffer_size)
|
|
+{
|
|
+ GError *error;
|
|
+ struct IceOutputStream *ice_stream = (struct IceOutputStream *)handle;
|
|
+ //GFileOutputStream *stream = (GFileOutputStream *)handle;
|
|
+ gssize s;
|
|
+
|
|
+// g_print ("(II) do_write (handle = '%lx', buffer = '%lx', buffer_size = %ld) \n",
|
|
+// (long int)_handle, (long int)buffer, (long int)buffer_size);
|
|
+
|
|
+ g_assert (ice_stream != NULL);
|
|
+
|
|
+ error = NULL;
|
|
+ s = g_output_stream_write (G_OUTPUT_STREAM (ice_stream->stream), buffer, buffer_size, G_VFS_JOB (job)->cancellable, &error);
|
|
+ if (s >= 0) {
|
|
+ g_vfs_job_write_set_written_size (job, s);
|
|
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
+ g_print ("(II) do_write success. \n");
|
|
+ } else {
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_print (" (EE) do_write: g_output_stream_write() failed, error: %s \n", error->message);
|
|
+ g_error_free (error);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+do_append (GVfsBackend *backend,
|
|
+ GVfsJobOpenForWrite *job,
|
|
+ const char *filename,
|
|
+ GFileCreateFlags flags)
|
|
+{
|
|
+ GVfsBackendDice *ice_backend = G_VFS_BACKEND_DICE (backend);
|
|
+ GError *error;
|
|
+ GFileInfo *info;
|
|
+ GFile *file;
|
|
+ struct IceOutputStream *ice_stream;
|
|
+ //GFileOutputStream *stream;
|
|
+
|
|
+ g_print ("(II) do_append (filename = %s) \n", filename);
|
|
+
|
|
+ info = get_g_file_info_from_deskice (ice_backend,
|
|
+ filename,
|
|
+ "*",
|
|
+ G_FILE_QUERY_INFO_NONE,
|
|
+ G_VFS_JOB (job));
|
|
+
|
|
+ if (info == NULL)
|
|
+ {
|
|
+ // The file must not exist, so just use the create function
|
|
+ do_create (backend, job, filename, flags);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // Get the real local path
|
|
+ const char *local_path = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_DICE_LOCAL_PATH);
|
|
+ g_assert (local_path != NULL);
|
|
+
|
|
+ file = get_g_file_from_local (local_path, G_VFS_JOB (job));
|
|
+ g_object_unref (info);
|
|
+
|
|
+ g_assert (file != NULL);
|
|
+
|
|
+ if (file)
|
|
+ {
|
|
+ error = NULL;
|
|
+ ice_stream = malloc (sizeof (struct IceOutputStream));
|
|
+ ice_stream->stream = g_file_append_to (file, flags, G_VFS_JOB (job)->cancellable, &error);
|
|
+ if (ice_stream->stream)
|
|
+ {
|
|
+ /* Should seek at the end of the file here */
|
|
+ if ((g_seekable_seek (G_SEEKABLE (ice_stream->stream), 0, G_SEEK_END, G_VFS_JOB (job)->cancellable, &error)) && (! error))
|
|
+ {
|
|
+ g_vfs_job_open_for_write_set_initial_offset (job, g_seekable_tell (G_SEEKABLE (ice_stream->stream)));
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_print (" (EE) do_append: error during g_file_output_stream_seek(), error: %s \n", error->message);
|
|
+ }
|
|
+
|
|
+ // Store the filename so we can close properly and notify the DICE Daemon
|
|
+ ice_stream->file_path = strdup (filename);
|
|
+ g_vfs_job_open_for_write_set_can_seek (job, g_seekable_can_seek (G_SEEKABLE (ice_stream->stream)));
|
|
+ g_vfs_job_open_for_write_set_handle (job, ice_stream);
|
|
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
+
|
|
+ g_print ("(II) do_append success. \n");
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ free (ice_stream);
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_print (" (EE) do_append: stream == NULL, error: %s \n", error->message);
|
|
+ g_error_free (error);
|
|
+ }
|
|
+ g_object_unref (file);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_print (" (EE) do_append: file == NULL \n");
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+do_replace (GVfsBackend *backend,
|
|
+ GVfsJobOpenForWrite *job,
|
|
+ const char *filename,
|
|
+ const char *etag,
|
|
+ gboolean make_backup,
|
|
+ GFileCreateFlags flags)
|
|
+{
|
|
+ GVfsBackendDice *ice_backend = G_VFS_BACKEND_DICE (backend);
|
|
+ struct IceOutputStream *ice_stream;
|
|
+ //GFileOutputStream *stream;
|
|
+ GError *error;
|
|
+ GFile *file;
|
|
+ GFileInfo *info;
|
|
+
|
|
+ g_print ("(II) do_replace (filename = '%s', etag = '%s') \n", filename, etag);
|
|
+
|
|
+ info = get_g_file_info_from_deskice (ice_backend,
|
|
+ filename,
|
|
+ "*",
|
|
+ G_FILE_QUERY_INFO_NONE,
|
|
+ G_VFS_JOB (job));
|
|
+
|
|
+ if (info == NULL)
|
|
+ {
|
|
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("Error in do_replace, file not found in deskice"));
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_error_free (error);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // Get the real local path
|
|
+ const char *local_path = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_DICE_LOCAL_PATH);
|
|
+ g_assert (local_path != NULL);
|
|
+
|
|
+ file = get_g_file_from_local (local_path, G_VFS_JOB (job));
|
|
+ g_object_unref (info);
|
|
+
|
|
+ g_assert (file != NULL);
|
|
+
|
|
+ if (file)
|
|
+ {
|
|
+ error = NULL;
|
|
+ ice_stream = malloc (sizeof (struct IceOutputStream));
|
|
+ ice_stream->stream = g_file_replace (file, etag, make_backup, flags, G_VFS_JOB (job)->cancellable, &error);
|
|
+ if (ice_stream->stream)
|
|
+ {
|
|
+ // Save off the filename so we can notify DICE Daemon during a close
|
|
+ ice_stream->file_path = strdup (filename);
|
|
+ g_vfs_job_open_for_write_set_can_seek (job, g_seekable_can_seek (G_SEEKABLE (ice_stream->stream)));
|
|
+ g_vfs_job_open_for_write_set_handle (job, ice_stream);
|
|
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
+ g_print ("(II) do_replace success. \n");
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ free (ice_stream);
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_print (" (EE) do_replace: stream == NULL, error: %s \n", error->message);
|
|
+ g_error_free (error);
|
|
+ }
|
|
+ g_object_unref (file);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_print (" (EE) do_replace: file == NULL \n");
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+do_delete (GVfsBackend *backend,
|
|
+ GVfsJobDelete *job,
|
|
+ const char *filename)
|
|
+{
|
|
+ GVfsBackendDice *ice_backend = G_VFS_BACKEND_DICE (backend);
|
|
+ GError *error;
|
|
+
|
|
+ g_print ("(II) do_delete (filename = %s) \n", filename);
|
|
+
|
|
+ if (filename != NULL)
|
|
+ {
|
|
+ error = NULL;
|
|
+ if (delete_local_file_from_deskice(ice_backend,
|
|
+ filename,
|
|
+ &error))
|
|
+ {
|
|
+ g_vfs_job_succeeded (G_VFS_JOB (job));
|
|
+ g_print ("(II) do_delete success. \n");
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
|
|
+ g_print (" (EE) do_delete: g_file_delete == FALSE, error: %s \n", error->message);
|
|
+ g_error_free (error);
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_print (" (EE) do_delete: filename == NULL \n");
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+g_vfs_backend_dice_class_init (GVfsBackendDiceClass *klass)
|
|
+{
|
|
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
+ GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
|
|
+
|
|
+ gobject_class->finalize = g_vfs_backend_dice_finalize;
|
|
+
|
|
+ backend_class->mount = do_mount;
|
|
+ backend_class->unmount = do_unmount;
|
|
+ backend_class->query_info = do_query_info;
|
|
+ backend_class->query_fs_info = do_query_fs_info;
|
|
+ backend_class->enumerate = do_enumerate;
|
|
+
|
|
+ backend_class->open_for_read = do_open_for_read;
|
|
+ backend_class->read = do_read;
|
|
+ backend_class->seek_on_read = do_seek_on_read;
|
|
+ backend_class->close_read = do_close_read;
|
|
+
|
|
+ backend_class->create = do_create;
|
|
+ backend_class->close_write = do_close_write;
|
|
+ backend_class->write = do_write;
|
|
+ backend_class->append_to = do_append;
|
|
+ backend_class->replace = do_replace;
|
|
+
|
|
+ backend_class->delete = do_delete;
|
|
+
|
|
+// backend_class->move = do_move;
|
|
+// backend_class->make_directory = do_make_directory;
|
|
+
|
|
+// backend_class->create_dir_monitor = do_create_dir_monitor;
|
|
+// backend_class->create_file_monitor = do_create_file_monitor;
|
|
+}
|
|
|
|
Property changes on: daemon/gvfsbackenddice.c
|
|
___________________________________________________________________
|
|
Added: svn:mergeinfo
|
|
|
|
Index: daemon/gvfsbackenddice.h
|
|
===================================================================
|
|
--- daemon/gvfsbackenddice.h (revision 0)
|
|
+++ daemon/gvfsbackenddice.h (revision 0)
|
|
@@ -0,0 +1,50 @@
|
|
+/* Novell IceDesktop Backend for GVfs
|
|
+ *
|
|
+ * Copyright (C) 2008 Novell, 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 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, write to the
|
|
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
+ * Boston, MA 02111-1307, USA.
|
|
+ *
|
|
+ * Author: Boyd Timothy <btimothy@novell.com>
|
|
+ */
|
|
+
|
|
+#ifndef __G_VFS_BACKEND_DICE_H__
|
|
+#define __G_VFS_BACKEND_DICE_H__
|
|
+
|
|
+#include <gvfsbackend.h>
|
|
+#include <gmountspec.h>
|
|
+
|
|
+G_BEGIN_DECLS
|
|
+
|
|
+#define G_VFS_TYPE_BACKEND_DICE (g_vfs_backend_dice_get_type ())
|
|
+#define G_VFS_BACKEND_DICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_DICE, GVfsBackendDice))
|
|
+#define G_VFS_BACKEND_DICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_DICE, GVfsBackendDiceClass))
|
|
+#define G_VFS_IS_BACKEND_DICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_DICE))
|
|
+#define G_VFS_IS_BACKEND_DICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_DICE))
|
|
+#define G_VFS_BACKEND_DICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_DICE, GVfsBackendDiceClass))
|
|
+
|
|
+typedef struct _GVfsBackendDice GVfsBackendDice;
|
|
+typedef struct _GVfsBackendDiceClass GVfsBackendDiceClass;
|
|
+
|
|
+struct _GVfsBackendDiceClass
|
|
+{
|
|
+ GVfsBackendClass parent_class;
|
|
+};
|
|
+
|
|
+GType g_vfs_backend_dice_get_type (void) G_GNUC_CONST;
|
|
+
|
|
+G_END_DECLS
|
|
+
|
|
+#endif /* __G_VFS_BACKEND_DICE_H__ */
|
|
|
|
Property changes on: daemon/gvfsbackenddice.h
|
|
___________________________________________________________________
|
|
Added: svn:mergeinfo
|
|
|
|
Index: daemon/Makefile.am
|
|
===================================================================
|
|
--- daemon/Makefile.am (revision 1814)
|
|
+++ daemon/Makefile.am (working copy)
|
|
@@ -8,6 +8,7 @@
|
|
-I$(top_srcdir)/common \
|
|
-I$(top_builddir) \
|
|
$(GLIB_CFLAGS) $(DBUS_CFLAGS) \
|
|
+ $(DBUS_GLIB_CFLAGS) \
|
|
$(OBEXFTP_CFLAGS) $(XML_CFLAGS) \
|
|
$(KEYRING_CFLAGS) \
|
|
-DDBUS_API_SUBJECT_TO_CHANGE \
|
|
@@ -21,7 +22,7 @@
|
|
libraries = \
|
|
libdaemon.la \
|
|
$(top_builddir)/common/libgvfscommon.la \
|
|
- $(GLIB_LIBS) $(DBUS_LIBS) $(KEYRING_LIBS)
|
|
+ $(GLIB_LIBS) $(DBUS_LIBS) $(DBUS_GLIB_LIBS) $(KEYRING_LIBS)
|
|
|
|
# D-BUS service file
|
|
%.service: %.service.in ../config.log
|
|
@@ -34,10 +35,10 @@
|
|
%.mount: %.mount.in ../config.log
|
|
sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
|
|
|
|
-libexec_PROGRAMS=gvfsd gvfsd-sftp gvfsd-trash gvfsd-computer gvfsd-burn gvfsd-localtest
|
|
+libexec_PROGRAMS=gvfsd gvfsd-sftp gvfsd-trash gvfsd-dice gvfsd-computer gvfsd-burn gvfsd-localtest
|
|
|
|
-mount_in_files = sftp.mount.in trash.mount.in computer.mount.in burn.mount.in localtest.mount.in
|
|
-mount_DATA = sftp.mount trash.mount computer.mount burn.mount localtest.mount
|
|
+mount_in_files = sftp.mount.in trash.mount.in dice.mount.in computer.mount.in burn.mount.in localtest.mount.in
|
|
+mount_DATA = sftp.mount trash.mount dice.mount computer.mount burn.mount localtest.mount
|
|
|
|
mount_in_files += http.mount.in dav.mount.in ftp.mount.in
|
|
if HAVE_HTTP
|
|
@@ -264,6 +265,19 @@
|
|
|
|
gvfsd_trash_LDADD = $(libraries)
|
|
|
|
+gvfsd_dice_SOURCES = \
|
|
+ gvfsbackenddice.c gvfsbackenddice.h \
|
|
+ daemon-main.c daemon-main.h \
|
|
+ daemon-main-generic.c
|
|
+
|
|
+gvfsd_dice_CPPFLAGS = \
|
|
+ -DBACKEND_HEADER=gvfsbackenddice.h \
|
|
+ -DDEFAULT_BACKEND_TYPE=dice \
|
|
+ -DMAX_JOB_THREADS=10 \
|
|
+ -DBACKEND_TYPES='"dice", G_VFS_TYPE_BACKEND_DICE,'
|
|
+
|
|
+gvfsd_dice_LDADD = $(libraries)
|
|
+
|
|
gvfsd_computer_SOURCES = \
|
|
gvfsbackendcomputer.c gvfsbackendcomputer.h \
|
|
daemon-main.c daemon-main.h \
|
|
Index: daemon/dice.mount.in
|
|
===================================================================
|
|
--- daemon/dice.mount.in (revision 0)
|
|
+++ daemon/dice.mount.in (revision 0)
|
|
@@ -0,0 +1,5 @@
|
|
+[Mount]
|
|
+Type=dice
|
|
+Exec=@libexecdir@/gvfsd-dice
|
|
+AutoMount=true
|
|
+DBusName=org.gtk.vfs.mountpoint.dice
|
|
|
|
Property changes on: daemon/dice.mount.in
|
|
___________________________________________________________________
|
|
Added: svn:mergeinfo
|
|
|