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