libudev-device.c revision 4189708ad0cde8e211e38d27de943579772f8869
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers/***
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers This file is part of systemd.
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers Copyright 2015 Tom Gundersen <teg@jklm.no>
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers systemd is free software; you can redistribute it and/or modify it
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers under the terms of the GNU Lesser General Public License as published by
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers the Free Software Foundation; either version 2.1 of the License, or
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers (at your option) any later version.
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers systemd is distributed in the hope that it will be useful, but
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers WITHOUT ANY WARRANTY; without even the implied warranty of
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers Lesser General Public License for more details.
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers You should have received a copy of the GNU Lesser General Public License
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers along with systemd; If not, see <http://www.gnu.org/licenses/>.
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers***/
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sievers#include <stdio.h>
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers#include <stdlib.h>
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers#include <stddef.h>
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers#include <unistd.h>
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers#include <stdbool.h>
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers#include <errno.h>
25da63b9dac8f166ebf390ca92d1de18fbfc9d11Kay Sievers#include <string.h>
25da63b9dac8f166ebf390ca92d1de18fbfc9d11Kay Sievers#include <dirent.h>
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sievers#include <fcntl.h>
a8eaaee72a2f06e0fb64fb71de3b71ecba31dafbJan Engelhardt#include <ctype.h>
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner#include <net/if.h>
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers#include <sys/stat.h>
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers#include <sys/ioctl.h>
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers#include <sys/socket.h>
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sievers#include <linux/sockios.h>
d4b687c96adf207f0878aebf3ce3371f6160687fKay Sievers
d4b687c96adf207f0878aebf3ce3371f6160687fKay Sievers#include "sd-device.h"
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen#include "device-util.h"
3058e017fced6d5c8712e10c8c1477421bc1e960Thadeu Lima de Souza Cascardo#include "device-private.h"
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers
3058e017fced6d5c8712e10c8c1477421bc1e960Thadeu Lima de Souza Cascardo#include "libudev.h"
214daa72cb0c72ea78d1eccd5ffe630a1e04b2f7Sean McGovern#include "libudev-private.h"
214daa72cb0c72ea78d1eccd5ffe630a1e04b2f7Sean McGovern#include "libudev-device-internal.h"
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers/**
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sievers * SECTION:libudev-device
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers * @short_description: kernel sys devices
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers *
214daa72cb0c72ea78d1eccd5ffe630a1e04b2f7Sean McGovern * Representation of kernel sys devices. Devices are uniquely identified
214daa72cb0c72ea78d1eccd5ffe630a1e04b2f7Sean McGovern * by their syspath, every device has exactly one path in the kernel sys
0d6ce9236f61cb991d7e8f2359d818e41ead0cf5Kay Sievers * filesystem. Devices usually belong to a kernel subsystem, and have
0d6ce9236f61cb991d7e8f2359d818e41ead0cf5Kay Sievers * a unique name inside that subsystem.
0d6ce9236f61cb991d7e8f2359d818e41ead0cf5Kay Sievers */
0d6ce9236f61cb991d7e8f2359d818e41ead0cf5Kay Sievers
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sievers/**
a8eaaee72a2f06e0fb64fb71de3b71ecba31dafbJan Engelhardt * udev_device_get_seqnum:
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * @udev_device: udev device
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers *
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers * This is only valid if the device was received through a monitor. Devices read from
a8eaaee72a2f06e0fb64fb71de3b71ecba31dafbJan Engelhardt * sys do not have a sequence number.
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers *
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers * Returns: the kernel event sequence number, or 0 if there is no sequence number available.
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers **/
de892aea1c486b59e04884268b612081d1660514Kay Sievers_public_ unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device)
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers{
a8eaaee72a2f06e0fb64fb71de3b71ecba31dafbJan Engelhardt const char *seqnum;
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers unsigned long long ret;
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers int r;
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers assert_return_errno(udev_device, 0, EINVAL);
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers r = sd_device_get_property_value(udev_device->device, "SEQNUM", &seqnum);
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers if (r == -ENOENT)
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers return 0;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers else if (r < 0) {
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers errno = -r;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers return 0;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers }
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers r = safe_atollu(seqnum, &ret);
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers if (r < 0) {
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers errno = -r;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers return 0;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers }
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers return ret;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers}
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers/**
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers * udev_device_get_devnum:
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering * @udev_device: udev device
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
19aa72f74e41045510b4af3f1415b419d42ff20bTom Gundersen * Get the device major/minor number.
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering *
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering * Returns: the dev_t number.
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering **/
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering_public_ dev_t udev_device_get_devnum(struct udev_device *udev_device)
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering{
de892aea1c486b59e04884268b612081d1660514Kay Sievers dev_t devnum;
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers int r;
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
a5c32cff1f56afe6f0c6c70d91a88a7a8238b2d7Harald Hoyer assert_return_errno(udev_device, makedev(0, 0), EINVAL);
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering r = sd_device_get_devnum(udev_device->device, &devnum);
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers if (r < 0) {
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers errno = -r;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers return makedev(0, 0);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers }
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers return devnum;
e3d563346c4237af23335cc6904e0662efdf62adTom Gundersen}
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers/**
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * udev_device_get_driver:
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * @udev_device: udev device
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * Get the kernel driver name.
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * Returns: the driver name string, or #NULL if there is no driver attached.
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers **/
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers_public_ const char *udev_device_get_driver(struct udev_device *udev_device)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers{
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers const char *driver;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers int r;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers assert_return_errno(udev_device, NULL, EINVAL);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers r = sd_device_get_driver(udev_device->device, &driver);
d4b687c96adf207f0878aebf3ce3371f6160687fKay Sievers if (r < 0) {
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers errno = -r;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers return NULL;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers }
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen return driver;
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen}
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen/**
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * udev_device_get_devtype:
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers * @udev_device: udev device
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers *
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen * Retrieve the devtype string of the udev device.
01d183ddae6fb3445c4519cf1d90c6575f17292eKay Sievers *
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen * Returns: the devtype name of the udev device, or #NULL if it can not be determined
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen **/
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen_public_ const char *udev_device_get_devtype(struct udev_device *udev_device)
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers{
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen const char *devtype;
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen int r;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers assert_return_errno(udev_device, NULL, EINVAL);
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen
309b578d313b363974b99e48f0e378111cc1fa91Tom Gundersen r = sd_device_get_devtype(udev_device->device, &devtype);
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen if (r < 0) {
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen errno = -r;
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen return NULL;
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen }
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen return devtype;
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen}
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen/**
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen * udev_device_get_subsystem:
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen * @udev_device: udev device
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * Retrieve the subsystem string of the udev device. The string does not
c0a43734ca84a3c9170d4a2d7f4d329b9ef47abcTom Gundersen * contain any "/".
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers *
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * Returns: the subsystem name of the udev device, or #NULL if it can not be determined
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers **/
137661d87525a3c339afd2804e577532d58d3fbcKay Sievers_public_ const char *udev_device_get_subsystem(struct udev_device *udev_device)
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers{
0454229c100a2113ba82df55703436d6cb2c492bJason S. McMullan const char *subsystem;
1cb5d1f31909c731d93568eb4838cb86e033d783Lennart Poettering int r;
1cb5d1f31909c731d93568eb4838cb86e033d783Lennart Poettering
de892aea1c486b59e04884268b612081d1660514Kay Sievers assert_return_errno(udev_device, NULL, EINVAL);
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering
0454229c100a2113ba82df55703436d6cb2c492bJason S. McMullan r = sd_device_get_subsystem(udev_device->device, &subsystem);
0454229c100a2113ba82df55703436d6cb2c492bJason S. McMullan if (r < 0) {
1cb5d1f31909c731d93568eb4838cb86e033d783Lennart Poettering errno = -r;
0454229c100a2113ba82df55703436d6cb2c492bJason S. McMullan return NULL;
1cb5d1f31909c731d93568eb4838cb86e033d783Lennart Poettering } else if (!subsystem)
de892aea1c486b59e04884268b612081d1660514Kay Sievers errno = ENODATA;
de892aea1c486b59e04884268b612081d1660514Kay Sievers
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers return subsystem;
1cb5d1f31909c731d93568eb4838cb86e033d783Lennart Poettering}
1cb5d1f31909c731d93568eb4838cb86e033d783Lennart Poettering
1cb5d1f31909c731d93568eb4838cb86e033d783Lennart Poettering/**
de892aea1c486b59e04884268b612081d1660514Kay Sievers * udev_device_get_property_value:
de892aea1c486b59e04884268b612081d1660514Kay Sievers * @udev_device: udev device
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * @key: property name
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
3058e017fced6d5c8712e10c8c1477421bc1e960Thadeu Lima de Souza Cascardo * Get the value of a given property.
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers *
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers * Returns: the property string, or #NULL if there is no such property.
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers **/
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers_public_ const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key)
b5dd8148730db080b48b874c214f8f74ae787d6bZbigniew Jędrzejewski-Szmek{
b5dd8148730db080b48b874c214f8f74ae787d6bZbigniew Jędrzejewski-Szmek const char *value = NULL;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers int r;
b5dd8148730db080b48b874c214f8f74ae787d6bZbigniew Jędrzejewski-Szmek
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers assert_return_errno(udev_device && key, NULL, EINVAL);
b5dd8148730db080b48b874c214f8f74ae787d6bZbigniew Jędrzejewski-Szmek
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers r = sd_device_get_property_value(udev_device->device, key, &value);
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers if (r < 0) {
309b578d313b363974b99e48f0e378111cc1fa91Tom Gundersen errno = -r;
3058e017fced6d5c8712e10c8c1477421bc1e960Thadeu Lima de Souza Cascardo return NULL;
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers }
3058e017fced6d5c8712e10c8c1477421bc1e960Thadeu Lima de Souza Cascardo
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers return value;
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers}
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers
214daa72cb0c72ea78d1eccd5ffe630a1e04b2f7Sean McGovernstruct udev_device *udev_device_new(struct udev *udev) {
214daa72cb0c72ea78d1eccd5ffe630a1e04b2f7Sean McGovern struct udev_device *udev_device;
1fa2f38f0f011010bf57522b42fcc168856a7003Zbigniew Jędrzejewski-Szmek
1fa2f38f0f011010bf57522b42fcc168856a7003Zbigniew Jędrzejewski-Szmek assert_return_errno(udev, NULL, EINVAL);
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers
1fa2f38f0f011010bf57522b42fcc168856a7003Zbigniew Jędrzejewski-Szmek udev_device = new0(struct udev_device, 1);
3058e017fced6d5c8712e10c8c1477421bc1e960Thadeu Lima de Souza Cascardo if (!udev_device) {
1fa2f38f0f011010bf57522b42fcc168856a7003Zbigniew Jędrzejewski-Szmek errno = ENOMEM;
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers return NULL;
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers }
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers udev_device->refcount = 1;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers udev_device->udev = udev;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers udev_list_init(udev, &udev_device->properties, true);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers udev_list_init(udev, &udev_device->tags, true);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers udev_list_init(udev, &udev_device->sysattrs, true);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers udev_list_init(udev, &udev_device->devlinks, true);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers return udev_device;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers}
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers/**
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * udev_device_new_from_syspath:
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * @udev: udev library context
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * @syspath: sys device path including sys directory
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers *
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * Create new udev device, and fill in information from the sys
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * device and the udev database entry. The syspath is the absolute
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * path to the device, including the sys mount point.
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers *
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * The initial refcount is 1, and needs to be decremented to
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * release the resources of the udev device.
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers *
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * Returns: a new udev device, or #NULL, if it does not exist
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers **/
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers_public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) {
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers struct udev_device *udev_device;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers int r;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers udev_device = udev_device_new(udev);
641906e9366891e0ad3e6e38b7396a427678c4cfThomas Hindoe Paaboel Andersen if (!udev_device)
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers return NULL;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers r = sd_device_new_from_syspath(&udev_device->device, syspath);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers if (r < 0) {
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers errno = -r;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers udev_device_unref(udev_device);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers return NULL;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers }
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers return udev_device;
214daa72cb0c72ea78d1eccd5ffe630a1e04b2f7Sean McGovern}
214daa72cb0c72ea78d1eccd5ffe630a1e04b2f7Sean McGovern
214daa72cb0c72ea78d1eccd5ffe630a1e04b2f7Sean McGovern/**
214daa72cb0c72ea78d1eccd5ffe630a1e04b2f7Sean McGovern * udev_device_new_from_devnum:
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers * @udev: udev library context
d5a89d7dc17a5ba5cf4fc71f82963c5c94a31c3dKay Sievers * @type: char or block device
3058e017fced6d5c8712e10c8c1477421bc1e960Thadeu Lima de Souza Cascardo * @devnum: device major/minor number
3058e017fced6d5c8712e10c8c1477421bc1e960Thadeu Lima de Souza Cascardo *
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers * Create new udev device, and fill in information from the sys
16f948cb208f1db9a1665f07ac9b22e416dc19d4Tom Gundersen * device and the udev database entry. The device is looked-up
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * by its major/minor number and type. Character and block device
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * numbers are not unique across the two types.
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers *
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * The initial refcount is 1, and needs to be decremented to
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * release the resources of the udev device.
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * Returns: a new udev device, or #NULL, if it does not exist
5b8180d3f6598a1b2f296645690de41d726fd5abKay Sievers **/
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers_public_ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum)
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen{
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen struct udev_device *udev_device;
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen int r;
5b8180d3f6598a1b2f296645690de41d726fd5abKay Sievers
54683f0f9b97a8f88aaf4fbb45b4d729057b101cTom Gundersen udev_device = udev_device_new(udev);
54683f0f9b97a8f88aaf4fbb45b4d729057b101cTom Gundersen if (!udev_device)
54683f0f9b97a8f88aaf4fbb45b4d729057b101cTom Gundersen return NULL;
54683f0f9b97a8f88aaf4fbb45b4d729057b101cTom Gundersen
54683f0f9b97a8f88aaf4fbb45b4d729057b101cTom Gundersen r = sd_device_new_from_devnum(&udev_device->device, type, devnum);
54683f0f9b97a8f88aaf4fbb45b4d729057b101cTom Gundersen if (r < 0) {
54683f0f9b97a8f88aaf4fbb45b4d729057b101cTom Gundersen errno = -r;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers udev_device_unref(udev_device);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers return NULL;
54683f0f9b97a8f88aaf4fbb45b4d729057b101cTom Gundersen }
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
bb26309dd042c79de907f103d83f398b9436cde0Rob Clark return udev_device;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers}
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers/**
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * udev_device_new_from_device_id:
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * @udev: udev library context
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * @id: text string identifying a kernel device
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * Create new udev device, and fill in information from the sys
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * device and the udev database entry. The device is looked-up
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * by a special string:
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * b8:2 - block device major:minor
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * c128:1 - char device major:minor
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * n3 - network device ifindex
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers * +sound:card29 - kernel driver core subsystem:device name
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * The initial refcount is 1, and needs to be decremented to
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * release the resources of the udev device.
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * Returns: a new udev device, or #NULL, if it does not exist
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers **/
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers_public_ struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id)
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen{
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen struct udev_device *udev_device;
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen int r;
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers udev_device = udev_device_new(udev);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers if (!udev_device)
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers return NULL;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers r = sd_device_new_from_device_id(&udev_device->device, id);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (r < 0) {
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers errno = -r;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers udev_device_unref(udev_device);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers return NULL;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers }
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers return udev_device;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers}
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers/**
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * udev_device_new_from_subsystem_sysname:
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * @udev: udev library context
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * @subsystem: the subsystem of the device
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * @sysname: the name of the device
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * Create new udev device, and fill in information from the sys device
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * and the udev database entry. The device is looked up by the subsystem
f7340ab269828d917cd1281e33e6dd4fdfee67b3Torstein Husebø * and name string of the device, like "mem" / "zero", or "block" / "sda".
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * The initial refcount is 1, and needs to be decremented to
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * release the resources of the udev device.
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
d5a89d7dc17a5ba5cf4fc71f82963c5c94a31c3dKay Sievers * Returns: a new udev device, or #NULL, if it does not exist
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers **/
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers_public_ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers{
d5a89d7dc17a5ba5cf4fc71f82963c5c94a31c3dKay Sievers struct udev_device *udev_device;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers int r;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers udev_device = udev_device_new(udev);
d5a89d7dc17a5ba5cf4fc71f82963c5c94a31c3dKay Sievers if (!udev_device)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers return NULL;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers r = sd_device_new_from_subsystem_sysname(&udev_device->device, subsystem, sysname);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (r < 0) {
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers errno = -r;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers udev_device_unref(udev_device);
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers return NULL;
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers }
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers return udev_device;
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers}
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen/**
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen * udev_device_new_from_environment
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers * @udev: udev library context
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers *
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers * Create new udev device, and fill in information from the
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers * current process environment. This only works reliable if
f4ddacbd4de0f159ec598f8ad690466a84787ec5Kay Sievers * the process is called from a udev rule. It is usually used
b5dd8148730db080b48b874c214f8f74ae787d6bZbigniew Jędrzejewski-Szmek * for tools executed from IMPORT= rules.
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers *
f4ddacbd4de0f159ec598f8ad690466a84787ec5Kay Sievers * The initial refcount is 1, and needs to be decremented to
f4ddacbd4de0f159ec598f8ad690466a84787ec5Kay Sievers * release the resources of the udev device.
b5dd8148730db080b48b874c214f8f74ae787d6bZbigniew Jędrzejewski-Szmek *
f4ddacbd4de0f159ec598f8ad690466a84787ec5Kay Sievers * Returns: a new udev device, or #NULL, if it does not exist
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers **/
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers_public_ struct udev_device *udev_device_new_from_environment(struct udev *udev)
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers{
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers struct udev_device *udev_device;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner int r;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner udev_device = udev_device_new(udev);
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner if (!udev_device)
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner return NULL;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen r = device_new_from_strv(&udev_device->device, environ);
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen if (r < 0) {
3b64e4d4f40baac56148c7d333d6a0053358ec7aTom Gundersen errno = -r;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner udev_device_unref(udev_device);
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner return NULL;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner }
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner return udev_device;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner}
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Bruecknerstatic struct udev_device *device_new_from_parent(struct udev_device *child)
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner{
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner struct udev_device *parent;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner int r;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner assert_return_errno(child, NULL, EINVAL);
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner parent = udev_device_new(child->udev);
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner if (!parent)
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner return NULL;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner r = sd_device_get_parent(child->device, &parent->device);
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner if (r < 0) {
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner errno = -r;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner udev_device_unref(parent);
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner return NULL;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner }
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner /* the parent is unref'ed with the child, so take a ref from libudev as well */
d4b687c96adf207f0878aebf3ce3371f6160687fKay Sievers sd_device_ref(parent->device);
d4b687c96adf207f0878aebf3ce3371f6160687fKay Sievers
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner return parent;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner}
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner/**
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * udev_device_get_parent:
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * @udev_device: the device to start searching from
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers *
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * Find the next parent device, and fill in information from the sys
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * device and the udev database entry.
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers *
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * Returned device is not referenced. It is attached to the child
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * device, and will be cleaned up when the child device is cleaned up.
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers *
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * It is not necessarily just the upper level directory, empty or not
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * recognized sys directories are ignored.
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers *
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * It can be called as many times as needed, without caring about
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * references.
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers *
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * Returns: a new udev device, or #NULL, if it no parent exist.
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers **/
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers_public_ struct udev_device *udev_device_get_parent(struct udev_device *udev_device)
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers{
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers assert_return_errno(udev_device, NULL, EINVAL);
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers if (!udev_device->parent_set) {
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers udev_device->parent_set = true;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers udev_device->parent = device_new_from_parent(udev_device);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers }
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers /* TODO: errno will differ here in case parent == NULL */
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers return udev_device->parent;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers}
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers/**
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * udev_device_get_parent_with_subsystem_devtype:
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * @udev_device: udev device to start searching from
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * @subsystem: the subsystem of the device
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * @devtype: the type (DEVTYPE) of the device
971e7fb62548f2c9c4e32684bb13409e6579dc6aKay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * Find the next parent device, with a matching subsystem and devtype
971e7fb62548f2c9c4e32684bb13409e6579dc6aKay Sievers * value, and fill in information from the sys device and the udev
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * database entry.
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * If devtype is #NULL, only subsystem is checked, and any devtype will
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * match.
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * Returned device is not referenced. It is attached to the child
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * device, and will be cleaned up when the child device is cleaned up.
a4bbef099209d4e3bccd913cd30da536f8971064Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * It can be called as many times as needed, without caring about
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers * references.
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers *
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers * Returns: a new udev device, or #NULL if no matching parent exists.
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers **/
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers_public_ struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype)
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers{
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers sd_device *parent;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers int r;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers assert_return_errno(udev_device, NULL, EINVAL);
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner /* this relies on the fact that finding the subdevice of a parent or the
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers parent of a subdevice commute */
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers /* first find the correct sd_device */
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers r = sd_device_get_parent_with_subsystem_devtype(udev_device->device, subsystem, devtype, &parent);
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner if (r < 0) {
19aa72f74e41045510b4af3f1415b419d42ff20bTom Gundersen errno = -r;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner return NULL;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner }
19aa72f74e41045510b4af3f1415b419d42ff20bTom Gundersen
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner /* then walk the chain of udev_device parents until the correspanding
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner one is found */
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner while ((udev_device = udev_device_get_parent(udev_device))) {
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers if (udev_device->device == parent)
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner return udev_device;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers }
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers errno = ENOENT;
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers return NULL;
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers}
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers/**
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers * udev_device_get_udev:
090be8653471e1abe3f1cdd32eaad0fbd65f85cdThomas Hindoe Paaboel Andersen * @udev_device: udev device
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers *
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers * Retrieve the udev library context the device was created with.
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers *
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * Returns: the udev library context
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers **/
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers_public_ struct udev *udev_device_get_udev(struct udev_device *udev_device)
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers{
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers assert_return_errno(udev_device, NULL, EINVAL);
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers return udev_device->udev;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers}
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers/**
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * udev_device_ref:
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * @udev_device: udev device
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * Take a reference of a udev device.
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * Returns: the passed udev device
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers **/
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers_public_ struct udev_device *udev_device_ref(struct udev_device *udev_device)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers{
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner if (udev_device)
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner udev_device->refcount++;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner return udev_device;
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner}
d4b687c96adf207f0878aebf3ce3371f6160687fKay Sievers
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner/**
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner * udev_device_unref:
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner * @udev_device: udev device
e0d4a0ac06afb856c9370c5c256f0f7bb7efdc8eHendrik Brueckner *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * Drop a reference of a udev device. If the refcount reaches zero,
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * the resources of the device will be released.
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * Returns: #NULL
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers **/
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers_public_ struct udev_device *udev_device_unref(struct udev_device *udev_device)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers{
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (udev_device && (-- udev_device->refcount) == 0) {
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers sd_device_unref(udev_device->device);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers udev_device_unref(udev_device->parent);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers udev_list_cleanup(&udev_device->properties);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers udev_list_cleanup(&udev_device->sysattrs);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers udev_list_cleanup(&udev_device->tags);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers udev_list_cleanup(&udev_device->devlinks);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers free(udev_device);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers }
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers return NULL;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers}
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers/**
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * udev_device_get_devpath:
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * @udev_device: udev device
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * Retrieve the kernel devpath value of the udev device. The path
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * does not contain the sys mount point, and starts with a '/'.
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * Returns: the devpath of the udev device
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers **/
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers_public_ const char *udev_device_get_devpath(struct udev_device *udev_device)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers{
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers const char *devpath;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers int r;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers assert_return_errno(udev_device, NULL, EINVAL);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers r = sd_device_get_devpath(udev_device->device, &devpath);
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers if (r < 0) {
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers errno = -r;
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers return NULL;
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers }
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers return devpath;
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers}
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers/**
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers * udev_device_get_syspath:
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers * @udev_device: udev device
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers *
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers * Retrieve the sys path of the udev device. The path is an
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers * absolute path and starts with the sys mount point.
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers *
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers * Returns: the sys path of the udev device
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers **/
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers_public_ const char *udev_device_get_syspath(struct udev_device *udev_device)
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers{
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers const char *syspath;
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers int r;
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers assert_return_errno(udev_device, NULL, EINVAL);
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
5ac0162c3af95efa08a07b84ff62ad32842922c7Lennart Poettering r = sd_device_get_syspath(udev_device->device, &syspath);
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers if (r < 0) {
errno = -r;
return NULL;
}
return syspath;
}
/**
* udev_device_get_sysname:
* @udev_device: udev device
*
* Get the kernel device name in /sys.
*
* Returns: the name string of the device device
**/
_public_ const char *udev_device_get_sysname(struct udev_device *udev_device)
{
const char *sysname;
int r;
assert_return_errno(udev_device, NULL, EINVAL);
r = sd_device_get_sysname(udev_device->device, &sysname);
if (r < 0) {
errno = -r;
return NULL;
}
return sysname;
}
/**
* udev_device_get_sysnum:
* @udev_device: udev device
*
* Get the instance number of the device.
*
* Returns: the trailing number string of the device name
**/
_public_ const char *udev_device_get_sysnum(struct udev_device *udev_device)
{
const char *sysnum;
int r;
assert_return_errno(udev_device, NULL, EINVAL);
r = sd_device_get_sysnum(udev_device->device, &sysnum);
if (r < 0) {
errno = -r;
return NULL;
}
return sysnum;
}
/**
* udev_device_get_devnode:
* @udev_device: udev device
*
* Retrieve the device node file name belonging to the udev device.
* The path is an absolute path, and starts with the device directory.
*
* Returns: the device node file name of the udev device, or #NULL if no device node exists
**/
_public_ const char *udev_device_get_devnode(struct udev_device *udev_device)
{
const char *devnode;
int r;
assert_return_errno(udev_device, NULL, EINVAL);
r = sd_device_get_devname(udev_device->device, &devnode);
if (r < 0) {
errno = -r;
return NULL;
}
return devnode;
}
/**
* udev_device_get_devlinks_list_entry:
* @udev_device: udev device
*
* Retrieve the list of device links pointing to the device file of
* the udev device. The next list entry can be retrieved with
* udev_list_entry_get_next(), which returns #NULL if no more entries exist.
* The devlink path can be retrieved from the list entry by
* udev_list_entry_get_name(). The path is an absolute path, and starts with
* the device directory.
*
* Returns: the first entry of the device node link list
**/
_public_ struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device)
{
assert_return_errno(udev_device, NULL, EINVAL);
if (device_get_devlinks_generation(udev_device->device) != udev_device->devlinks_generation ||
!udev_device->devlinks_read) {
const char *devlink;
udev_list_cleanup(&udev_device->devlinks);
FOREACH_DEVICE_DEVLINK(udev_device->device, devlink)
udev_list_entry_add(&udev_device->devlinks, devlink, NULL);
udev_device->devlinks_read = true;
udev_device->devlinks_generation = device_get_devlinks_generation(udev_device->device);
}
return udev_list_get_entry(&udev_device->devlinks);
}
/**
* udev_device_get_event_properties_entry:
* @udev_device: udev device
*
* Retrieve the list of key/value device properties of the udev
* device. The next list entry can be retrieved with udev_list_entry_get_next(),
* which returns #NULL if no more entries exist. The property name
* can be retrieved from the list entry by udev_list_entry_get_name(),
* the property value by udev_list_entry_get_value().
*
* Returns: the first entry of the property list
**/
_public_ struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device)
{
assert_return_errno(udev_device, NULL, EINVAL);
if (device_get_properties_generation(udev_device->device) != udev_device->properties_generation ||
!udev_device->properties_read) {
const char *key, *value;
udev_list_cleanup(&udev_device->properties);
FOREACH_DEVICE_PROPERTY(udev_device->device, key, value)
udev_list_entry_add(&udev_device->properties, key, value);
udev_device->properties_read = true;
udev_device->properties_generation = device_get_properties_generation(udev_device->device);
}
return udev_list_get_entry(&udev_device->properties);
}
/**
* udev_device_get_action:
* @udev_device: udev device
*
* This is only valid if the device was received through a monitor. Devices read from
* sys do not have an action string. Usual actions are: add, remove, change, online,
* offline.
*
* Returns: the kernel action value, or #NULL if there is no action value available.
**/
_public_ const char *udev_device_get_action(struct udev_device *udev_device) {
const char *action = NULL;
int r;
assert_return_errno(udev_device, NULL, EINVAL);
r = sd_device_get_property_value(udev_device->device, "ACTION", &action);
if (r < 0 && r != -ENOENT) {
errno = -r;
return NULL;
}
return action;
}
/**
* udev_device_get_usec_since_initialized:
* @udev_device: udev device
*
* Return the number of microseconds passed since udev set up the
* device for the first time.
*
* This is only implemented for devices with need to store properties
* in the udev database. All other devices return 0 here.
*
* Returns: the number of microseconds since the device was first seen.
**/
_public_ unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device)
{
usec_t ts;
int r;
assert_return(udev_device, -EINVAL);
r = sd_device_get_usec_since_initialized(udev_device->device, &ts);
if (r < 0) {
errno = EINVAL;
return 0;
}
return ts;
}
/**
* udev_device_get_sysattr_value:
* @udev_device: udev device
* @sysattr: attribute name
*
* The retrieved value is cached in the device. Repeated calls will return the same
* value and not open the attribute again.
*
* Returns: the content of a sys attribute file, or #NULL if there is no sys attribute value.
**/
_public_ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr)
{
const char *value;
int r;
assert_return_errno(udev_device, NULL, EINVAL);
r = sd_device_get_sysattr_value(udev_device->device, sysattr, &value);
if (r < 0) {
errno = -r;
return NULL;
}
return value;
}
/**
* udev_device_set_sysattr_value:
* @udev_device: udev device
* @sysattr: attribute name
* @value: new value to be set
*
* Update the contents of the sys attribute and the cached value of the device.
*
* Returns: Negative error code on failure or 0 on success.
**/
_public_ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value)
{
int r;
assert_return(udev_device, -EINVAL);
r = sd_device_set_sysattr_value(udev_device->device, sysattr, value);
if (r < 0)
return r;
return 0;
}
/**
* udev_device_get_sysattr_list_entry:
* @udev_device: udev device
*
* Retrieve the list of available sysattrs, with value being empty;
* This just return all available sysfs attributes for a particular
* device without reading their values.
*
* Returns: the first entry of the property list
**/
_public_ struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device)
{
assert_return_errno(udev_device, NULL, EINVAL);
if (!udev_device->sysattrs_read) {
const char *sysattr;
udev_list_cleanup(&udev_device->sysattrs);
FOREACH_DEVICE_SYSATTR(udev_device->device, sysattr)
udev_list_entry_add(&udev_device->properties, sysattr, NULL);
udev_device->sysattrs_read = true;
}
return udev_list_get_entry(&udev_device->sysattrs);
}
/**
* udev_device_get_is_initialized:
* @udev_device: udev device
*
* Check if udev has already handled the device and has set up
* device node permissions and context, or has renamed a network
* device.
*
* This is only implemented for devices with a device node
* or network interfaces. All other devices return 1 here.
*
* Returns: 1 if the device is set up. 0 otherwise.
**/
_public_ int udev_device_get_is_initialized(struct udev_device *udev_device)
{
int r, initialized;
assert_return(udev_device, -EINVAL);
r = sd_device_get_is_initialized(udev_device->device, &initialized);
if (r < 0) {
errno = -r;
return 0;
}
return initialized;
}
/**
* udev_device_get_tags_list_entry:
* @udev_device: udev device
*
* Retrieve the list of tags attached to the udev device. The next
* list entry can be retrieved with udev_list_entry_get_next(),
* which returns #NULL if no more entries exist. The tag string
* can be retrieved from the list entry by udev_list_entry_get_name().
*
* Returns: the first entry of the tag list
**/
_public_ struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device)
{
assert_return_errno(udev_device, NULL, EINVAL);
if (device_get_tags_generation(udev_device->device) != udev_device->tags_generation ||
!udev_device->tags_read) {
const char *tag;
udev_list_cleanup(&udev_device->tags);
FOREACH_DEVICE_TAG(udev_device->device, tag)
udev_list_entry_add(&udev_device->tags, tag, NULL);
udev_device->tags_read = true;
udev_device->tags_generation = device_get_tags_generation(udev_device->device);
}
return udev_list_get_entry(&udev_device->tags);
}
/**
* udev_device_has_tag:
* @udev_device: udev device
* @tag: tag name
*
* Check if a given device has a certain tag associated.
*
* Returns: 1 if the tag is found. 0 otherwise.
**/
_public_ int udev_device_has_tag(struct udev_device *udev_device, const char *tag)
{
assert_return(udev_device, 0);
return sd_device_has_tag(udev_device->device, tag);
}