mountmgr: Add support for UDisks2.
This commit is contained in:
parent
2f86012373
commit
2ffc57821f
|
@ -66,6 +66,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mountmgr);
|
|||
DO_FUNC(dbus_message_iter_append_basic); \
|
||||
DO_FUNC(dbus_message_iter_get_arg_type); \
|
||||
DO_FUNC(dbus_message_iter_get_basic); \
|
||||
DO_FUNC(dbus_message_iter_get_fixed_array); \
|
||||
DO_FUNC(dbus_message_iter_init); \
|
||||
DO_FUNC(dbus_message_iter_init_append); \
|
||||
DO_FUNC(dbus_message_iter_next); \
|
||||
|
@ -364,6 +365,161 @@ static BOOL udisks_enumerate_devices(void)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* to make things easier, UDisks2 stores strings as array of bytes instead of strings... */
|
||||
static const char *udisks2_string_from_array( DBusMessageIter *iter )
|
||||
{
|
||||
DBusMessageIter string;
|
||||
const char *array;
|
||||
int size;
|
||||
|
||||
p_dbus_message_iter_recurse( iter, &string );
|
||||
p_dbus_message_iter_get_fixed_array( &string, &array, &size );
|
||||
return array;
|
||||
}
|
||||
|
||||
/* find the drive entry in the dictionary and get its parameters */
|
||||
static void udisks2_get_drive_info( const char *drive_name, DBusMessageIter *dict,
|
||||
enum device_type *drive_type, int *removable )
|
||||
{
|
||||
DBusMessageIter iter, drive, variant;
|
||||
const char *name;
|
||||
|
||||
p_dbus_message_iter_recurse( dict, &iter );
|
||||
while ((name = udisks_next_dict_entry( &iter, &drive )))
|
||||
{
|
||||
if (strcmp( name, drive_name )) continue;
|
||||
while ((name = udisks_next_dict_entry( &drive, &iter )))
|
||||
{
|
||||
if (strcmp( name, "org.freedesktop.UDisks2.Drive" )) continue;
|
||||
while ((name = udisks_next_dict_entry( &iter, &variant )))
|
||||
{
|
||||
if (!strcmp( name, "Removable" ))
|
||||
p_dbus_message_iter_get_basic( &variant, removable );
|
||||
else if (!strcmp( name, "MediaCompatibility" ))
|
||||
*drive_type = udisks_parse_media_compatibility( &variant );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void udisks2_add_device( const char *udi, DBusMessageIter *dict, DBusMessageIter *block )
|
||||
{
|
||||
DBusMessageIter iter, variant, paths, string;
|
||||
const char *device = NULL;
|
||||
const char *mount_point = NULL;
|
||||
const char *type = NULL;
|
||||
const char *drive = NULL;
|
||||
GUID guid, *guid_ptr = NULL;
|
||||
const char *iface, *name;
|
||||
int removable = FALSE;
|
||||
enum device_type drive_type = DEVICE_UNKNOWN;
|
||||
|
||||
while ((iface = udisks_next_dict_entry( block, &iter )))
|
||||
{
|
||||
if (!strcmp( iface, "org.freedesktop.UDisks2.Filesystem" ))
|
||||
{
|
||||
while ((name = udisks_next_dict_entry( &iter, &variant )))
|
||||
{
|
||||
if (!strcmp( name, "MountPoints" ))
|
||||
{
|
||||
p_dbus_message_iter_recurse( &variant, &paths );
|
||||
if (p_dbus_message_iter_get_arg_type( &paths ) == DBUS_TYPE_ARRAY)
|
||||
{
|
||||
p_dbus_message_iter_recurse( &variant, &string );
|
||||
mount_point = udisks2_string_from_array( &string );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!strcmp( iface, "org.freedesktop.UDisks2.Block" ))
|
||||
{
|
||||
while ((name = udisks_next_dict_entry( &iter, &variant )))
|
||||
{
|
||||
if (!strcmp( name, "Device" ))
|
||||
device = udisks2_string_from_array( &variant );
|
||||
else if (!strcmp( name, "IdType" ))
|
||||
p_dbus_message_iter_get_basic( &variant, &type );
|
||||
else if (!strcmp( name, "Drive" ))
|
||||
{
|
||||
p_dbus_message_iter_get_basic( &variant, &drive );
|
||||
udisks2_get_drive_info( drive, dict, &drive_type, &removable );
|
||||
}
|
||||
else if (!strcmp( name, "IdUUID" ))
|
||||
{
|
||||
char *uuid_str;
|
||||
p_dbus_message_iter_get_basic( &variant, &uuid_str );
|
||||
guid_ptr = parse_uuid( &guid, uuid_str );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TRACE( "udi %s device %s mount point %s uuid %s type %s removable %u\n",
|
||||
debugstr_a(udi), debugstr_a(device), debugstr_a(mount_point),
|
||||
debugstr_guid(guid_ptr), debugstr_a(type), removable );
|
||||
|
||||
if (type)
|
||||
{
|
||||
if (!strcmp( type, "iso9660" ))
|
||||
{
|
||||
removable = TRUE;
|
||||
drive_type = DEVICE_CDROM;
|
||||
}
|
||||
else if (!strcmp( type, "udf" ))
|
||||
{
|
||||
removable = TRUE;
|
||||
drive_type = DEVICE_DVD;
|
||||
}
|
||||
}
|
||||
if (device)
|
||||
{
|
||||
if (removable) add_dos_device( -1, udi, device, mount_point, drive_type, guid_ptr );
|
||||
else if (guid_ptr) add_volume( udi, device, mount_point, DEVICE_HARDDISK_VOL, guid_ptr );
|
||||
}
|
||||
}
|
||||
|
||||
/* UDisks2 is almost, but not quite, entirely unlike UDisks.
|
||||
* It would have been easy to make it backwards compatible, but where would be the fun in that?
|
||||
*/
|
||||
static BOOL udisks2_add_devices( const char *changed )
|
||||
{
|
||||
DBusMessage *request, *reply;
|
||||
DBusMessageIter dict, iter, block;
|
||||
DBusError error;
|
||||
const char *udi;
|
||||
|
||||
request = p_dbus_message_new_method_call( "org.freedesktop.UDisks2", "/org/freedesktop/UDisks2",
|
||||
"org.freedesktop.DBus.ObjectManager", "GetManagedObjects" );
|
||||
if (!request) return FALSE;
|
||||
|
||||
p_dbus_error_init( &error );
|
||||
reply = p_dbus_connection_send_with_reply_and_block( connection, request, udisks_timeout, &error );
|
||||
p_dbus_message_unref( request );
|
||||
if (!reply)
|
||||
{
|
||||
WARN( "failed: %s\n", error.message );
|
||||
p_dbus_error_free( &error );
|
||||
return FALSE;
|
||||
}
|
||||
p_dbus_error_free( &error );
|
||||
|
||||
p_dbus_message_iter_init( reply, &dict );
|
||||
if (p_dbus_message_iter_get_arg_type( &dict ) == DBUS_TYPE_ARRAY)
|
||||
{
|
||||
p_dbus_message_iter_recurse( &dict, &iter );
|
||||
while ((udi = udisks_next_dict_entry( &iter, &block )))
|
||||
{
|
||||
if (!starts_with( udi, "/org/freedesktop/UDisks2/block_devices/" )) continue;
|
||||
if (changed && strcmp( changed, udi )) continue;
|
||||
udisks2_add_device( udi, &dict, &block );
|
||||
}
|
||||
}
|
||||
else WARN( "unexpected args in GetManagedObjects reply\n" );
|
||||
|
||||
p_dbus_message_unref( reply );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static DBusHandlerResult udisks_filter( DBusConnection *ctx, DBusMessage *msg, void *user_data )
|
||||
{
|
||||
char *path;
|
||||
|
@ -371,6 +527,7 @@ static DBusHandlerResult udisks_filter( DBusConnection *ctx, DBusMessage *msg, v
|
|||
|
||||
p_dbus_error_init( &error );
|
||||
|
||||
/* udisks signals */
|
||||
if (p_dbus_message_is_signal( msg, "org.freedesktop.UDisks", "DeviceAdded" ) &&
|
||||
p_dbus_message_get_args( msg, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID ))
|
||||
{
|
||||
|
@ -386,6 +543,24 @@ static DBusHandlerResult udisks_filter( DBusConnection *ctx, DBusMessage *msg, v
|
|||
{
|
||||
udisks_changed_device( path );
|
||||
}
|
||||
/* udisks2 signals */
|
||||
else if (p_dbus_message_is_signal( msg, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded" ) &&
|
||||
p_dbus_message_get_args( msg, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID ))
|
||||
{
|
||||
TRACE( "added %s\n", wine_dbgstr_a(path) );
|
||||
udisks2_add_devices( path );
|
||||
}
|
||||
else if (p_dbus_message_is_signal( msg, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved" ) &&
|
||||
p_dbus_message_get_args( msg, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID ))
|
||||
{
|
||||
udisks_removed_device( path );
|
||||
}
|
||||
else if (p_dbus_message_is_signal( msg, "org.freedesktop.DBus.Properties", "PropertiesChanged" ))
|
||||
{
|
||||
const char *udi = p_dbus_message_get_path( msg );
|
||||
TRACE( "changed %s\n", wine_dbgstr_a(udi) );
|
||||
udisks2_add_devices( udi );
|
||||
}
|
||||
else TRACE( "ignoring message type=%d path=%s interface=%s method=%s\n",
|
||||
p_dbus_message_get_type( msg ), p_dbus_message_get_path( msg ),
|
||||
p_dbus_message_get_interface( msg ), p_dbus_message_get_member( msg ) );
|
||||
|
@ -514,6 +689,12 @@ static DWORD WINAPI dbus_thread( void *arg )
|
|||
static const char udisks_match[] = "type='signal',"
|
||||
"interface='org.freedesktop.UDisks',"
|
||||
"sender='org.freedesktop.UDisks'";
|
||||
static const char udisks2_match_interfaces[] = "type='signal',"
|
||||
"interface='org.freedesktop.DBus.ObjectManager',"
|
||||
"path='/org/freedesktop/UDisks2'";
|
||||
static const char udisks2_match_properties[] = "type='signal',"
|
||||
"interface='org.freedesktop.DBus.Properties'";
|
||||
|
||||
|
||||
DBusError error;
|
||||
|
||||
|
@ -525,23 +706,33 @@ static DWORD WINAPI dbus_thread( void *arg )
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (p_dbus_connection_add_filter( connection, udisks_filter, NULL, NULL ))
|
||||
p_dbus_bus_add_match( connection, udisks_match, &error );
|
||||
/* first try UDisks2 */
|
||||
|
||||
if (!udisks_enumerate_devices())
|
||||
{
|
||||
p_dbus_bus_remove_match( connection, udisks_match, &error );
|
||||
p_dbus_connection_remove_filter( connection, udisks_filter, NULL );
|
||||
p_dbus_connection_add_filter( connection, udisks_filter, NULL, NULL );
|
||||
p_dbus_bus_add_match( connection, udisks2_match_interfaces, &error );
|
||||
p_dbus_bus_add_match( connection, udisks2_match_properties, &error );
|
||||
if (udisks2_add_devices( NULL )) goto found;
|
||||
p_dbus_bus_remove_match( connection, udisks2_match_interfaces, &error );
|
||||
p_dbus_bus_remove_match( connection, udisks2_match_properties, &error );
|
||||
|
||||
/* then try UDisks */
|
||||
|
||||
p_dbus_bus_add_match( connection, udisks_match, &error );
|
||||
if (udisks_enumerate_devices()) goto found;
|
||||
p_dbus_bus_remove_match( connection, udisks_match, &error );
|
||||
p_dbus_connection_remove_filter( connection, udisks_filter, NULL );
|
||||
|
||||
/* then finally HAL */
|
||||
|
||||
#ifdef SONAME_LIBHAL
|
||||
if (!hal_enumerate_devices())
|
||||
{
|
||||
p_dbus_error_free( &error );
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
if (!hal_enumerate_devices())
|
||||
{
|
||||
p_dbus_error_free( &error );
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
found:
|
||||
__TRY
|
||||
{
|
||||
while (p_dbus_connection_read_write_dispatch( connection, -1 )) /* nothing */ ;
|
||||
|
|
Loading…
Reference in New Issue