hal/hald/linux2/probing Makefile.am, 1.2, 1.3 linux_dvd_rw_utils.c, NONE, 1.1 linux_dvd_rw_utils.h, NONE, 1.1 probe-storage.c, NONE, 1.1 probe-volume.c, NONE, 1.1

David Zeuthen david at freedesktop.org
Thu Feb 10 09:04:00 PST 2005


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

Modified Files:
	Makefile.am 
Added Files:
	linux_dvd_rw_utils.c linux_dvd_rw_utils.h probe-storage.c 
	probe-volume.c 
Log Message:
2005-02-10  David Zeuthen  <davidz at redhat.com>

	* volume_id/fat.c (volume_id_probe_vfat): Must have been a typo by Kay,
	changed from VOLUME_ID_DISKLABEL to VOLUME_ID_FILESYSTEM.

	* tools/fstab-sync.c (remove_udi): Remember to init the DBusError since
	some operations may fail.
	(main): Look at $HALD_ACTION for add, remove instead of first 
	positional parameter $1.

	* hald/linux2/probing/probe-volume.c: New file

	* hald/linux2/probing/probe-storage.c: New file

	* hald/linux2/probing/linux_dvd_rw_utils.[ch]: New files (imported
	from hal-0.4.x)

	* hald/linux2/probing/Makefile.am: Add rules for hald-probe-storage
	and hald-probe-volume

	* hald/linux2/addons/addon-storage.c: New file

	* hald/linux2/addons/Makefile.am: Add rules for hald-addon-storage

	* hald/linux2/osspec.c (sigio_handler): New function
	(sigio_iochn_data): New function
	(osspec_init): Set up signal handler for SIGIO and the neccesary
	pipes to handle it safely. Set up directory watcher for /etc and
	invoke blockdev_mtab_changed whenever that happens

	* hald/linux2/hotplug.c (hotplug_rescan_device): Call blockdev_*
	if appropriate

	* hald/linux2/blockdev.h: Add some new prototype for interacting
	with hotplug.c (much like what physdev.h and classdev.h)
	exported. Also add the prototype for a new function
	blockdev_mtab_changed.

	* hald/linux2/blockdev.c: Actually put some code here (the previous
	code was just boiler plate).

	* hald/util.h (struct HalHelperData_s): Add boolean already_issued_
	callback

	* hald/util.c (hal_util_get_string_from_file): Truncate whitespace
	from string read
	(hal_util_terminate_helper): Don't remove the child watcher source,
	but set a flag that we already did the callback and helper_child_exited
	will reap the child (including removing sources). This helps reap the
	zombies I've been seeing.
	(helper_child_timeout): -do-
	(helper_child_exited): Only do callback if we haven't already done
	so.

	* hald/debug-hald.sh: Another nice script for running gdb on hald;
	just run this script and invoke the run command from the gdb console.

	* hald/run-hald.sh: Also export ../tools so we can get fstab-sync
	going. Set HAL_FDI_SOURCE

	* hald/device_info.c (di_search_and_merge): Respect the env
	var HAL_FDI_SOURCE which is useful for development as hald will
	read you local .fdi files

	* fdi/90defaultpolicy/storage-policy.fdi: Temporarily add
	fstab-sync add/rem callouts (mental note: move to other file
	soon); also add the media detection addon

	* fdi/90defaultpolicy/power-mgmt-policy.fdi: New file

	* fdi/90defaultpolicy/Makefile.am (fdi90defaultpolicydir): Add
	power-mgmt-policy.fdi



Index: Makefile.am
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/probing/Makefile.am,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Makefile.am	4 Feb 2005 05:24:25 -0000	1.2
+++ Makefile.am	10 Feb 2005 17:03:57 -0000	1.3
@@ -8,7 +8,7 @@
 	-I$(top_srcdir) \
 	@PACKAGE_CFLAGS@
 
-libexec_PROGRAMS = hald-probe-input hald-probe-hiddev
+libexec_PROGRAMS = hald-probe-input hald-probe-hiddev hald-probe-storage hald-probe-volume
 
 hald_probe_input_SOURCES = probe-input.c
 hald_probe_input_LDADD = $(top_builddir)/libhal/libhal.la
@@ -16,6 +16,12 @@
 hald_probe_hiddev_SOURCES = probe-hiddev.c
 hald_probe_hiddev_LDADD = $(top_builddir)/libhal/libhal.la
 
