View | Details | Raw Unified | Return to bug 368628
Collapse All | Expand All

(-)gvfs-0.2.3-pre/client/gdaemonfile.c (+2 lines)
Lines 1892-1897 g_daemon_file_set_attribute (GFile *file Link Here
1892
				   NULL, NULL, NULL,
1892
				   NULL, NULL, NULL,
1893
				   cancellable, &my_error);
1893
				   cancellable, &my_error);
1894
1894
1895
  dbus_message_unref (message);
1896
1895
  if (reply == NULL)
1897
  if (reply == NULL)
1896
    {
1898
    {
1897
      if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY))
1899
      if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY))
(-)gvfs-0.2.3-pre/client/gdaemonvfs.c (+9 lines)
Lines 298-303 g_daemon_vfs_init (GDaemonVfs *vfs) Link Here
298
  
298
  
299
  vfs->wrapped_vfs = g_vfs_get_local ();
299
  vfs->wrapped_vfs = g_vfs_get_local ();
300
300
301
  dbus_connection_set_exit_on_disconnect (vfs->async_bus, FALSE);
302
301
  _g_dbus_connection_integrate_with_main (vfs->async_bus);
303
  _g_dbus_connection_integrate_with_main (vfs->async_bus);
302
304
303
  modules = g_io_modules_load_all_in_directory (GVFS_MODULE_DIR);
305
  modules = g_io_modules_load_all_in_directory (GVFS_MODULE_DIR);
Lines 950-955 void g_vfs_uri_mapper_sftp_register (GIO Link Here
950
void
952
void
951
g_io_module_load (GIOModule *module)
953
g_io_module_load (GIOModule *module)
952
{
954
{
955
 /* This is so that system daemons can use gio
956
  * without spawning private dbus instances.
957
  * See bug 526454.
958
  */
959
  if (g_getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL)
960
    return;
961
953
  g_daemon_vfs_register_type (G_TYPE_MODULE (module));
962
  g_daemon_vfs_register_type (G_TYPE_MODULE (module));
954
  g_daemon_volume_monitor_register_types (G_TYPE_MODULE (module));
963
  g_daemon_volume_monitor_register_types (G_TYPE_MODULE (module));
955
964
(-)gvfs-0.2.3-pre/client/gvfsfusedaemon.c (-40 / +99 lines)
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,
(-)gvfs-0.2.3-pre/common/gmounttracker.c (-1 / +2 lines)
Lines 236-242 g_mount_tracker_finalize (GObject *objec Link Here
236
236
237
  tracker = G_MOUNT_TRACKER (object);
237
  tracker = G_MOUNT_TRACKER (object);
238
238
239
  g_mutex_free (tracker->lock);
239
  if (tracker->lock)
240
    g_mutex_free (tracker->lock);
240
  
241
  
241
  g_list_foreach (tracker->mounts,
242
  g_list_foreach (tracker->mounts,
242
		  (GFunc)g_mount_info_unref, NULL);
243
		  (GFunc)g_mount_info_unref, NULL);
(-)gvfs-0.2.3-pre/configure.ac (-1 / +1 lines)
Lines 58-64 DBUS_SERVICE_DIR=$with_dbus_service_dir Link Here
58
AC_SUBST(DBUS_SERVICE_DIR)
58
AC_SUBST(DBUS_SERVICE_DIR)
59
59
60
dnl **** gio module path handling ****
60
dnl **** gio module path handling ****
61
giomodulesdir=`pkg-config --variable=giomoduledir gio-2.0`
61
giomodulesdir=`pkg-config --define-variable=libdir=$libdir --variable=giomoduledir gio-2.0`
62
AC_SUBST(giomodulesdir)
62
AC_SUBST(giomodulesdir)
63
63
64
dnl ****************************
64
dnl ****************************
(-)gvfs-0.2.3-pre/daemon/gvfsbackendarchive.c (-5 / +33 lines)
Lines 322-327 create_root_file (GVfsBackendArchive *ba Link Here
322
  g_file_info_set_content_type (info, "inode/directory");
322
  g_file_info_set_content_type (info, "inode/directory");
323
  g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE, "inode/directory");
323
  g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE, "inode/directory");
324
324
325
  g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE);
326
  g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE);
327
  g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
328
  g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE, TRUE);
