hal/hald/linux2 blockdev.c, 1.32, 1.33 coldplug.c, 1.21,
1.22 hotplug.c, 1.19, 1.20 hotplug.h, 1.10, 1.11 osspec.c,
1.41, 1.42
Kay Sievers
kay at freedesktop.org
Mon Jan 23 04:15:52 PST 2006
- Previous message: hal/drive_id Makefile.am, 1.1, NONE ata.c, 1.3, NONE ata.h, 1.1,
NONE drive_id.c, 1.4, NONE drive_id.h, 1.2, NONE logging.h,
1.2, NONE scsi.c, 1.3, NONE scsi.h, 1.1, NONE util.c, 1.2,
NONE util.h, 1.1, NONE
- Next message: hal/hald util.c,1.35,1.36 util.h,1.16,1.17
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvs/hal/hal/hald/linux2
In directory gabe:/tmp/cvs-serv27406/hald/linux2
Modified Files:
blockdev.c coldplug.c hotplug.c hotplug.h osspec.c
Log Message:
2006-01-23 Kay Sievers <kay.sievers at vrfy.org>
Remove drive_id and use the udev provided data for block device
serial numbers and vendor/product information.
* Makefile.am:
* configure.in:
* drive_id/Makefile.am:
* drive_id/ata.c:
* drive_id/ata.h:
* drive_id/drive_id.c:
* drive_id/drive_id.h:
* drive_id/logging.h:
* drive_id/scsi.c:
* drive_id/scsi.h:
* drive_id/util.c:
* drive_id/util.h:
* hald/linux2/blockdev.c: (add_blockdev_probing_helper_done),
(blockdev_callouts_preprobing_storage_done),
(blockdev_callouts_preprobing_volume_done),
(hotplug_event_begin_add_blockdev):
* hald/linux2/coldplug.c: (hal_util_get_udevinfo_path),
(hal_util_init_sysfs_to_udev_map), (coldplug_get_hotplug_event),
(coldplug_synthesize_events), (coldplug_synthesize_block_event),
(coldplug_compute_visit_device):
* hald/linux2/hotplug.c: (fixup_net_device_for_renaming),
(hotplug_event_begin_sysfs):
* hald/linux2/hotplug.h:
* hald/linux2/osspec.c: (hald_udev_data), (osspec_init):
* hald/linux2/probing/Makefile.am:
* hald/linux2/probing/probe-storage.c: (main):
* hald/linux2/probing/probe-volume.c: (volume_id_log),
(strdup_valid_utf8), (set_volume_id_values):
* hald/util.c: (hal_util_strdup_valid_utf8):
* hald/util.h:
Index: blockdev.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/blockdev.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- blockdev.c 21 Jan 2006 16:54:04 -0000 1.32
+++ blockdev.c 23 Jan 2006 12:15:50 -0000 1.33
@@ -4,6 +4,7 @@
* blockdev.c : Handling of block devices
*
* Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
+ * Copyright (C) 2005,2006 Kay Sievers, <kay.sievers at vrfy.org>
*
* Licensed under the Academic Free License version 2.1
*
@@ -335,7 +336,7 @@
out:
- ;
+ return;
}
static void
@@ -353,7 +354,7 @@
hal_device_property_set_string (d, "info.product", "Ignored Device");
HAL_INFO (("Preprobing merged info.ignore==TRUE"));
-
+
/* Move from temporary to global device store */
hal_device_store_remove (hald_get_tdl (), d);
hal_device_store_add (hald_get_gdl (), d);
@@ -365,7 +366,6 @@
if (!hal_device_property_get_bool (d, "storage.media_check_enabled") &&
hal_device_property_get_bool (d, "storage.no_partitions_hint")) {
-
/* special probe for PC floppy drives */
if (strcmp (hal_device_property_get_string (d, "storage.bus"), "platform") == 0 &&
strcmp (hal_device_property_get_string (d, "storage.drive_type"), "floppy") == 0) {
@@ -389,7 +389,6 @@
/* run prober for
*
- * - drive_id
* - cdrom drive properties
* - non-partitioned filesystem on main block device
*/
@@ -397,23 +396,23 @@
HAL_INFO (("Probing storage device %s", hal_device_property_get_string (d, "block.device")));
/* probe the device */
- hald_runner_run(d,
- "hald-probe-storage", NULL,
- HAL_HELPER_TIMEOUT,
- add_blockdev_probing_helper_done,
- (gpointer) end_token, NULL);
-
+ hald_runner_run(d,
+ "hald-probe-storage", NULL,
+ HAL_HELPER_TIMEOUT,
+ add_blockdev_probing_helper_done,
+ (gpointer) end_token, NULL);
+
out:
- ;
+ return;
}
-static void
+static void
blockdev_callouts_preprobing_volume_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
{
void *end_token = (void *) userdata1;
if (hal_device_property_get_bool (d, "info.ignore")) {
- /* Leave the device here with info.ignore==TRUE so we won't pick up children
+ /* Leave the device here with info.ignore==TRUE so we won't pick up children
* Also remove category and all capabilities
*/
hal_device_property_remove (d, "info.category");
@@ -422,23 +421,23 @@
hal_device_property_set_string (d, "info.product", "Ignored Device");
HAL_INFO (("Preprobing merged info.ignore==TRUE"));
-
+
/* Move from temporary to global device store */
hal_device_store_remove (hald_get_tdl (), d);
hal_device_store_add (hald_get_gdl (), d);
-
+
hotplug_event_end (end_token);
goto out;
}
/* probe the device */
hald_runner_run (d,
- "hald-probe-volume", NULL,
- HAL_HELPER_TIMEOUT,
- add_blockdev_probing_helper_done,
- (gpointer) end_token, NULL);
+ "hald-probe-volume", NULL,
+ HAL_HELPER_TIMEOUT,
+ add_blockdev_probing_helper_done,
+ (gpointer) end_token, NULL);
out:
- ;
+ return;
}
static const gchar *
@@ -530,6 +529,7 @@
hotplug_event_begin_add_blockdev (const gchar *sysfs_path, const gchar *device_file, gboolean is_partition,
HalDevice *parent, void *end_token)
{
+ HotplugEvent *hotplug_event = (HotplugEvent *) end_token;
gchar *major_minor;
HalDevice *d;
unsigned int major, minor;
@@ -654,7 +654,7 @@
scsidev = NULL;
physdev = NULL;
- physdev_udi = NULL;
+ physdev_udi = NULL;
is_removable = FALSE;
is_hotpluggable = FALSE;
@@ -666,10 +666,16 @@
hal_device_property_set_bool (d, "storage.no_partitions_hint", TRUE);
hal_device_property_set_bool (d, "storage.media_check_enabled", TRUE);
hal_device_property_set_bool (d, "storage.automount_enabled_hint", TRUE);
- hal_device_property_set_string (d, "storage.model", "");
- hal_device_property_set_string (d, "storage.vendor", "");
hal_device_property_set_string (d, "storage.drive_type", "disk");
+ /* persistent properties from udev (may be empty) */
+ hal_device_property_set_string (d, "storage.model", hotplug_event->sysfs.model);
+ hal_device_property_set_string (d, "storage.vendor", hotplug_event->sysfs.vendor);
+ if (hotplug_event->sysfs.serial[0] != '\0')
+ hal_device_property_set_string (d, "storage.serial", hotplug_event->sysfs.serial);
+ if (hotplug_event->sysfs.revision[0] != '\0')
+ hal_device_property_set_string (d, "storage.firmware_version", hotplug_event->sysfs.revision);
+
/* walk up the device chain to find the physical device,
* start with our parent. On the way, optionally pick up
* the scsi if it exists */
@@ -728,7 +734,6 @@
hal_device_property_set_string
(d, "storage.bus", "ccw");
}
-
}
/* Go to parent */
@@ -858,10 +863,10 @@
* VOLUMES
*
************************/
-
hal_device_property_set_string (d, "block.storage_device", parent->udi);
- /* set defaults */
+ /* defaults */
+ hal_device_property_set_string (d, "storage.model", "");
hal_device_property_set_string (d, "volume.fstype", "");
hal_device_property_set_string (d, "volume.fsusage", "");
hal_device_property_set_string (d, "volume.fsversion", "");
@@ -907,9 +912,8 @@
goto error;
}
hal_device_property_set_uint64 (
- d, "volume.size",
- ((dbus_uint64_t)(512)) *
- ((dbus_uint64_t)(hal_device_property_set_int (d, "volume.block_size", 512))));
+ d, "volume.size",
+ ((dbus_uint64_t)(512)) * ((dbus_uint64_t)(hal_device_property_set_int (d, "volume.block_size", 512))));
/* add to TDL so preprobing callouts and prober can access it */
hal_device_store_add (hald_get_tdl (), d);
Index: coldplug.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/coldplug.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- coldplug.c 8 Nov 2005 15:47:36 -0000 1.21
+++ coldplug.c 23 Jan 2006 12:15:50 -0000 1.22
@@ -52,8 +52,10 @@
#define DMPREFIX "dm-"
+/* For debugging */
+#define HAL_COLDPLUG_VERBOSE
-static GHashTable *sysfs_to_dev_map;
+static GHashTable *sysfs_to_udev_map;
static char dev_root[HAL_PATH_MAX];
/* Returns the path of the udevinfo program
@@ -66,7 +68,7 @@
guint i;
struct stat s;
static gchar *path = NULL;
- gchar *possible_paths[] = {
+ gchar *possible_paths[] = {
"/usr/bin/udevinfo",
"/bin/udevinfo",
"/usr/sbin/udevinfo",
@@ -85,26 +87,18 @@
return path;
}
-
static gboolean
-hal_util_init_sysfs_to_dev_map (void)
+hal_util_init_sysfs_to_udev_map (void)
{
- char *udevdump_argv[] = { "/usr/bin/udevinfo", "-d", NULL };
+ char *udevdb_export_argv[] = { "/usr/bin/udevinfo", "-e", NULL };
char *udevroot_argv[] = { "/usr/bin/udevinfo", "-r", NULL };
char *udevinfo_stdout;
int udevinfo_exitcode;
+ HotplugEvent *hotplug_event = NULL;
char *p;
- char *q;
- char *r;
- int len;
- char sysfs_path[PATH_MAX + 1];
- char device_file[PATH_MAX + 1];
- const char *sysfs_mount_path;
- gboolean has_more_lines;
- sysfs_mount_path = get_hal_sysfs_path ();
- sysfs_to_dev_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
- udevdump_argv[0] = (char *) hal_util_get_udevinfo_path ();
+ sysfs_to_udev_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ udevdb_export_argv[0] = (char *) hal_util_get_udevinfo_path ();
udevroot_argv[0] = (char *) hal_util_get_udevinfo_path ();
/* get udevroot */
@@ -123,128 +117,164 @@
g_strlcpy(dev_root, udevinfo_stdout, sizeof(dev_root));
p = strchr(dev_root, '\n');
- if (p)
+ if (p != NULL)
p[0] = '\0';
g_free(udevinfo_stdout);
HAL_INFO (("dev_root is %s", dev_root));
- /* get udevdump */
- if (g_spawn_sync ("/", udevdump_argv, NULL, 0, NULL, NULL,
+ /* get udevdb export */
+ if (g_spawn_sync ("/", udevdb_export_argv, NULL, 0, NULL, NULL,
&udevinfo_stdout,
NULL,
&udevinfo_exitcode,
NULL) != TRUE) {
- HAL_ERROR (("Couldn't invoke %s", udevdump_argv[0]));
+ HAL_ERROR (("Couldn't invoke %s", udevdb_export_argv[0]));
g_free(udevinfo_stdout);
goto error;
}
if (udevinfo_exitcode != 0) {
- HAL_ERROR (("%s returned %d", udevdump_argv[0], udevinfo_exitcode));
+ HAL_ERROR (("%s returned %d", udevdb_export_argv[0], udevinfo_exitcode));
goto error;
}
- has_more_lines = TRUE;
+ /* read the export of the udev database */
p = udevinfo_stdout;
+ while (p[0] != '\0') {
+ char *line, *end;
+ gchar *str;
- do {
- if (*p == '\0') {
- has_more_lines = FALSE;
+ /* get line, terminate and move to next line */
+ line = p;
+ end = strchr(line, '\n');
+ if (end == NULL)
break;
- }
-
- for (q = p; *q != '\n' && *q != '\0' && *q != '='; q++)
- ;
+ end[0] = '\0';
+ p = &end[1];
- len = q - p;
- switch (*q) {
- case '=':
- strncpy (sysfs_path, p, len > PATH_MAX ? PATH_MAX : len);
- sysfs_path [len > PATH_MAX ? PATH_MAX : len] = '\0';
- break;
-
- case '\n':
- HAL_ERROR (("Expected '=', not '\\n' in line '%s'", p));
- goto error;
-
- case '\0':
- HAL_ERROR (("Expected '=', not '\\0' in line '%s'", p));
- goto error;
-
- default:
- HAL_ERROR (("Expected '=', not '%c' in line '%s'", *q, p));
- goto error;
+ /* insert device */
+ if (line[0] == '\0') {
+ if (hotplug_event != NULL) {
+ g_hash_table_insert (sysfs_to_udev_map, g_strdup (hotplug_event->sysfs.sysfs_path), hotplug_event);
+#ifdef HAL_COLDPLUG_VERBOSE
+ printf ("Got '%s' -> '%s'\n", hotplug_event->sysfs.sysfs_path, hotplug_event->sysfs.device_file);
+#endif
+ hotplug_event = NULL;
+ }
+ continue;
}
- q++;
- r = q;
- for ( ; *q != '\n' && *q != '\0'; q++)
- ;
-
- len = q - r;
- switch (*q) {
- case '\0':
- has_more_lines = FALSE;
- /* explicit fallthrough */
-
- case '\n':
- strncpy (device_file, r, len > PATH_MAX ? PATH_MAX : len);
- device_file [len > PATH_MAX ? PATH_MAX : len] = '\0';
- break;
- default:
- HAL_ERROR (("Expected '\\n' or '\\0', not '%c' in line '%s'", *q, p));
- goto error;
+ /* new device */
+ if (strncmp(line, "P: ", 3) == 0) {
+ hotplug_event = g_new0 (HotplugEvent, 1);
+ g_strlcpy (hotplug_event->sysfs.sysfs_path, get_hal_sysfs_path (), sizeof(hotplug_event->sysfs.sysfs_path));
+ g_strlcat (hotplug_event->sysfs.sysfs_path, &line[3], sizeof(hotplug_event->sysfs.sysfs_path));
+ continue;
}
- g_hash_table_insert (sysfs_to_dev_map, g_strdup_printf ("%s%s", sysfs_mount_path, sysfs_path),
- g_strdup(device_file));
-
-#ifdef HAL_COLDPLUG_VERBOSE
- printf ("Got '%s' -> '%s'\n", sysfs_path, device_file);
-#endif
- p = q + 1;
+ /* only valid if we have an actual device */
+ if (hotplug_event == NULL)
+ continue;
- } while (has_more_lines);
+ if (strncmp(line, "N: ", 3) == 0) {
+ g_snprintf (hotplug_event->sysfs.device_file, sizeof(hotplug_event->sysfs.device_file),
+ "%s/%s", dev_root, &line[3]);
+ } else if (strncmp(line, "E: ID_VENDOR=", 13) == 0) {
+ str = hal_util_strdup_valid_utf8(&line[13]);
+ g_strlcpy (hotplug_event->sysfs.vendor, str, sizeof(hotplug_event->sysfs.vendor));
+ g_free (str);
+ } else if (strncmp(line, "E: ID_MODEL=", 12) == 0) {
+ str = hal_util_strdup_valid_utf8(&line[12]);
+ g_strlcpy (hotplug_event->sysfs.model, str, sizeof(hotplug_event->sysfs.model));
+ g_free (str);
+ } else if (strncmp(line, "E: ID_REVISION=", 15) == 0) {
+ str = hal_util_strdup_valid_utf8(&line[15]);
+ g_strlcpy (hotplug_event->sysfs.revision, str, sizeof(hotplug_event->sysfs.revision));
+ g_free (str);
+ } else if (strncmp(line, "E: ID_SERIAL=", 13) == 0) {
+ str = hal_util_strdup_valid_utf8(&line[13]);
+ g_strlcpy (hotplug_event->sysfs.serial, str, sizeof(hotplug_event->sysfs.serial));
+ g_free (str);
+ } else if (strncmp(line, "E: ID_FS_USAGE=", 15) == 0) {
+ str = hal_util_strdup_valid_utf8(&line[15]);
+ g_strlcpy (hotplug_event->sysfs.fsusage, str, sizeof(hotplug_event->sysfs.fsusage));
+ g_free (str);
+ } else if (strncmp(line, "E: ID_FS_TYPE=", 14) == 0) {
+ str = hal_util_strdup_valid_utf8(&line[14]);
+ g_strlcpy (hotplug_event->sysfs.fstype, str, sizeof(hotplug_event->sysfs.fstype));
+ g_free (str);
+ } else if (strncmp(line, "E: ID_FS_VERSION=", 17) == 0) {
+ str = hal_util_strdup_valid_utf8(&line[17]);
+ g_strlcpy (hotplug_event->sysfs.fsversion, str, sizeof(hotplug_event->sysfs.fsversion));
+ g_free (str);
+ } else if (strncmp(line, "E: ID_FS_UUID=", 14) == 0) {
+ str = hal_util_strdup_valid_utf8(&line[14]);
+ g_strlcpy (hotplug_event->sysfs.fsuuid, str, sizeof(hotplug_event->sysfs.fsuuid));
+ g_free (str);
+ } else if (strncmp(line, "E: ID_FS_LABEL=", 15) == 0) {
+ str = hal_util_strdup_valid_utf8(&line[15]);
+ g_strlcpy (hotplug_event->sysfs.fslabel, str, sizeof(hotplug_event->sysfs.fslabel));
+ g_free (str);
+ }
+ }
g_free(udevinfo_stdout);
return TRUE;
error:
g_free(udevinfo_stdout);
- g_hash_table_destroy (sysfs_to_dev_map);
+ g_hash_table_destroy (sysfs_to_udev_map);
return FALSE;
}
-static gchar
-*coldplug_get_device_file(const gchar *sysfs_path)
+static HotplugEvent
+*coldplug_get_hotplug_event(const gchar *sysfs_path, const gchar *subsystem)
{
- const gchar *device_file;
+ HotplugEvent *hotplug_event, *hotplug_event_udev;
const char *pos;
gchar path[HAL_PATH_MAX];
struct stat statbuf;
- device_file = (gchar *) g_hash_table_lookup (sysfs_to_dev_map, sysfs_path);
- if (device_file != NULL)
- return g_strdup(device_file);
-
- HAL_INFO (("sysfs_path %s not in udevdb", sysfs_path));
-
- /* device is not in udevdb, use the default kernel name */
- pos = strrchr(sysfs_path, '/');
- if (pos == NULL)
+ hotplug_event = g_new0 (HotplugEvent, 1);
+ if (hotplug_event == NULL)
return NULL;
- g_strlcpy(path, dev_root, sizeof(path));
- g_strlcat(path, pos, sizeof(path));
- if (stat (path, &statbuf))
- return NULL;
+ /* lookup if udev has something stored in its database */
+ hotplug_event_udev = (HotplugEvent *) g_hash_table_lookup (sysfs_to_udev_map, sysfs_path);
+ if (hotplug_event_udev != NULL) {
+ memcpy(hotplug_event, hotplug_event_udev, sizeof(HotplugEvent));
+ HAL_INFO (("found in udevdb '%s' '%s'", hotplug_event->sysfs.sysfs_path, hotplug_event->sysfs.device_file));
+ } else {
+ /* device is not in udev database */
+ g_strlcpy(hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof(hotplug_event->sysfs.sysfs_path));
- if (!S_ISBLK (statbuf.st_mode) && !S_ISCHR (statbuf.st_mode))
- return NULL;
+ /* look if a device node is expected */
+ g_strlcpy(path, sysfs_path, sizeof(path));
+ g_strlcat(path, "/dev", sizeof(path));
+ if (stat (path, &statbuf) != 0)
+ goto no_node;
- HAL_INFO (("return sysfs_path %s", path));
+ /* look if the node exists */
+ pos = strrchr(sysfs_path, '/');
+ if (pos == NULL)
+ goto no_node;
+ g_strlcpy(path, dev_root, sizeof(path));
+ g_strlcat(path, pos, sizeof(path));
+ if (stat (path, &statbuf) != 0)
+ goto no_node;
+ if (!S_ISBLK (statbuf.st_mode) && !S_ISCHR (statbuf.st_mode))
+ goto no_node;
- return g_strdup(path);
+ HAL_INFO (("found device_file %s for sysfs_path %s", path, sysfs_path));
+ g_strlcpy(hotplug_event->sysfs.device_file, path, sizeof(hotplug_event->sysfs.device_file));
+ }
+
+no_node:
+ g_strlcpy (hotplug_event->sysfs.subsystem, subsystem, sizeof (hotplug_event->sysfs.subsystem));
+ hotplug_event->action = HOTPLUG_ACTION_ADD;
+ hotplug_event->type = HOTPLUG_EVENT_SYSFS;
+ hotplug_event->sysfs.net_ifindex = -1;
+ return hotplug_event;
}
static gboolean
@@ -255,9 +285,6 @@
GHashTable *sysfs_to_bus_map,
GHashTable *sysfs_to_class_in_devices_map);
-/* For debugging */
-/*#define HAL_COLDPLUG_VERBOSE*/
-
static void
free_hash_sys_to_class_in_dev (gpointer key, gpointer value, gpointer user_data)
{
@@ -284,7 +311,7 @@
* @return Ordered list of sysfs paths or NULL
* if there was an error
*/
-gboolean
+gboolean
coldplug_synthesize_events (void)
{
GDir *dir;
@@ -341,7 +368,7 @@
*/
GSList *sysfs_dm_dev = NULL;
- if (hal_util_init_sysfs_to_dev_map () == FALSE) {
+ if (hal_util_init_sysfs_to_udev_map () == FALSE) {
HAL_ERROR (("Unable to get sysfs to dev map"));
goto error;
}
@@ -503,7 +530,6 @@
gchar *sysfs_path;
gchar *subsystem;
HotplugEvent *hotplug_event;
- gchar *device_file;
sysfs_path = (gchar *) li->data;
subsystem = (gchar *) li->next->data;
@@ -511,19 +537,7 @@
#ifdef HAL_COLDPLUG_VERBOSE
printf ("class: %s (%s) (no device link)\n", sysfs_path, subsystem);
#endif
- hotplug_event = g_new0 (HotplugEvent, 1);
- hotplug_event->action = HOTPLUG_ACTION_ADD;
- hotplug_event->type = HOTPLUG_EVENT_SYSFS;
- g_strlcpy (hotplug_event->sysfs.subsystem, subsystem, sizeof (hotplug_event->sysfs.subsystem));
- g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
-
- device_file = coldplug_get_device_file (sysfs_path);
- if (device_file != NULL) {
- strncpy (hotplug_event->sysfs.device_file, device_file, sizeof (hotplug_event->sysfs.device_file));
- g_free (device_file);
- }
- hotplug_event->sysfs.net_ifindex = -1;
-
+ hotplug_event = coldplug_get_hotplug_event (sysfs_path, subsystem);
hotplug_event_enqueue (hotplug_event);
g_free (li->data);
@@ -556,7 +570,7 @@
g_slist_free (sysfs_dm_dev);
g_dir_close (dir);
- g_hash_table_destroy (sysfs_to_dev_map);
+ g_hash_table_destroy (sysfs_to_udev_map);
return TRUE;
error:
@@ -568,50 +582,18 @@
coldplug_synthesize_block_event(const gchar *f)
{
GDir *dir1;
- gsize flen;
HotplugEvent *hotplug_event;
- gchar *target;
- gchar *normalized_target;
GError *err = NULL;
gchar path[HAL_PATH_MAX];
gchar path1[HAL_PATH_MAX];
const gchar *f1;
- gchar *device_file;
g_snprintf (path, HAL_PATH_MAX, "%s/block/%s", get_hal_sysfs_path (), f);
#ifdef HAL_COLDPLUG_VERBOSE
printf ("block: %s (block)\n", path);
#endif
-
- g_snprintf (path1, HAL_PATH_MAX, "%s/block/%s/device", get_hal_sysfs_path (), f);
- if (((target = g_file_read_link (path1, NULL)) != NULL)) {
- normalized_target = hal_util_get_normalized_path (path1, target);
- g_free (target);
- } else {
- normalized_target = NULL;
- }
-
- hotplug_event = g_new0 (HotplugEvent, 1);
- hotplug_event->action = HOTPLUG_ACTION_ADD;
- hotplug_event->type = HOTPLUG_EVENT_SYSFS;
- g_strlcpy (hotplug_event->sysfs.subsystem, "block", sizeof (hotplug_event->sysfs.subsystem));
- g_strlcpy (hotplug_event->sysfs.sysfs_path, path, sizeof (hotplug_event->sysfs.sysfs_path));
-
- device_file = coldplug_get_device_file (path);
- if (device_file != NULL) {
- strncpy (hotplug_event->sysfs.device_file, device_file, sizeof (hotplug_event->sysfs.device_file));
- g_free (device_file);
- }
-
- if (normalized_target != NULL)
- g_strlcpy (hotplug_event->sysfs.wait_for_sysfs_path, normalized_target, sizeof (hotplug_event->sysfs.wait_for_sysfs_path));
- else
- hotplug_event->sysfs.wait_for_sysfs_path[0] = '\0';
- hotplug_event->sysfs.net_ifindex = -1;
+ hotplug_event = coldplug_get_hotplug_event (path, "block");
hotplug_event_enqueue (hotplug_event);
- g_free (normalized_target);
-
- flen = strlen (f);
if ((dir1 = g_dir_open (path, 0, &err)) == NULL) {
HAL_ERROR (("Unable to open %s: %s", path, err->message));
@@ -619,37 +601,24 @@
goto error;
}
while ((f1 = g_dir_read_name (dir1)) != NULL) {
- if (strncmp (f, f1, flen) == 0) {
+ if (strncmp (f, f1, strlen (f)) == 0) {
g_snprintf (path1, HAL_PATH_MAX, "%s/%s", path, f1);
#ifdef HAL_COLDPLUG_VERBOSE
printf ("block: %s (block)\n", path1);
#endif
-
- hotplug_event = g_new0 (HotplugEvent, 1);
- hotplug_event->action = HOTPLUG_ACTION_ADD;
- hotplug_event->type = HOTPLUG_EVENT_SYSFS;
- g_strlcpy (hotplug_event->sysfs.subsystem, "block", sizeof (hotplug_event->sysfs.subsystem));
- g_strlcpy (hotplug_event->sysfs.sysfs_path, path1, sizeof (hotplug_event->sysfs.sysfs_path));
- g_strlcpy (hotplug_event->sysfs.wait_for_sysfs_path, path, sizeof (hotplug_event->sysfs.wait_for_sysfs_path));
- device_file = coldplug_get_device_file (path1);
- if (device_file != NULL) {
- strncpy (hotplug_event->sysfs.device_file, device_file, sizeof (hotplug_event->sysfs.device_file));
- g_free (device_file);
- }
- hotplug_event->sysfs.net_ifindex = -1;
+ hotplug_event = coldplug_get_hotplug_event (path1, "block");
hotplug_event_enqueue (hotplug_event);
}
}
- g_dir_close (dir1);
+ g_dir_close (dir1);
return TRUE;
error:
return FALSE;
}
-
static void
-coldplug_compute_visit_device (const gchar *path,
+coldplug_compute_visit_device (const gchar *path,
GHashTable *sysfs_to_bus_map,
GHashTable *sysfs_to_class_in_devices_map)
{
@@ -664,24 +633,10 @@
bus = g_hash_table_lookup (sysfs_to_bus_map, path);
if (bus != NULL) {
HotplugEvent *hotplug_event;
- gchar *parent_sysfs_path;
-
#ifdef HAL_COLDPLUG_VERBOSE
printf ("bus: %s (%s)\n", path, bus);
#endif
-
- hotplug_event = g_new0 (HotplugEvent, 1);
- hotplug_event->action = HOTPLUG_ACTION_ADD;
- hotplug_event->type = HOTPLUG_EVENT_SYSFS;
- g_strlcpy (hotplug_event->sysfs.subsystem, bus, sizeof (hotplug_event->sysfs.subsystem));
- g_strlcpy (hotplug_event->sysfs.sysfs_path, path, sizeof (hotplug_event->sysfs.sysfs_path));
- hotplug_event->sysfs.net_ifindex = -1;
-
- parent_sysfs_path = hal_util_get_parent_path (path);
- g_strlcpy (hotplug_event->sysfs.wait_for_sysfs_path, parent_sysfs_path, sizeof (hotplug_event->sysfs.wait_for_sysfs_path));
- g_free (parent_sysfs_path);
-
- hotplug_event->sysfs.device_file[0] = '\0';
+ hotplug_event = coldplug_get_hotplug_event (path, bus);
hotplug_event_enqueue (hotplug_event);
}
@@ -690,31 +645,14 @@
for (i = class_devs; i != NULL; i = g_slist_next (g_slist_next (i))) {
gchar *sysfs_path;
gchar *subsystem;
- gchar *device_file;
HotplugEvent *hotplug_event;
sysfs_path = (gchar *) i->data;
subsystem = (gchar *) i->next->data;
-
#ifdef HAL_COLDPLUG_VERBOSE
printf ("class: %s (%s) (%s)\n", path, subsystem, sysfs_path);
#endif
- hotplug_event = g_new0 (HotplugEvent, 1);
- hotplug_event->action = HOTPLUG_ACTION_ADD;
- hotplug_event->type = HOTPLUG_EVENT_SYSFS;
- g_strlcpy (hotplug_event->sysfs.subsystem, subsystem, sizeof (hotplug_event->sysfs.subsystem));
- g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
-
- device_file = coldplug_get_device_file (sysfs_path);
- if (device_file != NULL) {
- strncpy (hotplug_event->sysfs.device_file, device_file, sizeof (hotplug_event->sysfs.device_file));
- g_free (device_file);
- }
- if (path != NULL)
- g_strlcpy (hotplug_event->sysfs.wait_for_sysfs_path, path, sizeof (hotplug_event->sysfs.wait_for_sysfs_path));
- else
- hotplug_event->sysfs.wait_for_sysfs_path[0] = '\0';
- hotplug_event->sysfs.net_ifindex = -1;
+ hotplug_event = coldplug_get_hotplug_event (sysfs_path, subsystem);
hotplug_event_enqueue (hotplug_event);
}
@@ -730,9 +668,7 @@
struct stat statbuf;
g_snprintf (path_child, HAL_PATH_MAX, "%s/%s", path, f);
-
if (lstat (path_child, &statbuf) == 0) {
-
if (!S_ISLNK (statbuf.st_mode)) {
/* recursion fun */
coldplug_compute_visit_device (path_child,
Index: hotplug.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/hotplug.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- hotplug.c 2 Nov 2005 15:38:14 -0000 1.19
+++ hotplug.c 23 Jan 2006 12:15:50 -0000 1.20
@@ -63,7 +63,7 @@
/** List of HotplugEvent objects we are currently processing */
GSList *hotplug_events_in_progress = NULL;
-void
+void
hotplug_event_end (void *end_token)
{
HotplugEvent *hotplug_event = (HotplugEvent *) end_token;
@@ -82,8 +82,6 @@
hotplug_event_process_queue ();
}
-
-
static void
fixup_net_device_for_renaming (HotplugEvent *hotplug_event)
{
@@ -103,7 +101,6 @@
HAL_WARNING (("Net interface @ %s with ifindex %d was probably renamed",
hotplug_event->sysfs.sysfs_path, hotplug_event->sysfs.net_ifindex));
-
g_snprintf (path, HAL_PATH_MAX, "%s/class/net" , get_hal_sysfs_path());
if ((dir = g_dir_open (path, 0, &err)) == NULL) {
HAL_ERROR (("Unable to open %/class/net: %s", get_hal_sysfs_path(), err->message));
@@ -122,11 +119,11 @@
}
}
- g_dir_close (dir);
+ g_dir_close (dir);
}
}
out:
- ;
+ return;
}
@@ -136,18 +133,15 @@
static char sys_devices_path[HAL_PATH_MAX];
static char sys_class_path[HAL_PATH_MAX];
static char sys_block_path[HAL_PATH_MAX];
- static gsize sys_devices_path_len = 0;
- static gsize sys_class_path_len = 0;
- static gsize sys_block_path_len = 0;
+ static gsize sys_devices_path_len;
+ static gsize sys_class_path_len;
+ static gsize sys_block_path_len;
- if (sys_block_path_len == 0) {
- sys_devices_path_len = g_snprintf (sys_devices_path, HAL_PATH_MAX, "%s/devices", get_hal_sysfs_path ());
- sys_class_path_len = g_snprintf (sys_class_path, HAL_PATH_MAX, "%s/class", get_hal_sysfs_path ());
- sys_block_path_len = g_snprintf (sys_block_path, HAL_PATH_MAX, "%s/block", get_hal_sysfs_path ());
- }
+ sys_devices_path_len = g_snprintf (sys_devices_path, HAL_PATH_MAX, "%s/devices", get_hal_sysfs_path ());
+ sys_class_path_len = g_snprintf (sys_class_path, HAL_PATH_MAX, "%s/class", get_hal_sysfs_path ());
+ sys_block_path_len = g_snprintf (sys_block_path, HAL_PATH_MAX, "%s/block", get_hal_sysfs_path ());
- if (hotplug_event->action == HOTPLUG_ACTION_ADD &&
- hal_device_store_match_key_value_string (hald_get_gdl (),
+ if (hotplug_event->action == HOTPLUG_ACTION_ADD && hal_device_store_match_key_value_string (hald_get_gdl (),
"linux.sysfs_path",
hotplug_event->sysfs.sysfs_path)) {
HAL_ERROR (("devpath %s already present in the store, ignore event", hotplug_event->sysfs.sysfs_path));
@@ -227,36 +221,36 @@
} else if (strncmp (hotplug_event->sysfs.sysfs_path, sys_block_path, sys_block_path_len) == 0) {
gchar *parent_path;
gboolean is_partition;
-
+
parent_path = hal_util_get_parent_path (hotplug_event->sysfs.sysfs_path);
is_partition = (strcmp (parent_path, sys_block_path) != 0);
-
+
if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
HalDevice *parent;
if (is_partition) {
- parent = hal_device_store_match_key_value_string (hald_get_gdl (),
- "linux.sysfs_path_device",
+ parent = hal_device_store_match_key_value_string (hald_get_gdl (),
+ "linux.sysfs_path_device",
parent_path);
} else {
gchar *target;
char physdevpath[256];
-
+
g_snprintf (physdevpath, HAL_PATH_MAX, "%s/device", hotplug_event->sysfs.sysfs_path);
if (((target = g_file_read_link (physdevpath, NULL)) != NULL)) {
gchar *normalized_target;
normalized_target = hal_util_get_normalized_path (hotplug_event->sysfs.sysfs_path, target);
g_free (target);
- parent = hal_device_store_match_key_value_string (hald_get_gdl (),
- "linux.sysfs_path_device",
+ parent = hal_device_store_match_key_value_string (hald_get_gdl (),
+ "linux.sysfs_path_device",
normalized_target);
g_free (normalized_target);
} else {
parent = NULL;
}
}
-
+
hotplug_event_begin_add_blockdev (hotplug_event->sysfs.sysfs_path,
hotplug_event->sysfs.device_file,
is_partition,
Index: hotplug.h
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/hotplug.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- hotplug.h 2 Nov 2005 15:38:14 -0000 1.10
+++ hotplug.h 23 Jan 2006 12:15:50 -0000 1.11
@@ -53,36 +53,42 @@
*/
typedef struct
{
- HotplugActionType action; /**< Whether the event is add or remove */
- HotplugEventType type; /**< Type of hotplug event */
+ HotplugActionType action; /* Whether the event is add or remove */
+ HotplugEventType type; /* Type of event */
union {
struct {
- char subsystem[HAL_PATH_MAX]; /**< Subsystem e.g. usb, pci (only for hotplug msg) */
- char sysfs_path[HAL_PATH_MAX]; /**< Path into sysfs e.g. /sys/block/sda */
-
- char wait_for_sysfs_path[HAL_PATH_MAX]; /**< Wait for completion of events that a) comes
- * before this one ; AND b) has a sysfs path that
- * is contained in or equals this */
-
- char device_file [HAL_PATH_MAX]; /**< Path to special device file (may be NULL) */
-
- int net_ifindex; /**< For network only; the value of the ifindex file */
+ char subsystem[HAL_NAME_MAX]; /* Kernel subsystem the device belongs to */
+ char sysfs_path[HAL_PATH_MAX]; /* Kernel device devpath */
+ char device_file[HAL_PATH_MAX]; /* Device node for the device */
+ unsigned long long seqnum; /* kernel uevent sequence number */
+ int net_ifindex; /* Kernel ifindex for network devices */
+
+ /* stuff udev may tell us about the device and we don't want to query */
+ char vendor[HAL_NAME_MAX];
+ char model[HAL_NAME_MAX];
+ char revision[HAL_NAME_MAX];
+ char serial[HAL_NAME_MAX];
+ char fsusage[HAL_NAME_MAX];
+ char fstype[HAL_NAME_MAX];
+ char fsversion[HAL_NAME_MAX];
+ char fslabel[HAL_NAME_MAX];
+ char fsuuid[HAL_NAME_MAX];
} sysfs;
struct {
- int acpi_type; /**< Type of ACPI object; see acpi.c */
- char acpi_path[HAL_PATH_MAX]; /**< Path into procfs, e.g. /proc/acpi/battery/BAT0/ */
+ int acpi_type; /* Type of ACPI object; see acpi.c */
+ char acpi_path[HAL_PATH_MAX]; /* Path into procfs, e.g. /proc/acpi/battery/BAT0/ */
} acpi;
struct {
- int apm_type; /**< Type of APM object; see apm.c */
- char apm_path[HAL_PATH_MAX]; /**< Path into procfs, e.g. /proc/apm */
+ int apm_type; /* Type of APM object; see apm.c */
+ char apm_path[HAL_PATH_MAX]; /* Path into procfs, e.g. /proc/apm */
} apm;
struct {
- int pmu_type; /**< Type of PMU object; see pmu.c */
- char pmu_path[HAL_PATH_MAX]; /**< Path into procfs, e.g. /proc/pmu/battery_0 */
+ int pmu_type; /* Type of PMU object; see pmu.c */
+ char pmu_path[HAL_PATH_MAX]; /* Path into procfs, e.g. /proc/pmu/battery_0 */
} pmu;
};
Index: osspec.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/osspec.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -d -r1.41 -r1.42
--- osspec.c 21 Jan 2006 19:39:58 -0000 1.41
+++ osspec.c 23 Jan 2006 12:15:50 -0000 1.42
@@ -4,6 +4,7 @@
* osspec.c : New and improved HAL backend for Linux 2.6
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ * Copyright (C) 2005,2006 Kay Sievers, <kay.sievers at vrfy.org>
* Copyright (C) 2005 Danny Kukawka, <danny.kukawka at web.de>
*
* Licensed under the Academic Free License version 2.1
@@ -107,13 +108,8 @@
char buf[2048];
size_t bufpos = 0;
- const char *devpath = NULL;
- const char *physdevpath = NULL;
const char *action = NULL;
- const char *subsystem = NULL;
- const char *devname = NULL;
- int ifindex = -1;
- unsigned long long seqnum = 0;
+ HotplugEvent *hotplug_event;
fd = g_io_channel_unix_get_fd (source);
@@ -150,9 +146,13 @@
goto out;
}
+ hotplug_event = g_new0 (HotplugEvent, 1);
+ hotplug_event->type = HOTPLUG_EVENT_SYSFS;
+
while (bufpos < sizeof (buf)) {
size_t keylen;
char *key;
+ char *str;
key = &buf[bufpos];
keylen = strlen(key);
@@ -163,70 +163,89 @@
if (strncmp(key, "ACTION=", 7) == 0)
action = &key[7];
else if (strncmp(key, "DEVPATH=", 8) == 0)
- devpath = &key[8];
+ g_snprintf (hotplug_event->sysfs.sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path),
+ "%s%s", hal_sysfs_path, &key[8]);
else if (strncmp(key, "SUBSYSTEM=", 10) == 0)
- subsystem = &key[10];
- else if (strncmp(key, "PHYSDEVPATH=", 12) == 0)
- physdevpath = &key[12];
+ g_strlcpy (hotplug_event->sysfs.subsystem, &key[10], sizeof (hotplug_event->sysfs.subsystem));
else if (strncmp(key, "DEVNAME=", 8) == 0)
- devname = &key[8];
+ g_strlcpy (hotplug_event->sysfs.device_file, &key[8], sizeof (hotplug_event->sysfs.device_file));
else if (strncmp(key, "SEQNUM=", 7) == 0)
- seqnum = strtoull(&key[7], NULL, 10);
+ hotplug_event->sysfs.seqnum = strtoull(&key[7], NULL, 10);
else if (strncmp(key, "IFINDEX=", 8) == 0)
- ifindex = strtoul(&key[8], NULL, 10);
+ hotplug_event->sysfs.net_ifindex = strtoul(&key[8], NULL, 10);
+ else if (strncmp(key, "ID_VENDOR=", 10) == 0) {
+ str = hal_util_strdup_valid_utf8(&key[10]);
+ g_strlcpy (hotplug_event->sysfs.vendor, str, sizeof(hotplug_event->sysfs.vendor));
+ g_free (str);
+ } else if (strncmp(key, "ID_MODEL=", 9) == 0) {
+ str = hal_util_strdup_valid_utf8(&key[9]);
+ g_strlcpy (hotplug_event->sysfs.model, str, sizeof(hotplug_event->sysfs.model));
+ g_free (str);
+ } else if (strncmp(key, "ID_REVISION=", 12) == 0) {
+ str = hal_util_strdup_valid_utf8(&key[12]);
+ g_strlcpy (hotplug_event->sysfs.revision, str, sizeof(hotplug_event->sysfs.revision));
+ g_free (str);
+ } else if (strncmp(key, "ID_SERIAL=", 10) == 0) {
+ str = hal_util_strdup_valid_utf8(&key[10]);
+ g_strlcpy (hotplug_event->sysfs.serial, str, sizeof(hotplug_event->sysfs.serial));
+ g_free (str);
+ } else if (strncmp(key, "ID_FS_USAGE=", 12) == 0) {
+ str = hal_util_strdup_valid_utf8(&key[12]);
+ g_strlcpy (hotplug_event->sysfs.fsusage, str, sizeof(hotplug_event->sysfs.fsusage));
+ g_free (str);
+ } else if (strncmp(key, "ID_FS_TYPE=", 11) == 0) {
+ str = hal_util_strdup_valid_utf8(&key[11]);
+ g_strlcpy (hotplug_event->sysfs.fstype, str, sizeof(hotplug_event->sysfs.fstype));
+ g_free (str);
+ } else if (strncmp(key, "ID_FS_VERSION=", 14) == 0) {
+ str = hal_util_strdup_valid_utf8(&key[14]);
+ g_strlcpy (hotplug_event->sysfs.fsversion, str, sizeof(hotplug_event->sysfs.fsversion));
+ g_free (str);
+ } else if (strncmp(key, "ID_FS_UUID=", 11) == 0) {
+ str = hal_util_strdup_valid_utf8(&key[11]);
+ g_strlcpy (hotplug_event->sysfs.fsuuid, str, sizeof(hotplug_event->sysfs.fsuuid));
+ g_free (str);
+ } else if (strncmp(key, "ID_FS_LABEL=", 12) == 0) {
+ str = hal_util_strdup_valid_utf8(&key[12]);
+ g_strlcpy (hotplug_event->sysfs.fslabel, str, sizeof(hotplug_event->sysfs.fslabel));
+ g_free (str);
+ }
}
- if (!devpath) {
- HAL_INFO (("missing DEVPATH"));
- goto out;
- }
if (!action) {
HAL_INFO (("missing ACTION"));
- goto out;
+ goto invalid;
}
- if (!subsystem) {
+ if (hotplug_event->sysfs.sysfs_path == NULL) {
+ HAL_INFO (("missing DEVPATH"));
+ goto invalid;
+ }
+ if (hotplug_event->sysfs.subsystem == NULL) {
HAL_INFO (("missing SUSBSYSTEM"));
- goto out;
+ goto invalid;
}
- if (!devname)
- devname = "";
- HAL_INFO (("SEQNUM=%lld, ACTION=%s, SUBSYS=%s, SYSFSPATH=%s, DEVNAME=%s, IFINDEX=%d",
- seqnum, action, subsystem, devpath, devname, ifindex));
+ HAL_INFO (("SEQNUM=%lld, ACTION=%s, SUBSYSTEM=%s, DEVPATH=%s, DEVNAME=%s, IFINDEX=%d",
+ hotplug_event->sysfs.seqnum, action, hotplug_event->sysfs.subsystem, hotplug_event->sysfs.sysfs_path,
+ hotplug_event->sysfs.device_file, hotplug_event->sysfs.net_ifindex));
if (strcmp (action, "add") == 0) {
- HotplugEvent *hotplug_event;
-
- hotplug_event = g_new0 (HotplugEvent, 1);
hotplug_event->action = HOTPLUG_ACTION_ADD;
- hotplug_event->type = HOTPLUG_EVENT_SYSFS;
- g_strlcpy (hotplug_event->sysfs.subsystem, subsystem, sizeof (hotplug_event->sysfs.subsystem));
- g_snprintf (hotplug_event->sysfs.sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path), "%s%s",
- hal_sysfs_path, devpath);
- g_strlcpy (hotplug_event->sysfs.device_file, devname, sizeof (hotplug_event->sysfs.device_file));
- hotplug_event->sysfs.net_ifindex = ifindex;
-
- /* queue up and process */
hotplug_event_enqueue (hotplug_event);
hotplug_event_process_queue ();
+ goto out;
+ }
- } else if (strcmp (action, "remove") == 0) {
- HotplugEvent *hotplug_event;
-
- hotplug_event = g_new0 (HotplugEvent, 1);
+ if (strcmp (action, "remove") == 0) {
hotplug_event->action = HOTPLUG_ACTION_REMOVE;
- hotplug_event->type = HOTPLUG_EVENT_SYSFS;
- g_strlcpy (hotplug_event->sysfs.subsystem, subsystem, sizeof (hotplug_event->sysfs.subsystem));
- g_snprintf (hotplug_event->sysfs.sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path), "%s%s",
- hal_sysfs_path, devpath);
- g_strlcpy (hotplug_event->sysfs.device_file, devname, sizeof (hotplug_event->sysfs.device_file));
- hotplug_event->sysfs.net_ifindex = ifindex;
-
- /* queue up and process */
hotplug_event_enqueue (hotplug_event);
hotplug_event_process_queue ();
+ goto out;
}
+invalid:
+ g_free (hotplug_event);
+
out:
return TRUE;
}
@@ -249,7 +268,6 @@
{
gchar path[HAL_PATH_MAX];
int udev_socket;
- int helper_socket;
struct sockaddr_un saddr;
socklen_t addrlen;
const int on = 1;
- Previous message: hal/drive_id Makefile.am, 1.1, NONE ata.c, 1.3, NONE ata.h, 1.1,
NONE drive_id.c, 1.4, NONE drive_id.h, 1.2, NONE logging.h,
1.2, NONE scsi.c, 1.3, NONE scsi.h, 1.1, NONE util.c, 1.2,
NONE util.h, 1.1, NONE
- Next message: hal/hald util.c,1.35,1.36 util.h,1.16,1.17
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the hal-commit
mailing list