+hald_probe_storage_SOURCES = probe-storage.c linux_dvd_rw_utils.c linux_dvd_rw_utils.h
+hald_probe_storage_LDADD = $(top_builddir)/libhal/libhal.la $(top_builddir)/drive_id/libdrive_id.la $(top_builddir)/volume_id/libvolume_id.la
+
+hald_probe_volume_SOURCES = probe-volume.c linux_dvd_rw_utils.c linux_dvd_rw_utils.h
+hald_probe_volume_LDADD = $(top_builddir)/libhal/libhal.la $(top_builddir)/drive_id/libdrive_id.la $(top_builddir)/volume_id/libvolume_id.la
+
 
 
 

--- NEW FILE: linux_dvd_rw_utils.c ---
/*
 * This is part of dvd+rw-tools by Andy Polyakov <appro at fy.chalmers.se>
 *
 * Use-it-on-your-own-risk, GPL bless...
 *
 * For further details see http://fy.chalmers.se/~appro/linux/DVD+RW/
*/

#define CREAM_ON_ERRNO(s)	do {				\
    switch ((s)[2]&0x0F)					\
    {	case 2:	if ((s)[12]==4) errno=EAGAIN;	break;		\
	case 5:	errno=EINVAL;					\
		if ((s)[13]==0)					\
		{   if ((s)[12]==0x21)		errno=ENOSPC;	\
		    else if ((s)[12]==0x20)	errno=ENODEV;	\
		}						\
		break;						\
    }								\
} while(0)
#define ERRCODE(s)	((((s)[2]&0x0F)<<16)|((s)[12]<<8)|((s)[13]))
#define	SK(errcode)	(((errcode)>>16)&0xF)
#define	ASC(errcode)	(((errcode)>>8)&0xFF)
#define ASCQ(errcode)	((errcode)&0xFF)

#ifndef _LARGEFILE_SOURCE
#define _LARGEFILE_SOURCE
#endif
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/cdrom.h>
#include <errno.h>
#include <string.h>
#include <mntent.h>
#include <sys/wait.h>
#include <sys/utsname.h>
#include <scsi/scsi.h>
#include <scsi/sg.h>
#include <poll.h>
#include <sys/time.h>

#include "linux_dvd_rw_utils.h"

typedef enum {
	NONE = CGC_DATA_NONE,	// 3
	READ = CGC_DATA_READ,	// 2
	WRITE = CGC_DATA_WRITE	// 1
} Direction;

typedef struct ScsiCommand ScsiCommand;

struct ScsiCommand {
	int fd;
	int autoclose;
	char *filename;
	struct cdrom_generic_command cgc;
	union {
		struct request_sense s;
		unsigned char u[18];
	} _sense;
	struct sg_io_hdr sg_io;
};

#define DIRECTION(i) (Dir_xlate[i]);

/* 1,CGC_DATA_WRITE
 * 2,CGC_DATA_READ
 * 3,CGC_DATA_NONE
 */
const int Dir_xlate[4] = {
	0,			// implementation-dependent...
	SG_DXFER_TO_DEV,	// 1,CGC_DATA_WRITE
	SG_DXFER_FROM_DEV,	// 2,CGC_DATA_READ
	SG_DXFER_NONE		// 3,CGC_DATA_NONE
};

static ScsiCommand *
scsi_command_new (void)
{
	ScsiCommand *cmd;

	cmd = (ScsiCommand *) malloc (sizeof (ScsiCommand));
	memset (cmd, 0, sizeof (ScsiCommand));
	cmd->fd = -1;
	cmd->filename = NULL;
	cmd->autoclose = 1;

	return cmd;
}

static ScsiCommand *
scsi_command_new_from_fd (int f)
{
	ScsiCommand *cmd;

	cmd = scsi_command_new ();
	cmd->fd = f;
	cmd->autoclose = 0;

	return cmd;
}

static void
scsi_command_free (ScsiCommand * cmd)
{
	if (cmd->fd >= 0 && cmd->autoclose) {
		close (cmd->fd);
		cmd->fd = -1;
	}
	if (cmd->filename) {
		free (cmd->filename);
		cmd->filename = NULL;
	}

	free (cmd);
}

