/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <strings.h>
#include <stdarg.h>
#include <fcntl.h>
#include <libintl.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <libhal.h>
#include <libhal-storage.h>
#include "rmm_common.h"
extern int rmm_debug;
static const char *action_strings[] = {
"eject",
"mount",
"remount",
"unmount",
"clear_mounts",
"closetray"
};
{
char **devices;
int nr;
/*
* setup D-Bus connection
*/
return (NULL);
}
dprintf("libhal_ctx_new failed");
return (NULL);
}
/*
* register callbacks
*/
}
}
if (propmod_cb != NULL) {
dprintf("property_watch_all failed %s",
return (NULL);
}
}
}
return (NULL);
}
/*
* The above functions do not guarantee that HAL is actually running.
* Check by invoking a method.
*/
return (NULL);
} else {
}
return (ctx);
}
void
{
(void) dbus_connection_unref(dbus_conn);
(void) libhal_ctx_free(hal_ctx);
}
/*
* find volume from any type of name, similar to the old media_findname()
* returns the LibHalDrive object and a list of LibHalVolume objects.
*/
{
char *p;
char lastc;
/* temporarily remove trailing slash */
if (*p == '/') {
lastc = *p;
*p = '\0';
} else {
p = NULL;
}
if (name[0] == '/') {
goto out;
} else {
goto out;
}
}
/* try volume label */
goto out;
}
out:
if (p != NULL) {
*p = lastc;
}
return (drive);
}
/*
* find default volume. Returns volume pointer and name in 'name'.
*/
{
int i;
/*
* Skip floppy if it has no media.
* XXX might want to actually check for media
* every time instead of relying on volcheck.
*/
"storage.removable.media_available", NULL)) {
break;
}
}
}
return (drive);
}
/*
* find volume by property=value
* returns the LibHalDrive object and a list of LibHalVolume objects.
* XXX add support for multiple properties, reduce D-Bus traffic
*/
{
LibHalVolume *v = NULL;
char **udis;
int num_udis;
int i;
/* get all devices with property=value */
return (NULL);
}
/* find volumes and drives among these devices */
for (i = 0; i < num_udis; i++) {
&error)) {
if (v != NULL) {
}
&error)) {
i_drive = i;
}
}
/* used prepend, preserve original order */
}
} else if (i_drive >= 0) {
}
return (drive);
}
static void
const char *device, char **drive_nicknames)
{
int i;
if (drive_nicknames != NULL) {
for (i = 0; drive_nicknames[i] != NULL; i++) {
drive_nicknames[i]);
}
}
if ((v != NULL) &&
(strlen(volume_label) > 0)) {
}
if ((v != NULL) &&
(strlen(mount_point) > 0)) {
}
(void) printf("\n");
}
/*
* print nicknames for each available volume
*
* print_mask:
* RMM_PRINT_MOUNTABLE print only mountable volumes
* RMM_PRINT_EJECTABLE print volume-less ejectable drives
*/
void
int print_mask)
{
char **udis;
int num_udis;
LibHalVolume *v;
const char *device;
char **nicknames;
int i;
GSList *j;
int nprinted;
return;
}
for (i = 0; i < num_udis; i++) {
continue;
}
/* find volumes belonging to this drive */
}
nprinted = 0;
v = (LibHalVolume *)(j->data);
if ((device = libhal_volume_get_device_file(v)) ==
NULL) {
continue;
}
if ((print_mask & RMM_PRINT_MOUNTABLE) &&
(libhal_volume_get_fsusage(v) !=
continue;
}
nprinted++;
}
if ((nprinted == 0) &&
(print_mask & RMM_PRINT_EJECTABLE) &&
}
}
}
/*
* find volume by nickname
* returns the LibHalDrive object and a list of LibHalVolume objects.
*/
{
char **udis;
int num_udis;
char **nicknames;
int i, j;
return (NULL);
}
/* find a drive by nickname */
continue;
}
}
}
}
/* found the drive, now find its volumes */
}
}
return (drive);
}
void
{
GSList *i;
}
}
/*
* Call HAL's Mount() method on the given device
*/
{
char *fstype;
"org.freedesktop.Hal.Device.Volume", "Mount"))) {
"mount failed for %s: cannot create dbus message\n", udi);
return (B_FALSE);
}
fstype = "";
if (mountpoint == NULL) {
mountpoint = "";
}
return (B_FALSE);
}
return (B_FALSE);
}
return (B_TRUE);
}
/*
* Call HAL's Unmount() method on the given device
*/
{
"org.freedesktop.Hal.Device.Volume", "Unmount"))) {
"unmount failed %s: cannot create dbus message\n", udi);
return (B_FALSE);
}
&opts, 0, DBUS_TYPE_INVALID)) {
return (B_FALSE);
}
return (B_FALSE);
}
return (B_TRUE);
}
/*
* Call HAL's Eject() method on the given device
*/
{
"org.freedesktop.Hal.Device.Storage", "Eject"))) {
return (B_FALSE);
}
return (B_FALSE);
}
return (B_FALSE);
}
return (B_TRUE);
}
/*
* Call HAL's CloseTray() method on the given device
*/
{
"org.freedesktop.Hal.Device.Storage", "CloseTray"))) {
"closetray failed for %s: cannot create dbus message\n",
udi);
return (B_FALSE);
}
dprintf("closetray %s: cannot append args to dbus message ",
udi);
return (B_FALSE);
}
return (B_FALSE);
}
return (B_TRUE);
}
/*
* Call HAL's Rescan() method on the given device
*/
{
"org.freedesktop.Hal.Device", "Rescan"))) {
dprintf("rescan failed for %s: cannot create dbus message\n",
udi);
return (B_FALSE);
}
return (B_FALSE);
}
return (B_TRUE);
}
{
"/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager",
"ClaimBranch"))) {
dprintf("cannot create dbus message\n");
return (B_FALSE);
}
dprintf("cannot append args to dbus message\n");
return (B_FALSE);
}
dprintf("cannot send dbus message\n");
return (B_FALSE);
}
return (B_TRUE);
}
{
"/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager",
"UnclaimBranch"))) {
dprintf("cannot create dbus message\n");
return (B_FALSE);
}
dprintf("cannot append args to dbus message\n");
return (B_FALSE);
}
dprintf("cannot send dbus message\n");
return (B_FALSE);
}
return (B_TRUE);
}
static boolean_t
{
char *mountp;
} else {
}
switch (action) {
case EJECT:
break;
case INSERT:
case REMOUNT:
if (libhal_volume_is_mounted(v)) {
goto done;
}
break;
case UNMOUNT:
if (!libhal_volume_is_mounted(v)) {
goto done;
}
break;
case CLOSETRAY:
break;
}
if (!ret) {
goto done;
}
switch (action) {
case EJECT:
break;
case INSERT:
case REMOUNT:
}
break;
case UNMOUNT:
break;
case CLOSETRAY:
break;
}
done:
return (ret);
}
/*
* top level action routine
*
* If non-null 'aa' is passed, it will be used, otherwise a local copy
* will be created.
*/
{
LibHalDrive *d;
LibHalVolume *v;
}
/* find the drive and its volumes */
if (d == NULL) {
return (B_FALSE);
}
d_udi = libhal_drive_get_udi(d);
goto out;
}
/*
* For those drives that do not require media eject,
* EJECT turns into UNMOUNT.
*/
}
/* per drive action */
goto out;
}
}
/* per volume action */
v = (LibHalVolume *)i->data;
udi = libhal_volume_get_udi(v);
continue;
}
dprintf("rmm_volume_aa_from_prop failed %s\n",
udi);
continue;
}
}
/* ejected above, just need postprocess */
}
if (ret) {
}
}
}
out:
return (ret);
}
/*
* rescan by name
* if name is NULL, rescan all drives
*/
{
const char *drive_udi;
char **udis;
int num_udis;
char *nickname;
int i;
return (B_FALSE);
}
num_udis = 1;
} else {
return (B_TRUE);
}
do_free_udis = TRUE;
}
for (i = 0; i < num_udis; i++) {
} else {
nickname = "";
}
}
gettext("rescan of %s failed: %s\n"),
continue;
}
if (query) {
"storage.removable.media_available", NULL);
if (ret) {
} else {
}
}
}
}
if (do_free_udis) {
}
return (ret);
}
/*
* set action_arg from volume properties
*/
{
const char *drive_udi;
char *volume_label;
char *mountpoint;
int len;
/* at least udi or volume must be supplied */
return (B_FALSE);
}
goto out;
}
}
dprintf("cannot get udi\n");
goto out;
}
}
dprintf("property %s not found %s\n",
"storage.solaris.legacy.symdev", drive_udi);
goto out;
}
dprintf("property %s not found %s\n",
goto out;
}
/* name is derived from volume label */
volume_label, len);
}
}
}
/* if no label, then unnamed_<mediatype> */
goto out;
}
}
"block.device", NULL))) {
goto out;
}
dprintf("property %s not found %s\n",
goto out;
}
"volume.fstype", NULL))) {
goto out;
}
"volume.is_partition", NULL)) {
dprintf("property %s not found %s\n",
"block.solaris.slice", udi);
goto out;
}
"volume.mount_point", NULL))) {
dprintf("property %s not found %s\n",
"volume.mount_point", udi);
goto out;
}
/*
* aa_mountpoint can be reallocated in rmm_volume_aa_update_mountpoint()
* won't have to choose between free() or libhal_free_string() later on
*/
goto out;
}
out:
}
if (!ret) {
}
return (ret);
}
/* ARGSUSED */
void
struct action_arg *aap)
{
}
}
void
{
}
}
}
}
}
}
}
}
}
/*
* get device's mount point from mnttab
*/
char *
{
FILE *f;
}
fclose(f);
}
return (mount_point);
}
/*
* get human readable string from error values
*/
const char *
{
const char *str;
} else {
switch (rmm_error) {
case RMM_EOK:
break;
case RMM_EDBUS_CONNECT:
break;
case RMM_EHAL_CONNECT:
break;
default:
break;
}
}
return (str);
}
void
{
}
}
static int
rmm_vold_isbadchar(int c)
{
int ret_val = 0;
switch (c) {
case '/':
case ';':
case '|':
ret_val = 1;
break;
default:
ret_val = 1;
}
}
return (ret_val);
}
char *
{
char *s = buf;
int i;
if (len > MAXNAMELEN) {
len = MAXNAMELEN;
}
for (i = 0; i < len; i++) {
if (name[i] == '\0') {
break;
}
} else if (rmm_vold_isbadchar((int)name[i])) {
*s++ = '_';
} else {
*s++ = name[i];
}
}
}
*s = '\0';
return (s);
}
/*
* swiped from mkdir.c
*/
int
{
int err;
char *slash;
return (0);
}
return (-1);
}
return (-1);
}
*slash = '\0';
*slash++ = '/';
return (err);
}
}
void
{
const char *p;
char *s;
if (rmm_debug == 0) {
return;
}
/* scan for %m and replace with errno msg */
p = fmt;
while (*p != '\0') {
if ((*p == '%') && (*(p+1) == 'm')) {
p += 2;
continue;
}
*s++ = *p++;
}
*s = '\0'; /* don't forget the null byte */
}