mirror of
https://github.com/systemd/systemd.git
synced 2024-11-05 15:21:37 +03:00
bf05675a20
GObject libudev access. Initial version from Bastien Nocera, current version by David Zeuthen.
892 lines
24 KiB
C
892 lines
24 KiB
C
/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||
*
|
||
* Copyright (C) 2008 David Zeuthen <davidz@redhat.com>
|
||
*
|
||
* This library is free software; you can redistribute it and/or
|
||
* modify it under the terms of the GNU Lesser General Public
|
||
* License as published by the Free Software Foundation; either
|
||
* version 2 of the License, or (at your option) any later version.
|
||
*
|
||
* This library 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
|
||
* Lesser General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU Lesser General Public
|
||
* License along with this library; 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 <stdlib.h>
|
||
#include <string.h>
|
||
|
||
#include "gudevdevice.h"
|
||
#include "gudevprivate.h"
|
||
|
||
/**
|
||
* SECTION:gudevdevice
|
||
* @short_description: Get information about a device
|
||
*
|
||
* The #GUdevDevice class is used to get information about a specific
|
||
* device. Note that you cannot instantiate a #GUdevDevice object
|
||
* yourself. Instead you must use #GUdevClient to obtain #GUdevDevice
|
||
* objects.
|
||
*
|
||
* To get basic information about a device, use
|
||
* g_udev_device_get_subsystem(), g_udev_device_get_devtype(),
|
||
* g_udev_device_get_name(), g_udev_device_get_number(),
|
||
* g_udev_device_get_sysfs_path(), g_udev_device_get_driver(),
|
||
* g_udev_device_get_action(), g_udev_device_get_seqnum(),
|
||
* g_udev_device_get_device_type(), g_udev_device_get_device_number(),
|
||
* g_udev_device_get_device_file(),
|
||
* g_udev_device_get_device_file_symlinks().
|
||
*
|
||
* To navigate the device tree, use g_udev_device_get_parent() and
|
||
* g_udev_device_get_parent_with_subsystem().
|
||
*
|
||
* To access udev properties for the device, use
|
||
* g_udev_device_get_property_keys(),
|
||
* g_udev_device_has_property(),
|
||
* g_udev_device_get_property(),
|
||
* g_udev_device_get_property_as_int(),
|
||
* g_udev_device_get_property_as_uint64(),
|
||
* g_udev_device_get_property_as_double(),
|
||
* g_udev_device_get_property_as_boolean() and
|
||
* g_udev_device_get_property_as_strv().
|
||
*
|
||
* To access sysfs attributes for the device, use
|
||
* g_udev_device_get_sysfs_attr(),
|
||
* g_udev_device_get_sysfs_attr_as_int(),
|
||
* g_udev_device_get_sysfs_attr_as_uint64(),
|
||
* g_udev_device_get_sysfs_attr_as_double(),
|
||
* g_udev_device_get_sysfs_attr_as_boolean() and
|
||
* g_udev_device_get_sysfs_attr_as_strv().
|
||
*
|
||
* Note that all getters on #GUdevDevice are non-reffing – returned
|
||
* values are owned by the object, should not be freed and are only
|
||
* valid as long as the object is alive.
|
||
*
|
||
* By design, #GUdevDevice will not react to changes for a device – it
|
||
* only contains a snapshot of information when the #GUdevDevice
|
||
* object was created. To work with changes, you typically connect to
|
||
* the #GUdevClient::uevent signal on a #GUdevClient and get a new
|
||
* #GUdevDevice whenever an event happens.
|
||
*/
|
||
|
||
struct _GUdevDevicePrivate
|
||
{
|
||
struct udev_device *udevice;
|
||
|
||
/* computed ondemand and cached */
|
||
gchar **device_file_symlinks;
|
||
gchar **property_keys;
|
||
GHashTable *prop_strvs;
|
||
GHashTable *sysfs_attr_strvs;
|
||
};
|
||
|
||
G_DEFINE_TYPE (GUdevDevice, g_udev_device, G_TYPE_OBJECT)
|
||
|
||
static void
|
||
g_udev_device_finalize (GObject *object)
|
||
{
|
||
GUdevDevice *device = G_UDEV_DEVICE (object);
|
||
|
||
g_strfreev (device->priv->device_file_symlinks);
|
||
g_strfreev (device->priv->property_keys);
|
||
|
||
if (device->priv->udevice != NULL)
|
||
udev_device_unref (device->priv->udevice);
|
||
|
||
if (device->priv->prop_strvs != NULL)
|
||
g_hash_table_unref (device->priv->prop_strvs);
|
||
|
||
if (device->priv->sysfs_attr_strvs != NULL)
|
||
g_hash_table_unref (device->priv->sysfs_attr_strvs);
|
||
|
||
if (G_OBJECT_CLASS (g_udev_device_parent_class)->finalize != NULL)
|
||
(* G_OBJECT_CLASS (g_udev_device_parent_class)->finalize) (object);
|
||
}
|
||
|
||
static void
|
||
g_udev_device_class_init (GUdevDeviceClass *klass)
|
||
{
|
||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||
|
||
gobject_class->finalize = g_udev_device_finalize;
|
||
|
||
g_type_class_add_private (klass, sizeof (GUdevDevicePrivate));
|
||
}
|
||
|
||
static void
|
||
g_udev_device_init (GUdevDevice *device)
|
||
{
|
||
device->priv = G_TYPE_INSTANCE_GET_PRIVATE (device,
|
||
G_UDEV_TYPE_DEVICE,
|
||
GUdevDevicePrivate);
|
||
}
|
||
|
||
|
||
GUdevDevice *
|
||
_g_udev_device_new (struct udev_device *udevice)
|
||
{
|
||
GUdevDevice *device;
|
||
|
||
device = G_UDEV_DEVICE (g_object_new (G_UDEV_TYPE_DEVICE, NULL));
|
||
device->priv->udevice = udev_device_ref (udevice);
|
||
|
||
return device;
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_subsystem:
|
||
* @device: A #GUdevDevice.
|
||
*
|
||
* Gets the subsystem for @device.
|
||
*
|
||
* Returns: The subsystem for @device.
|
||
*/
|
||
const gchar *
|
||
g_udev_device_get_subsystem (GUdevDevice *device)
|
||
{
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
return udev_device_get_subsystem (device->priv->udevice);
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_devtype:
|
||
* @device: A #GUdevDevice.
|
||
*
|
||
* Gets the device type for @device.
|
||
*
|
||
* Returns: The devtype for @device.
|
||
*/
|
||
const gchar *
|
||
g_udev_device_get_devtype (GUdevDevice *device)
|
||
{
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
return udev_device_get_devtype (device->priv->udevice);
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_name:
|
||
* @device: A #GUdevDevice.
|
||
*
|
||
* Gets the name of @device, e.g. "sda3".
|
||
*
|
||
* Returns: The name of @device.
|
||
*/
|
||
const gchar *
|
||
g_udev_device_get_name (GUdevDevice *device)
|
||
{
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
return udev_device_get_sysname (device->priv->udevice);
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_number:
|
||
* @device: A #GUdevDevice.
|
||
*
|
||
* Gets the number of @device, e.g. "3" if g_udev_device_get_name() returns "sda3".
|
||
*
|
||
* Returns: The number of @device.
|
||
*/
|
||
const gchar *
|
||
g_udev_device_get_number (GUdevDevice *device)
|
||
{
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
return udev_device_get_sysnum (device->priv->udevice);
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_sysfs_path:
|
||
* @device: A #GUdevDevice.
|
||
*
|
||
* Gets the sysfs path for @device.
|
||
*
|
||
* Returns: The sysfs path for @device.
|
||
*/
|
||
const gchar *
|
||
g_udev_device_get_sysfs_path (GUdevDevice *device)
|
||
{
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
return udev_device_get_syspath (device->priv->udevice);
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_driver:
|
||
* @device: A #GUdevDevice.
|
||
*
|
||
* Gets the name of the driver used for @device.
|
||
*
|
||
* Returns: The name of the driver for @device or %NULL if unknown.
|
||
*/
|
||
const gchar *
|
||
g_udev_device_get_driver (GUdevDevice *device)
|
||
{
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
return udev_device_get_driver (device->priv->udevice);
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_action:
|
||
* @device: A #GUdevDevice.
|
||
*
|
||
* Gets the most recent action (e.g. "add", "remove", "change", etc.) for @device.
|
||
*
|
||
* Returns: An action string.
|
||
*/
|
||
const gchar *
|
||
g_udev_device_get_action (GUdevDevice *device)
|
||
{
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
return udev_device_get_action (device->priv->udevice);
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_seqnum:
|
||
* @device: A #GUdevDevice.
|
||
*
|
||
* Gets the most recent sequence number for @device.
|
||
*
|
||
* Returns: A sequence number.
|
||
*/
|
||
guint64
|
||
g_udev_device_get_seqnum (GUdevDevice *device)
|
||
{
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0);
|
||
return udev_device_get_seqnum (device->priv->udevice);
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_device_type:
|
||
* @device: A #GUdevDevice.
|
||
*
|
||
* Gets the type of the device file, if any, for @device.
|
||
*
|
||
* Returns: The device number for @device or #G_UDEV_DEVICE_TYPE_NONE if the device does not have a device file.
|
||
*/
|
||
GUdevDeviceType
|
||
g_udev_device_get_device_type (GUdevDevice *device)
|
||
{
|
||
struct stat stat_buf;
|
||
const gchar *device_file;
|
||
GUdevDeviceType type;
|
||
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), G_UDEV_DEVICE_TYPE_NONE);
|
||
|
||
type = G_UDEV_DEVICE_TYPE_NONE;
|
||
|
||
/* TODO: would be better to have support for this in libudev... */
|
||
|
||
device_file = g_udev_device_get_device_file (device);
|
||
if (device_file == NULL)
|
||
goto out;
|
||
|
||
if (stat (device_file, &stat_buf) != 0)
|
||
goto out;
|
||
|
||
if (S_ISBLK (stat_buf.st_mode))
|
||
type = G_UDEV_DEVICE_TYPE_BLOCK;
|
||
else if (S_ISCHR (stat_buf.st_mode))
|
||
type = G_UDEV_DEVICE_TYPE_CHAR;
|
||
|
||
out:
|
||
return type;
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_device_number:
|
||
* @device: A #GUdevDevice.
|
||
*
|
||
* Gets the device number, if any, for @device.
|
||
*
|
||
* Returns: The device number for @device or 0 if unknown.
|
||
*/
|
||
GUdevDeviceNumber
|
||
g_udev_device_get_device_number (GUdevDevice *device)
|
||
{
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0);
|
||
return udev_device_get_devnum (device->priv->udevice);
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_device_file:
|
||
* @device: A #GUdevDevice.
|
||
*
|
||
* Gets the device file for @device.
|
||
*
|
||
* Returns: The device file for @device or %NULL if no device file
|
||
* exists.
|
||
*/
|
||
const gchar *
|
||
g_udev_device_get_device_file (GUdevDevice *device)
|
||
{
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
return udev_device_get_devnode (device->priv->udevice);
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_device_file_symlinks:
|
||
* @device: A #GUdevDevice.
|
||
*
|
||
* Gets a list of symlinks (in <literal>/dev</literal>) that points to
|
||
* the device file for @device.
|
||
*
|
||
* Returns: (transfer none) (array zero-terminated=1) (element-type utf8): A %NULL terminated string array of symlinks. This array is owned by @device and should not be freed by the caller.
|
||
*/
|
||
const gchar * const *
|
||
g_udev_device_get_device_file_symlinks (GUdevDevice *device)
|
||
{
|
||
struct udev_list_entry *l;
|
||
GPtrArray *p;
|
||
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
|
||
if (device->priv->device_file_symlinks != NULL)
|
||
goto out;
|
||
|
||
p = g_ptr_array_new ();
|
||
for (l = udev_device_get_devlinks_list_entry (device->priv->udevice); l != NULL; l = udev_list_entry_get_next (l))
|
||
{
|
||
g_ptr_array_add (p, g_strdup (udev_list_entry_get_name (l)));
|
||
}
|
||
g_ptr_array_add (p, NULL);
|
||
device->priv->device_file_symlinks = (gchar **) g_ptr_array_free (p, FALSE);
|
||
|
||
out:
|
||
return (const gchar * const *) device->priv->device_file_symlinks;
|
||
}
|
||
|
||
/* ---------------------------------------------------------------------------------------------------- */
|
||
|
||
/**
|
||
* g_udev_device_get_parent:
|
||
* @device: A #GUdevDevice.
|
||
*
|
||
* Gets the immediate parent of @device, if any.
|
||
*
|
||
* Returns: A #GUdevDevice or %NULL if @device has no parent. Free with g_object_unref().
|
||
*/
|
||
GUdevDevice *
|
||
g_udev_device_get_parent (GUdevDevice *device)
|
||
{
|
||
GUdevDevice *ret;
|
||
struct udev_device *udevice;
|
||
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
|
||
ret = NULL;
|
||
|
||
udevice = udev_device_get_parent (device->priv->udevice);
|
||
if (udevice == NULL)
|
||
goto out;
|
||
|
||
ret = _g_udev_device_new (udevice);
|
||
|
||
out:
|
||
return ret;
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_parent_with_subsystem:
|
||
* @device: A #GUdevDevice.
|
||
* @subsystem: The subsystem of the parent to get.
|
||
* @devtype: (allow-none): The devtype of the parent to get or %NULL.
|
||
*
|
||
* Walks up the chain of parents of @device and returns the first
|
||
* device encountered where @subsystem and @devtype matches, if any.
|
||
*
|
||
* Returns: A #GUdevDevice or %NULL if @device has no parent with @subsystem and @devtype. Free with g_object_unref().
|
||
*/
|
||
GUdevDevice *
|
||
g_udev_device_get_parent_with_subsystem (GUdevDevice *device,
|
||
const gchar *subsystem,
|
||
const gchar *devtype)
|
||
{
|
||
GUdevDevice *ret;
|
||
struct udev_device *udevice;
|
||
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
g_return_val_if_fail (subsystem != NULL, NULL);
|
||
|
||
ret = NULL;
|
||
|
||
udevice = udev_device_get_parent_with_subsystem_devtype (device->priv->udevice,
|
||
subsystem,
|
||
devtype);
|
||
if (udevice == NULL)
|
||
goto out;
|
||
|
||
ret = _g_udev_device_new (udevice);
|
||
|
||
out:
|
||
return ret;
|
||
}
|
||
|
||
/* ---------------------------------------------------------------------------------------------------- */
|
||
|
||
/**
|
||
* g_udev_device_get_property_keys:
|
||
* @device: A #GUdevDevice.
|
||
*
|
||
* Gets all keys for properties on @device.
|
||
*
|
||
* Returns: (transfer none) (array zero-terminated=1) (element-type utf8): A %NULL terminated string array of property keys. This array is owned by @device and should not be freed by the caller.
|
||
*/
|
||
const gchar* const *
|
||
g_udev_device_get_property_keys (GUdevDevice *device)
|
||
{
|
||
struct udev_list_entry *l;
|
||
GPtrArray *p;
|
||
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
|
||
if (device->priv->property_keys != NULL)
|
||
goto out;
|
||
|
||
p = g_ptr_array_new ();
|
||
for (l = udev_device_get_properties_list_entry (device->priv->udevice); l != NULL; l = udev_list_entry_get_next (l))
|
||
{
|
||
g_ptr_array_add (p, g_strdup (udev_list_entry_get_name (l)));
|
||
}
|
||
g_ptr_array_add (p, NULL);
|
||
device->priv->property_keys = (gchar **) g_ptr_array_free (p, FALSE);
|
||
|
||
out:
|
||
return (const gchar * const *) device->priv->property_keys;
|
||
}
|
||
|
||
|
||
/**
|
||
* g_udev_device_has_property:
|
||
* @device: A #GUdevDevice.
|
||
* @key: Name of property.
|
||
*
|
||
* Check if a the property with the given key exists.
|
||
*
|
||
* Returns: %TRUE only if the value for @key exist.
|
||
*/
|
||
gboolean
|
||
g_udev_device_has_property (GUdevDevice *device,
|
||
const gchar *key)
|
||
{
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE);
|
||
g_return_val_if_fail (key != NULL, FALSE);
|
||
return udev_device_get_property_value (device->priv->udevice, key) != NULL;
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_property:
|
||
* @device: A #GUdevDevice.
|
||
* @key: Name of property.
|
||
*
|
||
* Look up the value for @key on @device.
|
||
*
|
||
* Returns: The value for @key or %NULL if @key doesn't exist on @device. Do not free this string, it is owned by @device.
|
||
*/
|
||
const gchar *
|
||
g_udev_device_get_property (GUdevDevice *device,
|
||
const gchar *key)
|
||
{
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
g_return_val_if_fail (key != NULL, NULL);
|
||
return udev_device_get_property_value (device->priv->udevice, key);
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_property_as_int:
|
||
* @device: A #GUdevDevice.
|
||
* @key: Name of property.
|
||
*
|
||
* Look up the value for @key on @device and convert it to an integer
|
||
* using strtol().
|
||
*
|
||
* Returns: The value for @key or 0 if @key doesn't exist or
|
||
* isn't an integer.
|
||
*/
|
||
gint
|
||
g_udev_device_get_property_as_int (GUdevDevice *device,
|
||
const gchar *key)
|
||
{
|
||
gint result;
|
||
const gchar *s;
|
||
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0);
|
||
g_return_val_if_fail (key != NULL, 0);
|
||
|
||
result = 0;
|
||
s = g_udev_device_get_property (device, key);
|
||
if (s == NULL)
|
||
goto out;
|
||
|
||
result = strtol (s, NULL, 0);
|
||
out:
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_property_as_uint64:
|
||
* @device: A #GUdevDevice.
|
||
* @key: Name of property.
|
||
*
|
||
* Look up the value for @key on @device and convert it to an unsigned
|
||
* 64-bit integer using strtoll().
|
||
*
|
||
* Returns: The value for @key or 0 if @key doesn't exist or isn't a
|
||
* #guint64.
|
||
*/
|
||
guint64
|
||
g_udev_device_get_property_as_uint64 (GUdevDevice *device,
|
||
const gchar *key)
|
||
{
|
||
guint64 result;
|
||
const gchar *s;
|
||
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0);
|
||
g_return_val_if_fail (key != NULL, 0);
|
||
|
||
result = 0;
|
||
s = g_udev_device_get_property (device, key);
|
||
if (s == NULL)
|
||
goto out;
|
||
|
||
result = strtoll (s, NULL, 0);
|
||
out:
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_property_as_double:
|
||
* @device: A #GUdevDevice.
|
||
* @key: Name of property.
|
||
*
|
||
* Look up the value for @key on @device and convert it to a double
|
||
* precision floating point number using strtod().
|
||
*
|
||
* Returns: The value for @key or 0.0 if @key doesn't exist or isn't a
|
||
* #gdouble.
|
||
*/
|
||
gdouble
|
||
g_udev_device_get_property_as_double (GUdevDevice *device,
|
||
const gchar *key)
|
||
{
|
||
gdouble result;
|
||
const gchar *s;
|
||
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0.0);
|
||
g_return_val_if_fail (key != NULL, 0.0);
|
||
|
||
result = 0.0;
|
||
s = g_udev_device_get_property (device, key);
|
||
if (s == NULL)
|
||
goto out;
|
||
|
||
result = strtod (s, NULL);
|
||
out:
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_property_as_boolean:
|
||
* @device: A #GUdevDevice.
|
||
* @key: Name of property.
|
||
*
|
||
* Look up the value for @key on @device and convert it to an
|
||
* boolean. This is done by doing a case-insensitive string comparison
|
||
* on the string value against "1" and "true".
|
||
*
|
||
* Returns: The value for @key or %FALSE if @key doesn't exist or
|
||
* isn't a #gboolean.
|
||
*/
|
||
gboolean
|
||
g_udev_device_get_property_as_boolean (GUdevDevice *device,
|
||
const gchar *key)
|
||
{
|
||
gboolean result;
|
||
const gchar *s;
|
||
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE);
|
||
g_return_val_if_fail (key != NULL, FALSE);
|
||
|
||
result = FALSE;
|
||
s = g_udev_device_get_property (device, key);
|
||
if (s == NULL)
|
||
goto out;
|
||
|
||
if (strcmp (s, "1") == 0 || g_ascii_strcasecmp (s, "true") == 0)
|
||
result = TRUE;
|
||
out:
|
||
return result;
|
||
}
|
||
|
||
static gchar **
|
||
split_at_whitespace (const gchar *s)
|
||
{
|
||
gchar **result;
|
||
guint n;
|
||
guint m;
|
||
|
||
result = g_strsplit_set (s, " \v\t\r\n", 0);
|
||
|
||
/* remove empty strings, thanks GLib */
|
||
for (n = 0; result[n] != NULL; n++)
|
||
{
|
||
if (strlen (result[n]) == 0)
|
||
{
|
||
g_free (result[n]);
|
||
for (m = n; result[m] != NULL; m++)
|
||
result[m] = result[m + 1];
|
||
n--;
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_property_as_strv:
|
||
* @device: A #GUdevDevice.
|
||
* @key: Name of property.
|
||
*
|
||
* Look up the value for @key on @device and return the result of
|
||
* splitting it into non-empty tokens split at white space (only space
|
||
* (' '), form-feed ('\f'), newline ('\n'), carriage return ('\r'),
|
||
* horizontal tab ('\t'), and vertical tab ('\v') are considered; the
|
||
* locale is not taken into account).
|
||
*
|
||
* Returns: (transfer none) (array zero-terminated=1) (element-type utf8): The value of @key on @device split into tokens or %NULL if @key doesn't exist. This array is owned by @device and should not be freed by the caller.
|
||
*/
|
||
const gchar* const *
|
||
g_udev_device_get_property_as_strv (GUdevDevice *device,
|
||
const gchar *key)
|
||
{
|
||
gchar **result;
|
||
const gchar *s;
|
||
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
g_return_val_if_fail (key != NULL, NULL);
|
||
|
||
if (device->priv->prop_strvs != NULL)
|
||
{
|
||
result = g_hash_table_lookup (device->priv->prop_strvs, key);
|
||
if (result != NULL)
|
||
goto out;
|
||
}
|
||
|
||
result = NULL;
|
||
s = g_udev_device_get_property (device, key);
|
||
if (s == NULL)
|
||
goto out;
|
||
|
||
result = split_at_whitespace (s);
|
||
if (result == NULL)
|
||
goto out;
|
||
|
||
if (device->priv->prop_strvs == NULL)
|
||
device->priv->prop_strvs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_strfreev);
|
||
g_hash_table_insert (device->priv->prop_strvs, g_strdup (key), result);
|
||
|
||
out:
|
||
return (const gchar* const *) result;
|
||
}
|
||
|
||
/* ---------------------------------------------------------------------------------------------------- */
|
||
|
||
/**
|
||
* g_udev_device_get_sysfs_attr:
|
||
* @device: A #GUdevDevice.
|
||
* @name: Name of the sysfs attribute.
|
||
*
|
||
* Look up the sysfs attribute with @name on @device.
|
||
*
|
||
* Returns: The value of the sysfs attribute or %NULL if there is no
|
||
* such attribute. Do not free this string, it is owned by @device.
|
||
*/
|
||
const gchar *
|
||
g_udev_device_get_sysfs_attr (GUdevDevice *device,
|
||
const gchar *name)
|
||
{
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
g_return_val_if_fail (name != NULL, NULL);
|
||
return udev_device_get_sysattr_value (device->priv->udevice, name);
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_sysfs_attr_as_int:
|
||
* @device: A #GUdevDevice.
|
||
* @name: Name of the sysfs attribute.
|
||
*
|
||
* Look up the sysfs attribute with @name on @device and convert it to an integer
|
||
* using strtol().
|
||
*
|
||
* Returns: The value of the sysfs attribute or 0 if there is no such
|
||
* attribute.
|
||
*/
|
||
gint
|
||
g_udev_device_get_sysfs_attr_as_int (GUdevDevice *device,
|
||
const gchar *name)
|
||
{
|
||
gint result;
|
||
const gchar *s;
|
||
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0);
|
||
g_return_val_if_fail (name != NULL, 0);
|
||
|
||
result = 0;
|
||
s = g_udev_device_get_sysfs_attr (device, name);
|
||
if (s == NULL)
|
||
goto out;
|
||
|
||
result = strtol (s, NULL, 0);
|
||
out:
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_sysfs_attr_as_uint64:
|
||
* @device: A #GUdevDevice.
|
||
* @name: Name of the sysfs attribute.
|
||
*
|
||
* Look up the sysfs attribute with @name on @device and convert it to an unsigned
|
||
* 64-bit integer using strtoll().
|
||
*
|
||
* Returns: The value of the sysfs attribute or 0 if there is no such
|
||
* attribute.
|
||
*/
|
||
guint64
|
||
g_udev_device_get_sysfs_attr_as_uint64 (GUdevDevice *device,
|
||
const gchar *name)
|
||
{
|
||
guint64 result;
|
||
const gchar *s;
|
||
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0);
|
||
g_return_val_if_fail (name != NULL, 0);
|
||
|
||
result = 0;
|
||
s = g_udev_device_get_sysfs_attr (device, name);
|
||
if (s == NULL)
|
||
goto out;
|
||
|
||
result = strtoll (s, NULL, 0);
|
||
out:
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_sysfs_attr_as_double:
|
||
* @device: A #GUdevDevice.
|
||
* @name: Name of the sysfs attribute.
|
||
*
|
||
* Look up the sysfs attribute with @name on @device and convert it to a double
|
||
* precision floating point number using strtod().
|
||
*
|
||
* Returns: The value of the sysfs attribute or 0.0 if there is no such
|
||
* attribute.
|
||
*/
|
||
gdouble
|
||
g_udev_device_get_sysfs_attr_as_double (GUdevDevice *device,
|
||
const gchar *name)
|
||
{
|
||
gdouble result;
|
||
const gchar *s;
|
||
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0.0);
|
||
g_return_val_if_fail (name != NULL, 0.0);
|
||
|
||
result = 0.0;
|
||
s = g_udev_device_get_sysfs_attr (device, name);
|
||
if (s == NULL)
|
||
goto out;
|
||
|
||
result = strtod (s, NULL);
|
||
out:
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_sysfs_attr_as_boolean:
|
||
* @device: A #GUdevDevice.
|
||
* @name: Name of the sysfs attribute.
|
||
*
|
||
* Look up the sysfs attribute with @name on @device and convert it to an
|
||
* boolean. This is done by doing a case-insensitive string comparison
|
||
* on the string value against "1" and "true".
|
||
*
|
||
* Returns: The value of the sysfs attribute or %FALSE if there is no such
|
||
* attribute.
|
||
*/
|
||
gboolean
|
||
g_udev_device_get_sysfs_attr_as_boolean (GUdevDevice *device,
|
||
const gchar *name)
|
||
{
|
||
gboolean result;
|
||
const gchar *s;
|
||
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE);
|
||
g_return_val_if_fail (name != NULL, FALSE);
|
||
|
||
result = FALSE;
|
||
s = g_udev_device_get_sysfs_attr (device, name);
|
||
if (s == NULL)
|
||
goto out;
|
||
|
||
if (strcmp (s, "1") == 0 || g_ascii_strcasecmp (s, "true") == 0)
|
||
result = TRUE;
|
||
out:
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* g_udev_device_get_sysfs_attr_as_strv:
|
||
* @device: A #GUdevDevice.
|
||
* @name: Name of the sysfs attribute.
|
||
*
|
||
* Look up the sysfs attribute with @name on @device and return the result of
|
||
* splitting it into non-empty tokens split at white space (only space (' '),
|
||
* form-feed ('\f'), newline ('\n'), carriage return ('\r'), horizontal
|
||
* tab ('\t'), and vertical tab ('\v') are considered; the locale is
|
||
* not taken into account).
|
||
*
|
||
* Returns: (transfer none) (array zero-terminated=1) (element-type utf8): The value of the sysfs attribute split into tokens or %NULL if there is no such attribute. This array is owned by @device and should not be freed by the caller.
|
||
*/
|
||
const gchar * const *
|
||
g_udev_device_get_sysfs_attr_as_strv (GUdevDevice *device,
|
||
const gchar *name)
|
||
{
|
||
gchar **result;
|
||
const gchar *s;
|
||
|
||
g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
|
||
g_return_val_if_fail (name != NULL, NULL);
|
||
|
||
if (device->priv->sysfs_attr_strvs != NULL)
|
||
{
|
||
result = g_hash_table_lookup (device->priv->sysfs_attr_strvs, name);
|
||
if (result != NULL)
|
||
goto out;
|
||
}
|
||
|
||
result = NULL;
|
||
s = g_udev_device_get_sysfs_attr (device, name);
|
||
if (s == NULL)
|
||
goto out;
|
||
|
||
result = split_at_whitespace (s);
|
||
if (result == NULL)
|
||
goto out;
|
||
|
||
if (device->priv->sysfs_attr_strvs == NULL)
|
||
device->priv->sysfs_attr_strvs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_strfreev);
|
||
g_hash_table_insert (device->priv->sysfs_attr_strvs, g_strdup (name), result);
|
||
|
||
out:
|
||
return (const gchar* const *) result;
|
||
}
|