static int
scsi_command_transport (ScsiCommand * cmd, Direction dir, void *buf,
			size_t sz)
{
	int ret = 0;

	cmd->sg_io.dxferp = buf;
	cmd->sg_io.dxfer_len = sz;
	cmd->sg_io.dxfer_direction = DIRECTION (dir);

	if (ioctl (cmd->fd, SG_IO, &cmd->sg_io))
		return -1;

	if ((cmd->sg_io.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
		errno = EIO;
		ret = -1;
		if (cmd->sg_io.masked_status & CHECK_CONDITION) {
			CREAM_ON_ERRNO (cmd->sg_io.sbp);
			ret = ERRCODE (cmd->sg_io.sbp);
			if (ret == 0)
				ret = -1;
		}
	}

	return ret;
}

static void
scsi_command_init (ScsiCommand * cmd, size_t i, int arg)
{
	if (i == 0) {
		memset (&cmd->cgc, 0, sizeof (cmd->cgc));
		memset (&cmd->_sense, 0, sizeof (cmd->_sense));
		cmd->cgc.quiet = 1;
		cmd->cgc.sense = &cmd->_sense.s;
		memset (&cmd->sg_io, 0, sizeof (cmd->sg_io));
		cmd->sg_io.interface_id = 'S';
		cmd->sg_io.mx_sb_len = sizeof (cmd->_sense);
		cmd->sg_io.cmdp = cmd->cgc.cmd;
		cmd->sg_io.sbp = cmd->_sense.u;
		cmd->sg_io.flags = SG_FLAG_LUN_INHIBIT | SG_FLAG_DIRECT_IO;
	}
	cmd->sg_io.cmd_len = i + 1;
	cmd->cgc.cmd[i] = arg;
}

int
get_dvd_r_rw_profile (int fd)
{
	ScsiCommand *cmd;
	int retval = -1;
	unsigned char page[20];
	unsigned char *list;
	int i, len;

	cmd = scsi_command_new_from_fd (fd);

	scsi_command_init (cmd, 0, 0x46);
	scsi_command_init (cmd, 1, 2);
	scsi_command_init (cmd, 8, 8);
	scsi_command_init (cmd, 9, 0);
	if (scsi_command_transport (cmd, READ, page, 8)) {
		/* GET CONFIGURATION failed */
		scsi_command_free (cmd);
		return -1;
	}

	/* See if it's 2 gen drive by checking if DVD+R profile is an option */
	len = 4 + (page[0] << 24 | page[1] << 16 | page[2] << 8 | page[3]);
	if (len > 264) {
		scsi_command_free (cmd);
		/* insane profile list length */
		return -1;
	}

	list = (unsigned char *) malloc (len);

	scsi_command_init (cmd, 0, 0x46);
	scsi_command_init (cmd, 1, 2);
	scsi_command_init (cmd, 7, len >> 8);
	scsi_command_init (cmd, 8, len);
	scsi_command_init (cmd, 9, 0);
	if (scsi_command_transport (cmd, READ, list, len)) {
		/* GET CONFIGURATION failed */
		scsi_command_free (cmd);
		free (list);
		return -1;
	}

	for (i = 12; i < list[11]; i += 4) {
		int profile = (list[i] << 8 | list[i + 1]);
		/* 0x1B: DVD+R
		 * 0x1A: DVD+RW */
		if (profile == 0x1B) {
			if (retval == 1)
				retval = 2;
			else
				retval = 0;
		} else if (profile == 0x1A) {
			if (retval == 0)
				retval = 2;
			else
				retval = 1;
		}
	}

	scsi_command_free (cmd);
	free (list);

	return retval;
}

static unsigned char *
pull_page2a_from_fd (int fd)
{
	ScsiCommand *cmd;
	unsigned char header[12], *page2A;
	unsigned int len, bdlen;

	cmd = scsi_command_new_from_fd (fd);

	scsi_command_init (cmd, 0, 0x5A);	/* MODE SENSE */
	scsi_command_init (cmd, 1, 0x08);	/* Disable Block Descriptors */
	scsi_command_init (cmd, 2, 0x2A);	/* Capabilities and Mechanical Status */
	scsi_command_init (cmd, 8, sizeof (header));	/* header only to start with */
	scsi_command_init (cmd, 9, 0);

	if (scsi_command_transport (cmd, READ, header, sizeof (header))) {
		/* MODE SENSE failed */
		scsi_command_free (cmd);
		return NULL;
	}

	len = (header[0] << 8 | header[1]) + 2;
	bdlen = header[6] << 8 | header[7];

	/* should never happen as we set "DBD" above */
	if (bdlen) {
		if (len < (8 + bdlen + 30)) {
			/* LUN impossible to bear with */
			scsi_command_free (cmd);
			return NULL;
		}
	} else if (len < (8 + 2 + (unsigned int) header[9])) {
		/* SANYO does this. */
		len = 8 + 2 + header[9];
	}

	page2A = (unsigned char *) malloc (len);
	if (page2A == NULL) {
		/* ENOMEM */
		scsi_command_free (cmd);
		return NULL;
	}

	scsi_command_init (cmd, 0, 0x5A);	/* MODE SENSE */
	scsi_command_init (cmd, 1, 0x08);	/* Disable Block Descriptors */
	scsi_command_init (cmd, 2, 0x2A);	/* Capabilities and Mechanical Status */
	scsi_command_init (cmd, 7, len >> 8);
	scsi_command_init (cmd, 8, len);	/* Real length */
	scsi_command_init (cmd, 9, 0);
	if (scsi_command_transport (cmd, READ, page2A, len)) {
		/* MODE SENSE failed */
		scsi_command_free (cmd);
		free (page2A);
		return NULL;
	}

	scsi_command_free (cmd);

	len -= 2;
	/* paranoia */
	if (len < ((unsigned int) page2A[0] << 8 | page2A[1])) {
		page2A[0] = len >> 8;
		page2A[1] = len;
	}

	return page2A;
}

int
get_read_write_speed (int fd, int *read_speed, int *write_speed)
{
	unsigned char *page2A;
	int len, hlen;
	unsigned char *p;

	*read_speed = 0;
	*write_speed = 0;

	page2A = pull_page2a_from_fd (fd);
	if (page2A == NULL) {
		printf ("Failed to get Page 2A\n");
		/* Failed to get Page 2A */
		return -1;
	}

	len = (page2A[0] << 8 | page2A[1]) + 2;
	hlen = 8 + (page2A[6] << 8 | page2A[7]);
	p = page2A + hlen;

	/* Values guessed from the cd_mode_page_2A struct
	 * in cdrecord's libscg/scg/scsireg.h */
	if (len < (hlen + 30) || p[1] < (30 - 2)) {
		/* no MMC-3 "Current Write Speed" present,
		 * try to use the MMC-2 one */
		if (len < (hlen + 20) || p[1] < (20 - 2))
			*write_speed = 0;
		else
			*write_speed = p[18] << 8 | p[19];
	} else {
		*write_speed = p[28] << 8 | p[29];
	}

	if (len >= hlen+9)
	    *read_speed = p[8] << 8 | p[9];
	else
	    *read_speed = 0;

	free (page2A);

	return 0;
}

int
get_disc_type (int fd)
{
	ScsiCommand *cmd;
	int retval = -1;
	unsigned char header[8];

	cmd = scsi_command_new_from_fd (fd);

	scsi_command_init (cmd, 0, 0x46);
	scsi_command_init (cmd, 1, 1);
	scsi_command_init (cmd, 8, 8);
	scsi_command_init (cmd, 9, 0);
	if (scsi_command_transport (cmd, READ, header, 8)) {
		/* GET CONFIGURATION failed */
		scsi_command_free (cmd);
		return -1;
	}
	
	retval = (header[6]<<8)|(header[7]);


	scsi_command_free (cmd);
	return retval;
}


int
disc_is_appendable (int fd)
{
	ScsiCommand *cmd;
	int retval = -1;
	unsigned char header[32];

	cmd = scsi_command_new_from_fd (fd);

	/* see section 5.19 of MMC-3 from http://www.t10.org/drafts.htm#mmc3 */
	scsi_command_init (cmd, 0, 0x51); /* READ_DISC_INFORMATION */
	scsi_command_init (cmd, 8, 32);
	scsi_command_init (cmd, 9, 0);
	if (scsi_command_transport (cmd, READ, header, 32)) {
		/* READ_DISC_INFORMATION failed */
		scsi_command_free (cmd);
		return 0;
	}
	
	retval = ((header[2]&0x03) == 0x01);

	scsi_command_free (cmd);
	return retval;
}

int
disc_is_rewritable (int fd)
{
	ScsiCommand *cmd;
	int retval = -1;
	unsigned char header[32];

	cmd = scsi_command_new_from_fd (fd);

	/* see section 5.19 of MMC-3 from http://www.t10.org/drafts.htm#mmc3 */
	scsi_command_init (cmd, 0, 0x51); /* READ_DISC_INFORMATION */
	scsi_command_init (cmd, 8, 32);
	scsi_command_init (cmd, 9, 0);
	if (scsi_command_transport (cmd, READ, header, 32)) {
		/* READ_DISC_INFORMATION failed */
		scsi_command_free (cmd);
		return 0;
	}
	
	retval = ((header[2]&0x10) != 0);

	scsi_command_free (cmd);
	return retval;
}

--- NEW FILE: linux_dvd_rw_utils.h ---
//
// This is part of dvd+rw-tools by Andy Polyakov <appro at fy.chalmers.se>
//
// Use-it-on-your-own-risk, GPL bless...
//
// For further details see http://fy.chalmers.se/~appro/linux/DVD+RW/
//

#ifndef LINUX_DVD_RW_UTILS_H
#define LINUX_DVD_RW_UTILS_H

int get_dvd_r_rw_profile (int fd);
int get_read_write_speed (int fd, int *read_speed, int *write_speed);
int get_disc_type (int fd);
int disc_is_appendable (int fd);
int disc_is_rewritable (int fd);

#endif				/* LINUX_DVD_RW_UTILS_H */

--- NEW FILE: probe-storage.c ---
/***************************************************************************
 * CVSID: $Id: probe-storage.c,v 1.1 2005/02/10 17:03:57 david Exp $
 *
 * probe-storage.c : Probe storage devices
 *
 * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
 *
 * Licensed under the Academic Free License version 2.0
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 **************************************************************************/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <asm/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/kdev_t.h>
#include <linux/cdrom.h>
#include <linux/fs.h>

#include "libhal/libhal.h"

#include "drive_id/drive_id.h"
#include "volume_id/volume_id.h"

#include "linux_dvd_rw_utils.h"

#include "shared.h"

int 
main (int argc, char *argv[])
{
	int fd;
	int ret;
	char *udi;
	char *device_file;
	LibHalContext *ctx = NULL;
	DBusError error;
	DBusConnection *conn;
	char *bus;
	char *drive_type;

	fd = -1;

	/* assume failure */
	ret = 1;

	if ((udi = getenv ("UDI")) == NULL)
		goto out;
	if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL)
		goto out;
	if ((bus = getenv ("HAL_PROP_STORAGE_BUS")) == NULL)
		goto out;
	if ((drive_type = getenv ("HAL_PROP_STORAGE_DRIVE_TYPE")) == NULL)
		goto out;

	dbus_error_init (&error);
	if ((conn = dbus_bus_get (DBUS_BUS_SYSTEM, &error)) == NULL)
		goto out;

	if ((ctx = libhal_ctx_new ()) == NULL)
		goto out;
	if (!libhal_ctx_set_dbus_connection (ctx, conn))
		goto out;
	if (!libhal_ctx_init (ctx, &error))
		goto out;

	printf ("**************************************************\n");
	printf ("**************************************************\n");
	printf ("Doing probe-storage for %s (bus %s) (drive_type %s)\n", device_file, bus, drive_type);
	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;
		}
		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");
			}
			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;
		}
		
		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 (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);
		}
	}

	/* TODO: see if we got a file system on the main block device */



	ret = 0;

