|
Lines 1-7
Link Here
|
| 1 |
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
1 |
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| 2 |
/* GIO - GLib Input, Output and Streaming Library |
2 |
|
|
|
3 |
/* gvfsfusedaemon.c - FUSE file system mapping daemon for GVFS |
| 3 |
* |
4 |
* |
| 4 |
* Copyright (C) 2006-2007 Red Hat, Inc. |
5 |
* Copyright (C) 2007-2008 Hans Petter Jansson |
| 5 |
* |
6 |
* |
| 6 |
* This library is free software; you can redistribute it and/or |
7 |
* This library is free software; you can redistribute it and/or |
| 7 |
* modify it under the terms of the GNU Lesser General Public |
8 |
* modify it under the terms of the GNU Lesser General Public |
|
Lines 18-27
Link Here
|
| 18 |
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
19 |
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
| 19 |
* Boston, MA 02111-1307, USA. |
20 |
* Boston, MA 02111-1307, USA. |
| 20 |
* |
21 |
* |
| 21 |
* Author: Alexander Larsson <alexl@redhat.com> |
22 |
* Author: Hans Petter Jansson <hpj@novell.com> |
| 22 |
*/ |
23 |
*/ |
| 23 |
|
24 |
|
| 24 |
|
|
|
| 25 |
#include <config.h> |
25 |
#include <config.h> |
| 26 |
|
26 |
|
| 27 |
#include <stdio.h> |
27 |
#include <stdio.h> |
|
Lines 55-62
Link Here
|
| 55 |
|
55 |
|
| 56 |
#define DEBUG_ENABLED 0 |
56 |
#define DEBUG_ENABLED 0 |
| 57 |
|
57 |
|
| 58 |
#define GET_FILE_HANDLE(fi) (GUINT_TO_POINTER ((guint) (fi)->fh)) |
58 |
#define GET_FILE_HANDLE(fi) ((gpointer) (fi)->fh) |
| 59 |
#define SET_FILE_HANDLE(fi, fh) ((fi)->fh = (guint64) GPOINTER_TO_UINT (fh)) |
59 |
#define SET_FILE_HANDLE(fi, fh) ((fi)->fh = (guint64) (fh)) |
| 60 |
|
60 |
|
| 61 |
typedef struct { |
61 |
typedef struct { |
| 62 |
time_t creation_time; |
62 |
time_t creation_time; |
|
Lines 71-77
typedef enum {
Link Here
|
| 71 |
} FileOp; |
71 |
} FileOp; |
| 72 |
|
72 |
|
| 73 |
typedef struct { |
73 |
typedef struct { |
|
|
74 |
gint refcount; |
| 75 |
|
| 74 |
GMutex *mutex; |
76 |
GMutex *mutex; |
|
|
77 |
gchar *path; |
| 75 |
FileOp op; |
78 |
FileOp op; |
| 76 |
gpointer stream; |
79 |
gpointer stream; |
| 77 |
gint length; |
80 |
gint length; |
|
Lines 183-199
errno_from_error (GError *error)
Link Here
|
| 183 |
} |
186 |
} |
| 184 |
|
187 |
|
| 185 |
static FileHandle * |
188 |
static FileHandle * |
| 186 |
file_handle_new (void) |
189 |
file_handle_new (const gchar *path) |
| 187 |
{ |
190 |
{ |
| 188 |
FileHandle *file_handle; |
191 |
FileHandle *file_handle; |
| 189 |
|
192 |
|
| 190 |
file_handle = g_new0 (FileHandle, 1); |
193 |
file_handle = g_new0 (FileHandle, 1); |
|
|
194 |
file_handle->refcount = 1; |
| 191 |
file_handle->mutex = g_mutex_new (); |
195 |
file_handle->mutex = g_mutex_new (); |
| 192 |
file_handle->op = FILE_OP_NONE; |
196 |
file_handle->op = FILE_OP_NONE; |
|
|
197 |
file_handle->path = g_strdup (path); |
| 193 |
|
198 |
|
| 194 |
return file_handle; |
199 |
return file_handle; |
| 195 |
} |
200 |
} |
| 196 |
|
201 |
|
|
|
202 |
static FileHandle * |
| 203 |
file_handle_ref (FileHandle *file_handle) |
| 204 |
{ |
| 205 |
g_atomic_int_inc (&file_handle->refcount); |
| 206 |
return file_handle; |
| 207 |
} |
| 208 |
|
| 209 |
static void |
| 210 |
file_handle_unref (FileHandle *file_handle) |
| 211 |
{ |
| 212 |
if (g_atomic_int_dec_and_test (&file_handle->refcount)) |
| 213 |
{ |
| 214 |
g_static_mutex_lock (&global_mutex); |
| 215 |
|
| 216 |
/* Test again, since e.g. get_file_handle_for_path() might have |
| 217 |
* snatched the global mutex and revived the file handle between |
| 218 |
* g_atomic_int_dec_and_test() and us obtaining the lock. */ |
| 219 |
|
| 220 |
if (g_atomic_int_get (&file_handle->refcount) == 0) |
| 221 |
g_hash_table_remove (global_fh_table, file_handle->path); |
| 222 |
|
| 223 |
g_static_mutex_unlock (&global_mutex); |
| 224 |
} |
| 225 |
} |
| 226 |
|
| 197 |
static void |
227 |
static void |
| 198 |
file_handle_close_stream (FileHandle *file_handle) |
228 |
file_handle_close_stream (FileHandle *file_handle) |
| 199 |
{ |
229 |
{ |
|
Lines 220-230
file_handle_close_stream (FileHandle *fi
Link Here
|
| 220 |
} |
250 |
} |
| 221 |
} |
251 |
} |
| 222 |
|
252 |
|
|
|
253 |
/* Called on hash table removal */ |
| 223 |
static void |
254 |
static void |
| 224 |
file_handle_free (FileHandle *file_handle) |
255 |
file_handle_free (FileHandle *file_handle) |
| 225 |
{ |
256 |
{ |
| 226 |
file_handle_close_stream (file_handle); |
257 |
file_handle_close_stream (file_handle); |
| 227 |
g_mutex_free (file_handle->mutex); |
258 |
g_mutex_free (file_handle->mutex); |
|
|
259 |
g_free (file_handle->path); |
| 228 |
g_free (file_handle); |
260 |
g_free (file_handle); |
| 229 |
} |
261 |
} |
| 230 |
|
262 |
|
|
Lines 234-240
get_file_handle_for_path (const gchar *p
Link Here
|
| 234 |
FileHandle *fh; |
266 |
FileHandle *fh; |
| 235 |
|
267 |
|
| 236 |
g_static_mutex_lock (&global_mutex); |
268 |
g_static_mutex_lock (&global_mutex); |
|
|
269 |
|
| 237 |
fh = g_hash_table_lookup (global_fh_table, path); |
270 |
fh = g_hash_table_lookup (global_fh_table, path); |
|
|
271 |
if (fh) |
| 272 |
file_handle_ref (fh); |
| 273 |
|
| 238 |
g_static_mutex_unlock (&global_mutex); |
274 |
g_static_mutex_unlock (&global_mutex); |
| 239 |
|
275 |
|
| 240 |
return fh; |
276 |
return fh; |
|
Lines 245-260
get_or_create_file_handle_for_path (cons
Link Here
|
| 245 |
{ |
281 |
{ |
| 246 |
FileHandle *fh; |
282 |
FileHandle *fh; |
| 247 |
|
283 |
|
| 248 |
fh = get_file_handle_for_path (path); |
284 |
g_static_mutex_lock (&global_mutex); |
| 249 |
if (!fh) |
|
|
| 250 |
{ |
| 251 |
fh = file_handle_new (); |
| 252 |
|
285 |
|
| 253 |
g_static_mutex_lock (&global_mutex); |
286 |
fh = g_hash_table_lookup (global_fh_table, path); |
| 254 |
g_hash_table_insert (global_fh_table, g_strdup (path), fh); |
287 |
|
| 255 |
g_static_mutex_unlock (&global_mutex); |
288 |
if (fh) |
|
|
289 |
{ |
| 290 |
file_handle_ref (fh); |
| 291 |
} |
| 292 |
else |
| 293 |
{ |
| 294 |
fh = file_handle_new (path); |
| 295 |
g_hash_table_insert (global_fh_table, fh->path, fh); |
| 256 |
} |
296 |
} |
| 257 |
|
297 |
|
|
|
298 |
g_static_mutex_unlock (&global_mutex); |
| 299 |
|
| 258 |
return fh; |
300 |
return fh; |
| 259 |
} |
301 |
} |
| 260 |
|
302 |
|
|
Lines 271-298
reindex_file_handle_for_path (const gcha
Link Here
|
| 271 |
(gpointer *) &fh)) |
313 |
(gpointer *) &fh)) |
| 272 |
goto out; |
314 |
goto out; |
| 273 |
|
315 |
|
| 274 |
g_free (old_path_internal); |
316 |
g_hash_table_steal (global_fh_table, old_path); |
| 275 |
g_hash_table_insert (global_fh_table, g_strdup (new_path), fh); |
|
|
| 276 |
|
317 |
|
| 277 |
out: |
318 |
g_free (fh->path); |
| 278 |
g_static_mutex_unlock (&global_mutex); |
319 |
fh->path = g_strdup (new_path); |
| 279 |
} |
|
|
| 280 |
|
320 |
|
| 281 |
static gboolean |
321 |
g_hash_table_insert (global_fh_table, fh->path, fh); |
| 282 |
free_file_handle_for_path (const gchar *path) |
|
|
| 283 |
{ |
| 284 |
FileHandle *fh; |
| 285 |
|
322 |
|
| 286 |
fh = get_file_handle_for_path (path); |
323 |
out: |
| 287 |
if (fh) |
324 |
g_static_mutex_unlock (&global_mutex); |
| 288 |
{ |
|
|
| 289 |
g_static_mutex_lock (&global_mutex); |
| 290 |
g_hash_table_remove (global_fh_table, path); |
| 291 |
g_static_mutex_unlock (&global_mutex); |
| 292 |
return TRUE; |
| 293 |
} |
| 294 |
|
| 295 |
return FALSE; |
| 296 |
} |
325 |
} |
| 297 |
|
326 |
|
| 298 |
static MountRecord * |
327 |
static MountRecord * |
|
Lines 795-801
vfs_getattr (const gchar *path, struct s
Link Here
|
| 795 |
} |
824 |
} |
| 796 |
|
825 |
|
| 797 |
if (fh) |
826 |
if (fh) |
| 798 |
g_mutex_unlock (fh->mutex); |
827 |
{ |
|
|
828 |
g_mutex_unlock (fh->mutex); |
| 829 |
file_handle_unref (fh); |
| 830 |
} |
| 799 |
|
831 |
|
| 800 |
debug_print ("vfs_getattr: -> %s\n", strerror (-result)); |
832 |
debug_print ("vfs_getattr: -> %s\n", strerror (-result)); |
| 801 |
|
833 |
|
|
Lines 929-938
vfs_open (const gchar *path, struct fuse
Link Here
|
| 929 |
|
961 |
|
| 930 |
/* Set up a stream here, so we can check for errors */ |
962 |
/* Set up a stream here, so we can check for errors */ |
| 931 |
|
963 |
|
|
|
964 |
g_mutex_lock (fh->mutex); |
| 965 |
|
| 932 |
if (fi->flags & O_WRONLY || fi->flags & O_RDWR) |
966 |
if (fi->flags & O_WRONLY || fi->flags & O_RDWR) |
| 933 |
result = setup_output_stream (file, fh); |
967 |
result = setup_output_stream (file, fh); |
| 934 |
else |
968 |
else |
| 935 |
result = setup_input_stream (file, fh); |
969 |
result = setup_input_stream (file, fh); |
|
|
970 |
|
| 971 |
g_mutex_unlock (fh->mutex); |
| 972 |
|
| 973 |
/* The added reference to the file handle is released in vfs_release() */ |
| 936 |
} |
974 |
} |
| 937 |
else if (file_type == G_FILE_TYPE_DIRECTORY) |
975 |
else if (file_type == G_FILE_TYPE_DIRECTORY) |
| 938 |
{ |
976 |
{ |
|
Lines 1015-1024
vfs_create (const gchar *path, mode_t mo
Link Here
|
| 1015 |
|
1053 |
|
| 1016 |
SET_FILE_HANDLE (fi, fh); |
1054 |
SET_FILE_HANDLE (fi, fh); |
| 1017 |
|
1055 |
|
| 1018 |
g_assert (fh->stream == NULL); |
1056 |
g_mutex_lock (fh->mutex); |
| 1019 |
|
1057 |
|
|
|
1058 |
file_handle_close_stream (fh); |
| 1020 |
fh->stream = file_output_stream; |
1059 |
fh->stream = file_output_stream; |
| 1021 |
fh->op = FILE_OP_WRITE; |
1060 |
fh->op = FILE_OP_WRITE; |
|
|
1061 |
|
| 1062 |
g_mutex_unlock (fh->mutex); |
| 1063 |
|
| 1064 |
/* The added reference to the file handle is released in vfs_release() */ |
| 1022 |
} |
1065 |
} |
| 1023 |
else |
1066 |
else |
| 1024 |
{ |
1067 |
{ |
|
Lines 1047-1053
vfs_release (const gchar *path, struct f
Link Here
|
| 1047 |
debug_print ("vfs_release: %s\n", path); |
1090 |
debug_print ("vfs_release: %s\n", path); |
| 1048 |
|
1091 |
|
| 1049 |
if (fh) |
1092 |
if (fh) |
| 1050 |
free_file_handle_for_path (path); |
1093 |
file_handle_unref (fh); |
| 1051 |
|
1094 |
|
| 1052 |
return 0; |
1095 |
return 0; |
| 1053 |
} |
1096 |
} |
|
Lines 1479-1484
vfs_rename (const gchar *old_path, const
Link Here
|
| 1479 |
if (fh) |
1522 |
if (fh) |
| 1480 |
{ |
1523 |
{ |
| 1481 |
g_mutex_unlock (fh->mutex); |
1524 |
g_mutex_unlock (fh->mutex); |
|
|
1525 |
file_handle_unref (fh); |
| 1482 |
} |
1526 |
} |
| 1483 |
|
1527 |
|
| 1484 |
if (result == -EISDIR) |
1528 |
if (result == -EISDIR) |
|
Lines 1530-1535
vfs_unlink (const gchar *path)
Link Here
|
| 1530 |
if (fh) |
1574 |
if (fh) |
| 1531 |
{ |
1575 |
{ |
| 1532 |
g_mutex_unlock (fh->mutex); |
1576 |
g_mutex_unlock (fh->mutex); |
|
|
1577 |
file_handle_unref (fh); |
| 1533 |
} |
1578 |
} |
| 1534 |
|
1579 |
|
| 1535 |
if (error) |
1580 |
if (error) |
|
Lines 1748-1754
vfs_truncate (const gchar *path, off_t s
Link Here
|
| 1748 |
} |
1793 |
} |
| 1749 |
|
1794 |
|
| 1750 |
if (fh) |
1795 |
if (fh) |
| 1751 |
g_mutex_unlock (fh->mutex); |
1796 |
{ |
|
|
1797 |
g_mutex_unlock (fh->mutex); |
| 1798 |
file_handle_unref (fh); |
| 1799 |
} |
| 1752 |
|
1800 |
|
| 1753 |
g_object_unref (file); |
1801 |
g_object_unref (file); |
| 1754 |
} |
1802 |
} |
|
Lines 1998-2003
subthread_main (gpointer data)
Link Here
|
| 1998 |
g_object_unref (volume_monitor); |
2046 |
g_object_unref (volume_monitor); |
| 1999 |
volume_monitor = NULL; |
2047 |
volume_monitor = NULL; |
| 2000 |
|
2048 |
|
|
|
2049 |
/* Tell the main thread to unmount. Using kill() is necessary according to FUSE maintainers. */ |
| 2050 |
kill (getpid (), SIGHUP); |
| 2051 |
|
| 2001 |
return NULL; |
2052 |
return NULL; |
| 2002 |
} |
2053 |
} |
| 2003 |
|
2054 |
|
|
Lines 2025-2038
dbus_filter_func (DBusConnection *connec
Link Here
|
| 2025 |
*new_owner == 0) |
2076 |
*new_owner == 0) |
| 2026 |
{ |
2077 |
{ |
| 2027 |
/* The daemon died, unmount */ |
2078 |
/* The daemon died, unmount */ |
| 2028 |
kill (getpid(), SIGHUP); |
2079 |
g_main_loop_quit (subthread_main_loop); |
| 2029 |
} |
2080 |
} |
| 2030 |
} |
2081 |
} |
|
|
2082 |
else if (dbus_message_is_signal (message, |
| 2083 |
DBUS_INTERFACE_LOCAL, |
| 2084 |
"Disconnected")) |
| 2085 |
{ |
| 2086 |
/* Session bus died, unmount */ |
| 2087 |
g_main_loop_quit (subthread_main_loop); |
| 2088 |
} |
| 2031 |
|
2089 |
|
| 2032 |
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; |
2090 |
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; |
| 2033 |
} |
2091 |
} |
| 2034 |
|
2092 |
|
| 2035 |
|
|
|
| 2036 |
static gpointer |
2093 |
static gpointer |
| 2037 |
vfs_init (struct fuse_conn_info *conn) |
2094 |
vfs_init (struct fuse_conn_info *conn) |
| 2038 |
{ |
2095 |
{ |
|
Lines 2046-2052
vfs_init (struct fuse_conn_info *conn)
Link Here
|
| 2046 |
|
2103 |
|
| 2047 |
mount_list_mutex = g_mutex_new (); |
2104 |
mount_list_mutex = g_mutex_new (); |
| 2048 |
global_fh_table = g_hash_table_new_full (g_str_hash, g_str_equal, |
2105 |
global_fh_table = g_hash_table_new_full (g_str_hash, g_str_equal, |
| 2049 |
g_free, (GDestroyNotify) file_handle_free); |
2106 |
NULL, (GDestroyNotify) file_handle_free); |
| 2050 |
|
2107 |
|
| 2051 |
dbus_error_init (&error); |
2108 |
dbus_error_init (&error); |
| 2052 |
|
2109 |
|
|
Lines 2059-2064
vfs_init (struct fuse_conn_info *conn)
Link Here
|
| 2059 |
return NULL; |
2116 |
return NULL; |
| 2060 |
} |
2117 |
} |
| 2061 |
|
2118 |
|
|
|
2119 |
dbus_connection_set_exit_on_disconnect (dbus_conn, FALSE); |
| 2120 |
|
| 2062 |
_g_dbus_connection_integrate_with_main (dbus_conn); |
2121 |
_g_dbus_connection_integrate_with_main (dbus_conn); |
| 2063 |
|
2122 |
|
| 2064 |
dbus_bus_add_match (dbus_conn, |
2123 |
dbus_bus_add_match (dbus_conn, |