329
  g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
330
  g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, FALSE);
331
325
  icon = g_themed_icon_new ("folder");
332
  icon = g_themed_icon_new ("folder");
326
  g_file_info_set_icon (info, icon);
333
  g_file_info_set_icon (info, icon);
327
  g_object_unref (icon);
334
  g_object_unref (icon);
Lines 340-358 archive_file_set_info_from_entry (Archiv Link Here
340
  g_file_info_set_attribute_uint64 (info,
347
  g_file_info_set_attribute_uint64 (info,
341
				    G_FILE_ATTRIBUTE_TIME_ACCESS,
348
				    G_FILE_ATTRIBUTE_TIME_ACCESS,
342
				    archive_entry_atime (entry));
349
				    archive_entry_atime (entry));
343
  g_file_info_set_attribute_uint64 (info,
350
  g_file_info_set_attribute_uint32 (info,
344
				    G_FILE_ATTRIBUTE_TIME_ACCESS_USEC,
351
				    G_FILE_ATTRIBUTE_TIME_ACCESS_USEC,
345
				    archive_entry_atime_nsec (entry) / 1000);
352
				    archive_entry_atime_nsec (entry) / 1000);
346
  g_file_info_set_attribute_uint64 (info,
353
  g_file_info_set_attribute_uint64 (info,
347
				    G_FILE_ATTRIBUTE_TIME_CHANGED,
354
				    G_FILE_ATTRIBUTE_TIME_CHANGED,
348
				    archive_entry_ctime (entry));
355
				    archive_entry_ctime (entry));
349
  g_file_info_set_attribute_uint64 (info,
356
  g_file_info_set_attribute_uint32 (info,
350
				    G_FILE_ATTRIBUTE_TIME_CHANGED_USEC,
357
				    G_FILE_ATTRIBUTE_TIME_CHANGED_USEC,
351
				    archive_entry_ctime_nsec (entry) / 1000);
358
				    archive_entry_ctime_nsec (entry) / 1000);
352
  g_file_info_set_attribute_uint64 (info,
359
  g_file_info_set_attribute_uint64 (info,
353
				    G_FILE_ATTRIBUTE_TIME_MODIFIED,
360
				    G_FILE_ATTRIBUTE_TIME_MODIFIED,
354
				    archive_entry_mtime (entry));
361
				    archive_entry_mtime (entry));
355
  g_file_info_set_attribute_uint64 (info,
362
  g_file_info_set_attribute_uint32 (info,
356
				    G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC,
363
				    G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC,
357
				    archive_entry_mtime_nsec (entry) / 1000);
364
				    archive_entry_mtime_nsec (entry) / 1000);
358
365
Lines 387-392 archive_file_set_info_from_entry (Archiv Link Here
387
  g_file_info_set_size (info,
394
  g_file_info_set_size (info,
388
			archive_entry_size (entry));
395
			archive_entry_size (entry));
389
396
397
  g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE);
398
  g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE);
399
  g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
400
  g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE, type == G_FILE_TYPE_DIRECTORY);
401
  g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
402
  g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, FALSE);
