static gboolean disk_is_partitioned_by_kernel (GUdevDevice *device) { gboolean ret = FALSE; GDir *dir = NULL; const gchar *name; const gchar *device_name; g_return_val_if_fail (g_strcmp0 (g_udev_device_get_devtype (device), "disk") == 0, FALSE); dir = g_dir_open (g_udev_device_get_sysfs_path (device), 0 /* flags */, NULL /* GError */); if (dir == NULL) goto out; device_name = g_udev_device_get_name (device); while ((name = g_dir_read_name (dir)) != NULL) { /* TODO: could check that it's a block device - for now, just * checking the name suffices */ if (g_str_has_prefix (name, device_name)) { ret = TRUE; goto out; } } out: if (dir != NULL) g_dir_close (dir); return ret; }
static gboolean filesystem_check (StoragedObject *object) { StoragedLinuxBlockObject *block_object = STORAGED_LINUX_BLOCK_OBJECT (object); gboolean ret = FALSE; gboolean detected_as_filesystem = FALSE; StoragedMountType mount_type; /* if blkid(8) has detected the device as a filesystem, trust that */ if (g_strcmp0 (storaged_block_get_id_usage (block_object->iface_block_device), "filesystem") == 0) { detected_as_filesystem = TRUE; /* except, if we are a whole-disk device and the kernel has already partitioned us... * in that case, don't pretend we're a filesystem * * (see partition_table_check() above for the similar case where we don't pretend * to be a partition table) */ if (g_strcmp0 (g_udev_device_get_devtype (block_object->device->udev_device), "disk") == 0 && disk_is_partitioned_by_kernel (block_object->device->udev_device)) { detected_as_filesystem = FALSE; } } if (drive_does_not_detect_media_change (block_object) || detected_as_filesystem || (storaged_mount_monitor_is_dev_in_use (block_object->mount_monitor, g_udev_device_get_device_number (block_object->device->udev_device), &mount_type) && mount_type == STORAGED_MOUNT_TYPE_FILESYSTEM)) ret = TRUE; return ret; }
static gboolean loop_check (UDisksLinuxBlockObject *object) { gboolean ret; ret = FALSE; if (g_str_has_prefix (g_udev_device_get_name (object->device->udev_device), "loop") && g_strcmp0 (g_udev_device_get_devtype (object->device->udev_device), "disk") == 0) ret = TRUE; return ret; }
static gboolean loop_check (StoragedObject *object) { StoragedLinuxBlockObject *block_object = STORAGED_LINUX_BLOCK_OBJECT (object); gboolean ret; ret = FALSE; if (g_str_has_prefix (g_udev_device_get_name (block_object->device->udev_device), "loop") && g_strcmp0 (g_udev_device_get_devtype (block_object->device->udev_device), "disk") == 0) ret = TRUE; return ret; }
static gboolean partition_table_check (StoragedObject *object) { StoragedLinuxBlockObject *block_object = STORAGED_LINUX_BLOCK_OBJECT (object); gboolean ret = FALSE; /* only consider whole disks, never partitions */ if (g_strcmp0 (g_udev_device_get_devtype (block_object->device->udev_device), "disk") != 0) goto out; /* if blkid(8) already identified the device as a partition table, it's all good */ if (g_udev_device_has_property (block_object->device->udev_device, "ID_PART_TABLE_TYPE")) { /* however, if blkid(8) also think that we're a filesystem... then don't * mark us as a partition table ... except if we are partitioned by the * kernel * * (see filesystem_check() for the similar case where we don't pretend * to be a filesystem) */ if (g_strcmp0 (g_udev_device_get_property (block_object->device->udev_device, "ID_FS_USAGE"), "filesystem") == 0) { if (!disk_is_partitioned_by_kernel (block_object->device->udev_device)) { goto out; } } ret = TRUE; goto out; } /* Note that blkid(8) might not detect all partition table * formats that the kernel knows about.... so we need to * double check... * * Fortunately, note that the kernel guarantees that all children * block devices that are partitions are created before the uevent * for the parent block device.... so if the parent block device has * children... then it must be partitioned by the kernel, hence it * must contain a partition table. */ if (disk_is_partitioned_by_kernel (block_object->device->udev_device)) { ret = TRUE; goto out; } out: return ret; }
/** * udisks_linux_drive_object_get_block: * @object: A #UDisksLinuxDriveObject. * @get_hw: If the drive is multipath, set to %TRUE to get a path device instead of the multipath device. * * Gets a #UDisksLinuxBlockObject representing a block device associated with @object. * * Returns: A #UDisksLinuxBlockObject or %NULL. The returned object * must be freed with g_object_unref(). */ UDisksLinuxBlockObject * udisks_linux_drive_object_get_block (UDisksLinuxDriveObject *object, gboolean get_hw) { GDBusObjectManagerServer *object_manager; UDisksLinuxBlockObject *ret; GList *objects; GList *l; /* TODO: actually look at @get_hw */ ret = NULL; object_manager = udisks_daemon_get_object_manager (object->daemon); objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (object_manager)); for (l = objects; l != NULL; l = l->next) { GDBusObjectSkeleton *iter_object = G_DBUS_OBJECT_SKELETON (l->data); UDisksBlock *block; UDisksLinuxDevice *device; gboolean is_disk; if (!UDISKS_IS_LINUX_BLOCK_OBJECT (iter_object)) continue; device = udisks_linux_block_object_get_device (UDISKS_LINUX_BLOCK_OBJECT (iter_object)); is_disk = (g_strcmp0 (g_udev_device_get_devtype (device->udev_device), "disk") == 0); g_object_unref (device); if (!is_disk) continue; block = udisks_object_peek_block (UDISKS_OBJECT (iter_object)); if (g_strcmp0 (udisks_block_get_drive (block), g_dbus_object_get_object_path (G_DBUS_OBJECT (object))) == 0) { ret = g_object_ref (iter_object); goto out; } } out: g_list_foreach (objects, (GFunc) g_object_unref, NULL); g_list_free (objects); return ret; }
static void dump_device_and_parent(GUdevDevice * device, guint indent) { const gchar *const *list; const gchar *const *iter; GUdevDevice *parent; char propstr[500]; guint32 namelen = 0, i; println(indent, "------------------------------------------------------"); println(indent, "%-20s %s", _("Name:"), g_udev_device_get_name(device)); println(indent, "%-20s %s", _("Type:"), g_udev_device_get_devtype(device)); println(indent, "%-20s %s", _("Subsystem:"), g_udev_device_get_subsystem(device)); println(indent, "%-20s %s", _("Number:"), g_udev_device_get_number(device)); println(indent, "%-20s %s", _("Path:"), g_udev_device_get_sysfs_path(device)); println(indent, "%-20s %s", _("Driver:"), g_udev_device_get_driver(device)); println(indent, "%-20s %lld", _("Sequential Number:"), (long long int)g_udev_device_get_seqnum(device)); println(indent, "%-20s %s", _("Device File:"), g_udev_device_get_device_file(device)); println(indent, " "); println(indent, _("Properties:")); /* Get longest property name length for alignment */ list = g_udev_device_get_property_keys(device); for (iter = list; iter && *iter; iter++) { if (strlen(*iter) > namelen) namelen = strlen(*iter); } namelen++; for (iter = list; iter && *iter; iter++) { strcpy(propstr, *iter); strcat(propstr, ":"); for (i = 0; i < namelen - strlen(*iter); i++) strcat(propstr, " "); strcat(propstr, g_udev_device_get_property(device, *iter)); println(indent + 2, "%s", propstr); } println(indent, " "); parent = g_udev_device_get_parent(device); if (parent) { dump_device_and_parent(parent, indent + 4); g_object_unref(parent); } }
/** * storaged_linux_drive_object_get_block: * @object: A #StoragedLinuxDriveObject. * @get_hw: If the drive is multipath, set to %TRUE to get a path device instead of the multipath device. * * Gets a #StoragedLinuxBlockObject representing a block device associated with @object. * * Returns: A #StoragedLinuxBlockObject or %NULL. The returned object * must be freed with g_object_unref(). */ StoragedLinuxBlockObject * storaged_linux_drive_object_get_block (StoragedLinuxDriveObject *object, gboolean get_hw) { GDBusObjectManagerServer *object_manager; StoragedLinuxBlockObject *ret; GList *objects; GList *l; ret = NULL; object_manager = storaged_daemon_get_object_manager (object->daemon); objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (object_manager)); for (l = objects; l != NULL; l = l->next) { GDBusObjectSkeleton *iter_object = G_DBUS_OBJECT_SKELETON (l->data); StoragedBlock *block; StoragedLinuxDevice *device; gboolean skip; if (!STORAGED_IS_LINUX_BLOCK_OBJECT (iter_object)) continue; device = storaged_linux_block_object_get_device (STORAGED_LINUX_BLOCK_OBJECT (iter_object)); skip = (g_strcmp0 (g_udev_device_get_devtype (device->udev_device), "disk") != 0 || (get_hw && is_dm_multipath (device))); g_object_unref (device); if (skip) continue; block = storaged_object_peek_block (STORAGED_OBJECT (iter_object)); if (g_strcmp0 (storaged_block_get_drive (block), g_dbus_object_get_object_path (G_DBUS_OBJECT (object))) == 0) { ret = g_object_ref (iter_object); goto out; } } out: g_list_foreach (objects, (GFunc) g_object_unref, NULL); g_list_free (objects); return ret; }
static gboolean partition_check (UDisksLinuxBlockObject *object) { gboolean ret = FALSE; /* could be partitioned by the kernel */ if (g_strcmp0 (g_udev_device_get_devtype (object->device->udev_device), "partition") == 0) { ret = TRUE; goto out; } /* if blkid(8) already identified the device as a partition, it's all good */ if (g_udev_device_has_property (object->device->udev_device, "ID_PART_ENTRY_SCHEME")) { ret = TRUE; goto out; } out: return ret; }
static gboolean partition_check (StoragedObject *object) { StoragedLinuxBlockObject *block_object = STORAGED_LINUX_BLOCK_OBJECT (object); gboolean ret = FALSE; /* could be partitioned by the kernel */ if (g_strcmp0 (g_udev_device_get_devtype (block_object->device->udev_device), "partition") == 0) { ret = TRUE; goto out; } /* if blkid(8) already identified the device as a partition, it's all good */ if (g_udev_device_has_property (block_object->device->udev_device, "ID_PART_ENTRY_SCHEME")) { ret = TRUE; goto out; } out: return ret; }
/* <internal> * storaged_linux_drive_object_should_include_device: * @client: A #GUdevClient. * @device: A #StoragedLinuxDevice. * @out_vpd: Return location for unique ID or %NULL. * * Checks if we should even construct a #StoragedLinuxDriveObject for @device. * * Returns: %TRUE if we should construct an object, %FALSE otherwise. */ gboolean storaged_linux_drive_object_should_include_device (GUdevClient *client, StoragedLinuxDevice *device, gchar **out_vpd) { gboolean ret; gchar *vpd; ret = FALSE; vpd = NULL; /* The 'block' subsystem encompasses several objects with varying * DEVTYPE including * * - disk * - partition * * and we are only interested in the first. */ if (g_strcmp0 (g_udev_device_get_devtype (device->udev_device), "disk") != 0) goto out; vpd = check_for_vpd (device->udev_device); if (vpd == NULL) { const gchar *name; const gchar *vendor; const gchar *model; const gchar *dm_uuid; GUdevDevice *parent; name = g_udev_device_get_name (device->udev_device); /* workaround for floppy devices */ if (g_str_has_prefix (name, "fd")) { vpd = g_strdup_printf ("pcfloppy_%s", name); goto found; } /* workaround for missing serial/wwn on virtio-blk */ if (g_str_has_prefix (name, "vd")) { vpd = g_strdup (name); goto found; } /* workaround for missing serial/wwn on VMware */ vendor = g_udev_device_get_property (device->udev_device, "ID_VENDOR"); model = g_udev_device_get_property (device->udev_device, "ID_MODEL"); if (g_str_has_prefix (name, "sd") && vendor != NULL && g_strcmp0 (vendor, "VMware") == 0 && model != NULL && g_str_has_prefix (model, "Virtual")) { vpd = g_strdup (name); goto found; } /* workaround for missing serial/wwn on firewire devices */ parent = g_udev_device_get_parent_with_subsystem (device->udev_device, "firewire", NULL); if (parent != NULL) { vpd = g_strdup (name); g_object_unref (parent); goto found; } /* dm-multipath */ if (is_dm_multipath (device)) { gchar **slaves; guint n; slaves = storaged_daemon_util_resolve_links (g_udev_device_get_sysfs_path (device->udev_device), "slaves"); for (n = 0; slaves[n] != NULL; n++) { GUdevDevice *slave; slave = g_udev_client_query_by_sysfs_path (client, slaves[n]); if (slave != NULL) { vpd = check_for_vpd (slave); if (vpd != NULL) { g_object_unref (slave); g_strfreev (slaves); goto found; } g_object_unref (slave); } } g_strfreev (slaves); } } found: if (vpd != NULL) { if (out_vpd != NULL) { *out_vpd = vpd; vpd = NULL; } ret = TRUE; } out: g_free (vpd); return ret; }
static GUdevDevice * find_physical_device (GUdevDevice *child) { GUdevDevice *iter, *old = NULL; GUdevDevice *physdev = NULL; const char *subsys, *type, *name; guint32 i = 0; gboolean is_usb = FALSE, is_pci = FALSE, is_pcmcia = FALSE, is_platform = FALSE; gboolean is_pnp = FALSE; g_return_val_if_fail (child != NULL, NULL); /* Bluetooth rfcomm devices are "virtual" and don't necessarily have * parents at all. */ name = g_udev_device_get_name (child); if (name && strncmp (name, "rfcomm", 6) == 0) return g_object_ref (child); iter = g_object_ref (child); while (iter && i++ < 8) { subsys = g_udev_device_get_subsystem (iter); if (subsys) { if (is_usb || g_str_has_prefix (subsys, "usb")) { is_usb = TRUE; type = g_udev_device_get_devtype (iter); if (type && !strcmp (type, "usb_device")) { physdev = iter; break; } } else if (is_pcmcia || !strcmp (subsys, "pcmcia")) { GUdevDevice *pcmcia_parent; const char *tmp_subsys; is_pcmcia = TRUE; /* If the parent of this PCMCIA device is no longer part of * the PCMCIA subsystem, we want to stop since we're looking * for the base PCMCIA device, not the PCMCIA controller which * is usually PCI or some other bus type. */ pcmcia_parent = g_udev_device_get_parent (iter); if (pcmcia_parent) { tmp_subsys = g_udev_device_get_subsystem (pcmcia_parent); if (tmp_subsys && strcmp (tmp_subsys, "pcmcia")) physdev = iter; g_object_unref (pcmcia_parent); if (physdev) break; } } else if (is_platform || !strcmp (subsys, "platform")) { /* Take the first platform parent as the physical device */ is_platform = TRUE; physdev = iter; break; } else if (is_pci || !strcmp (subsys, "pci")) { is_pci = TRUE; physdev = iter; break; } else if (is_pnp || !strcmp (subsys, "pnp")) { is_pnp = TRUE; physdev = iter; break; } } old = iter; iter = g_udev_device_get_parent (old); g_object_unref (old); } return physdev; }
/** * udisks_linux_mdraid_object_uevent: * @object: A #UDisksLinuxMDRaidObject. * @action: Uevent action or %NULL * @device: A #UDisksLinuxDevice device object or %NULL if the device hasn't changed. * @is_member: %TRUE if @device is a member, %FALSE if it's the raid device. * * Updates all information on interfaces on @mdraid. */ void udisks_linux_mdraid_object_uevent (UDisksLinuxMDRaidObject *object, const gchar *action, UDisksLinuxDevice *device, gboolean is_member) { gboolean conf_changed = FALSE; g_return_if_fail (UDISKS_IS_LINUX_MDRAID_OBJECT (object)); g_return_if_fail (UDISKS_IS_LINUX_DEVICE (device)); /* udisks_debug ("is_member=%d for uuid %s and device %s", is_member, object->uuid, g_udev_device_get_device_file (device->udev_device)); */ if (is_member) { GList *link = NULL; link = NULL; if (device != NULL) link = find_link_for_sysfs_path_for_member (object, g_udev_device_get_sysfs_path (device->udev_device)); if (g_strcmp0 (action, "remove") == 0) { if (link != NULL) { g_object_unref (UDISKS_LINUX_DEVICE (link->data)); object->member_devices = g_list_delete_link (object->member_devices, link); } else { udisks_warning ("MDRaid with UUID %s doesn't have member device with sysfs path %s on remove event", object->uuid, g_udev_device_get_sysfs_path (device->udev_device)); } } else { if (link != NULL) { if (device != link->data) { g_object_unref (UDISKS_LINUX_DEVICE (link->data)); link->data = g_object_ref (device); } } else { if (device != NULL) { object->member_devices = g_list_append (object->member_devices, g_object_ref (device)); } } } } else { /* Skip partitions of raid devices */ if (g_strcmp0 (g_udev_device_get_devtype (device->udev_device), "disk") != 0) goto out; if (g_strcmp0 (action, "remove") == 0) { if (object->raid_device != NULL) if (g_strcmp0 (g_udev_device_get_sysfs_path (object->raid_device->udev_device), g_udev_device_get_sysfs_path (device->udev_device)) == 0) { g_clear_object (&object->raid_device); raid_device_removed (object, object->raid_device); } else { udisks_warning ("MDRaid with UUID %s doesn't have raid device with sysfs path %s on remove event (it has %s)", object->uuid, g_udev_device_get_sysfs_path (device->udev_device), g_udev_device_get_sysfs_path (object->raid_device->udev_device)); } else { udisks_warning ("MDRaid with UUID %s doesn't have raid device with sysfs path %s on remove event", object->uuid, g_udev_device_get_sysfs_path (device->udev_device)); } } else { if (object->raid_device == NULL) { object->raid_device = g_object_ref (device); raid_device_added (object, object->raid_device); } else { if (device != object->raid_device) { /* device changed -- remove and re-add the file watchers */ raid_device_removed (object, object->raid_device); g_clear_object (&object->raid_device); object->raid_device = g_object_ref (device); raid_device_added (object, object->raid_device); } } } } /* if we don't have any devices, no point in updating (we should get nuked soon anyway) */ if (udisks_linux_mdraid_object_have_devices (object)) { conf_changed = FALSE; conf_changed |= update_iface (object, action, mdraid_check, mdraid_connect, mdraid_update, UDISKS_TYPE_LINUX_MDRAID, &object->iface_mdraid); } out: ; }