out:
	if (fd >= 0)
		close (fd);

	if (ctx != NULL) {
		dbus_error_init (&error);
		libhal_ctx_shutdown (ctx, &error);
		libhal_ctx_free (ctx);
	}

	return ret;
}

--- NEW FILE: probe-volume.c ---
/***************************************************************************
 * CVSID: $Id: probe-volume.c,v 1.1 2005/02/10 17:03:57 david Exp $
 *
 * probe-volume.c : Probe for volume type (filesystems etc.)
 *
 * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
 *
 * Licensed under the Academic Free License version 2.0
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 **************************************************************************/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <asm/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <linux/kdev_t.h>
#include <linux/cdrom.h>
#include <linux/fs.h>

#include "libhal/libhal.h"

#include "drive_id/drive_id.h"
#include "volume_id/volume_id.h"
#include "volume_id/msdos.h"

#include "linux_dvd_rw_utils.h"

#include "shared.h"

static void
set_volume_id_values (LibHalContext *ctx, const char *udi, struct volume_id *vid)
{
	char buf[256];
	const char *usage;
	DBusError error;

	dbus_error_init (&error);

	switch (vid->usage_id) {
	case VOLUME_ID_FILESYSTEM:
		usage = "filesystem";
		break;
	case VOLUME_ID_PARTITIONTABLE:
		usage = "partitiontable";
		break;
	case VOLUME_ID_OTHER:
		usage = "other";
		break;
	case VOLUME_ID_RAID:
		usage = "raid";
		break;
	case VOLUME_ID_UNUSED:
		libhal_device_set_property_string (ctx, udi, "info.product", "Volume (unused)", &error);
		usage = "unused";
		return;
	default:
		usage = "";
	}

	libhal_device_set_property_string (ctx, udi, "volume.fsusage", usage, &error);
	HAL_INFO (("volume.fsusage = '%s'", usage));

	libhal_device_set_property_string (ctx, udi, "volume.fstype", vid->type, &error);
	HAL_INFO (("volume.fstype = '%s'", vid->type));
	if (vid->type_version[0] != '\0') {
		libhal_device_set_property_string (ctx, udi, "volume.fsversion", vid->type_version, &error);
		HAL_INFO (("volume.fsversion = '%s'", vid->type_version));
	}
	libhal_device_set_property_string (ctx, udi, "volume.uuid", vid->uuid, &error);
	HAL_INFO (("volume.uuid = '%s'", vid->uuid));
	libhal_device_set_property_string (ctx, udi, "volume.label", vid->label, &error);
	HAL_INFO (("volume.label = '%s'", vid->label));

	if (vid->label[0] != '\0') {
		libhal_device_set_property_string (ctx, udi, "info.product", vid->label, &error);
	} else {
		snprintf (buf, sizeof (buf), "Volume (%s)", vid->type);
		libhal_device_set_property_string (ctx, udi, "info.product", buf, &error);
	}
}

