hal/hald/linux2/probing probe-storage.c, 1.1, 1.2 probe-volume.c, 1.1, 1.2

David Zeuthen david at freedesktop.org
Fri Feb 11 14:01:10 PST 2005


Update of /cvs/hal/hal/hald/linux2/probing
In directory gabe:/tmp/cvs-serv4717/hald/linux2/probing

Modified Files:
	probe-storage.c probe-volume.c 
Log Message:
2005-02-11  David Zeuthen  <davidz at redhat.com>

	With this path, all storage devices should be working just as
	well as on the 0.4.x branch. 

	In fact, since we're doing things in separate processes hald now
	nicely handles my very troublesome USB 6in1 card reader. There's
	other improvements too; we handle media with non-partitioned file
	systems _a lot nicer_, especially those on PCMCIA card
	readers (driven by ide-cs) since we now have logic to discard
	hotplug rem/add for those partitions.

	Rock on.

	* libhal/libhal.h: Add prototypes for libhal_device_rescan()
	and libhal_device_reprobe()

	* libhal/libhal.c (libhal_device_rescan): New function
	(libhal_device_reprobe): New function

	* hald/linux2/probing/probe-volume.c (main): Be able to probe for
	volumes on main block devices. Retrieve optical disc properties
	if applicable.

	* hald/linux2/probing/probe-storage.c (is_mounted): New function
	(main): Add a new option --only-check-for-media which is used on
	Rescan() of a storage device. Check for fs on main block device or
	a disc in the optical drive. Return code 2 if that is the case.

	* hald/linux2/addons/addon-storage.c (force_unmount): New function
	(unmount_childs): New function
	(is_mounted): New function
	(main): Do lazy unmount, if necessary, when media goes away. Handle
	polling on optical drives.

	* hald/linux2/hotplug.h: Add prototype for hotplug_event_reposted()
	and hotplug_event_enqueue_at_front().

	* hald/linux2/hotplug.c (hotplug_event_reposted): New function;
	like event_end but without deleting the hotplug event (useful
	for reordering events)
	(hotplug_event_enqueue_at_front): New function; to insert events
	at the front of the queue

	* hald/linux2/blockdev.c:
	(generate_fakevolume_hotplug_event_add_for_storage_device): New
	function (and what a nice long name :-/)
	(add_blockdev_probing_helper_done): Check result from hald-probe-
	storage and add a new fakevolume add event if one was detected.
	(hotplug_event_begin_add_blockdev): Handle fakevolume add events.
	Add some more debug spewage when things fail.
	(force_unmount): New function
	(hotplug_event_begin_remove_blockdev): Handle fakevolume remove
	events; reorder queue to process non-handled volume before
	the storage device. Nice.
	(block_rescan_storage_done): New function
	(blockdev_rescan_device): Actually do something here; a Rescan()
	method call on a storage device will induce searching a filesystem
	on the main block device

	* hald/hald.c (main): Add new master_slave code but comment it out
	for now

	* fdi/20freedesktop/lexar-media-cf-reader.fdi: Fix up

	* fdi/20freedesktop/6in1-card-reader.fdi: Fix up to use new way
	of figuring vendor_id/product_id etc.



Index: probe-storage.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/probing/probe-storage.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- probe-storage.c	10 Feb 2005 17:03:57 -0000	1.1
+++ probe-storage.c	11 Feb 2005 22:01:08 -0000	1.2
@@ -40,6 +40,7 @@
 #include <linux/kdev_t.h>
 #include <linux/cdrom.h>
 #include <linux/fs.h>
+#include <mntent.h>
 
 #include "libhal/libhal.h"
 
@@ -50,6 +51,40 @@
 
 #include "shared.h"
 