403
390
  /* FIXME: add info for these
404
  /* FIXME: add info for these
391
dev_t			 archive_entry_dev(struct archive_entry *);
405
dev_t			 archive_entry_dev(struct archive_entry *);
392
dev_t			 archive_entry_devmajor(struct archive_entry *);
406
dev_t			 archive_entry_devmajor(struct archive_entry *);
Lines 508-518 do_mount (GVfsBackend *backend, Link Here
508
          return;
522
          return;
509
        }
523
        }
510
      
524
      
511
      archive->file = g_file_new_for_uri (filename);
525
      archive->file = g_file_new_for_commandline_arg (filename);
512
      g_free (filename);
526
      g_free (filename);
513
    }
527
    }
514
  else
528
  else
515
    archive->file = g_file_new_for_uri (file);
529
    archive->file = g_file_new_for_commandline_arg (file);
516
  
530
  
517
  DEBUG ("Trying to mount %s\n", g_file_get_uri (archive->file));
531
  DEBUG ("Trying to mount %s\n", g_file_get_uri (archive->file));
518
532
Lines 714-719 do_enumerate (GVfsBackend *backend, Link Here
714
  g_vfs_job_succeeded (G_VFS_JOB (job));
728
  g_vfs_job_succeeded (G_VFS_JOB (job));
715
}
729
}
716
730
731
static gboolean
732
try_query_fs_info (GVfsBackend *backend,
733
                   GVfsJobQueryFsInfo *job,
734
                   const char *filename,
735
                   GFileInfo *info,
736
                   GFileAttributeMatcher *attribute_matcher)
737
{
738
  g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, TRUE);
739
  g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_FILESYSTEM_USE_PREVIEW, G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL);
740
  g_vfs_job_succeeded (G_VFS_JOB (job));
741
  return TRUE;
742
}
743
717
static void
744
static void
718
g_vfs_backend_archive_class_init (GVfsBackendArchiveClass *klass)
745
g_vfs_backend_archive_class_init (GVfsBackendArchiveClass *klass)
719
{
746
{
Lines 729-732 g_vfs_backend_archive_class_init (GVfsBa Link Here
729
  backend_class->read = do_read;
756
  backend_class->read = do_read;
730
  backend_class->enumerate = do_enumerate;
757
  backend_class->enumerate = do_enumerate;
731
  backend_class->query_info = do_query_info;
758
  backend_class->query_info = do_query_info;
759
  backend_class->try_query_fs_info = try_query_fs_info;
732
}
760
}
(-)gvfs-0.2.3-pre/daemon/gvfsbackenddav.c (+2 lines)
Lines 1409-1414 g_mount_spec_from_dav_uri (SoupURI *uri) Link Here
1409
      g_free (port);
1409
      g_free (port);
1410
    }
1410
    }
1411
1411
1412
  g_mount_spec_set_mount_prefix (spec, uri->path);
1413
1412
  return spec;
1414
  return spec;
1413
}
1415
}
1414
1416
(-)gvfs-0.2.3-pre/daemon/gvfsbackendftp.c (-7 / +82 lines)
Lines 135-140 G_DEFINE_TYPE (GVfsBackendFtp, g_vfs_bac Link Here
135
135
136
#define STATUS_GROUP(status) ((status) / 100)
136
#define STATUS_GROUP(status) ((status) / 100)
137
137
138
typedef void (* Ftp550Handler) (FtpConnection *conn, const FtpFile *file);
139
138
/*** FTP CONNECTION ***/
140
/*** FTP CONNECTION ***/
139
141
140
struct _FtpConnection
142
struct _FtpConnection
Lines 250-257 ftp_connection_set_error_from_response ( Link Here
250
      case 550: /* Requested action not taken. File unavailable (e.g., file not found, no access). */
252
      case 550: /* Requested action not taken. File unavailable (e.g., file not found, no access). */
251
	/* FIXME: This is a lot of different errors. So we have to pretend to 
253
	/* FIXME: This is a lot of different errors. So we have to pretend to 
252
	 * be smart here. */
254
	 * be smart here. */
253
	code = G_IO_ERROR_NOT_FOUND;
255
	code = G_IO_ERROR_FAILED;
254
	msg = _("File unavailable");
256
	msg = _("Operation failed");
255
	break;
257
	break;
256
      case 451: /* Requested action aborted: local error in processing. */
258
      case 451: /* Requested action aborted: local error in processing. */
257
	code = G_IO_ERROR_FAILED;
259
	code = G_IO_ERROR_FAILED;
Lines 298-303 ftp_connection_set_error_from_response ( Link Here
298
 * RESPONSE_PASS_300: Don't treat 3XX responses, but return them
300
 * RESPONSE_PASS_300: Don't treat 3XX responses, but return them
299
 * RESPONSE_PASS_400: Don't treat 4XX responses, but return them
301
 * RESPONSE_PASS_400: Don't treat 4XX responses, but return them
300
 * RESPONSE_PASS_500: Don't treat 5XX responses, but return them
302
 * RESPONSE_PASS_500: Don't treat 5XX responses, but return them
303
 * RESPONSE_PASS_550: Don't treat 550 responses, but return them
301
 * RESPONSE_FAIL_200: Fail on a 2XX response
304
 * RESPONSE_FAIL_200: Fail on a 2XX response
302
 */
305
 */
303
306
Lines 306-312 typedef enum { Link Here
306
  RESPONSE_PASS_300 = (1 << 1),
309
  RESPONSE_PASS_300 = (1 << 1),
307
  RESPONSE_PASS_400 = (1 << 2),
310
  RESPONSE_PASS_400 = (1 << 2),
308
  RESPONSE_PASS_500 = (1 << 3),
311
  RESPONSE_PASS_500 = (1 << 3),
309
  RESPONSE_FAIL_200 = (1 << 4)
312
  RESPONSE_PASS_550 = (1 << 4),
313
  RESPONSE_FAIL_200 = (1 << 5)
310
} ResponseFlags;
314
} ResponseFlags;
311
315
312
/**
316
/**
Lines 460-466 ftp_connection_receive (FtpConnection *c Link Here
460
	return 0;
464
	return 0;
461
	break;
465
	break;
462
      case 5:
466
      case 5:
463
	if (flags & RESPONSE_PASS_500)
467
	if ((flags & RESPONSE_PASS_500) || (response == 550 && (flags & RESPONSE_PASS_550)))
464
	  break;
468
	  break;
465
	ftp_connection_set_error_from_response (conn, response);
469
	ftp_connection_set_error_from_response (conn, response);
466
	return 0;
470
	return 0;
Lines 565-570 ftp_connection_send (FtpConnection *conn Link Here
565
}
569
}
566
570
567
static void
571
static void
572
ftp_connection_check_file (FtpConnection *conn,
573
                           const Ftp550Handler *handlers,
574
                           const FtpFile *file)
575
{
576
  while (*handlers && !ftp_connection_in_error (conn))
577
    {
578
      (*handlers) (conn, file);
579
      handlers++;
580
    }
581
}
582
583
static guint
584
ftp_connection_send_and_check (FtpConnection *conn,
585
                               ResponseFlags flags,
586
                               const Ftp550Handler *handlers,
587
                               const FtpFile *file,
588
                               const char *format,
589
                               ...) G_GNUC_PRINTF (5, 6);
590
static guint
591
ftp_connection_send_and_check (FtpConnection *conn,
592
                               ResponseFlags flags,
593
                               const Ftp550Handler *handlers,
594
                               const FtpFile *file,
595
                               const char *format,
596
                               ...)
597
{
598
  va_list varargs;
599
  guint response;
600
601
  /* check that there's no 550 handling used - don't allow bad use of API */
602
  g_return_val_if_fail ((flags & RESPONSE_PASS_550) == 0, 0);
603
  g_return_val_if_fail (handlers != NULL, 0);
604
  g_return_val_if_fail (file != NULL, 0);
605
606
  va_start (varargs, format);
607
  response = ftp_connection_sendv (conn,
608
                                   flags | RESPONSE_PASS_550,
609
                                   format,
610
                                   varargs);
611
  va_end (varargs);
612
  if (response == 550)
613
    {
614
      ftp_connection_check_file (conn, handlers, file);
615
      if (!ftp_connection_in_error (conn))
616
          ftp_connection_set_error_from_response (conn, response);
617
      response = 0;
618
    }
619
  return response;
620
}
621
622
static void
568
ftp_connection_parse_features (FtpConnection *conn)
623
ftp_connection_parse_features (FtpConnection *conn)
569
{
624
{
570
  struct {
625
  struct {
Lines 1462-1467 do_unmount (GVfsBackend * backend, Link Here
1462
}
1517
}
1463
1518
1464
static void
1519
static void
1520
error_550_is_directory (FtpConnection *conn, const FtpFile *file)
1521
{
1522
  guint response = ftp_connection_send (conn, 
1523
                                        RESPONSE_PASS_550,
1524
                                        "CWD %s", file);
1525
1526
  if (STATUS_GROUP (response) == 2)
1527
    {
1528
      g_set_error (&conn->error, G_IO_ERROR, 
1529
                   G_IO_ERROR_IS_DIRECTORY,
1530
                   _("File is directory"));
1531
    }
1532
}
1533
1534
static void
1465
do_open_for_read (GVfsBackend *backend,
1535
do_open_for_read (GVfsBackend *backend,
1466
		  GVfsJobOpenForRead *job,
1536
		  GVfsJobOpenForRead *job,
1467
		  const char *filename)
1537
		  const char *filename)
Lines 1469-1474 do_open_for_read (GVfsBackend *backend, Link Here
1469
  GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
1539
  GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend);
1470
  FtpConnection *conn;
1540
  FtpConnection *conn;
1471
  FtpFile *file;
1541
  FtpFile *file;
1542
  static const Ftp550Handler open_read_handlers[] = { error_550_is_directory, NULL };
1472
1543
1473
  conn = g_vfs_backend_ftp_pop_connection (ftp, G_VFS_JOB (job));
1544
  conn = g_vfs_backend_ftp_pop_connection (ftp, G_VFS_JOB (job));
1474
  if (!conn)
1545
  if (!conn)
Lines 1477-1485 do_open_for_read (GVfsBackend *backend, Link Here
1477
  ftp_connection_ensure_data_connection (conn);
1548
  ftp_connection_ensure_data_connection (conn);
1478
1549
1479
  file = ftp_filename_from_gvfs_path (conn, filename);
1550
  file = ftp_filename_from_gvfs_path (conn, filename);
1480
  ftp_connection_send (conn,
1551
  ftp_connection_send_and_check (conn,
1481
		       RESPONSE_PASS_100 | RESPONSE_FAIL_200,
1552
		                 RESPONSE_PASS_100 | RESPONSE_FAIL_200, 
1482
		       "RETR %s", file);
1553
		                 &open_read_handlers[0],
1554
		                 file,
1555
		                 "RETR %s", file);
1483
  g_free (file);
1556
  g_free (file);
1484
1557
1485
  if (ftp_connection_in_error (conn))
1558
  if (ftp_connection_in_error (conn))
Lines 1782-1787 do_enumerate_directory (FtpConnection *c Link Here
1782
	    if (got_boundary)
1855
	    if (got_boundary)
1783
	      {
1856
	      {
1784
		name[bytes_read - 1] = 0;
1857
		name[bytes_read - 1] = 0;
1858
		if (bytes_read >= 2 && name[bytes_read - 2] == '\r') 
1859
				name[bytes_read - 2] = 0;
1785
		DEBUG ("--- %s\n", name);
1860
		DEBUG ("--- %s\n", name);
1786
		list = g_list_prepend (list, g_strdup (name));
1861
		list = g_list_prepend (list, g_strdup (name));
1787
		bytes_read = 0;
1862
		bytes_read = 0;
(-)gvfs-0.2.3-pre/daemon/gvfsbackendgphoto2.c (+2 lines)
Lines 1394-1399 do_mount (GVfsBackend *backend, Link Here
1394
      return;
1394
      return;
1395
    }
1395
    }
1396
  
1396
  
1397
  dbus_connection_set_exit_on_disconnect (gphoto2_backend->dbus_connection, FALSE);
1398
1397
  gphoto2_backend->hal_ctx = libhal_ctx_new ();
1399
  gphoto2_backend->hal_ctx = libhal_ctx_new ();
1398
  if (gphoto2_backend->hal_ctx == NULL)
1400
  if (gphoto2_backend->hal_ctx == NULL)
1399
    {
1401
    {
(-)gvfs-0.2.3-pre/daemon/gvfsbackendhttp.c (+26 lines)
Lines 75-83 g_vfs_backend_http_finalize (GObject *ob Link Here
75
    (*G_OBJECT_CLASS (g_vfs_backend_http_parent_class)->finalize) (object);
75
    (*G_OBJECT_CLASS (g_vfs_backend_http_parent_class)->finalize) (object);
76
}
76
}
77
77
78
#define DEBUG_MAX_BODY_SIZE (100 * 1024 * 1024)
79
78
static void
80
static void
79
g_vfs_backend_http_init (GVfsBackendHttp *backend)
81
g_vfs_backend_http_init (GVfsBackendHttp *backend)
80
{
82
{
83
   const char         *debug;
84
81
  g_vfs_backend_set_user_visible (G_VFS_BACKEND (backend), FALSE);  
85
  g_vfs_backend_set_user_visible (G_VFS_BACKEND (backend), FALSE);  
82
86
83
  backend->session = soup_session_sync_new_with_options ("user-agent",
87
  backend->session = soup_session_sync_new_with_options ("user-agent",
Lines 87-92 g_vfs_backend_http_init (GVfsBackendHttp Link Here
87
  backend->session_async = soup_session_async_new_with_options ("user-agent",
91
  backend->session_async = soup_session_async_new_with_options ("user-agent",
88
                                                                "gvfs/" VERSION,
92
                                                                "gvfs/" VERSION,
89
                                                                NULL);
93
                                                                NULL);
94
95
  /* Logging */
96
  debug = g_getenv ("GVFS_HTTP_DEBUG");
97
  if (debug)
98
    {
99
      SoupLogger         *logger;
100
      SoupLoggerLogLevel  level;
101
102
      if (g_ascii_strcasecmp (debug, "all") ||
103
          g_ascii_strcasecmp (debug, "body"))
104
        level = SOUP_LOGGER_LOG_BODY;
105
      else if (g_ascii_strcasecmp (debug, "header"))
106
        level = SOUP_LOGGER_LOG_HEADERS;
107
      else
108
        level = SOUP_LOGGER_LOG_MINIMAL;
109
110
      logger = soup_logger_new (level, DEBUG_MAX_BODY_SIZE);
111
      soup_logger_attach (logger, backend->session);
112
      soup_logger_attach (logger, backend->session_async);
113
      g_object_unref (logger);
114
    }
115
90
}
116
}
91
117
92
/* ************************************************************************* */
118
/* ************************************************************************* */
(-)gvfs-0.2.3-pre/daemon/gvfsbackendsmb.c (-2 / +18 lines)
Lines 612-628 do_open_for_read (GVfsBackend *backend, Link Here
612
  GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
612
  GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend);
613
  char *uri;
613
  char *uri;
614
  SMBCFILE *file;
614
  SMBCFILE *file;
615
  struct stat st;
615
  smbc_open_fn smbc_open;
616
  smbc_open_fn smbc_open;
617
  smbc_stat_fn smbc_stat;
618
  int res;
619
  int olderr;
620
616
621
617
  uri = create_smb_uri (op_backend->server, op_backend->share, filename);
622
  uri = create_smb_uri (op_backend->server, op_backend->share, filename);
618
  smbc_open = smbc_getFunctionOpen (op_backend->smb_context);
623
  smbc_open = smbc_getFunctionOpen (op_backend->smb_context);
619
  file = smbc_open (op_backend->smb_context, uri, O_RDONLY, 0);
624
  file = smbc_open (op_backend->smb_context, uri, O_RDONLY, 0);
620
  g_free (uri);
621
625
622
  if (file == NULL)
626
  if (file == NULL)
623
    g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
627
    {
628
      olderr = errno;
629
      smbc_stat = smbc_getFunctionStat (op_backend->smb_context);
630
      res = smbc_stat (op_backend->smb_context, uri, &st);
631
      g_free (uri);
632
      if ((res == 0) && (S_ISDIR (st.st_mode)))
633
            g_vfs_job_failed (G_VFS_JOB (job),
634
                              G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY,
635
                             _("Can't open directory"));
636
      else
637
        g_vfs_job_failed_from_errno (G_VFS_JOB (job), olderr);
638
  }
624
  else
639
  else
625
    {
640
    {
641
      
626
      g_vfs_job_open_for_read_set_can_seek (job, TRUE);
642
      g_vfs_job_open_for_read_set_can_seek (job, TRUE);
627
      g_vfs_job_open_for_read_set_handle (job, file);
643
      g_vfs_job_open_for_read_set_handle (job, file);
628
      g_vfs_job_succeeded (G_VFS_JOB (job));
644
      g_vfs_job_succeeded (G_VFS_JOB (job));
(-)gvfs-0.2.3-pre/daemon/gvfsbackendtrash.c (-17 / +32 lines)
Lines 148-164 escape_pathname (const char *dir) Link Here
148
  while (*dir == '/')
148
  while (*dir == '/')
149
    dir++;
149
    dir++;
150
150
151
  /* Underscores are doubled, count them */
151
  /* count characters that need to be escaped. */
152
  count = 0;
152
  count = 0;
153
  p = dir;
153
  p = dir;
154
  while (*p)
154
  while (*p)
155
    {
155
    {
156
      if (*p == '_')
156
      if (*p == '_')
157
        count++;
157
        count++;
158
      if (*p == '/')
159
        count++;
160
      if (*p == '%')
161
        count++;
158
      p++;
162
      p++;
159
    }
163
    }
160
  
164
  
161
  res = g_malloc (strlen (dir) + count + 1);
165
  res = g_malloc (strlen (dir) + count*2 + 1);
162
  
166
  
163
  p = dir;
167
  p = dir;
164
  d = res;
168
  d = res;
Lines 167-184 escape_pathname (const char *dir) Link Here
167
      c = *p++;
171
      c = *p++;
168
      if (c == '_')
172
      if (c == '_')
169
        {
173
        {
170
          *d++ = '_';
174
          *d++ = '%';
171
          *d++ = '_';
175
          *d++ = '5';
176
          *d++ = 'f';
172
        }
177
        }
173
      else if (c == '/')
178
      else if (c == '/')
174
        {
179
        {
175
          *d++ = '_';
180
          *d++ = '%';
181
          *d++ = '2';
182
          *d++ = 'f';
176
          
183
          
177
          /* Skip consecutive slashes, they are unnecessary,
184
          /* Skip consecutive slashes, they are unnecessary,
178
             and break our escaping */
185
             and break our escaping */
179
          while (*p == '/')
186
          while (*p == '/')
180
            p++;
187
            p++;
181
        }
188
        }
189
      else if (c == '%')
190
        {
191
          *d++ = '%';
192
          *d++ = '2';
193
          *d++ = '5';
194
        }
182
      else
195
      else
183
        *d++ = c;
196
        *d++ = c;
184
    }
197
    }
Lines 216-235 unescape_pathname (const char *escaped_d Link Here
216
  while (p < end)
229
  while (p < end)
217
    {
230
    {
218
      c = *p++;
231
      c = *p++;
219
      if (c == '_')
232
      if (c == '%' && p < (end-1))
220
        {
233
        {
221
          if (p == end)
234
          if (*(p) == '2' && *(p+1) == 'f')
222
            *d++ = '_';
223
          else
224
            {
235
            {
225
              c = *p;
236
              *d++ = '/';
226
              if (c == '_')
237
              p+=2;
227
                {
238
            }
228
                  p++;
239
          else if (*(p) == '2' && *(p+1) == '5')
229
                  *d++ = '_';
240
            {
230
                }
241
              *d++ = '%';
231
              else
242
              p+=2;
232
                *d++ = '/';
243
            }
244
          else if (*(p) == '5' && *(p+1) == 'f')
245
            {
246
              *d++ = '_';
247
              p+=2;
233
            }
248
            }
234
        }
249
        }
235
      else
250
      else
(-)gvfs-0.2.3-pre/hal/ghalvolumemonitor.c (-1 / +46 lines)
Lines 845-850 get_mount_point_for_device (HalDevice *d Link Here
845
}
845
}
846
846
847
static gboolean
847
static gboolean
848
should_mount_be_ignored (HalPool *pool, HalDevice *d)
849
{
850
  const char *device_mount_point;
851
852
  device_mount_point = hal_device_get_property_string (d, "volume.mount_point");
853
  if (device_mount_point != NULL && strlen (device_mount_point) > 0)
854
    {
855
      GUnixMountEntry *mount_entry;
856
857
      /*g_warning ("device_mount_point = '%s'", device_mount_point);*/
858
859
      mount_entry = g_unix_mount_at (device_mount_point, NULL);
860
      if (mount_entry != NULL) {
861
        if (!g_unix_mount_guess_should_display (mount_entry))
862
          {
863
            g_unix_mount_free (mount_entry);
864
            return TRUE;
865
          }
866
        g_unix_mount_free (mount_entry);
867
      }
868
    }
869
870
  return FALSE;
871
}
872
873
static gboolean
848
should_volume_be_ignored (HalPool *pool, HalDevice *d, GList *fstab_mount_points)
874
should_volume_be_ignored (HalPool *pool, HalDevice *d, GList *fstab_mount_points)
849
{
875
{
850
  gboolean volume_ignore;
876
  gboolean volume_ignore;
Lines 893-898 should_volume_be_ignored (HalPool *pool, Link Here
893
  if (mount_point != NULL && !_g_unix_mount_point_guess_should_display (mount_point))
919
  if (mount_point != NULL && !_g_unix_mount_point_guess_should_display (mount_point))
894
    return TRUE;
920
    return TRUE;
895
921
922
  if (hal_device_get_property_bool (d, "volume.is_mounted"))
923
    return should_mount_be_ignored (pool, d);
924
896
  return FALSE;
925
  return FALSE;
897
}
926
}
898
927
Lines 1207-1219 update_mounts (GHalVolumeMonitor *monito Link Here
1207
{
1236
{
1208
  GList *new_mounts;
1237
  GList *new_mounts;
1209
  GList *removed, *added;
1238
  GList *removed, *added;
1210
  GList *l;
1239
  GList *l, *ll;
1211
  GHalMount *mount;
1240
  GHalMount *mount;
1212
  GHalVolume *volume;
1241
  GHalVolume *volume;
1213
  const char *device_path;
1242
  const char *device_path;
1214
  const char *mount_path;
1243
  const char *mount_path;
1215
  
1244
  
1216
  new_mounts = g_unix_mounts_get (NULL);
1245
  new_mounts = g_unix_mounts_get (NULL);
1246
1247
  /* remove mounts we want to ignore - we do it here so we get to reevaluate
1248
   * on the next update whether they should still be ignored
1249
   */
1250
  for (l = new_mounts; l != NULL; l = ll)
1251
    {
1252
      GUnixMountEntry *mount_entry = l->data;
1253
      ll = l->next;
1254
1255
      /* keep in sync with should_mount_be_ignored() */
1256
      if (!g_unix_mount_guess_should_display (mount_entry))
1257
        {
1258
          g_unix_mount_free (mount_entry);
1259
          new_mounts = g_list_delete_link (new_mounts, l);
1260
        }
1261
    }
1217
  
1262
  
1218
  new_mounts = g_list_sort (new_mounts, (GCompareFunc) g_unix_mount_compare);
1263
  new_mounts = g_list_sort (new_mounts, (GCompareFunc) g_unix_mount_compare);
1219
  
1264
  
(-)gvfs-0.2.3-pre/hal/hal-device.c (-1 / +1 lines)
Lines 245-251 hal_device_new_from_udi_and_properties ( Link Here
245
  HalDevice *device;
245
  HalDevice *device;
246
  
246
  
247
  device = HAL_DEVICE (g_object_new (HAL_TYPE_DEVICE, NULL));
247
  device = HAL_DEVICE (g_object_new (HAL_TYPE_DEVICE, NULL));
248
  device->priv->udi = udi;
248
  device->priv->udi = g_strdup (udi);
249
  device->priv->hal_ctx = hal_ctx;
249
  device->priv->hal_ctx = hal_ctx;
250
  device->priv->properties = properties;
250
  device->priv->properties = properties;
251
  return device;
251
  return device;
(-)gvfs-0.2.3-pre/hal/hal-pool.c (-3 / +4 lines)
Lines 308-313 hal_pool_new (char **cap_only) Link Here
308
      goto out;
308
      goto out;
309
    }
309
    }
310
  
310
  
311
  dbus_connection_set_exit_on_disconnect (dbus_connection, FALSE);
312
311
  hal_ctx = libhal_ctx_new ();
313
  hal_ctx = libhal_ctx_new ();
312
  if (hal_ctx == NULL)
314
  if (hal_ctx == NULL)
313
    {
315
    {
Lines 359-367 hal_pool_new (char **cap_only) Link Here
359
    {
361
    {
360
      for (i = 0; i < num_devices; i++)
362
      for (i = 0; i < num_devices; i++)
361
        hal_pool_add_device_by_udi_and_properties (pool, devices[i], properties[i], FALSE);
363
        hal_pool_add_device_by_udi_and_properties (pool, devices[i], properties[i], FALSE);
362
      /* _add_device_by_udi_and_properties steals the given parameters */
364
      libhal_free_string_array (devices);
363
      free (devices);
365
      free (properties); /* hal_pool_add_device_by_udi_and_properties steals the given properties */
364
      free (properties);
365
      goto out;
366
      goto out;
366
    }
367
    }
367
#endif
368
#endif

Return to bug 368628