1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  */
22 
23 #include <config.h>
24 
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <sys/un.h>
29 
30 #include <glib.h>
31 #include <glib/gi18n.h>
32 #include "gvfsjobmountmountable.h"
33 #include "gvfsdaemonutils.h"
34 
35 G_DEFINE_TYPE (GVfsJobMountMountable, g_vfs_job_mount_mountable, G_VFS_TYPE_JOB_DBUS)
36 
37 static void         run          (GVfsJob        *job);
38 static gboolean     try          (GVfsJob        *job);
39 static void         create_reply (GVfsJob               *job,
40                                   GVfsDBusMount         *object,
41                                   GDBusMethodInvocation *invocation);
42 
43 static void
g_vfs_job_mount_mountable_finalize(GObject * object)44 g_vfs_job_mount_mountable_finalize (GObject *object)
45 {
46   GVfsJobMountMountable *job;
47 
48   job = G_VFS_JOB_MOUNT_MOUNTABLE (object);
49 
50   if (job->mount_source)
51     g_object_unref (job->mount_source);
52 
53   if (job->mount_spec)
54     g_mount_spec_unref (job->mount_spec);
55 
56   g_free (job->filename);
57   g_free (job->target_filename);
58 
59   if (G_OBJECT_CLASS (g_vfs_job_mount_mountable_parent_class)->finalize)
60     (*G_OBJECT_CLASS (g_vfs_job_mount_mountable_parent_class)->finalize) (object);
61 }
62 
63 static void
g_vfs_job_mount_mountable_class_init(GVfsJobMountMountableClass * klass)64 g_vfs_job_mount_mountable_class_init (GVfsJobMountMountableClass *klass)
65 {
66   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
67   GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass);
68   GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass);
69 
70   gobject_class->finalize = g_vfs_job_mount_mountable_finalize;
71   job_class->run = run;
72   job_class->try = try;
73   job_dbus_class->create_reply = create_reply;
74 }
75 
76 static void
g_vfs_job_mount_mountable_init(GVfsJobMountMountable * job)77 g_vfs_job_mount_mountable_init (GVfsJobMountMountable *job)
78 {
79 }
80 
81 gboolean
g_vfs_job_mount_mountable_new_handle(GVfsDBusMount * object,GDBusMethodInvocation * invocation,const gchar * arg_path_data,const gchar * arg_dbus_id,const gchar * arg_obj_path,GVfsBackend * backend)82 g_vfs_job_mount_mountable_new_handle (GVfsDBusMount *object,
83                                       GDBusMethodInvocation *invocation,
84                                       const gchar *arg_path_data,
85                                       const gchar *arg_dbus_id,
86                                       const gchar *arg_obj_path,
87                                       GVfsBackend *backend)
88 {
89   GVfsJobMountMountable *job;
90 
91   if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
92     return TRUE;
93 
94   job = g_object_new (G_VFS_TYPE_JOB_MOUNT_MOUNTABLE,
95                       "object", object,
96                       "invocation", invocation,
97                       NULL);
98 
99   job->filename = g_strdup (arg_path_data);
100   job->backend = backend;
101   job->mount_source = g_mount_source_new (arg_dbus_id, arg_obj_path);
102 
103   g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
104   g_object_unref (job);
105 
106   return TRUE;
107 }
108 
109 void
g_vfs_job_mount_mountable_set_target(GVfsJobMountMountable * job,GMountSpec * mount_spec,const char * filename,gboolean must_mount_location)110 g_vfs_job_mount_mountable_set_target (GVfsJobMountMountable *job,
111 				      GMountSpec *mount_spec,
112 				      const char *filename,
113 				      gboolean must_mount_location)
114 {
115   job->mount_spec = g_mount_spec_ref (mount_spec);
116   job->target_filename = g_strdup (filename);
117   job->must_mount_location = must_mount_location;
118 }
119 
120 void
g_vfs_job_mount_mountable_set_target_uri(GVfsJobMountMountable * job,const char * uri,gboolean must_mount_location)121 g_vfs_job_mount_mountable_set_target_uri (GVfsJobMountMountable *job,
122 					  const char *uri,
123 					  gboolean must_mount_location)
124 {
125   job->target_uri = g_strdup (uri);
126   job->must_mount_location = must_mount_location;
127 }
128 
129 static void
run(GVfsJob * job)130 run (GVfsJob *job)
131 {
132   GVfsJobMountMountable *op_job = G_VFS_JOB_MOUNT_MOUNTABLE (job);
133   GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
134 
135   if (class->mount_mountable == NULL)
136     {
137       g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
138 			_("Operation not supported"));
139       return;
140     }
141 
142   class->mount_mountable (op_job->backend,
143 			  op_job,
144 			  op_job->filename,
145 			  op_job->mount_source);
146 }
147 
148 static gboolean
try(GVfsJob * job)149 try (GVfsJob *job)
150 {
151   GVfsJobMountMountable *op_job = G_VFS_JOB_MOUNT_MOUNTABLE (job);
152   GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
153 
154   if (class->try_mount_mountable == NULL)
155     return FALSE;
156 
157   return class->try_mount_mountable (op_job->backend,
158 				     op_job,
159 				     op_job->filename,
160 				     op_job->mount_source);
161 }
162 
163 /* Might be called on an i/o thread */
164 static void
create_reply(GVfsJob * job,GVfsDBusMount * object,GDBusMethodInvocation * invocation)165 create_reply (GVfsJob *job,
166               GVfsDBusMount *object,
167               GDBusMethodInvocation *invocation)
168 {
169   GVfsJobMountMountable *op_job = G_VFS_JOB_MOUNT_MOUNTABLE (job);
170   gboolean is_uri, must_mount;
171   GMountSpec *fake_mountspec = NULL;
172 
173   must_mount = op_job->must_mount_location;
174   is_uri = op_job->target_uri != NULL;
175 
176   if (is_uri)
177     fake_mountspec = g_mount_spec_new (NULL);
178 
179   gvfs_dbus_mount_complete_mount_mountable (object,
180                                             invocation,
181                                             is_uri,
182                                             is_uri ? op_job->target_uri : op_job->target_filename,
183                                             must_mount,
184                                             g_mount_spec_to_dbus (is_uri ? fake_mountspec : op_job->mount_spec));
185 
186   if (fake_mountspec)
187     g_mount_spec_unref (fake_mountspec);
188 }
189