+
+/** Check if a filesystem on a special device file is mounted
+ *
+ *  @param  device_file         Special device file, e.g. /dev/cdrom
+ *  @return                     TRUE iff there is a filesystem system mounted
+ *                              on the special device file
+ */
+static dbus_bool_t
+is_mounted (const char *device_file)
+{
+	FILE *f;
+	dbus_bool_t rc;
+	struct mntent mnt;
+	struct mntent *mnte;
+	char buf[512];
+
+	rc = FALSE;
+
+	if ((f = setmntent ("/etc/mtab", "r")) == NULL)
+		goto out;
+
+	while ((mnte = getmntent_r (f, &mnt, buf, sizeof(buf))) != NULL) {
+		if (strcmp (device_file, mnt.mnt_fsname) == 0) {
+			rc = TRUE;
+			goto out1;
+		}
+	}
+
+out1:
+	endmntent (f);
+out:
+	return rc;
+}
+
 int 
 main (int argc, char *argv[])
 {
@@ -62,6 +97,8 @@
 	DBusConnection *conn;
 	char *bus;
 	char *drive_type;
+	struct volume_id *vid;
+	dbus_bool_t only_check_for_fs;
 
 	fd = -1;
 
@@ -77,6 +114,11 @@
 	if ((drive_type = getenv ("HAL_PROP_STORAGE_DRIVE_TYPE")) == NULL)
 		goto out;
 
+	if (argc == 2 && strcmp (argv[1], "--only-check-for-media") == 0)
+		only_check_for_fs = TRUE;
+	else
+		only_check_for_fs = FALSE;
+
 	dbus_error_init (&error);
 	if ((conn = dbus_bus_get (DBUS_BUS_SYSTEM, &error)) == NULL)
 		goto out;
@@ -90,133 +132,236 @@
 
 	printf ("**************************************************\n");
 	printf ("**************************************************\n");
-	printf ("Doing probe-storage for %s (bus %s) (drive_type %s)\n", device_file, bus, drive_type);
+	printf ("Doing probe-storage for %s (bus %s) (drive_type %s) (--only-check-for-fs==%d)\n", 
+		device_file, bus, drive_type, only_check_for_fs);
 	printf ("**************************************************\n");
 	printf ("**************************************************\n");
 
-	fd = open (device_file, O_RDONLY | O_NONBLOCK);
-	if (fd < 0) {
-		printf ("Cannot open %s: %s\n", device_file, strerror (errno));
-		goto out;
-	}
-
-	/* Only do drive_id on IDE and real SCSI disks - specifically
-	 * not on USB which uses emulated SCSI since an INQUIRY on
-	 * most USB devices may crash the storage device if the
-	 * transfer length isn't exactly 36 bytes. See Red Hat bug
-	 * #145256 for details.
-	 */
-	if (strcmp (bus, "ide") == 0 ||
-	    strcmp (bus, "scsi") == 0) {
-		struct drive_id *did;
-
-		did = drive_id_open_fd (fd);
-		if (drive_id_probe_all (did) == 0) {
-			if (did->serial[0] != '\0')
-				if (!libhal_device_set_property_string (ctx, udi, "storage.serial", 
-									did->serial, &error))
-					goto out;
-
-			if (did->firmware[0] != '\0')
-				if (!libhal_device_set_property_string (ctx, udi, "storage.firmware_version", 
-									did->firmware, &error))
-					goto out;
+	if (!only_check_for_fs) {
+		fd = open (device_file, O_RDONLY | O_NONBLOCK);
+		if (fd < 0) {
+			printf ("Cannot open %s: %s\n", device_file, strerror (errno));
+			goto out;
 		}
-		drive_id_close (did);		
-	}
 
-#if 0
-	/* TODO: test for SATA drives once that gets exported to user space */
-	{
-		int fd;
-		unsigned char unused;
-		
-		if ((fd = open (device_file, O_RDONLY|O_NDELAY)) != -1) {
-			if (ioctl (fd, ATA_IOC_GET_IO32, &unused) >= 0) {
-				hal_device_property_set_string (stordev, "storage.bus", "sata");
+		/* Only do drive_id on IDE and real SCSI disks - specifically
+		 * not on USB which uses emulated SCSI since an INQUIRY on
+		 * most USB devices may crash the storage device if the
+		 * transfer length isn't exactly 36 bytes. See Red Hat bug
+		 * #145256 for details.
+		 */
+		if (strcmp (bus, "ide") == 0 ||
+		    strcmp (bus, "scsi") == 0) {
+			struct drive_id *did;
+			
+			did = drive_id_open_fd (fd);
+			if (drive_id_probe_all (did) == 0) {
+				if (did->serial[0] != '\0')
+					if (!libhal_device_set_property_string (ctx, udi, "storage.serial", 
+										did->serial, &error))
+						goto out;
+				
+				if (did->firmware[0] != '\0')
+					if (!libhal_device_set_property_string (ctx, udi, "storage.firmware_version", 
+										did->firmware, &error))
+						goto out;
 			}
-			close (fd);
-		}
-	}
-#endif
-
-	/* Get properties for CD-ROM drive */
-	if (strcmp (drive_type, "cdrom") == 0) {
-		int capabilities;
-		int read_speed, write_speed;
-
-		if( ioctl (fd, CDROM_SET_OPTIONS, CDO_USE_FFLAGS) < 0 ) {
-			HAL_ERROR (("CDROM_SET_OPTIONS failed: %s\n", strerror(errno)));
-			goto out;
+			drive_id_close (did);		
 		}
-		
-		capabilities = ioctl (fd, CDROM_GET_CAPABILITY, 0);
-		if (capabilities < 0)
-			goto out;
-		
-		libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdr", FALSE, &error);
-		libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdrw", FALSE, &error);
-		libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvd", FALSE, &error);
-		libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdr", FALSE, &error);
-		libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdrw", FALSE, &error);
-		libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdram", FALSE, &error);
-		libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusr", FALSE, &error);
-		libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrw", FALSE, &error);
 
-		if (capabilities & CDC_CD_R) {
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdr", TRUE, &error);
+#if 0
+		/* TODO: test for SATA drives once that gets exported to user space */
+		{
+			int fd;
+			unsigned char unused;
+			
+			if ((fd = open (device_file, O_RDONLY|O_NDELAY)) != -1) {
+				if (ioctl (fd, ATA_IOC_GET_IO32, &unused) >= 0) {
+					hal_device_property_set_string (stordev, "storage.bus", "sata");
+				}
+				close (fd);
 		}
-		
-		if (capabilities & CDC_CD_RW) {
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdrw", TRUE, &error);
 		}
-		if (capabilities & CDC_DVD) {
-			int profile;
+#endif
+
+		/* Get properties for CD-ROM drive */
+		if (strcmp (drive_type, "cdrom") == 0) {
+			int capabilities;
+			int read_speed, write_speed;
 			
-			/** @todo FIXME BUG XXX: need to check for dvdrw (prolly need to rewrite much of 
-			 *  the linux_dvdrw_utils.c file)
-			 */
+			if( ioctl (fd, CDROM_SET_OPTIONS, CDO_USE_FFLAGS) < 0 ) {
+				HAL_ERROR (("CDROM_SET_OPTIONS failed: %s\n", strerror(errno)));
+				goto out;
+			}
 			
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvd", TRUE, &error);
+			capabilities = ioctl (fd, CDROM_GET_CAPABILITY, 0);
+			if (capabilities < 0)
+				goto out;
 			
-			profile = get_dvd_r_rw_profile (fd);
-			if (profile == 2) {
-				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusr", TRUE, &error);
-				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrw", TRUE, &error);
-			} else if (profile == 0) {
-				libhal_device_set_property_bool(ctx, udi, "storage.cdrom.dvdplusr", TRUE, &error);
-			} else if (profile == 1) {
-				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrw", TRUE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdr", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdrw", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvd", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdr", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdrw", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdram", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusr", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrw", FALSE, &error);
+			
+			if (capabilities & CDC_CD_R) {
+				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdr", TRUE, &error);
+			}
+			
+			if (capabilities & CDC_CD_RW) {
+				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdrw", TRUE, &error);
+			}
+			if (capabilities & CDC_DVD) {
+				int profile;
+				
+				/** @todo FIXME BUG XXX: need to check for dvdrw (prolly need to rewrite much of 
+				 *  the linux_dvdrw_utils.c file)
+				 */
+				
+				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvd", TRUE, &error);
+				
+				profile = get_dvd_r_rw_profile (fd);
+				if (profile == 2) {
+					libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusr", TRUE, &error);
+					libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrw", TRUE, &error);
+				} else if (profile == 0) {
+					libhal_device_set_property_bool(ctx, udi, "storage.cdrom.dvdplusr", TRUE, &error);
+				} else if (profile == 1) {
+					libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrw", TRUE, &error);
+				}
+			}
+			if (capabilities & CDC_DVD_R) {
+				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdr", TRUE, &error);
+			}
+			if (capabilities & CDC_DVD_RAM) {
+				libhal_device_set_property_bool (ctx, udi, "storage.dvdram", TRUE, &error);
+			}
+			
+			/* while we're at it, check if we support media changed */
+			if (capabilities & CDC_MEDIA_CHANGED) {
+				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.support_media_changed", TRUE, &error);
+			} else {
+				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.support_media_changed", FALSE, &error);
+			}
+			
+			if (get_read_write_speed(fd, &read_speed, &write_speed) >= 0) {
+				libhal_device_set_property_int (ctx, udi, "storage.cdrom.read_speed", read_speed, &error);
+				if (write_speed > 0)
+					libhal_device_set_property_int (ctx, udi, "storage.cdrom.write_speed", write_speed, &error);
+				else
+					libhal_device_set_property_int (ctx, udi, "storage.cdrom.write_speed", 0, &error);
 			}
-		}
-		if (capabilities & CDC_DVD_R) {
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdr", TRUE, &error);
-		}
-		if (capabilities & CDC_DVD_RAM) {
-			libhal_device_set_property_bool (ctx, udi, "storage.dvdram", TRUE, &error);
 		}
 		
-		/* while we're at it, check if we support media changed */
-		if (capabilities & CDC_MEDIA_CHANGED) {
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.support_media_changed", TRUE, &error);
+		close (fd);
+	} /* !only_check_for_fs */
+
+	ret = 0;
+
+	/* See if we got a file system on the main block device - which 
+	 * means doing a data (non O_NONBLOCK) open - this might fail, 
+	 * especially if we don't have any media...
+	 */
+	fd = open (device_file, O_RDONLY | O_NONBLOCK);
+	if (fd < 0) {
+		printf ("Cannot open %s: %s\n", device_file, strerror (errno));
+		goto out;
+	}
+
+	/* probe for file system */
+	vid = volume_id_open_fd (fd);
+	if (vid != NULL) {
+		if (volume_id_probe_all (vid, 0, 0 /* size */) == 0) {
+			/* signal to hald that we've found a file system and a fakevolume
+			 * should be added - see hald/linux2/blockdev.c:add_blockdev_probing_helper_done()
+			 * and hald/linux2/blockdev.c:block_rescan_storage_done().
+			 */
+			if (vid->usage_id == VOLUME_ID_FILESYSTEM)
+				ret = 2;
 		} else {
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.support_media_changed", FALSE, &error);
-		}
-		
-		if (get_read_write_speed(fd, &read_speed, &write_speed) >= 0) {
-			libhal_device_set_property_int (ctx, udi, "storage.cdrom.read_speed", read_speed, &error);
-			if (write_speed > 0)
-				libhal_device_set_property_int (ctx, udi, "storage.cdrom.write_speed", write_speed, &error);
-			else
-				libhal_device_set_property_int (ctx, udi, "storage.cdrom.write_speed", 0, &error);
+			;
 		}
+		volume_id_close(vid);
 	}
 
-	/* TODO: see if we got a file system on the main block device */
+	/* Also return 2 if we're a cdrom and we got a disc */
+	if (ret != 2 && strcmp (drive_type, "cdrom") == 0) {
+		char *support_media_changed_str;
+		int support_media_changed;
+		int got_media;
+		int drive;
+
+		support_media_changed_str = getenv ("HAL_PROP_STORAGE_CDROM_SUPPORT_MEDIA_CHANGED");
+		if (support_media_changed_str != NULL && strcmp (support_media_changed_str, "true") == 0)
+			support_media_changed = TRUE;
+		else
+			support_media_changed = FALSE;
 
+		close (fd);
+		fd = open (device_file, O_RDONLY | O_NONBLOCK | O_EXCL);
+
+		if (fd < 0 && errno == EBUSY) {
+			/* this means the disc is mounted or some other app,
+			 * like a cd burner, has already opened O_EXCL */
+				
+			/* HOWEVER, when starting hald, a disc may be
+			 * mounted; so check /etc/mtab to see if it
+			 * actually is mounted. If it is we retry to open
+			 * without O_EXCL
+			 */
+			if (!is_mounted (device_file))
+				goto out;
 
+			fd = open (device_file, O_RDONLY | O_NONBLOCK);
+		}
 
-	ret = 0;
+		if (fd < 0) {
+			HAL_INFO (("open failed for %s: %s", device_file, strerror (errno))); 
+			goto out;
+		}
+
+		got_media = FALSE;
+
+		/* Check if a disc is in the drive
+		 *
+		 * @todo Use MMC-2 API if applicable
+		 */
+		drive = ioctl (fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
+		switch (drive) {
+			/* explicit fallthrough */
+		case CDS_NO_INFO:
+		case CDS_NO_DISC:
+		case CDS_TRAY_OPEN:
+		case CDS_DRIVE_NOT_READY:
+			break;
+			
+		case CDS_DISC_OK:
+			/* some CD-ROMs report CDS_DISK_OK even with an open
+			 * tray; if media check has the same value two times in
+			 * a row then this seems to be the case and we must not
+			 * report that there is a media in it. */
+			if (support_media_changed &&
+			    ioctl (fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT) && 
+			    ioctl (fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT)) {
+			} else {
+				got_media = TRUE;
+			}
+			break;
+			
+		case -1:
+			HAL_ERROR(("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)));
+			break;
+			
+		default:
+			break;
+		}
+
+		if (got_media)
+			ret = 2;
+	}
 
 out:
 	if (fd >= 0)

Index: probe-volume.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/probing/probe-volume.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- probe-volume.c	10 Feb 2005 17:03:57 -0000	1.1
+++ probe-volume.c	11 Feb 2005 22:01:08 -0000	1.2
@@ -119,6 +119,8 @@
 	struct volume_id *vid;
 	char *stordev_dev_file;
 	char *partition_number_str;
+	char *is_disc_str;
+	dbus_bool_t is_disc;
 	unsigned int partition_number;
 	unsigned int block_size;
 	dbus_uint64_t vol_size;
@@ -136,9 +138,17 @@
 		goto out;
 	if ((sysfs_path = getenv ("HAL_PROP_LINUX_SYSFS_PATH")) == NULL)
 		goto out;
-	if ((partition_number_str = getenv ("HAL_PROP_VOLUME_PARTITION_NUMBER")) == NULL)
-		goto out;
-	partition_number = (unsigned int) atoi (partition_number_str);
+	partition_number_str = getenv ("HAL_PROP_VOLUME_PARTITION_NUMBER");
+	if (partition_number_str != NULL)
+		partition_number = (unsigned int) atoi (partition_number_str);
+	else
+		partition_number = (unsigned int) -1;
+
+	is_disc_str = getenv ("HAL_PROP_VOLUME_IS_DISC");
+	if (is_disc_str != NULL && strcmp (is_disc_str, "true") == 0)
+		is_disc = TRUE;
+	else
+		is_disc = FALSE;
 
 	dbus_error_init (&error);
 	if ((conn = dbus_bus_get (DBUS_BUS_SYSTEM, &error)) == NULL)
@@ -172,46 +182,53 @@
 		volume_id_close(vid);
 	}
 
-	/* get partition type - presently we only support PC style partition tables */
-	if ((stordev_dev_file = libhal_device_get_property_string (ctx, parent_udi, "block.device", &error)) == NULL) {
-		goto out;
-	}
-	vid = volume_id_open_node (stordev_dev_file);
-	if (vid != NULL) {
- 		if (volume_id_probe_msdos_part_table (vid, 0) == 0) {
-			HAL_INFO (("Number of partitions = %d", vid->partition_count));
-			
-			if (partition_number > 0 && partition_number <= vid->partition_count) {
-				struct volume_id_partition *p;
-				p = &vid->partitions[partition_number-1];
-
-				libhal_device_set_property_int (ctx, udi,
-								"volume.partition.msdos_part_table_type",
-								p->partition_type_raw, &error);
+	/* get partition type (if we are from partitioned media)
+	 *
+	 * (presently we only support PC style partition tables)
+	 */
+	if (partition_number_str != NULL) {
+		if ((stordev_dev_file = libhal_device_get_property_string (
+			     ctx, parent_udi, "block.device", &error)) == NULL) {
+			goto out;
+		}
+		vid = volume_id_open_node (stordev_dev_file);
+		if (vid != NULL) {
+			if (volume_id_probe_msdos_part_table (vid, 0) == 0) {
+				HAL_INFO (("Number of partitions = %d", vid->partition_count));
 				
-				/* NOTE: We trust the type from the partition table
-				 * if it explicitly got correct entries for RAID and
-				 * LVM partitions.
-				 *
-				 * Btw, in general it's not a good idea to trust the
-				 * partition table type as many geek^Wexpert users use 
-				 * FAT filesystems on type 0x83 which is Linux.
-				 *
-				 * Linux RAID autodetect is 0xfd and Linux LVM is 0x8e
-				 */
-				if (p->partition_type_raw == 0xfd ||
-				    p->partition_type_raw == 0x8e ) {
-					libhal_device_set_property_string (ctx, udi, "volume.fsusage", "raid", &error);
-				}
+				if (partition_number > 0 && partition_number <= vid->partition_count) {
+					struct volume_id_partition *p;
+					p = &vid->partitions[partition_number-1];
+					
+					libhal_device_set_property_int (ctx, udi,
+									"volume.partition.msdos_part_table_type",
+									p->partition_type_raw, &error);
+					
+					/* NOTE: We trust the type from the partition table
+					 * if it explicitly got correct entries for RAID and
+					 * LVM partitions.
+					 *
+					 * Btw, in general it's not a good idea to trust the
+					 * partition table type as many geek^Wexpert users use 
+					 * FAT filesystems on type 0x83 which is Linux.
+					 *
+					 * Linux RAID autodetect is 0xfd and Linux LVM is 0x8e
+					 */
+					if (p->partition_type_raw == 0xfd ||
+					    p->partition_type_raw == 0x8e ) {
+						libhal_device_set_property_string (
+							ctx, udi, "volume.fsusage", "raid", &error);
+					}
 				
-			} else {
-				HAL_WARNING (("partition_number=%d not in [0;%d[", 
-					      partition_number, vid->partition_count));
+				} else {
+					HAL_WARNING (("partition_number=%d not in [0;%d[", 
+						      partition_number, vid->partition_count));
+				}
 			}
-		}
-		volume_id_close(vid);
-	}		
-	libhal_free_string (stordev_dev_file);
+			volume_id_close(vid);
+		}		
+		libhal_free_string (stordev_dev_file);
+	}
 
 	/* block size and total size */
 	if (ioctl (fd, BLKSSZGET, &block_size) == 0) {
@@ -223,8 +240,117 @@
 		libhal_device_set_property_uint64 (ctx, udi, "volume.size", vol_size, &error);
 	}
 
+	/* good so far */
 	ret = 0;
 
+	if (is_disc) {
+		int type;
+
+		/* defaults */
+		libhal_device_set_property_string (ctx, udi, "volume.disc.type", "unknown", &error);
+		libhal_device_set_property_bool (ctx, udi, "volume.disc.has_audio", FALSE, &error);
+		libhal_device_set_property_bool (ctx, udi, "volume.disc.has_data", FALSE, &error);
+		libhal_device_set_property_bool (ctx, udi, "volume.disc.is_blank", FALSE, &error);
+		libhal_device_set_property_bool (ctx, udi, "volume.disc.is_appendable", FALSE, &error);
+		libhal_device_set_property_bool (ctx, udi, "volume.disc.is_rewritable", FALSE, &error);
+
+		/* Suggested by Alex Larsson to get rid of log spewage
+		 * on Alan's cd changer (RH bug 130649) */
+		if (ioctl (fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) != CDS_DISC_OK) {
+			goto out;
+		}
+
+		/* check for audio/data/blank */
+		type = ioctl (fd, CDROM_DISC_STATUS, CDSL_CURRENT);
+		switch (type) {
+		case CDS_AUDIO:		/* audio CD */
+			libhal_device_set_property_bool (ctx, udi, "volume.disc.has_audio", TRUE, &error);
+			HAL_INFO (("Disc in %s has audio", device_file));
+			break;
+		case CDS_MIXED:		/* mixed mode CD */
+			libhal_device_set_property_bool (ctx, udi, "volume.disc.has_audio", TRUE, &error);
+			libhal_device_set_property_bool (ctx, udi, "volume.disc.has_data", TRUE, &error);
+			HAL_INFO (("Disc in %s has audio+data", device_file));
+			break;
+		case CDS_DATA_1:	/* data CD */
+		case CDS_DATA_2:
+		case CDS_XA_2_1:
+		case CDS_XA_2_2:
+			libhal_device_set_property_bool (ctx, udi, "volume.disc.has_data", TRUE, &error);
+			HAL_INFO (("Disc in %s has data", device_file));
+			break;
+		case CDS_NO_INFO:	/* blank or invalid CD */
+			libhal_device_set_property_bool (ctx, udi, "volume.disc.is_blank", TRUE, &error);
+			HAL_INFO (("Disc in %s is blank", device_file));
+			break;
+			
+		default:		/* should never see this */
+			libhal_device_set_property_string (ctx, udi, "volume.disc_type", "unknown", &error);
+			HAL_INFO (("Disc in %s returned unknown CDROM_DISC_STATUS", device_file));
+			break;
+		}
+		
+		/* see table 373 in MMC-3 for details on disc type
+		 * http://www.t10.org/drafts.htm#mmc3
+		 */
+		type = get_disc_type (fd);
+		HAL_INFO (("get_disc_type returned 0x%02x", type));
+		if (type != -1) {
+			switch (type) {
+			case 0x08: /* CD-ROM */
+				libhal_device_set_property_string (ctx, udi, "volume.disc.type", "cd_rom", &error);
+				break;
+			case 0x09: /* CD-R */
+				libhal_device_set_property_string (ctx, udi, "volume.disc.type", "cd_r", &error);
+				break;
+			case 0x0a: /* CD-RW */
+				libhal_device_set_property_string (ctx, udi, "volume.disc.type", "cd_rw", &error);
+				libhal_device_set_property_bool (ctx, udi, "volume.disc.is_rewritable", TRUE, &error);
+				break;
+			case 0x10: /* DVD-ROM */
+				libhal_device_set_property_string (ctx, udi, "volume.disc.type", "dvd_rom", &error);
+				break;
+			case 0x11: /* DVD-R Sequential */
+				libhal_device_set_property_string (ctx, udi, "volume.disc.type", "dvd_r", &error);
+				break;
+			case 0x12: /* DVD-RAM */
+				libhal_device_set_property_string (ctx, udi, "volume.disc.type", "dvd_ram", &error);
+				libhal_device_set_property_bool (ctx, udi, "volume.disc.is_rewritable", TRUE, &error);
+				break;
+			case 0x13: /* DVD-RW Restricted Overwrite */
+				libhal_device_set_property_string (ctx, udi, "volume.disc.type", "dvd_rw", &error);
+				libhal_device_set_property_bool (ctx, udi, "volume.disc.is_rewritable", TRUE, &error);
+				break;
+			case 0x14: /* DVD-RW Sequential */
+				libhal_device_set_property_string (ctx, udi, "volume.disc.type", "dvd_rw", &error);
+				libhal_device_set_property_bool (ctx, udi, "volume.disc.is_rewritable", TRUE, &error);
+				break;
+			case 0x1A: /* DVD+RW */
+				libhal_device_set_property_string (ctx, udi, "volume.disc.type", "dvd_plus_rw", &error);
+				libhal_device_set_property_bool (ctx, udi, "volume.disc.is_rewritable", TRUE, &error);
+				break;
+			case 0x1B: /* DVD+R */
+				libhal_device_set_property_string (ctx, udi, "volume.disc.type", "dvd_plus_r", &error);
+				libhal_device_set_property_bool (ctx, udi, "volume.disc.is_rewritable", TRUE, &error);
+				break;
+			default: 
+				break;
+			}
+		}
+
+		/* On some hardware the get_disc_type call fails,
+		   so we use this as a backup */
+		if (disc_is_rewritable (fd)) {
+			libhal_device_set_property_bool (ctx, udi, "volume.disc.is_rewritable", TRUE, &error);
+		}
+		
+		if (disc_is_appendable (fd)) {
+			libhal_device_set_property_bool (ctx, udi, "volume.disc.is_appendable", TRUE, &error);
+		}
+		
+	}
+
+
 out:
 	if (fd >= 0)
 		close (fd);




More information about the hal-commit mailing list