diff --git a/gvfs-1.0.0.tar.bz2 b/gvfs-1.0.0.tar.bz2 deleted file mode 100644 index 5317cb2..0000000 --- a/gvfs-1.0.0.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:054ad02427ecf79e74c92b75d587db56c380170e1f975a8ebd0a1a41afeb0211 -size 914844 diff --git a/gvfs-1.0.1.tar.bz2 b/gvfs-1.0.1.tar.bz2 new file mode 100644 index 0000000..072fc13 --- /dev/null +++ b/gvfs-1.0.1.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67e7dd1dca32a99eb1102a853d2df1bac782d50a4361511409572cfe8ea51147 +size 898295 diff --git a/gvfs-dice-backend.patch b/gvfs-dice-backend.patch new file mode 100644 index 0000000..5e799c3 --- /dev/null +++ b/gvfs-dice-backend.patch @@ -0,0 +1,1549 @@ +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 ++ */ ++ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#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 ++ */ ++ ++#ifndef __G_VFS_BACKEND_DICE_H__ ++#define __G_VFS_BACKEND_DICE_H__ ++ ++#include ++#include ++ ++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 + diff --git a/gvfs.changes b/gvfs.changes index 6b434d6..97c85b0 100644 --- a/gvfs.changes +++ b/gvfs.changes @@ -1,3 +1,15 @@ +------------------------------------------------------------------- +Fri Oct 3 11:26:25 WST 2008 - mboman@suse.de + +- Update to version 1.0.1: + + bgo#547568 - gvfsd-trash crash due to race condition + +------------------------------------------------------------------- +Wed Sep 24 00:37:04 CDT 2008 - hpj@suse.de + +- Add gvfs-dice-backend.patch, which implements the Novell + IceDesktop backend. + ------------------------------------------------------------------- Mon Sep 22 08:53:34 CDT 2008 - maw@suse.de diff --git a/gvfs.spec b/gvfs.spec index d95ef4b..4187d8a 100644 --- a/gvfs.spec +++ b/gvfs.spec @@ -1,5 +1,5 @@ # -# spec file for package gvfs (Version 1.0.0) +# spec file for package gvfs (Version 1.0.1) # # Copyright (c) 2008 SUSE LINUX Products GmbH, Nuernberg, Germany. # @@ -44,13 +44,15 @@ BuildRequires: libgphoto2 BuildRequires: extra-rpm-macros %endif Summary: VFS functionality for GLib -Version: 1.0.0 +Version: 1.0.1 Release: 1 License: LGPL v2.0 or later Group: Development/Libraries/C and C++ Source0: %{name}-%{version}.tar.bz2 # PATCH-FIX-UPSTREAM gvfs-no-shebang.patch bgo523420 maw@suse.de Patch0: gvfs-no-shebang.patch +# PATCH-FEATURE-OPENSUSE gvfs-dice-backend.patch hpj@suse.de -- Implements Novell IceDesktop backend. Should be upstreamed eventually. +Patch1: gvfs-dice-backend.patch Url: http://www.gnome.org BuildRoot: %{_tmppath}/%{name}-%{version}-build AutoReqProv: on @@ -136,9 +138,12 @@ Authors: %prep %setup -n %{name}-%{version} %patch0 -p1 +%patch1 %build export CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing" +autoreconf -f +libtoolize -c -f %configure \ --libexecdir=%{_libdir}/%{name} %__make @@ -190,6 +195,12 @@ rm -rf $RPM_BUILD_ROOT %files lang -f %{name}.lang %changelog +* Fri Oct 03 2008 mboman@suse.de +- Update to version 1.0.1: + + bgo#547568 - gvfsd-trash crash due to race condition +* Wed Sep 24 2008 hpj@suse.de +- Add gvfs-dice-backend.patch, which implements the Novell + IceDesktop backend. * Mon Sep 22 2008 maw@suse.de - Update to version 1.0.0: + Bug fixed: bgo#524498. @@ -199,9 +210,9 @@ rm -rf $RPM_BUILD_ROOT + Fix crash while browsing ssh locations + Fix --enable/disable-keyring configure switch + Updated translations. -* Tue Sep 16 2008 dmueller@suse.de +* Wed Sep 17 2008 dmueller@suse.de - update buildrequires -* Wed Sep 10 2008 maw@suse.de +* Thu Sep 11 2008 maw@suse.de - Update to version 0.99.7.1: + Revert to using powers of 10 instead of powers of 2 for display sizes; this means we will agree with printed sizes for @@ -209,19 +220,19 @@ rm -rf $RPM_BUILD_ROOT report "64MB volume" instead of "61.7MB volume" as previously + Bugs fixed: bgo#546971 and bgo#550858 + Updated translations. -* Mon Sep 08 2008 kukuk@suse.de +* Tue Sep 09 2008 kukuk@suse.de - Make obex-data-server really a recommends as requested initialy in bugzilla. -* Mon Sep 01 2008 mboman@novell.com +* Tue Sep 02 2008 mboman@novell.com - Update to version 0.99.6: + Better cross-backend copy/move logic. + Bugs fixed: bgo#548841, bgo#547133, bgo#538573, bgo#549253, bgo#549553, bgo#550100, bgo#529971, rh#460223 + Translation updates -* Sun Aug 31 2008 ro@suse.de +* Mon Sep 01 2008 ro@suse.de - add libexpat-devel to buildrequires so that obex backend is built -* Thu Aug 28 2008 maw@suse.de +* Fri Aug 29 2008 maw@suse.de - Update to version 0.93.5: + Support und update serialization of GEmblem and GEmblemedIcon + Add x-content/* support to daemon mounts @@ -235,14 +246,14 @@ rm -rf $RPM_BUILD_ROOT + Updated translations - Drop gvfs-bnc382172-home-trash-monitoring.patch, because it has been upstreamed (see bgo#509740 and bnc#382172). -* Fri Aug 01 2008 maw@suse.de +* Sat Aug 02 2008 maw@suse.de - Update to version 0.99.3: + Move hal and gphoto volume monitors out of process + Fix recursive copying + Make the fuse daemon more reliable + Many smaller bugfixes + Updated translations. -* Fri Jun 06 2008 maw@suse.de +* Sat Jun 07 2008 maw@suse.de - Update to versino 0.99.1: + Fix directory copy/delete problems + Fuse daemon robustness fixes @@ -255,14 +266,14 @@ rm -rf $RPM_BUILD_ROOT + Many smaller bug fixes + Updated translations - Remove upstreamed patch: gvfs-bnc368628-fuse-robustness.patch. -* Fri May 23 2008 hpj@suse.de +* Sat May 24 2008 hpj@suse.de - Merge gvfs-bgo531516-fuse-cleanup-when-killed.patch into gvfs-bnc368628-fuse-robustness.patch so as to avoid overlapping patches. - Add upstream fixes to thread locking and file handle life-cycles to gvfs-bnc368628-fuse-robustness.patch. Prevents more crashes. - Depend on libcdio-devel for building, so we get the CDDA backend. -* Wed May 21 2008 hpj@suse.de +* Thu May 22 2008 hpj@suse.de - Add gvfs-bgo531516-fuse-cleanup-when-killed.patch, which fixes the remaining issues covered by BNC #368628. * Tue May 13 2008 hpj@suse.de @@ -271,7 +282,7 @@ rm -rf $RPM_BUILD_ROOT * Thu May 08 2008 hpj@suse.de - Add gvfs-bnc368628-fuse-robustness.patch, which probably fixes BNC #368628. -* Wed Apr 09 2008 maw@suse.de +* Thu Apr 10 2008 maw@suse.de - Update to version 0.2.3: + WebDAV: implement set_display_name + WebDAV fixes @@ -282,7 +293,7 @@ rm -rf $RPM_BUILD_ROOT * Wed Apr 09 2008 sbrabec@suse.cz - Directory ownership of %%{_libdir}/gio/modules moved to glib2, where it logically belongs. -* Tue Apr 01 2008 rodrigo@suse.de +* Wed Apr 02 2008 rodrigo@suse.de - Update to version 0.2.2: * Respect the giomoduledir provided in gio package config file * Better mount icon and name for archive backend @@ -294,13 +305,13 @@ rm -rf $RPM_BUILD_ROOT * sftp: Kerberos support * smb: Port to new samba 3.2.0 API (backwards compat) * sftp: Handle overwrites correctly (was silent overwrite) -* Tue Mar 25 2008 maw@suse.de +* Wed Mar 26 2008 maw@suse.de - gvfs now recommends gvfs-backends (bnc#373477). -* Wed Mar 19 2008 maw@suse.de +* Thu Mar 20 2008 maw@suse.de - Reduce build requirements - Split out a shared library package, libgnomevfscommon0, and two module subpackages, gvfs-backends and gvfs-fuse. -* Tue Mar 18 2008 jpr@suse.de +* Wed Mar 19 2008 jpr@suse.de - Update to version 0.2.1 * Added archive backend * Implement most of the async functions in GDaemonFile @@ -314,7 +325,7 @@ rm -rf $RPM_BUILD_ROOT * Enviroment variable to disable fuse backend at runtime * Mon Mar 17 2008 jpr@suse.de - Add recommends for obex-data-server (bnc #368776) -* Thu Mar 13 2008 maw@suse.de +* Fri Mar 14 2008 maw@suse.de - Update to version 0.2.0.1: + Fix crashes + Build and portability fixes @@ -326,14 +337,14 @@ rm -rf $RPM_BUILD_ROOT + obex: Give better error message on broken phones + sftp: Allow setting permissions + dav: Correct mount name, file icons and file types. -* Tue Mar 04 2008 jpr@suse.de +* Wed Mar 05 2008 jpr@suse.de - Update to version 0.1.11 * Correctly free mounts * Disable debug log * Fix volume monitor change reporting * Fix timeout during automount - enable obex backend -* Tue Mar 04 2008 maw@suse.de +* Wed Mar 05 2008 maw@suse.de - Update to version 0.1.9: + Added ftp backend + Added obexftp backend @@ -343,7 +354,7 @@ rm -rf $RPM_BUILD_ROOT + Allow backends to specify uri details in .mount file + Fix leaks and crashes + Fix icon for audio cds. -* Fri Feb 29 2008 jpr@suse.de +* Sat Mar 01 2008 jpr@suse.de - Update to 0.1.8 * Update for gio API changes * Add gphoto2 backend @@ -360,10 +371,10 @@ rm -rf $RPM_BUILD_ROOT * Add bash completion support for command line apps * Fix handling of blank cds and audio cds * Support port in sftp uris -* Thu Feb 28 2008 jpr@suse.de +* Fri Feb 29 2008 jpr@suse.de - Move the gio modules into the main package (#358748) - Enable gconf backend -* Mon Feb 18 2008 maw@suse.de +* Tue Feb 19 2008 maw@suse.de - Update to version 0.1.7: + Update for gio API changes + Add gconf based implementation of @@ -376,9 +387,9 @@ rm -rf $RPM_BUILD_ROOT + Pick up cdrom icons from autorun.inf + Add "filesystem" file to computer:// + Fix renaming in sftp and smb. -* Fri Feb 08 2008 maw@suse.de +* Sat Feb 09 2008 maw@suse.de - Recomend fuse (bnc#359928). -* Wed Jan 30 2008 maw@suse.de +* Thu Jan 31 2008 maw@suse.de - Update to version 0.1.6: + Updates to work with more recent glib + Fix sftp error handling on reading directories @@ -387,5 +398,5 @@ rm -rf $RPM_BUILD_ROOT + hal: Don't show drives if all volumes are hidden + Enable translations + Plus some files that were missing in 0.1.5. -* Tue Jan 22 2008 maw@suse.de +* Wed Jan 23 2008 maw@suse.de - Initial package, version 0.1.4.