summaryrefslogtreecommitdiff
path: root/trunk/daemon/gvfsdaemonutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/daemon/gvfsdaemonutils.c')
-rw-r--r--trunk/daemon/gvfsdaemonutils.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/trunk/daemon/gvfsdaemonutils.c b/trunk/daemon/gvfsdaemonutils.c
new file mode 100644
index 00000000..b221fdb8
--- /dev/null
+++ b/trunk/daemon/gvfsdaemonutils.c
@@ -0,0 +1,286 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <gio/gio.h>
+#include "gdbusutils.h"
+#include "gsysutils.h"
+#include "gvfsdaemonutils.h"
+#include "gvfsdaemonprotocol.h"
+
+static gint32 extra_fd_slot = -1;
+static GStaticMutex extra_lock = G_STATIC_MUTEX_INIT;
+
+typedef struct {
+ int extra_fd;
+ int fd_count;
+} ConnectionExtra;
+
+static void
+free_extra (gpointer p)
+{
+ ConnectionExtra *extra = p;
+ close (extra->extra_fd);
+ g_free (extra);
+}
+
+void
+dbus_connection_add_fd_send_fd (DBusConnection *connection,
+ int extra_fd)
+{
+ ConnectionExtra *extra;
+
+ if (extra_fd_slot == -1 &&
+ !dbus_connection_allocate_data_slot (&extra_fd_slot))
+ g_error ("Unable to allocate data slot");
+
+ extra = g_new0 (ConnectionExtra, 1);
+ extra->extra_fd = extra_fd;
+
+ if (!dbus_connection_set_data (connection, extra_fd_slot, extra, free_extra))
+ _g_dbus_oom ();
+}
+
+gboolean
+dbus_connection_send_fd (DBusConnection *connection,
+ int fd,
+ int *fd_id,
+ GError **error)
+{
+ ConnectionExtra *extra;
+
+ g_assert (extra_fd_slot != -1);
+ extra = dbus_connection_get_data (connection, extra_fd_slot);
+ g_assert (extra != NULL);
+
+ if (extra->extra_fd == -1)
+ {
+ g_set_error (error, G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ _("Internal Error (%s)"), "No fd passing socket available");
+ return FALSE;
+ }
+
+ g_static_mutex_lock (&extra_lock);
+
+ if (_g_socket_send_fd (extra->extra_fd, fd) == -1)
+ {
+ int errsv = errno;
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ _("Error sending fd: %s"),
+ g_strerror (errsv));
+ g_static_mutex_unlock (&extra_lock);
+ return FALSE;
+ }
+
+ *fd_id = extra->fd_count++;
+
+ g_static_mutex_unlock (&extra_lock);
+
+ return TRUE;
+}
+
+char *
+g_error_to_daemon_reply (GError *error, guint32 seq_nr, gsize *len_out)
+{
+ char *buffer;
+ const char *domain;
+ gsize domain_len, message_len;
+ GVfsDaemonSocketProtocolReply *reply;
+ gsize len;
+
+ domain = g_quark_to_string (error->domain);
+ domain_len = strlen (domain);
+ message_len = strlen (error->message);
+
+ len = G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE +
+ domain_len + 1 + message_len + 1;
+ buffer = g_malloc (len);
+
+ reply = (GVfsDaemonSocketProtocolReply *)buffer;
+ reply->type = g_htonl (G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR);
+ reply->seq_nr = g_htonl (seq_nr);
+ reply->arg1 = g_htonl (error->code);
+ reply->arg2 = g_htonl (domain_len + 1 + message_len + 1);
+
+ memcpy (buffer + G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE,
+ domain, domain_len + 1);
+ memcpy (buffer + G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE + domain_len + 1,
+ error->message, message_len + 1);
+
+ *len_out = len;
+
+ return buffer;
+}
+
+/**
+ * gvfs_file_info_populate_default:
+ * @info: file info to populate
+ * @name_string: a bytes string of possibly the full path to the given file
+ * @type: type of this file
+ *
+ * Calls gvfs_file_info_populate_names_as_local() and
+ * gvfs_file_info_populate_content_types() on the given @name_string.
+ **/
+void
+gvfs_file_info_populate_default (GFileInfo *info,
+ const char *name_string,
+ GFileType type)
+{
+ char *edit_name;
+
+ g_return_if_fail (G_IS_FILE_INFO (info));
+ g_return_if_fail (name_string != NULL);
+
+ edit_name = gvfs_file_info_populate_names_as_local (info, name_string);
+ gvfs_file_info_populate_content_types (info, edit_name, type);
+ g_free (edit_name);
+}
+
+/**
+ * gvfs_file_info_populate_names_as_local:
+ * @info: the file info to fill
+ * @name_string: a bytes string of possibly the full path to the given file
+ *
+ * Sets the name of the file info to @name_string and determines display and
+ * edit name for it.
+ *
+ * This generates the display name based on what encoding is used for local filenames.
+ * It might be a good thing to use if you have no idea of the remote system filename
+ * encoding, but if you know the actual encoding use, or if you allow per-mount
+ * configuration of filename encoding in your backend you should not use this.
+ *
+ * Returns: the utf-8 encoded edit name for the given file.
+ **/
+char *
+gvfs_file_info_populate_names_as_local (GFileInfo *info,
+ const char *name_string)
+{
+ //const char *slash;
+ char *edit_name;
+
+ g_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
+ g_return_val_if_fail (name_string != NULL, NULL);
+
+#if 0
+ slash = strrchr (name_string, '/');
+ if (slash && slash[1])
+ name_string = slash + 1;
+#endif
+ edit_name = g_filename_display_basename (name_string);
+ g_file_info_set_edit_name (info, edit_name);
+
+ if (strstr (edit_name, "\357\277\275") != NULL)
+ {
+ char *display_name;
+
+ display_name = g_strconcat (edit_name, _(" (invalid encoding)"), NULL);
+ g_file_info_set_display_name (info, display_name);
+ g_free (display_name);
+ }
+ else
+ g_file_info_set_display_name (info, edit_name);
+
+ return edit_name;
+}
+
+/**
+ * gvfs_file_info_populate_content_types:
+ * @info: the file info to fill
+ * @basename: utf-8 encoded base name of file
+ * @type: type of this file
+ *
+ * Takes the base name and guesses content type and icon with it. This function
+ * is intended for remote files. Do not use it for directories.
+ **/
+void
+gvfs_file_info_populate_content_types (GFileInfo *info,
+ const char *basename,
+ GFileType type)
+{
+ char *free_mimetype = NULL;
+ const char *mimetype;
+ GIcon *icon;
+
+ g_return_if_fail (G_IS_FILE_INFO (info));
+ g_return_if_fail (basename != NULL);
+
+ g_file_info_set_file_type (info, type);
+
+ switch (type)
+ {
+ case G_FILE_TYPE_DIRECTORY:
+ mimetype = "inode/directory";
+ break;
+ case G_FILE_TYPE_SYMBOLIC_LINK:
+ mimetype = "inode/symlink";
+ break;
+ case G_FILE_TYPE_SPECIAL:
+ mimetype = "inode/special";
+ break;
+ case G_FILE_TYPE_SHORTCUT:
+ mimetype = "inode/shortcut";
+ break;
+ case G_FILE_TYPE_MOUNTABLE:
+ mimetype = "inode/mountable";
+ break;
+ case G_FILE_TYPE_REGULAR:
+ free_mimetype = g_content_type_guess (basename, NULL, 0, NULL);
+ mimetype = free_mimetype;
+ break;
+ case G_FILE_TYPE_UNKNOWN:
+ default:
+ mimetype = "application/octet-stream";
+ break;
+ }
+
+ g_file_info_set_content_type (info, mimetype);
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE, mimetype);
+
+ if (type == G_FILE_TYPE_DIRECTORY)
+ icon = g_themed_icon_new ("folder");
+ else
+ {
+ icon = g_content_type_get_icon (mimetype);
+ }
+
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
+
+ g_free (free_mimetype);
+}
+