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_append_basic); \
|
||||||
DO_FUNC(dbus_message_iter_get_arg_type); \
|
DO_FUNC(dbus_message_iter_get_arg_type); \
|
||||||
DO_FUNC(dbus_message_iter_get_basic); \
|
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); \
|
||||||
DO_FUNC(dbus_message_iter_init_append); \
|
DO_FUNC(dbus_message_iter_init_append); \
|
||||||
DO_FUNC(dbus_message_iter_next); \
|
DO_FUNC(dbus_message_iter_next); \
|
||||||
|
@ -364,6 +365,161 @@ static BOOL udisks_enumerate_devices(void)
|
||||||
return TRUE;
|
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 )
|
static DBusHandlerResult udisks_filter( DBusConnection *ctx, DBusMessage *msg, void *user_data )
|
||||||
{
|
{
|
||||||
char *path;
|
char *path;
|
||||||
|
@ -371,6 +527,7 @@ static DBusHandlerResult udisks_filter( DBusConnection *ctx, DBusMessage *msg, v
|
||||||
|
|
||||||
p_dbus_error_init( &error );
|
p_dbus_error_init( &error );
|
||||||
|
|
||||||
|
/* udisks signals */
|
||||||
if (p_dbus_message_is_signal( msg, "org.freedesktop.UDisks", "DeviceAdded" ) &&
|
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 ))
|
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 );
|
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",
|
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_type( msg ), p_dbus_message_get_path( msg ),
|
||||||
p_dbus_message_get_interface( msg ), p_dbus_message_get_member( 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',"
|
static const char udisks_match[] = "type='signal',"
|
||||||
"interface='org.freedesktop.UDisks',"
|
"interface='org.freedesktop.UDisks',"
|
||||||
"sender='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;
|
DBusError error;
|
||||||
|
|
||||||
|
@ -525,14 +706,24 @@ static DWORD WINAPI dbus_thread( void *arg )
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_dbus_connection_add_filter( connection, udisks_filter, NULL, NULL ))
|
/* first try UDisks2 */
|
||||||
p_dbus_bus_add_match( connection, udisks_match, &error );
|
|
||||||
|
|
||||||
if (!udisks_enumerate_devices())
|
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_bus_remove_match( connection, udisks_match, &error );
|
||||||
p_dbus_connection_remove_filter( connection, udisks_filter, NULL );
|
p_dbus_connection_remove_filter( connection, udisks_filter, NULL );
|
||||||
|
|
||||||
|
/* then finally HAL */
|
||||||
|
|
||||||
#ifdef SONAME_LIBHAL
|
#ifdef SONAME_LIBHAL
|
||||||
if (!hal_enumerate_devices())
|
if (!hal_enumerate_devices())
|
||||||
{
|
{
|
||||||
|
@ -540,8 +731,8 @@ static DWORD WINAPI dbus_thread( void *arg )
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
|
found:
|
||||||
__TRY
|
__TRY
|
||||||
{
|
{
|
||||||
while (p_dbus_connection_read_write_dispatch( connection, -1 )) /* nothing */ ;
|
while (p_dbus_connection_read_write_dispatch( connection, -1 )) /* nothing */ ;
|
||||||
|
|
Loading…
Reference in New Issue