int 
main (int argc, char *argv[])
{
	int fd;
	int ret;
	char *udi;
	char *device_file;
	LibHalContext *ctx = NULL;
	DBusError error;
	DBusConnection *conn;
	char *parent_udi;
	char *sysfs_path;
	struct volume_id *vid;
	char *stordev_dev_file;
	char *partition_number_str;
	unsigned int partition_number;
	unsigned int block_size;
	dbus_uint64_t vol_size;

	fd = -1;

	/* assume failure */
	ret = 1;

	if ((udi = getenv ("UDI")) == NULL)
		goto out;
	if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL)
		goto out;
	if ((parent_udi = getenv ("HAL_PROP_INFO_PARENT")) == NULL)
		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);

	dbus_error_init (&error);
	if ((conn = dbus_bus_get (DBUS_BUS_SYSTEM, &error)) == NULL)
		goto out;

	if ((ctx = libhal_ctx_new ()) == NULL)
		goto out;
	if (!libhal_ctx_set_dbus_connection (ctx, conn))
		goto out;
	if (!libhal_ctx_init (ctx, &error))
		goto out;

	printf ("**************************************************\n");
	printf ("**************************************************\n");
	printf ("Doing probe-volume for %s\n", device_file);
	printf ("**************************************************\n");
	printf ("**************************************************\n");

	fd = open (device_file, O_RDONLY);
	if (fd < 0)
		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) {
			set_volume_id_values(ctx, udi, vid);
		} else {
			libhal_device_set_property_string (ctx, udi, "info.product", "Volume", &error);
		}
		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);
				
				/* 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));
			}
		}
		volume_id_close(vid);
	}		
	libhal_free_string (stordev_dev_file);

	/* block size and total size */
	if (ioctl (fd, BLKSSZGET, &block_size) == 0) {
		HAL_INFO (("volume.block_size = %d", block_size));
		libhal_device_set_property_int (ctx, udi, "volume.block_size", block_size, &error);
	}
	if (ioctl (fd, BLKGETSIZE64, &vol_size) == 0) {
		HAL_INFO (("volume.size = %llu", vol_size));
		libhal_device_set_property_uint64 (ctx, udi, "volume.size", vol_size, &error);
	}

	ret = 0;

out:
	if (fd >= 0)
		close (fd);

	if (ctx != NULL) {
		dbus_error_init (&error);
		libhal_ctx_shutdown (ctx, &error);
		libhal_ctx_free (ctx);
	}

	return ret;

}




More information about the hal-commit mailing list