From 43a593b5b4097b887e49eaacafbc1337bd709718 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Thu, 7 May 2015 12:17:37 +0200 Subject: [PATCH 1/1] Initial import Import initial libgudev from systemd-218. This includes the libgudev sources, the introspection data and gtk-doc reference documentation. --- .gitignore | 41 ++ Makefile.am | 187 +++++++ autogen.sh | 18 + configure.ac | 65 +++ docs/.gitignore | 12 + docs/Makefile.am | 107 ++++ docs/gudev-docs.xml | 53 ++ docs/gudev-sections.txt | 102 ++++ docs/gudev.types | 4 + docs/version.xml.in | 1 + gudev-1.0.pc.in | 11 + gudev/gudev.h | 32 ++ gudev/gudevclient.c | 533 ++++++++++++++++++++ gudev/gudevclient.h | 99 ++++ gudev/gudevdevice.c | 1027 +++++++++++++++++++++++++++++++++++++++ gudev/gudevdevice.h | 130 +++++ gudev/gudevenumerator.c | 429 ++++++++++++++++ gudev/gudevenumerator.h | 106 ++++ gudev/gudevenums.h | 48 ++ gudev/gudevenumtypes.c.template | 39 ++ gudev/gudevenumtypes.h.template | 24 + gudev/gudevmarshal.list | 1 + gudev/gudevprivate.h | 40 ++ gudev/gudevtypes.h | 50 ++ libgudev-1.0.sym | 68 +++ scripts/gjs-example.js | 75 +++ scripts/seed-example-enum.js | 38 ++ scripts/seed-example.js | 72 +++ 28 files changed, 3412 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile.am create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 docs/.gitignore create mode 100644 docs/Makefile.am create mode 100644 docs/gudev-docs.xml create mode 100644 docs/gudev-sections.txt create mode 100644 docs/gudev.types create mode 100644 docs/version.xml.in create mode 100644 gudev-1.0.pc.in create mode 100644 gudev/gudev.h create mode 100644 gudev/gudevclient.c create mode 100644 gudev/gudevclient.h create mode 100644 gudev/gudevdevice.c create mode 100644 gudev/gudevdevice.h create mode 100644 gudev/gudevenumerator.c create mode 100644 gudev/gudevenumerator.h create mode 100644 gudev/gudevenums.h create mode 100644 gudev/gudevenumtypes.c.template create mode 100644 gudev/gudevenumtypes.h.template create mode 100644 gudev/gudevmarshal.list create mode 100644 gudev/gudevprivate.h create mode 100644 gudev/gudevtypes.h create mode 100644 libgudev-1.0.sym create mode 100755 scripts/gjs-example.js create mode 100755 scripts/seed-example-enum.js create mode 100755 scripts/seed-example.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6f43cc9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +*.a +*.cache +*.gir +*.html +*.la +*.lo +*.log +*.o +*.plist +*.pyc +*.stamp +*.swp +*.trs +*.typelib +*~ +.deps/ +.dirstamp +.libs/ +/*.gcda +/*.gcno +/*.tar.bz2 +/*.tar.gz +/*.tar.xz +/Makefile +/Makefile.in +/aclocal.m4 +/build-aux/ +/config.h +/config.h.in +/config.log +/config.status +/configure +/gtk-doc.make +/gudev/gudevenumtypes.h +/gudev/gudevenumtypes.c +/gudev/gudevmarshal.h +/gudev/gudevmarshal.c +/gudev-1.0.pc +/libtool +/m4/ +/stamp-* diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..18822be --- /dev/null +++ b/Makefile.am @@ -0,0 +1,187 @@ +# ------------------------------------------------------------------------------ +# Common variables + +ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} +AUTOMAKE_OPTIONS = color-tests parallel-tests +DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc +SUBDIRS = . +lib_LTLIBRARIES = +noinst_DATA = +MANPAGES = +CLEANFILES = $(BUILT_SOURCES) +EXTRA_DIST = +BUILT_SOURCES = + +GCC_COLORS ?= 'ooh, shiny!' +export GCC_COLORS + +# remove targets if the command fails +.DELETE_ON_ERROR: + +# keep intermediate files +.SECONDARY: + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = + +AM_MAKEFLAGS = --no-print-directory +AM_CPPFLAGS = +AM_CFLAGS = + +# ------------------------------------------------------------------------------ +# Version numbers + +LIBGUDEV_CURRENT=2 +LIBGUDEV_REVISION=0 +LIBGUDEV_AGE=2 + +# ------------------------------------------------------------------------------ +# libgudev + +libgudev_includedir = $(includedir)/gudev-1.0/gudev + +libgudev_include_HEADERS = \ + gudev/gudev.h \ + gudev/gudevenums.h \ + gudev/gudevenumtypes.h \ + gudev/gudevtypes.h \ + gudev/gudevclient.h \ + gudev/gudevdevice.h \ + gudev/gudevenumerator.h + +lib_LTLIBRARIES += \ + libgudev-1.0.la + +pkgconfig_DATA += \ + gudev-1.0.pc + +EXTRA_DIST += \ + gudev-1.0.pc.in \ + gudev/gudevmarshal.list \ + gudev/gudevenumtypes.h.template \ + gudev/gudevenumtypes.c.template \ + scripts/gjs-example.js \ + scripts/seed-example-enum.js \ + scripts/seed-example.js + +libgudev_1_0_la_SOURCES = \ + libgudev-1.0.sym \ + gudev/gudevenums.h \ + gudev/gudevenumtypes.h \ + gudev/gudevenumtypes.h\ + gudev/gudevtypes.h \ + gudev/gudevclient.h \ + gudev/gudevclient.c \ + gudev/gudevdevice.h \ + gudev/gudevdevice.c \ + gudev/gudevenumerator.h \ + gudev/gudevenumerator.c \ + gudev/gudevprivate.h + +nodist_libgudev_1_0_la_SOURCES = \ + gudev/gudevmarshal.h \ + gudev/gudevmarshal.c \ + gudev/gudevenumtypes.h \ + gudev/gudevenumtypes.c + +BUILT_SOURCES += \ + $(nodist_libgudev_1_0_la_SOURCES) + +libgudev_1_0_la_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -I$(top_builddir)/gudev \ + -I$(top_srcdir)/gudev \ + -D_POSIX_PTHREAD_SEMANTICS \ + -D_REENTRANT \ + -D_GUDEV_COMPILATION \ + -DG_LOG_DOMAIN=\"GUdev\" + +libgudev_1_0_la_CFLAGS = \ + $(AM_CFLAGS) \ + -fvisibility=default \ + $(LIBUDEV_CFLAGS) \ + $(GLIB_CFLAGS) + +libgudev_1_0_la_LIBADD = \ + $(LIBUDEV_LIBS) \ + $(GLIB_LIBS) + +libgudev_1_0_la_LDFLAGS = \ + $(AM_LDFLAGS) \ + -version-info $(LIBGUDEV_CURRENT):$(LIBGUDEV_REVISION):$(LIBGUDEV_AGE) \ + -export-dynamic \ + -no-undefined \ + -Wl,--version-script=$(top_srcdir)/libgudev-1.0.sym + +gudev/gudevmarshal.h: gudev/gudevmarshal.list + $(AM_V_at)$(MKDIR_P) $(dir $@) + $(AM_V_GEN)glib-genmarshal $< --prefix=g_udev_marshal --header > $@ + +gudev/gudevmarshal.c: gudev/gudevmarshal.list + $(AM_V_at)$(MKDIR_P) $(dir $@) + $(AM_V_GEN)echo '#include "gudevmarshal.h"' > $@ && \ + glib-genmarshal $< --prefix=g_udev_marshal --body >> $@ + +gudev/gudevenumtypes.%: gudev/gudevenumtypes.%.template gudev/gudevenums.h + $(AM_V_at)$(MKDIR_P) $(dir $@) + $(AM_V_GEN)glib-mkenums --template $^ > $@ + +if HAVE_INTROSPECTION +-include $(INTROSPECTION_MAKEFILE) + +gudev/GUdev-1.0.gir: libgudev-1.0.la + +gudev_GUdev_1_0_gir_INCLUDES = GObject-2.0 + +gudev_GUdev_1_0_gir_CFLAGS = \ + $(AM_CFLAGS) \ + $(INCLUDES) \ + -D_GUDEV_COMPILATION \ + -D_GUDEV_WORK_AROUND_DEV_T_BUG \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/gudev \ + -I$(top_builddir)/gudev + +gudev_GUdev_1_0_gir_LIBS = libgudev-1.0.la + +gudev_GUdev_1_0_gir_SCANNERFLAGS = \ + --pkg-export=gudev-1.0 \ + --warn-all + +gudev_GUdev_1_0_gir_FILES = \ + gudev/gudev.h \ + gudev/gudevtypes.h \ + gudev/gudevenums.h \ + gudev/gudevenumtypes.h \ + gudev/gudevclient.h \ + gudev/gudevdevice.h \ + gudev/gudevenumerator.h \ + gudev/gudevclient.c \ + gudev/gudevdevice.c \ + gudev/gudevenumerator.c + +INTROSPECTION_GIRS = gudev/GUdev-1.0.gir +INTROSPECTION_SCANNER_ARGS = --c-include=gudev/gudev.h + +girdir = $(datadir)/gir-1.0 +gir_DATA = \ + gudev/GUdev-1.0.gir + +typelibsdir = $(libdir)/girepository-1.0 +typelibs_DATA = \ + gudev/GUdev-1.0.typelib + +CLEANFILES += $(gir_DATA) $(typelibs_DATA) +endif # HAVE_INTROSPECTION + +# ------------------------------------------------------------------------------ +# docs + +if ENABLE_GTK_DOC +SUBDIRS += docs +endif + +#docs/html: +# $(AM_V_at)$(MKDIR_P) $(dir $@) +# $(AM_V_LN)$(LN_S) -f ../gudev/html $@ diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..f235b50 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,18 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +which gnome-autogen.sh || { + echo "You need to install gnome-common from the GNOME git" + exit 1 +} + +git submodule update --init --recursive + +REQUIRED_AUTOCONF_VERSION=2.64 +REQUIRED_AUTOMAKE_VERSION=1.11 +REQUIRED_INTLTOOL_VERSION=0.40.0 +REQUIRED_PKG_CONFIG_VERSION=0.22 +. gnome-autogen.sh diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..f920fae --- /dev/null +++ b/configure.ac @@ -0,0 +1,65 @@ +AC_PREREQ([2.64]) +AC_INIT([libgudev], + [220], + [http://bugzilla.gnome.org/enter_bug.cgi?product=gudev], + [libgudev], + [https://developer.gnome.org/gudev]) +AC_CONFIG_SRCDIR([gudev/gudev.h]) +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_AUX_DIR([build-aux]) + +AC_USE_SYSTEM_EXTENSIONS +AC_SYS_LARGEFILE +AM_MAINTAINER_MODE([enable]) +AM_INIT_AUTOMAKE([foreign 1.11 -Wall -Wno-portability silent-rules tar-pax no-dist-gzip dist-xz subdir-objects parallel-tests]) +AM_SILENT_RULES([yes]) +AC_CANONICAL_HOST +LT_PREREQ([2.2]) +LT_INIT([disable-static]) + +AC_PROG_MKDIR_P +AC_PROG_LN_S +AC_PROG_SED +AC_PROG_GREP +AC_PROG_AWK +AC_PROG_CC_C99 +PKG_PROG_PKG_CONFIG + +# gtkdocize greps for '^GTK_DOC_CHECK', so it needs to be on its own line +m4_ifdef([GTK_DOC_CHECK], [ +GTK_DOC_CHECK([1.18],[--flavour no-tmpl])], + [AM_CONDITIONAL([ENABLE_GTK_DOC], [false]) + enable_gtk_doc=no]) + +m4_ifdef([GOBJECT_INTROSPECTION_CHECK], [ +GOBJECT_INTROSPECTION_CHECK([1.31.1]) +], [ + AM_CONDITIONAL([HAVE_INTROSPECTION], [false]) + enable_introspection=no]) + +PKG_CHECK_MODULES([LIBUDEV], [libudev >= 218]) +PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.22.0 gobject-2.0 >= 2.22.0 gio-2.0]) + +AC_CONFIG_FILES([ + Makefile + gudev-1.0.pc + docs/Makefile + docs/version.xml +]) + +AC_OUTPUT +AC_MSG_RESULT([ + $PACKAGE_NAME $VERSION + gintrospection: ${enable_introspection} + gtk-doc: ${enable_gtk_doc} + + prefix: ${prefix} + exec_prefix: ${exec_prefix} + includedir: ${includedir} + libdir: ${libdir} + + CFLAGS: ${CFLAGS} + CPPFLAGS: ${CPPFLAGS} + LDFLAGS: ${LDFLAGS} +]) diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..c99095e --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,12 @@ +/*.txt +/Makefile +/Makefile.in +/gudev.args +/gudev.hierarchy +/gudev.interfaces +/gudev.prerequisites +/gudev.signals +/html/ +/tmpl/ +/version.xml +/xml/ diff --git a/docs/Makefile.am b/docs/Makefile.am new file mode 100644 index 0000000..0e8d7d0 --- /dev/null +++ b/docs/Makefile.am @@ -0,0 +1,107 @@ +## Process this file with automake to produce Makefile.in + +# We require automake 1.10 at least. +AUTOMAKE_OPTIONS = 1.10 color-tests + +# This is a blank Makefile.am for using gtk-doc. +# Copy this to your project's API docs directory and modify the variables to +# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples +# of using the various options. + +# The name of the module, e.g. 'glib'. +DOC_MODULE=gudev + +# Uncomment for versioned docs and specify the version of the module, e.g. '2'. +#DOC_MODULE_VERSION=2 + +# The top-level SGML file. You can change this if you want to. +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml + +# The directory containing the source code. Relative to $(srcdir). +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting the functions and macros. +# e.g. DOC_SOURCE_DIR=../../../gtk +DOC_SOURCE_DIR=$(top_srcdir)/gudev $(top_builddir)/gudev + +# Extra options to pass to gtkdoc-scangobj. Not normally needed. +SCANGOBJ_OPTIONS= + +# Extra options to supply to gtkdoc-scan. +# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" +SCAN_OPTIONS= + +# Extra options to supply to gtkdoc-mkdb. +# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml +MKDB_OPTIONS=--xml-mode --output-format=xml --name-space=g_udev + +# Extra options to supply to gtkdoc-mktmpl +# e.g. MKTMPL_OPTIONS=--only-section-tmpl +MKTMPL_OPTIONS= + +# Extra options to supply to gtkdoc-mkhtml +MKHTML_OPTIONS=--path=$(abs_srcdir) --path=$(abs_builddir) + +# Extra options to supply to gtkdoc-fixref. Not normally needed. +# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html +FIXXREF_OPTIONS=>/dev/null 2>&1 + +# Used for dependencies. The docs will be rebuilt if any of these change. +# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h +# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c +HFILE_GLOB=$(top_srcdir)/gudev/*.h +CFILE_GLOB=$(top_srcdir)/gudev/*.c + +# Extra header to include when scanning, which are not under DOC_SOURCE_DIR +# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h +EXTRA_HFILES= + +# Header files to ignore when scanning. Use base file name, no paths +# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h +IGNORE_HFILES=gudevenumtypes.h gudevmarshal.h + +# Images to copy into HTML directory. +# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png +HTML_IMAGES= + +# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). +# e.g. content_files=running.sgml building.sgml changes-2.0.sgml +content_files = version.xml + +# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded +# These files must be listed here *and* in content_files +# e.g. expand_content_files=running.sgml +expand_content_files= + +# Hack, hack. You silly gtk-doc, you must not add CFLAGS multiple +# times when calling gcc; it surely can not work with options that must +# be listed only once. +# Kill CFLAGS here because gtk-doc thinks adding CFLAGS to CC _and_ also +# adding CFLAGS itself again would work. +override CFLAGS= +override LDFLAGS= + +# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. +# Only needed if you are using gtkdoc-scangobj to dynamically query widget +# signals and properties. +# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) +# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) +GTKDOC_CFLAGS = \ + $(GLIB_CFLAGS) \ + -I$(top_srcdir)/gudev \ + -I$(top_builddir)/gudev + +GTKDOC_LIBS = \ + $(GLIB_LIBS) \ + $(top_builddir)/libgudev-1.0.la + +# This includes the standard gtk-doc make rules, copied by gtkdocize. +include $(top_srcdir)/gtk-doc.make + +# Other files to distribute +# e.g. EXTRA_DIST += version.xml.in +EXTRA_DIST += version.xml.in + +# Files not to distribute +# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types +# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt +#DISTCLEANFILES += diff --git a/docs/gudev-docs.xml b/docs/gudev-docs.xml new file mode 100644 index 0000000..2961da3 --- /dev/null +++ b/docs/gudev-docs.xml @@ -0,0 +1,53 @@ + + +]> + + + GUdev Reference Manual + + For version &version; — the latest version of this + documentation can be found at + + https://developer.gnome.org/gudev + . + + + 2009-2015 + David Zeuthen <davidz@redhat.com> + Bastien Nocera <hadess@hadess.net> + David Herrmann <dh.herrmann@gmail.com> + + + + + API Reference + + + + + + + Object Hierarchy + + + + + API Index + + + + + Index of new symbols in 165 + + + + + Index of deprecated API + + + + + diff --git a/docs/gudev-sections.txt b/docs/gudev-sections.txt new file mode 100644 index 0000000..90765ee --- /dev/null +++ b/docs/gudev-sections.txt @@ -0,0 +1,102 @@ +
+gudevclient +GUdevClient +GUdevClient +GUdevClientClass +GUdevDeviceType +GUdevDeviceNumber +g_udev_client_new +g_udev_client_query_by_subsystem +g_udev_client_query_by_device_number +g_udev_client_query_by_device_file +g_udev_client_query_by_sysfs_path +g_udev_client_query_by_subsystem_and_name + +G_UDEV_CLIENT +G_UDEV_IS_CLIENT +G_UDEV_TYPE_CLIENT +g_udev_client_get_type +G_UDEV_CLIENT_CLASS +G_UDEV_IS_CLIENT_CLASS +G_UDEV_CLIENT_GET_CLASS + +GUdevClientPrivate +
+ +
+gudevdevice +GUdevDevice +GUdevDevice +GUdevDeviceClass +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 +g_udev_device_get_parent +g_udev_device_get_parent_with_subsystem +g_udev_device_get_tags +g_udev_device_get_is_initialized +g_udev_device_get_usec_since_initialized +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 +g_udev_device_get_property_as_strv +g_udev_device_get_sysfs_attr_keys +g_udev_device_has_sysfs_attr +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 +g_udev_device_get_sysfs_attr_as_strv + +G_UDEV_DEVICE +G_UDEV_IS_DEVICE +G_UDEV_TYPE_DEVICE +g_udev_device_get_type +G_UDEV_DEVICE_CLASS +G_UDEV_IS_DEVICE_CLASS +G_UDEV_DEVICE_GET_CLASS + +GUdevDevicePrivate +
+ +
+gudevenumerator +GUdevEnumerator +GUdevEnumerator +GUdevEnumeratorClass +g_udev_enumerator_new +g_udev_enumerator_add_match_subsystem +g_udev_enumerator_add_nomatch_subsystem +g_udev_enumerator_add_match_sysfs_attr +g_udev_enumerator_add_nomatch_sysfs_attr +g_udev_enumerator_add_match_property +g_udev_enumerator_add_match_name +g_udev_enumerator_add_match_tag +g_udev_enumerator_add_match_is_initialized +g_udev_enumerator_add_sysfs_path +g_udev_enumerator_execute + +G_UDEV_ENUMERATOR +G_UDEV_IS_ENUMERATOR +G_UDEV_TYPE_ENUMERATOR +g_udev_enumerator_get_type +G_UDEV_ENUMERATOR_CLASS +G_UDEV_IS_ENUMERATOR_CLASS +G_UDEV_ENUMERATOR_GET_CLASS + +GUdevEnumeratorPrivate +
diff --git a/docs/gudev.types b/docs/gudev.types new file mode 100644 index 0000000..a89857a --- /dev/null +++ b/docs/gudev.types @@ -0,0 +1,4 @@ +g_udev_device_type_get_type +g_udev_device_get_type +g_udev_client_get_type +g_udev_enumerator_get_type diff --git a/docs/version.xml.in b/docs/version.xml.in new file mode 100644 index 0000000..d78bda9 --- /dev/null +++ b/docs/version.xml.in @@ -0,0 +1 @@ +@VERSION@ diff --git a/gudev-1.0.pc.in b/gudev-1.0.pc.in new file mode 100644 index 0000000..058262d --- /dev/null +++ b/gudev-1.0.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: gudev-1.0 +Description: GObject bindings for libudev +Version: @VERSION@ +Requires: glib-2.0, gobject-2.0 +Libs: -L${libdir} -lgudev-1.0 +Cflags: -I${includedir}/gudev-1.0 diff --git a/gudev/gudev.h b/gudev/gudev.h new file mode 100644 index 0000000..1dc42b1 --- /dev/null +++ b/gudev/gudev.h @@ -0,0 +1,32 @@ +/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2008 David Zeuthen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __G_UDEV_H__ +#define __G_UDEV_H__ + +#define _GUDEV_INSIDE_GUDEV_H +#include +#include +#include +#include +#include +#include +#undef _GUDEV_INSIDE_GUDEV_H + +#endif /* __G_UDEV_H__ */ diff --git a/gudev/gudevclient.c b/gudev/gudevclient.c new file mode 100644 index 0000000..8b9516c --- /dev/null +++ b/gudev/gudevclient.c @@ -0,0 +1,533 @@ +/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2008-2010 David Zeuthen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "gudevclient.h" +#include "gudevdevice.h" +#include "gudevmarshal.h" +#include "gudevprivate.h" + +/** + * SECTION:gudevclient + * @short_description: Query devices and listen to uevents + * + * #GUdevClient is used to query information about devices on a Linux + * system from the Linux kernel and the udev device + * manager. + * + * Device information is retrieved from the kernel (through the + * sysfs filesystem) and the udev daemon (through a + * tmpfs filesystem) and presented through + * #GUdevDevice objects. This means that no blocking IO ever happens + * (in both cases, we are essentially just reading data from kernel + * memory) and as such there are no asynchronous versions of the + * provided methods. + * + * To get #GUdevDevice objects, use + * g_udev_client_query_by_subsystem(), + * g_udev_client_query_by_device_number(), + * g_udev_client_query_by_device_file(), + * g_udev_client_query_by_sysfs_path(), + * g_udev_client_query_by_subsystem_and_name() + * or the #GUdevEnumerator type. + * + * To listen to uevents, connect to the #GUdevClient::uevent signal. + */ + +struct _GUdevClientPrivate +{ + GSource *watch_source; + struct udev *udev; + struct udev_monitor *monitor; + + gchar **subsystems; +}; + +enum +{ + PROP_0, + PROP_SUBSYSTEMS, +}; + +enum +{ + UEVENT_SIGNAL, + LAST_SIGNAL, +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (GUdevClient, g_udev_client, G_TYPE_OBJECT) + +/* ---------------------------------------------------------------------------------------------------- */ + +static gboolean +monitor_event (GIOChannel *source, + GIOCondition condition, + gpointer data) +{ + GUdevClient *client = (GUdevClient *) data; + GUdevDevice *device; + struct udev_device *udevice; + + if (client->priv->monitor == NULL) + goto out; + udevice = udev_monitor_receive_device (client->priv->monitor); + if (udevice == NULL) + goto out; + + device = _g_udev_device_new (udevice); + udev_device_unref (udevice); + g_signal_emit (client, + signals[UEVENT_SIGNAL], + 0, + g_udev_device_get_action (device), + device); + g_object_unref (device); + + out: + return TRUE; +} + +static void +g_udev_client_finalize (GObject *object) +{ + GUdevClient *client = G_UDEV_CLIENT (object); + + if (client->priv->watch_source != NULL) + { + g_source_destroy (client->priv->watch_source); + client->priv->watch_source = NULL; + } + + if (client->priv->monitor != NULL) + { + udev_monitor_unref (client->priv->monitor); + client->priv->monitor = NULL; + } + + if (client->priv->udev != NULL) + { + udev_unref (client->priv->udev); + client->priv->udev = NULL; + } + + g_strfreev (client->priv->subsystems); + + if (G_OBJECT_CLASS (g_udev_client_parent_class)->finalize != NULL) + G_OBJECT_CLASS (g_udev_client_parent_class)->finalize (object); +} + +static void +g_udev_client_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GUdevClient *client = G_UDEV_CLIENT (object); + + switch (prop_id) + { + case PROP_SUBSYSTEMS: + if (client->priv->subsystems != NULL) + g_strfreev (client->priv->subsystems); + client->priv->subsystems = g_strdupv (g_value_get_boxed (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +g_udev_client_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GUdevClient *client = G_UDEV_CLIENT (object); + + switch (prop_id) + { + case PROP_SUBSYSTEMS: + g_value_set_boxed (value, client->priv->subsystems); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +g_udev_client_constructed (GObject *object) +{ + GUdevClient *client = G_UDEV_CLIENT (object); + GIOChannel *channel; + guint n; + + client->priv->udev = udev_new (); + + /* connect to event source */ + client->priv->monitor = udev_monitor_new_from_netlink (client->priv->udev, "udev"); + + //g_debug ("ss = %p", client->priv->subsystems); + + if (client->priv->subsystems != NULL) + { + /* install subsystem filters to only wake up for certain events */ + for (n = 0; client->priv->subsystems[n] != NULL; n++) + { + gchar *subsystem; + gchar *devtype; + gchar *s; + + subsystem = g_strdup (client->priv->subsystems[n]); + devtype = NULL; + + //g_debug ("s = '%s'", subsystem); + + s = strstr (subsystem, "/"); + if (s != NULL) + { + devtype = s + 1; + *s = '\0'; + } + + if (client->priv->monitor != NULL) + udev_monitor_filter_add_match_subsystem_devtype (client->priv->monitor, subsystem, devtype); + + g_free (subsystem); + } + + /* listen to events, and buffer them */ + if (client->priv->monitor != NULL) + { + udev_monitor_enable_receiving (client->priv->monitor); + channel = g_io_channel_unix_new (udev_monitor_get_fd (client->priv->monitor)); + client->priv->watch_source = g_io_create_watch (channel, G_IO_IN); + g_io_channel_unref (channel); + g_source_set_callback (client->priv->watch_source, (GSourceFunc) monitor_event, client, NULL); + g_source_attach (client->priv->watch_source, g_main_context_get_thread_default ()); + g_source_unref (client->priv->watch_source); + } + else + { + client->priv->watch_source = NULL; + } + } + + if (G_OBJECT_CLASS (g_udev_client_parent_class)->constructed != NULL) + G_OBJECT_CLASS (g_udev_client_parent_class)->constructed (object); +} + + +static void +g_udev_client_class_init (GUdevClientClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gobject_class->constructed = g_udev_client_constructed; + gobject_class->set_property = g_udev_client_set_property; + gobject_class->get_property = g_udev_client_get_property; + gobject_class->finalize = g_udev_client_finalize; + + /** + * GUdevClient:subsystems: + * + * The subsystems to listen for uevents on. + * + * To listen for only a specific DEVTYPE for a given SUBSYSTEM, use + * "subsystem/devtype". For example, to only listen for uevents + * where SUBSYSTEM is usb and DEVTYPE is usb_interface, use + * "usb/usb_interface". + * + * If this property is %NULL, then no events will be reported. If + * it's the empty array, events from all subsystems will be + * reported. + */ + g_object_class_install_property (gobject_class, + PROP_SUBSYSTEMS, + g_param_spec_boxed ("subsystems", + "The subsystems to listen for changes on", + "The subsystems to listen for changes on", + G_TYPE_STRV, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE)); + + /** + * GUdevClient::uevent: + * @client: The #GUdevClient receiving the event. + * @action: The action for the uevent e.g. "add", "remove", "change", "move", etc. + * @device: Details about the #GUdevDevice the event is for. + * + * Emitted when @client receives an uevent. + * + * This signal is emitted in the + * thread-default main loop + * of the thread that @client was created in. + */ + signals[UEVENT_SIGNAL] = g_signal_new ("uevent", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GUdevClientClass, uevent), + NULL, + NULL, + g_udev_marshal_VOID__STRING_OBJECT, + G_TYPE_NONE, + 2, + G_TYPE_STRING, + G_UDEV_TYPE_DEVICE); + + g_type_class_add_private (klass, sizeof (GUdevClientPrivate)); +} + +static void +g_udev_client_init (GUdevClient *client) +{ + client->priv = G_TYPE_INSTANCE_GET_PRIVATE (client, + G_UDEV_TYPE_CLIENT, + GUdevClientPrivate); +} + +/** + * g_udev_client_new: + * @subsystems: (array zero-terminated=1) (element-type utf8) (transfer none) (allow-none): A %NULL terminated string array of subsystems to listen for uevents on, %NULL to not listen on uevents at all, or an empty array to listen to uevents on all subsystems. See the documentation for the #GUdevClient:subsystems property for details on this parameter. + * + * Constructs a #GUdevClient object that can be used to query + * information about devices. Connect to the #GUdevClient::uevent + * signal to listen for uevents. Note that signals are emitted in the + * thread-default main loop + * of the thread that you call this constructor from. + * + * Returns: A new #GUdevClient object. Free with g_object_unref(). + */ +GUdevClient * +g_udev_client_new (const gchar * const *subsystems) +{ + return G_UDEV_CLIENT (g_object_new (G_UDEV_TYPE_CLIENT, "subsystems", subsystems, NULL)); +} + +/** + * g_udev_client_query_by_subsystem: + * @client: A #GUdevClient. + * @subsystem: (allow-none): The subsystem to get devices for or %NULL to get all devices. + * + * Gets all devices belonging to @subsystem. + * + * Returns: (nullable) (element-type GUdevDevice) (transfer full): A + * list of #GUdevDevice objects. The caller should free the result by + * using g_object_unref() on each element in the list and then + * g_list_free() on the list. + */ +GList * +g_udev_client_query_by_subsystem (GUdevClient *client, + const gchar *subsystem) +{ + struct udev_enumerate *enumerate; + struct udev_list_entry *l, *devices; + GList *ret; + + g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); + + ret = NULL; + + /* prepare a device scan */ + enumerate = udev_enumerate_new (client->priv->udev); + + /* filter for subsystem */ + if (subsystem != NULL) + udev_enumerate_add_match_subsystem (enumerate, subsystem); + /* retrieve the list */ + udev_enumerate_scan_devices (enumerate); + + /* add devices to the list */ + devices = udev_enumerate_get_list_entry (enumerate); + for (l = devices; l != NULL; l = udev_list_entry_get_next (l)) + { + struct udev_device *udevice; + GUdevDevice *device; + + udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate), + udev_list_entry_get_name (l)); + if (udevice == NULL) + continue; + device = _g_udev_device_new (udevice); + udev_device_unref (udevice); + ret = g_list_prepend (ret, device); + } + udev_enumerate_unref (enumerate); + + ret = g_list_reverse (ret); + + return ret; +} + +/** + * g_udev_client_query_by_device_number: + * @client: A #GUdevClient. + * @type: A value from the #GUdevDeviceType enumeration. + * @number: A device number. + * + * Looks up a device for a type and device number. + * + * Returns: (nullable) (transfer full): A #GUdevDevice object or %NULL + * if the device was not found. Free with g_object_unref(). + */ +GUdevDevice * +g_udev_client_query_by_device_number (GUdevClient *client, + GUdevDeviceType type, + GUdevDeviceNumber number) +{ + struct udev_device *udevice; + GUdevDevice *device; + + g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); + + device = NULL; + udevice = udev_device_new_from_devnum (client->priv->udev, type, number); + + if (udevice == NULL) + goto out; + + device = _g_udev_device_new (udevice); + udev_device_unref (udevice); + + out: + return device; +} + +/** + * g_udev_client_query_by_device_file: + * @client: A #GUdevClient. + * @device_file: A device file. + * + * Looks up a device for a device file. + * + * Returns: (nullable) (transfer full): A #GUdevDevice object or %NULL + * if the device was not found. Free with g_object_unref(). + */ +GUdevDevice * +g_udev_client_query_by_device_file (GUdevClient *client, + const gchar *device_file) +{ + struct stat stat_buf; + GUdevDevice *device; + + g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); + g_return_val_if_fail (device_file != NULL, NULL); + + device = NULL; + + if (stat (device_file, &stat_buf) != 0) + goto out; + + if (stat_buf.st_rdev == 0) + goto out; + + if (S_ISBLK (stat_buf.st_mode)) + device = g_udev_client_query_by_device_number (client, G_UDEV_DEVICE_TYPE_BLOCK, stat_buf.st_rdev); + else if (S_ISCHR (stat_buf.st_mode)) + device = g_udev_client_query_by_device_number (client, G_UDEV_DEVICE_TYPE_CHAR, stat_buf.st_rdev); + + out: + return device; +} + +/** + * g_udev_client_query_by_sysfs_path: + * @client: A #GUdevClient. + * @sysfs_path: A sysfs path. + * + * Looks up a device for a sysfs path. + * + * Returns: (nullable) (transfer full): A #GUdevDevice object or %NULL + * if the device was not found. Free with g_object_unref(). + */ +GUdevDevice * +g_udev_client_query_by_sysfs_path (GUdevClient *client, + const gchar *sysfs_path) +{ + struct udev_device *udevice; + GUdevDevice *device; + + g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); + g_return_val_if_fail (sysfs_path != NULL, NULL); + + device = NULL; + udevice = udev_device_new_from_syspath (client->priv->udev, sysfs_path); + if (udevice == NULL) + goto out; + + device = _g_udev_device_new (udevice); + udev_device_unref (udevice); + + out: + return device; +} + +/** + * g_udev_client_query_by_subsystem_and_name: + * @client: A #GUdevClient. + * @subsystem: A subsystem name. + * @name: The name of the device. + * + * Looks up a device for a subsystem and name. + * + * Returns: (nullable) (transfer full): A #GUdevDevice object or %NULL + * if the device was not found. Free with g_object_unref(). + */ +GUdevDevice * +g_udev_client_query_by_subsystem_and_name (GUdevClient *client, + const gchar *subsystem, + const gchar *name) +{ + struct udev_device *udevice; + GUdevDevice *device; + + g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); + g_return_val_if_fail (subsystem != NULL, NULL); + g_return_val_if_fail (name != NULL, NULL); + + device = NULL; + udevice = udev_device_new_from_subsystem_sysname (client->priv->udev, subsystem, name); + if (udevice == NULL) + goto out; + + device = _g_udev_device_new (udevice); + udev_device_unref (udevice); + + out: + return device; +} + +struct udev * +_g_udev_client_get_udev (GUdevClient *client) +{ + g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); + return client->priv->udev; +} diff --git a/gudev/gudevclient.h b/gudev/gudevclient.h new file mode 100644 index 0000000..23bfce6 --- /dev/null +++ b/gudev/gudevclient.h @@ -0,0 +1,99 @@ +/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2008 David Zeuthen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + +#ifndef __G_UDEV_CLIENT_H__ +#define __G_UDEV_CLIENT_H__ + +#include + +G_BEGIN_DECLS + +#define G_UDEV_TYPE_CLIENT (g_udev_client_get_type ()) +#define G_UDEV_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_UDEV_TYPE_CLIENT, GUdevClient)) +#define G_UDEV_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_UDEV_TYPE_CLIENT, GUdevClientClass)) +#define G_UDEV_IS_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_UDEV_TYPE_CLIENT)) +#define G_UDEV_IS_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_UDEV_TYPE_CLIENT)) +#define G_UDEV_CLIENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_UDEV_TYPE_CLIENT, GUdevClientClass)) + +typedef struct _GUdevClientClass GUdevClientClass; +typedef struct _GUdevClientPrivate GUdevClientPrivate; + +/** + * GUdevClient: + * + * The #GUdevClient struct is opaque and should not be accessed directly. + */ +struct _GUdevClient +{ + GObject parent; + + /*< private >*/ + GUdevClientPrivate *priv; +}; + +/** + * GUdevClientClass: + * @parent_class: Parent class. + * @uevent: Signal class handler for the #GUdevClient::uevent signal. + * + * Class structure for #GUdevClient. + */ +struct _GUdevClientClass +{ + GObjectClass parent_class; + + /* signals */ + void (*uevent) (GUdevClient *client, + const gchar *action, + GUdevDevice *device); + + /*< private >*/ + /* Padding for future expansion */ + void (*reserved1) (void); + void (*reserved2) (void); + void (*reserved3) (void); + void (*reserved4) (void); + void (*reserved5) (void); + void (*reserved6) (void); + void (*reserved7) (void); + void (*reserved8) (void); +}; + +GType g_udev_client_get_type (void) G_GNUC_CONST; +GUdevClient *g_udev_client_new (const gchar* const *subsystems); +GList *g_udev_client_query_by_subsystem (GUdevClient *client, + const gchar *subsystem); +GUdevDevice *g_udev_client_query_by_device_number (GUdevClient *client, + GUdevDeviceType type, + GUdevDeviceNumber number); +GUdevDevice *g_udev_client_query_by_device_file (GUdevClient *client, + const gchar *device_file); +GUdevDevice *g_udev_client_query_by_sysfs_path (GUdevClient *client, + const gchar *sysfs_path); +GUdevDevice *g_udev_client_query_by_subsystem_and_name (GUdevClient *client, + const gchar *subsystem, + const gchar *name); + +G_END_DECLS + +#endif /* __G_UDEV_CLIENT_H__ */ diff --git a/gudev/gudevdevice.c b/gudev/gudevdevice.c new file mode 100644 index 0000000..5530d2c --- /dev/null +++ b/gudev/gudevdevice.c @@ -0,0 +1,1027 @@ +/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2008 David Zeuthen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#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_keys(), + * g_udev_device_has_sysfs_attr(), + * 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; + gchar **sysfs_attr_keys; + gchar **tags; + 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); + g_strfreev (device->priv->sysfs_attr_keys); + g_strfreev (device->priv->tags); + + 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: (nullable): 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: (nullable): 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 /dev) 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: (nullable) (transfer full): 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: (nullable) (transfer full): 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: (nullable): 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 g_ascii_strtoull(). + * + * 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 = g_ascii_strtoull (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: (nullable) (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_keys: + * @device: A #GUdevDevice. + * + * Gets all keys for sysfs attributes on @device. + * + * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): A %NULL terminated string array of sysfs attribute keys. This array is owned by @device and should not be freed by the caller. + */ +const gchar * const * +g_udev_device_get_sysfs_attr_keys (GUdevDevice *device) +{ + struct udev_list_entry *l; + GPtrArray *p; + + g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); + + if (device->priv->sysfs_attr_keys != NULL) + goto out; + + p = g_ptr_array_new (); + for (l = udev_device_get_sysattr_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->sysfs_attr_keys = (gchar **) g_ptr_array_free (p, FALSE); + + out: + return (const gchar * const *) device->priv->sysfs_attr_keys; +} + +/** + * g_udev_device_has_sysfs_attr: + * @device: A #GUdevDevice. + * @key: Name of sysfs attribute. + * + * Check if a the sysfs attribute with the given key exists. + * + * Returns: %TRUE only if the value for @key exist. + */ +gboolean +g_udev_device_has_sysfs_attr (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_sysattr_value (device->priv->udevice, key) != NULL; +} + +/** + * 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: (nullable): 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 g_ascii_strtoull(). + * + * 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 = g_ascii_strtoull (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: (nullable) (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; +} + +/** + * g_udev_device_get_tags: + * @device: A #GUdevDevice. + * + * Gets all tags for @device. + * + * Returns: (transfer none) (array zero-terminated=1) (element-type utf8): A %NULL terminated string array of tags. This array is owned by @device and should not be freed by the caller. + * + * Since: 165 + */ +const gchar* const * +g_udev_device_get_tags (GUdevDevice *device) +{ + struct udev_list_entry *l; + GPtrArray *p; + + g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL); + + if (device->priv->tags != NULL) + goto out; + + p = g_ptr_array_new (); + for (l = udev_device_get_tags_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->tags = (gchar **) g_ptr_array_free (p, FALSE); + + out: + return (const gchar * const *) device->priv->tags; +} + +/** + * g_udev_device_get_is_initialized: + * @device: A #GUdevDevice. + * + * Gets whether @device has been initalized. + * + * Returns: Whether @device has been initialized. + * + * Since: 165 + */ +gboolean +g_udev_device_get_is_initialized (GUdevDevice *device) +{ + g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE); + return udev_device_get_is_initialized (device->priv->udevice); +} + +/** + * g_udev_device_get_usec_since_initialized: + * @device: A #GUdevDevice. + * + * Gets number of micro-seconds since @device was initialized. + * + * This only works for devices with properties in the udev + * database. All other devices return 0. + * + * Returns: Number of micro-seconds since @device was initialized or 0 if unknown. + * + * Since: 165 + */ +guint64 +g_udev_device_get_usec_since_initialized (GUdevDevice *device) +{ + g_return_val_if_fail (G_UDEV_IS_DEVICE (device), 0); + return udev_device_get_usec_since_initialized (device->priv->udevice); +} diff --git a/gudev/gudevdevice.h b/gudev/gudevdevice.h new file mode 100644 index 0000000..72ec180 --- /dev/null +++ b/gudev/gudevdevice.h @@ -0,0 +1,130 @@ +/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2008 David Zeuthen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + +#ifndef __G_UDEV_DEVICE_H__ +#define __G_UDEV_DEVICE_H__ + +#include + +G_BEGIN_DECLS + +#define G_UDEV_TYPE_DEVICE (g_udev_device_get_type ()) +#define G_UDEV_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_UDEV_TYPE_DEVICE, GUdevDevice)) +#define G_UDEV_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_UDEV_TYPE_DEVICE, GUdevDeviceClass)) +#define G_UDEV_IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_UDEV_TYPE_DEVICE)) +#define G_UDEV_IS_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_UDEV_TYPE_DEVICE)) +#define G_UDEV_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_UDEV_TYPE_DEVICE, GUdevDeviceClass)) + +typedef struct _GUdevDeviceClass GUdevDeviceClass; +typedef struct _GUdevDevicePrivate GUdevDevicePrivate; + +/** + * GUdevDevice: + * + * The #GUdevDevice struct is opaque and should not be accessed directly. + */ +struct _GUdevDevice +{ + GObject parent; + + /*< private >*/ + GUdevDevicePrivate *priv; +}; + +/** + * GUdevDeviceClass: + * @parent_class: Parent class. + * + * Class structure for #GUdevDevice. + */ +struct _GUdevDeviceClass +{ + GObjectClass parent_class; + + /*< private >*/ + /* Padding for future expansion */ + void (*reserved1) (void); + void (*reserved2) (void); + void (*reserved3) (void); + void (*reserved4) (void); + void (*reserved5) (void); + void (*reserved6) (void); + void (*reserved7) (void); + void (*reserved8) (void); +}; + +GType g_udev_device_get_type (void) G_GNUC_CONST; +gboolean g_udev_device_get_is_initialized (GUdevDevice *device); +guint64 g_udev_device_get_usec_since_initialized (GUdevDevice *device); +const gchar *g_udev_device_get_subsystem (GUdevDevice *device); +const gchar *g_udev_device_get_devtype (GUdevDevice *device); +const gchar *g_udev_device_get_name (GUdevDevice *device); +const gchar *g_udev_device_get_number (GUdevDevice *device); +const gchar *g_udev_device_get_sysfs_path (GUdevDevice *device); +const gchar *g_udev_device_get_driver (GUdevDevice *device); +const gchar *g_udev_device_get_action (GUdevDevice *device); +guint64 g_udev_device_get_seqnum (GUdevDevice *device); +GUdevDeviceType g_udev_device_get_device_type (GUdevDevice *device); +GUdevDeviceNumber g_udev_device_get_device_number (GUdevDevice *device); +const gchar *g_udev_device_get_device_file (GUdevDevice *device); +const gchar* const *g_udev_device_get_device_file_symlinks (GUdevDevice *device); +GUdevDevice *g_udev_device_get_parent (GUdevDevice *device); +GUdevDevice *g_udev_device_get_parent_with_subsystem (GUdevDevice *device, + const gchar *subsystem, + const gchar *devtype); +const gchar* const *g_udev_device_get_property_keys (GUdevDevice *device); +gboolean g_udev_device_has_property (GUdevDevice *device, + const gchar *key); +const gchar *g_udev_device_get_property (GUdevDevice *device, + const gchar *key); +gint g_udev_device_get_property_as_int (GUdevDevice *device, + const gchar *key); +guint64 g_udev_device_get_property_as_uint64 (GUdevDevice *device, + const gchar *key); +gdouble g_udev_device_get_property_as_double (GUdevDevice *device, + const gchar *key); +gboolean g_udev_device_get_property_as_boolean (GUdevDevice *device, + const gchar *key); +const gchar* const *g_udev_device_get_property_as_strv (GUdevDevice *device, + const gchar *key); + +const gchar* const *g_udev_device_get_sysfs_attr_keys (GUdevDevice *device); +gboolean g_udev_device_has_sysfs_attr (GUdevDevice *device, + const gchar *key); +const gchar *g_udev_device_get_sysfs_attr (GUdevDevice *device, + const gchar *name); +gint g_udev_device_get_sysfs_attr_as_int (GUdevDevice *device, + const gchar *name); +guint64 g_udev_device_get_sysfs_attr_as_uint64 (GUdevDevice *device, + const gchar *name); +gdouble g_udev_device_get_sysfs_attr_as_double (GUdevDevice *device, + const gchar *name); +gboolean g_udev_device_get_sysfs_attr_as_boolean (GUdevDevice *device, + const gchar *name); +const gchar* const *g_udev_device_get_sysfs_attr_as_strv (GUdevDevice *device, + const gchar *name); +const gchar* const *g_udev_device_get_tags (GUdevDevice *device); + +G_END_DECLS + +#endif /* __G_UDEV_DEVICE_H__ */ diff --git a/gudev/gudevenumerator.c b/gudev/gudevenumerator.c new file mode 100644 index 0000000..1fb3098 --- /dev/null +++ b/gudev/gudevenumerator.c @@ -0,0 +1,429 @@ +/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2008-2010 David Zeuthen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "gudevclient.h" +#include "gudevenumerator.h" +#include "gudevdevice.h" +#include "gudevmarshal.h" +#include "gudevprivate.h" + +/** + * SECTION:gudevenumerator + * @short_description: Lookup and sort devices + * + * #GUdevEnumerator is used to lookup and sort devices. + * + * Since: 165 + */ + +struct _GUdevEnumeratorPrivate +{ + GUdevClient *client; + struct udev_enumerate *e; +}; + +enum +{ + PROP_0, + PROP_CLIENT, +}; + +G_DEFINE_TYPE (GUdevEnumerator, g_udev_enumerator, G_TYPE_OBJECT) + +/* ---------------------------------------------------------------------------------------------------- */ + +static void +g_udev_enumerator_finalize (GObject *object) +{ + GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object); + + if (enumerator->priv->client != NULL) + { + g_object_unref (enumerator->priv->client); + enumerator->priv->client = NULL; + } + + if (enumerator->priv->e != NULL) + { + udev_enumerate_unref (enumerator->priv->e); + enumerator->priv->e = NULL; + } + + if (G_OBJECT_CLASS (g_udev_enumerator_parent_class)->finalize != NULL) + G_OBJECT_CLASS (g_udev_enumerator_parent_class)->finalize (object); +} + +static void +g_udev_enumerator_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object); + + switch (prop_id) + { + case PROP_CLIENT: + if (enumerator->priv->client != NULL) + g_object_unref (enumerator->priv->client); + enumerator->priv->client = g_value_dup_object (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +g_udev_enumerator_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object); + + switch (prop_id) + { + case PROP_CLIENT: + g_value_set_object (value, enumerator->priv->client); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +g_udev_enumerator_constructed (GObject *object) +{ + GUdevEnumerator *enumerator = G_UDEV_ENUMERATOR (object); + + g_assert (G_UDEV_IS_CLIENT (enumerator->priv->client)); + + enumerator->priv->e = udev_enumerate_new (_g_udev_client_get_udev (enumerator->priv->client)); + + if (G_OBJECT_CLASS (g_udev_enumerator_parent_class)->constructed != NULL) + G_OBJECT_CLASS (g_udev_enumerator_parent_class)->constructed (object); +} + +static void +g_udev_enumerator_class_init (GUdevEnumeratorClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gobject_class->finalize = g_udev_enumerator_finalize; + gobject_class->set_property = g_udev_enumerator_set_property; + gobject_class->get_property = g_udev_enumerator_get_property; + gobject_class->constructed = g_udev_enumerator_constructed; + + /** + * GUdevEnumerator:client: + * + * The #GUdevClient to enumerate devices from. + * + * Since: 165 + */ + g_object_class_install_property (gobject_class, + PROP_CLIENT, + g_param_spec_object ("client", + "The client to enumerate devices from", + "The client to enumerate devices from", + G_UDEV_TYPE_CLIENT, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE)); + + g_type_class_add_private (klass, sizeof (GUdevEnumeratorPrivate)); +} + +static void +g_udev_enumerator_init (GUdevEnumerator *enumerator) +{ + enumerator->priv = G_TYPE_INSTANCE_GET_PRIVATE (enumerator, + G_UDEV_TYPE_ENUMERATOR, + GUdevEnumeratorPrivate); +} + +/** + * g_udev_enumerator_new: + * @client: A #GUdevClient to enumerate devices from. + * + * Constructs a #GUdevEnumerator object that can be used to enumerate + * and sort devices. Use the add_match_*() and add_nomatch_*() methods + * and execute the query to get a list of devices with + * g_udev_enumerator_execute(). + * + * Returns: A new #GUdevEnumerator object. Free with g_object_unref(). + * + * Since: 165 + */ +GUdevEnumerator * +g_udev_enumerator_new (GUdevClient *client) +{ + g_return_val_if_fail (G_UDEV_IS_CLIENT (client), NULL); + return G_UDEV_ENUMERATOR (g_object_new (G_UDEV_TYPE_ENUMERATOR, "client", client, NULL)); +} + + +/** + * g_udev_enumerator_add_match_subsystem: + * @enumerator: A #GUdevEnumerator. + * @subsystem: Wildcard for subsystem name e.g. 'scsi' or 'a*'. + * + * All returned devices will match the given @subsystem. + * + * Returns: (transfer none): The passed in @enumerator. + * + * Since: 165 + */ +GUdevEnumerator * +g_udev_enumerator_add_match_subsystem (GUdevEnumerator *enumerator, + const gchar *subsystem) +{ + g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); + g_return_val_if_fail (subsystem != NULL, NULL); + udev_enumerate_add_match_subsystem (enumerator->priv->e, subsystem); + return enumerator; +} + +/** + * g_udev_enumerator_add_nomatch_subsystem: + * @enumerator: A #GUdevEnumerator. + * @subsystem: Wildcard for subsystem name e.g. 'scsi' or 'a*'. + * + * All returned devices will not match the given @subsystem. + * + * Returns: (transfer none): The passed in @enumerator. + * + * Since: 165 + */ +GUdevEnumerator * +g_udev_enumerator_add_nomatch_subsystem (GUdevEnumerator *enumerator, + const gchar *subsystem) +{ + g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); + g_return_val_if_fail (subsystem != NULL, NULL); + udev_enumerate_add_nomatch_subsystem (enumerator->priv->e, subsystem); + return enumerator; +} + +/** + * g_udev_enumerator_add_match_sysfs_attr: + * @enumerator: A #GUdevEnumerator. + * @name: Wildcard filter for sysfs attribute key. + * @value: Wildcard filter for sysfs attribute value. + * + * All returned devices will have a sysfs attribute matching the given @name and @value. + * + * Returns: (transfer none): The passed in @enumerator. + * + * Since: 165 + */ +GUdevEnumerator * +g_udev_enumerator_add_match_sysfs_attr (GUdevEnumerator *enumerator, + const gchar *name, + const gchar *value) +{ + g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (value != NULL, NULL); + udev_enumerate_add_match_sysattr (enumerator->priv->e, name, value); + return enumerator; +} + +/** + * g_udev_enumerator_add_nomatch_sysfs_attr: + * @enumerator: A #GUdevEnumerator. + * @name: Wildcard filter for sysfs attribute key. + * @value: Wildcard filter for sysfs attribute value. + * + * All returned devices will not have a sysfs attribute matching the given @name and @value. + * + * Returns: (transfer none): The passed in @enumerator. + * + * Since: 165 + */ +GUdevEnumerator * +g_udev_enumerator_add_nomatch_sysfs_attr (GUdevEnumerator *enumerator, + const gchar *name, + const gchar *value) +{ + g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (value != NULL, NULL); + udev_enumerate_add_nomatch_sysattr (enumerator->priv->e, name, value); + return enumerator; +} + +/** + * g_udev_enumerator_add_match_property: + * @enumerator: A #GUdevEnumerator. + * @name: Wildcard filter for property name. + * @value: Wildcard filter for property value. + * + * All returned devices will have a property matching the given @name and @value. + * + * Returns: (transfer none): The passed in @enumerator. + * + * Since: 165 + */ +GUdevEnumerator * +g_udev_enumerator_add_match_property (GUdevEnumerator *enumerator, + const gchar *name, + const gchar *value) +{ + g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (value != NULL, NULL); + udev_enumerate_add_match_property (enumerator->priv->e, name, value); + return enumerator; +} + +/** + * g_udev_enumerator_add_match_name: + * @enumerator: A #GUdevEnumerator. + * @name: Wildcard filter for kernel name e.g. "sda*". + * + * All returned devices will match the given @name. + * + * Returns: (transfer none): The passed in @enumerator. + * + * Since: 165 + */ +GUdevEnumerator * +g_udev_enumerator_add_match_name (GUdevEnumerator *enumerator, + const gchar *name) +{ + g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); + g_return_val_if_fail (name != NULL, NULL); + udev_enumerate_add_match_sysname (enumerator->priv->e, name); + return enumerator; +} + +/** + * g_udev_enumerator_add_sysfs_path: + * @enumerator: A #GUdevEnumerator. + * @sysfs_path: A sysfs path, e.g. "/sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda" + * + * Add a device to the list of devices, to retrieve it back sorted in dependency order. + * + * Returns: (transfer none): The passed in @enumerator. + * + * Since: 165 + */ +GUdevEnumerator * +g_udev_enumerator_add_sysfs_path (GUdevEnumerator *enumerator, + const gchar *sysfs_path) +{ + g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); + g_return_val_if_fail (sysfs_path != NULL, NULL); + udev_enumerate_add_syspath (enumerator->priv->e, sysfs_path); + return enumerator; +} + +/** + * g_udev_enumerator_add_match_tag: + * @enumerator: A #GUdevEnumerator. + * @tag: A udev tag e.g. "udev-acl". + * + * All returned devices will match the given @tag. + * + * Returns: (transfer none): The passed in @enumerator. + * + * Since: 165 + */ +GUdevEnumerator * +g_udev_enumerator_add_match_tag (GUdevEnumerator *enumerator, + const gchar *tag) +{ + g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); + g_return_val_if_fail (tag != NULL, NULL); + udev_enumerate_add_match_tag (enumerator->priv->e, tag); + return enumerator; +} + +/** + * g_udev_enumerator_add_match_is_initialized: + * @enumerator: A #GUdevEnumerator. + * + * All returned devices will be initialized. + * + * Returns: (transfer none): The passed in @enumerator. + * + * Since: 165 + */ +GUdevEnumerator * +g_udev_enumerator_add_match_is_initialized (GUdevEnumerator *enumerator) +{ + g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); + udev_enumerate_add_match_is_initialized (enumerator->priv->e); + return enumerator; +} + +/** + * g_udev_enumerator_execute: + * @enumerator: A #GUdevEnumerator. + * + * Executes the query in @enumerator. + * + * Returns: (element-type GUdevDevice) (transfer full): A list of #GUdevDevice objects. The caller should free the result by using g_object_unref() on each element in the list and then g_list_free() on the list. + * + * Since: 165 + */ +GList * +g_udev_enumerator_execute (GUdevEnumerator *enumerator) +{ + GList *ret; + struct udev_list_entry *l, *devices; + + g_return_val_if_fail (G_UDEV_IS_ENUMERATOR (enumerator), NULL); + + ret = NULL; + + /* retrieve the list */ + udev_enumerate_scan_devices (enumerator->priv->e); + + devices = udev_enumerate_get_list_entry (enumerator->priv->e); + for (l = devices; l != NULL; l = udev_list_entry_get_next (l)) + { + struct udev_device *udevice; + GUdevDevice *device; + + udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerator->priv->e), + udev_list_entry_get_name (l)); + if (udevice == NULL) + continue; + + device = _g_udev_device_new (udevice); + udev_device_unref (udevice); + ret = g_list_prepend (ret, device); + } + + ret = g_list_reverse (ret); + + return ret; +} diff --git a/gudev/gudevenumerator.h b/gudev/gudevenumerator.h new file mode 100644 index 0000000..e1dbcf1 --- /dev/null +++ b/gudev/gudevenumerator.h @@ -0,0 +1,106 @@ +/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2008-2010 David Zeuthen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + +#ifndef __G_UDEV_ENUMERATOR_H__ +#define __G_UDEV_ENUMERATOR_H__ + +#include + +G_BEGIN_DECLS + +#define G_UDEV_TYPE_ENUMERATOR (g_udev_enumerator_get_type ()) +#define G_UDEV_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_UDEV_TYPE_ENUMERATOR, GUdevEnumerator)) +#define G_UDEV_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_UDEV_TYPE_ENUMERATOR, GUdevEnumeratorClass)) +#define G_UDEV_IS_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_UDEV_TYPE_ENUMERATOR)) +#define G_UDEV_IS_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_UDEV_TYPE_ENUMERATOR)) +#define G_UDEV_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_UDEV_TYPE_ENUMERATOR, GUdevEnumeratorClass)) + +typedef struct _GUdevEnumeratorClass GUdevEnumeratorClass; +typedef struct _GUdevEnumeratorPrivate GUdevEnumeratorPrivate; + +/** + * GUdevEnumerator: + * + * The #GUdevEnumerator struct is opaque and should not be accessed directly. + * + * Since: 165 + */ +struct _GUdevEnumerator +{ + GObject parent; + + /*< private >*/ + GUdevEnumeratorPrivate *priv; +}; + +/** + * GUdevEnumeratorClass: + * @parent_class: Parent class. + * + * Class structure for #GUdevEnumerator. + * + * Since: 165 + */ +struct _GUdevEnumeratorClass +{ + GObjectClass parent_class; + + /*< private >*/ + /* Padding for future expansion */ + void (*reserved1) (void); + void (*reserved2) (void); + void (*reserved3) (void); + void (*reserved4) (void); + void (*reserved5) (void); + void (*reserved6) (void); + void (*reserved7) (void); + void (*reserved8) (void); +}; + +GType g_udev_enumerator_get_type (void) G_GNUC_CONST; +GUdevEnumerator *g_udev_enumerator_new (GUdevClient *client); +GUdevEnumerator *g_udev_enumerator_add_match_subsystem (GUdevEnumerator *enumerator, + const gchar *subsystem); +GUdevEnumerator *g_udev_enumerator_add_nomatch_subsystem (GUdevEnumerator *enumerator, + const gchar *subsystem); +GUdevEnumerator *g_udev_enumerator_add_match_sysfs_attr (GUdevEnumerator *enumerator, + const gchar *name, + const gchar *value); +GUdevEnumerator *g_udev_enumerator_add_nomatch_sysfs_attr (GUdevEnumerator *enumerator, + const gchar *name, + const gchar *value); +GUdevEnumerator *g_udev_enumerator_add_match_property (GUdevEnumerator *enumerator, + const gchar *name, + const gchar *value); +GUdevEnumerator *g_udev_enumerator_add_match_name (GUdevEnumerator *enumerator, + const gchar *name); +GUdevEnumerator *g_udev_enumerator_add_match_tag (GUdevEnumerator *enumerator, + const gchar *tag); +GUdevEnumerator *g_udev_enumerator_add_match_is_initialized (GUdevEnumerator *enumerator); +GUdevEnumerator *g_udev_enumerator_add_sysfs_path (GUdevEnumerator *enumerator, + const gchar *sysfs_path); +GList *g_udev_enumerator_execute (GUdevEnumerator *enumerator); + +G_END_DECLS + +#endif /* __G_UDEV_ENUMERATOR_H__ */ diff --git a/gudev/gudevenums.h b/gudev/gudevenums.h new file mode 100644 index 0000000..467e93b --- /dev/null +++ b/gudev/gudevenums.h @@ -0,0 +1,48 @@ +/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2008 David Zeuthen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + +#ifndef __G_UDEV_ENUMS_H__ +#define __G_UDEV_ENUMS_H__ + +#include + +G_BEGIN_DECLS + +/** + * GUdevDeviceType: + * @G_UDEV_DEVICE_TYPE_NONE: Device does not have a device file. + * @G_UDEV_DEVICE_TYPE_BLOCK: Device is a block device. + * @G_UDEV_DEVICE_TYPE_CHAR: Device is a character device. + * + * Enumeration used to specify a the type of a device. + */ +typedef enum +{ + G_UDEV_DEVICE_TYPE_NONE = 0, + G_UDEV_DEVICE_TYPE_BLOCK = 'b', + G_UDEV_DEVICE_TYPE_CHAR = 'c', +} GUdevDeviceType; + +G_END_DECLS + +#endif /* __G_UDEV_ENUMS_H__ */ diff --git a/gudev/gudevenumtypes.c.template b/gudev/gudevenumtypes.c.template new file mode 100644 index 0000000..fc30b39 --- /dev/null +++ b/gudev/gudevenumtypes.c.template @@ -0,0 +1,39 @@ +/*** BEGIN file-header ***/ +#include + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@filename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} + +/*** END value-tail ***/ + +/*** BEGIN file-tail ***/ +/*** END file-tail ***/ diff --git a/gudev/gudevenumtypes.h.template b/gudev/gudevenumtypes.h.template new file mode 100644 index 0000000..d0ab339 --- /dev/null +++ b/gudev/gudevenumtypes.h.template @@ -0,0 +1,24 @@ +/*** BEGIN file-header ***/ +#ifndef __GUDEV_ENUM_TYPES_H__ +#define __GUDEV_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS +/*** END file-header ***/ + +/*** BEGIN file-production ***/ + +/* enumerations from "@filename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType @enum_name@_get_type (void) G_GNUC_CONST; +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) +/*** END value-header ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* __GUDEV_ENUM_TYPES_H__ */ +/*** END file-tail ***/ diff --git a/gudev/gudevmarshal.list b/gudev/gudevmarshal.list new file mode 100644 index 0000000..7e66599 --- /dev/null +++ b/gudev/gudevmarshal.list @@ -0,0 +1 @@ +VOID:STRING,OBJECT diff --git a/gudev/gudevprivate.h b/gudev/gudevprivate.h new file mode 100644 index 0000000..52e272b --- /dev/null +++ b/gudev/gudevprivate.h @@ -0,0 +1,40 @@ +/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2008 David Zeuthen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + +#ifndef __G_UDEV_PRIVATE_H__ +#define __G_UDEV_PRIVATE_H__ + +#include + +#include + +G_BEGIN_DECLS + +GUdevDevice * +_g_udev_device_new (struct udev_device *udevice); + +struct udev *_g_udev_client_get_udev (GUdevClient *client); + +G_END_DECLS + +#endif /* __G_UDEV_PRIVATE_H__ */ diff --git a/gudev/gudevtypes.h b/gudev/gudevtypes.h new file mode 100644 index 0000000..e2f688f --- /dev/null +++ b/gudev/gudevtypes.h @@ -0,0 +1,50 @@ +/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2008 David Zeuthen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if !defined (_GUDEV_COMPILATION) && !defined(_GUDEV_INSIDE_GUDEV_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + +#ifndef __G_UDEV_TYPES_H__ +#define __G_UDEV_TYPES_H__ + +#include +#include + +G_BEGIN_DECLS + +typedef struct _GUdevClient GUdevClient; +typedef struct _GUdevDevice GUdevDevice; +typedef struct _GUdevEnumerator GUdevEnumerator; + +/** + * GUdevDeviceNumber: + * + * Corresponds to the standard #dev_t type as defined by POSIX (Until + * bug 584517 is resolved this work-around is needed). + */ +#ifdef _GUDEV_WORK_AROUND_DEV_T_BUG +typedef guint64 GUdevDeviceNumber; /* __UQUAD_TYPE */ +#else +typedef dev_t GUdevDeviceNumber; +#endif + +G_END_DECLS + +#endif /* __G_UDEV_TYPES_H__ */ diff --git a/libgudev-1.0.sym b/libgudev-1.0.sym new file mode 100644 index 0000000..0600486 --- /dev/null +++ b/libgudev-1.0.sym @@ -0,0 +1,68 @@ +/*** + This file is part of systemd. + + systemd 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.1 of the License, or + (at your option) any later version. +***/ + +{ +global: + g_udev_client_get_type; + g_udev_client_new; + g_udev_client_query_by_device_file; + g_udev_client_query_by_device_number; + g_udev_client_query_by_subsystem; + g_udev_client_query_by_subsystem_and_name; + g_udev_client_query_by_sysfs_path; + g_udev_device_get_action; + g_udev_device_get_device_file; + g_udev_device_get_device_file_symlinks; + g_udev_device_get_device_number; + g_udev_device_get_device_type; + g_udev_device_get_devtype; + g_udev_device_get_driver; + g_udev_device_get_is_initialized; + g_udev_device_get_name; + g_udev_device_get_number; + g_udev_device_get_parent; + g_udev_device_get_parent_with_subsystem; + g_udev_device_get_property; + g_udev_device_get_property_as_boolean; + g_udev_device_get_property_as_double; + g_udev_device_get_property_as_int; + g_udev_device_get_property_as_strv; + g_udev_device_get_property_as_uint64; + g_udev_device_get_property_keys; + g_udev_device_get_seqnum; + g_udev_device_get_subsystem; + g_udev_device_get_sysfs_attr; + g_udev_device_get_sysfs_attr_as_boolean; + g_udev_device_get_sysfs_attr_as_double; + g_udev_device_get_sysfs_attr_as_int; + g_udev_device_get_sysfs_attr_as_strv; + g_udev_device_get_sysfs_attr_as_uint64; + g_udev_device_get_sysfs_attr_keys; + g_udev_device_get_sysfs_path; + g_udev_device_get_tags; + g_udev_device_get_type; + g_udev_device_get_usec_since_initialized; + g_udev_device_has_property; + g_udev_device_has_sysfs_attr; + g_udev_device_type_get_type; + g_udev_enumerator_add_match_is_initialized; + g_udev_enumerator_add_match_name; + g_udev_enumerator_add_match_property; + g_udev_enumerator_add_match_subsystem; + g_udev_enumerator_add_match_sysfs_attr; + g_udev_enumerator_add_match_tag; + g_udev_enumerator_add_nomatch_subsystem; + g_udev_enumerator_add_nomatch_sysfs_attr; + g_udev_enumerator_add_sysfs_path; + g_udev_enumerator_execute; + g_udev_enumerator_get_type; + g_udev_enumerator_new; +local: + *; +}; diff --git a/scripts/gjs-example.js b/scripts/gjs-example.js new file mode 100755 index 0000000..5586fd6 --- /dev/null +++ b/scripts/gjs-example.js @@ -0,0 +1,75 @@ +#!/usr/bin/env gjs-console + +// This currently depends on the following patches to gjs +// +// http://bugzilla.gnome.org/show_bug.cgi?id=584558 +// http://bugzilla.gnome.org/show_bug.cgi?id=584560 +// http://bugzilla.gnome.org/show_bug.cgi?id=584568 + +const GUdev = imports.gi.GUdev; +const Mainloop = imports.mainloop; + +function print_device (device) { + print (" subsystem: " + device.get_subsystem ()); + print (" devtype: " + device.get_devtype ()); + print (" name: " + device.get_name ()); + print (" number: " + device.get_number ()); + print (" sysfs_path: " + device.get_sysfs_path ()); + print (" driver: " + device.get_driver ()); + print (" action: " + device.get_action ()); + print (" seqnum: " + device.get_seqnum ()); + print (" device type: " + device.get_device_type ()); + print (" device number: " + device.get_device_number ()); + print (" device file: " + device.get_device_file ()); + print (" device file symlinks: " + device.get_device_file_symlinks ()); + print (" foo: " + device.get_sysfs_attr_as_strv ("stat")); + var keys = device.get_property_keys (); + for (var n = 0; n < keys.length; n++) { + print (" " + keys[n] + "=" + device.get_property (keys[n])); + } +} + +function on_uevent (client, action, device) { + print ("action " + action + " on device " + device.get_sysfs_path()); + print_device (device); + print (""); +} + +var client = new GUdev.Client ({subsystems: ["block", "usb/usb_interface"]}); +client.connect ("uevent", on_uevent); + +var block_devices = client.query_by_subsystem ("block"); +for (var n = 0; n < block_devices.length; n++) { + print ("block device: " + block_devices[n].get_device_file ()); +} + +var d; + +d = client.query_by_device_number (GUdev.DeviceType.BLOCK, 0x0810); +if (d == null) { + print ("query_by_device_number 0x810 -> null"); +} else { + print ("query_by_device_number 0x810 -> " + d.get_device_file ()); + var dd = d.get_parent_with_subsystem ("usb", null); + print_device (dd); + print ("--------------------------------------------------------------------------"); + while (d != null) { + print_device (d); + print (""); + d = d.get_parent (); + } +} + +d = client.query_by_sysfs_path ("/sys/block/sda/sda1"); +print ("query_by_sysfs_path (\"/sys/block/sda1\") -> " + d.get_device_file ()); + +d = client.query_by_subsystem_and_name ("block", "sda2"); +print ("query_by_subsystem_and_name (\"block\", \"sda2\") -> " + d.get_device_file ()); + +d = client.query_by_device_file ("/dev/sda"); +print ("query_by_device_file (\"/dev/sda\") -> " + d.get_device_file ()); + +d = client.query_by_device_file ("/dev/block/8:0"); +print ("query_by_device_file (\"/dev/block/8:0\") -> " + d.get_device_file ()); + +Mainloop.run('udev-example'); diff --git a/scripts/seed-example-enum.js b/scripts/seed-example-enum.js new file mode 100755 index 0000000..66206ad --- /dev/null +++ b/scripts/seed-example-enum.js @@ -0,0 +1,38 @@ +#!/usr/bin/env seed + +const GLib = imports.gi.GLib; +const GUdev = imports.gi.GUdev; + +function print_device(device) { + print(" initialized: " + device.get_is_initialized()); + print(" usec since initialized: " + device.get_usec_since_initialized()); + print(" subsystem: " + device.get_subsystem()); + print(" devtype: " + device.get_devtype()); + print(" name: " + device.get_name()); + print(" number: " + device.get_number()); + print(" sysfs_path: " + device.get_sysfs_path()); + print(" driver: " + device.get_driver()); + print(" action: " + device.get_action()); + print(" seqnum: " + device.get_seqnum()); + print(" device type: " + device.get_device_type()); + print(" device number: " + device.get_device_number()); + print(" device file: " + device.get_device_file()); + print(" device file symlinks: " + device.get_device_file_symlinks()); + print(" tags: " + device.get_tags()); + var keys = device.get_property_keys(); + for (var n = 0; n < keys.length; n++) { + print(" " + keys[n] + "=" + device.get_property(keys[n])); + } +} + +var client = new GUdev.Client({subsystems: []}); +var enumerator = new GUdev.Enumerator({client: client}); +enumerator.add_match_subsystem('b*') + +var devices = enumerator.execute(); + +for (var n=0; n < devices.length; n++) { + var device = devices[n]; + print_device(device); + print(""); +} diff --git a/scripts/seed-example.js b/scripts/seed-example.js new file mode 100755 index 0000000..e2ac324 --- /dev/null +++ b/scripts/seed-example.js @@ -0,0 +1,72 @@ +#!/usr/bin/env seed + +// seed example + +const GLib = imports.gi.GLib; +const GUdev = imports.gi.GUdev; + +function print_device (device) { + print (" subsystem: " + device.get_subsystem ()); + print (" devtype: " + device.get_devtype ()); + print (" name: " + device.get_name ()); + print (" number: " + device.get_number ()); + print (" sysfs_path: " + device.get_sysfs_path ()); + print (" driver: " + device.get_driver ()); + print (" action: " + device.get_action ()); + print (" seqnum: " + device.get_seqnum ()); + print (" device type: " + device.get_device_type ()); + print (" device number: " + device.get_device_number ()); + print (" device file: " + device.get_device_file ()); + print (" device file symlinks: " + device.get_device_file_symlinks ()); + print (" foo: " + device.get_sysfs_attr_as_strv ("stat")); + var keys = device.get_property_keys (); + for (var n = 0; n < keys.length; n++) { + print (" " + keys[n] + "=" + device.get_property (keys[n])); + } +} + +function on_uevent (client, action, device) { + print ("action " + action + " on device " + device.get_sysfs_path()); + print_device (device); + print (""); +} + +var client = new GUdev.Client ({subsystems: ["block", "usb/usb_interface"]}); +client.signal.connect ("uevent", on_uevent); + +var block_devices = client.query_by_subsystem ("block"); +for (var n = 0; n < block_devices.length; n++) { + print ("block device: " + block_devices[n].get_device_file ()); +} + +var d; + +d = client.query_by_device_number (GUdev.DeviceType.BLOCK, 0x0810); +if (d == null) { + print ("query_by_device_number 0x810 -> null"); +} else { + print ("query_by_device_number 0x810 -> " + d.get_device_file ()); + dd = d.get_parent_with_subsystem ("usb", null); + print_device (dd); + print ("--------------------------------------------------------------------------"); + while (d != null) { + print_device (d); + print (""); + d = d.get_parent (); + } +} + +d = client.query_by_sysfs_path ("/sys/block/sda/sda1"); +print ("query_by_sysfs_path (\"/sys/block/sda1\") -> " + d.get_device_file ()); + +d = client.query_by_subsystem_and_name ("block", "sda2"); +print ("query_by_subsystem_and_name (\"block\", \"sda2\") -> " + d.get_device_file ()); + +d = client.query_by_device_file ("/dev/sda"); +print ("query_by_device_file (\"/dev/sda\") -> " + d.get_device_file ()); + +d = client.query_by_device_file ("/dev/block/8:0"); +print ("query_by_device_file (\"/dev/block/8:0\") -> " + d.get_device_file ()); + +var mainloop = GLib.main_loop_new (); +GLib.main_loop_run (mainloop); -- 2.7.4