/***************************************************************************
* CVSID: $Id$
*
* libhal-storage.c : HAL convenience library for storage devices and volumes
*
* Copyright (C) 2004 Red Hat, Inc.
*
* Author: David Zeuthen <davidz@redhat.com>
*
* Licensed under the Academic Free License version 2.1
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libhal.h>
#include "libhal-storage.h"
#ifdef ENABLE_NLS
# include <libintl.h>
# ifdef gettext_noop
# else
# endif
#else
/* Stubs that do something close enough. */
#endif
typedef struct IconMappingEntry_s {
char *path;
struct LibHalStoragePolicy_s {
};
{
p = malloc (sizeof (LibHalStoragePolicy));
if (p == NULL)
goto out;
p->icon_mappings = NULL;
out:
return p;
}
void
{
IconMappingEntry *i;
IconMappingEntry *j;
/* free all icon mappings */
j = i->next;
free (i);
}
}
void
libhal_storage_policy_set_icon_path (LibHalStoragePolicy *policy, LibHalStoragePolicyIcon icon, const char *path)
{
IconMappingEntry *i;
/* see if it already exist */
goto out;
}
}
i = malloc (sizeof (IconMappingEntry));
if (i == NULL)
goto out;
policy->icon_mappings = i;
out:
return;
}
void
libhal_storage_policy_set_icon_mapping (LibHalStoragePolicy *policy, LibHalStoragePolicyIconPair *pairs)
{
}
}
const char *
{
IconMappingEntry *i;
const char *path;
goto out;
}
}
out:
return path;
}
char *
{
char *result;
int cur_str = 0;
do {
/* found the unit, display a comma number if result is a single digit */
} else {
}
goto out;
}
cur_str++;
} while (1);
out:
return result;
}
static void
fixup_string (char *s)
{
/* TODO: first strip leading and trailing whitespace */
/*g_strstrip (s);*/
/* TODO: could do nice things on all-upper case strings */
}
/* volume may be NULL (e.g. if drive supports removable media) */
char *
libhal_drive_policy_compute_display_name (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
{
char *name;
char *size_str;
char *vendormodel_str;
const char *model;
const char *vendor;
else
else
} else {
else {
}
}
if (drive_type==LIBHAL_DRIVE_TYPE_CDROM) {
/* Optical drive handling */
char *first;
char *second;
first = "CD-ROM";
first = "CD-R";
first = "CD-RW";
second = "";
second = "/DVD-ROM";
second = "/DVD+R";
second = "/DVD+RW";
second = "/DVD-R";
second = "/DVD-RW";
second = "/DVD-RAM";
if ((drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_DVDR) &&
second = "/DVD±R DL";
else
second = "/DVD±R";
}
if ((drive_cdrom_caps & LIBHAL_DRIVE_CDROM_CAPS_DVDRW) &&
second = "/DVD±RW DL";
else
second = "/DVD±RW";
}
second = "/BD-ROM";
second = "/BD-R";
second = "/BD-RE";
second = "/HD DVD-ROM";
second = "/HD DVD-R";
second = "/HD DVD-RW";
if (drive_is_hotpluggable) {
} else {
}
} else if (drive_type==LIBHAL_DRIVE_TYPE_FLOPPY) {
/* Floppy Drive handling */
else
/* Harddisks */
if (drive_is_hotpluggable) {
} else {
}
} else {
else
}
} else {
/* The rest - includes drives with removable Media */
if (strlen (vendormodel_str) > 0)
else
}
return name;
}
char *
libhal_volume_policy_compute_display_name (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
{
char *name;
char *size_str;
const char *volume_label;
const char *model;
const char *vendor;
/* If the volume label is available use that
*
* TODO: If label is a fully-qualified UNIX path don't use that
*/
if (volume_label != NULL) {
goto out;
}
/* Handle media in optical drives */
if (drive_type==LIBHAL_DRIVE_TYPE_CDROM) {
switch (libhal_volume_get_disc_type (volume)) {
default:
/* explict fallthrough */
break;
else
break;
else
break;
break;
else
break;
else
break;
else
break;
else
break;
else
break;
else
break;
break;
else
break;
else
break;
break;
else
break;
else
break;
}
/* Special case for pure audio disc */
}
goto out;
}
/* Fallback: size of media */
if (drive_is_removable) {
} else {
}
/* Fallback: Use drive name */
/*name = libhal_drive_policy_compute_display_name (drive, volume);*/
out:
return name;
}
char *
libhal_drive_policy_compute_icon_name (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
{
const char *name;
/* by design, the enums are laid out so we can do easy computations */
switch (drive_type) {
case LIBHAL_DRIVE_TYPE_DISK:
case LIBHAL_DRIVE_TYPE_CDROM:
case LIBHAL_DRIVE_TYPE_FLOPPY:
break;
default:
}
else
return NULL;
}
char *
libhal_volume_policy_compute_icon_name (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
{
const char *name;
/* by design, the enums are laid out so we can do easy computations */
if (libhal_volume_is_disc (volume)) {
goto out;
}
goto out;
}
switch (drive_type) {
case LIBHAL_DRIVE_TYPE_DISK:
case LIBHAL_DRIVE_TYPE_CDROM:
case LIBHAL_DRIVE_TYPE_FLOPPY:
break;
default:
}
out:
else
return NULL;
}
/** Policy function to determine if a volume should be visible in a desktop
* environment. This is useful to hide certain system volumes as bootstrap
* partitions, the /usr partition, swap partitions and other volumes that
* a unprivileged desktop user shouldn't know even exists.
*
* @param drive Drive that the volume is stemming from
* @param volume Volume
* @param policy Policy object
* @param target_mount_point The mount point that the volume is expected to
* be mounted at if not already mounted. This may
* then mount point isn't taking into account when
* evaluating whether the volume should be visible
* @return Whether the volume should be shown in a desktop
* environment.
*/
libhal_volume_policy_should_be_visible (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy,
const char *target_mount_point)
{
unsigned int i;
const char *label;
const char *mount_point;
const char *fstype;
const char *fhs23_toplevel_mount_points[] = {
"/",
"/bin",
"/boot",
"/dev",
"/etc",
"/home",
"/lib",
"/lib64",
"/media",
"/mnt",
"/opt",
"/root",
"/sbin",
"/srv",
"/tmp",
"/usr",
"/var",
"/proc",
"/sbin",
};
is_visible = FALSE;
/* skip if hal says it's not used as a filesystem */
goto out;
/* use target mount point if we're not mounted yet */
if (mount_point == NULL)
/* bail out if we don't know the filesystem */
goto out;
/* blacklist fhs2.3 top level mount points */
if (mount_point != NULL) {
for (i = 0; fhs23_toplevel_mount_points[i] != NULL; i++) {
goto out;
}
}
/* blacklist partitions with name 'bootstrap' of type HFS (Apple uses that) */
goto out;
/* only the real lucky mount points will make it this far :-) */
is_visible = TRUE;
out:
return is_visible;
}
/*************************************************************************/
struct LibHalDrive_s {
char *udi;
int device_major;
int device_minor;
char *device_file;
char *type_textual;
* IDE, USB, IEEE1394 device */
char *dedicated_icon_drive;
char *dedicated_icon_volume;
char *serial;
char *firmware_version;
char *desired_mount_point;
char *mount_filesystem;
char *partition_scheme;
char **capabilities;
};
struct LibHalVolume_s {
char *udi;
int device_major;
int device_minor;
char *device_file;
char *fsversion;
char *uuid;
char *storage_device;
unsigned int partition_number;
char *partition_scheme;
char *partition_type;
char *partition_label;
char *partition_uuid;
char **partition_flags;
unsigned int block_size;
unsigned int num_blocks;
char *desired_mount_point;
char *mount_filesystem;
char *crypto_backing_volume;
};
const char *
{
return drive->dedicated_icon_drive;
}
const char *
{
return drive->dedicated_icon_volume;
}
/** Free all resources used by a LibHalDrive object.
*
* @param drive Object to free
*/
void
{
return;
}
/** Free all resources used by a LibHalVolume object.
*
* @param vol Object to free
*/
void
{
return;
}
static char **
{
unsigned int num_elems;
unsigned int i;
char **res;
;
goto out;
for (i = 0; i < num_elems; i++)
out:
return res;
}
/* ok, hey, so this is a bit ugly */
#define LIBHAL_PROP_EXTRACT_END ;
#define LIBHAL_PROP_EXTRACT_INT(_property_, _where_) else if (strcmp (key, _property_) == 0 && type == LIBHAL_PROPERTY_TYPE_INT32) _where_ = libhal_psi_get_int (&it)
#define LIBHAL_PROP_EXTRACT_UINT64(_property_, _where_) else if (strcmp (key, _property_) == 0 && type == LIBHAL_PROPERTY_TYPE_UINT64) _where_ = libhal_psi_get_uint64 (&it)
#define LIBHAL_PROP_EXTRACT_STRING(_property_, _where_) else if (strcmp (key, _property_) == 0 && type == LIBHAL_PROPERTY_TYPE_STRING) _where_ = (libhal_psi_get_string (&it) != NULL && strlen (libhal_psi_get_string (&it)) > 0) ? strdup (libhal_psi_get_string (&it)) : NULL
#define LIBHAL_PROP_EXTRACT_BOOL(_property_, _where_) else if (strcmp (key, _property_) == 0 && type == LIBHAL_PROPERTY_TYPE_BOOLEAN) _where_ = libhal_psi_get_bool (&it)
#define LIBHAL_PROP_EXTRACT_BOOL_BITFIELD(_property_, _where_, _field_) else if (strcmp (key, _property_) == 0 && type == LIBHAL_PROPERTY_TYPE_BOOLEAN) _where_ |= libhal_psi_get_bool (&it) ? _field_ : 0
#define LIBHAL_PROP_EXTRACT_STRLIST(_property_, _where_) else if (strcmp (key, _property_) == 0 && type == LIBHAL_PROPERTY_TYPE_STRLIST) _where_ = my_strvdup (libhal_psi_get_strlist (&it))
/** Given a UDI for a HAL device of capability 'storage', this
* function retrieves all the relevant properties into convenient
* in-process data structures.
*
* @param hal_ctx libhal context
* @param udi HAL UDI
* @return LibHalDrive object or NULL if UDI is invalid
*/
{
char *bus_textual;
unsigned int i;
properties = NULL;
bus_textual = NULL;
dbus_error_init (&error);
goto error;
goto error;
goto error;
if (properties == NULL)
goto error;
/* we can count on hal to give us all these properties */
int type;
char *key;
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.cdr", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_CDR);
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.cdrw", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_CDRW);
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvd", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDROM);
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvdplusr", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDPLUSR);
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvdplusrw", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDPLUSRW);
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvdplusrwdl", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDPLUSRWDL);
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvdplusrdl", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDPLUSRDL);
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvdr", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDR);
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvdrw", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDRW);
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.dvdram", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_DVDRAM);
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.bd", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_BDROM);
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.bdr", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_BDR);
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.bdre", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_BDRE);
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.hddvd", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_HDDVDROM);
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.hddvdr", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_HDDVDR);
LIBHAL_PROP_EXTRACT_BOOL_BITFIELD ("storage.cdrom.hddvdrw", drive->cdrom_caps, LIBHAL_DRIVE_CDROM_CAPS_HDDVDRW);
}
if (drive->is_removable)
else
} else {
}
}
break;
break;
}
}
}
if (bus_textual != NULL) {
}
}
return drive;
return NULL;
}
const char *
{
return volume->storage_device;
}
{
return drive->physical_device;
}
{
return drive->requires_eject;
}
/** Given a UDI for a LIBHAL device of capability 'volume', this
* function retrieves all the relevant properties into convenient
* in-process data structures.
*
* @param hal_ctx libhal context
* @param udi HAL UDI
* @return LibHalVolume object or NULL if UDI is invalid
*/
{
char *disc_type_textual;
char *vol_fsusage_textual;
properties = NULL;
dbus_error_init (&error);
goto error;
goto error;
if (properties == NULL)
goto error;
/* we can count on hal to give us all these properties */
int type;
char *key;
LIBHAL_PROP_EXTRACT_UINT64 ("volume.partition.msdos_part_table_start", vol->msdos_part_table_start);
}
if (disc_type_textual != NULL) {
}
}
if (vol_fsusage_textual != NULL) {
} else {
}
}
return vol;
if (dbus_error_is_set (&error)) {
dbus_error_free (&error);
}
return NULL;
}
/** If the volume is on a drive with a MSDOS style partition table, return
* the partition table id.
*
* @param volume Volume object
* @return The partition type or -1 if volume is not
* a partition or the media the volume stems from
* isn't partition with a MS DOS style table
*/
int
{
return volume->msdos_part_table_type;
}
/** If the volume is on a drive with a MSDOS style partition table, return
* the partition start offset according to the partition table.
*
* @param volume Volume object
* @return The partition start offset or -1 if volume isnt
* a partition or the media the volume stems from
* isn't partition with a MS DOS style table
*/
{
return volume->msdos_part_table_start;
}
/** If the volume is on a drive with a MSDOS style partition table, return
* the partition size according to the partition table.
*
* @param volume Volume object
* @return The partition size or -1 if volume is not
* a partition or the media the volume stems from
* isn't partition with a MS DOS style table
*/
{
return volume->msdos_part_table_size;
}
/***********************************************************************/
*
* @param hal_ctx libhal context to use
* @return LibHalDrive object or NULL if it doesn't exist
*/
{
int i;
char **hal_udis;
int num_hal_udis;
char *found_udi;
dbus_error_init (&error);
goto out;
}
for (i = 0; i < num_hal_udis; i++) {
char *udi;
char *storage_udi;
dbus_error_init (&err1);
dbus_error_init (&err2);
if (storage_udi == NULL)
continue;
break;
}
}
out:
return result;
}
/** Get the volume object for a given device file.
*
* @param hal_ctx libhal context to use
* @return LibHalVolume object or NULL if it doesn't exist
*/
{
int i;
char **hal_udis;
int num_hal_udis;
char *found_udi;
dbus_error_init (&error);
goto out;
for (i = 0; i < num_hal_udis; i++) {
char *udi;
break;
}
}
out:
return result;
}
{
if (volume->volume_size > 0)
return volume->volume_size;
else
}
{
return volume->disc_capacity;
}
{
return drive->is_hotpluggable;
}
{
return drive->is_removable;
}
{
return drive->is_media_detected;
}
{
return drive->drive_size;
}
{
return drive->drive_media_size;
}
const char *
{
return drive->partition_scheme;
}
{
}
{
}
{
return drive->cdrom_caps;
}
unsigned int
{
return drive->device_major;
}
unsigned int
{
return drive->device_minor;
}
const char *
{
return drive->type_textual;
}
const char *
{
return drive->device_file;
}
const char *
{
}
const char *
{
}
const char *
{
return drive->firmware_version;
}
const char *
{
}
const char *
{
}
/*****************************************************************************/
const char *
{
}
const char *
{
return volume->device_file;
}
{
return volume->device_major;
}
{
return volume->device_minor;
}
const char *
{
}
const char *
{
}
{
}
{
return volume->is_mounted;
}
{
return volume->is_mounted_read_only;
}
{
return volume->is_partition;
}
{
}
unsigned int
{
return volume->partition_number;
}
const char *
{
return volume->partition_scheme;
}
const char *
{
return volume->partition_type;
}
const char *
{
return volume->partition_label;
}
const char *
{
return volume->partition_uuid;
}
const char **
{
return (const char **) volume->partition_flags;
}
{
return volume->partition_start_offset;
}
{
return volume->partition_media_size;
}
const char *
{
return volume->volume_label;
}
const char *
{
return volume->mount_point;
}
const char *
{
}
{
return volume->disc_has_audio;
}
{
return volume->disc_has_data;
}
{
return volume->disc_is_blank;
}
{
return volume->disc_is_rewritable;
}
{
return volume->disc_is_appendable;
}
{
}
{
return volume->ignore_volume;
}
char **
{
int i;
char **udis;
int num_udis;
const char *drive_udi;
char **result;
*num_volumes = 0;
goto out;
/* get initial list... */
dbus_error_init (&error);
goto out;
}
goto out;
/* ...and filter out the single UDI that is the drive itself */
for (i = 0; i < num_udis; i++) {
continue;
}
/* set last element (above removed UDI) to NULL for libhal_free_string_array()*/
out:
return result;
}
const char *
{
return volume->crypto_backing_volume;
}
char *
{
char **clear_devices;
int num_clear_devices;
char *result;
dbus_error_init (&error);
"volume.crypto_luks.clear.backing_volume",
&error);
if (clear_devices != NULL) {
if (num_clear_devices >= 1) {
}
}
return result;
}
/*************************************************************************/
char *
{
char *result;
dbus_error_init (&error);
return result;
}
{
dbus_error_init (&error);
return result;
}
char *
{
char *result;
dbus_error_init (&error);
return result;
}
char *
{
char *result;
dbus_error_init (&error);
return result;
}
/*************************************************************************/
{
printf ("should_mount=%d, no_partitions_hint=%d\n", drive->should_mount, drive->no_partitions_hint);
}
const char *
{
return drive->desired_mount_point;
}
/* safely strcat() at most the remaining space in 'dst' */
} while(0)
static void
{
if(hal_ctx == 0) {
return;
}
dbus_error_init (&error);
/* first collect from root computer device */
if (properties == NULL ) {
return;
}
int type;
char *key;
char *location;
is_imply_opt = TRUE;
if (only_collect_imply_opts) {
if (!is_imply_opt)
continue;
} else {
if (is_imply_opt)
continue;
}
if (libhal_psi_get_bool (&it)) {
/* see if option is already there */
if (strlen (options_string) > 0)
}
} else {
/* remove option if already there */
char *end;
location[0] = '\0';
} else {
}
}
}
}
}
}
const char *
{
const char *result;
/* collect options != ('pamconsole', 'user', 'users', 'defaults' options that imply other options) */
mopts_collect (drive->hal_ctx, stor_mount_option_default_begin, sizeof (stor_mount_option_default_begin),
/* ensure ('pamconsole', 'user', 'users', 'defaults' options that imply other options), are first */
mopts_collect (drive->hal_ctx, stor_mount_option_default_begin, sizeof (stor_mount_option_default_begin),
return result;
}
const char *
{
return drive->mount_filesystem;
}
libhal_volume_policy_is_mountable (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
{
}
const char *libhal_volume_policy_get_desired_mount_point (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
{
return volume->desired_mount_point;
}
const char *libhal_volume_policy_get_mount_options (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
{
const char *result;
/* ensure ('pamconsole', 'user', 'users', 'defaults' options that imply other options), are first */
mopts_collect (drive->hal_ctx, stor_mount_option_default_begin, sizeof (stor_mount_option_default_begin),
/* collect options != ('pamconsole', 'user', 'users', 'defaults' options that imply other options) */
mopts_collect (drive->hal_ctx, stor_mount_option_default_begin, sizeof (stor_mount_option_default_begin),
return result;
}
const char *libhal_volume_policy_get_mount_fs (LibHalDrive *drive, LibHalVolume *volume, LibHalStoragePolicy *policy)
{
return volume->mount_filesystem;
}
{
return drive->no_partitions_hint;
}
/** @} */