diff --git a/.gitignore b/.gitignore
index a8db8d4..4fe48c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,20 @@
*~
+*.orig
+*.backup
*.pyc
*.o
*.so
*.so.*
*.swp
*.kate-swp
+*.patch
+*.diff
+
+build
+*.log
+*.notes
+*.petes
+*.tux
+*.mingus
+*.stuff
+.gitignore
diff --git a/buildconf.mk b/buildconf.mk
index 436bc6d..941c5f0 100644
--- a/buildconf.mk
+++ b/buildconf.mk
@@ -22,7 +22,7 @@ INCLUDEDIR ?= $(INCLUDE_PREFIX)/include
ETCDIR ?= $(PREFIX)/etc
ETCDIR_VDEV ?= $(ETCDIR)/vdev
SHAREDIR ?= $(PREFIX)/share
-PKGCONFIG ?= $(INCLUDE_PREFIX)/share/pkgconfig
+PKGCONFIG ?= $(INCLUDE_PREFIX)/share/pkgconfig
RUNDIR ?= $(PREFIX)/run
RUNDIR_VDEV ?= $(RUNDIR)/vdev
LOGDIR ?= $(PREFIX)/var/log
@@ -68,8 +68,12 @@ BUILD_HWDB := $(BUILD_LIBDIR)/vdev/hwdb
BUILD_HWDB_DIRS := $(BUILD_HWDB)
INSTALL_HWDB := $(DESTDIR)$(LIBDIR)/vdev/hwdb
-# compiler
-CFLAGS := -Wall -std=c99 -g -fPIC -fstack-protector -fstack-protector-all -pthread -Wno-unused-variable -Wno-unused-but-set-variable
+# compiler original settings
+#CFLAGS := -Wall -std=c99 -g -fPIC -fstack-protector -fstack-protector-all -pthread -Wno-unused-variable -Wno-unused-but-set-variable
+# compiler : headers also set some C standards though perhaps boiler plate ?
+# noiser settings for hair shirted types and deeper testing and analysis.
+CFLAGS := -g -fPIC -fstack-protector -fstack-protector-all -pthread\
+ -Wall -Wextra -std=c11 #-pedantic-errors
LDFLAGS :=
INC := -I. -I$(ROOT_DIR) -I$(BUILD_INCLUDEDIR)
DEFS := -D_THREAD_SAFE -D__STDC_FORMAT_MACROS -D_VDEV_OS_$(OS) -D_XOPEN_SOURCE=700
diff --git a/debian.mk b/debian.mk
new file mode 100644
index 0000000..d1a0436
--- /dev/null
+++ b/debian.mk
@@ -0,0 +1,31 @@
+
+LIC=gpl3
+#EMAIL=ralph.ronnquist@gmail.com
+EMAIL=pete.gossner@gmail.com
+VERSION=1.0alpha-petes
+ARCH=$(shell uname -r)
+HOMEPAGE="github.com/PeteGozz/vdev"
+
+DEBS += vdevd_$(VERSION)_$(ARCH).deb
+DEBS += libudev1-compat_$(VERSION)_$(ARCH).deb
+DEBS += vdev_$(VERSION)_$(ARCH).deb
+
+all: $(DEBS)
+
+vdevd_$(VERSION)_$(ARCH).deb:
+ $(MAKE) -C vdevd -f ../debian.mk deb PACKAGE=vdevd
+
+libudev1-compat_$(VERSION)_$(ARCH).deb:
+ $(MAKE) -C libudev-compat -f ../debian.mk deb PACKAGE=libudev1-compat
+
+vdev_$(VERSION)_$(ARCH).deb:
+ $(MAKE) -C example -f ../debian.mk deb PACKAGE=vdev
+
+vdevfs_$(VERSION)_$(ARCH).deb:
+ $(MAKE) -C fs -f ../debian.mk deb PACKAGE=vdevfs
+
+.PHONY: deb
+deb:
+ dh_make -a -s -n -y -e "$(EMAIL)" -p $(PACKAGE)_$(VERSION) -c $(LIC)
+ PREFIX= INCLUDE_PREFIX=/usr dpkg-buildpackage -b -uc
+
diff --git a/example/initramfs/hooks/vdev b/example/initramfs/hooks/vdev
index 61b3fa1..664c345 100755
--- a/example/initramfs/hooks/vdev
+++ b/example/initramfs/hooks/vdev
@@ -1,4 +1,6 @@
#!/bin/sh -e
+# posix shell or maybe dash only
+#debug# set -x
PREREQS=""
@@ -11,29 +13,41 @@ case "$1" in
;;
esac
-. /usr/share/initramfs-tools/hook-functions
+. /usr/share/initramfs-tools/hook-functions
+
+# Needed for keyboard or most mice
+# see: /dev/input/*
+
+force_load evdev
+if [ $? != 0 ]; then
+ echo "WARNING:[Xorg] eventfs _may_ not present X with keyboard or mouse devices"
+ sleep 2;
+fi
# helper programs
-mkdir -p $DESTDIR/lib/vdev
-for prog in /lib/vdev/*; do
+mkdir -vp $DESTDIR/lib/vdev
+
+for prog in /lib/vdev/*; do
# shell script or library?
if [ -z "${prog#*.sh}" ]; then
-
cp -a $prog $DESTDIR/lib/vdev/
else
-
# binary?
if [ -f $prog -a -x $prog ]; then
-
copy_exec $prog /lib/vdev
fi
fi
done
+# libudev-compat
+if [ -f /lib/libudev.so.1 ] ; then
+ copy_exec /lib/libudev.so.1
+fi
+
# config
-mkdir -p $DESTDIR/etc/vdev
-cp -a /etc/vdev/* $DESTDIR/etc/vdev/
+mkdir -pv $DESTDIR/etc/vdev
+cp -avf /etc/vdev/* $DESTDIR/etc/vdev/
# the daemon itself
copy_exec /sbin/vdevd
@@ -42,39 +56,51 @@ copy_exec /sbin/vdevd
if [ -f /sbin/blkid ]; then
copy_exec /sbin/blkid
else
- echo "WARN: could not find blkid in /sbin/blkid. /dev/disk symlinks will not be created."
+ echo "WARN: could not find blkid in /sbin/blkid."
+ echo " /dev/disk symlinks will not be created."
fi
# lvm tools (needed by vdevd's helpers)
if [ -f /sbin/lvs ]; then
copy_exec /sbin/lvs
else
- echo "WARN: could not find lvs in /sbin/lvs. Logical volume symlinks will not be created."
+ echo "WARN: could not find lvs in /sbin/lvs."
+ echo " Logical volume symlinks will not be created."
fi
if [ -f /sbin/pvs ]; then
copy_exec /sbin/pvs
else
- echo "WARN: could not find pvs in /sbin/pvs. Physical volume symlinks will not be created."
+ echo "WARN: could not find pvs in /sbin/pvs."
+ echo " Physical volume symlinks will not be created."
fi
if [ -f /sbin/lvm ]; then
copy_exec /sbin/lvm
else
- echo "WARN: could not find lvm in /sbin/lvm. Logical volume symlinks will not be created."
+ echo "WARN: could not find lvm in /sbin/lvm."
+ echo " Logical volume symlinks will not be created."
fi
-
+#
# network tools (needed by vdevd's helpers)
+# busy box may provide alternatives
+# for human uses. (?)
+#
+if ! [ -f /sbin/ip ] && ! [ -f /bin/ip ]; then
+ echo "WARN: could not find iproute2 in /bin/ip or /sbin/ip."
+ echo " Networking may not be available"
+fi
+
if [ -f /bin/ip ]; then
copy_exec /bin/ip
fi
if [ -f /sbin/ip ]; then
copy_exec /sbin/ip
-fi
-
-if ! [ -f /sbin/ip ] && ! [ -f /bin/ip ]; then
- echo "WARN: could not find iproute2 in /bin/ip or /sbin/ip. Network interfaces will not be configured."
+else [ -f /sbin/ifconfig ]; then
+# try the classical tool
+ copy_exec /sbin/ifconfig
+ echo "NOTE: installing /sbin/ifconfig as networking tool"
fi
# SELinux tools
@@ -83,23 +109,31 @@ if [ -f /sbin/restorecon ]; then
fi
# device tools
+# prefer most current
if [ -f /sbin/MAKEDEV ]; then
- copy_exec /sbin/MAKEDEV || true
+ copy_exec /sbin/MAKEDEV
+else
+ echo "WARNING: No MAKEDEV found to install"
+ echo "vdev --once may be your best alternative"
fi
# device mapper tools
if [ -f /sbin/dmsetup ]; then
copy_exec /sbin/dmsetup
else
- echo "WARN: could not find dmsetup in /sbin/dmsetup. Device mapper symlinks will not be created."
+ echo "WARN: could not find dmsetup in /sbin/dmsetup."
+ echo " Device mapper symlinks will not be created."
fi
# hardware database
if [ -f /lib/vdev/hwdb/hwdb.squashfs ]; then
+ copy_exec /sbin/losetup
mkdir -p $DESTDIR/lib/vdev/hwdb
cp -a /lib/vdev/hwdb/hwdb.squashfs $DESTDIR/lib/vdev/hwdb
else
- echo "WARN: could not find hardware database in /lib/vdev/hwdb. Some hardware metadata may not be generated."
+ echo "WARN: could not find hardware database in /lib/vdev/hwdb."
+ echo "Some hardware metadata may not be generated."
+ sleep 2
fi
# GNU tools (not the busybox equivalents)
@@ -112,19 +146,42 @@ copy_exec /bin/egrep
copy_exec /bin/kmod
# users and groups databases
-cp -a /etc/passwd $DESTDIR/etc/passwd
-cp -a /etc/group $DESTDIR/etc/group
-
-# extra libc goodies
-copy_exec /lib/x86_64-linux-gnu/libc.so.6
-copy_exec /lib/x86_64-linux-gnu/libnss_compat.so.2
-copy_exec /lib/x86_64-linux-gnu/libnsl.so.1
-copy_exec /lib/x86_64-linux-gnu/libnss_nis.so.2
-copy_exec /lib/x86_64-linux-gnu/libnss_files.so.2
+cp -va /etc/passwd $DESTDIR/etc/passwd
+cp -va /etc/group $DESTDIR/etc/group
+
+#
+# extra libc goodies
+# Falling to i386 if i686 is the uname machine type
+# and the i686 libc version is not found.
+#
+#
+if [ -d /lib/$(arch)-linux-gnu ]; then
+ LIBC=/lib/$(arch)-linux-gnu
+elif [ -d /lib/i386-linux-gnu ]; then
+ LIBC=/lib/i386-linux-gnu
+else
+ # make noise and trigger -e if set
+ echo "Unable to find libc shared object files for $(arch)"
+ sleep 1
+ echo "Please check dependancies or package install order"
+ sleep 2
+ /bin/false
+fi
-# since vdevd is multi-threaded, libpthread will dynamically load libgcc_s
+copy_exec $LIBC/libc.so.6 || echo "$LIBC/libc.so.6 (still) not found"
+copy_exec $LIBC/libnss_compat.so.2
+copy_exec $LIBC/libnsl.so.1
+copy_exec $LIBC/libnss_nis.so.2
+copy_exec $LIBC/libnss_files.so.2
+#
+# since vdevd is multi-threaded,
+# libpthread will need to dynamically load libgcc_s
# (and copy_exec won't detect this)
-copy_exec /lib/`gcc -print-multiarch`/libgcc_s.so.1
+#
+copy_exec $LIBC/libgcc_s.so.1 || echo "libpthread needs libgcc_s"
# until we're confident that the scripts work with busybox's sh, use dash
copy_exec /bin/dash
+
+# be polite
+exit
diff --git a/example/sysv-initscript.sh b/example/sysv-initscript.sh
index 18ffee0..7aaff3b 100755
--- a/example/sysv-initscript.sh
+++ b/example/sysv-initscript.sh
@@ -3,8 +3,8 @@
# Provides: udev
# Required-Start: mountkernfs
# Required-Stop:
-# Default-Start: S
-# Default-Stop:
+# Default-Start: S
+# Default-Stop:
# Short-Description: Start vdevd, populate /dev and load drivers.
### END INIT INFO
@@ -33,7 +33,7 @@ source_ini_file() {
FILE_PATH=$1
NAMESPACE=$2
-
+ # convert [ini style header] to ""
/bin/cat $FILE_PATH | /bin/sed "s/.*\[.*\].*//g" | \
while read line; do
@@ -41,8 +41,7 @@ source_ini_file() {
VALUE=$(echo $line | /bin/sed "s/^.*=\(.*\)$/\1/g");
if [ -n "$KEY" ]; then
-
- echo "${NAMESPACE}${KEY}=${VALUE}"
+ echo "${NAMESPACE}${KEY}=${VALUE}"
fi
done
}
@@ -79,7 +78,7 @@ eval $(source_ini_file $VDEV_CONFIG "vdev_config_")
# config sanity check
if [ -z "$vdev_config_pidfile" ]; then
log_warning_msg "No PID file defined in $VDEV_CONFIG. Please set the pidfile= directive."
- log_warning_msg "You will be unable stop or restart vdevd with this script."
+ log_warning_msg "You will be unable control vdevd with this init script."
fi
@@ -119,12 +118,13 @@ vdevd_start() {
# start vdev
if "$VDEV_BIN" -c "$VDEV_CONFIG" $@ "$VDEV_MOUNTPOINT"; then
- log_end_msg $?
-
+ log_end_msg $?
+
else
- log_warning_msg $?
- log_warning_msg "Waiting 15 seconds and trying to continue anyway"
- sleep 15
+ log_warning_msg $?
+ log_warning_msg "Errors when starting \"$VDEV_BIN\" -c \"$VDEV_CONFIG\" "
+ log_warning_msg "Waiting 15 seconds and trying to continue anyway"
+ sleep 15
fi
return 0
diff --git a/example/vdevd.conf b/example/vdevd.conf
index 4f13930..3507bf9 100644
--- a/example/vdevd.conf
+++ b/example/vdevd.conf
@@ -1,4 +1,5 @@
[vdev-config]
+
firmware=/lib/firmware
acls=./build/etc/vdev/acls
actions=./build/etc/vdev/actions
diff --git a/fs/acl.c b/fs/acl.c
index 34f6022..819d260 100644
--- a/fs/acl.c
+++ b/fs/acl.c
@@ -21,84 +21,94 @@
#include "acl.h"
-#define INI_MAX_LINE 4096
+#define INI_MAX_LINE 4096
#define INI_STOP_ON_FIRST_ERROR 1
#include "libvdev/ini.h"
#include "libvdev/match.h"
#include "libvdev/config.h"
-SGLIB_DEFINE_VECTOR_PROTOTYPES( vdev_acl );
-SGLIB_DEFINE_VECTOR_FUNCTIONS( vdev_acl );
+SGLIB_DEFINE_VECTOR_PROTOTYPES (vdev_acl);
+SGLIB_DEFINE_VECTOR_FUNCTIONS (vdev_acl);
// parse the ACL mode
-static int vdev_acl_parse_mode( mode_t* mode, char const* mode_str ) {
-
- char* tmp = NULL;
-
- *mode = ((mode_t)strtol( mode_str, &tmp, 8 )) & 0777;
-
- if( *tmp != '\0' ) {
+static int
+vdev_acl_parse_mode (mode_t * mode, char const *mode_str)
+{
+
+ char *tmp = NULL;
+
+ *mode = ((mode_t) strtol (mode_str, &tmp, 8)) & 0777;
+
+ if (*tmp != '\0')
+ {
return -EINVAL;
- }
- else {
+ }
+ else
+ {
return 0;
- }
+ }
}
-
// get a passwd struct for a user.
// on success, fill in pwd and *pwd_buf (the caller must free *pwd_buf, but not pwd).
// return 0 on success
// return -EINVAL if any argument is NULL
// return -ENOMEM on OOM
// return -ENOENT if the username cnanot be loaded
-int vdev_get_passwd( char const* username, struct passwd* pwd, char** pwd_buf ) {
-
- struct passwd* result = NULL;
- char* buf = NULL;
- int buf_len = 0;
- int rc = 0;
-
- if( pwd == NULL || username == NULL || pwd_buf == NULL ) {
+int
+vdev_get_passwd (char const *username, struct passwd *pwd, char **pwd_buf)
+{
+
+ struct passwd *result = NULL;
+ char *buf = NULL;
+ int buf_len = 0;
+ int rc = 0;
+
+ if (pwd == NULL || username == NULL || pwd_buf == NULL)
+ {
return -EINVAL;
- }
-
- memset( pwd, 0, sizeof(struct passwd) );
-
- buf_len = sysconf( _SC_GETPW_R_SIZE_MAX );
- if( buf_len <= 0 ) {
+ }
+
+ memset (pwd, 0, sizeof (struct passwd));
+
+ buf_len = sysconf (_SC_GETPW_R_SIZE_MAX);
+ if (buf_len <= 0)
+ {
buf_len = 65536;
- }
-
- buf = VDEV_CALLOC( char, buf_len );
- if( buf == NULL ) {
+ }
+
+ buf = VDEV_CALLOC (char, buf_len);
+ if (buf == NULL)
+ {
return -ENOMEM;
- }
-
- rc = getpwnam_r( username, pwd, buf, buf_len, &result );
-
- if( result == NULL ) {
-
- if( rc == 0 ) {
- free( buf );
- return -ENOENT;
- }
- else {
- rc = -errno;
- free( buf );
-
- vdev_error("getpwnam_r(%s) errno = %d\n", username, rc);
- return rc;
- }
- }
-
- *pwd_buf = buf;
-
- // success!
- return rc;
-}
+ }
+
+ rc = getpwnam_r (username, pwd, buf, buf_len, &result);
+
+ if (result == NULL)
+ {
+ if (rc == 0)
+ {
+ free (buf);
+ return -ENOENT;
+ }
+ else
+ {
+ rc = -errno;
+ free (buf);
+
+ vdev_error ("getpwnam_r(%s) errno = %d\n", username, rc);
+ return rc;
+ }
+ }
+
+ *pwd_buf = buf;
+
+ // success!
+ return rc;
+}
// get a group struct for a group.
// on success, fill in grp and *grp_buf (the caller must free *grp_buf, but not grp).
@@ -106,181 +116,203 @@ int vdev_get_passwd( char const* username, struct passwd* pwd, char** pwd_buf )
// return -ENOMEM on OOM
// return -EINVAL if any argument is NULL
// return -ENOENT if the group cannot be found
-int vdev_get_group( char const* groupname, struct group* grp, char** grp_buf ) {
-
- struct group* result = NULL;
- char* buf = NULL;
- int buf_len = 0;
- int rc = 0;
-
- if( grp == NULL || groupname == NULL || grp_buf == NULL ) {
+int
+vdev_get_group (char const *groupname, struct group *grp, char **grp_buf)
+{
+
+ struct group *result = NULL;
+ char *buf = NULL;
+ int buf_len = 0;
+ int rc = 0;
+
+ if (grp == NULL || groupname == NULL || grp_buf == NULL)
+ {
return -EINVAL;
- }
-
- memset( grp, 0, sizeof(struct group) );
-
- buf_len = sysconf( _SC_GETGR_R_SIZE_MAX );
- if( buf_len <= 0 ) {
+ }
+
+ memset (grp, 0, sizeof (struct group));
+
+ buf_len = sysconf (_SC_GETGR_R_SIZE_MAX);
+ if (buf_len <= 0)
+ {
buf_len = 65536;
- }
-
- buf = VDEV_CALLOC( char, buf_len );
- if( buf == NULL ) {
+ }
+
+ buf = VDEV_CALLOC (char, buf_len);
+ if (buf == NULL)
+ {
return -ENOMEM;
- }
-
- rc = getgrnam_r( groupname, grp, buf, buf_len, &result );
-
- if( result == NULL ) {
-
- if( rc == 0 ) {
- free( buf );
- return -ENOENT;
- }
- else {
- rc = -errno;
- free( buf );
-
- vdev_error("getgrnam_r(%s) errno = %d\n", groupname, rc);
- return rc;
- }
- }
-
- // success!
- return rc;
-}
+ }
+
+ rc = getgrnam_r (groupname, grp, buf, buf_len, &result);
+
+ if (result == NULL)
+ {
+ if (rc == 0)
+ {
+ free (buf);
+ return -ENOENT;
+ }
+ else
+ {
+ rc = -errno;
+ free (buf);
+
+ vdev_error ("getgrnam_r(%s) errno = %d\n", groupname, rc);
+ return rc;
+ }
+ }
+ // success!
+ return rc;
+}
// parse a username or uid from a string.
// translate a username into a uid, if needed
// return 0 and set *uid on success
// return negative if we failed to look up the corresponding user (see vdev_get_passwd)
// return negative on error
-int vdev_parse_uid( char const* uid_str, uid_t* uid ) {
-
- bool parsed = false;
- int rc = 0;
-
- if( uid_str == NULL || uid == NULL ) {
+int
+vdev_parse_uid (char const *uid_str, uid_t * uid)
+{
+
+ bool parsed = false;
+ int rc = 0;
+
+ if (uid_str == NULL || uid == NULL)
+ {
return -EINVAL;
- }
-
- *uid = (uid_t)vdev_parse_uint64( uid_str, &parsed );
-
- // not a number?
- if( !parsed ) {
-
+ }
+
+ *uid = (uid_t) vdev_parse_uint64 (uid_str, &parsed);
+
+ // not a number?
+ if (!parsed)
+ {
+
// probably a username
- char* pwd_buf = NULL;
+ char *pwd_buf = NULL;
struct passwd pwd;
-
+
// look up the uid...
- rc = vdev_get_passwd( uid_str, &pwd, &pwd_buf );
- if( rc != 0 ) {
-
- vdev_error("vdev_get_passwd(%s) rc = %d\n", uid_str, rc );
- return rc;
- }
-
+ rc = vdev_get_passwd (uid_str, &pwd, &pwd_buf);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_get_passwd(%s) rc = %d\n", uid_str, rc);
+ return rc;
+ }
+
*uid = pwd.pw_uid;
-
- free( pwd_buf );
- }
-
- return 0;
-}
+ free (pwd_buf);
+ }
+
+ return 0;
+}
// parse a group name or GID from a string
// translate a group name into a gid, if needed
// return 0 and set gid on success
// return negative if we failed to look up the corresponding group (see vdev_get_group)
// return negative on error
-int vdev_parse_gid( char const* gid_str, gid_t* gid ) {
-
- bool parsed = false;
- int rc = 0;
-
- if( gid_str == NULL || gid == NULL ) {
- return -EINVAL;
- }
-
- *gid = (gid_t)vdev_parse_uint64( gid_str, &parsed );
-
- // not a number?
- if( !parsed ) {
-
+int
+vdev_parse_gid (char const *gid_str, gid_t * gid)
+{
+
+ bool parsed = false;
+ int rc = 0;
+
+ if (gid_str == NULL || gid == NULL)
+ {
+ return -EINVAL;
+ }
+
+ *gid = (gid_t) vdev_parse_uint64 (gid_str, &parsed);
+
+ // not a number?
+ if (!parsed)
+ {
+
// probably a group name
- char* grp_buf = NULL;
+ char *grp_buf = NULL;
struct group grp;
-
+
// look up the gid...
- rc = vdev_get_group( gid_str, &grp, &grp_buf );
- if( rc != 0 ) {
-
- vdev_error("vdev_get_group(%s) rc = %d\n", gid_str, rc );
- return rc;
- }
-
+ rc = vdev_get_group (gid_str, &grp, &grp_buf);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_get_group(%s) rc = %d\n", gid_str, rc);
+ return rc;
+ }
+
*gid = grp.gr_gid;
-
- free( grp_buf );
- }
-
- return 0;
-}
+ free (grp_buf);
+ }
+
+ return 0;
+}
// verify that a UID is valid
// return 0 on success
// return -ENOMEM on OOM
// return -ENOENT on failure to look up the user
// return negative on error
-int vdev_validate_uid( uid_t uid ) {
-
- struct passwd* result = NULL;
- char* buf = NULL;
- int buf_len = 0;
- int rc = 0;
- struct passwd pwd;
-
- memset( &pwd, 0, sizeof(struct passwd) );
-
- buf_len = sysconf( _SC_GETPW_R_SIZE_MAX );
- if( buf_len <= 0 ) {
+int
+vdev_validate_uid (uid_t uid)
+{
+
+ struct passwd *result = NULL;
+ char *buf = NULL;
+ int buf_len = 0;
+ int rc = 0;
+ struct passwd pwd;
+
+ memset (&pwd, 0, sizeof (struct passwd));
+
+ buf_len = sysconf (_SC_GETPW_R_SIZE_MAX);
+ if (buf_len <= 0)
+ {
buf_len = 65536;
- }
-
- buf = VDEV_CALLOC( char, buf_len );
- if( buf == NULL ) {
+ }
+
+ buf = VDEV_CALLOC (char, buf_len);
+ if (buf == NULL)
+ {
return -ENOMEM;
- }
-
- rc = getpwuid_r( uid, &pwd, buf, buf_len, &result );
-
- if( result == NULL ) {
-
- if( rc == 0 ) {
- free( buf );
- return -ENOENT;
- }
- else {
- rc = -errno;
- free( buf );
-
- vdev_error("getpwuid_r(%d) errno = %d\n", uid, rc);
- return rc;
- }
- }
-
- if( uid != pwd.pw_uid ) {
+ }
+
+ rc = getpwuid_r (uid, &pwd, buf, buf_len, &result);
+
+ if (result == NULL)
+ {
+
+ if (rc == 0)
+ {
+ free (buf);
+ return -ENOENT;
+ }
+ else
+ {
+ rc = -errno;
+ free (buf);
+
+ vdev_error ("getpwuid_r(%d) errno = %d\n", uid, rc);
+ return rc;
+ }
+ }
+
+ if (uid != pwd.pw_uid)
+ {
// should *never* happen
rc = -EINVAL;
- }
-
- free( buf );
-
- return rc;
+ }
+
+ free (buf);
+
+ return rc;
}
// verify that a GID is valid
@@ -288,769 +320,896 @@ int vdev_validate_uid( uid_t uid ) {
// return -ENOMEM on OOM
// return -ENOENT if we couldn't find the corresponding group
// return negative on other error
-int vdev_validate_gid( gid_t gid ) {
-
- struct group* result = NULL;
- struct group grp;
- char* buf = NULL;
- int buf_len = 0;
- int rc = 0;
-
- memset( &grp, 0, sizeof(struct group) );
-
- buf_len = sysconf( _SC_GETGR_R_SIZE_MAX );
- if( buf_len <= 0 ) {
+int
+vdev_validate_gid (gid_t gid)
+{
+
+ struct group *result = NULL;
+ struct group grp;
+ char *buf = NULL;
+ int buf_len = 0;
+ int rc = 0;
+
+ memset (&grp, 0, sizeof (struct group));
+
+ buf_len = sysconf (_SC_GETGR_R_SIZE_MAX);
+ if (buf_len <= 0)
+ {
buf_len = 65536;
- }
-
- buf = VDEV_CALLOC( char, buf_len );
- if( buf == NULL ) {
+ }
+
+ buf = VDEV_CALLOC (char, buf_len);
+ if (buf == NULL)
+ {
return -ENOMEM;
- }
-
- rc = getgrgid_r( gid, &grp, buf, buf_len, &result );
-
- if( result == NULL ) {
-
- if( rc == 0 ) {
- free( buf );
- return -ENOENT;
- }
- else {
- rc = -errno;
- free( buf );
-
- vdev_error("getgrgid_r(%d) errno = %d\n", gid, rc);
- return rc;
- }
- }
-
- if( gid != grp.gr_gid ) {
+ }
+
+ rc = getgrgid_r (gid, &grp, buf, buf_len, &result);
+
+ if (result == NULL)
+ {
+
+ if (rc == 0)
+ {
+ free (buf);
+ return -ENOENT;
+ }
+ else
+ {
+ rc = -errno;
+ free (buf);
+
+ vdev_error ("getgrgid_r(%d) errno = %d\n", gid, rc);
+ return rc;
+ }
+ }
+
+ if (gid != grp.gr_gid)
+ {
rc = -EINVAL;
- }
-
- free( buf );
-
- return rc;
-}
+ }
+ free (buf);
+ return rc;
+}
// callback from inih to parse an acl
// return 1 on success
// return 0 on failure
-static int vdev_acl_ini_parser( void* userdata, char const* section, char const* name, char const* value ) {
-
- struct vdev_acl* acl = (struct vdev_acl*)userdata;
-
- // verify this is an acl section
- if( strcmp(section, VDEV_ACL_NAME) != 0 ) {
-
- fprintf(stderr, "Invalid section '%s'\n", section);
+static int
+vdev_acl_ini_parser (void *userdata, char const *section,
+ char const *name, char const *value)
+{
+
+ struct vdev_acl *acl = (struct vdev_acl *) userdata;
+
+ // verify this is an acl section
+ if (strcmp (section, VDEV_ACL_NAME) != 0)
+ {
+
+ fprintf (stderr, "Invalid section '%s'\n", section);
return 0;
- }
-
- if( strcmp(name, VDEV_ACL_NAME_UID ) == 0 ) {
-
+ }
+
+ if (strcmp (name, VDEV_ACL_NAME_UID) == 0)
+ {
+
// parse user or UID
uid_t uid = 0;
- int rc = vdev_parse_uid( value, &uid );
-
- if( rc != 0 ) {
- vdev_error("vdev_parse_uid(%s) rc = %d\n", value, rc );
-
- fprintf(stderr, "Invalid user/UID '%s'\n", value );
- return 0;
- }
-
+ int rc = vdev_parse_uid (value, &uid);
+
+ if (rc != 0)
+ {
+ vdev_error ("vdev_parse_uid(%s) rc = %d\n", value, rc);
+
+ fprintf (stderr, "Invalid user/UID '%s'\n", value);
+ return 0;
+ }
+
acl->has_uid = true;
acl->uid = uid;
return 1;
- }
-
- if( strcmp(name, VDEV_ACL_NAME_SETUID ) == 0 ) {
-
+ }
+
+ if (strcmp (name, VDEV_ACL_NAME_SETUID) == 0)
+ {
+
// parse user or UID
uid_t uid = 0;
- int rc = vdev_parse_uid( value, &uid );
-
- if( rc != 0 ) {
- vdev_error("vdev_parse_uid(%s) rc = %d\n", value, rc );
-
- fprintf(stderr, "Invalid user/UID '%s'\n", value );
- return 0;
- }
-
+ int rc = vdev_parse_uid (value, &uid);
+
+ if (rc != 0)
+ {
+ vdev_error ("vdev_parse_uid(%s) rc = %d\n", value, rc);
+
+ fprintf (stderr, "Invalid user/UID '%s'\n", value);
+ return 0;
+ }
+
acl->has_setuid = true;
acl->setuid = uid;
return 1;
- }
-
- if( strcmp(name, VDEV_ACL_NAME_GID ) == 0 ) {
-
+ }
+
+ if (strcmp (name, VDEV_ACL_NAME_GID) == 0)
+ {
+
// parse group or GID
gid_t gid = 0;
- int rc = vdev_parse_gid( value, &gid );
-
- if( rc != 0 ) {
- vdev_error("vdev_parse_gid(%s) rc = %d\n", value, rc );
-
- fprintf(stderr, "Invalid group/GID '%s'\n", value );
- return 0;
- }
-
+ int rc = vdev_parse_gid (value, &gid);
+
+ if (rc != 0)
+ {
+ vdev_error ("vdev_parse_gid(%s) rc = %d\n", value, rc);
+
+ fprintf (stderr, "Invalid group/GID '%s'\n", value);
+ return 0;
+ }
+
acl->has_gid = true;
acl->gid = gid;
return 1;
- }
-
- if( strcmp(name, VDEV_ACL_NAME_SETGID ) == 0 ) {
-
+ }
+
+ if (strcmp (name, VDEV_ACL_NAME_SETGID) == 0)
+ {
+
// parse group or GID
gid_t gid = 0;
- int rc = vdev_parse_gid( value, &gid );
-
- if( rc != 0 ) {
- vdev_error("vdev_parse_gid(%s) rc = %d\n", value, rc );
-
- fprintf(stderr, "Invalid group/GID '%s'\n", value );
- return 0;
- }
-
+ int rc = vdev_parse_gid (value, &gid);
+
+ if (rc != 0)
+ {
+ vdev_error ("vdev_parse_gid(%s) rc = %d\n", value, rc);
+
+ fprintf (stderr, "Invalid group/GID '%s'\n", value);
+ return 0;
+ }
+
acl->has_setgid = true;
acl->setgid = gid;
return 1;
- }
-
- if( strcmp(name, VDEV_ACL_NAME_SETMODE ) == 0 ) {
-
+ }
+
+ if (strcmp (name, VDEV_ACL_NAME_SETMODE) == 0)
+ {
+
// parse mode
mode_t mode = 0;
- int rc = vdev_acl_parse_mode( &mode, value );
-
- if( rc != 0 ) {
- vdev_error("vdev_acl_parse_mode(%s) rc = %d\n", value, rc );
-
- fprintf(stderr, "Invalid mode '%s'\n", value );
- return 0;
- }
-
+ int rc = vdev_acl_parse_mode (&mode, value);
+
+ if (rc != 0)
+ {
+ vdev_error ("vdev_acl_parse_mode(%s) rc = %d\n", value, rc);
+
+ fprintf (stderr, "Invalid mode '%s'\n", value);
+ return 0;
+ }
+
acl->has_setmode = true;
acl->setmode = mode;
return 1;
- }
-
- if( strcmp(name, VDEV_ACL_DEVICE_REGEX ) == 0 ) {
-
+ }
+
+ if (strcmp (name, VDEV_ACL_DEVICE_REGEX) == 0)
+ {
+
// parse and preserve this value
- int rc = vdev_match_regex_append( &acl->paths, &acl->regexes, &acl->num_paths, value );
-
- if( rc != 0 ) {
- vdev_error("vdev_match_regex_append(%s) rc = %d\n", value, rc );
-
- fprintf(stderr, "Invalid regex '%s'\n", value );
- return 0;
- }
-
+ int rc = vdev_match_regex_append (&acl->paths, &acl->regexes,
+ &acl->num_paths, value);
+
+ if (rc != 0)
+ {
+ vdev_error ("vdev_match_regex_append(%s) rc = %d\n", value, rc);
+
+ fprintf (stderr, "Invalid regex '%s'\n", value);
+ return 0;
+ }
+
return 1;
- }
-
- if( strcmp(name, VDEV_ACL_NAME_PROC_PATH ) == 0 ) {
-
+ }
+
+ if (strcmp (name, VDEV_ACL_NAME_PROC_PATH) == 0)
+ {
+
// preserve this value
- if( acl->proc_path != NULL ) {
-
- fprintf(stderr, "Duplicate process path '%s'\n", value );
- return 0;
- }
-
+ if (acl->proc_path != NULL)
+ {
+
+ fprintf (stderr, "Duplicate process path '%s'\n", value);
+ return 0;
+ }
+
acl->has_proc = true;
- acl->proc_path = vdev_strdup_or_null(value);
+ acl->proc_path = vdev_strdup_or_null (value);
return 1;
- }
-
- if( strcmp(name, VDEV_ACL_NAME_PROC_PREDICATE ) == 0 ) {
-
+ }
+
+ if (strcmp (name, VDEV_ACL_NAME_PROC_PREDICATE) == 0)
+ {
+
// preserve this value
- if( acl->proc_predicate_cmd != NULL ) {
-
- fprintf(stderr, "Duplicate predicate '%s'\n", value );
- return 0;
- }
-
+ if (acl->proc_predicate_cmd != NULL)
+ {
+
+ fprintf (stderr, "Duplicate predicate '%s'\n", value);
+ return 0;
+ }
+
acl->has_proc = true;
- acl->proc_predicate_cmd = vdev_strdup_or_null(value);
+ acl->proc_predicate_cmd = vdev_strdup_or_null (value);
return 1;
- }
-
- if( strcmp(name, VDEV_ACL_NAME_PROC_INODE ) == 0 ) {
-
+ }
+
+ if (strcmp (name, VDEV_ACL_NAME_PROC_INODE) == 0)
+ {
+
// preserve this value
ino_t inode = 0;
bool success = false;
-
- inode = vdev_parse_uint64( value, &success );
- if( !success ) {
-
- fprintf(stderr, "Failed to parse inode '%s'\n", value );
- return 0;
- }
-
+
+ inode = vdev_parse_uint64 (value, &success);
+ if (!success)
+ {
+
+ fprintf (stderr, "Failed to parse inode '%s'\n", value);
+ return 0;
+ }
+
acl->has_proc = true;
acl->proc_inode = inode;
return 1;
- }
-
- fprintf(stderr, "Unrecognized field '%s'\n", name);
- return 0;
-}
+ }
+ fprintf (stderr, "Unrecognized field '%s'\n", name);
+ return 0;
+}
// acl sanity check
-int vdev_acl_sanity_check( struct vdev_acl* acl ) {
-
- int rc = 0;
-
- if( acl->has_gid ) {
-
- rc = vdev_validate_gid( acl->gid );
- if( rc != 0 ) {
-
- fprintf(stderr, "Invalid GID %d\n", acl->gid );
- return rc;
- }
- }
-
- if( acl->has_setgid ) {
-
- rc = vdev_validate_gid( acl->gid );
- if( rc != 0 ) {
-
- fprintf(stderr, "Invalid set-GID %d\n", acl->setgid );
- return rc;
- }
- }
-
- if( acl->has_uid ) {
-
- rc = vdev_validate_uid( acl->uid );
- if( rc != 0 ) {
-
- fprintf(stderr, "Invalid UID %d\n", acl->uid );
- return rc;
- }
- }
-
- if( acl->has_setuid ) {
-
- rc = vdev_validate_uid( acl->uid );
- if( rc != 0 ) {
-
- fprintf(stderr, "Invalid set-UID %d\n", acl->setuid );
- return rc;
- }
- }
-
- return rc;
+int
+vdev_acl_sanity_check (struct vdev_acl *acl)
+{
+
+ int rc = 0;
+
+ if (acl->has_gid)
+ {
+
+ rc = vdev_validate_gid (acl->gid);
+ if (rc != 0)
+ {
+
+ fprintf (stderr, "Invalid GID %d\n", acl->gid);
+ return rc;
+ }
+ }
+
+ if (acl->has_setgid)
+ {
+
+ rc = vdev_validate_gid (acl->gid);
+ if (rc != 0)
+ {
+
+ fprintf (stderr, "Invalid set-GID %d\n", acl->setgid);
+ return rc;
+ }
+ }
+
+ if (acl->has_uid)
+ {
+
+ rc = vdev_validate_uid (acl->uid);
+ if (rc != 0)
+ {
+
+ fprintf (stderr, "Invalid UID %d\n", acl->uid);
+ return rc;
+ }
+ }
+
+ if (acl->has_setuid)
+ {
+
+ rc = vdev_validate_uid (acl->uid);
+ if (rc != 0)
+ {
+
+ fprintf (stderr, "Invalid set-UID %d\n", acl->setuid);
+ return rc;
+ }
+ }
+
+ return rc;
}
// initialize an acl
-int vdev_acl_init( struct vdev_acl* acl ) {
- memset( acl, 0, sizeof(struct vdev_acl) );
- return 0;
+int
+vdev_acl_init (struct vdev_acl *acl)
+{
+ memset (acl, 0, sizeof (struct vdev_acl));
+ return 0;
}
-
// free an acl
-int vdev_acl_free( struct vdev_acl* acl ) {
-
- if( acl->num_paths > 0 ) {
-
- vdev_match_regexes_free( acl->paths, acl->regexes, acl->num_paths );
- }
-
- if( acl->proc_path != NULL ) {
- free( acl->proc_path );
+int
+vdev_acl_free (struct vdev_acl *acl)
+{
+
+ if (acl->num_paths > 0)
+ {
+
+ vdev_match_regexes_free (acl->paths, acl->regexes, acl->num_paths);
+ }
+
+ if (acl->proc_path != NULL)
+ {
+ free (acl->proc_path);
acl->proc_path = NULL;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// load an ACL from a file handle
-int vdev_acl_load_file( FILE* file, struct vdev_acl* acl ) {
-
- int rc = 0;
-
- vdev_acl_init( acl );
-
- rc = ini_parse_file( file, vdev_acl_ini_parser, acl );
- if( rc != 0 ) {
- vdev_error("ini_parse_file(ACL) rc = %d\n", rc );
+int
+vdev_acl_load_file (FILE * file, struct vdev_acl *acl)
+{
+
+ int rc = 0;
+
+ vdev_acl_init (acl);
+
+ rc = ini_parse_file (file, vdev_acl_ini_parser, acl);
+ if (rc != 0)
+ {
+ vdev_error ("ini_parse_file(ACL) rc = %d\n", rc);
return rc;
- }
-
- // sanity check
- rc = vdev_acl_sanity_check( acl );
- if( rc != 0 ) {
-
- vdev_error("vdev_acl_sanity_check rc = %d\n", rc );
-
- vdev_acl_free( acl );
- memset( acl, 0, sizeof(struct vdev_acl) );
+ }
+ // sanity check
+ rc = vdev_acl_sanity_check (acl);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_acl_sanity_check rc = %d\n", rc);
+
+ vdev_acl_free (acl);
+ memset (acl, 0, sizeof (struct vdev_acl));
return rc;
- }
-
- return rc;
-}
+ }
+ return rc;
+}
// load an ACL from a file, given the path
-int vdev_acl_load( char const* path, struct vdev_acl* acl ) {
-
- int rc = 0;
- FILE* f = NULL;
-
- f = fopen( path, "r" );
- if( f == NULL ) {
-
+int
+vdev_acl_load (char const *path, struct vdev_acl *acl)
+{
+
+ int rc = 0;
+ FILE *f = NULL;
+
+ f = fopen (path, "r");
+ if (f == NULL)
+ {
+
rc = -errno;
- vdev_error("fopen(%s) errno = %d\n", path,rc );
+ vdev_error ("fopen(%s) errno = %d\n", path, rc);
return rc;
- }
-
- rc = vdev_acl_load_file( f, acl );
-
- fclose( f );
-
- if( rc != 0 ) {
- vdev_error("vdev_acl_load_file(%s) rc = %d\n", path, rc );
- }
-
- return rc;
-}
+ }
+
+ rc = vdev_acl_load_file (f, acl);
+
+ fclose (f);
+
+ if (rc != 0)
+ {
+ vdev_error ("vdev_acl_load_file(%s) rc = %d\n", path, rc);
+ }
+ return rc;
+}
// free a vector of acls
-static void vdev_acl_free_vector( struct sglib_vdev_acl_vector* acls ) {
-
- for( unsigned long i = 0; i < sglib_vdev_acl_vector_size( acls ); i++ ) {
-
- struct vdev_acl* acl = sglib_vdev_acl_vector_at_ref( acls, i );
-
- vdev_acl_free( acl );
- }
-
- sglib_vdev_acl_vector_clear( acls );
+static void
+vdev_acl_free_vector (struct sglib_vdev_acl_vector *acls)
+{
+
+ for (unsigned long i = 0; i < sglib_vdev_acl_vector_size (acls); i++)
+ {
+
+ struct vdev_acl *acl = sglib_vdev_acl_vector_at_ref (acls, i);
+
+ vdev_acl_free (acl);
+ }
+
+ sglib_vdev_acl_vector_clear (acls);
}
// free a C-style list of acls (including the list itself)
-int vdev_acl_free_all( struct vdev_acl* acl_list, size_t num_acls ) {
-
- int rc = 0;
-
- for( unsigned int i = 0; i < num_acls; i++ ) {
-
- rc = vdev_acl_free( &acl_list[i] );
- if( rc != 0 ) {
-
- return rc;
- }
- }
-
- free( acl_list );
-
- return rc;
-}
+int
+vdev_acl_free_all (struct vdev_acl *acl_list, size_t num_acls)
+{
+
+ int rc = 0;
+
+ for (unsigned int i = 0; i < num_acls; i++)
+ {
+ rc = vdev_acl_free (&acl_list[i]);
+ if (rc != 0)
+ {
+
+ return rc;
+ }
+ }
+
+ free (acl_list);
+
+ return rc;
+}
// loader for an acl
-int vdev_acl_loader( char const* fp, void* cls ) {
-
- struct vdev_acl acl;
- int rc = 0;
- struct stat sb;
-
- struct sglib_vdev_acl_vector* acls = (struct sglib_vdev_acl_vector*)cls;
-
- // skip if not a regular file
- rc = stat( fp, &sb );
- if( rc != 0 ) {
-
+int
+vdev_acl_loader (char const *fp, void *cls)
+{
+
+ struct vdev_acl acl;
+ int rc = 0;
+ struct stat sb;
+
+ struct sglib_vdev_acl_vector *acls = (struct sglib_vdev_acl_vector *) cls;
+
+ // skip if not a regular file
+ rc = stat (fp, &sb);
+ if (rc != 0)
+ {
+
rc = -errno;
- vdev_error("stat(%s) rc = %d\n", fp, rc );
+ vdev_error ("stat(%s) rc = %d\n", fp, rc);
return rc;
- }
-
- if( !S_ISREG( sb.st_mode ) ) {
-
+ }
+
+ if (!S_ISREG (sb.st_mode))
+ {
+
return 0;
- }
-
- vdev_debug("Load ACL %s\n", fp );
-
- memset( &acl, 0, sizeof(struct vdev_acl) );
-
- rc = vdev_acl_load( fp, &acl );
- if( rc != 0 ) {
-
- vdev_error("vdev_acl_load(%s) rc = %d\n", fp, rc );
+ }
+
+ vdev_debug ("Load ACL %s\n", fp);
+
+ memset (&acl, 0, sizeof (struct vdev_acl));
+
+ rc = vdev_acl_load (fp, &acl);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_acl_load(%s) rc = %d\n", fp, rc);
return rc;
- }
-
- // save this acl
- rc = sglib_vdev_acl_vector_push_back( acls, acl );
- if( rc != 0 ) {
-
+ }
+ // save this acl
+ rc = sglib_vdev_acl_vector_push_back (acls, acl);
+ if (rc != 0)
+ {
+
// OOM
- vdev_acl_free( &acl );
+ vdev_acl_free (&acl);
return rc;
- }
-
- return 0;
+ }
+
+ return 0;
}
// load all ACLs from a directory, in lexographic order
// return 0 on success, negative on error
-int vdev_acl_load_all( char const* dir_path, struct vdev_acl** ret_acls, size_t* ret_num_acls ) {
-
- int rc = 0;
- struct sglib_vdev_acl_vector acls;
-
- sglib_vdev_acl_vector_init( &acls );
-
- rc = vdev_load_all( dir_path, vdev_acl_loader, &acls );
-
- if( rc != 0 ) {
-
- vdev_acl_free_vector( &acls );
+int
+vdev_acl_load_all (char const *dir_path, struct vdev_acl **ret_acls,
+ size_t * ret_num_acls)
+{
+
+ int rc = 0;
+ struct sglib_vdev_acl_vector acls;
+
+ sglib_vdev_acl_vector_init (&acls);
+
+ rc = vdev_load_all (dir_path, vdev_acl_loader, &acls);
+
+ if (rc != 0)
+ {
+
+ vdev_acl_free_vector (&acls);
return rc;
- }
- else {
-
- if( sglib_vdev_acl_vector_size( &acls ) == 0 ) {
-
- // nothing
- *ret_acls = NULL;
- *ret_num_acls = 0;
- }
- else {
-
- // extract values
- unsigned long len = 0;
-
- sglib_vdev_acl_vector_yoink( &acls, ret_acls, &len );
-
- *ret_num_acls = len;
- }
- }
-
- return 0;
+ }
+ else
+ {
+
+ if (sglib_vdev_acl_vector_size (&acls) == 0)
+ {
+
+ // nothing
+ *ret_acls = NULL;
+ *ret_num_acls = 0;
+ }
+ else
+ {
+
+ // extract values
+ unsigned long len = 0;
+
+ sglib_vdev_acl_vector_yoink (&acls, ret_acls, &len);
+
+ *ret_num_acls = len;
+ }
+ }
+
+ return 0;
}
// modify a stat buffer to apply a user access control list, if the acl says so
-int vdev_acl_do_set_user( struct vdev_acl* acl, uid_t caller_uid, struct stat* sb ) {
-
- if( acl->has_setuid && acl->has_uid ) {
-
+int
+vdev_acl_do_set_user (struct vdev_acl *acl, uid_t caller_uid, struct stat *sb)
+{
+
+ if (acl->has_setuid && acl->has_uid)
+ {
+
// change the UID of this path
- if( acl->uid == caller_uid ) {
- sb->st_uid = acl->setuid;
- }
- }
-
- return 0;
+ if (acl->uid == caller_uid)
+ {
+ sb->st_uid = acl->setuid;
+ }
+ }
+
+ return 0;
}
// modify a stat buffer to apply a group access control list
-int vdev_acl_do_set_group( struct vdev_acl* acl, gid_t caller_gid, struct stat* sb ) {
-
- if( acl->has_setgid && acl->has_gid ) {
-
+int
+vdev_acl_do_set_group (struct vdev_acl *acl, gid_t caller_gid,
+ struct stat *sb)
+{
+
+ if (acl->has_setgid && acl->has_gid)
+ {
+
// change the GID of this path
- if( acl->gid == caller_gid ) {
- sb->st_gid = acl->setgid;
- }
- }
-
- return 0;
+ if (acl->gid == caller_gid)
+ {
+ sb->st_gid = acl->setgid;
+ }
+ }
+
+ return 0;
}
// modify a stat buffer to apply the mode
-int vdev_acl_do_set_mode( struct vdev_acl* acl, struct stat* sb ) {
-
- if( acl->has_setmode ) {
-
+int
+vdev_acl_do_set_mode (struct vdev_acl *acl, struct stat *sb)
+{
+
+ if (acl->has_setmode)
+ {
+
// clear permission bits
sb->st_mode &= ~(0777);
-
+
// set permission bits
sb->st_mode |= acl->setmode;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// evaluate a predicate command, with the appropriate environment variables set.
// on success, fill in the exit code.
// return 0 on success
// return negative on error
-int vdev_acl_run_predicate( struct vdev_acl* acl, struct pstat* ps, uid_t caller_uid, gid_t caller_gid, int* exit_code ) {
-
- int exit_status = 0;
- char* cmd_buf = NULL;
- char env_buf[3][100];
- char* predicate_env[4];
- int rc = 0;
-
- // build the command with the apporpriate environment variables:
- // * VDEV_GID: the gid of the calling process
- // * VDEV_UID: the uid of the calling process
- // * VDEV_PID: the pid of the calling process
-
- sprintf(env_buf[0], "VDEV_UID=%u", caller_uid );
- sprintf(env_buf[1], "VDEV_GID=%u", caller_gid );
- sprintf(env_buf[2], "VDEV_PID=%u", pstat_get_pid( ps ));
-
- predicate_env[0] = env_buf[0];
- predicate_env[1] = env_buf[1];
- predicate_env[2] = env_buf[2];
- predicate_env[3] = NULL;
-
- rc = vdev_subprocess( cmd_buf, predicate_env, NULL, 0, -1, &exit_status, true );
-
- if( rc != 0 ) {
-
- vdev_error("vdev_subprocess('%s') rc = %d\n", cmd_buf, rc );
-
- free( cmd_buf );
+int
+vdev_acl_run_predicate (struct vdev_acl *acl, struct pstat *ps,
+ uid_t caller_uid, gid_t caller_gid, int *exit_code)
+{
+
+ int exit_status = 0;
+ char *cmd_buf = NULL;
+ char env_buf[3][100];
+ char *predicate_env[4];
+ int rc = 0;
+
+ // build the command with the apporpriate environment variables:
+ // * VDEV_GID: the gid of the calling process
+ // * VDEV_UID: the uid of the calling process
+ // * VDEV_PID: the pid of the calling process
+
+ sprintf (env_buf[0], "VDEV_UID=%u", caller_uid);
+ sprintf (env_buf[1], "VDEV_GID=%u", caller_gid);
+ sprintf (env_buf[2], "VDEV_PID=%u", pstat_get_pid (ps));
+
+ predicate_env[0] = env_buf[0];
+ predicate_env[1] = env_buf[1];
+ predicate_env[2] = env_buf[2];
+ predicate_env[3] = NULL;
+
+ rc = vdev_subprocess (cmd_buf, predicate_env, NULL, 0, -1, &exit_status,
+ true);
+
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_subprocess('%s') rc = %d\n", cmd_buf, rc);
+
+ free (cmd_buf);
return rc;
- }
-
- *exit_code = exit_status;
-
- free( cmd_buf );
-
- return 0;
+ }
+
+ *exit_code = exit_status;
+
+ free (cmd_buf);
+
+ return 0;
}
-
// check that the caller PID is matched by the given ACL.
// every process match criterion must be satisfied.
// return 1 if all ACL criteria match
// return 0 if at least one ACL criterion does not match
// return negative on error
-int vdev_acl_match_process( struct vdev_acl* acl, struct pstat* ps, uid_t caller_uid, gid_t caller_gid ) {
-
- int rc = 0;
- char path[PATH_MAX+1];
- struct stat sb;
-
- if( !acl->has_proc ) {
+int
+vdev_acl_match_process (struct vdev_acl *acl, struct pstat *ps,
+ uid_t caller_uid, gid_t caller_gid)
+{
+
+ int rc = 0;
+ char path[PATH_MAX + 1];
+ struct stat sb;
+
+ if (!acl->has_proc)
+ {
// applies to anyone
return 1;
- }
-
- if( acl->proc_path != NULL || acl->has_proc_inode ) {
-
- if( acl->proc_path != NULL ) {
-
- pstat_get_path( ps, path );
- if( strcmp( acl->proc_path, path ) != 0 ) {
-
- // doesn't match
- return 0;
- }
- }
-
- if( acl->has_proc_inode ) {
-
- pstat_get_stat( ps, &sb );
- if( acl->proc_inode != sb.st_ino ) {
-
- // doesn't match
- return 0;
- }
- }
- }
-
- // filter on a given PID list generator?
- if( acl->proc_predicate_cmd != NULL ) {
-
+ }
+
+ if (acl->proc_path != NULL || acl->has_proc_inode)
+ {
+
+ if (acl->proc_path != NULL)
+ {
+
+ pstat_get_path (ps, path);
+ if (strcmp (acl->proc_path, path) != 0)
+ {
+
+ // doesn't match
+ return 0;
+ }
+ }
+
+ if (acl->has_proc_inode)
+ {
+
+ pstat_get_stat (ps, &sb);
+ if (acl->proc_inode != sb.st_ino)
+ {
+
+ // doesn't match
+ return 0;
+ }
+ }
+ }
+ // filter on a given PID list generator?
+ if (acl->proc_predicate_cmd != NULL)
+ {
+
// run the command and use the exit code to see if
// this ACL applies to the calling process
int exit_status = 0;
-
- rc = vdev_acl_run_predicate( acl, ps, caller_uid, caller_gid, &exit_status );
- if( rc != 0 ) {
-
- vdev_error("vdev_acl_run_predicate('%s') rc = %d\n", acl->proc_predicate_cmd, rc );
- return rc;
- }
-
+
+ rc = vdev_acl_run_predicate (acl, ps, caller_uid, caller_gid,
+ &exit_status);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_acl_run_predicate('%s') rc = %d\n",
+ acl->proc_predicate_cmd, rc);
+ return rc;
+ }
// exit status follows shell-like semantics:
// 0 indicates "yes, this applies."
// non-zero indicates "no, this does not apply"
-
- if( exit_status == 0 ) {
- return 1;
- }
- else {
- return 0;
- }
- }
-
- // all checks match
- return 1;
-}
+ if (exit_status == 0)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ // all checks match
+ return 1;
+}
// given a list of access control lists, find the index of the first one that applies to the given caller and path.
// return >= 0 with the index
// return num_acls if not found
// return negative on error
-int vdev_acl_find_next( char const* path, struct pstat* caller_proc, uid_t caller_uid, gid_t caller_gid, struct vdev_acl* acls, size_t num_acls ) {
-
- int rc = 0;
- bool found = false;
- int idx = 0;
-
- for( unsigned int i = 0; i < num_acls; i++ ) {
-
+int
+vdev_acl_find_next (char const *path, struct pstat *caller_proc,
+ uid_t caller_uid, gid_t caller_gid,
+ struct vdev_acl *acls, size_t num_acls)
+{
+
+ int rc = 0;
+ bool found = false;
+ int idx = 0;
+
+ for (unsigned int i = 0; i < num_acls; i++)
+ {
+
rc = 0;
-
+
// match UID?
- if( acls[i].has_uid && acls[i].uid != caller_uid ) {
- // nope
- continue;
- }
-
+ if (acls[i].has_uid && acls[i].uid != caller_uid)
+ {
+ // nope
+ continue;
+ }
// match GID?
- if( acls[i].has_gid && acls[i].gid != caller_gid ) {
- // nope
- continue;
- }
-
+ if (acls[i].has_gid && acls[i].gid != caller_gid)
+ {
+ // nope
+ continue;
+ }
// match path?
- if( acls[i].num_paths > 0 ) {
-
- rc = vdev_match_first_regex( path, acls[i].regexes, acls[i].num_paths );
-
- if( rc >= (signed)acls[i].num_paths ) {
- // no match
- continue;
- }
- }
-
- if( rc < 0 ) {
-
- vdev_error("vdev_match_first_regex(%s) rc = %d\n", path, rc );
- break;
- }
-
+ if (acls[i].num_paths > 0)
+ {
+
+ rc = vdev_match_first_regex (path, acls[i].regexes,
+ acls[i].num_paths);
+
+ if (rc >= (signed) acls[i].num_paths)
+ {
+ // no match
+ continue;
+ }
+ }
+
+ if (rc < 0)
+ {
+
+ vdev_error ("vdev_match_first_regex(%s) rc = %d\n", path, rc);
+ break;
+ }
// match process? Do this last, since it can be expensive
- rc = vdev_acl_match_process( &acls[i], caller_proc, caller_uid, caller_gid );
- if( rc == 0 ) {
- // no match
- continue;
- }
-
- if( rc < 0 ) {
-
- // error...
- vdev_error("vdev_acl_match_process(%d) rc = %d\n", pstat_get_pid( caller_proc ), rc );
- break;
- }
-
+ rc = vdev_acl_match_process (&acls[i], caller_proc, caller_uid,
+ caller_gid);
+ if (rc == 0)
+ {
+ // no match
+ continue;
+ }
+
+ if (rc < 0)
+ {
+
+ // error...
+ vdev_error ("vdev_acl_match_process(%d) rc = %d\n",
+ pstat_get_pid (caller_proc), rc);
+ break;
+ }
// success!
found = true;
idx = i;
rc = 0;
break;
- }
-
- if( found ) {
+ }
+
+ if (found)
+ {
return idx;
- }
- else {
- if( rc >= 0 ) {
- return num_acls;
- }
- else {
- return rc;
- }
- }
+ }
+ else
+ {
+ if (rc >= 0)
+ {
+ return num_acls;
+ }
+ else
+ {
+ return rc;
+ }
+ }
}
// apply the acl to the stat buf, filtering on caller uid, gid, and process information
-int vdev_acl_apply( struct vdev_acl* acl, uid_t caller_uid, gid_t caller_gid, struct stat* sb ) {
-
- // set user, group, mode (if given)
- vdev_acl_do_set_user( acl, caller_uid, sb );
- vdev_acl_do_set_group( acl, caller_gid, sb );
- vdev_acl_do_set_mode( acl, sb );
-
- return 0;
-}
+int
+vdev_acl_apply (struct vdev_acl *acl, uid_t caller_uid, gid_t caller_gid,
+ struct stat *sb)
+{
+
+ // set user, group, mode (if given)
+ vdev_acl_do_set_user (acl, caller_uid, sb);
+ vdev_acl_do_set_group (acl, caller_gid, sb);
+ vdev_acl_do_set_mode (acl, sb);
+ return 0;
+}
// go through the list of acls and apply any modifications to the given stat buffer
// return 1 if at least one ACL matches
// return 0 if there are no matches (i.e. this device node should be hidden)
// return negative on error
-int vdev_acl_apply_all( struct vdev_config* config, struct vdev_acl* acls, size_t num_acls, char const* path, struct pstat* caller_proc, uid_t caller_uid, gid_t caller_gid, struct stat* sb ) {
-
- int rc = 0;
- int acl_offset = 0;
- int i = 0;
- bool found = false;
-
- // special case: if there are no ACLs, then follow the config default policy
- if( num_acls == 0 ) {
+int
+vdev_acl_apply_all (struct vdev_config *config, struct vdev_acl *acls,
+ size_t num_acls, char const *path,
+ struct pstat *caller_proc, uid_t caller_uid,
+ gid_t caller_gid, struct stat *sb)
+{
+
+ int rc = 0;
+ int acl_offset = 0;
+ int i = 0;
+ bool found = false;
+
+ // special case: if there are no ACLs, then follow the config default policy
+ if (num_acls == 0)
+ {
return config->default_policy;
- }
-
- while( acl_offset < (signed)num_acls ) {
-
+ }
+
+ while (acl_offset < (signed) num_acls)
+ {
+
// find the next acl
- rc = vdev_acl_find_next( path, caller_proc, caller_uid, caller_gid, acls + acl_offset, num_acls - acl_offset );
-
- if( rc == (signed)(num_acls - acl_offset) ) {
-
- // not found
- rc = 0;
- break;
- }
- else if( rc < 0 ) {
-
- vdev_error("vdev_acl_find_next(%s, offset = %d) rc = %d\n", path, acl_offset, rc );
- break;
- }
- else {
-
- // matched! advance offset to next acl
- i = acl_offset + rc;
- acl_offset += rc + 1;
- found = true;
-
- // apply the ACL
- rc = vdev_acl_apply( &acls[i], caller_uid, caller_gid, sb );
- if( rc != 0 ) {
-
- vdev_error("vdev_acl_apply(%s, offset = %d) rc = %d\n", path, acl_offset, rc );
- break;
- }
- }
- }
-
- if( rc == 0 ) {
+ rc = vdev_acl_find_next (path, caller_proc, caller_uid,
+ caller_gid, acls + acl_offset,
+ num_acls - acl_offset);
+
+ if (rc == (signed) (num_acls - acl_offset))
+ {
+
+ // not found
+ rc = 0;
+ break;
+ }
+ else if (rc < 0)
+ {
+
+ vdev_error
+ ("vdev_acl_find_next(%s, offset = %d) rc = %d\n",
+ path, acl_offset, rc);
+ break;
+ }
+ else
+ {
+
+ // matched! advance offset to next acl
+ i = acl_offset + rc;
+ acl_offset += rc + 1;
+ found = true;
+
+ // apply the ACL
+ rc = vdev_acl_apply (&acls[i], caller_uid, caller_gid, sb);
+ if (rc != 0)
+ {
+
+ vdev_error
+ ("vdev_acl_apply(%s, offset = %d) rc = %d\n",
+ path, acl_offset, rc);
+ break;
+ }
+ }
+ }
+
+ if (rc == 0)
+ {
// no error reported
- if( found ) {
- rc = 1;
- }
- }
-
- return rc;
+ if (found)
+ {
+ rc = 1;
+ }
+ }
+
+ return rc;
}
diff --git a/fs/acl.h b/fs/acl.h
index 8a13a08..2baa6cf 100644
--- a/fs/acl.h
+++ b/fs/acl.h
@@ -46,39 +46,40 @@
#define VDEV_ACL_PROC_BUFLEN 65536
// vdev access control list.
-struct vdev_acl {
-
- // user to match
- bool has_uid;
- uid_t uid;
-
- // group to match
- bool has_gid;
- gid_t gid;
-
- // process info to match (set at least one; all must match for the ACL to apply)
- bool has_proc; // if true, at least one of the following is filled in (and the ACL will only apply if the request is from one of the indicated processes)
- char* proc_path; // path to the allowed process
- char* proc_predicate_cmd; // command string to run to see if this ACL applies to the calling process (based on the exit code: 0 indicates 'yes, this applies'; nonzero indicates 'no, does not apply')
- bool has_proc_inode; // whether or not the ACL has an inode check
- ino_t proc_inode; // process binary's inode
-
- // UID to set on match
- bool has_setuid;
- uid_t setuid;
-
- // GID to set on match
- bool has_setgid;
- gid_t setgid;
-
- // mode to set on match
- bool has_setmode;
- mode_t setmode;
-
- // device node path regexes over which this ACL applies (NULL-terminated)
- char** paths;
- regex_t* regexes;
- size_t num_paths;
+struct vdev_acl
+{
+
+ // user to match
+ bool has_uid;
+ uid_t uid;
+
+ // group to match
+ bool has_gid;
+ gid_t gid;
+
+ // process info to match (set at least one; all must match for the ACL to apply)
+ bool has_proc; // if true, at least one of the following is filled in (and the ACL will only apply if the request is from one of the indicated processes)
+ char *proc_path; // path to the allowed process
+ char *proc_predicate_cmd; // command string to run to see if this ACL applies to the calling process (based on the exit code: 0 indicates 'yes, this applies'; nonzero indicates 'no, does not apply')
+ bool has_proc_inode; // whether or not the ACL has an inode check
+ ino_t proc_inode; // process binary's inode
+
+ // UID to set on match
+ bool has_setuid;
+ uid_t setuid;
+
+ // GID to set on match
+ bool has_setgid;
+ gid_t setgid;
+
+ // mode to set on match
+ bool has_setmode;
+ mode_t setmode;
+
+ // device node path regexes over which this ACL applies (NULL-terminated)
+ char **paths;
+ regex_t *regexes;
+ size_t num_paths;
};
typedef struct vdev_acl vdev_acl;
@@ -86,15 +87,16 @@ typedef struct vdev_acl vdev_acl;
// prototype...
struct vdev_config;
-C_LINKAGE_BEGIN
+C_LINKAGE_BEGIN int vdev_acl_init (struct vdev_acl *acl);
+int vdev_acl_load_all (char const *dir_path, struct vdev_acl **ret_acls,
+ size_t * ret_num_acls);
+int vdev_acl_free (struct vdev_acl *acl);
+int vdev_acl_free_all (struct vdev_acl *acl_list, size_t num_acls);
-int vdev_acl_init( struct vdev_acl* acl );
-int vdev_acl_load_all( char const* dir_path, struct vdev_acl** ret_acls, size_t* ret_num_acls );
-int vdev_acl_free( struct vdev_acl* acl );
-int vdev_acl_free_all( struct vdev_acl* acl_list, size_t num_acls );
-
-int vdev_acl_apply_all( struct vdev_config* conf, struct vdev_acl* acls, size_t num_acls, char const* path, struct pstat* caller_proc, uid_t caller_uid, gid_t caller_gid, struct stat* sb );
+int vdev_acl_apply_all (struct vdev_config *conf, struct vdev_acl *acls,
+ size_t num_acls, char const *path,
+ struct pstat *caller_proc, uid_t caller_uid,
+ gid_t caller_gid, struct stat *sb);
C_LINKAGE_END
-
#endif
diff --git a/fs/fs.c b/fs/fs.c
index 1daa5de..578428b 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -19,1274 +19,1454 @@
.
*/
-
#include "fs.h"
#include "acl.h"
-static char const* vdev_fuse_odev = "-odev";
-static char const* vdev_fuse_ononempty = "-ononempty";
-static char const* vdev_fuse_allow_other = "-oallow_other";
+static char const *vdev_fuse_odev = "-odev";
+static char const *vdev_fuse_ononempty = "-ononempty";
+static char const *vdev_fuse_allow_other = "-oallow_other";
// scanning context queue entry
-struct vdevfs_scandirat_queue {
-
- int fd;
- char* path;
-
- struct vdevfs_scandirat_queue* next;
+struct vdevfs_scandirat_queue
+{
+
+ int fd;
+ char *path;
+
+ struct vdevfs_scandirat_queue *next;
};
// scanning context, for vdevfs_dev_import
-struct vdevfs_scandirat_context {
+struct vdevfs_scandirat_context
+{
- struct fskit_core* core; // fskit core context
- struct fskit_entry* parent_dir; // corresponding fskit directory being scanned
- char* parent_path;
-
- struct vdevfs_scandirat_queue* tail;
-};
+ struct fskit_core *core; // fskit core context
+ struct fskit_entry *parent_dir; // corresponding fskit directory being scanned
+ char *parent_path;
+ struct vdevfs_scandirat_queue *tail;
+};
// set up a vdevfs_scandirat_context
// always succeeds
-static void vdevfs_scandirat_context_init( struct vdevfs_scandirat_context* ctx, struct fskit_core* core, struct fskit_entry* parent_dir, char* parent_path, struct vdevfs_scandirat_queue* tail ) {
-
- ctx->core = core;
- ctx->parent_dir = parent_dir;
- ctx->parent_path = parent_path;
- ctx->tail = tail;
-}
+static void
+vdevfs_scandirat_context_init (struct vdevfs_scandirat_context *ctx,
+ struct fskit_core *core,
+ struct fskit_entry *parent_dir,
+ char *parent_path,
+ struct vdevfs_scandirat_queue *tail)
+{
+ ctx->core = core;
+ ctx->parent_dir = parent_dir;
+ ctx->parent_path = parent_path;
+ ctx->tail = tail;
+}
// callback to be fed int vdev_load_all_at.
// builds up the children listing of vdevfs_scandirat_context.parent_dir.
// if we find a directory, open it and enqueue its file descriptor to dir_queue.
// return 0 on success
// return -ENOMEM on OOM
-static int vdevfs_scandirat_context_callback( int dirfd, struct dirent* dent, void* cls ) {
-
- struct vdevfs_scandirat_context* ctx = (struct vdevfs_scandirat_context*)cls;
-
- int rc = 0;
- int fd = 0;
- struct stat sb;
- struct fskit_entry* child;
- char linkbuf[8193]; // for resolving an underlying symlink
- char const* method_name; // for logging
- char* joined_path = NULL;
- struct vdevfs_scandirat_queue* next = NULL;
-
- // skip . and ..
- if( strcmp( dent->d_name, "." ) == 0 || strcmp( dent->d_name, ".." ) == 0 ) {
+static int
+vdevfs_scandirat_context_callback (int dirfd, struct dirent *dent, void *cls)
+{
+
+ struct vdevfs_scandirat_context *ctx =
+ (struct vdevfs_scandirat_context *) cls;
+
+ int rc = 0;
+ int fd = 0;
+ struct stat sb;
+ struct fskit_entry *child;
+ char linkbuf[8193]; // for resolving an underlying symlink
+ char const *method_name; // for logging
+ char *joined_path = NULL;
+ struct vdevfs_scandirat_queue *next = NULL;
+
+ // skip . and ..
+ if (strcmp (dent->d_name, ".") == 0 || strcmp (dent->d_name, "..") == 0)
+ {
return 0;
- }
-
- // learn more...
- rc = fstatat( dirfd, dent->d_name, &sb, AT_SYMLINK_NOFOLLOW );
- if( rc != 0 ) {
-
+ }
+ // learn more...
+ rc = fstatat (dirfd, dent->d_name, &sb, AT_SYMLINK_NOFOLLOW);
+ if (rc != 0)
+ {
+
rc = -errno;
-
+
// mask errors; just log the serious ones
- if( rc != -ENOENT && rc != -EACCES ) {
-
- vdev_error("fstatat(%d, '%s') rc = %d\n", dirfd, dent->d_name, rc );
- }
-
+ if (rc != -ENOENT && rc != -EACCES)
+ {
+
+ vdev_error ("fstatat(%d, '%s') rc = %d\n", dirfd, dent->d_name, rc);
+ }
+
return 0;
- }
-
- // directory? get an fd to it if so, so we can keep scanning
- if( S_ISDIR( sb.st_mode ) ) {
-
+ }
+ // directory? get an fd to it if so, so we can keep scanning
+ if (S_ISDIR (sb.st_mode))
+ {
+
// try to get at it
- fd = openat( dirfd, dent->d_name, O_RDONLY );
- if( fd < 0 ) {
-
- rc = -errno;
-
- // mask errors; just log the serious ones
- if( rc != -ENOENT && rc != -EACCES ) {
-
- vdev_error("openat(%d, '%s') rc = %d\n", dirfd, dent->d_name, rc );
- }
-
- return 0;
- }
-
+ fd = openat (dirfd, dent->d_name, O_RDONLY);
+ if (fd < 0)
+ {
+
+ rc = -errno;
+
+ // mask errors; just log the serious ones
+ if (rc != -ENOENT && rc != -EACCES)
+ {
+
+ vdev_error ("openat(%d, '%s') rc = %d\n", dirfd,
+ dent->d_name, rc);
+ }
+
+ return 0;
+ }
// woo! save it
- joined_path = vdev_fullpath( ctx->parent_path, dent->d_name, NULL );
- if( joined_path == NULL ) {
-
- close( fd );
- return -ENOMEM;
- }
-
- next = VDEV_CALLOC( struct vdevfs_scandirat_queue, 1 );
- if( next == NULL ) {
-
- close( fd );
- free( joined_path );
- return -ENOMEM;
- }
-
+ joined_path = vdev_fullpath (ctx->parent_path, dent->d_name, NULL);
+ if (joined_path == NULL)
+ {
+
+ close (fd);
+ return -ENOMEM;
+ }
+
+ next = VDEV_CALLOC (struct vdevfs_scandirat_queue, 1);
+ if (next == NULL)
+ {
+
+ close (fd);
+ free (joined_path);
+ return -ENOMEM;
+ }
+
next->fd = fd;
next->path = joined_path;
next->next = NULL;
-
+
ctx->tail->next = next;
ctx->tail = ctx->tail->next;
- }
-
- // construct an inode for this entry
- child = fskit_entry_new();
- if( child == NULL ) {
-
+ }
+ // construct an inode for this entry
+ child = fskit_entry_new ();
+ if (child == NULL)
+ {
+
return -ENOMEM;
- }
-
- // regular file?
- if( S_ISREG( sb.st_mode ) ) {
-
+ }
+ // regular file?
+ if (S_ISREG (sb.st_mode))
+ {
+
method_name = "fskit_entry_init_file";
- rc = fskit_entry_init_file( child, sb.st_ino, sb.st_uid, sb.st_gid, sb.st_mode & 0777 );
- }
-
- // directory?
- else if( S_ISDIR( sb.st_mode ) ) {
-
+ rc = fskit_entry_init_file (child, sb.st_ino, sb.st_uid,
+ sb.st_gid, sb.st_mode & 0777);
+ }
+ // directory?
+ else if (S_ISDIR (sb.st_mode))
+ {
+
method_name = "fskit_entry_init_dir";
- rc = fskit_entry_init_dir( child, ctx->parent_dir, sb.st_ino, sb.st_uid, sb.st_gid, sb.st_mode & 0777 );
- }
-
- // named pipe?
- else if( S_ISFIFO( sb.st_mode ) ) {
-
+ rc = fskit_entry_init_dir (child, ctx->parent_dir, sb.st_ino,
+ sb.st_uid, sb.st_gid, sb.st_mode & 0777);
+ }
+ // named pipe?
+ else if (S_ISFIFO (sb.st_mode))
+ {
+
method_name = "fskit_entry_init_fifo";
- rc = fskit_entry_init_fifo( child, sb.st_ino, sb.st_uid, sb.st_gid, sb.st_mode & 0777 );
- }
-
- // unix domain socket?
- else if( S_ISSOCK( sb.st_mode ) ) {
-
+ rc = fskit_entry_init_fifo (child, sb.st_ino, sb.st_uid,
+ sb.st_gid, sb.st_mode & 0777);
+ }
+ // unix domain socket?
+ else if (S_ISSOCK (sb.st_mode))
+ {
+
method_name = "fskit_entry_init_sock";
- rc = fskit_entry_init_sock( child, sb.st_ino, sb.st_uid, sb.st_gid, sb.st_mode & 0777 );
- }
-
- // character device?
- else if( S_ISCHR( sb.st_mode ) ) {
-
+ rc = fskit_entry_init_sock (child, sb.st_ino, sb.st_uid,
+ sb.st_gid, sb.st_mode & 0777);
+ }
+ // character device?
+ else if (S_ISCHR (sb.st_mode))
+ {
+
method_name = "fskit_entry_init_chr";
- rc = fskit_entry_init_chr( child, sb.st_ino, sb.st_uid, sb.st_gid, sb.st_mode, sb.st_rdev );
- }
-
- // block device?
- else if( S_ISBLK( sb.st_mode ) ) {
-
+ rc = fskit_entry_init_chr (child, sb.st_ino, sb.st_uid,
+ sb.st_gid, sb.st_mode, sb.st_rdev);
+ }
+ // block device?
+ else if (S_ISBLK (sb.st_mode))
+ {
+
method_name = "fskit_entry_init_blk";
- rc = fskit_entry_init_blk( child, sb.st_ino, sb.st_uid, sb.st_gid, sb.st_mode, sb.st_rdev );
- }
-
- // symbolic link?
- else if( S_ISLNK( sb.st_mode ) ) {
-
+ rc = fskit_entry_init_blk (child, sb.st_ino, sb.st_uid,
+ sb.st_gid, sb.st_mode, sb.st_rdev);
+ }
+ // symbolic link?
+ else if (S_ISLNK (sb.st_mode))
+ {
+
// read the link first...
- memset( linkbuf, 0, 8193 );
-
- rc = readlinkat( dirfd, dent->d_name, linkbuf, 8192 );
- if( rc < 0 ) {
-
- rc = -errno;
-
- // mask error, but log serious ones. this link will not appear in the listing
- if( rc != -ENOENT && rc != -EACCES ) {
-
- vdev_error("readlinkat(%d, '%s') rc = %d\n", dirfd, dent->d_name, rc );
- }
-
- free( child );
- child = NULL;
-
- return 0;
- }
-
+ memset (linkbuf, 0, 8193);
+
+ rc = readlinkat (dirfd, dent->d_name, linkbuf, 8192);
+ if (rc < 0)
+ {
+
+ rc = -errno;
+
+ // mask error, but log serious ones. this link will not appear in the listing
+ if (rc != -ENOENT && rc != -EACCES)
+ {
+
+ vdev_error ("readlinkat(%d, '%s') rc = %d\n",
+ dirfd, dent->d_name, rc);
+ }
+
+ free (child);
+ child = NULL;
+
+ return 0;
+ }
+
method_name = "fskit_entry_init_symlink";
- rc = fskit_entry_init_symlink( child, sb.st_ino, linkbuf );
- }
-
- // success?
- if( rc != 0 ) {
-
- vdev_error("%s( on %d, '%s' ) rc = %d\n", method_name, dirfd, dent->d_name, rc );
-
- free( child );
+ rc = fskit_entry_init_symlink (child, sb.st_ino, linkbuf);
+ }
+ // success?
+ if (rc != 0)
+ {
+
+ vdev_error ("%s( on %d, '%s' ) rc = %d\n", method_name, dirfd,
+ dent->d_name, rc);
+
+ free (child);
child = NULL;
-
+
return rc;
- }
-
- // insert into parent
- rc = fskit_entry_attach_lowlevel( ctx->parent_dir, child, dent->d_name );
- if( rc != 0 ) {
-
+ }
+ // insert into parent
+ rc = fskit_entry_attach_lowlevel (ctx->parent_dir, child, dent->d_name);
+ if (rc != 0)
+ {
+
// OOM
- fskit_entry_destroy( ctx->core, child, false );
-
- free( child );
+ fskit_entry_destroy (ctx->core, child, false);
+
+ free (child);
child = NULL;
-
+
return rc;
- }
-
- // success!
- return rc;
+ }
+ // success!
+ return rc;
}
-
// load the filesystem with metadata from under the mountpoint
// return 0 on success
// return -ENOMEM on OOM
-static int vdevfs_dev_import( struct fskit_fuse_state* fs, void* arg ) {
-
- struct vdevfs* vdev = (struct vdevfs*)arg;
- int rc = 0;
- struct vdevfs_scandirat_queue* dir_queue = NULL;
- struct vdevfs_scandirat_queue* dir_queue_tail = NULL;
- struct vdevfs_scandirat_queue* ptr = NULL;
- struct fskit_entry* dir_ent = NULL;
-
- struct vdevfs_scandirat_context scan_context;
-
- char* root = vdev_strdup_or_null("/");
- if( root == NULL ) {
+static int
+vdevfs_dev_import (struct fskit_fuse_state *fs, void *arg)
+{
+
+ struct vdevfs *vdev = (struct vdevfs *) arg;
+ int rc = 0;
+ struct vdevfs_scandirat_queue *dir_queue = NULL;
+ struct vdevfs_scandirat_queue *dir_queue_tail = NULL;
+ struct vdevfs_scandirat_queue *ptr = NULL;
+ struct fskit_entry *dir_ent = NULL;
+
+ struct vdevfs_scandirat_context scan_context;
+
+ char *root = vdev_strdup_or_null ("/");
+ if (root == NULL)
+ {
return -ENOMEM;
- }
-
- int root_fd = dup( vdev->mountpoint_dirfd );
- if( root_fd < 0 ) {
-
- vdev_error("dup(%d) rc = %d\n", vdev->mountpoint_dirfd, rc );
+ }
+
+ int root_fd = dup (vdev->mountpoint_dirfd);
+ if (root_fd < 0)
+ {
+
+ vdev_error ("dup(%d) rc = %d\n", vdev->mountpoint_dirfd, rc);
rc = -errno;
- free( root );
+ free (root);
return rc;
- }
-
- // start at the mountpoint
- dir_queue = VDEV_CALLOC( struct vdevfs_scandirat_queue, 1 );
- if( dir_queue == NULL ) {
-
- free( root );
- close( root_fd );
+ }
+ // start at the mountpoint
+ dir_queue = VDEV_CALLOC (struct vdevfs_scandirat_queue, 1);
+ if (dir_queue == NULL)
+ {
+
+ free (root);
+ close (root_fd);
return -ENOMEM;
- }
-
- dir_queue->fd = root_fd;
- dir_queue->path = root;
- dir_queue->next = NULL;
-
- dir_queue_tail = dir_queue;
-
- while( dir_queue != NULL ) {
-
+ }
+
+ dir_queue->fd = root_fd;
+ dir_queue->path = root;
+ dir_queue->next = NULL;
+
+ dir_queue_tail = dir_queue;
+
+ while (dir_queue != NULL)
+ {
+
int dirfd = dir_queue->fd;
- char* dirpath = dir_queue->path;
-
+ char *dirpath = dir_queue->path;
+
// look up this entry
- dir_ent = fskit_entry_resolve_path( fskit_fuse_get_core( vdev->fs ), dirpath, 0, 0, true, &rc );
- if( rc != 0 ) {
-
- // shouldn't happen--we're going breadth-first
- vdev_error("fskit_entry_resolve_path('%s') rc = %d\n", dirpath, rc );
- break;
- }
-
+ dir_ent =
+ fskit_entry_resolve_path (fskit_fuse_get_core (vdev->fs),
+ dirpath, 0, 0, true, &rc);
+ if (rc != 0)
+ {
+
+ // shouldn't happen--we're going breadth-first
+ vdev_error ("fskit_entry_resolve_path('%s') rc = %d\n",
+ dirpath, rc);
+ break;
+ }
// make a scan context
- vdevfs_scandirat_context_init( &scan_context, fskit_fuse_get_core( vdev->fs ), dir_ent, dirpath, dir_queue_tail );
-
+ vdevfs_scandirat_context_init (&scan_context,
+ fskit_fuse_get_core (vdev->fs),
+ dir_ent, dirpath, dir_queue_tail);
+
// scan this directory
- rc = vdev_load_all_at( dirfd, vdevfs_scandirat_context_callback, &scan_context );
-
- fskit_entry_unlock( dir_ent );
-
- if( rc != 0 ) {
-
- // failed
- vdev_error("vdev_load_all_at(%d, '%s') rc = %d\n", dirfd, dirpath, rc );
- break;
- }
-
+ rc = vdev_load_all_at (dirfd, vdevfs_scandirat_context_callback,
+ &scan_context);
+
+ fskit_entry_unlock (dir_ent);
+
+ if (rc != 0)
+ {
+
+ // failed
+ vdev_error ("vdev_load_all_at(%d, '%s') rc = %d\n",
+ dirfd, dirpath, rc);
+ break;
+ }
// advance tail pointer
dir_queue_tail = scan_context.tail;
-
+
// advance to next directory
- close( dirfd );
- free( dirpath );
+ close (dirfd);
+ free (dirpath);
dirpath = NULL;
-
+
ptr = dir_queue;
dir_queue = dir_queue->next;
-
- memset( ptr, 0, sizeof(struct vdevfs_scandirat_queue) );
- free( ptr );
- }
-
- // free any remaining directory state
- for( struct vdevfs_scandirat_queue* ptr = dir_queue; ptr != NULL; ) {
-
- int fd = ptr->fd;
- char* path = ptr->path;
- struct vdevfs_scandirat_queue* old_ptr = ptr;
-
- close( fd );
- free( path );
-
- ptr = ptr->next;
-
- memset( old_ptr, 0, sizeof(struct vdevfs_scandirat_queue) );
- free( old_ptr );
- }
-
- return rc;
-}
+ memset (ptr, 0, sizeof (struct vdevfs_scandirat_queue));
+ free (ptr);
+ }
+
+ // free any remaining directory state
+ for (struct vdevfs_scandirat_queue * ptr = dir_queue; ptr != NULL;)
+ {
+
+ int fd = ptr->fd;
+ char *path = ptr->path;
+ struct vdevfs_scandirat_queue *old_ptr = ptr;
+
+ close (fd);
+ free (path);
+
+ ptr = ptr->next;
+
+ memset (old_ptr, 0, sizeof (struct vdevfs_scandirat_queue));
+ free (old_ptr);
+ }
+
+ return rc;
+}
// get the mountpoint option, by parsing the FUSE command line
-static int vdev_get_mountpoint( int fuse_argc, char** fuse_argv, char** ret_mountpoint ) {
-
- struct fuse_args fargs = FUSE_ARGS_INIT(fuse_argc, fuse_argv);
- char* mountpoint = NULL;
- int unused_1;
- int unused_2;
- int rc = 0;
-
- // parse command-line...
- rc = fuse_parse_cmdline( &fargs, &mountpoint, &unused_1, &unused_2 );
- if( rc < 0 ) {
-
- vdev_error("fuse_parse_cmdline rc = %d\n", rc );
- fuse_opt_free_args(&fargs);
+static int
+vdev_get_mountpoint (int fuse_argc, char **fuse_argv, char **ret_mountpoint)
+{
+
+ struct fuse_args fargs = FUSE_ARGS_INIT (fuse_argc, fuse_argv);
+ char *mountpoint = NULL;
+ int unused_1;
+ int unused_2;
+ int rc = 0;
+
+ // parse command-line...
+ rc = fuse_parse_cmdline (&fargs, &mountpoint, &unused_1, &unused_2);
+ if (rc < 0)
+ {
+
+ vdev_error ("fuse_parse_cmdline rc = %d\n", rc);
+ fuse_opt_free_args (&fargs);
return rc;
- }
-
- else {
-
- if( mountpoint != NULL ) {
-
- *ret_mountpoint = strdup( mountpoint );
- free( mountpoint );
-
- rc = 0;
- }
- else {
- rc = -ENOMEM;
- }
-
- fuse_opt_free_args(&fargs);
- }
-
- return 0;
-}
+ }
+
+ else
+ {
+
+ if (mountpoint != NULL)
+ {
+ *ret_mountpoint = strdup (mountpoint);
+ free (mountpoint);
+
+ rc = 0;
+ }
+ else
+ {
+ rc = -ENOMEM;
+ }
+
+ fuse_opt_free_args (&fargs);
+ }
+
+ return 0;
+}
// initialize the filesystem front-end
// call after vdev_init
// return 0 on success
// return -ENOMEM on OOM
// return negative on error
-int vdevfs_init( struct vdevfs* vdev, int argc, char** argv ) {
-
- int rc = 0;
- int rh = 0;
- struct fskit_core* core = NULL;
- int fuse_argc = 0;
- char** fuse_argv = NULL;
- int dirfd = 0;
-
- // library setup
- vdev_setup_global();
-
- struct fskit_fuse_state* fs = fskit_fuse_state_new();
-
- if( fs == NULL ) {
+int
+vdevfs_init (struct vdevfs *vdev, int argc, char **argv)
+{
+
+ int rc = 0;
+ int rh = 0;
+ struct fskit_core *core = NULL;
+ int fuse_argc = 0;
+ char **fuse_argv = NULL;
+ int dirfd = 0;
+
+ // library setup
+ vdev_setup_global ();
+
+ struct fskit_fuse_state *fs = fskit_fuse_state_new ();
+
+ if (fs == NULL)
+ {
return -ENOMEM;
- }
-
- fuse_argv = VDEV_CALLOC( char*, argc + 5 );
-
- if( fuse_argv == NULL ) {
-
- free( fs );
+ }
+
+ fuse_argv = VDEV_CALLOC (char *, argc + 5);
+
+ if (fuse_argv == NULL)
+ {
+
+ free (fs);
return -ENOMEM;
- }
-
- // load config
- vdev->config = VDEV_CALLOC( struct vdev_config, 1 );
- if( vdev->config == NULL ) {
-
- free( fs );
- free( fuse_argv );
+ }
+ // load config
+ vdev->config = VDEV_CALLOC (struct vdev_config, 1);
+ if (vdev->config == NULL)
+ {
+
+ free (fs);
+ free (fuse_argv);
return -ENOMEM;
- }
-
- // init config
- rc = vdev_config_init( vdev->config );
- if( rc != 0 ) {
-
- vdev_error("vdev_config_init rc = %d\n", rc );
-
- vdevfs_shutdown( vdev );
- free( fs );
- free( fuse_argv );
+ }
+ // init config
+ rc = vdev_config_init (vdev->config);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_config_init rc = %d\n", rc);
+
+ vdevfs_shutdown (vdev);
+ free (fs);
+ free (fuse_argv);
return rc;
- }
-
- // parse opts
- rc = vdev_config_load_from_args( vdev->config, argc, argv, &fuse_argc, fuse_argv );
- if( rc != 0 ) {
-
- vdev_error("vdev_opts_parse rc = %d\n", rc );
-
- vdev_config_usage( argv[0] );
-
- free( fs );
- free( fuse_argv );
- vdevfs_shutdown( vdev );
+ }
+ // parse opts
+ rc = vdev_config_load_from_args (vdev->config, argc, argv, &fuse_argc,
+ fuse_argv);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_opts_parse rc = %d\n", rc);
+
+ vdev_config_usage (argv[0]);
+
+ free (fs);
+ free (fuse_argv);
+ vdevfs_shutdown (vdev);
return rc;
- }
-
- // get the mountpoint, but from FUSE
- if( vdev->config->mountpoint != NULL ) {
- free( vdev->config->mountpoint );
- }
-
- rc = vdev_get_mountpoint( fuse_argc, fuse_argv, &vdev->config->mountpoint );
- if( rc != 0 ) {
-
- vdev_error("vdev_get_mountpoint rc = %d\n", rc );
-
- vdev_config_usage( argv[0] );
-
- free( fs );
- free( fuse_argv );
+ }
+ // get the mountpoint, but from FUSE
+ if (vdev->config->mountpoint != NULL)
+ {
+ free (vdev->config->mountpoint);
+ }
+
+ rc = vdev_get_mountpoint (fuse_argc, fuse_argv, &vdev->config->mountpoint);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_get_mountpoint rc = %d\n", rc);
+
+ vdev_config_usage (argv[0]);
+
+ free (fs);
+ free (fuse_argv);
return rc;
- }
-
- vdev_set_debug_level( vdev->config->debug_level );
- vdev_set_error_level( vdev->config->error_level );
-
- vdev_debug("Config file: %s\n", vdev->config->config_path );
-
- rc = vdev_config_load( vdev->config->config_path, vdev->config );
- if( rc != 0 ) {
-
- vdev_error("vdev_config_load('%s') rc = %d\n", vdev->config->config_path, rc );
-
- vdevfs_shutdown( vdev );
- free( fs );
- free( fuse_argv );
+ }
+
+ vdev_set_debug_level (vdev->config->debug_level);
+ vdev_set_error_level (vdev->config->error_level);
+
+ vdev_debug ("Config file: %s\n", vdev->config->config_path);
+
+ rc = vdev_config_load (vdev->config->config_path, vdev->config);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_config_load('%s') rc = %d\n",
+ vdev->config->config_path, rc);
+
+ vdevfs_shutdown (vdev);
+ free (fs);
+ free (fuse_argv);
return rc;
- }
-
- vdev_debug("vdev ACLs dir: %s\n", vdev->config->acls_dir );
-
- // force -odev, since we'll create device nodes
- fuse_argv[fuse_argc] = (char*)vdev_fuse_odev;
- fuse_argc++;
-
- // force -oallow_other, since we'll want to expose this to everyone
- fuse_argv[fuse_argc] = (char*)vdev_fuse_allow_other;
- fuse_argc++;
-
- // force -ononempty, since we'll want to import the underlying filesystem
- fuse_argv[fuse_argc] = (char*)vdev_fuse_ononempty;
- fuse_argc++;
-
- vdev->mountpoint = vdev_strdup_or_null( vdev->config->mountpoint );
-
- if( vdev->mountpoint == NULL ) {
-
- vdev_error("Failed to set mountpoint, config.mountpount = '%s'\n", vdev->config->mountpoint );
-
- vdevfs_shutdown( vdev );
- free( fuse_argv );
- free( fs );
+ }
+
+ vdev_debug ("vdev ACLs dir: %s\n", vdev->config->acls_dir);
+
+ // force -odev, since we'll create device nodes
+ fuse_argv[fuse_argc] = (char *) vdev_fuse_odev;
+ fuse_argc++;
+
+ // force -oallow_other, since we'll want to expose this to everyone
+ fuse_argv[fuse_argc] = (char *) vdev_fuse_allow_other;
+ fuse_argc++;
+
+ // force -ononempty, since we'll want to import the underlying filesystem
+ fuse_argv[fuse_argc] = (char *) vdev_fuse_ononempty;
+ fuse_argc++;
+
+ vdev->mountpoint = vdev_strdup_or_null (vdev->config->mountpoint);
+
+ if (vdev->mountpoint == NULL)
+ {
+
+ vdev_error
+ ("Failed to set mountpoint, config.mountpount = '%s'\n",
+ vdev->config->mountpoint);
+
+ vdevfs_shutdown (vdev);
+ free (fuse_argv);
+ free (fs);
return -EINVAL;
- }
- else {
-
- vdev_debug("mountpoint: %s\n", vdev->mountpoint );
- }
-
- vdev->argc = argc;
- vdev->argv = argv;
- vdev->fuse_argc = fuse_argc;
- vdev->fuse_argv = fuse_argv;
-
- fskit_set_debug_level( vdev->config->debug_level );
- fskit_set_error_level( vdev->config->error_level );
-
- // get mountpoint directory
- dirfd = open( vdev->mountpoint, O_DIRECTORY );
- if( dirfd < 0 ) {
-
+ }
+ else
+ {
+
+ vdev_debug ("mountpoint: %s\n", vdev->mountpoint);
+ }
+
+ vdev->argc = argc;
+ vdev->argv = argv;
+ vdev->fuse_argc = fuse_argc;
+ vdev->fuse_argv = fuse_argv;
+
+ fskit_set_debug_level (vdev->config->debug_level);
+ fskit_set_error_level (vdev->config->error_level);
+
+ // get mountpoint directory
+ dirfd = open (vdev->mountpoint, O_DIRECTORY);
+ if (dirfd < 0)
+ {
+
rc = -errno;
- vdev_error("open('%s') rc = %d\n", vdev->mountpoint, rc );
-
- free( fs );
- vdevfs_shutdown( vdev );
+ vdev_error ("open('%s') rc = %d\n", vdev->mountpoint, rc);
+
+ free (fs);
+ vdevfs_shutdown (vdev);
return rc;
- }
-
- vdev->mountpoint_dirfd = dirfd;
-
- // set up fskit
- rc = fskit_fuse_init( fs, vdev );
- if( rc != 0 ) {
-
- vdev_error("fskit_fuse_init rc = %d\n", rc );
- free( fs );
- vdevfs_shutdown( vdev );
+ }
+
+ vdev->mountpoint_dirfd = dirfd;
+
+ // set up fskit
+ rc = fskit_fuse_init (fs, vdev);
+ if (rc != 0)
+ {
+
+ vdev_error ("fskit_fuse_init rc = %d\n", rc);
+ free (fs);
+ vdevfs_shutdown (vdev);
return rc;
- }
-
- // load ACLs
- rc = vdev_acl_load_all( vdev->config->acls_dir, &vdev->acls, &vdev->num_acls );
- if( rc != 0 ) {
-
- vdev_error("vdev_acl_load_all('%s') rc = %d\n", vdev->config->acls_dir, rc );
-
- fskit_fuse_shutdown( fs, NULL );
- free( fs );
- vdevfs_shutdown( vdev );
+ }
+ // load ACLs
+ rc = vdev_acl_load_all (vdev->config->acls_dir, &vdev->acls,
+ &vdev->num_acls);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_acl_load_all('%s') rc = %d\n",
+ vdev->config->acls_dir, rc);
+
+ fskit_fuse_shutdown (fs, NULL);
+ free (fs);
+ vdevfs_shutdown (vdev);
return rc;
- }
-
- // make sure the fs can access its methods through the VFS
- fskit_fuse_setting_enable( fs, FSKIT_FUSE_SET_FS_ACCESS );
-
- core = fskit_fuse_get_core( fs );
-
- // add handlers.
- rh = fskit_route_readdir( core, FSKIT_ROUTE_ANY, vdevfs_readdir, FSKIT_CONCURRENT );
- if( rh < 0 ) {
-
- vdev_error("fskit_route_readdir(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
+ }
+ // make sure the fs can access its methods through the VFS
+ fskit_fuse_setting_enable (fs, FSKIT_FUSE_SET_FS_ACCESS);
+
+ core = fskit_fuse_get_core (fs);
+
+ // add handlers.
+ rh = fskit_route_readdir (core, FSKIT_ROUTE_ANY, vdevfs_readdir,
+ FSKIT_CONCURRENT);
+ if (rh < 0)
+ {
+
+ vdev_error ("fskit_route_readdir(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh);
goto vdev_route_fail;
- }
-
- rh = fskit_route_stat( core, FSKIT_ROUTE_ANY, vdevfs_stat, FSKIT_CONCURRENT );
- if( rh < 0 ) {
-
- vdev_error("fskit_route_stat(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
+ }
+
+ rh = fskit_route_stat (core, FSKIT_ROUTE_ANY, vdevfs_stat,
+ FSKIT_CONCURRENT);
+ if (rh < 0)
+ {
+
+ vdev_error ("fskit_route_stat(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh);
goto vdev_route_fail;
- }
-
- rh = fskit_route_mknod( core, FSKIT_ROUTE_ANY, vdevfs_mknod, FSKIT_CONCURRENT );
- if( rc < 0 ) {
-
- vdev_error("fskit_route_mknod(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
+ }
+
+ rh = fskit_route_mknod (core, FSKIT_ROUTE_ANY, vdevfs_mknod,
+ FSKIT_CONCURRENT);
+ if (rc < 0)
+ {
+
+ vdev_error ("fskit_route_mknod(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh);
goto vdev_route_fail;
- }
-
- rh = fskit_route_mkdir( core, FSKIT_ROUTE_ANY, vdevfs_mkdir, FSKIT_CONCURRENT );
- if( rh < 0 ) {
-
- vdev_error("fskit_route_mkdir(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
+ }
+
+ rh = fskit_route_mkdir (core, FSKIT_ROUTE_ANY, vdevfs_mkdir,
+ FSKIT_CONCURRENT);
+ if (rh < 0)
+ {
+
+ vdev_error ("fskit_route_mkdir(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh);
goto vdev_route_fail;
- }
-
- rh = fskit_route_create( core, FSKIT_ROUTE_ANY, vdevfs_create, FSKIT_CONCURRENT );
- if( rh < 0 ) {
-
- vdev_error("fskit_route_create(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
+ }
+
+ rh = fskit_route_create (core, FSKIT_ROUTE_ANY, vdevfs_create,
+ FSKIT_CONCURRENT);
+ if (rh < 0)
+ {
+
+ vdev_error ("fskit_route_create(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh);
goto vdev_route_fail;
- }
-
- rh = fskit_route_open( core, FSKIT_ROUTE_ANY, vdevfs_open, FSKIT_CONCURRENT );
- if( rh < 0 ) {
-
- vdev_error("fskit_route_open(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
+ }
+
+ rh = fskit_route_open (core, FSKIT_ROUTE_ANY, vdevfs_open,
+ FSKIT_CONCURRENT);
+ if (rh < 0)
+ {
+
+ vdev_error ("fskit_route_open(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh);
goto vdev_route_fail;
- }
-
- rh = fskit_route_read( core, FSKIT_ROUTE_ANY, vdevfs_read, FSKIT_CONCURRENT );
- if( rh < 0 ) {
-
- vdev_error("fskit_route_read(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
+ }
+
+ rh = fskit_route_read (core, FSKIT_ROUTE_ANY, vdevfs_read,
+ FSKIT_CONCURRENT);
+ if (rh < 0)
+ {
+
+ vdev_error ("fskit_route_read(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh);
goto vdev_route_fail;
- }
-
- rh = fskit_route_write( core, FSKIT_ROUTE_ANY, vdevfs_write, FSKIT_CONCURRENT );
- if( rh < 0 ) {
-
- vdev_error("fskit_route_write(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
+ }
+
+ rh = fskit_route_write (core, FSKIT_ROUTE_ANY, vdevfs_write,
+ FSKIT_CONCURRENT);
+ if (rh < 0)
+ {
+
+ vdev_error ("fskit_route_write(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh);
goto vdev_route_fail;
- }
-
- rh = fskit_route_close( core, FSKIT_ROUTE_ANY, vdevfs_close, FSKIT_CONCURRENT );
- if( rh < 0 ) {
-
- vdev_error("fskit_route_close(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
+ }
+
+ rh = fskit_route_close (core, FSKIT_ROUTE_ANY, vdevfs_close,
+ FSKIT_CONCURRENT);
+ if (rh < 0)
+ {
+
+ vdev_error ("fskit_route_close(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh);
goto vdev_route_fail;
- }
-
- rh = fskit_route_sync( core, FSKIT_ROUTE_ANY, vdevfs_sync, FSKIT_CONCURRENT );
- if( rh < 0 ) {
-
- vdev_error("fskit_route_sync(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
+ }
+
+ rh = fskit_route_sync (core, FSKIT_ROUTE_ANY, vdevfs_sync,
+ FSKIT_CONCURRENT);
+ if (rh < 0)
+ {
+
+ vdev_error ("fskit_route_sync(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh);
goto vdev_route_fail;
- }
-
- rh = fskit_route_detach( core, FSKIT_ROUTE_ANY, vdevfs_detach, FSKIT_CONCURRENT );
- if( rh < 0 ) {
-
- vdev_error("fskit_route_detach(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
+ }
+
+ rh = fskit_route_detach (core, FSKIT_ROUTE_ANY, vdevfs_detach,
+ FSKIT_CONCURRENT);
+ if (rh < 0)
+ {
+
+ vdev_error ("fskit_route_detach(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh);
goto vdev_route_fail;
- }
-
- vdev->fs = fs;
- vdev->close_rh = rh;
-
- // set the root to be owned by the effective UID and GID of user
- fskit_chown( core, "/", 0, 0, geteuid(), getegid() );
-
- // import the underlying filesystem once we're mounted, but before taking requests.
- rc = fskit_fuse_postmount_callback( fs, vdevfs_dev_import, vdev );
- if( rc != 0 ) {
-
- vdev_error("fskit_fuse_postmount_callback() rc = %d\n", rc );
-
+ }
+
+ vdev->fs = fs;
+ vdev->close_rh = rh;
+
+ // set the root to be owned by the effective UID and GID of user
+ fskit_chown (core, "/", 0, 0, geteuid (), getegid ());
+
+ // import the underlying filesystem once we're mounted, but before taking requests.
+ rc = fskit_fuse_postmount_callback (fs, vdevfs_dev_import, vdev);
+ if (rc != 0)
+ {
+
+ vdev_error ("fskit_fuse_postmount_callback() rc = %d\n", rc);
+
vdev->fs = NULL;
goto vdev_route_fail;
- }
-
- return 0;
+ }
+
+ return 0;
vdev_route_fail:
- fskit_fuse_shutdown( fs, NULL );
- free( fs );
- vdevfs_shutdown( vdev );
- return rh;
+ fskit_fuse_shutdown (fs, NULL);
+ free (fs);
+ vdevfs_shutdown (vdev);
+ return rh;
}
-
// main loop for vdev frontend
-int vdevfs_main( struct vdevfs* vdev, int fuse_argc, char** fuse_argv ) {
-
- int rc = 0;
-
- rc = fskit_fuse_main( vdev->fs, fuse_argc, fuse_argv );
-
- return rc;
-}
+int
+vdevfs_main (struct vdevfs *vdev, int fuse_argc, char **fuse_argv)
+{
+ int rc = 0;
+
+ rc = fskit_fuse_main (vdev->fs, fuse_argc, fuse_argv);
+
+ return rc;
+}
// shut down the front-end
-int vdevfs_shutdown( struct vdevfs* vdev ) {
-
- if( vdev->fs != NULL ) {
-
+int
+vdevfs_shutdown (struct vdevfs *vdev)
+{
+
+ if (vdev->fs != NULL)
+ {
+
// stop processing unlink() requests, since the filesystem itself will unlink all files when it frees itself up.
- fskit_unroute_detach( fskit_fuse_get_core( vdev->fs ), vdev->close_rh );
-
- fskit_fuse_shutdown( vdev->fs, NULL );
- free( vdev->fs );
+ fskit_unroute_detach (fskit_fuse_get_core (vdev->fs), vdev->close_rh);
+
+ fskit_fuse_shutdown (vdev->fs, NULL);
+ free (vdev->fs);
vdev->fs = NULL;
- }
-
- if( vdev->acls != NULL ) {
- vdev_acl_free_all( vdev->acls, vdev->num_acls );
- }
-
- if( vdev->config != NULL ) {
- vdev_config_free( vdev->config );
- free( vdev->config );
+ }
+
+ if (vdev->acls != NULL)
+ {
+ vdev_acl_free_all (vdev->acls, vdev->num_acls);
+ }
+
+ if (vdev->config != NULL)
+ {
+ vdev_config_free (vdev->config);
+ free (vdev->config);
vdev->config = NULL;
- }
-
- if( vdev->mountpoint != NULL ) {
-
- free( vdev->mountpoint );
+ }
+
+ if (vdev->mountpoint != NULL)
+ {
+
+ free (vdev->mountpoint);
vdev->mountpoint = NULL;
- }
-
- if( vdev->fuse_argv != NULL ) {
-
- free( vdev->fuse_argv );
+ }
+
+ if (vdev->fuse_argv != NULL)
+ {
+
+ free (vdev->fuse_argv);
vdev->fuse_argc = 0;
- vdev->fuse_argv = NULL;
- }
-
- if( vdev->mountpoint_dirfd >= 0 ) {
-
- close( vdev->mountpoint_dirfd );
+ vdev->fuse_argv = NULL;
+ }
+
+ if (vdev->mountpoint_dirfd >= 0)
+ {
+
+ close (vdev->mountpoint_dirfd);
vdev->mountpoint_dirfd = -1;
- }
-
- memset( vdev, 0, sizeof(struct vdevfs) );
-
- return 0;
-}
+ }
+ memset (vdev, 0, sizeof (struct vdevfs));
+
+ return 0;
+}
// for creating, opening, or stating files, verify that the caller is permitted according to our ACLs
// return 0 on success
// return -EPERM if denied
// return other -errno on error
-static int vdevfs_access_check( struct vdevfs* vdev, struct fskit_fuse_state* fs_state, char const* method_name, char const* path ) {
-
- int rc = 0;
- pid_t pid = 0;
- uid_t uid = 0;
- gid_t gid = 0;
- struct stat sb;
- struct pstat* ps = NULL;
-
- memset( &sb, 0, sizeof(struct stat) );
- sb.st_mode = 0777;
-
- // stat the calling process
- pid = fskit_fuse_get_pid();
- uid = fskit_fuse_get_uid( fs_state );
- gid = fskit_fuse_get_gid( fs_state );
-
- ps = pstat_new();
- if( ps == NULL ) {
+static int
+vdevfs_access_check (struct vdevfs *vdev,
+ struct fskit_fuse_state *fs_state,
+ char const *method_name, char const *path)
+{
+
+ int rc = 0;
+ pid_t pid = 0;
+ uid_t uid = 0;
+ gid_t gid = 0;
+ struct stat sb;
+ struct pstat *ps = NULL;
+
+ memset (&sb, 0, sizeof (struct stat));
+ sb.st_mode = 0777;
+
+ // stat the calling process
+ pid = fskit_fuse_get_pid ();
+ uid = fskit_fuse_get_uid (fs_state);
+ gid = fskit_fuse_get_gid (fs_state);
+
+ ps = pstat_new ();
+ if (ps == NULL)
+ {
return -ENOMEM;
- }
-
- vdev_debug("%s('%s') from user %d group %d task %d\n", method_name, path, uid, gid, pid );
-
- // see who's asking
- rc = pstat( pid, ps, 0 );
- if( rc != 0 ) {
-
- vdev_error("pstat(%d) rc = %d\n", pid, rc );
- pstat_free( ps );
+ }
+
+ vdev_debug ("%s('%s') from user %d group %d task %d\n", method_name,
+ path, uid, gid, pid);
+
+ // see who's asking
+ rc = pstat (pid, ps, 0);
+ if (rc != 0)
+ {
+
+ vdev_error ("pstat(%d) rc = %d\n", pid, rc);
+ pstat_free (ps);
return -EIO;
- }
-
- // apply the ACLs on the stat buffer
- rc = vdev_acl_apply_all( vdev->config, vdev->acls, vdev->num_acls, path, ps, uid, gid, &sb );
- pstat_free( ps );
-
- if( rc < 0 ) {
-
- vdev_error("vdev_acl_apply_all(%s, uid=%d, gid=%d, pid=%d) rc = %d\n", path, uid, gid, pid, rc );
+ }
+ // apply the ACLs on the stat buffer
+ rc = vdev_acl_apply_all (vdev->config, vdev->acls, vdev->num_acls, path,
+ ps, uid, gid, &sb);
+ pstat_free (ps);
+
+ if (rc < 0)
+ {
+
+ vdev_error
+ ("vdev_acl_apply_all(%s, uid=%d, gid=%d, pid=%d) rc = %d\n",
+ path, uid, gid, pid, rc);
return -EIO;
- }
-
- // omit entirely?
- if( rc == 0 || (sb.st_mode & 0777) == 0 ) {
-
+ }
+ // omit entirely?
+ if (rc == 0 || (sb.st_mode & 0777) == 0)
+ {
+
// filter
- vdev_debug("DENY '%s'\n", path );
+ vdev_debug ("DENY '%s'\n", path);
return -EPERM;
- }
- else {
-
+ }
+ else
+ {
+
// accept!
return 0;
- }
+ }
}
-
// mknod: create the device node as normal, but also write to the underlying filesystem as an emergency counter-measure
-int vdevfs_mknod( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, mode_t mode, dev_t dev, void** inode_cls ) {
-
- int rc = 0;
- struct vdevfs* vdev = (struct vdevfs*)fskit_core_get_user_data( core );
- struct fskit_fuse_state* fs_state = fskit_fuse_get_state();
- char const* path = NULL;
-
- rc = vdevfs_access_check( vdev, fs_state, "mknod", fskit_route_metadata_get_path( grp ) );
- if( rc < 0 ) {
-
+int
+vdevfs_mknod (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, mode_t mode, dev_t dev,
+ void **inode_cls)
+{
+
+ int rc = 0;
+ struct vdevfs *vdev = (struct vdevfs *) fskit_core_get_user_data (core);
+ struct fskit_fuse_state *fs_state = fskit_fuse_get_state ();
+ char const *path = NULL;
+
+ rc = vdevfs_access_check (vdev, fs_state, "mknod",
+ fskit_route_metadata_get_path (grp));
+ if (rc < 0)
+ {
+
// denied!
return -EACCES;
- }
-
- // must be relative path
- path = fskit_route_metadata_get_path( grp );
- while( *path == '/' && *path != '\0' ) {
+ }
+ // must be relative path
+ path = fskit_route_metadata_get_path (grp);
+ while (*path == '/' && *path != '\0')
+ {
path++;
- }
-
- if( *path == '\0' ) {
+ }
+
+ if (*path == '\0')
+ {
path = ".";
- }
-
- rc = mknodat( vdev->mountpoint_dirfd, path, dev, mode );
-
- if( rc != 0 ) {
-
+ }
+
+ rc = mknodat (vdev->mountpoint_dirfd, path, dev, mode);
+
+ if (rc != 0)
+ {
+
rc = -errno;
- vdev_error("mknodat('%s', '%s') rc = %d\n", vdev->mountpoint, path, rc );
-
+ vdev_error ("mknodat('%s', '%s') rc = %d\n", vdev->mountpoint,
+ path, rc);
+
return rc;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// mkdir: create the directory as normal, but also write to the underlying filesystem as an emergency counter-measure
-int vdevfs_mkdir( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, mode_t mode, void** inode_cls ) {
-
- int rc = 0;
- struct vdevfs* vdev = (struct vdevfs*)fskit_core_get_user_data( core );
- struct fskit_fuse_state* fs_state = fskit_fuse_get_state();
- char const* path = NULL;
-
- rc = vdevfs_access_check( vdev, fs_state, "mkdir", fskit_route_metadata_get_path( grp ) );
- if( rc < 0 ) {
-
+int
+vdevfs_mkdir (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, mode_t mode, void **inode_cls)
+{
+
+ int rc = 0;
+ struct vdevfs *vdev = (struct vdevfs *) fskit_core_get_user_data (core);
+ struct fskit_fuse_state *fs_state = fskit_fuse_get_state ();
+ char const *path = NULL;
+
+ rc = vdevfs_access_check (vdev, fs_state, "mkdir",
+ fskit_route_metadata_get_path (grp));
+ if (rc < 0)
+ {
+
// denied!
return -EACCES;
- }
-
- // must be relative path
- path = fskit_route_metadata_get_path( grp );
- while( *path == '/' && *path != '\0' ) {
+ }
+ // must be relative path
+ path = fskit_route_metadata_get_path (grp);
+ while (*path == '/' && *path != '\0')
+ {
path++;
- }
-
- if( *path == '\0' ) {
+ }
+
+ if (*path == '\0')
+ {
path = ".";
- }
-
- rc = mkdirat( vdev->mountpoint_dirfd, path, mode );
-
- if( rc != 0 ) {
-
+ }
+
+ rc = mkdirat (vdev->mountpoint_dirfd, path, mode);
+
+ if (rc != 0)
+ {
+
rc = -errno;
- vdev_error("mkdirat('%s', '%s') rc = %d\n", vdev->mountpoint, path, rc );
-
+ vdev_error ("mkdirat('%s', '%s') rc = %d\n", vdev->mountpoint,
+ path, rc);
+
return rc;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// creat: create the file as usual, but also write to the underlying filesystem as an emergency counter-measure
// NOTE: since this is backed by FUSE, this handler will only be called for regular files
-int vdevfs_create( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, mode_t mode, void** inode_cls, void** handle_cls ) {
-
- int fd = 0;
- struct vdevfs* vdev = (struct vdevfs*)fskit_core_get_user_data( core );
- struct fskit_fuse_state* fs_state = fskit_fuse_get_state();
- char const* path = NULL;
- int rc = 0;
-
- rc = vdevfs_access_check( vdev, fs_state, "create", fskit_route_metadata_get_path( grp ) );
- if( rc < 0 ) {
-
+int
+vdevfs_create (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, mode_t mode, void **inode_cls,
+ void **handle_cls)
+{
+
+ int fd = 0;
+ struct vdevfs *vdev = (struct vdevfs *) fskit_core_get_user_data (core);
+ struct fskit_fuse_state *fs_state = fskit_fuse_get_state ();
+ char const *path = NULL;
+ int rc = 0;
+
+ rc = vdevfs_access_check (vdev, fs_state, "create",
+ fskit_route_metadata_get_path (grp));
+ if (rc < 0)
+ {
+
// denied!
return -EACCES;
- }
-
- // must be relative path
- path = fskit_route_metadata_get_path( grp );
- while( *path == '/' && *path != '\0' ) {
+ }
+ // must be relative path
+ path = fskit_route_metadata_get_path (grp);
+ while (*path == '/' && *path != '\0')
+ {
path++;
- }
-
- if( *path == '\0' ) {
+ }
+
+ if (*path == '\0')
+ {
path = ".";
- }
-
- // success!
- fd = openat( vdev->mountpoint_dirfd, path, O_CREAT | O_WRONLY | O_TRUNC, mode );
- if( fd < 0 ) {
-
+ }
+ // success!
+ fd = openat (vdev->mountpoint_dirfd, path, O_CREAT | O_WRONLY | O_TRUNC,
+ mode);
+ if (fd < 0)
+ {
+
fd = -errno;
- vdev_error("openat('%s', '%s') rc = %d\n", vdev->mountpoint, path, fd );
-
+ vdev_error ("openat('%s', '%s') rc = %d\n", vdev->mountpoint, path, fd);
+
return fd;
- }
-
- // careful...
- void* handle_data = NULL;
- memcpy( &handle_data, &fd, 4 );
-
- *handle_cls = handle_data;
-
- return 0;
-}
+ }
+ // careful...
+ void *handle_data = NULL;
+ memcpy (&handle_data, &fd, 4);
+ *handle_cls = handle_data;
+
+ return 0;
+}
// open: open the file as usual, but from the underlying filesystem
// NOTE: since this is backed by FUSE, this handler will only be called for regular files
-int vdevfs_open( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, int flags, void** handle_cls ) {
-
- int fd = 0;
- struct vdevfs* vdev = (struct vdevfs*)fskit_core_get_user_data( core );
- struct fskit_fuse_state* fs_state = fskit_fuse_get_state();
- char const* path = NULL;
-
- int rc = 0;
-
- // dir or file?
- char const* method = NULL;
-
- if( fskit_entry_get_type( fent ) == FSKIT_ENTRY_TYPE_DIR ) {
-
- rc = vdevfs_access_check( vdev, fs_state, "opendir", fskit_route_metadata_get_path( grp ) );
- }
- else {
-
- rc = vdevfs_access_check( vdev, fs_state, "open", fskit_route_metadata_get_path( grp ) );
- }
-
- if( rc < 0 ) {
-
+int
+vdevfs_open (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, int flags, void **handle_cls)
+{
+
+ int fd = 0;
+ struct vdevfs *vdev = (struct vdevfs *) fskit_core_get_user_data (core);
+ struct fskit_fuse_state *fs_state = fskit_fuse_get_state ();
+ char const *path = NULL;
+
+ int rc = 0;
+
+ // dir or file?
+ char const *method = NULL;
+
+ if (fskit_entry_get_type (fent) == FSKIT_ENTRY_TYPE_DIR)
+ {
+
+ rc = vdevfs_access_check (vdev, fs_state, "opendir",
+ fskit_route_metadata_get_path (grp));
+ }
+ else
+ {
+
+ rc = vdevfs_access_check (vdev, fs_state, "open",
+ fskit_route_metadata_get_path (grp));
+ }
+
+ if (rc < 0)
+ {
+
// denied!
return -ENOENT;
- }
-
- // only care about open() for files
- if( fskit_entry_get_type( fent ) == FSKIT_ENTRY_TYPE_DIR ) {
-
+ }
+ // only care about open() for files
+ if (fskit_entry_get_type (fent) == FSKIT_ENTRY_TYPE_DIR)
+ {
+
// done!
return 0;
- }
-
- // must be relative path
- path = fskit_route_metadata_get_path( grp );
- while( *path == '/' && *path != '\0' ) {
+ }
+ // must be relative path
+ path = fskit_route_metadata_get_path (grp);
+ while (*path == '/' && *path != '\0')
+ {
path++;
- }
-
- if( *path == '\0' ) {
+ }
+
+ if (*path == '\0')
+ {
path = ".";
- }
-
- fd = openat( vdev->mountpoint_dirfd, path, flags );
- if( fd < 0 ) {
-
+ }
+
+ fd = openat (vdev->mountpoint_dirfd, path, flags);
+ if (fd < 0)
+ {
+
fd = -errno;
- vdev_error("openat(%d, '%s') rc = %d\n", vdev->mountpoint_dirfd, path, fd );
-
+ vdev_error ("openat(%d, '%s') rc = %d\n", vdev->mountpoint_dirfd,
+ path, fd);
+
return fd;
- }
-
- // careful...
- void* handle_data = NULL;
- memcpy( &handle_data, &fd, 4 );
-
- *handle_cls = handle_data;
-
- return 0;
-}
+ }
+ // careful...
+ void *handle_data = NULL;
+ memcpy (&handle_data, &fd, 4);
+ *handle_cls = handle_data;
+
+ return 0;
+}
// read: read as usual, but from the underlying filesystem
// NOTE: since this is backed by FUSE, this handler will only be called for regular files
-int vdevfs_read( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, char* buf, size_t len, off_t offset, void* handle_cls ) {
-
- // careful...
- int fd = 0;
- memcpy( &fd, &handle_cls, 4 );
-
- int rc = 0;
- struct vdevfs* vdev = (struct vdevfs*)fskit_core_get_user_data( core );
-
- rc = lseek( fd, offset, SEEK_SET );
- if( rc < 0 ) {
-
+int
+vdevfs_read (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, char *buf, size_t len, off_t offset,
+ void *handle_cls)
+{
+
+ // careful...
+ int fd = 0;
+ memcpy (&fd, &handle_cls, 4);
+
+ int rc = 0;
+ struct vdevfs *vdev = (struct vdevfs *) fskit_core_get_user_data (core);
+
+ rc = lseek (fd, offset, SEEK_SET);
+ if (rc < 0)
+ {
+
rc = -errno;
- vdev_error("lseek(%d '%s') rc = %d\n", fd, fskit_route_metadata_get_path( grp ), rc );
-
+ vdev_error ("lseek(%d '%s') rc = %d\n", fd,
+ fskit_route_metadata_get_path (grp), rc);
+
return rc;
- }
-
- rc = read( fd, buf, len );
- if( rc < 0 ) {
-
+ }
+
+ rc = read (fd, buf, len);
+ if (rc < 0)
+ {
+
rc = -errno;
- vdev_error("read(%d '%s') rc = %d\n", fd, fskit_route_metadata_get_path( grp ), rc );
-
+ vdev_error ("read(%d '%s') rc = %d\n", fd,
+ fskit_route_metadata_get_path (grp), rc);
+
return rc;
- }
-
- return rc;
-}
+ }
+ return rc;
+}
// write; write as usual, but to the underlying filesystem
// NOTE: since this is backed by FUSE, this handler will only be called for regular files
-int vdevfs_write( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, char* buf, size_t len, off_t offset, void* handle_cls ) {
-
- // careful...
- int fd = 0;
- memcpy( &fd, &handle_cls, 4 );
-
-
- int rc = 0;
- struct vdevfs* vdev = (struct vdevfs*)fskit_core_get_user_data( core );
-
- rc = lseek( fd, offset, SEEK_SET );
- if( rc < 0 ) {
-
+int
+vdevfs_write (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, char *buf, size_t len, off_t offset,
+ void *handle_cls)
+{
+
+ // careful...
+ int fd = 0;
+ memcpy (&fd, &handle_cls, 4);
+
+ int rc = 0;
+ struct vdevfs *vdev = (struct vdevfs *) fskit_core_get_user_data (core);
+
+ rc = lseek (fd, offset, SEEK_SET);
+ if (rc < 0)
+ {
+
rc = -errno;
- vdev_error("lseek(%d '%s') rc = %d\n", fd, fskit_route_metadata_get_path( grp ), rc );
-
+ vdev_error ("lseek(%d '%s') rc = %d\n", fd,
+ fskit_route_metadata_get_path (grp), rc);
+
return rc;
- }
-
- rc = write( fd, buf, len );
- if( rc < 0 ) {
-
+ }
+
+ rc = write (fd, buf, len);
+ if (rc < 0)
+ {
+
rc = -errno;
- vdev_error("write(%d '%s') rc = %d\n", fd, fskit_route_metadata_get_path( grp ), rc );
-
+ vdev_error ("write(%d '%s') rc = %d\n", fd,
+ fskit_route_metadata_get_path (grp), rc);
+
return rc;
- }
-
- return rc;
-}
+ }
+ return rc;
+}
// close: close as usual
// NOTE: since this is backed by FUSE, this handler will only be called for regular files
-int vdevfs_close( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, void* handle_cls ) {
-
- // only care about close() for files
- if( fskit_entry_get_type( fent ) == FSKIT_ENTRY_TYPE_DIR ) {
-
+int
+vdevfs_close (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, void *handle_cls)
+{
+
+ // only care about close() for files
+ if (fskit_entry_get_type (fent) == FSKIT_ENTRY_TYPE_DIR)
+ {
+
// done!
return 0;
- }
-
- // careful...
- int fd = 0;
- memcpy( &fd, &handle_cls, 4 );
-
- int rc = 0;
-
- rc = close( fd );
- if( rc < 0 ) {
-
+ }
+ // careful...
+ int fd = 0;
+ memcpy (&fd, &handle_cls, 4);
+
+ int rc = 0;
+
+ rc = close (fd);
+ if (rc < 0)
+ {
+
rc = -errno;
- vdev_error("close(%d '%s') rc = %d\n", fd, fskit_route_metadata_get_path( grp ), rc );
-
+ vdev_error ("close(%d '%s') rc = %d\n", fd,
+ fskit_route_metadata_get_path (grp), rc);
+
return rc;
- }
-
- return rc;
-}
+ }
+ return rc;
+}
// sync: sync as usual
// NOTE: since this is backed by FUSE, this handler will only be called for regular files
-int vdevfs_sync( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent ) {
-
- void* user_data = fskit_entry_get_user_data( fent );
-
- // careful...
- int fd = 0;
- memcpy( &fd, &user_data, 4 );
-
- int rc = 0;
-
- rc = fsync( fd );
- if( rc < 0 ) {
-
+int
+vdevfs_sync (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent)
+{
+
+ void *user_data = fskit_entry_get_user_data (fent);
+
+ // careful...
+ int fd = 0;
+ memcpy (&fd, &user_data, 4);
+
+ int rc = 0;
+
+ rc = fsync (fd);
+ if (rc < 0)
+ {
+
rc = -errno;
- vdev_error("fsync(%d '%s') rc = %d\n", fd, fskit_route_metadata_get_path( grp ), rc );
-
+ vdev_error ("fsync(%d '%s') rc = %d\n", fd,
+ fskit_route_metadata_get_path (grp), rc);
+
return rc;
- }
-
- return rc;
-}
+ }
+ return rc;
+}
// unlink/rmdir: remove the file or device node from the underlying filesystem
-int vdevfs_detach( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, void* inode_cls ) {
-
- int rc = 0;
- struct vdevfs* vdev = (struct vdevfs*)fskit_core_get_user_data( core );
- struct fskit_fuse_state* fs_state = fskit_fuse_get_state();
- char const* method = NULL;
-
- if( fskit_entry_get_type( fent ) == FSKIT_ENTRY_TYPE_DIR ) {
-
+int
+vdevfs_detach (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, void *inode_cls)
+{
+
+ int rc = 0;
+ struct vdevfs *vdev = (struct vdevfs *) fskit_core_get_user_data (core);
+ struct fskit_fuse_state *fs_state = fskit_fuse_get_state ();
+ char const *method = NULL;
+
+ if (fskit_entry_get_type (fent) == FSKIT_ENTRY_TYPE_DIR)
+ {
+
method = "rmdir";
- }
- else {
-
+ }
+ else
+ {
+
method = "unlink";
- }
-
-
- rc = vdevfs_access_check( vdev, fs_state, method, fskit_route_metadata_get_path( grp ) );
- if( rc < 0 ) {
-
+ }
+
+ rc = vdevfs_access_check (vdev, fs_state, method,
+ fskit_route_metadata_get_path (grp));
+ if (rc < 0)
+ {
+
// denied!
return -ENOENT;
- }
-
- if( rc != 0 ) {
-
+ }
+
+ if (rc != 0)
+ {
+
rc = -errno;
- vdev_error("%s('%s', '%s') rc = %d\n", method, vdev->mountpoint, fskit_route_metadata_get_path( grp ), rc );
-
+ vdev_error ("%s('%s', '%s') rc = %d\n", method, vdev->mountpoint,
+ fskit_route_metadata_get_path (grp), rc);
+
return rc;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// stat: equvocate about which devices exist, depending on who's asking
// return -ENOENT not only if the file doesn't exist, but also if the file is blocked by the ACL
-int vdevfs_stat( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, struct stat* sb ) {
-
- int rc = 0;
- struct vdevfs* vdev = (struct vdevfs*)fskit_core_get_user_data( core );
- struct fskit_fuse_state* fs_state = fskit_fuse_get_state();
+int
+vdevfs_stat (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, struct stat *sb)
+{
+
+ int rc = 0;
+ struct vdevfs *vdev = (struct vdevfs *) fskit_core_get_user_data (core);
+ struct fskit_fuse_state *fs_state = fskit_fuse_get_state ();
- if( fent == NULL ) {
+ if (fent == NULL)
+ {
return -ENOENT;
- }
-
- rc = vdevfs_access_check( vdev, fs_state, "stat", fskit_route_metadata_get_path( grp ) );
- if( rc < 0 ) {
-
+ }
+
+ rc = vdevfs_access_check (vdev, fs_state, "stat",
+ fskit_route_metadata_get_path (grp));
+ if (rc < 0)
+ {
+
// denied!
return -ENOENT;
- }
- else {
-
+ }
+ else
+ {
+
return 0;
- }
+ }
}
// readdir: equivocate about which devices exist, depending on who's asking
// omit entries if the ACLs forbid them
-int vdevfs_readdir( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, struct fskit_dir_entry** dirents, size_t num_dirents ) {
-
- int rc = 0;
- struct fskit_entry* child = NULL;
-
- // entries to omit in the listing
- unsigned int omitted_idx = 0;
- int* omitted = VDEV_CALLOC( int, num_dirents );
- if( omitted == NULL ) {
- return -ENOMEM;
- }
-
- pid_t pid = 0;
- uid_t uid = 0;
- gid_t gid = 0;
-
- struct vdevfs* vdev = (struct vdevfs*)fskit_core_get_user_data( core );
- struct fskit_fuse_state* fs_state = fskit_fuse_get_state();
-
- struct stat sb;
- struct stat fskit_sb;
- struct pstat* ps = NULL;
- char* child_path = NULL;
-
- pid = fskit_fuse_get_pid();
- uid = fskit_fuse_get_uid( fs_state );
- gid = fskit_fuse_get_gid( fs_state );
-
- vdev_debug("vdevfs_readdir(%s, %zu) from user %d group %d task %d\n", fskit_route_metadata_get_path( grp ), num_dirents, uid, gid, pid );
-
- ps = pstat_new();
- if( ps == NULL ) {
- free( omitted );
+int
+vdevfs_readdir (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, struct fskit_dir_entry **dirents,
+ size_t num_dirents)
+{
+
+ int rc = 0;
+ struct fskit_entry *child = NULL;
+
+ // entries to omit in the listing
+ unsigned int omitted_idx = 0;
+ int *omitted = VDEV_CALLOC (int, num_dirents);
+ if (omitted == NULL)
+ {
+ return -ENOMEM;
+ }
+
+ pid_t pid = 0;
+ uid_t uid = 0;
+ gid_t gid = 0;
+
+ struct vdevfs *vdev = (struct vdevfs *) fskit_core_get_user_data (core);
+ struct fskit_fuse_state *fs_state = fskit_fuse_get_state ();
+
+ struct stat sb;
+ struct stat fskit_sb;
+ struct pstat *ps = NULL;
+ char *child_path = NULL;
+
+ pid = fskit_fuse_get_pid ();
+ uid = fskit_fuse_get_uid (fs_state);
+ gid = fskit_fuse_get_gid (fs_state);
+
+ vdev_debug ("vdevfs_readdir(%s, %zu) from user %d group %d task %d\n",
+ fskit_route_metadata_get_path (grp), num_dirents, uid, gid,
+ pid);
+
+ ps = pstat_new ();
+ if (ps == NULL)
+ {
+ free (omitted);
return -ENOMEM;
- }
-
- // see who's asking
- rc = pstat( pid, ps, 0 );
- if( rc != 0 ) {
-
- vdev_error("pstat(%d) rc = %d\n", pid, rc );
- pstat_free( ps );
- free( omitted );
+ }
+ // see who's asking
+ rc = pstat (pid, ps, 0);
+ if (rc != 0)
+ {
+
+ vdev_error ("pstat(%d) rc = %d\n", pid, rc);
+ pstat_free (ps);
+ free (omitted);
return -EIO;
- }
-
- for( unsigned int i = 0; i < num_dirents; i++ ) {
-
+ }
+
+ for (unsigned int i = 0; i < num_dirents; i++)
+ {
+
// skip . and ..
- if( strcmp(dirents[i]->name, ".") == 0 || strcmp(dirents[i]->name, "..") == 0 ) {
- continue;
- }
-
+ if (strcmp (dirents[i]->name, ".") == 0
+ || strcmp (dirents[i]->name, "..") == 0)
+ {
+ continue;
+ }
// find the associated fskit_entry
- child = fskit_dir_find_by_name( fent, dirents[i]->name );
-
- if( child == NULL ) {
- // strange, shouldn't happen...
- continue;
- }
-
- fskit_entry_rlock( child );
-
+ child = fskit_dir_find_by_name (fent, dirents[i]->name);
+
+ if (child == NULL)
+ {
+ // strange, shouldn't happen...
+ continue;
+ }
+
+ fskit_entry_rlock (child);
+
// construct a stat buffer from what we actually need
- memset( &sb, 0, sizeof(struct stat) );
-
- fskit_entry_fstat( child, &fskit_sb );
+ memset (&sb, 0, sizeof (struct stat));
+
+ fskit_entry_fstat (child, &fskit_sb);
sb.st_uid = fskit_sb.st_uid;
sb.st_gid = fskit_sb.st_gid;
sb.st_mode = fskit_sb.st_mode;
-
- child_path = fskit_fullpath( fskit_route_metadata_get_path( grp ), fskit_route_metadata_get_name( grp ), NULL );
- if( child_path == NULL ) {
-
- // can't continue; OOM
- fskit_entry_unlock( child );
- rc = -ENOMEM;
- break;
- }
-
+
+ child_path =
+ fskit_fullpath (fskit_route_metadata_get_path (grp),
+ fskit_route_metadata_get_name (grp), NULL);
+ if (child_path == NULL)
+ {
+
+ // can't continue; OOM
+ fskit_entry_unlock (child);
+ rc = -ENOMEM;
+ break;
+ }
// filter it
- rc = vdev_acl_apply_all( vdev->config, vdev->acls, vdev->num_acls, child_path, ps, uid, gid, &sb );
- if( rc < 0 ) {
-
- vdev_error("vdev_acl_apply_all('%s', uid=%d, gid=%d, pid=%d) rc = %d\n", child_path, uid, gid, pid, rc );
- rc = -EIO;
- }
- else if( rc == 0 || (sb.st_mode & 0777) == 0 ) {
-
- // omit this one
- vdev_debug("Filter '%s'\n", fskit_route_metadata_get_name( grp ) );
- omitted[ omitted_idx ] = i;
- omitted_idx++;
-
- rc = 0;
- }
- else {
-
- // success; matched
- rc = 0;
- }
-
- fskit_entry_unlock( child );
-
- free( child_path );
-
+ rc = vdev_acl_apply_all (vdev->config, vdev->acls,
+ vdev->num_acls, child_path, ps, uid, gid, &sb);
+ if (rc < 0)
+ {
+
+ vdev_error
+ ("vdev_acl_apply_all('%s', uid=%d, gid=%d, pid=%d) rc = %d\n",
+ child_path, uid, gid, pid, rc);
+ rc = -EIO;
+ }
+ else if (rc == 0 || (sb.st_mode & 0777) == 0)
+ {
+
+ // omit this one
+ vdev_debug ("Filter '%s'\n", fskit_route_metadata_get_name (grp));
+ omitted[omitted_idx] = i;
+ omitted_idx++;
+
+ rc = 0;
+ }
+ else
+ {
+
+ // success; matched
+ rc = 0;
+ }
+
+ fskit_entry_unlock (child);
+
+ free (child_path);
+
// error?
- if( rc != 0 ) {
- break;
- }
- }
-
- // skip ACL'ed entries
- for( unsigned int i = 0; i < omitted_idx; i++ ) {
-
- fskit_readdir_omit( dirents, omitted[i] );
- }
-
- pstat_free( ps );
- free( omitted );
- return rc;
+ if (rc != 0)
+ {
+ break;
+ }
+ }
+
+ // skip ACL'ed entries
+ for (unsigned int i = 0; i < omitted_idx; i++)
+ {
+
+ fskit_readdir_omit (dirents, omitted[i]);
+ }
+
+ pstat_free (ps);
+ free (omitted);
+ return rc;
}
diff --git a/fs/fs.h b/fs/fs.h
index 022aab1..1484852 100644
--- a/fs/fs.h
+++ b/fs/fs.h
@@ -32,56 +32,69 @@
#include "libvdev/util.h"
#include "libvdev/config.h"
+struct vdevfs
+{
-struct vdevfs {
-
- // configuration
- struct vdev_config* config;
-
- // arguments
- int argc;
- char** argv;
-
- // FUSE-filtered arguments
- int fuse_argc;
- char** fuse_argv;
-
- // mountpoint; where /dev is
- char* mountpoint;
-
- // mountpoint dir handle, underneath /dev
- int mountpoint_dirfd;
-
- // fskit core
- struct fskit_fuse_state* fs;
-
- // acls
- struct vdev_acl* acls;
- size_t num_acls;
-
- // close route handler id
- int close_rh;
-};
+ // configuration
+ struct vdev_config *config;
+
+ // arguments
+ int argc;
+ char **argv;
+
+ // FUSE-filtered arguments
+ int fuse_argc;
+ char **fuse_argv;
+
+ // mountpoint; where /dev is
+ char *mountpoint;
+
+ // mountpoint dir handle, underneath /dev
+ int mountpoint_dirfd;
+ // fskit core
+ struct fskit_fuse_state *fs;
+
+ // acls
+ struct vdev_acl *acls;
+ size_t num_acls;
+
+ // close route handler id
+ int close_rh;
+};
C_LINKAGE_BEGIN
-
-int vdevfs_mkdir( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, mode_t mode, void** inode_cls );
-int vdevfs_mknod( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, mode_t mode, dev_t dev, void** inode_cls );
-int vdevfs_create( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, mode_t mode, void** inode_cls, void** handle_cls );
-int vdevfs_open( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, int flags, void** handle_cls );
-int vdevfs_read( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, char* buf, size_t len, off_t offset, void* handle_cls );
-int vdevfs_write( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, char* buf, size_t len, off_t offset, void* handle_cls );
-int vdevfs_close( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, void* handle_cls );
-int vdevfs_sync( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent );
-int vdevfs_detach( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, void* inode_cls );
-int vdevfs_stat( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, struct stat* sb );
-int vdevfs_readdir( struct fskit_core* core, struct fskit_route_metadata* grp, struct fskit_entry* fent, struct fskit_dir_entry** dirents, size_t num_dirents );
-
-int vdevfs_init( struct vdevfs* vdev, int argc, char** argv );
-int vdevfs_main( struct vdevfs* vdev, int fuse_argc, char** fuse_argv );
-int vdevfs_shutdown( struct vdevfs* vdev );
+ int vdevfs_mkdir (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, mode_t mode, void **inode_cls);
+int vdevfs_mknod (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, mode_t mode, dev_t dev,
+ void **inode_cls);
+int vdevfs_create (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, mode_t mode, void **inode_cls,
+ void **handle_cls);
+int vdevfs_open (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, int flags, void **handle_cls);
+int vdevfs_read (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, char *buf, size_t len,
+ off_t offset, void *handle_cls);
+int vdevfs_write (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, char *buf, size_t len,
+ off_t offset, void *handle_cls);
+int vdevfs_close (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, void *handle_cls);
+int vdevfs_sync (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent);
+int vdevfs_detach (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, void *inode_cls);
+int vdevfs_stat (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent, struct stat *sb);
+int vdevfs_readdir (struct fskit_core *core, struct fskit_route_metadata *grp,
+ struct fskit_entry *fent,
+ struct fskit_dir_entry **dirents, size_t num_dirents);
-C_LINKAGE_END
+int vdevfs_init (struct vdevfs *vdev, int argc, char **argv);
+int vdevfs_main (struct vdevfs *vdev, int fuse_argc, char **fuse_argv);
+int vdevfs_shutdown (struct vdevfs *vdev);
-#endif // _VDEV_FS_H_
+C_LINKAGE_END
+#endif // _VDEV_FS_H_
diff --git a/fs/main.c b/fs/main.c
index d805556..fdc8c0c 100644
--- a/fs/main.c
+++ b/fs/main.c
@@ -22,28 +22,29 @@
#include "main.h"
// run!
-int main( int argc, char** argv ) {
-
- int rc = 0;
- pid_t pid = 0;
- struct vdevfs vdev;
-
- memset( &vdev, 0, sizeof(struct vdevfs) );
-
- // set up global vdev state
- rc = vdevfs_init( &vdev, argc, argv );
- if( rc != 0 ) {
-
- vdev_error("vdevfs_init rc = %d\n", rc );
-
- exit(1);
- }
-
- // run!
- rc = vdevfs_main( &vdev, vdev.fuse_argc, vdev.fuse_argv );
-
- vdevfs_shutdown( &vdev );
-
- return rc;
-}
+int
+main (int argc, char **argv)
+{
+
+ int rc = 0;
+ pid_t pid = 0;
+ struct vdevfs vdev;
+
+ memset (&vdev, 0, sizeof (struct vdevfs));
+
+ // set up global vdev state
+ rc = vdevfs_init (&vdev, argc, argv);
+ if (rc != 0)
+ {
+ vdev_error ("vdevfs_init rc = %d\n", rc);
+
+ exit (1);
+ }
+ // run!
+ rc = vdevfs_main (&vdev, vdev.fuse_argc, vdev.fuse_argv);
+
+ vdevfs_shutdown (&vdev);
+
+ return rc;
+}
diff --git a/libudev-compat/MurmurHash2.c b/libudev-compat/MurmurHash2.c
index 35f0949..e379482 100644
--- a/libudev-compat/MurmurHash2.c
+++ b/libudev-compat/MurmurHash2.c
@@ -35,7 +35,7 @@
// Other compilers
-#else // defined(_MSC_VER)
+#else // defined(_MSC_VER)
#define BIG_CONSTANT(x) (x##LLU)
@@ -43,7 +43,8 @@
//-----------------------------------------------------------------------------
-uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed )
+uint32_t
+MurmurHash2 (const void *key, int len, uint32_t seed)
{
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
@@ -57,32 +58,35 @@ uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed )
// Mix 4 bytes at a time into the hash
- const unsigned char * data = (const unsigned char *)key;
+ const unsigned char *data = (const unsigned char *) key;
- while(len >= 4)
- {
- uint32_t k = *(uint32_t*)data;
+ while (len >= 4)
+ {
+ uint32_t k = *(uint32_t *) data;
- k *= m;
- k ^= k >> r;
- k *= m;
+ k *= m;
+ k ^= k >> r;
+ k *= m;
- h *= m;
- h ^= k;
+ h *= m;
+ h ^= k;
- data += 4;
- len -= 4;
- }
+ data += 4;
+ len -= 4;
+ }
// Handle the last few bytes of the input array
- switch(len)
- {
- case 3: h ^= data[2] << 16;
- case 2: h ^= data[1] << 8;
- case 1: h ^= data[0];
+ switch (len)
+ {
+ case 3:
+ h ^= data[2] << 16;
+ case 2:
+ h ^= data[1] << 8;
+ case 1:
+ h ^= data[0];
h *= m;
- };
+ };
// Do a few final mixes of the hash to ensure the last few
// bytes are well-incorporated.
diff --git a/libudev-compat/MurmurHash2.h b/libudev-compat/MurmurHash2.h
index d4f4cf1..b1b21b4 100644
--- a/libudev-compat/MurmurHash2.h
+++ b/libudev-compat/MurmurHash2.h
@@ -27,7 +27,7 @@ typedef unsigned __int64 uint64_t;
// Other compilers
-#else // defined(_MSC_VER)
+#else // defined(_MSC_VER)
#include
@@ -35,7 +35,7 @@ typedef unsigned __int64 uint64_t;
//-----------------------------------------------------------------------------
-uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed );
+uint32_t MurmurHash2 (const void *key, int len, uint32_t seed);
//-----------------------------------------------------------------------------
diff --git a/libudev-compat/device-nodes.c b/libudev-compat/device-nodes.c
index ce76c26..1130d17 100644
--- a/libudev-compat/device-nodes.c
+++ b/libudev-compat/device-nodes.c
@@ -34,48 +34,58 @@
#include "device-nodes.h"
#include "utf8.h"
-int whitelisted_char_for_devnode(char c, const char *white) {
- if ((c >= '0' && c <= '9') ||
- (c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- strchr("#+-.:=@_", c) != NULL ||
- (white != NULL && strchr(white, c) != NULL))
- return 1;
- return 0;
+int
+whitelisted_char_for_devnode (char c, const char *white)
+{
+ if ((c >= '0' && c <= '9') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z') ||
+ strchr ("#+-.:=@_", c) != NULL ||
+ (white != NULL && strchr (white, c) != NULL))
+ return 1;
+ return 0;
}
-int encode_devnode_name(const char *str, char *str_enc, size_t len) {
- size_t i, j;
+int
+encode_devnode_name (const char *str, char *str_enc, size_t len)
+{
+ size_t i, j;
- if (str == NULL || str_enc == NULL)
- return -EINVAL;
+ if (str == NULL || str_enc == NULL)
+ return -EINVAL;
- for (i = 0, j = 0; str[i] != '\0'; i++) {
- int seqlen;
+ for (i = 0, j = 0; str[i] != '\0'; i++)
+ {
+ int seqlen;
- seqlen = utf8_encoded_valid_unichar(&str[i]);
- if (seqlen > 1) {
- if (len-j < (size_t)seqlen)
- goto err;
- memcpy(&str_enc[j], &str[i], seqlen);
- j += seqlen;
- i += (seqlen-1);
- } else if (str[i] == '\\' || !whitelisted_char_for_devnode(str[i], NULL)) {
- if (len-j < 4)
- goto err;
- sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]);
- j += 4;
- } else {
- if (len-j < 1)
- goto err;
- str_enc[j] = str[i];
- j++;
- }
- }
- if (len-j < 1)
- goto err;
- str_enc[j] = '\0';
- return 0;
+ seqlen = utf8_encoded_valid_unichar (&str[i]);
+ if (seqlen > 1)
+ {
+ if (len - j < (size_t) seqlen)
+ goto err;
+ memcpy (&str_enc[j], &str[i], seqlen);
+ j += seqlen;
+ i += (seqlen - 1);
+ }
+ else if (str[i] == '\\' || !whitelisted_char_for_devnode (str[i], NULL))
+ {
+ if (len - j < 4)
+ goto err;
+ sprintf (&str_enc[j], "\\x%02x", (unsigned char) str[i]);
+ j += 4;
+ }
+ else
+ {
+ if (len - j < 1)
+ goto err;
+ str_enc[j] = str[i];
+ j++;
+ }
+ }
+ if (len - j < 1)
+ goto err;
+ str_enc[j] = '\0';
+ return 0;
err:
- return -EINVAL;
+ return -EINVAL;
}
diff --git a/libudev-compat/device-nodes.h b/libudev-compat/device-nodes.h
index 93d4904..4e81c1b 100644
--- a/libudev-compat/device-nodes.h
+++ b/libudev-compat/device-nodes.h
@@ -29,7 +29,7 @@
#ifndef _LIBUDEV_COMPAT_DEVICE_NODES_H_
#define _LIBUDEV_COMPAT_DEVICE_NODES_H_
-int encode_devnode_name(const char *str, char *str_enc, size_t len);
-int whitelisted_char_for_devnode(char c, const char *additional);
+int encode_devnode_name (const char *str, char *str_enc, size_t len);
+int whitelisted_char_for_devnode (char c, const char *additional);
-#endif
\ No newline at end of file
+#endif
diff --git a/libudev-compat/hashmap.c b/libudev-compat/hashmap.c
index aa782fa..9f85d2e 100644
--- a/libudev-compat/hashmap.c
+++ b/libudev-compat/hashmap.c
@@ -94,28 +94,31 @@
#define INV_KEEP_FREE 5U
/* Fields common to entries of all hashmap/set types */
-struct hashmap_base_entry {
- const void *key;
+struct hashmap_base_entry
+{
+ const void *key;
};
/* Entry types for specific hashmap/set types
* hashmap_base_entry must be at the beginning of each entry struct. */
-struct plain_hashmap_entry {
- struct hashmap_base_entry b;
- void *value;
+struct plain_hashmap_entry
+{
+ struct hashmap_base_entry b;
+ void *value;
};
-struct ordered_hashmap_entry {
- struct plain_hashmap_entry p;
- unsigned iterate_next, iterate_previous;
+struct ordered_hashmap_entry
+{
+ struct plain_hashmap_entry p;
+ unsigned iterate_next, iterate_previous;
};
-struct set_entry {
- struct hashmap_base_entry b;
+struct set_entry
+{
+ struct hashmap_base_entry b;
};
-
/* In several functions it is advantageous to have the hash table extended
* virtually by a couple of additional buckets. We reserve special index values
* for these "swap" buckets. */
@@ -125,47 +128,49 @@ struct set_entry {
#define _IDX_SWAP_END (_IDX_SWAP_BEGIN + 2)
/* special index for freshly initialized iterators */
-#define IDX_FIRST (UINT_MAX - 1)
+#define IDX_FIRST (UINT_MAX - 1)
/* special index value meaning "none" or "end" */
-#define IDX_NIL UINT_MAX
+#define IDX_NIL UINT_MAX
-assert_cc(IDX_FIRST == _IDX_SWAP_END);
-assert_cc(IDX_FIRST == _IDX_ITERATOR_FIRST);
+assert_cc (IDX_FIRST == _IDX_SWAP_END);
+assert_cc (IDX_FIRST == _IDX_ITERATOR_FIRST);
/* Storage space for the "swap" buckets.
* All entry types can fit into a ordered_hashmap_entry. */
-struct swap_entries {
- struct ordered_hashmap_entry e[_IDX_SWAP_END - _IDX_SWAP_BEGIN];
+struct swap_entries
+{
+ struct ordered_hashmap_entry e[_IDX_SWAP_END - _IDX_SWAP_BEGIN];
};
/* Distance from Initial Bucket */
typedef uint8_t dib_raw_t;
-#define DIB_RAW_OVERFLOW ((dib_raw_t)0xfdU) /* indicates DIB value is greater than representable */
-#define DIB_RAW_REHASH ((dib_raw_t)0xfeU) /* entry yet to be rehashed during in-place resize */
-#define DIB_RAW_FREE ((dib_raw_t)0xffU) /* a free bucket */
-#define DIB_RAW_INIT ((char)DIB_RAW_FREE) /* a byte to memset a DIB store with when initializing */
+#define DIB_RAW_OVERFLOW ((dib_raw_t)0xfdU) /* indicates DIB value is greater than representable */
+#define DIB_RAW_REHASH ((dib_raw_t)0xfeU) /* entry yet to be rehashed during in-place resize */
+#define DIB_RAW_FREE ((dib_raw_t)0xffU) /* a free bucket */
+#define DIB_RAW_INIT ((char)DIB_RAW_FREE) /* a byte to memset a DIB store with when initializing */
#define DIB_FREE UINT_MAX
#ifdef ENABLE_DEBUG_HASHMAP
-struct hashmap_debug_info {
- LIST_FIELDS(struct hashmap_debug_info, debug_list);
- unsigned max_entries; /* high watermark of n_entries */
-
- /* who allocated this hashmap */
- int line;
- const char *file;
- const char *func;
-
- /* fields to detect modification while iterating */
- unsigned put_count; /* counts puts into the hashmap */
- unsigned rem_count; /* counts removals from hashmap */
- unsigned last_rem_idx; /* remembers last removal index */
+struct hashmap_debug_info
+{
+ LIST_FIELDS (struct hashmap_debug_info, debug_list);
+ unsigned max_entries; /* high watermark of n_entries */
+
+ /* who allocated this hashmap */
+ int line;
+ const char *file;
+ const char *func;
+
+ /* fields to detect modification while iterating */
+ unsigned put_count; /* counts puts into the hashmap */
+ unsigned rem_count; /* counts removals from hashmap */
+ unsigned last_rem_idx; /* remembers last removal index */
};
/* Tracks all existing hashmaps. Get at it from gdb. See sd_dump_hashmaps.py */
-static LIST_HEAD(struct hashmap_debug_info, hashmap_debug_list);
+static LIST_HEAD (struct hashmap_debug_info, hashmap_debug_list);
#define HASHMAP_DEBUG_FIELDS struct hashmap_debug_info debug;
@@ -173,42 +178,45 @@ static LIST_HEAD(struct hashmap_debug_info, hashmap_debug_list);
#define HASHMAP_DEBUG_FIELDS
#endif /* ENABLE_DEBUG_HASHMAP */
-enum HashmapType {
- HASHMAP_TYPE_PLAIN,
- HASHMAP_TYPE_ORDERED,
- HASHMAP_TYPE_SET,
- _HASHMAP_TYPE_MAX
+enum HashmapType
+{
+ HASHMAP_TYPE_PLAIN,
+ HASHMAP_TYPE_ORDERED,
+ HASHMAP_TYPE_SET,
+ _HASHMAP_TYPE_MAX
};
-struct _packed_ indirect_storage {
- char *storage; /* where buckets and DIBs are stored */
- uint8_t hash_key[HASH_KEY_SIZE]; /* hash key; changes during resize */
+struct _packed_ indirect_storage
+{
+ char *storage; /* where buckets and DIBs are stored */
+ uint8_t hash_key[HASH_KEY_SIZE]; /* hash key; changes during resize */
- unsigned n_entries; /* number of stored entries */
- unsigned n_buckets; /* number of buckets */
+ unsigned n_entries; /* number of stored entries */
+ unsigned n_buckets; /* number of buckets */
- unsigned idx_lowest_entry; /* Index below which all buckets are free.
- Makes "while(hashmap_steal_first())" loops
- O(n) instead of O(n^2) for unordered hashmaps. */
- uint8_t _pad[3]; /* padding for the whole HashmapBase */
- /* The bitfields in HashmapBase complete the alignment of the whole thing. */
+ unsigned idx_lowest_entry; /* Index below which all buckets are free.
+ Makes "while(hashmap_steal_first())" loops
+ O(n) instead of O(n^2) for unordered hashmaps. */
+ uint8_t _pad[3]; /* padding for the whole HashmapBase */
+ /* The bitfields in HashmapBase complete the alignment of the whole thing. */
};
-struct direct_storage {
- /* This gives us 39 bytes on 64bit, or 35 bytes on 32bit.
- * That's room for 4 set_entries + 4 DIB bytes + 3 unused bytes on 64bit,
- * or 7 set_entries + 7 DIB bytes + 0 unused bytes on 32bit. */
- char storage[sizeof(struct indirect_storage)];
+struct direct_storage
+{
+ /* This gives us 39 bytes on 64bit, or 35 bytes on 32bit.
+ * That's room for 4 set_entries + 4 DIB bytes + 3 unused bytes on 64bit,
+ * or 7 set_entries + 7 DIB bytes + 0 unused bytes on 32bit. */
+ char storage[sizeof (struct indirect_storage)];
};
#define DIRECT_BUCKETS(entry_t) \
(sizeof(struct direct_storage) / (sizeof(entry_t) + sizeof(dib_raw_t)))
/* We should be able to store at least one entry directly. */
-assert_cc(DIRECT_BUCKETS(struct ordered_hashmap_entry) >= 1);
+assert_cc (DIRECT_BUCKETS (struct ordered_hashmap_entry) >= 1);
/* We have 3 bits for n_direct_entries. */
-assert_cc(DIRECT_BUCKETS(struct set_entry) < (1 << 3));
+assert_cc (DIRECT_BUCKETS (struct set_entry) < (1 << 3));
/* Hashmaps with directly stored entries all use this shared hash key.
* It's no big deal if the key is guessed, because there can be only
@@ -218,555 +226,667 @@ static uint8_t shared_hash_key[HASH_KEY_SIZE];
static bool shared_hash_key_initialized;
/* Fields that all hashmap/set types must have */
-struct HashmapBase {
- const struct hash_ops *hash_ops; /* hash and compare ops to use */
-
- union _packed_ {
- struct indirect_storage indirect; /* if has_indirect */
- struct direct_storage direct; /* if !has_indirect */
- };
-
- enum HashmapType type:2; /* HASHMAP_TYPE_* */
- bool has_indirect:1; /* whether indirect storage is used */
- unsigned n_direct_entries:3; /* Number of entries in direct storage.
- * Only valid if !has_indirect. */
- bool from_pool:1; /* whether was allocated from mempool */
- HASHMAP_DEBUG_FIELDS /* optional hashmap_debug_info */
+struct HashmapBase
+{
+ const struct hash_ops *hash_ops; /* hash and compare ops to use */
+
+ union _packed_
+ {
+ struct indirect_storage indirect; /* if has_indirect */
+ struct direct_storage direct; /* if !has_indirect */
+ };
+
+ enum HashmapType type:2; /* HASHMAP_TYPE_* */
+ bool has_indirect:1; /* whether indirect storage is used */
+ unsigned n_direct_entries:3; /* Number of entries in direct storage.
+ * Only valid if !has_indirect. */
+ bool from_pool:1; /* whether was allocated from mempool */
+ HASHMAP_DEBUG_FIELDS /* optional hashmap_debug_info */
};
/* Specific hash types
* HashmapBase must be at the beginning of each hashmap struct. */
-struct Hashmap {
- struct HashmapBase b;
+struct Hashmap
+{
+ struct HashmapBase b;
};
-struct OrderedHashmap {
- struct HashmapBase b;
- unsigned iterate_list_head, iterate_list_tail;
+struct OrderedHashmap
+{
+ struct HashmapBase b;
+ unsigned iterate_list_head, iterate_list_tail;
};
-struct Set {
- struct HashmapBase b;
+struct Set
+{
+ struct HashmapBase b;
};
-DEFINE_MEMPOOL(hashmap_pool, Hashmap, 8);
-DEFINE_MEMPOOL(ordered_hashmap_pool, OrderedHashmap, 8);
+DEFINE_MEMPOOL (hashmap_pool, Hashmap, 8);
+DEFINE_MEMPOOL (ordered_hashmap_pool, OrderedHashmap, 8);
/* No need for a separate Set pool */
-assert_cc(sizeof(Hashmap) == sizeof(Set));
-
-struct hashmap_type_info {
- size_t head_size;
- size_t entry_size;
- struct mempool *mempool;
- unsigned n_direct_buckets;
+assert_cc (sizeof (Hashmap) == sizeof (Set));
+
+struct hashmap_type_info
+{
+ size_t head_size;
+ size_t entry_size;
+ struct mempool *mempool;
+ unsigned n_direct_buckets;
};
static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = {
- [HASHMAP_TYPE_PLAIN] = {
- .head_size = sizeof(Hashmap),
- .entry_size = sizeof(struct plain_hashmap_entry),
- .mempool = &hashmap_pool,
- .n_direct_buckets = DIRECT_BUCKETS(struct plain_hashmap_entry),
- },
- [HASHMAP_TYPE_ORDERED] = {
- .head_size = sizeof(OrderedHashmap),
- .entry_size = sizeof(struct ordered_hashmap_entry),
- .mempool = &ordered_hashmap_pool,
- .n_direct_buckets = DIRECT_BUCKETS(struct ordered_hashmap_entry),
- },
- [HASHMAP_TYPE_SET] = {
- .head_size = sizeof(Set),
- .entry_size = sizeof(struct set_entry),
- .mempool = &hashmap_pool,
- .n_direct_buckets = DIRECT_BUCKETS(struct set_entry),
- },
+ [HASHMAP_TYPE_PLAIN] = {
+ .head_size = sizeof (Hashmap),
+ .entry_size = sizeof (struct plain_hashmap_entry),
+ .mempool = &hashmap_pool,
+ .n_direct_buckets =
+ DIRECT_BUCKETS (struct plain_hashmap_entry),
+ },
+ [HASHMAP_TYPE_ORDERED] = {
+ .head_size = sizeof (OrderedHashmap),
+ .entry_size =
+ sizeof (struct ordered_hashmap_entry),
+ .mempool = &ordered_hashmap_pool,
+ .n_direct_buckets =
+ DIRECT_BUCKETS (struct ordered_hashmap_entry),
+ },
+ [HASHMAP_TYPE_SET] = {
+ .head_size = sizeof (Set),
+ .entry_size = sizeof (struct set_entry),
+ .mempool = &hashmap_pool,
+ .n_direct_buckets = DIRECT_BUCKETS (struct set_entry),
+ },
};
-unsigned long string_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
- uint64_t u;
- siphash24((uint8_t*) &u, p, strlen(p), hash_key);
- return (unsigned long) u;
+unsigned long
+string_hash_func (const void *p, const uint8_t hash_key[HASH_KEY_SIZE])
+{
+ uint64_t u;
+ siphash24 ((uint8_t *) & u, p, strlen (p), hash_key);
+ return (unsigned long) u;
}
-int string_compare_func(const void *a, const void *b) {
- return strcmp(a, b);
+int
+string_compare_func (const void *a, const void *b)
+{
+ return strcmp (a, b);
}
const struct hash_ops string_hash_ops = {
- .hash = string_hash_func,
- .compare = string_compare_func
+ .hash = string_hash_func,
+ .compare = string_compare_func
};
-unsigned long trivial_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
- uint64_t u;
- siphash24((uint8_t*) &u, &p, sizeof(p), hash_key);
- return (unsigned long) u;
+unsigned long
+trivial_hash_func (const void *p, const uint8_t hash_key[HASH_KEY_SIZE])
+{
+ uint64_t u;
+ siphash24 ((uint8_t *) & u, &p, sizeof (p), hash_key);
+ return (unsigned long) u;
}
-int trivial_compare_func(const void *a, const void *b) {
- return a < b ? -1 : (a > b ? 1 : 0);
+int
+trivial_compare_func (const void *a, const void *b)
+{
+ return a < b ? -1 : (a > b ? 1 : 0);
}
const struct hash_ops trivial_hash_ops = {
- .hash = trivial_hash_func,
- .compare = trivial_compare_func
+ .hash = trivial_hash_func,
+ .compare = trivial_compare_func
};
-unsigned long uint64_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
- uint64_t u;
- siphash24((uint8_t*) &u, p, sizeof(uint64_t), hash_key);
- return (unsigned long) u;
+unsigned long
+uint64_hash_func (const void *p, const uint8_t hash_key[HASH_KEY_SIZE])
+{
+ uint64_t u;
+ siphash24 ((uint8_t *) & u, p, sizeof (uint64_t), hash_key);
+ return (unsigned long) u;
}
-int uint64_compare_func(const void *_a, const void *_b) {
- uint64_t a, b;
- a = *(const uint64_t*) _a;
- b = *(const uint64_t*) _b;
- return a < b ? -1 : (a > b ? 1 : 0);
+int
+uint64_compare_func (const void *_a, const void *_b)
+{
+ uint64_t a, b;
+ a = *(const uint64_t *) _a;
+ b = *(const uint64_t *) _b;
+ return a < b ? -1 : (a > b ? 1 : 0);
}
const struct hash_ops uint64_hash_ops = {
- .hash = uint64_hash_func,
- .compare = uint64_compare_func
+ .hash = uint64_hash_func,
+ .compare = uint64_compare_func
};
#if SIZEOF_DEV_T != 8
-unsigned long devt_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
- uint64_t u;
- siphash24((uint8_t*) &u, p, sizeof(dev_t), hash_key);
- return (unsigned long) u;
+unsigned long
+devt_hash_func (const void *p, const uint8_t hash_key[HASH_KEY_SIZE])
+{
+ uint64_t u;
+ siphash24 ((uint8_t *) & u, p, sizeof (dev_t), hash_key);
+ return (unsigned long) u;
}
-int devt_compare_func(const void *_a, const void *_b) {
- dev_t a, b;
- a = *(const dev_t*) _a;
- b = *(const dev_t*) _b;
- return a < b ? -1 : (a > b ? 1 : 0);
+int
+devt_compare_func (const void *_a, const void *_b)
+{
+ dev_t a, b;
+ a = *(const dev_t *) _a;
+ b = *(const dev_t *) _b;
+ return a < b ? -1 : (a > b ? 1 : 0);
}
const struct hash_ops devt_hash_ops = {
- .hash = devt_hash_func,
- .compare = devt_compare_func
+ .hash = devt_hash_func,
+ .compare = devt_compare_func
};
#endif
-static unsigned n_buckets(HashmapBase *h) {
- return h->has_indirect ? h->indirect.n_buckets
- : hashmap_type_info[h->type].n_direct_buckets;
+static unsigned
+n_buckets (HashmapBase * h)
+{
+ return h->has_indirect ? h->indirect.n_buckets
+ : hashmap_type_info[h->type].n_direct_buckets;
}
-static unsigned n_entries(HashmapBase *h) {
- return h->has_indirect ? h->indirect.n_entries
- : h->n_direct_entries;
+static unsigned
+n_entries (HashmapBase * h)
+{
+ return h->has_indirect ? h->indirect.n_entries : h->n_direct_entries;
}
-static void n_entries_inc(HashmapBase *h) {
- if (h->has_indirect)
- h->indirect.n_entries++;
- else
- h->n_direct_entries++;
+static void
+n_entries_inc (HashmapBase * h)
+{
+ if (h->has_indirect)
+ h->indirect.n_entries++;
+ else
+ h->n_direct_entries++;
}
-static void n_entries_dec(HashmapBase *h) {
- if (h->has_indirect)
- h->indirect.n_entries--;
- else
- h->n_direct_entries--;
+static void
+n_entries_dec (HashmapBase * h)
+{
+ if (h->has_indirect)
+ h->indirect.n_entries--;
+ else
+ h->n_direct_entries--;
}
-static char *storage_ptr(HashmapBase *h) {
- return h->has_indirect ? h->indirect.storage
- : h->direct.storage;
+static char *
+storage_ptr (HashmapBase * h)
+{
+ return h->has_indirect ? h->indirect.storage : h->direct.storage;
}
-static uint8_t *hash_key(HashmapBase *h) {
- return h->has_indirect ? h->indirect.hash_key
- : shared_hash_key;
+static uint8_t *
+hash_key (HashmapBase * h)
+{
+ return h->has_indirect ? h->indirect.hash_key : shared_hash_key;
}
-static unsigned base_bucket_hash(HashmapBase *h, const void *p) {
- return (unsigned) (h->hash_ops->hash(p, hash_key(h)) % n_buckets(h));
+static unsigned
+base_bucket_hash (HashmapBase * h, const void *p)
+{
+ return (unsigned) (h->hash_ops->hash (p, hash_key (h)) % n_buckets (h));
}
+
#define bucket_hash(h, p) base_bucket_hash(HASHMAP_BASE(h), p)
-static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) {
- static uint8_t current[HASH_KEY_SIZE];
- static bool current_initialized = false;
+static void
+get_hash_key (uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok)
+{
+ static uint8_t current[HASH_KEY_SIZE];
+ static bool current_initialized = false;
- /* Returns a hash function key to use. In order to keep things
- * fast we will not generate a new key each time we allocate a
- * new hash table. Instead, we'll just reuse the most recently
- * generated one, except if we never generated one or when we
- * are rehashing an entire hash table because we reached a
- * fill level */
+ /* Returns a hash function key to use. In order to keep things
+ * fast we will not generate a new key each time we allocate a
+ * new hash table. Instead, we'll just reuse the most recently
+ * generated one, except if we never generated one or when we
+ * are rehashing an entire hash table because we reached a
+ * fill level */
- if (!current_initialized || !reuse_is_ok) {
- random_bytes(current, sizeof(current));
- current_initialized = true;
- }
+ if (!current_initialized || !reuse_is_ok)
+ {
+ random_bytes (current, sizeof (current));
+ current_initialized = true;
+ }
- memcpy(hash_key, current, sizeof(current));
+ memcpy (hash_key, current, sizeof (current));
}
-static struct hashmap_base_entry *bucket_at(HashmapBase *h, unsigned idx) {
- return (struct hashmap_base_entry*)
- (storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size);
+static struct hashmap_base_entry *
+bucket_at (HashmapBase * h, unsigned idx)
+{
+ return (struct hashmap_base_entry *)
+ (storage_ptr (h) + idx * hashmap_type_info[h->type].entry_size);
}
-static struct plain_hashmap_entry *plain_bucket_at(Hashmap *h, unsigned idx) {
- return (struct plain_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx);
+static struct plain_hashmap_entry *
+plain_bucket_at (Hashmap * h, unsigned idx)
+{
+ return (struct plain_hashmap_entry *) bucket_at (HASHMAP_BASE (h), idx);
}
-static struct ordered_hashmap_entry *ordered_bucket_at(OrderedHashmap *h, unsigned idx) {
- return (struct ordered_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx);
+static struct ordered_hashmap_entry *
+ordered_bucket_at (OrderedHashmap * h, unsigned idx)
+{
+ return (struct ordered_hashmap_entry *) bucket_at (HASHMAP_BASE (h), idx);
}
-static struct set_entry *set_bucket_at(Set *h, unsigned idx) {
- return (struct set_entry*) bucket_at(HASHMAP_BASE(h), idx);
+static struct set_entry *
+set_bucket_at (Set * h, unsigned idx)
+{
+ return (struct set_entry *) bucket_at (HASHMAP_BASE (h), idx);
}
-static struct ordered_hashmap_entry *bucket_at_swap(struct swap_entries *swap, unsigned idx) {
- return &swap->e[idx - _IDX_SWAP_BEGIN];
+static struct ordered_hashmap_entry *
+bucket_at_swap (struct swap_entries *swap, unsigned idx)
+{
+ return &swap->e[idx - _IDX_SWAP_BEGIN];
}
/* Returns a pointer to the bucket at index idx.
* Understands real indexes and swap indexes, hence "_virtual". */
-static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_entries *swap,
- unsigned idx) {
- if (idx < _IDX_SWAP_BEGIN)
- return bucket_at(h, idx);
+static struct hashmap_base_entry *
+bucket_at_virtual (HashmapBase * h, struct swap_entries *swap, unsigned idx)
+{
+ if (idx < _IDX_SWAP_BEGIN)
+ return bucket_at (h, idx);
- if (idx < _IDX_SWAP_END)
- return &bucket_at_swap(swap, idx)->p.b;
+ if (idx < _IDX_SWAP_END)
+ return &bucket_at_swap (swap, idx)->p.b;
- assert_not_reached("Invalid index");
- return NULL;
+ assert_not_reached ("Invalid index");
+ return NULL;
}
-static dib_raw_t *dib_raw_ptr(HashmapBase *h) {
- return (dib_raw_t*)
- (storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h));
+static dib_raw_t *
+dib_raw_ptr (HashmapBase * h)
+{
+ return (dib_raw_t *)
+ (storage_ptr (h) + hashmap_type_info[h->type].entry_size * n_buckets (h));
}
-static unsigned bucket_distance(HashmapBase *h, unsigned idx, unsigned from) {
- return idx >= from ? idx - from
- : n_buckets(h) + idx - from;
+static unsigned
+bucket_distance (HashmapBase * h, unsigned idx, unsigned from)
+{
+ return idx >= from ? idx - from : n_buckets (h) + idx - from;
}
-static unsigned bucket_calculate_dib(HashmapBase *h, unsigned idx, dib_raw_t raw_dib) {
- unsigned initial_bucket;
+static unsigned
+bucket_calculate_dib (HashmapBase * h, unsigned idx, dib_raw_t raw_dib)
+{
+ unsigned initial_bucket;
- if (raw_dib == DIB_RAW_FREE)
- return DIB_FREE;
+ if (raw_dib == DIB_RAW_FREE)
+ return DIB_FREE;
- if (_likely_(raw_dib < DIB_RAW_OVERFLOW))
- return raw_dib;
+ if (_likely_ (raw_dib < DIB_RAW_OVERFLOW))
+ return raw_dib;
- /*
- * Having an overflow DIB value is very unlikely. The hash function
- * would have to be bad. For example, in a table of size 2^24 filled
- * to load factor 0.9 the maximum observed DIB is only about 60.
- * In theory (assuming I used Maxima correctly), for an infinite size
- * hash table with load factor 0.8 the probability of a given entry
- * having DIB > 40 is 1.9e-8.
- * This returns the correct DIB value by recomputing the hash value in
- * the unlikely case. XXX Hitting this case could be a hint to rehash.
- */
- initial_bucket = bucket_hash(h, bucket_at(h, idx)->key);
- return bucket_distance(h, idx, initial_bucket);
+ /*
+ * Having an overflow DIB value is very unlikely. The hash function
+ * would have to be bad. For example, in a table of size 2^24 filled
+ * to load factor 0.9 the maximum observed DIB is only about 60.
+ * In theory (assuming I used Maxima correctly), for an infinite size
+ * hash table with load factor 0.8 the probability of a given entry
+ * having DIB > 40 is 1.9e-8.
+ * This returns the correct DIB value by recomputing the hash value in
+ * the unlikely case. XXX Hitting this case could be a hint to rehash.
+ */
+ initial_bucket = bucket_hash (h, bucket_at (h, idx)->key);
+ return bucket_distance (h, idx, initial_bucket);
}
-static void bucket_set_dib(HashmapBase *h, unsigned idx, unsigned dib) {
- dib_raw_ptr(h)[idx] = dib != DIB_FREE ? MIN(dib, DIB_RAW_OVERFLOW) : DIB_RAW_FREE;
+static void
+bucket_set_dib (HashmapBase * h, unsigned idx, unsigned dib)
+{
+ dib_raw_ptr (h)[idx] =
+ dib != DIB_FREE ? MIN (dib, DIB_RAW_OVERFLOW) : DIB_RAW_FREE;
}
-static unsigned skip_free_buckets(HashmapBase *h, unsigned idx) {
- dib_raw_t *dibs;
+static unsigned
+skip_free_buckets (HashmapBase * h, unsigned idx)
+{
+ dib_raw_t *dibs;
- dibs = dib_raw_ptr(h);
+ dibs = dib_raw_ptr (h);
- for ( ; idx < n_buckets(h); idx++)
- if (dibs[idx] != DIB_RAW_FREE)
- return idx;
+ for (; idx < n_buckets (h); idx++)
+ if (dibs[idx] != DIB_RAW_FREE)
+ return idx;
- return IDX_NIL;
+ return IDX_NIL;
}
-static void bucket_mark_free(HashmapBase *h, unsigned idx) {
- memzero(bucket_at(h, idx), hashmap_type_info[h->type].entry_size);
- bucket_set_dib(h, idx, DIB_FREE);
+static void
+bucket_mark_free (HashmapBase * h, unsigned idx)
+{
+ memzero (bucket_at (h, idx), hashmap_type_info[h->type].entry_size);
+ bucket_set_dib (h, idx, DIB_FREE);
}
-static void bucket_move_entry(HashmapBase *h, struct swap_entries *swap,
- unsigned from, unsigned to) {
- struct hashmap_base_entry *e_from, *e_to;
+static void
+bucket_move_entry (HashmapBase * h, struct swap_entries *swap,
+ unsigned from, unsigned to)
+{
+ struct hashmap_base_entry *e_from, *e_to;
- assert(from != to);
+ assert (from != to);
- e_from = bucket_at_virtual(h, swap, from);
- e_to = bucket_at_virtual(h, swap, to);
+ e_from = bucket_at_virtual (h, swap, from);
+ e_to = bucket_at_virtual (h, swap, to);
- memcpy(e_to, e_from, hashmap_type_info[h->type].entry_size);
+ memcpy (e_to, e_from, hashmap_type_info[h->type].entry_size);
- if (h->type == HASHMAP_TYPE_ORDERED) {
- OrderedHashmap *lh = (OrderedHashmap*) h;
- struct ordered_hashmap_entry *le, *le_to;
+ if (h->type == HASHMAP_TYPE_ORDERED)
+ {
+ OrderedHashmap *lh = (OrderedHashmap *) h;
+ struct ordered_hashmap_entry *le, *le_to;
- le_to = (struct ordered_hashmap_entry*) e_to;
+ le_to = (struct ordered_hashmap_entry *) e_to;
- if (le_to->iterate_next != IDX_NIL) {
- le = (struct ordered_hashmap_entry*)
- bucket_at_virtual(h, swap, le_to->iterate_next);
- le->iterate_previous = to;
- }
+ if (le_to->iterate_next != IDX_NIL)
+ {
+ le = (struct ordered_hashmap_entry *)
+ bucket_at_virtual (h, swap, le_to->iterate_next);
+ le->iterate_previous = to;
+ }
- if (le_to->iterate_previous != IDX_NIL) {
- le = (struct ordered_hashmap_entry*)
- bucket_at_virtual(h, swap, le_to->iterate_previous);
- le->iterate_next = to;
- }
+ if (le_to->iterate_previous != IDX_NIL)
+ {
+ le = (struct ordered_hashmap_entry *)
+ bucket_at_virtual (h, swap, le_to->iterate_previous);
+ le->iterate_next = to;
+ }
- if (lh->iterate_list_head == from)
- lh->iterate_list_head = to;
- if (lh->iterate_list_tail == from)
- lh->iterate_list_tail = to;
- }
+ if (lh->iterate_list_head == from)
+ lh->iterate_list_head = to;
+ if (lh->iterate_list_tail == from)
+ lh->iterate_list_tail = to;
+ }
}
-static unsigned next_idx(HashmapBase *h, unsigned idx) {
- return (idx + 1U) % n_buckets(h);
+static unsigned
+next_idx (HashmapBase * h, unsigned idx)
+{
+ return (idx + 1U) % n_buckets (h);
}
-static unsigned prev_idx(HashmapBase *h, unsigned idx) {
- return (n_buckets(h) + idx - 1U) % n_buckets(h);
+static unsigned
+prev_idx (HashmapBase * h, unsigned idx)
+{
+ return (n_buckets (h) + idx - 1U) % n_buckets (h);
}
-static void *entry_value(HashmapBase *h, struct hashmap_base_entry *e) {
- switch (h->type) {
+static void *
+entry_value (HashmapBase * h, struct hashmap_base_entry *e)
+{
+ switch (h->type)
+ {
- case HASHMAP_TYPE_PLAIN:
- case HASHMAP_TYPE_ORDERED:
- return ((struct plain_hashmap_entry*)e)->value;
+ case HASHMAP_TYPE_PLAIN:
+ case HASHMAP_TYPE_ORDERED:
+ return ((struct plain_hashmap_entry *) e)->value;
- case HASHMAP_TYPE_SET:
- return (void*) e->key;
+ case HASHMAP_TYPE_SET:
+ return (void *) e->key;
- default:
- assert_not_reached("Unknown hashmap type");
- return NULL;
- }
+ default:
+ assert_not_reached ("Unknown hashmap type");
+ return NULL;
+ }
}
-static void base_remove_entry(HashmapBase *h, unsigned idx) {
- unsigned left, right, prev, dib;
- dib_raw_t raw_dib, *dibs;
+static void
+base_remove_entry (HashmapBase * h, unsigned idx)
+{
+ unsigned left, right, prev, dib;
+ dib_raw_t raw_dib, *dibs;
- dibs = dib_raw_ptr(h);
- assert(dibs[idx] != DIB_RAW_FREE);
+ dibs = dib_raw_ptr (h);
+ assert (dibs[idx] != DIB_RAW_FREE);
#ifdef ENABLE_DEBUG_HASHMAP
- h->debug.rem_count++;
- h->debug.last_rem_idx = idx;
+ h->debug.rem_count++;
+ h->debug.last_rem_idx = idx;
#endif
- left = idx;
- /* Find the stop bucket ("right"). It is either free or has DIB == 0. */
- for (right = next_idx(h, left); ; right = next_idx(h, right)) {
- raw_dib = dibs[right];
- if (raw_dib == 0 || raw_dib == DIB_RAW_FREE)
- break;
-
- /* The buckets are not supposed to be all occupied and with DIB > 0.
- * That would mean we could make everyone better off by shifting them
- * backward. This scenario is impossible. */
- assert(left != right);
- }
-
- if (h->type == HASHMAP_TYPE_ORDERED) {
- OrderedHashmap *lh = (OrderedHashmap*) h;
- struct ordered_hashmap_entry *le = ordered_bucket_at(lh, idx);
-
- if (le->iterate_next != IDX_NIL)
- ordered_bucket_at(lh, le->iterate_next)->iterate_previous = le->iterate_previous;
- else
- lh->iterate_list_tail = le->iterate_previous;
-
- if (le->iterate_previous != IDX_NIL)
- ordered_bucket_at(lh, le->iterate_previous)->iterate_next = le->iterate_next;
- else
- lh->iterate_list_head = le->iterate_next;
- }
-
- /* Now shift all buckets in the interval (left, right) one step backwards */
- for (prev = left, left = next_idx(h, left); left != right;
- prev = left, left = next_idx(h, left)) {
- dib = bucket_calculate_dib(h, left, dibs[left]);
- assert(dib != 0);
- bucket_move_entry(h, NULL, left, prev);
- bucket_set_dib(h, prev, dib - 1);
- }
-
- bucket_mark_free(h, prev);
- n_entries_dec(h);
+ left = idx;
+ /* Find the stop bucket ("right"). It is either free or has DIB == 0. */
+ for (right = next_idx (h, left);; right = next_idx (h, right))
+ {
+ raw_dib = dibs[right];
+ if (raw_dib == 0 || raw_dib == DIB_RAW_FREE)
+ break;
+
+ /* The buckets are not supposed to be all occupied and with DIB > 0.
+ * That would mean we could make everyone better off by shifting them
+ * backward. This scenario is impossible. */
+ assert (left != right);
+ }
+
+ if (h->type == HASHMAP_TYPE_ORDERED)
+ {
+ OrderedHashmap *lh = (OrderedHashmap *) h;
+ struct ordered_hashmap_entry *le = ordered_bucket_at (lh, idx);
+
+ if (le->iterate_next != IDX_NIL)
+ ordered_bucket_at (lh,
+ le->iterate_next)->iterate_previous =
+ le->iterate_previous;
+ else
+ lh->iterate_list_tail = le->iterate_previous;
+
+ if (le->iterate_previous != IDX_NIL)
+ ordered_bucket_at (lh,
+ le->iterate_previous)->iterate_next =
+ le->iterate_next;
+ else
+ lh->iterate_list_head = le->iterate_next;
+ }
+
+ /* Now shift all buckets in the interval (left, right) one step backwards */
+ for (prev = left, left = next_idx (h, left); left != right;
+ prev = left, left = next_idx (h, left))
+ {
+ dib = bucket_calculate_dib (h, left, dibs[left]);
+ assert (dib != 0);
+ bucket_move_entry (h, NULL, left, prev);
+ bucket_set_dib (h, prev, dib - 1);
+ }
+
+ bucket_mark_free (h, prev);
+ n_entries_dec (h);
}
+
#define remove_entry(h, idx) base_remove_entry(HASHMAP_BASE(h), idx)
-static unsigned hashmap_iterate_in_insertion_order(OrderedHashmap *h, Iterator *i) {
- struct ordered_hashmap_entry *e;
- unsigned idx;
-
- assert(h);
- assert(i);
-
- if (i->idx == IDX_NIL)
- goto at_end;
-
- if (i->idx == IDX_FIRST && h->iterate_list_head == IDX_NIL)
- goto at_end;
-
- if (i->idx == IDX_FIRST) {
- idx = h->iterate_list_head;
- e = ordered_bucket_at(h, idx);
- } else {
- idx = i->idx;
- e = ordered_bucket_at(h, idx);
- /*
- * We allow removing the current entry while iterating, but removal may cause
- * a backward shift. The next entry may thus move one bucket to the left.
- * To detect when it happens, we remember the key pointer of the entry we were
- * going to iterate next. If it does not match, there was a backward shift.
- */
- if (e->p.b.key != i->next_key) {
- idx = prev_idx(HASHMAP_BASE(h), idx);
- e = ordered_bucket_at(h, idx);
- }
- assert(e->p.b.key == i->next_key);
- }
+static unsigned
+hashmap_iterate_in_insertion_order (OrderedHashmap * h, Iterator * i)
+{
+ struct ordered_hashmap_entry *e;
+ unsigned idx;
+
+ assert (h);
+ assert (i);
+
+ if (i->idx == IDX_NIL)
+ goto at_end;
+
+ if (i->idx == IDX_FIRST && h->iterate_list_head == IDX_NIL)
+ goto at_end;
+
+ if (i->idx == IDX_FIRST)
+ {
+ idx = h->iterate_list_head;
+ e = ordered_bucket_at (h, idx);
+ }
+ else
+ {
+ idx = i->idx;
+ e = ordered_bucket_at (h, idx);
+ /*
+ * We allow removing the current entry while iterating, but removal may cause
+ * a backward shift. The next entry may thus move one bucket to the left.
+ * To detect when it happens, we remember the key pointer of the entry we were
+ * going to iterate next. If it does not match, there was a backward shift.
+ */
+ if (e->p.b.key != i->next_key)
+ {
+ idx = prev_idx (HASHMAP_BASE (h), idx);
+ e = ordered_bucket_at (h, idx);
+ }
+ assert (e->p.b.key == i->next_key);
+ }
#ifdef ENABLE_DEBUG_HASHMAP
- i->prev_idx = idx;
+ i->prev_idx = idx;
#endif
- if (e->iterate_next != IDX_NIL) {
- struct ordered_hashmap_entry *n;
- i->idx = e->iterate_next;
- n = ordered_bucket_at(h, i->idx);
- i->next_key = n->p.b.key;
- } else
- i->idx = IDX_NIL;
+ if (e->iterate_next != IDX_NIL)
+ {
+ struct ordered_hashmap_entry *n;
+ i->idx = e->iterate_next;
+ n = ordered_bucket_at (h, i->idx);
+ i->next_key = n->p.b.key;
+ }
+ else
+ i->idx = IDX_NIL;
- return idx;
+ return idx;
at_end:
- i->idx = IDX_NIL;
- return IDX_NIL;
-}
-
-static unsigned hashmap_iterate_in_internal_order(HashmapBase *h, Iterator *i) {
- unsigned idx;
-
- assert(h);
- assert(i);
-
- if (i->idx == IDX_NIL)
- goto at_end;
-
- if (i->idx == IDX_FIRST) {
- /* fast forward to the first occupied bucket */
- if (h->has_indirect) {
- i->idx = skip_free_buckets(h, h->indirect.idx_lowest_entry);
- h->indirect.idx_lowest_entry = i->idx;
- } else
- i->idx = skip_free_buckets(h, 0);
-
- if (i->idx == IDX_NIL)
- goto at_end;
- } else {
- struct hashmap_base_entry *e;
-
- assert(i->idx > 0);
-
- e = bucket_at(h, i->idx);
- /*
- * We allow removing the current entry while iterating, but removal may cause
- * a backward shift. The next entry may thus move one bucket to the left.
- * To detect when it happens, we remember the key pointer of the entry we were
- * going to iterate next. If it does not match, there was a backward shift.
- */
- if (e->key != i->next_key)
- e = bucket_at(h, --i->idx);
-
- assert(e->key == i->next_key);
- }
-
- idx = i->idx;
+ i->idx = IDX_NIL;
+ return IDX_NIL;
+}
+
+static unsigned
+hashmap_iterate_in_internal_order (HashmapBase * h, Iterator * i)
+{
+ unsigned idx;
+
+ assert (h);
+ assert (i);
+
+ if (i->idx == IDX_NIL)
+ goto at_end;
+
+ if (i->idx == IDX_FIRST)
+ {
+ /* fast forward to the first occupied bucket */
+ if (h->has_indirect)
+ {
+ i->idx = skip_free_buckets (h, h->indirect.idx_lowest_entry);
+ h->indirect.idx_lowest_entry = i->idx;
+ }
+ else
+ i->idx = skip_free_buckets (h, 0);
+
+ if (i->idx == IDX_NIL)
+ goto at_end;
+ }
+ else
+ {
+ struct hashmap_base_entry *e;
+
+ assert (i->idx > 0);
+
+ e = bucket_at (h, i->idx);
+ /*
+ * We allow removing the current entry while iterating, but removal may cause
+ * a backward shift. The next entry may thus move one bucket to the left.
+ * To detect when it happens, we remember the key pointer of the entry we were
+ * going to iterate next. If it does not match, there was a backward shift.
+ */
+ if (e->key != i->next_key)
+ e = bucket_at (h, --i->idx);
+
+ assert (e->key == i->next_key);
+ }
+
+ idx = i->idx;
#ifdef ENABLE_DEBUG_HASHMAP
- i->prev_idx = idx;
+ i->prev_idx = idx;
#endif
- i->idx = skip_free_buckets(h, i->idx + 1);
- if (i->idx != IDX_NIL)
- i->next_key = bucket_at(h, i->idx)->key;
- else
- i->idx = IDX_NIL;
+ i->idx = skip_free_buckets (h, i->idx + 1);
+ if (i->idx != IDX_NIL)
+ i->next_key = bucket_at (h, i->idx)->key;
+ else
+ i->idx = IDX_NIL;
- return idx;
+ return idx;
at_end:
- i->idx = IDX_NIL;
- return IDX_NIL;
-}
-
-static unsigned hashmap_iterate_entry(HashmapBase *h, Iterator *i) {
- if (!h) {
- i->idx = IDX_NIL;
- return IDX_NIL;
- }
-
+ i->idx = IDX_NIL;
+ return IDX_NIL;
+}
+
+static unsigned
+hashmap_iterate_entry (HashmapBase * h, Iterator * i)
+{
+ if (!h)
+ {
+ i->idx = IDX_NIL;
+ return IDX_NIL;
+ }
#ifdef ENABLE_DEBUG_HASHMAP
- if (i->idx == IDX_FIRST) {
- i->put_count = h->debug.put_count;
- i->rem_count = h->debug.rem_count;
- } else {
- /* While iterating, must not add any new entries */
- assert(i->put_count == h->debug.put_count);
- /* ... or remove entries other than the current one */
- assert(i->rem_count == h->debug.rem_count ||
- (i->rem_count == h->debug.rem_count - 1 &&
- i->prev_idx == h->debug.last_rem_idx));
- /* Reset our removals counter */
- i->rem_count = h->debug.rem_count;
- }
+ if (i->idx == IDX_FIRST)
+ {
+ i->put_count = h->debug.put_count;
+ i->rem_count = h->debug.rem_count;
+ }
+ else
+ {
+ /* While iterating, must not add any new entries */
+ assert (i->put_count == h->debug.put_count);
+ /* ... or remove entries other than the current one */
+ assert (i->rem_count == h->debug.rem_count ||
+ (i->rem_count == h->debug.rem_count - 1 &&
+ i->prev_idx == h->debug.last_rem_idx));
+ /* Reset our removals counter */
+ i->rem_count = h->debug.rem_count;
+ }
#endif
- return h->type == HASHMAP_TYPE_ORDERED ? hashmap_iterate_in_insertion_order((OrderedHashmap*) h, i)
- : hashmap_iterate_in_internal_order(h, i);
+ return h->type ==
+ HASHMAP_TYPE_ORDERED ?
+ hashmap_iterate_in_insertion_order ((OrderedHashmap *) h, i)
+ : hashmap_iterate_in_internal_order (h, i);
}
-void *internal_hashmap_iterate(HashmapBase *h, Iterator *i, const void **key) {
- struct hashmap_base_entry *e;
- void *data;
- unsigned idx;
+void *
+internal_hashmap_iterate (HashmapBase * h, Iterator * i, const void **key)
+{
+ struct hashmap_base_entry *e;
+ void *data;
+ unsigned idx;
- idx = hashmap_iterate_entry(h, i);
- if (idx == IDX_NIL) {
- if (key)
- *key = NULL;
+ idx = hashmap_iterate_entry (h, i);
+ if (idx == IDX_NIL)
+ {
+ if (key)
+ *key = NULL;
- return NULL;
- }
+ return NULL;
+ }
- e = bucket_at(h, idx);
- data = entry_value(h, e);
- if (key)
- *key = e->key;
+ e = bucket_at (h, idx);
+ data = entry_value (h, e);
+ if (key)
+ *key = e->key;
- return data;
+ return data;
}
-void *set_iterate(Set *s, Iterator *i) {
- return internal_hashmap_iterate(HASHMAP_BASE(s), i, NULL);
+void *
+set_iterate (Set * s, Iterator * i)
+{
+ return internal_hashmap_iterate (HASHMAP_BASE (s), i, NULL);
}
#define HASHMAP_FOREACH_IDX(idx, h, i) \
@@ -774,191 +894,247 @@ void *set_iterate(Set *s, Iterator *i) {
(idx != IDX_NIL); \
(idx) = hashmap_iterate_entry((h), &(i)))
-static void reset_direct_storage(HashmapBase *h) {
- const struct hashmap_type_info *hi = &hashmap_type_info[h->type];
- void *p;
+static void
+reset_direct_storage (HashmapBase * h)
+{
+ const struct hashmap_type_info *hi = &hashmap_type_info[h->type];
+ void *p;
- assert(!h->has_indirect);
+ assert (!h->has_indirect);
- p = mempset(h->direct.storage, 0, hi->entry_size * hi->n_direct_buckets);
- memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets);
+ p = mempset (h->direct.storage, 0, hi->entry_size * hi->n_direct_buckets);
+ memset (p, DIB_RAW_INIT, sizeof (dib_raw_t) * hi->n_direct_buckets);
}
-static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) {
- HashmapBase *h;
- const struct hashmap_type_info *hi = &hashmap_type_info[type];
- bool use_pool;
+static struct HashmapBase *
+hashmap_base_new (const struct hash_ops *hash_ops,
+ enum HashmapType type HASHMAP_DEBUG_PARAMS)
+{
+ HashmapBase *h;
+ const struct hashmap_type_info *hi = &hashmap_type_info[type];
+ bool use_pool;
- use_pool = is_main_thread();
+ use_pool = is_main_thread ();
- h = use_pool ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size);
+ h = use_pool ? mempool_alloc0_tile (hi->mempool) : malloc0 (hi->head_size);
- if (!h)
- return NULL;
+ if (!h)
+ return NULL;
- h->type = type;
- h->from_pool = use_pool;
- h->hash_ops = hash_ops ? hash_ops : &trivial_hash_ops;
+ h->type = type;
+ h->from_pool = use_pool;
+ h->hash_ops = hash_ops ? hash_ops : &trivial_hash_ops;
- if (type == HASHMAP_TYPE_ORDERED) {
- OrderedHashmap *lh = (OrderedHashmap*)h;
- lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL;
- }
+ if (type == HASHMAP_TYPE_ORDERED)
+ {
+ OrderedHashmap *lh = (OrderedHashmap *) h;
+ lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL;
+ }
- reset_direct_storage(h);
-
- if (!shared_hash_key_initialized) {
- random_bytes(shared_hash_key, sizeof(shared_hash_key));
- shared_hash_key_initialized= true;
- }
+ reset_direct_storage (h);
+ if (!shared_hash_key_initialized)
+ {
+ random_bytes (shared_hash_key, sizeof (shared_hash_key));
+ shared_hash_key_initialized = true;
+ }
#ifdef ENABLE_DEBUG_HASHMAP
- LIST_PREPEND(debug_list, hashmap_debug_list, &h->debug);
- h->debug.func = func;
- h->debug.file = file;
- h->debug.line = line;
+ LIST_PREPEND (debug_list, hashmap_debug_list, &h->debug);
+ h->debug.func = func;
+ h->debug.file = file;
+ h->debug.line = line;
#endif
- return h;
+ return h;
}
-Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return (Hashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
+Hashmap *
+internal_hashmap_new (const struct hash_ops * hash_ops HASHMAP_DEBUG_PARAMS)
+{
+ return (Hashmap *) hashmap_base_new (hash_ops,
+ HASHMAP_TYPE_PLAIN
+ HASHMAP_DEBUG_PASS_ARGS);
}
-OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return (OrderedHashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
+OrderedHashmap *
+internal_ordered_hashmap_new (const struct hash_ops *
+ hash_ops HASHMAP_DEBUG_PARAMS)
+{
+ return (OrderedHashmap *) hashmap_base_new (hash_ops,
+ HASHMAP_TYPE_ORDERED
+ HASHMAP_DEBUG_PASS_ARGS);
}
-Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return (Set*) hashmap_base_new(hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
+Set *
+internal_set_new (const struct hash_ops * hash_ops HASHMAP_DEBUG_PARAMS)
+{
+ return (Set *) hashmap_base_new (hash_ops,
+ HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
}
-static int hashmap_base_ensure_allocated(HashmapBase **h, const struct hash_ops *hash_ops,
- enum HashmapType type HASHMAP_DEBUG_PARAMS) {
- HashmapBase *q;
+static int
+hashmap_base_ensure_allocated (HashmapBase ** h,
+ const struct hash_ops *hash_ops,
+ enum HashmapType type HASHMAP_DEBUG_PARAMS)
+{
+ HashmapBase *q;
- assert(h);
+ assert (h);
- if (*h)
- return 0;
+ if (*h)
+ return 0;
- q = hashmap_base_new(hash_ops, type HASHMAP_DEBUG_PASS_ARGS);
- if (!q)
- return -ENOMEM;
+ q = hashmap_base_new (hash_ops, type HASHMAP_DEBUG_PASS_ARGS);
+ if (!q)
+ return -ENOMEM;
- *h = q;
- return 0;
+ *h = q;
+ return 0;
}
-int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
+int
+internal_hashmap_ensure_allocated (Hashmap ** h,
+ const struct hash_ops *hash_ops
+ HASHMAP_DEBUG_PARAMS)
+{
+ return hashmap_base_ensure_allocated ((HashmapBase **) h, hash_ops,
+ HASHMAP_TYPE_PLAIN
+ HASHMAP_DEBUG_PASS_ARGS);
}
-int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
+int
+internal_ordered_hashmap_ensure_allocated (OrderedHashmap ** h,
+ const struct hash_ops *hash_ops
+ HASHMAP_DEBUG_PARAMS)
+{
+ return hashmap_base_ensure_allocated ((HashmapBase **) h, hash_ops,
+ HASHMAP_TYPE_ORDERED
+ HASHMAP_DEBUG_PASS_ARGS);
}
-int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return hashmap_base_ensure_allocated((HashmapBase**)s, hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
+int
+internal_set_ensure_allocated (Set ** s,
+ const struct hash_ops *hash_ops
+ HASHMAP_DEBUG_PARAMS)
+{
+ return hashmap_base_ensure_allocated ((HashmapBase **) s, hash_ops,
+ HASHMAP_TYPE_SET
+ HASHMAP_DEBUG_PASS_ARGS);
}
-static void hashmap_free_no_clear(HashmapBase *h) {
- assert(!h->has_indirect);
- assert(!h->n_direct_entries);
+static void
+hashmap_free_no_clear (HashmapBase * h)
+{
+ assert (!h->has_indirect);
+ assert (!h->n_direct_entries);
#ifdef ENABLE_DEBUG_HASHMAP
- LIST_REMOVE(debug_list, hashmap_debug_list, &h->debug);
+ LIST_REMOVE (debug_list, hashmap_debug_list, &h->debug);
#endif
- if (h->from_pool)
- mempool_free_tile(hashmap_type_info[h->type].mempool, h);
- else
- free(h);
+ if (h->from_pool)
+ mempool_free_tile (hashmap_type_info[h->type].mempool, h);
+ else
+ free (h);
}
-void internal_hashmap_free(HashmapBase *h) {
+void
+internal_hashmap_free (HashmapBase * h)
+{
- /* Free the hashmap, but nothing in it */
+ /* Free the hashmap, but nothing in it */
- if (!h)
- return;
+ if (!h)
+ return;
- internal_hashmap_clear(h);
- hashmap_free_no_clear(h);
+ internal_hashmap_clear (h);
+ hashmap_free_no_clear (h);
}
-void internal_hashmap_free_free(HashmapBase *h) {
+void
+internal_hashmap_free_free (HashmapBase * h)
+{
- /* Free the hashmap and all data objects in it, but not the
- * keys */
+ /* Free the hashmap and all data objects in it, but not the
+ * keys */
- if (!h)
- return;
+ if (!h)
+ return;
- internal_hashmap_clear_free(h);
- hashmap_free_no_clear(h);
+ internal_hashmap_clear_free (h);
+ hashmap_free_no_clear (h);
}
-void hashmap_free_free_free(Hashmap *h) {
+void
+hashmap_free_free_free (Hashmap * h)
+{
- /* Free the hashmap and all data and key objects in it */
+ /* Free the hashmap and all data and key objects in it */
- if (!h)
- return;
+ if (!h)
+ return;
- hashmap_clear_free_free(h);
- hashmap_free_no_clear(HASHMAP_BASE(h));
+ hashmap_clear_free_free (h);
+ hashmap_free_no_clear (HASHMAP_BASE (h));
}
-void internal_hashmap_clear(HashmapBase *h) {
- if (!h)
- return;
+void
+internal_hashmap_clear (HashmapBase * h)
+{
+ if (!h)
+ return;
- if (h->has_indirect) {
- free(h->indirect.storage);
- h->has_indirect = false;
- }
+ if (h->has_indirect)
+ {
+ free (h->indirect.storage);
+ h->has_indirect = false;
+ }
- h->n_direct_entries = 0;
- reset_direct_storage(h);
+ h->n_direct_entries = 0;
+ reset_direct_storage (h);
- if (h->type == HASHMAP_TYPE_ORDERED) {
- OrderedHashmap *lh = (OrderedHashmap*) h;
- lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL;
- }
+ if (h->type == HASHMAP_TYPE_ORDERED)
+ {
+ OrderedHashmap *lh = (OrderedHashmap *) h;
+ lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL;
+ }
}
-void internal_hashmap_clear_free(HashmapBase *h) {
- unsigned idx;
+void
+internal_hashmap_clear_free (HashmapBase * h)
+{
+ unsigned idx;
- if (!h)
- return;
+ if (!h)
+ return;
- for (idx = skip_free_buckets(h, 0); idx != IDX_NIL;
- idx = skip_free_buckets(h, idx + 1))
- free(entry_value(h, bucket_at(h, idx)));
+ for (idx = skip_free_buckets (h, 0); idx != IDX_NIL;
+ idx = skip_free_buckets (h, idx + 1))
+ free (entry_value (h, bucket_at (h, idx)));
- internal_hashmap_clear(h);
+ internal_hashmap_clear (h);
}
-void hashmap_clear_free_free(Hashmap *h) {
- unsigned idx;
+void
+hashmap_clear_free_free (Hashmap * h)
+{
+ unsigned idx;
- if (!h)
- return;
+ if (!h)
+ return;
- for (idx = skip_free_buckets(HASHMAP_BASE(h), 0); idx != IDX_NIL;
- idx = skip_free_buckets(HASHMAP_BASE(h), idx + 1)) {
- struct plain_hashmap_entry *e = plain_bucket_at(h, idx);
- free((void*)e->b.key);
- free(e->value);
- }
+ for (idx = skip_free_buckets (HASHMAP_BASE (h), 0); idx != IDX_NIL;
+ idx = skip_free_buckets (HASHMAP_BASE (h), idx + 1))
+ {
+ struct plain_hashmap_entry *e = plain_bucket_at (h, idx);
+ free ((void *) e->b.key);
+ free (e->value);
+ }
- internal_hashmap_clear(HASHMAP_BASE(h));
+ internal_hashmap_clear (HASHMAP_BASE (h));
}
-static int resize_buckets(HashmapBase *h, unsigned entries_add);
+static int resize_buckets (HashmapBase * h, unsigned entries_add);
/*
* Finds an empty bucket to put an entry into, starting the scan at 'idx'.
@@ -969,53 +1145,59 @@ static int resize_buckets(HashmapBase *h, unsigned entries_add);
* Returns: true if it left a displaced entry to rehash next in IDX_PUT,
* false otherwise.
*/
-static bool hashmap_put_robin_hood(HashmapBase *h, unsigned idx,
- struct swap_entries *swap) {
- dib_raw_t raw_dib, *dibs;
- unsigned dib, distance;
+static bool
+hashmap_put_robin_hood (HashmapBase * h, unsigned idx,
+ struct swap_entries *swap)
+{
+ dib_raw_t raw_dib, *dibs;
+ unsigned dib, distance;
#ifdef ENABLE_DEBUG_HASHMAP
- h->debug.put_count++;
+ h->debug.put_count++;
#endif
- dibs = dib_raw_ptr(h);
+ dibs = dib_raw_ptr (h);
- for (distance = 0; ; distance++) {
- raw_dib = dibs[idx];
- if (raw_dib == DIB_RAW_FREE || raw_dib == DIB_RAW_REHASH) {
- if (raw_dib == DIB_RAW_REHASH)
- bucket_move_entry(h, swap, idx, IDX_TMP);
+ for (distance = 0;; distance++)
+ {
+ raw_dib = dibs[idx];
+ if (raw_dib == DIB_RAW_FREE || raw_dib == DIB_RAW_REHASH)
+ {
+ if (raw_dib == DIB_RAW_REHASH)
+ bucket_move_entry (h, swap, idx, IDX_TMP);
- if (h->has_indirect && h->indirect.idx_lowest_entry > idx)
- h->indirect.idx_lowest_entry = idx;
+ if (h->has_indirect && h->indirect.idx_lowest_entry > idx)
+ h->indirect.idx_lowest_entry = idx;
- bucket_set_dib(h, idx, distance);
- bucket_move_entry(h, swap, IDX_PUT, idx);
- if (raw_dib == DIB_RAW_REHASH) {
- bucket_move_entry(h, swap, IDX_TMP, IDX_PUT);
- return true;
- }
+ bucket_set_dib (h, idx, distance);
+ bucket_move_entry (h, swap, IDX_PUT, idx);
+ if (raw_dib == DIB_RAW_REHASH)
+ {
+ bucket_move_entry (h, swap, IDX_TMP, IDX_PUT);
+ return true;
+ }
- return false;
- }
+ return false;
+ }
- dib = bucket_calculate_dib(h, idx, raw_dib);
+ dib = bucket_calculate_dib (h, idx, raw_dib);
- if (dib < distance) {
- /* Found a wealthier entry. Go Robin Hood! */
+ if (dib < distance)
+ {
+ /* Found a wealthier entry. Go Robin Hood! */
- bucket_set_dib(h, idx, distance);
+ bucket_set_dib (h, idx, distance);
- /* swap the entries */
- bucket_move_entry(h, swap, idx, IDX_TMP);
- bucket_move_entry(h, swap, IDX_PUT, idx);
- bucket_move_entry(h, swap, IDX_TMP, IDX_PUT);
+ /* swap the entries */
+ bucket_move_entry (h, swap, idx, IDX_TMP);
+ bucket_move_entry (h, swap, IDX_PUT, idx);
+ bucket_move_entry (h, swap, IDX_TMP, IDX_PUT);
- distance = dib;
- }
+ distance = dib;
+ }
- idx = next_idx(h, idx);
- }
+ idx = next_idx (h, idx);
+ }
}
/*
@@ -1028,52 +1210,58 @@ static bool hashmap_put_robin_hood(HashmapBase *h, unsigned idx,
* -ENOMEM if may_resize==true and resize failed with -ENOMEM.
* Cannot return -ENOMEM if !may_resize.
*/
-static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx,
- struct swap_entries *swap, bool may_resize) {
- struct ordered_hashmap_entry *new_entry;
- int r;
-
- assert(idx < n_buckets(h));
-
- new_entry = bucket_at_swap(swap, IDX_PUT);
-
- if (may_resize) {
- r = resize_buckets(h, 1);
- if (r < 0)
- return r;
- if (r > 0)
- idx = bucket_hash(h, new_entry->p.b.key);
- }
- assert(n_entries(h) < n_buckets(h));
-
- if (h->type == HASHMAP_TYPE_ORDERED) {
- OrderedHashmap *lh = (OrderedHashmap*) h;
-
- new_entry->iterate_next = IDX_NIL;
- new_entry->iterate_previous = lh->iterate_list_tail;
-
- if (lh->iterate_list_tail != IDX_NIL) {
- struct ordered_hashmap_entry *old_tail;
-
- old_tail = ordered_bucket_at(lh, lh->iterate_list_tail);
- assert(old_tail->iterate_next == IDX_NIL);
- old_tail->iterate_next = IDX_PUT;
- }
-
- lh->iterate_list_tail = IDX_PUT;
- if (lh->iterate_list_head == IDX_NIL)
- lh->iterate_list_head = IDX_PUT;
- }
-
- assert_se(hashmap_put_robin_hood(h, idx, swap) == false);
-
- n_entries_inc(h);
+static int
+hashmap_base_put_boldly (HashmapBase * h, unsigned idx,
+ struct swap_entries *swap, bool may_resize)
+{
+ struct ordered_hashmap_entry *new_entry;
+ int r;
+
+ assert (idx < n_buckets (h));
+
+ new_entry = bucket_at_swap (swap, IDX_PUT);
+
+ if (may_resize)
+ {
+ r = resize_buckets (h, 1);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ idx = bucket_hash (h, new_entry->p.b.key);
+ }
+ assert (n_entries (h) < n_buckets (h));
+
+ if (h->type == HASHMAP_TYPE_ORDERED)
+ {
+ OrderedHashmap *lh = (OrderedHashmap *) h;
+
+ new_entry->iterate_next = IDX_NIL;
+ new_entry->iterate_previous = lh->iterate_list_tail;
+
+ if (lh->iterate_list_tail != IDX_NIL)
+ {
+ struct ordered_hashmap_entry *old_tail;
+
+ old_tail = ordered_bucket_at (lh, lh->iterate_list_tail);
+ assert (old_tail->iterate_next == IDX_NIL);
+ old_tail->iterate_next = IDX_PUT;
+ }
+
+ lh->iterate_list_tail = IDX_PUT;
+ if (lh->iterate_list_head == IDX_NIL)
+ lh->iterate_list_head = IDX_PUT;
+ }
+
+ assert_se (hashmap_put_robin_hood (h, idx, swap) == false);
+
+ n_entries_inc (h);
#ifdef ENABLE_DEBUG_HASHMAP
- h->debug.max_entries = MAX(h->debug.max_entries, n_entries(h));
+ h->debug.max_entries = MAX (h->debug.max_entries, n_entries (h));
#endif
- return 1;
+ return 1;
}
+
#define hashmap_put_boldly(h, idx, swap, may_resize) \
hashmap_base_put_boldly(HASHMAP_BASE(h), idx, swap, may_resize)
@@ -1082,586 +1270,659 @@ static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx,
* 1 if successfully resized.
* -ENOMEM on allocation failure.
*/
-static int resize_buckets(HashmapBase *h, unsigned entries_add) {
- struct swap_entries swap;
- char *new_storage;
- dib_raw_t *old_dibs, *new_dibs;
- const struct hashmap_type_info *hi;
- unsigned idx, optimal_idx;
- unsigned old_n_buckets, new_n_buckets, n_rehashed, new_n_entries;
- uint8_t new_shift;
- bool rehash_next;
-
- assert(h);
-
- hi = &hashmap_type_info[h->type];
- new_n_entries = n_entries(h) + entries_add;
-
- /* overflow? */
- if (_unlikely_(new_n_entries < entries_add))
- return -ENOMEM;
-
- /* For direct storage we allow 100% load, because it's tiny. */
- if (!h->has_indirect && new_n_entries <= hi->n_direct_buckets)
- return 0;
-
- /*
- * Load factor = n/m = 1 - (1/INV_KEEP_FREE).
- * From it follows: m = n + n/(INV_KEEP_FREE - 1)
- */
- new_n_buckets = new_n_entries + new_n_entries / (INV_KEEP_FREE - 1);
- /* overflow? */
- if (_unlikely_(new_n_buckets < new_n_entries))
- return -ENOMEM;
-
- if (_unlikely_(new_n_buckets > UINT_MAX / (hi->entry_size + sizeof(dib_raw_t))))
- return -ENOMEM;
-
- old_n_buckets = n_buckets(h);
-
- if (_likely_(new_n_buckets <= old_n_buckets))
- return 0;
-
- new_shift = log2u_round_up(MAX(
- new_n_buckets * (hi->entry_size + sizeof(dib_raw_t)),
- 2 * sizeof(struct direct_storage)));
-
- /* Realloc storage (buckets and DIB array). */
- new_storage = realloc(h->has_indirect ? h->indirect.storage : NULL,
- 1U << new_shift);
- if (!new_storage)
- return -ENOMEM;
-
- /* Must upgrade direct to indirect storage. */
- if (!h->has_indirect) {
- memcpy(new_storage, h->direct.storage,
- old_n_buckets * (hi->entry_size + sizeof(dib_raw_t)));
- h->indirect.n_entries = h->n_direct_entries;
- h->indirect.idx_lowest_entry = 0;
- h->n_direct_entries = 0;
- }
-
- /* Get a new hash key. If we've just upgraded to indirect storage,
- * allow reusing a previously generated key. It's still a different key
- * from the shared one that we used for direct storage. */
- get_hash_key(h->indirect.hash_key, !h->has_indirect);
-
- h->has_indirect = true;
- h->indirect.storage = new_storage;
- h->indirect.n_buckets = (1U << new_shift) /
- (hi->entry_size + sizeof(dib_raw_t));
-
- old_dibs = (dib_raw_t*)(new_storage + hi->entry_size * old_n_buckets);
- new_dibs = dib_raw_ptr(h);
-
- /*
- * Move the DIB array to the new place, replacing valid DIB values with
- * DIB_RAW_REHASH to indicate all of the used buckets need rehashing.
- * Note: Overlap is not possible, because we have at least doubled the
- * number of buckets and dib_raw_t is smaller than any entry type.
- */
- for (idx = 0; idx < old_n_buckets; idx++) {
- assert(old_dibs[idx] != DIB_RAW_REHASH);
- new_dibs[idx] = old_dibs[idx] == DIB_RAW_FREE ? DIB_RAW_FREE
- : DIB_RAW_REHASH;
- }
-
- /* Zero the area of newly added entries (including the old DIB area) */
- memzero(bucket_at(h, old_n_buckets),
- (n_buckets(h) - old_n_buckets) * hi->entry_size);
-
- /* The upper half of the new DIB array needs initialization */
- memset(&new_dibs[old_n_buckets], DIB_RAW_INIT,
- (n_buckets(h) - old_n_buckets) * sizeof(dib_raw_t));
-
- /* Rehash entries that need it */
- n_rehashed = 0;
- for (idx = 0; idx < old_n_buckets; idx++) {
- if (new_dibs[idx] != DIB_RAW_REHASH)
- continue;
-
- optimal_idx = bucket_hash(h, bucket_at(h, idx)->key);
-
- /*
- * Not much to do if by luck the entry hashes to its current
- * location. Just set its DIB.
- */
- if (optimal_idx == idx) {
- new_dibs[idx] = 0;
- n_rehashed++;
- continue;
- }
-
- new_dibs[idx] = DIB_RAW_FREE;
- bucket_move_entry(h, &swap, idx, IDX_PUT);
- /* bucket_move_entry does not clear the source */
- memzero(bucket_at(h, idx), hi->entry_size);
-
- do {
- /*
- * Find the new bucket for the current entry. This may make
- * another entry homeless and load it into IDX_PUT.
- */
- rehash_next = hashmap_put_robin_hood(h, optimal_idx, &swap);
- n_rehashed++;
-
- /* Did the current entry displace another one? */
- if (rehash_next)
- optimal_idx = bucket_hash(h, bucket_at_swap(&swap, IDX_PUT)->p.b.key);
- } while (rehash_next);
- }
-
- assert(n_rehashed == n_entries(h));
-
- return 1;
+static int
+resize_buckets (HashmapBase * h, unsigned entries_add)
+{
+ struct swap_entries swap;
+ char *new_storage;
+ dib_raw_t *old_dibs, *new_dibs;
+ const struct hashmap_type_info *hi;
+ unsigned idx, optimal_idx;
+ unsigned old_n_buckets, new_n_buckets, n_rehashed, new_n_entries;
+ uint8_t new_shift;
+ bool rehash_next;
+
+ assert (h);
+
+ hi = &hashmap_type_info[h->type];
+ new_n_entries = n_entries (h) + entries_add;
+
+ /* overflow? */
+ if (_unlikely_ (new_n_entries < entries_add))
+ return -ENOMEM;
+
+ /* For direct storage we allow 100% load, because it's tiny. */
+ if (!h->has_indirect && new_n_entries <= hi->n_direct_buckets)
+ return 0;
+
+ /*
+ * Load factor = n/m = 1 - (1/INV_KEEP_FREE).
+ * From it follows: m = n + n/(INV_KEEP_FREE - 1)
+ */
+ new_n_buckets = new_n_entries + new_n_entries / (INV_KEEP_FREE - 1);
+ /* overflow? */
+ if (_unlikely_ (new_n_buckets < new_n_entries))
+ return -ENOMEM;
+
+ if (_unlikely_
+ (new_n_buckets > UINT_MAX / (hi->entry_size + sizeof (dib_raw_t))))
+ return -ENOMEM;
+
+ old_n_buckets = n_buckets (h);
+
+ if (_likely_ (new_n_buckets <= old_n_buckets))
+ return 0;
+
+ new_shift =
+ log2u_round_up (MAX
+ (new_n_buckets *
+ (hi->entry_size + sizeof (dib_raw_t)),
+ 2 * sizeof (struct direct_storage)));
+
+ /* Realloc storage (buckets and DIB array). */
+ new_storage = realloc (h->has_indirect ? h->indirect.storage : NULL,
+ 1U << new_shift);
+ if (!new_storage)
+ return -ENOMEM;
+
+ /* Must upgrade direct to indirect storage. */
+ if (!h->has_indirect)
+ {
+ memcpy (new_storage, h->direct.storage,
+ old_n_buckets * (hi->entry_size + sizeof (dib_raw_t)));
+ h->indirect.n_entries = h->n_direct_entries;
+ h->indirect.idx_lowest_entry = 0;
+ h->n_direct_entries = 0;
+ }
+
+ /* Get a new hash key. If we've just upgraded to indirect storage,
+ * allow reusing a previously generated key. It's still a different key
+ * from the shared one that we used for direct storage. */
+ get_hash_key (h->indirect.hash_key, !h->has_indirect);
+
+ h->has_indirect = true;
+ h->indirect.storage = new_storage;
+ h->indirect.n_buckets = (1U << new_shift) /
+ (hi->entry_size + sizeof (dib_raw_t));
+
+ old_dibs = (dib_raw_t *) (new_storage + hi->entry_size * old_n_buckets);
+ new_dibs = dib_raw_ptr (h);
+
+ /*
+ * Move the DIB array to the new place, replacing valid DIB values with
+ * DIB_RAW_REHASH to indicate all of the used buckets need rehashing.
+ * Note: Overlap is not possible, because we have at least doubled the
+ * number of buckets and dib_raw_t is smaller than any entry type.
+ */
+ for (idx = 0; idx < old_n_buckets; idx++)
+ {
+ assert (old_dibs[idx] != DIB_RAW_REHASH);
+ new_dibs[idx] = old_dibs[idx] == DIB_RAW_FREE ? DIB_RAW_FREE
+ : DIB_RAW_REHASH;
+ }
+
+ /* Zero the area of newly added entries (including the old DIB area) */
+ memzero (bucket_at (h, old_n_buckets),
+ (n_buckets (h) - old_n_buckets) * hi->entry_size);
+
+ /* The upper half of the new DIB array needs initialization */
+ memset (&new_dibs[old_n_buckets], DIB_RAW_INIT,
+ (n_buckets (h) - old_n_buckets) * sizeof (dib_raw_t));
+
+ /* Rehash entries that need it */
+ n_rehashed = 0;
+ for (idx = 0; idx < old_n_buckets; idx++)
+ {
+ if (new_dibs[idx] != DIB_RAW_REHASH)
+ continue;
+
+ optimal_idx = bucket_hash (h, bucket_at (h, idx)->key);
+
+ /*
+ * Not much to do if by luck the entry hashes to its current
+ * location. Just set its DIB.
+ */
+ if (optimal_idx == idx)
+ {
+ new_dibs[idx] = 0;
+ n_rehashed++;
+ continue;
+ }
+
+ new_dibs[idx] = DIB_RAW_FREE;
+ bucket_move_entry (h, &swap, idx, IDX_PUT);
+ /* bucket_move_entry does not clear the source */
+ memzero (bucket_at (h, idx), hi->entry_size);
+
+ do
+ {
+ /*
+ * Find the new bucket for the current entry. This may make
+ * another entry homeless and load it into IDX_PUT.
+ */
+ rehash_next = hashmap_put_robin_hood (h, optimal_idx, &swap);
+ n_rehashed++;
+
+ /* Did the current entry displace another one? */
+ if (rehash_next)
+ optimal_idx =
+ bucket_hash (h, bucket_at_swap (&swap, IDX_PUT)->p.b.key);
+ }
+ while (rehash_next);
+ }
+
+ assert (n_rehashed == n_entries (h));
+
+ return 1;
}
/*
* Finds an entry with a matching key
* Returns: index of the found entry, or IDX_NIL if not found.
*/
-static unsigned base_bucket_scan(HashmapBase *h, unsigned idx, const void *key) {
- struct hashmap_base_entry *e;
- unsigned dib, distance;
- dib_raw_t *dibs = dib_raw_ptr(h);
-
- assert(idx < n_buckets(h));
+static unsigned
+base_bucket_scan (HashmapBase * h, unsigned idx, const void *key)
+{
+ struct hashmap_base_entry *e;
+ unsigned dib, distance;
+ dib_raw_t *dibs = dib_raw_ptr (h);
- for (distance = 0; ; distance++) {
- if (dibs[idx] == DIB_RAW_FREE)
- return IDX_NIL;
+ assert (idx < n_buckets (h));
- dib = bucket_calculate_dib(h, idx, dibs[idx]);
+ for (distance = 0;; distance++)
+ {
+ if (dibs[idx] == DIB_RAW_FREE)
+ return IDX_NIL;
- if (dib < distance)
- return IDX_NIL;
- if (dib == distance) {
- e = bucket_at(h, idx);
- if (h->hash_ops->compare(e->key, key) == 0)
- return idx;
- }
+ dib = bucket_calculate_dib (h, idx, dibs[idx]);
- idx = next_idx(h, idx);
- }
-}
-#define bucket_scan(h, idx, key) base_bucket_scan(HASHMAP_BASE(h), idx, key)
-
-int hashmap_put(Hashmap *h, const void *key, void *value) {
- struct swap_entries swap;
- struct plain_hashmap_entry *e;
- unsigned hash, idx;
-
- assert(h);
+ if (dib < distance)
+ return IDX_NIL;
+ if (dib == distance)
+ {
+ e = bucket_at (h, idx);
+ if (h->hash_ops->compare (e->key, key) == 0)
+ return idx;
+ }
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx != IDX_NIL) {
- e = plain_bucket_at(h, idx);
- if (e->value == value)
- return 0;
- return -EEXIST;
- }
-
- e = &bucket_at_swap(&swap, IDX_PUT)->p;
- e->b.key = key;
- e->value = value;
- return hashmap_put_boldly(h, hash, &swap, true);
+ idx = next_idx (h, idx);
+ }
}
-int set_put(Set *s, const void *key) {
- struct swap_entries swap;
- struct hashmap_base_entry *e;
- unsigned hash, idx;
-
- assert(s);
-
- hash = bucket_hash(s, key);
- idx = bucket_scan(s, hash, key);
- if (idx != IDX_NIL)
- return 0;
-
- e = &bucket_at_swap(&swap, IDX_PUT)->p.b;
- e->key = key;
- return hashmap_put_boldly(s, hash, &swap, true);
-}
-
-int hashmap_replace(Hashmap *h, const void *key, void *value) {
- struct swap_entries swap;
- struct plain_hashmap_entry *e;
- unsigned hash, idx;
-
- assert(h);
+#define bucket_scan(h, idx, key) base_bucket_scan(HASHMAP_BASE(h), idx, key)
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx != IDX_NIL) {
- e = plain_bucket_at(h, idx);
+int
+hashmap_put (Hashmap * h, const void *key, void *value)
+{
+ struct swap_entries swap;
+ struct plain_hashmap_entry *e;
+ unsigned hash, idx;
+
+ assert (h);
+
+ hash = bucket_hash (h, key);
+ idx = bucket_scan (h, hash, key);
+ if (idx != IDX_NIL)
+ {
+ e = plain_bucket_at (h, idx);
+ if (e->value == value)
+ return 0;
+ return -EEXIST;
+ }
+
+ e = &bucket_at_swap (&swap, IDX_PUT)->p;
+ e->b.key = key;
+ e->value = value;
+ return hashmap_put_boldly (h, hash, &swap, true);
+}
+
+int
+set_put (Set * s, const void *key)
+{
+ struct swap_entries swap;
+ struct hashmap_base_entry *e;
+ unsigned hash, idx;
+
+ assert (s);
+
+ hash = bucket_hash (s, key);
+ idx = bucket_scan (s, hash, key);
+ if (idx != IDX_NIL)
+ return 0;
+
+ e = &bucket_at_swap (&swap, IDX_PUT)->p.b;
+ e->key = key;
+ return hashmap_put_boldly (s, hash, &swap, true);
+}
+
+int
+hashmap_replace (Hashmap * h, const void *key, void *value)
+{
+ struct swap_entries swap;
+ struct plain_hashmap_entry *e;
+ unsigned hash, idx;
+
+ assert (h);
+
+ hash = bucket_hash (h, key);
+ idx = bucket_scan (h, hash, key);
+ if (idx != IDX_NIL)
+ {
+ e = plain_bucket_at (h, idx);
#ifdef ENABLE_DEBUG_HASHMAP
- /* Although the key is equal, the key pointer may have changed,
- * and this would break our assumption for iterating. So count
- * this operation as incompatible with iteration. */
- if (e->b.key != key) {
- h->b.debug.put_count++;
- h->b.debug.rem_count++;
- h->b.debug.last_rem_idx = idx;
- }
+ /* Although the key is equal, the key pointer may have changed,
+ * and this would break our assumption for iterating. So count
+ * this operation as incompatible with iteration. */
+ if (e->b.key != key)
+ {
+ h->b.debug.put_count++;
+ h->b.debug.rem_count++;
+ h->b.debug.last_rem_idx = idx;
+ }
#endif
- e->b.key = key;
- e->value = value;
- return 0;
- }
+ e->b.key = key;
+ e->value = value;
+ return 0;
+ }
- e = &bucket_at_swap(&swap, IDX_PUT)->p;
- e->b.key = key;
- e->value = value;
- return hashmap_put_boldly(h, hash, &swap, true);
+ e = &bucket_at_swap (&swap, IDX_PUT)->p;
+ e->b.key = key;
+ e->value = value;
+ return hashmap_put_boldly (h, hash, &swap, true);
}
-int hashmap_update(Hashmap *h, const void *key, void *value) {
- struct plain_hashmap_entry *e;
- unsigned hash, idx;
+int
+hashmap_update (Hashmap * h, const void *key, void *value)
+{
+ struct plain_hashmap_entry *e;
+ unsigned hash, idx;
- assert(h);
+ assert (h);
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx == IDX_NIL)
- return -ENOENT;
+ hash = bucket_hash (h, key);
+ idx = bucket_scan (h, hash, key);
+ if (idx == IDX_NIL)
+ return -ENOENT;
- e = plain_bucket_at(h, idx);
- e->value = value;
- return 0;
+ e = plain_bucket_at (h, idx);
+ e->value = value;
+ return 0;
}
-void *internal_hashmap_get(HashmapBase *h, const void *key) {
- struct hashmap_base_entry *e;
- unsigned hash, idx;
+void *
+internal_hashmap_get (HashmapBase * h, const void *key)
+{
+ struct hashmap_base_entry *e;
+ unsigned hash, idx;
- if (!h)
- return NULL;
+ if (!h)
+ return NULL;
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx == IDX_NIL)
- return NULL;
+ hash = bucket_hash (h, key);
+ idx = bucket_scan (h, hash, key);
+ if (idx == IDX_NIL)
+ return NULL;
- e = bucket_at(h, idx);
- return entry_value(h, e);
+ e = bucket_at (h, idx);
+ return entry_value (h, e);
}
-void *hashmap_get2(Hashmap *h, const void *key, void **key2) {
- struct plain_hashmap_entry *e;
- unsigned hash, idx;
+void *
+hashmap_get2 (Hashmap * h, const void *key, void **key2)
+{
+ struct plain_hashmap_entry *e;
+ unsigned hash, idx;
- if (!h)
- return NULL;
+ if (!h)
+ return NULL;
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx == IDX_NIL)
- return NULL;
+ hash = bucket_hash (h, key);
+ idx = bucket_scan (h, hash, key);
+ if (idx == IDX_NIL)
+ return NULL;
- e = plain_bucket_at(h, idx);
- if (key2)
- *key2 = (void*) e->b.key;
+ e = plain_bucket_at (h, idx);
+ if (key2)
+ *key2 = (void *) e->b.key;
- return e->value;
+ return e->value;
}
-bool internal_hashmap_contains(HashmapBase *h, const void *key) {
- unsigned hash;
+bool
+internal_hashmap_contains (HashmapBase * h, const void *key)
+{
+ unsigned hash;
- if (!h)
- return false;
+ if (!h)
+ return false;
- hash = bucket_hash(h, key);
- return bucket_scan(h, hash, key) != IDX_NIL;
+ hash = bucket_hash (h, key);
+ return bucket_scan (h, hash, key) != IDX_NIL;
}
-void *internal_hashmap_remove(HashmapBase *h, const void *key) {
- struct hashmap_base_entry *e;
- unsigned hash, idx;
- void *data;
+void *
+internal_hashmap_remove (HashmapBase * h, const void *key)
+{
+ struct hashmap_base_entry *e;
+ unsigned hash, idx;
+ void *data;
- if (!h)
- return NULL;
+ if (!h)
+ return NULL;
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx == IDX_NIL)
- return NULL;
+ hash = bucket_hash (h, key);
+ idx = bucket_scan (h, hash, key);
+ if (idx == IDX_NIL)
+ return NULL;
- e = bucket_at(h, idx);
- data = entry_value(h, e);
- remove_entry(h, idx);
+ e = bucket_at (h, idx);
+ data = entry_value (h, e);
+ remove_entry (h, idx);
- return data;
+ return data;
}
-void *hashmap_remove2(Hashmap *h, const void *key, void **rkey) {
- struct plain_hashmap_entry *e;
- unsigned hash, idx;
- void *data;
+void *
+hashmap_remove2 (Hashmap * h, const void *key, void **rkey)
+{
+ struct plain_hashmap_entry *e;
+ unsigned hash, idx;
+ void *data;
- if (!h) {
- if (rkey)
- *rkey = NULL;
- return NULL;
- }
+ if (!h)
+ {
+ if (rkey)
+ *rkey = NULL;
+ return NULL;
+ }
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx == IDX_NIL) {
- if (rkey)
- *rkey = NULL;
- return NULL;
- }
+ hash = bucket_hash (h, key);
+ idx = bucket_scan (h, hash, key);
+ if (idx == IDX_NIL)
+ {
+ if (rkey)
+ *rkey = NULL;
+ return NULL;
+ }
- e = plain_bucket_at(h, idx);
- data = e->value;
- if (rkey)
- *rkey = (void*) e->b.key;
+ e = plain_bucket_at (h, idx);
+ data = e->value;
+ if (rkey)
+ *rkey = (void *) e->b.key;
- remove_entry(h, idx);
+ remove_entry (h, idx);
- return data;
+ return data;
}
-int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value) {
- struct swap_entries swap;
- struct plain_hashmap_entry *e;
- unsigned old_hash, new_hash, idx;
+int
+hashmap_remove_and_put (Hashmap * h, const void *old_key,
+ const void *new_key, void *value)
+{
+ struct swap_entries swap;
+ struct plain_hashmap_entry *e;
+ unsigned old_hash, new_hash, idx;
- if (!h)
- return -ENOENT;
+ if (!h)
+ return -ENOENT;
- old_hash = bucket_hash(h, old_key);
- idx = bucket_scan(h, old_hash, old_key);
- if (idx == IDX_NIL)
- return -ENOENT;
+ old_hash = bucket_hash (h, old_key);
+ idx = bucket_scan (h, old_hash, old_key);
+ if (idx == IDX_NIL)
+ return -ENOENT;
- new_hash = bucket_hash(h, new_key);
- if (bucket_scan(h, new_hash, new_key) != IDX_NIL)
- return -EEXIST;
+ new_hash = bucket_hash (h, new_key);
+ if (bucket_scan (h, new_hash, new_key) != IDX_NIL)
+ return -EEXIST;
- remove_entry(h, idx);
+ remove_entry (h, idx);
- e = &bucket_at_swap(&swap, IDX_PUT)->p;
- e->b.key = new_key;
- e->value = value;
- assert_se(hashmap_put_boldly(h, new_hash, &swap, false) == 1);
+ e = &bucket_at_swap (&swap, IDX_PUT)->p;
+ e->b.key = new_key;
+ e->value = value;
+ assert_se (hashmap_put_boldly (h, new_hash, &swap, false) == 1);
- return 0;
+ return 0;
}
-int set_remove_and_put(Set *s, const void *old_key, const void *new_key) {
- struct swap_entries swap;
- struct hashmap_base_entry *e;
- unsigned old_hash, new_hash, idx;
+int
+set_remove_and_put (Set * s, const void *old_key, const void *new_key)
+{
+ struct swap_entries swap;
+ struct hashmap_base_entry *e;
+ unsigned old_hash, new_hash, idx;
- if (!s)
- return -ENOENT;
+ if (!s)
+ return -ENOENT;
- old_hash = bucket_hash(s, old_key);
- idx = bucket_scan(s, old_hash, old_key);
- if (idx == IDX_NIL)
- return -ENOENT;
+ old_hash = bucket_hash (s, old_key);
+ idx = bucket_scan (s, old_hash, old_key);
+ if (idx == IDX_NIL)
+ return -ENOENT;
- new_hash = bucket_hash(s, new_key);
- if (bucket_scan(s, new_hash, new_key) != IDX_NIL)
- return -EEXIST;
+ new_hash = bucket_hash (s, new_key);
+ if (bucket_scan (s, new_hash, new_key) != IDX_NIL)
+ return -EEXIST;
- remove_entry(s, idx);
+ remove_entry (s, idx);
- e = &bucket_at_swap(&swap, IDX_PUT)->p.b;
- e->key = new_key;
- assert_se(hashmap_put_boldly(s, new_hash, &swap, false) == 1);
+ e = &bucket_at_swap (&swap, IDX_PUT)->p.b;
+ e->key = new_key;
+ assert_se (hashmap_put_boldly (s, new_hash, &swap, false) == 1);
- return 0;
+ return 0;
}
-int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value) {
- struct swap_entries swap;
- struct plain_hashmap_entry *e;
- unsigned old_hash, new_hash, idx_old, idx_new;
+int
+hashmap_remove_and_replace (Hashmap * h, const void *old_key,
+ const void *new_key, void *value)
+{
+ struct swap_entries swap;
+ struct plain_hashmap_entry *e;
+ unsigned old_hash, new_hash, idx_old, idx_new;
- if (!h)
- return -ENOENT;
+ if (!h)
+ return -ENOENT;
- old_hash = bucket_hash(h, old_key);
- idx_old = bucket_scan(h, old_hash, old_key);
- if (idx_old == IDX_NIL)
- return -ENOENT;
+ old_hash = bucket_hash (h, old_key);
+ idx_old = bucket_scan (h, old_hash, old_key);
+ if (idx_old == IDX_NIL)
+ return -ENOENT;
- old_key = bucket_at(HASHMAP_BASE(h), idx_old)->key;
+ old_key = bucket_at (HASHMAP_BASE (h), idx_old)->key;
- new_hash = bucket_hash(h, new_key);
- idx_new = bucket_scan(h, new_hash, new_key);
- if (idx_new != IDX_NIL)
- if (idx_old != idx_new) {
- remove_entry(h, idx_new);
- /* Compensate for a possible backward shift. */
- if (old_key != bucket_at(HASHMAP_BASE(h), idx_old)->key)
- idx_old = prev_idx(HASHMAP_BASE(h), idx_old);
- assert(old_key == bucket_at(HASHMAP_BASE(h), idx_old)->key);
- }
+ new_hash = bucket_hash (h, new_key);
+ idx_new = bucket_scan (h, new_hash, new_key);
+ if (idx_new != IDX_NIL)
+ if (idx_old != idx_new)
+ {
+ remove_entry (h, idx_new);
+ /* Compensate for a possible backward shift. */
+ if (old_key != bucket_at (HASHMAP_BASE (h), idx_old)->key)
+ idx_old = prev_idx (HASHMAP_BASE (h), idx_old);
+ assert (old_key == bucket_at (HASHMAP_BASE (h), idx_old)->key);
+ }
- remove_entry(h, idx_old);
+ remove_entry (h, idx_old);
- e = &bucket_at_swap(&swap, IDX_PUT)->p;
- e->b.key = new_key;
- e->value = value;
- assert_se(hashmap_put_boldly(h, new_hash, &swap, false) == 1);
+ e = &bucket_at_swap (&swap, IDX_PUT)->p;
+ e->b.key = new_key;
+ e->value = value;
+ assert_se (hashmap_put_boldly (h, new_hash, &swap, false) == 1);
- return 0;
+ return 0;
}
-void *hashmap_remove_value(Hashmap *h, const void *key, void *value) {
- struct plain_hashmap_entry *e;
- unsigned hash, idx;
+void *
+hashmap_remove_value (Hashmap * h, const void *key, void *value)
+{
+ struct plain_hashmap_entry *e;
+ unsigned hash, idx;
- if (!h)
- return NULL;
+ if (!h)
+ return NULL;
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx == IDX_NIL)
- return NULL;
+ hash = bucket_hash (h, key);
+ idx = bucket_scan (h, hash, key);
+ if (idx == IDX_NIL)
+ return NULL;
- e = plain_bucket_at(h, idx);
- if (e->value != value)
- return NULL;
+ e = plain_bucket_at (h, idx);
+ if (e->value != value)
+ return NULL;
- remove_entry(h, idx);
+ remove_entry (h, idx);
- return value;
+ return value;
}
-static unsigned find_first_entry(HashmapBase *h) {
- Iterator i = ITERATOR_FIRST;
+static unsigned
+find_first_entry (HashmapBase * h)
+{
+ Iterator i = ITERATOR_FIRST;
- if (!h || !n_entries(h))
- return IDX_NIL;
+ if (!h || !n_entries (h))
+ return IDX_NIL;
- return hashmap_iterate_entry(h, &i);
+ return hashmap_iterate_entry (h, &i);
}
-void *internal_hashmap_first(HashmapBase *h) {
- unsigned idx;
+void *
+internal_hashmap_first (HashmapBase * h)
+{
+ unsigned idx;
- idx = find_first_entry(h);
- if (idx == IDX_NIL)
- return NULL;
+ idx = find_first_entry (h);
+ if (idx == IDX_NIL)
+ return NULL;
- return entry_value(h, bucket_at(h, idx));
+ return entry_value (h, bucket_at (h, idx));
}
-void *internal_hashmap_first_key(HashmapBase *h) {
- struct hashmap_base_entry *e;
- unsigned idx;
+void *
+internal_hashmap_first_key (HashmapBase * h)
+{
+ struct hashmap_base_entry *e;
+ unsigned idx;
- idx = find_first_entry(h);
- if (idx == IDX_NIL)
- return NULL;
+ idx = find_first_entry (h);
+ if (idx == IDX_NIL)
+ return NULL;
- e = bucket_at(h, idx);
- return (void*) e->key;
+ e = bucket_at (h, idx);
+ return (void *) e->key;
}
-void *internal_hashmap_steal_first(HashmapBase *h) {
- struct hashmap_base_entry *e;
- void *data;
- unsigned idx;
+void *
+internal_hashmap_steal_first (HashmapBase * h)
+{
+ struct hashmap_base_entry *e;
+ void *data;
+ unsigned idx;
- idx = find_first_entry(h);
- if (idx == IDX_NIL)
- return NULL;
+ idx = find_first_entry (h);
+ if (idx == IDX_NIL)
+ return NULL;
- e = bucket_at(h, idx);
- data = entry_value(h, e);
- remove_entry(h, idx);
+ e = bucket_at (h, idx);
+ data = entry_value (h, e);
+ remove_entry (h, idx);
- return data;
+ return data;
}
-void *internal_hashmap_steal_first_key(HashmapBase *h) {
- struct hashmap_base_entry *e;
- void *key;
- unsigned idx;
+void *
+internal_hashmap_steal_first_key (HashmapBase * h)
+{
+ struct hashmap_base_entry *e;
+ void *key;
+ unsigned idx;
- idx = find_first_entry(h);
- if (idx == IDX_NIL)
- return NULL;
+ idx = find_first_entry (h);
+ if (idx == IDX_NIL)
+ return NULL;
- e = bucket_at(h, idx);
- key = (void*) e->key;
- remove_entry(h, idx);
+ e = bucket_at (h, idx);
+ key = (void *) e->key;
+ remove_entry (h, idx);
- return key;
+ return key;
}
-unsigned internal_hashmap_size(HashmapBase *h) {
+unsigned
+internal_hashmap_size (HashmapBase * h)
+{
- if (!h)
- return 0;
+ if (!h)
+ return 0;
- return n_entries(h);
+ return n_entries (h);
}
-unsigned internal_hashmap_buckets(HashmapBase *h) {
+unsigned
+internal_hashmap_buckets (HashmapBase * h)
+{
- if (!h)
- return 0;
+ if (!h)
+ return 0;
- return n_buckets(h);
+ return n_buckets (h);
}
-int internal_hashmap_merge(Hashmap *h, Hashmap *other) {
- Iterator i;
- unsigned idx;
+int
+internal_hashmap_merge (Hashmap * h, Hashmap * other)
+{
+ Iterator i;
+ unsigned idx;
- assert(h);
+ assert (h);
- HASHMAP_FOREACH_IDX(idx, HASHMAP_BASE(other), i) {
- struct plain_hashmap_entry *pe = plain_bucket_at(other, idx);
- int r;
+ HASHMAP_FOREACH_IDX (idx, HASHMAP_BASE (other), i)
+ {
+ struct plain_hashmap_entry *pe = plain_bucket_at (other, idx);
+ int r;
- r = hashmap_put(h, pe->b.key, pe->value);
- if (r < 0 && r != -EEXIST)
- return r;
- }
+ r = hashmap_put (h, pe->b.key, pe->value);
+ if (r < 0 && r != -EEXIST)
+ return r;
+ }
- return 0;
+ return 0;
}
-int set_merge(Set *s, Set *other) {
- Iterator i;
- unsigned idx;
+int
+set_merge (Set * s, Set * other)
+{
+ Iterator i;
+ unsigned idx;
- assert(s);
+ assert (s);
- HASHMAP_FOREACH_IDX(idx, HASHMAP_BASE(other), i) {
- struct set_entry *se = set_bucket_at(other, idx);
- int r;
+ HASHMAP_FOREACH_IDX (idx, HASHMAP_BASE (other), i)
+ {
+ struct set_entry *se = set_bucket_at (other, idx);
+ int r;
- r = set_put(s, se->b.key);
- if (r < 0)
- return r;
- }
+ r = set_put (s, se->b.key);
+ if (r < 0)
+ return r;
+ }
- return 0;
+ return 0;
}
-int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add) {
- int r;
+int
+internal_hashmap_reserve (HashmapBase * h, unsigned entries_add)
+{
+ int r;
- assert(h);
+ assert (h);
- r = resize_buckets(h, entries_add);
- if (r < 0)
- return r;
+ r = resize_buckets (h, entries_add);
+ if (r < 0)
+ return r;
- return 0;
+ return 0;
}
/*
@@ -1670,194 +1931,215 @@ int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add) {
* Returns: 0 on success.
* -ENOMEM on alloc failure, in which case no move has been done.
*/
-int internal_hashmap_move(HashmapBase *h, HashmapBase *other) {
- struct swap_entries swap;
- struct hashmap_base_entry *e, *n;
- Iterator i;
- unsigned idx;
- int r;
-
- assert(h);
-
- if (!other)
- return 0;
-
- assert(other->type == h->type);
-
- /*
- * This reserves buckets for the worst case, where none of other's
- * entries are yet present in h. This is preferable to risking
- * an allocation failure in the middle of the moving and having to
- * rollback or return a partial result.
- */
- r = resize_buckets(h, n_entries(other));
- if (r < 0)
- return r;
-
- HASHMAP_FOREACH_IDX(idx, other, i) {
- unsigned h_hash;
-
- e = bucket_at(other, idx);
- h_hash = bucket_hash(h, e->key);
- if (bucket_scan(h, h_hash, e->key) != IDX_NIL)
- continue;
-
- n = &bucket_at_swap(&swap, IDX_PUT)->p.b;
- n->key = e->key;
- if (h->type != HASHMAP_TYPE_SET)
- ((struct plain_hashmap_entry*) n)->value =
- ((struct plain_hashmap_entry*) e)->value;
- assert_se(hashmap_put_boldly(h, h_hash, &swap, false) == 1);
-
- remove_entry(other, idx);
- }
-
- return 0;
-}
-
-int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key) {
- struct swap_entries swap;
- unsigned h_hash, other_hash, idx;
- struct hashmap_base_entry *e, *n;
- int r;
-
- assert(h);
-
- h_hash = bucket_hash(h, key);
- if (bucket_scan(h, h_hash, key) != IDX_NIL)
- return -EEXIST;
-
- if (!other)
- return -ENOENT;
-
- assert(other->type == h->type);
-
- other_hash = bucket_hash(other, key);
- idx = bucket_scan(other, other_hash, key);
- if (idx == IDX_NIL)
- return -ENOENT;
-
- e = bucket_at(other, idx);
-
- n = &bucket_at_swap(&swap, IDX_PUT)->p.b;
- n->key = e->key;
- if (h->type != HASHMAP_TYPE_SET)
- ((struct plain_hashmap_entry*) n)->value =
- ((struct plain_hashmap_entry*) e)->value;
- r = hashmap_put_boldly(h, h_hash, &swap, true);
- if (r < 0)
- return r;
-
- remove_entry(other, idx);
- return 0;
-}
-
-HashmapBase *internal_hashmap_copy(HashmapBase *h) {
- HashmapBase *copy;
- int r;
+int
+internal_hashmap_move (HashmapBase * h, HashmapBase * other)
+{
+ struct swap_entries swap;
+ struct hashmap_base_entry *e, *n;
+ Iterator i;
+ unsigned idx;
+ int r;
+
+ assert (h);
+
+ if (!other)
+ return 0;
+
+ assert (other->type == h->type);
+
+ /*
+ * This reserves buckets for the worst case, where none of other's
+ * entries are yet present in h. This is preferable to risking
+ * an allocation failure in the middle of the moving and having to
+ * rollback or return a partial result.
+ */
+ r = resize_buckets (h, n_entries (other));
+ if (r < 0)
+ return r;
+
+ HASHMAP_FOREACH_IDX (idx, other, i)
+ {
+ unsigned h_hash;
+
+ e = bucket_at (other, idx);
+ h_hash = bucket_hash (h, e->key);
+ if (bucket_scan (h, h_hash, e->key) != IDX_NIL)
+ continue;
+
+ n = &bucket_at_swap (&swap, IDX_PUT)->p.b;
+ n->key = e->key;
+ if (h->type != HASHMAP_TYPE_SET)
+ ((struct plain_hashmap_entry *) n)->value =
+ ((struct plain_hashmap_entry *) e)->value;
+ assert_se (hashmap_put_boldly (h, h_hash, &swap, false) == 1);
+
+ remove_entry (other, idx);
+ }
+
+ return 0;
+}
+
+int
+internal_hashmap_move_one (HashmapBase * h, HashmapBase * other,
+ const void *key)
+{
+ struct swap_entries swap;
+ unsigned h_hash, other_hash, idx;
+ struct hashmap_base_entry *e, *n;
+ int r;
+
+ assert (h);
+
+ h_hash = bucket_hash (h, key);
+ if (bucket_scan (h, h_hash, key) != IDX_NIL)
+ return -EEXIST;
+
+ if (!other)
+ return -ENOENT;
+
+ assert (other->type == h->type);
+
+ other_hash = bucket_hash (other, key);
+ idx = bucket_scan (other, other_hash, key);
+ if (idx == IDX_NIL)
+ return -ENOENT;
+
+ e = bucket_at (other, idx);
- assert(h);
+ n = &bucket_at_swap (&swap, IDX_PUT)->p.b;
+ n->key = e->key;
+ if (h->type != HASHMAP_TYPE_SET)
+ ((struct plain_hashmap_entry *) n)->value =
+ ((struct plain_hashmap_entry *) e)->value;
+ r = hashmap_put_boldly (h, h_hash, &swap, true);
+ if (r < 0)
+ return r;
+
+ remove_entry (other, idx);
+ return 0;
+}
+
+HashmapBase *
+internal_hashmap_copy (HashmapBase * h)
+{
+ HashmapBase *copy;
+ int r;
- copy = hashmap_base_new(h->hash_ops, h->type HASHMAP_DEBUG_SRC_ARGS);
- if (!copy)
- return NULL;
+ assert (h);
- switch (h->type) {
- case HASHMAP_TYPE_PLAIN:
- case HASHMAP_TYPE_ORDERED:
- r = hashmap_merge((Hashmap*)copy, (Hashmap*)h);
- break;
- case HASHMAP_TYPE_SET:
- r = set_merge((Set*)copy, (Set*)h);
- break;
- default:
- assert_not_reached("Unknown hashmap type");
- }
+ copy = hashmap_base_new (h->hash_ops, h->type HASHMAP_DEBUG_SRC_ARGS);
+ if (!copy)
+ return NULL;
+
+ switch (h->type)
+ {
+ case HASHMAP_TYPE_PLAIN:
+ case HASHMAP_TYPE_ORDERED:
+ r = hashmap_merge ((Hashmap *) copy, (Hashmap *) h);
+ break;
+ case HASHMAP_TYPE_SET:
+ r = set_merge ((Set *) copy, (Set *) h);
+ break;
+ default:
+ assert_not_reached ("Unknown hashmap type");
+ }
- if (r < 0) {
- internal_hashmap_free(copy);
- return NULL;
- }
+ if (r < 0)
+ {
+ internal_hashmap_free (copy);
+ return NULL;
+ }
- return copy;
+ return copy;
}
-char **internal_hashmap_get_strv(HashmapBase *h) {
- char **sv;
- Iterator i;
- unsigned idx, n;
+char **
+internal_hashmap_get_strv (HashmapBase * h)
+{
+ char **sv;
+ Iterator i;
+ unsigned idx, n;
- sv = new(char*, n_entries(h)+1);
- if (!sv)
- return NULL;
+ sv = new (char *, n_entries (h) + 1);
+ if (!sv)
+ return NULL;
- n = 0;
- HASHMAP_FOREACH_IDX(idx, h, i)
- sv[n++] = entry_value(h, bucket_at(h, idx));
- sv[n] = NULL;
+ n = 0;
+ HASHMAP_FOREACH_IDX (idx, h, i)
+ sv[n++] = entry_value (h, bucket_at (h, idx));
+ sv[n] = NULL;
- return sv;
+ return sv;
}
-void *ordered_hashmap_next(OrderedHashmap *h, const void *key) {
- struct ordered_hashmap_entry *e;
- unsigned hash, idx;
+void *
+ordered_hashmap_next (OrderedHashmap * h, const void *key)
+{
+ struct ordered_hashmap_entry *e;
+ unsigned hash, idx;
- assert(key);
+ assert (key);
- if (!h)
- return NULL;
+ if (!h)
+ return NULL;
- hash = bucket_hash(h, key);
- idx = bucket_scan(h, hash, key);
- if (idx == IDX_NIL)
- return NULL;
+ hash = bucket_hash (h, key);
+ idx = bucket_scan (h, hash, key);
+ if (idx == IDX_NIL)
+ return NULL;
- e = ordered_bucket_at(h, idx);
- if (e->iterate_next == IDX_NIL)
- return NULL;
- return ordered_bucket_at(h, e->iterate_next)->p.value;
+ e = ordered_bucket_at (h, idx);
+ if (e->iterate_next == IDX_NIL)
+ return NULL;
+ return ordered_bucket_at (h, e->iterate_next)->p.value;
}
-int set_consume(Set *s, void *value) {
- int r;
+int
+set_consume (Set * s, void *value)
+{
+ int r;
- r = set_put(s, value);
- if (r <= 0)
- free(value);
+ r = set_put (s, value);
+ if (r <= 0)
+ free (value);
- return r;
+ return r;
}
-int set_put_strdup(Set *s, const char *p) {
- char *c;
- int r;
+int
+set_put_strdup (Set * s, const char *p)
+{
+ char *c;
+ int r;
- assert(s);
- assert(p);
+ assert (s);
+ assert (p);
- c = strdup(p);
- if (!c)
- return -ENOMEM;
+ c = strdup (p);
+ if (!c)
+ return -ENOMEM;
- r = set_consume(s, c);
- if (r == -EEXIST)
- return 0;
+ r = set_consume (s, c);
+ if (r == -EEXIST)
+ return 0;
- return r;
+ return r;
}
-int set_put_strdupv(Set *s, char **l) {
- int n = 0, r;
- char **i;
+int
+set_put_strdupv (Set * s, char **l)
+{
+ int n = 0, r;
+ char **i;
- STRV_FOREACH(i, l) {
- r = set_put_strdup(s, *i);
- if (r < 0)
- return r;
+ STRV_FOREACH (i, l)
+ {
+ r = set_put_strdup (s, *i);
+ if (r < 0)
+ return r;
- n += r;
- }
+ n += r;
+ }
- return n;
+ return n;
}
diff --git a/libudev-compat/hashmap.h b/libudev-compat/hashmap.h
index 1587e98..1941034 100644
--- a/libudev-compat/hashmap.h
+++ b/libudev-compat/hashmap.h
@@ -57,61 +57,72 @@
typedef struct HashmapBase HashmapBase;
/* Specific hashmap/set types */
-typedef struct Hashmap Hashmap; /* Maps keys to values */
-typedef struct OrderedHashmap OrderedHashmap; /* Like Hashmap, but also remembers entry insertion order */
-typedef struct Set Set; /* Stores just keys */
+typedef struct Hashmap Hashmap; /* Maps keys to values */
+typedef struct OrderedHashmap OrderedHashmap; /* Like Hashmap, but also remembers entry insertion order */
+typedef struct Set Set; /* Stores just keys */
/* Ideally the Iterator would be an opaque struct, but it is instantiated
* by hashmap users, so the definition has to be here. Do not use its fields
* directly. */
-typedef struct {
- unsigned idx; /* index of an entry to be iterated next */
- const void *next_key; /* expected value of that entry's key pointer */
+typedef struct
+{
+ unsigned idx; /* index of an entry to be iterated next */
+ const void *next_key; /* expected value of that entry's key pointer */
#ifdef ENABLE_DEBUG_HASHMAP
- unsigned put_count; /* hashmap's put_count recorded at start of iteration */
- unsigned rem_count; /* hashmap's rem_count in previous iteration */
- unsigned prev_idx; /* idx in previous iteration */
+ unsigned put_count; /* hashmap's put_count recorded at start of iteration */
+ unsigned rem_count; /* hashmap's rem_count in previous iteration */
+ unsigned prev_idx; /* idx in previous iteration */
#endif
} Iterator;
#define _IDX_ITERATOR_FIRST (UINT_MAX - 1)
#define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL })
-typedef unsigned long (*hash_func_t)(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]);
-typedef int (*compare_func_t)(const void *a, const void *b);
+typedef unsigned long (*hash_func_t) (const void *p,
+ const uint8_t hash_key[HASH_KEY_SIZE]);
+typedef int (*compare_func_t) (const void *a, const void *b);
-struct hash_ops {
- hash_func_t hash;
- compare_func_t compare;
+struct hash_ops
+{
+ hash_func_t hash;
+ compare_func_t compare;
};
-unsigned long string_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) _pure_;
-int string_compare_func(const void *a, const void *b) _pure_;
-extern const struct hash_ops string_hash_ops;
+unsigned long
+string_hash_func (const void *p, const uint8_t hash_key[HASH_KEY_SIZE])
+ _pure_;
+ int string_compare_func (const void *a, const void *b) _pure_;
+ extern const struct hash_ops string_hash_ops;
/* This will compare the passed pointers directly, and will not
* dereference them. This is hence not useful for strings or
* suchlike. */
-unsigned long trivial_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) _pure_;
-int trivial_compare_func(const void *a, const void *b) _const_;
-extern const struct hash_ops trivial_hash_ops;
+ unsigned long trivial_hash_func (const void *p,
+ const uint8_t hash_key[HASH_KEY_SIZE])
+ _pure_;
+ int trivial_compare_func (const void *a, const void *b) _const_;
+ extern const struct hash_ops trivial_hash_ops;
/* 32bit values we can always just embedd in the pointer itself, but
* in order to support 32bit archs we need store 64bit values
* indirectly, since they don't fit in a pointer. */
-unsigned long uint64_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) _pure_;
-int uint64_compare_func(const void *a, const void *b) _pure_;
-extern const struct hash_ops uint64_hash_ops;
+ unsigned long uint64_hash_func (const void *p,
+ const uint8_t hash_key[HASH_KEY_SIZE])
+ _pure_;
+ int uint64_compare_func (const void *a, const void *b) _pure_;
+ extern const struct hash_ops uint64_hash_ops;
/* On some archs dev_t is 32bit, and on others 64bit. And sometimes
* it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */
#if SIZEOF_DEV_T != 8
-unsigned long devt_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) _pure_;
-int devt_compare_func(const void *a, const void *b) _pure_;
-extern const struct hash_ops devt_hash_ops = {
- .hash = devt_hash_func,
- .compare = devt_compare_func
-};
+ unsigned long devt_hash_func (const void *p,
+ const uint8_t hash_key[HASH_KEY_SIZE])
+ _pure_;
+ int devt_compare_func (const void *a, const void *b) _pure_;
+ extern const struct hash_ops devt_hash_ops = {
+ .hash = devt_hash_func,
+ .compare = devt_compare_func
+ };
#else
#define devt_hash_func uint64_hash_func
#define devt_compare_func uint64_compare_func
@@ -140,199 +151,315 @@ extern const struct hash_ops devt_hash_ops = {
(void)0)
#ifdef ENABLE_DEBUG_HASHMAP
-# define HASHMAP_DEBUG_PARAMS , const char *func, const char *file, int line
-# define HASHMAP_DEBUG_SRC_ARGS , __func__, __FILE__, __LINE__
-# define HASHMAP_DEBUG_PASS_ARGS , func, file, line
+#define HASHMAP_DEBUG_PARAMS , const char *func, const char *file, int line
+#define HASHMAP_DEBUG_SRC_ARGS , __func__, __FILE__, __LINE__
+#define HASHMAP_DEBUG_PASS_ARGS , func, file, line
#else
-# define HASHMAP_DEBUG_PARAMS
-# define HASHMAP_DEBUG_SRC_ARGS
-# define HASHMAP_DEBUG_PASS_ARGS
+#define HASHMAP_DEBUG_PARAMS
+#define HASHMAP_DEBUG_SRC_ARGS
+#define HASHMAP_DEBUG_PASS_ARGS
#endif
-Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
-OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
+ Hashmap *internal_hashmap_new (const struct hash_ops *hash_ops
+ HASHMAP_DEBUG_PARAMS);
+ OrderedHashmap *internal_ordered_hashmap_new (const struct hash_ops
+ *hash_ops
+ HASHMAP_DEBUG_PARAMS);
#define hashmap_new(ops) internal_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
#define ordered_hashmap_new(ops) internal_ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
-void internal_hashmap_free(HashmapBase *h);
-static inline void hashmap_free(Hashmap *h) {
- internal_hashmap_free(HASHMAP_BASE(h));
+ void internal_hashmap_free (HashmapBase * h);
+ static inline void hashmap_free (Hashmap * h)
+{
+ internal_hashmap_free (HASHMAP_BASE (h));
}
-static inline void ordered_hashmap_free(OrderedHashmap *h) {
- internal_hashmap_free(HASHMAP_BASE(h));
+
+static inline void
+ordered_hashmap_free (OrderedHashmap * h)
+{
+ internal_hashmap_free (HASHMAP_BASE (h));
}
-void internal_hashmap_free_free(HashmapBase *h);
-static inline void hashmap_free_free(Hashmap *h) {
- internal_hashmap_free_free(HASHMAP_BASE(h));
+void internal_hashmap_free_free (HashmapBase * h);
+static inline void
+hashmap_free_free (Hashmap * h)
+{
+ internal_hashmap_free_free (HASHMAP_BASE (h));
}
-static inline void ordered_hashmap_free_free(OrderedHashmap *h) {
- internal_hashmap_free_free(HASHMAP_BASE(h));
+
+static inline void
+ordered_hashmap_free_free (OrderedHashmap * h)
+{
+ internal_hashmap_free_free (HASHMAP_BASE (h));
}
-void hashmap_free_free_free(Hashmap *h);
-static inline void ordered_hashmap_free_free_free(OrderedHashmap *h) {
- hashmap_free_free_free(PLAIN_HASHMAP(h));
+void hashmap_free_free_free (Hashmap * h);
+static inline void
+ordered_hashmap_free_free_free (OrderedHashmap * h)
+{
+ hashmap_free_free_free (PLAIN_HASHMAP (h));
}
-HashmapBase *internal_hashmap_copy(HashmapBase *h);
-static inline Hashmap *hashmap_copy(Hashmap *h) {
- return (Hashmap*) internal_hashmap_copy(HASHMAP_BASE(h));
+HashmapBase *internal_hashmap_copy (HashmapBase * h);
+static inline Hashmap *
+hashmap_copy (Hashmap * h)
+{
+ return (Hashmap *) internal_hashmap_copy (HASHMAP_BASE (h));
}
-static inline OrderedHashmap *ordered_hashmap_copy(OrderedHashmap *h) {
- return (OrderedHashmap*) internal_hashmap_copy(HASHMAP_BASE(h));
+
+static inline OrderedHashmap *
+ordered_hashmap_copy (OrderedHashmap * h)
+{
+ return (OrderedHashmap *) internal_hashmap_copy (HASHMAP_BASE (h));
}
-int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
-int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
+int internal_hashmap_ensure_allocated (Hashmap ** h,
+ const struct hash_ops *hash_ops
+ HASHMAP_DEBUG_PARAMS);
+int internal_ordered_hashmap_ensure_allocated (OrderedHashmap ** h,
+ const struct hash_ops *hash_ops
+ HASHMAP_DEBUG_PARAMS);
#define hashmap_ensure_allocated(h, ops) internal_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
#define ordered_hashmap_ensure_allocated(h, ops) internal_ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
-int hashmap_put(Hashmap *h, const void *key, void *value);
-static inline int ordered_hashmap_put(OrderedHashmap *h, const void *key, void *value) {
- return hashmap_put(PLAIN_HASHMAP(h), key, value);
+int hashmap_put (Hashmap * h, const void *key, void *value);
+static inline int
+ordered_hashmap_put (OrderedHashmap * h, const void *key, void *value)
+{
+ return hashmap_put (PLAIN_HASHMAP (h), key, value);
}
-int hashmap_update(Hashmap *h, const void *key, void *value);
-static inline int ordered_hashmap_update(OrderedHashmap *h, const void *key, void *value) {
- return hashmap_update(PLAIN_HASHMAP(h), key, value);
+int hashmap_update (Hashmap * h, const void *key, void *value);
+static inline int
+ordered_hashmap_update (OrderedHashmap * h, const void *key, void *value)
+{
+ return hashmap_update (PLAIN_HASHMAP (h), key, value);
}
-int hashmap_replace(Hashmap *h, const void *key, void *value);
-static inline int ordered_hashmap_replace(OrderedHashmap *h, const void *key, void *value) {
- return hashmap_replace(PLAIN_HASHMAP(h), key, value);
+int hashmap_replace (Hashmap * h, const void *key, void *value);
+static inline int
+ordered_hashmap_replace (OrderedHashmap * h, const void *key, void *value)
+{
+ return hashmap_replace (PLAIN_HASHMAP (h), key, value);
}
-void *internal_hashmap_get(HashmapBase *h, const void *key);
-static inline void *hashmap_get(Hashmap *h, const void *key) {
- return internal_hashmap_get(HASHMAP_BASE(h), key);
+void *internal_hashmap_get (HashmapBase * h, const void *key);
+static inline void *
+hashmap_get (Hashmap * h, const void *key)
+{
+ return internal_hashmap_get (HASHMAP_BASE (h), key);
}
-static inline void *ordered_hashmap_get(OrderedHashmap *h, const void *key) {
- return internal_hashmap_get(HASHMAP_BASE(h), key);
+
+static inline void *
+ordered_hashmap_get (OrderedHashmap * h, const void *key)
+{
+ return internal_hashmap_get (HASHMAP_BASE (h), key);
}
-void *hashmap_get2(Hashmap *h, const void *key, void **rkey);
-static inline void *ordered_hashmap_get2(OrderedHashmap *h, const void *key, void **rkey) {
- return hashmap_get2(PLAIN_HASHMAP(h), key, rkey);
+void *hashmap_get2 (Hashmap * h, const void *key, void **rkey);
+static inline void *
+ordered_hashmap_get2 (OrderedHashmap * h, const void *key, void **rkey)
+{
+ return hashmap_get2 (PLAIN_HASHMAP (h), key, rkey);
}
-bool internal_hashmap_contains(HashmapBase *h, const void *key);
-static inline bool hashmap_contains(Hashmap *h, const void *key) {
- return internal_hashmap_contains(HASHMAP_BASE(h), key);
+bool internal_hashmap_contains (HashmapBase * h, const void *key);
+static inline bool
+hashmap_contains (Hashmap * h, const void *key)
+{
+ return internal_hashmap_contains (HASHMAP_BASE (h), key);
}
-static inline bool ordered_hashmap_contains(OrderedHashmap *h, const void *key) {
- return internal_hashmap_contains(HASHMAP_BASE(h), key);
+
+static inline bool
+ordered_hashmap_contains (OrderedHashmap * h, const void *key)
+{
+ return internal_hashmap_contains (HASHMAP_BASE (h), key);
}
-void *internal_hashmap_remove(HashmapBase *h, const void *key);
-static inline void *hashmap_remove(Hashmap *h, const void *key) {
- return internal_hashmap_remove(HASHMAP_BASE(h), key);
+void *internal_hashmap_remove (HashmapBase * h, const void *key);
+static inline void *
+hashmap_remove (Hashmap * h, const void *key)
+{
+ return internal_hashmap_remove (HASHMAP_BASE (h), key);
}
-static inline void *ordered_hashmap_remove(OrderedHashmap *h, const void *key) {
- return internal_hashmap_remove(HASHMAP_BASE(h), key);
+
+static inline void *
+ordered_hashmap_remove (OrderedHashmap * h, const void *key)
+{
+ return internal_hashmap_remove (HASHMAP_BASE (h), key);
}
-void *hashmap_remove2(Hashmap *h, const void *key, void **rkey);
-static inline void *ordered_hashmap_remove2(OrderedHashmap *h, const void *key, void **rkey) {
- return hashmap_remove2(PLAIN_HASHMAP(h), key, rkey);
+void *hashmap_remove2 (Hashmap * h, const void *key, void **rkey);
+static inline void *
+ordered_hashmap_remove2 (OrderedHashmap * h, const void *key, void **rkey)
+{
+ return hashmap_remove2 (PLAIN_HASHMAP (h), key, rkey);
}
-void *hashmap_remove_value(Hashmap *h, const void *key, void *value);
-static inline void *ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) {
- return hashmap_remove_value(PLAIN_HASHMAP(h), key, value);
+void *hashmap_remove_value (Hashmap * h, const void *key, void *value);
+static inline void *
+ordered_hashmap_remove_value (OrderedHashmap * h,
+ const void *key, void *value)
+{
+ return hashmap_remove_value (PLAIN_HASHMAP (h), key, value);
}
-int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value);
-static inline int ordered_hashmap_remove_and_put(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) {
- return hashmap_remove_and_put(PLAIN_HASHMAP(h), old_key, new_key, value);
+int hashmap_remove_and_put (Hashmap * h, const void *old_key,
+ const void *new_key, void *value);
+static inline int
+ordered_hashmap_remove_and_put (OrderedHashmap * h,
+ const void *old_key,
+ const void *new_key, void *value)
+{
+ return hashmap_remove_and_put (PLAIN_HASHMAP (h), old_key, new_key, value);
}
-int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value);
-static inline int ordered_hashmap_remove_and_replace(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) {
- return hashmap_remove_and_replace(PLAIN_HASHMAP(h), old_key, new_key, value);
+int hashmap_remove_and_replace (Hashmap * h, const void *old_key,
+ const void *new_key, void *value);
+static inline int
+ordered_hashmap_remove_and_replace (OrderedHashmap * h,
+ const void *old_key,
+ const void *new_key, void *value)
+{
+ return hashmap_remove_and_replace (PLAIN_HASHMAP (h), old_key, new_key,
+ value);
}
/* Since merging data from a OrderedHashmap into a Hashmap or vice-versa
* should just work, allow this by having looser type-checking here. */
-int internal_hashmap_merge(Hashmap *h, Hashmap *other);
+int internal_hashmap_merge (Hashmap * h, Hashmap * other);
#define hashmap_merge(h, other) internal_hashmap_merge(PLAIN_HASHMAP(h), PLAIN_HASHMAP(other))
#define ordered_hashmap_merge(h, other) hashmap_merge(h, other)
-int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add);
-static inline int hashmap_reserve(Hashmap *h, unsigned entries_add) {
- return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add);
+int internal_hashmap_reserve (HashmapBase * h, unsigned entries_add);
+static inline int
+hashmap_reserve (Hashmap * h, unsigned entries_add)
+{
+ return internal_hashmap_reserve (HASHMAP_BASE (h), entries_add);
}
-static inline int ordered_hashmap_reserve(OrderedHashmap *h, unsigned entries_add) {
- return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add);
+
+static inline int
+ordered_hashmap_reserve (OrderedHashmap * h, unsigned entries_add)
+{
+ return internal_hashmap_reserve (HASHMAP_BASE (h), entries_add);
}
-int internal_hashmap_move(HashmapBase *h, HashmapBase *other);
+int internal_hashmap_move (HashmapBase * h, HashmapBase * other);
/* Unlike hashmap_merge, hashmap_move does not allow mixing the types. */
-static inline int hashmap_move(Hashmap *h, Hashmap *other) {
- return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other));
+static inline int
+hashmap_move (Hashmap * h, Hashmap * other)
+{
+ return internal_hashmap_move (HASHMAP_BASE (h), HASHMAP_BASE (other));
}
-static inline int ordered_hashmap_move(OrderedHashmap *h, OrderedHashmap *other) {
- return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other));
+
+static inline int
+ordered_hashmap_move (OrderedHashmap * h, OrderedHashmap * other)
+{
+ return internal_hashmap_move (HASHMAP_BASE (h), HASHMAP_BASE (other));
}
-int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key);
-static inline int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) {
- return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key);
+int internal_hashmap_move_one (HashmapBase * h, HashmapBase * other,
+ const void *key);
+static inline int
+hashmap_move_one (Hashmap * h, Hashmap * other, const void *key)
+{
+ return internal_hashmap_move_one (HASHMAP_BASE (h), HASHMAP_BASE (other),
+ key);
}
-static inline int ordered_hashmap_move_one(OrderedHashmap *h, OrderedHashmap *other, const void *key) {
- return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key);
+
+static inline int
+ordered_hashmap_move_one (OrderedHashmap * h,
+ OrderedHashmap * other, const void *key)
+{
+ return internal_hashmap_move_one (HASHMAP_BASE (h), HASHMAP_BASE (other),
+ key);
}
-unsigned internal_hashmap_size(HashmapBase *h) _pure_;
-static inline unsigned hashmap_size(Hashmap *h) {
- return internal_hashmap_size(HASHMAP_BASE(h));
+unsigned
+internal_hashmap_size (HashmapBase * h)
+ _pure_;
+ static inline unsigned hashmap_size (Hashmap * h)
+{
+ return internal_hashmap_size (HASHMAP_BASE (h));
}
-static inline unsigned ordered_hashmap_size(OrderedHashmap *h) {
- return internal_hashmap_size(HASHMAP_BASE(h));
+
+static inline unsigned
+ordered_hashmap_size (OrderedHashmap * h)
+{
+ return internal_hashmap_size (HASHMAP_BASE (h));
}
-static inline bool hashmap_isempty(Hashmap *h) {
- return hashmap_size(h) == 0;
+static inline bool
+hashmap_isempty (Hashmap * h)
+{
+ return hashmap_size (h) == 0;
}
-static inline bool ordered_hashmap_isempty(OrderedHashmap *h) {
- return ordered_hashmap_size(h) == 0;
+
+static inline bool
+ordered_hashmap_isempty (OrderedHashmap * h)
+{
+ return ordered_hashmap_size (h) == 0;
}
-unsigned internal_hashmap_buckets(HashmapBase *h) _pure_;
-static inline unsigned hashmap_buckets(Hashmap *h) {
- return internal_hashmap_buckets(HASHMAP_BASE(h));
+unsigned
+internal_hashmap_buckets (HashmapBase * h)
+ _pure_;
+ static inline unsigned hashmap_buckets (Hashmap * h)
+{
+ return internal_hashmap_buckets (HASHMAP_BASE (h));
}
-static inline unsigned ordered_hashmap_buckets(OrderedHashmap *h) {
- return internal_hashmap_buckets(HASHMAP_BASE(h));
+
+static inline unsigned
+ordered_hashmap_buckets (OrderedHashmap * h)
+{
+ return internal_hashmap_buckets (HASHMAP_BASE (h));
}
-void *internal_hashmap_iterate(HashmapBase *h, Iterator *i, const void **key);
-static inline void *hashmap_iterate(Hashmap *h, Iterator *i, const void **key) {
- return internal_hashmap_iterate(HASHMAP_BASE(h), i, key);
+void *internal_hashmap_iterate (HashmapBase * h, Iterator * i,
+ const void **key);
+static inline void *
+hashmap_iterate (Hashmap * h, Iterator * i, const void **key)
+{
+ return internal_hashmap_iterate (HASHMAP_BASE (h), i, key);
}
-static inline void *ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, const void **key) {
- return internal_hashmap_iterate(HASHMAP_BASE(h), i, key);
+
+static inline void *
+ordered_hashmap_iterate (OrderedHashmap * h, Iterator * i, const void **key)
+{
+ return internal_hashmap_iterate (HASHMAP_BASE (h), i, key);
}
-void internal_hashmap_clear(HashmapBase *h);
-static inline void hashmap_clear(Hashmap *h) {
- internal_hashmap_clear(HASHMAP_BASE(h));
+void internal_hashmap_clear (HashmapBase * h);
+static inline void
+hashmap_clear (Hashmap * h)
+{
+ internal_hashmap_clear (HASHMAP_BASE (h));
}
-static inline void ordered_hashmap_clear(OrderedHashmap *h) {
- internal_hashmap_clear(HASHMAP_BASE(h));
+
+static inline void
+ordered_hashmap_clear (OrderedHashmap * h)
+{
+ internal_hashmap_clear (HASHMAP_BASE (h));
}
-void internal_hashmap_clear_free(HashmapBase *h);
-static inline void hashmap_clear_free(Hashmap *h) {
- internal_hashmap_clear_free(HASHMAP_BASE(h));
+void internal_hashmap_clear_free (HashmapBase * h);
+static inline void
+hashmap_clear_free (Hashmap * h)
+{
+ internal_hashmap_clear_free (HASHMAP_BASE (h));
}
-static inline void ordered_hashmap_clear_free(OrderedHashmap *h) {
- internal_hashmap_clear_free(HASHMAP_BASE(h));
+
+static inline void
+ordered_hashmap_clear_free (OrderedHashmap * h)
+{
+ internal_hashmap_clear_free (HASHMAP_BASE (h));
}
-void hashmap_clear_free_free(Hashmap *h);
-static inline void ordered_hashmap_clear_free_free(OrderedHashmap *h) {
- hashmap_clear_free_free(PLAIN_HASHMAP(h));
+void hashmap_clear_free_free (Hashmap * h);
+static inline void
+ordered_hashmap_clear_free_free (OrderedHashmap * h)
+{
+ hashmap_clear_free_free (PLAIN_HASHMAP (h));
}
/*
@@ -346,47 +473,74 @@ static inline void ordered_hashmap_clear_free_free(OrderedHashmap *h) {
* the first entry is O(1).
*/
-void *internal_hashmap_steal_first(HashmapBase *h);
-static inline void *hashmap_steal_first(Hashmap *h) {
- return internal_hashmap_steal_first(HASHMAP_BASE(h));
+void *internal_hashmap_steal_first (HashmapBase * h);
+static inline void *
+hashmap_steal_first (Hashmap * h)
+{
+ return internal_hashmap_steal_first (HASHMAP_BASE (h));
}
-static inline void *ordered_hashmap_steal_first(OrderedHashmap *h) {
- return internal_hashmap_steal_first(HASHMAP_BASE(h));
+
+static inline void *
+ordered_hashmap_steal_first (OrderedHashmap * h)
+{
+ return internal_hashmap_steal_first (HASHMAP_BASE (h));
}
-void *internal_hashmap_steal_first_key(HashmapBase *h);
-static inline void *hashmap_steal_first_key(Hashmap *h) {
- return internal_hashmap_steal_first_key(HASHMAP_BASE(h));
+void *internal_hashmap_steal_first_key (HashmapBase * h);
+static inline void *
+hashmap_steal_first_key (Hashmap * h)
+{
+ return internal_hashmap_steal_first_key (HASHMAP_BASE (h));
}
-static inline void *ordered_hashmap_steal_first_key(OrderedHashmap *h) {
- return internal_hashmap_steal_first_key(HASHMAP_BASE(h));
+
+static inline void *
+ordered_hashmap_steal_first_key (OrderedHashmap * h)
+{
+ return internal_hashmap_steal_first_key (HASHMAP_BASE (h));
}
-void *internal_hashmap_first_key(HashmapBase *h) _pure_;
-static inline void *hashmap_first_key(Hashmap *h) {
- return internal_hashmap_first_key(HASHMAP_BASE(h));
+void *
+internal_hashmap_first_key (HashmapBase * h)
+ _pure_;
+ static inline void *hashmap_first_key (Hashmap * h)
+{
+ return internal_hashmap_first_key (HASHMAP_BASE (h));
}
-static inline void *ordered_hashmap_first_key(OrderedHashmap *h) {
- return internal_hashmap_first_key(HASHMAP_BASE(h));
+
+static inline void *
+ordered_hashmap_first_key (OrderedHashmap * h)
+{
+ return internal_hashmap_first_key (HASHMAP_BASE (h));
}
-void *internal_hashmap_first(HashmapBase *h) _pure_;
-static inline void *hashmap_first(Hashmap *h) {
- return internal_hashmap_first(HASHMAP_BASE(h));
+void *
+internal_hashmap_first (HashmapBase * h)
+ _pure_;
+ static inline void *hashmap_first (Hashmap * h)
+{
+ return internal_hashmap_first (HASHMAP_BASE (h));
}
-static inline void *ordered_hashmap_first(OrderedHashmap *h) {
- return internal_hashmap_first(HASHMAP_BASE(h));
+
+static inline void *
+ordered_hashmap_first (OrderedHashmap * h)
+{
+ return internal_hashmap_first (HASHMAP_BASE (h));
}
/* no hashmap_next */
-void *ordered_hashmap_next(OrderedHashmap *h, const void *key);
+void *ordered_hashmap_next (OrderedHashmap * h, const void *key);
-char **internal_hashmap_get_strv(HashmapBase *h);
-static inline char **hashmap_get_strv(Hashmap *h) {
- return internal_hashmap_get_strv(HASHMAP_BASE(h));
+char **internal_hashmap_get_strv (HashmapBase * h);
+static inline char **
+hashmap_get_strv (Hashmap * h)
+{
+ return internal_hashmap_get_strv (HASHMAP_BASE (h));
}
-static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) {
- return internal_hashmap_get_strv(HASHMAP_BASE(h));
+
+static inline char **
+ordered_hashmap_get_strv (OrderedHashmap * h)
+{
+ return internal_hashmap_get_strv (HASHMAP_BASE (h));
}
/*
@@ -415,12 +569,13 @@ static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) {
(e); \
(e) = ordered_hashmap_iterate((h), &(i), (const void**) &(k)))
-DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC (Hashmap *, hashmap_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC (Hashmap *, hashmap_free_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC (Hashmap *, hashmap_free_free_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC (OrderedHashmap *, ordered_hashmap_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC (OrderedHashmap *, ordered_hashmap_free_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC (OrderedHashmap *,
+ ordered_hashmap_free_free_free);
#define _cleanup_hashmap_free_ _cleanup_(hashmap_freep)
#define _cleanup_hashmap_free_free_ _cleanup_(hashmap_free_freep)
@@ -429,4 +584,4 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free_free);
#define _cleanup_ordered_hashmap_free_free_ _cleanup_(ordered_hashmap_free_freep)
#define _cleanup_ordered_hashmap_free_free_free_ _cleanup_(ordered_hashmap_free_free_freep)
-#endif
\ No newline at end of file
+#endif
diff --git a/libudev-compat/hwdb-internal.h b/libudev-compat/hwdb-internal.h
index 85fed35..333f120 100644
--- a/libudev-compat/hwdb-internal.h
+++ b/libudev-compat/hwdb-internal.h
@@ -34,50 +34,54 @@
#define HWDB_SIG { 'K', 'S', 'L', 'P', 'H', 'H', 'R', 'H' }
/* on-disk trie objects */
-struct trie_header_f {
- uint8_t signature[8];
-
- /* version of tool which created the file */
- le64_t tool_version;
- le64_t file_size;
-
- /* size of structures to allow them to grow */
- le64_t header_size;
- le64_t node_size;
- le64_t child_entry_size;
- le64_t value_entry_size;
-
- /* offset of the root trie node */
- le64_t nodes_root_off;
-
- /* size of the nodes and string section */
- le64_t nodes_len;
- le64_t strings_len;
+struct trie_header_f
+{
+ uint8_t signature[8];
+
+ /* version of tool which created the file */
+ le64_t tool_version;
+ le64_t file_size;
+
+ /* size of structures to allow them to grow */
+ le64_t header_size;
+ le64_t node_size;
+ le64_t child_entry_size;
+ le64_t value_entry_size;
+
+ /* offset of the root trie node */
+ le64_t nodes_root_off;
+
+ /* size of the nodes and string section */
+ le64_t nodes_len;
+ le64_t strings_len;
} _packed_;
-struct trie_node_f {
- /* prefix of lookup string, shared by all children */
- le64_t prefix_off;
- /* size of children entry array appended to the node */
- uint8_t children_count;
- uint8_t padding[7];
- /* size of value entry array appended to the node */
- le64_t values_count;
+struct trie_node_f
+{
+ /* prefix of lookup string, shared by all children */
+ le64_t prefix_off;
+ /* size of children entry array appended to the node */
+ uint8_t children_count;
+ uint8_t padding[7];
+ /* size of value entry array appended to the node */
+ le64_t values_count;
} _packed_;
/* array of child entries, follows directly the node record */
-struct trie_child_entry_f {
- /* index of the child node */
- uint8_t c;
- uint8_t padding[7];
- /* offset of the child node */
- le64_t child_off;
+struct trie_child_entry_f
+{
+ /* index of the child node */
+ uint8_t c;
+ uint8_t padding[7];
+ /* offset of the child node */
+ le64_t child_off;
} _packed_;
/* array of value entries, follows directly the node record/child array */
-struct trie_value_entry_f {
- le64_t key_off;
- le64_t value_off;
+struct trie_value_entry_f
+{
+ le64_t key_off;
+ le64_t value_off;
} _packed_;
-#endif
+#endif
diff --git a/libudev-compat/hwdb-util.h b/libudev-compat/hwdb-util.h
index bc110d1..d3de530 100644
--- a/libudev-compat/hwdb-util.h
+++ b/libudev-compat/hwdb-util.h
@@ -34,9 +34,9 @@
#include "sd-hwdb.h"
-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_hwdb*, sd_hwdb_unref);
+DEFINE_TRIVIAL_CLEANUP_FUNC (sd_hwdb *, sd_hwdb_unref);
#define _cleanup_hwdb_unref_ _cleanup_(sd_hwdb_unrefp)
-bool hwdb_validate(sd_hwdb *hwdb);
+bool hwdb_validate (sd_hwdb * hwdb);
-#endif
\ No newline at end of file
+#endif
diff --git a/libudev-compat/libudev-device-private.c b/libudev-compat/libudev-device-private.c
index 7b47ba8..b4a1793 100644
--- a/libudev-compat/libudev-device-private.c
+++ b/libudev-compat/libudev-device-private.c
@@ -39,164 +39,200 @@
#include "log.h"
#include "util.h"
-static void udev_device_tag(struct udev_device *dev, const char *tag, bool add)
+static void
+udev_device_tag (struct udev_device *dev, const char *tag, bool add)
{
- const char *id;
- char filename[UTIL_PATH_SIZE];
-
- id = udev_device_get_id_filename(dev);
- if (id == NULL)
- return;
- strscpyl(filename, sizeof(filename), "/run/udev/tags/", tag, "/", id, NULL);
-
- if (add) {
- int fd;
-
- mkdir_parents(filename, 0755);
- fd = open(filename, O_WRONLY|O_CREAT|O_CLOEXEC|O_TRUNC|O_NOFOLLOW, 0444);
- if (fd >= 0)
- close(fd);
- } else {
- unlink(filename);
- }
+ const char *id;
+ char filename[UTIL_PATH_SIZE];
+
+ id = udev_device_get_id_filename (dev);
+ if (id == NULL)
+ return;
+ strscpyl (filename, sizeof (filename), "/run/udev/tags/", tag, "/", id,
+ NULL);
+
+ if (add)
+ {
+ int fd;
+
+ mkdir_parents (filename, 0755);
+ fd = open (filename,
+ O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC | O_NOFOLLOW, 0444);
+ if (fd >= 0)
+ close (fd);
+ }
+ else
+ {
+ unlink (filename);
+ }
}
-int udev_device_tag_index(struct udev_device *dev, struct udev_device *dev_old, bool add)
+int
+udev_device_tag_index (struct udev_device *dev, struct udev_device *dev_old,
+ bool add)
{
- struct udev_list_entry *list_entry;
- bool found;
-
- if (add && dev_old != NULL) {
- /* delete possible left-over tags */
- udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(dev_old)) {
- const char *tag_old = udev_list_entry_get_name(list_entry);
- struct udev_list_entry *list_entry_current;
-
- found = false;
- udev_list_entry_foreach(list_entry_current, udev_device_get_tags_list_entry(dev)) {
- const char *tag = udev_list_entry_get_name(list_entry_current);
-
- if (streq(tag, tag_old)) {
- found = true;
- break;
- }
- }
- if (!found)
- udev_device_tag(dev_old, tag_old, false);
- }
- }
-
- udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(dev))
- udev_device_tag(dev, udev_list_entry_get_name(list_entry), add);
-
- return 0;
+ struct udev_list_entry *list_entry;
+ bool found;
+
+ if (add && dev_old != NULL)
+ {
+ /* delete possible left-over tags */
+ udev_list_entry_foreach (list_entry,
+ udev_device_get_tags_list_entry (dev_old))
+ {
+ const char *tag_old = udev_list_entry_get_name (list_entry);
+ struct udev_list_entry *list_entry_current;
+
+ found = false;
+ udev_list_entry_foreach (list_entry_current,
+ udev_device_get_tags_list_entry (dev))
+ {
+ const char *tag = udev_list_entry_get_name (list_entry_current);
+
+ if (streq (tag, tag_old))
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ udev_device_tag (dev_old, tag_old, false);
+ }
+ }
+
+ udev_list_entry_foreach (list_entry,
+ udev_device_get_tags_list_entry (dev))
+ udev_device_tag (dev, udev_list_entry_get_name (list_entry), add);
+
+ return 0;
}
-static bool device_has_info(struct udev_device *udev_device)
+static bool
+device_has_info (struct udev_device *udev_device)
{
- struct udev_list_entry *list_entry;
-
- if (udev_device_get_devlinks_list_entry(udev_device) != NULL)
- return true;
- if (udev_device_get_devlink_priority(udev_device) != 0)
- return true;
- udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(udev_device))
- if (udev_list_entry_get_num(list_entry))
- return true;
- if (udev_device_get_tags_list_entry(udev_device) != NULL)
- return true;
- if (udev_device_get_watch_handle(udev_device) >= 0)
- return true;
- return false;
+ struct udev_list_entry *list_entry;
+
+ if (udev_device_get_devlinks_list_entry (udev_device) != NULL)
+ return true;
+ if (udev_device_get_devlink_priority (udev_device) != 0)
+ return true;
+ udev_list_entry_foreach (list_entry,
+ udev_device_get_properties_list_entry
+ (udev_device))
+ if (udev_list_entry_get_num (list_entry))
+ return true;
+ if (udev_device_get_tags_list_entry (udev_device) != NULL)
+ return true;
+ if (udev_device_get_watch_handle (udev_device) >= 0)
+ return true;
+ return false;
}
-int udev_device_update_db(struct udev_device *udev_device)
+int
+udev_device_update_db (struct udev_device *udev_device)
{
- bool has_info;
- const char *id;
- char filename[UTIL_PATH_SIZE];
- char filename_tmp[UTIL_PATH_SIZE];
- FILE *f;
- int r;
-
- id = udev_device_get_id_filename(udev_device);
- if (id == NULL)
- return -1;
-
- has_info = device_has_info(udev_device);
- strscpyl(filename, sizeof(filename), "/run/udev/data/", id, NULL);
-
- /* do not store anything for otherwise empty devices */
- if (!has_info &&
- major(udev_device_get_devnum(udev_device)) == 0 &&
- udev_device_get_ifindex(udev_device) == 0) {
- unlink(filename);
- return 0;
- }
-
- /* write a database file */
- strscpyl(filename_tmp, sizeof(filename_tmp), filename, ".tmp", NULL);
- mkdir_parents(filename_tmp, 0755);
- f = fopen(filename_tmp, "we");
- if (f == NULL) {
- int errsv = errno;
- log_debug("unable to create temporary db file '%s': %s", filename_tmp, strerror(errsv));
- return errsv;
- }
-
- /*
- * set 'sticky' bit to indicate that we should not clean the
- * database when we transition from initramfs to the real root
- */
- if (udev_device_get_db_persist(udev_device))
- fchmod(fileno(f), 01644);
-
- if (has_info) {
- struct udev_list_entry *list_entry;
-
- if (major(udev_device_get_devnum(udev_device)) > 0) {
- udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(udev_device))
- fprintf(f, "S:%s\n", udev_list_entry_get_name(list_entry) + strlen("/dev/"));
- if (udev_device_get_devlink_priority(udev_device) != 0)
- fprintf(f, "L:%i\n", udev_device_get_devlink_priority(udev_device));
- if (udev_device_get_watch_handle(udev_device) >= 0)
- fprintf(f, "W:%i\n", udev_device_get_watch_handle(udev_device));
- }
-
- if (udev_device_get_usec_initialized(udev_device) > 0)
- fprintf(f, "I:"USEC_FMT"\n", udev_device_get_usec_initialized(udev_device));
-
- udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(udev_device)) {
- if (!udev_list_entry_get_num(list_entry))
- continue;
- fprintf(f, "E:%s=%s\n",
- udev_list_entry_get_name(list_entry),
- udev_list_entry_get_value(list_entry));
- }
-
- udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(udev_device))
- fprintf(f, "G:%s\n", udev_list_entry_get_name(list_entry));
- }
-
- fclose(f);
- r = rename(filename_tmp, filename);
- if (r < 0)
- return -1;
- log_debug("created %s file '%s' for '%s'", has_info ? "db" : "empty",
- filename, udev_device_get_devpath(udev_device));
- return 0;
+ bool has_info;
+ const char *id;
+ char filename[UTIL_PATH_SIZE];
+ char filename_tmp[UTIL_PATH_SIZE];
+ FILE *f;
+ int r;
+
+ id = udev_device_get_id_filename (udev_device);
+ if (id == NULL)
+ return -1;
+
+ has_info = device_has_info (udev_device);
+ strscpyl (filename, sizeof (filename), "/run/udev/data/", id, NULL);
+
+ /* do not store anything for otherwise empty devices */
+ if (!has_info &&
+ major (udev_device_get_devnum (udev_device)) == 0 &&
+ udev_device_get_ifindex (udev_device) == 0)
+ {
+ unlink (filename);
+ return 0;
+ }
+
+ /* write a database file */
+ strscpyl (filename_tmp, sizeof (filename_tmp), filename, ".tmp", NULL);
+ mkdir_parents (filename_tmp, 0755);
+ f = fopen (filename_tmp, "we");
+ if (f == NULL)
+ {
+ int errsv = errno;
+ log_debug ("unable to create temporary db file '%s': %s",
+ filename_tmp, strerror (errsv));
+ return errsv;
+ }
+
+ /*
+ * set 'sticky' bit to indicate that we should not clean the
+ * database when we transition from initramfs to the real root
+ */
+ if (udev_device_get_db_persist (udev_device))
+ fchmod (fileno (f), 01644);
+
+ if (has_info)
+ {
+ struct udev_list_entry *list_entry;
+
+ if (major (udev_device_get_devnum (udev_device)) > 0)
+ {
+ udev_list_entry_foreach (list_entry,
+ udev_device_get_devlinks_list_entry
+ (udev_device))
+ fprintf (f, "S:%s\n",
+ udev_list_entry_get_name (list_entry) +
+ strlen ("/dev/"));
+ if (udev_device_get_devlink_priority (udev_device) != 0)
+ fprintf (f, "L:%i\n",
+ udev_device_get_devlink_priority (udev_device));
+ if (udev_device_get_watch_handle (udev_device) >= 0)
+ fprintf (f, "W:%i\n", udev_device_get_watch_handle (udev_device));
+ }
+
+ if (udev_device_get_usec_initialized (udev_device) > 0)
+ fprintf (f, "I:" USEC_FMT "\n",
+ udev_device_get_usec_initialized (udev_device));
+
+ udev_list_entry_foreach (list_entry,
+ udev_device_get_properties_list_entry
+ (udev_device))
+ {
+ if (!udev_list_entry_get_num (list_entry))
+ continue;
+ fprintf (f, "E:%s=%s\n",
+ udev_list_entry_get_name (list_entry),
+ udev_list_entry_get_value (list_entry));
+ }
+
+ udev_list_entry_foreach (list_entry,
+ udev_device_get_tags_list_entry
+ (udev_device))
+ fprintf (f, "G:%s\n", udev_list_entry_get_name (list_entry));
+ }
+
+ fclose (f);
+ r = rename (filename_tmp, filename);
+ if (r < 0)
+ return -1;
+ log_debug ("created %s file '%s' for '%s'", has_info ? "db" : "empty",
+ filename, udev_device_get_devpath (udev_device));
+ return 0;
}
-int udev_device_delete_db(struct udev_device *udev_device)
+int
+udev_device_delete_db (struct udev_device *udev_device)
{
- const char *id;
- char filename[UTIL_PATH_SIZE];
+ const char *id;
+ char filename[UTIL_PATH_SIZE];
- id = udev_device_get_id_filename(udev_device);
- if (id == NULL)
- return -1;
- strscpyl(filename, sizeof(filename), "/run/udev/data/", id, NULL);
+ id = udev_device_get_id_filename (udev_device);
+ if (id == NULL)
+ return -1;
+ strscpyl (filename, sizeof (filename), "/run/udev/data/", id, NULL);
- unlink(filename);
- return 0;
+ unlink (filename);
+ return 0;
}
diff --git a/libudev-compat/libudev-device.c b/libudev-compat/libudev-device.c
index 91f2c8e..a848351 100644
--- a/libudev-compat/libudev-device.c
+++ b/libudev-compat/libudev-device.c
@@ -47,10 +47,17 @@
#include "libudev.h"
#include "libudev-private.h"
-static int udev_device_read_uevent_file(struct udev_device *udev_device);
-static int udev_device_read_db(struct udev_device *udev_device);
-static int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode);
-static struct udev_list_entry *udev_device_add_property_internal(struct udev_device *udev_device, const char *key, const char *value);
+static int udev_device_read_uevent_file (struct udev_device *udev_device);
+static int udev_device_read_db (struct udev_device *udev_device);
+static int udev_device_set_devnode (struct udev_device *udev_device,
+ const char *devnode);
+static struct udev_list_entry *udev_device_add_property_internal (struct
+ udev_device
+ *udev_device,
+ const char
+ *key,
+ const char
+ *value);
/**
* SECTION:libudev-device
@@ -67,52 +74,53 @@ static struct udev_list_entry *udev_device_add_property_internal(struct udev_dev
*
* Opaque object representing one kernel sys device.
*/
-struct udev_device {
- struct udev *udev;
- struct udev_device *parent_device;
- char *syspath;
- const char *devpath;
- char *sysname;
- const char *sysnum;
- char *devnode;
- mode_t devnode_mode;
- uid_t devnode_uid;
- gid_t devnode_gid;
- char *subsystem;
- char *devtype;
- char *driver;
- char *action;
- char *devpath_old;
- char *id_filename;
- char **envp;
- char *monitor_buf;
- size_t monitor_buf_len;
- struct udev_list devlinks_list;
- struct udev_list properties_list;
- struct udev_list sysattr_value_list;
- struct udev_list sysattr_list;
- struct udev_list tags_list;
- unsigned long long int seqnum;
- usec_t usec_initialized;
- int devlink_priority;
- int refcount;
- dev_t devnum;
- int ifindex;
- int watch_handle;
- int maj, min;
- bool parent_set;
- bool subsystem_set;
- bool devtype_set;
- bool devlinks_uptodate;
- bool envp_uptodate;
- bool tags_uptodate;
- bool driver_set;
- bool info_loaded;
- bool db_loaded;
- bool uevent_loaded;
- bool is_initialized;
- bool sysattr_list_read;
- bool db_persist;
+struct udev_device
+{
+ struct udev *udev;
+ struct udev_device *parent_device;
+ char *syspath;
+ const char *devpath;
+ char *sysname;
+ const char *sysnum;
+ char *devnode;
+ mode_t devnode_mode;
+ uid_t devnode_uid;
+ gid_t devnode_gid;
+ char *subsystem;
+ char *devtype;
+ char *driver;
+ char *action;
+ char *devpath_old;
+ char *id_filename;
+ char **envp;
+ char *monitor_buf;
+ size_t monitor_buf_len;
+ struct udev_list devlinks_list;
+ struct udev_list properties_list;
+ struct udev_list sysattr_value_list;
+ struct udev_list sysattr_list;
+ struct udev_list tags_list;
+ unsigned long long int seqnum;
+ usec_t usec_initialized;
+ int devlink_priority;
+ int refcount;
+ dev_t devnum;
+ int ifindex;
+ int watch_handle;
+ int maj, min;
+ bool parent_set;
+ bool subsystem_set;
+ bool devtype_set;
+ bool devlinks_uptodate;
+ bool envp_uptodate;
+ bool tags_uptodate;
+ bool driver_set;
+ bool info_loaded;
+ bool db_loaded;
+ bool uevent_loaded;
+ bool is_initialized;
+ bool sysattr_list_read;
+ bool db_persist;
};
/**
@@ -124,38 +132,43 @@ struct udev_device {
*
* Returns: the kernel event sequence number, or 0 if there is no sequence number available.
**/
-unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device)
+unsigned long long int
+udev_device_get_seqnum (struct udev_device *udev_device)
{
- if (udev_device == NULL)
- return 0;
- return udev_device->seqnum;
+ if (udev_device == NULL)
+ return 0;
+ return udev_device->seqnum;
}
-static int udev_device_set_seqnum(struct udev_device *udev_device, unsigned long long int seqnum)
+static int
+udev_device_set_seqnum (struct udev_device *udev_device,
+ unsigned long long int seqnum)
{
- char num[32];
+ char num[32];
- udev_device->seqnum = seqnum;
- snprintf(num, sizeof(num), "%llu", seqnum);
- udev_device_add_property_internal(udev_device, "SEQNUM", num);
- return 0;
+ udev_device->seqnum = seqnum;
+ snprintf (num, sizeof (num), "%llu", seqnum);
+ udev_device_add_property_internal (udev_device, "SEQNUM", num);
+ return 0;
}
-int udev_device_get_ifindex(struct udev_device *udev_device)
+int
+udev_device_get_ifindex (struct udev_device *udev_device)
{
- if (!udev_device->info_loaded)
- udev_device_read_uevent_file(udev_device);
- return udev_device->ifindex;
+ if (!udev_device->info_loaded)
+ udev_device_read_uevent_file (udev_device);
+ return udev_device->ifindex;
}
-static int udev_device_set_ifindex(struct udev_device *udev_device, int ifindex)
+static int
+udev_device_set_ifindex (struct udev_device *udev_device, int ifindex)
{
- char num[32];
+ char num[32];
- udev_device->ifindex = ifindex;
- snprintf(num, sizeof(num), "%d", ifindex);
- udev_device_add_property_internal(udev_device, "IFINDEX", num);
- return 0;
+ udev_device->ifindex = ifindex;
+ snprintf (num, sizeof (num), "%d", ifindex);
+ udev_device_add_property_internal (udev_device, "IFINDEX", num);
+ return 0;
}
/**
@@ -166,47 +179,53 @@ static int udev_device_set_ifindex(struct udev_device *udev_device, int ifindex)
*
* Returns: the dev_t number.
**/
-dev_t udev_device_get_devnum(struct udev_device *udev_device)
+dev_t
+udev_device_get_devnum (struct udev_device * udev_device)
{
- if (udev_device == NULL)
- return makedev(0, 0);
- if (!udev_device->info_loaded)
- udev_device_read_uevent_file(udev_device);
- return udev_device->devnum;
+ if (udev_device == NULL)
+ return makedev (0, 0);
+ if (!udev_device->info_loaded)
+ udev_device_read_uevent_file (udev_device);
+ return udev_device->devnum;
}
-static int udev_device_set_devnum(struct udev_device *udev_device, dev_t devnum)
+static int
+udev_device_set_devnum (struct udev_device *udev_device, dev_t devnum)
{
- char num[32];
+ char num[32];
- udev_device->devnum = devnum;
+ udev_device->devnum = devnum;
- snprintf(num, sizeof(num), "%u", major(devnum));
- udev_device_add_property_internal(udev_device, "MAJOR", num);
- snprintf(num, sizeof(num), "%u", minor(devnum));
- udev_device_add_property_internal(udev_device, "MINOR", num);
- return 0;
+ snprintf (num, sizeof (num), "%u", major (devnum));
+ udev_device_add_property_internal (udev_device, "MAJOR", num);
+ snprintf (num, sizeof (num), "%u", minor (devnum));
+ udev_device_add_property_internal (udev_device, "MINOR", num);
+ return 0;
}
-const char *udev_device_get_devpath_old(struct udev_device *udev_device)
+const char *
+udev_device_get_devpath_old (struct udev_device *udev_device)
{
- return udev_device->devpath_old;
+ return udev_device->devpath_old;
}
-static int udev_device_set_devpath_old(struct udev_device *udev_device, const char *devpath_old)
+static int
+udev_device_set_devpath_old (struct udev_device *udev_device,
+ const char *devpath_old)
{
- const char *pos;
+ const char *pos;
- free(udev_device->devpath_old);
- udev_device->devpath_old = strdup(devpath_old);
- if (udev_device->devpath_old == NULL)
- return -ENOMEM;
- udev_device_add_property_internal(udev_device, "DEVPATH_OLD", udev_device->devpath_old);
+ free (udev_device->devpath_old);
+ udev_device->devpath_old = strdup (devpath_old);
+ if (udev_device->devpath_old == NULL)
+ return -ENOMEM;
+ udev_device_add_property_internal (udev_device, "DEVPATH_OLD",
+ udev_device->devpath_old);
- pos = strrchr(udev_device->devpath_old, '/');
- if (pos == NULL)
- return -EINVAL;
- return 0;
+ pos = strrchr (udev_device->devpath_old, '/');
+ if (pos == NULL)
+ return -EINVAL;
+ return 0;
}
/**
@@ -217,29 +236,35 @@ static int udev_device_set_devpath_old(struct udev_device *udev_device, const ch
*
* Returns: the driver name string, or #NULL if there is no driver attached.
**/
-const char *udev_device_get_driver(struct udev_device *udev_device)
+const char *
+udev_device_get_driver (struct udev_device *udev_device)
{
- char driver[UTIL_NAME_SIZE];
+ char driver[UTIL_NAME_SIZE];
- if (udev_device == NULL)
- return NULL;
- if (!udev_device->driver_set) {
- udev_device->driver_set = true;
- if (util_get_sys_core_link_value(udev_device->udev, "driver", udev_device->syspath, driver, sizeof(driver)) > 0)
- udev_device->driver = strdup(driver);
- }
- return udev_device->driver;
+ if (udev_device == NULL)
+ return NULL;
+ if (!udev_device->driver_set)
+ {
+ udev_device->driver_set = true;
+ if (util_get_sys_core_link_value
+ (udev_device->udev, "driver", udev_device->syspath, driver,
+ sizeof (driver)) > 0)
+ udev_device->driver = strdup (driver);
+ }
+ return udev_device->driver;
}
-static int udev_device_set_driver(struct udev_device *udev_device, const char *driver)
+static int
+udev_device_set_driver (struct udev_device *udev_device, const char *driver)
{
- free(udev_device->driver);
- udev_device->driver = strdup(driver);
- if (udev_device->driver == NULL)
- return -ENOMEM;
- udev_device->driver_set = true;
- udev_device_add_property_internal(udev_device, "DRIVER", udev_device->driver);
- return 0;
+ free (udev_device->driver);
+ udev_device->driver = strdup (driver);
+ if (udev_device->driver == NULL)
+ return -ENOMEM;
+ udev_device->driver_set = true;
+ udev_device_add_property_internal (udev_device, "DRIVER",
+ udev_device->driver);
+ return 0;
}
/**
@@ -250,37 +275,44 @@ static int udev_device_set_driver(struct udev_device *udev_device, const char *d
*
* Returns: the devtype name of the udev device, or #NULL if it can not be determined
**/
-const char *udev_device_get_devtype(struct udev_device *udev_device)
-{
- if (udev_device == NULL)
- return NULL;
- if (!udev_device->devtype_set) {
- udev_device->devtype_set = true;
- udev_device_read_uevent_file(udev_device);
- }
- return udev_device->devtype;
-}
-
-static int udev_device_set_devtype(struct udev_device *udev_device, const char *devtype)
-{
- free(udev_device->devtype);
- udev_device->devtype = strdup(devtype);
- if (udev_device->devtype == NULL)
- return -ENOMEM;
- udev_device->devtype_set = true;
- udev_device_add_property_internal(udev_device, "DEVTYPE", udev_device->devtype);
- return 0;
-}
-
-static int udev_device_set_subsystem(struct udev_device *udev_device, const char *subsystem)
-{
- free(udev_device->subsystem);
- udev_device->subsystem = strdup(subsystem);
- if (udev_device->subsystem == NULL)
- return -ENOMEM;
- udev_device->subsystem_set = true;
- udev_device_add_property_internal(udev_device, "SUBSYSTEM", udev_device->subsystem);
- return 0;
+const char *
+udev_device_get_devtype (struct udev_device *udev_device)
+{
+ if (udev_device == NULL)
+ return NULL;
+ if (!udev_device->devtype_set)
+ {
+ udev_device->devtype_set = true;
+ udev_device_read_uevent_file (udev_device);
+ }
+ return udev_device->devtype;
+}
+
+static int
+udev_device_set_devtype (struct udev_device *udev_device, const char *devtype)
+{
+ free (udev_device->devtype);
+ udev_device->devtype = strdup (devtype);
+ if (udev_device->devtype == NULL)
+ return -ENOMEM;
+ udev_device->devtype_set = true;
+ udev_device_add_property_internal (udev_device, "DEVTYPE",
+ udev_device->devtype);
+ return 0;
+}
+
+static int
+udev_device_set_subsystem (struct udev_device *udev_device,
+ const char *subsystem)
+{
+ free (udev_device->subsystem);
+ udev_device->subsystem = strdup (subsystem);
+ if (udev_device->subsystem == NULL)
+ return -ENOMEM;
+ udev_device->subsystem_set = true;
+ udev_device_add_property_internal (udev_device, "SUBSYSTEM",
+ udev_device->subsystem);
+ return 0;
}
/**
@@ -292,197 +324,230 @@ static int udev_device_set_subsystem(struct udev_device *udev_device, const char
*
* Returns: the subsystem name of the udev device, or #NULL if it can not be determined
**/
-const char *udev_device_get_subsystem(struct udev_device *udev_device)
+const char *
+udev_device_get_subsystem (struct udev_device *udev_device)
{
- char subsystem[UTIL_NAME_SIZE];
+ char subsystem[UTIL_NAME_SIZE];
- if (udev_device == NULL)
- return NULL;
- if (!udev_device->subsystem_set) {
- udev_device->subsystem_set = true;
- /* read "subsystem" link */
- if (util_get_sys_core_link_value(udev_device->udev, "subsystem", udev_device->syspath, subsystem, sizeof(subsystem)) > 0) {
- udev_device_set_subsystem(udev_device, subsystem);
- return udev_device->subsystem;
- }
- /* implicit names */
- if (startswith(udev_device->devpath, "/module/")) {
- udev_device_set_subsystem(udev_device, "module");
- return udev_device->subsystem;
- }
- if (strstr(udev_device->devpath, "/drivers/") != NULL) {
- udev_device_set_subsystem(udev_device, "drivers");
- return udev_device->subsystem;
- }
- if (startswith(udev_device->devpath, "/subsystem/") ||
- startswith(udev_device->devpath, "/class/") ||
- startswith(udev_device->devpath, "/bus/")) {
- udev_device_set_subsystem(udev_device, "subsystem");
- return udev_device->subsystem;
- }
- }
- return udev_device->subsystem;
+ if (udev_device == NULL)
+ return NULL;
+ if (!udev_device->subsystem_set)
+ {
+ udev_device->subsystem_set = true;
+ /* read "subsystem" link */
+ if (util_get_sys_core_link_value
+ (udev_device->udev, "subsystem", udev_device->syspath,
+ subsystem, sizeof (subsystem)) > 0)
+ {
+ udev_device_set_subsystem (udev_device, subsystem);
+ return udev_device->subsystem;
+ }
+ /* implicit names */
+ if (startswith (udev_device->devpath, "/module/"))
+ {
+ udev_device_set_subsystem (udev_device, "module");
+ return udev_device->subsystem;
+ }
+ if (strstr (udev_device->devpath, "/drivers/") != NULL)
+ {
+ udev_device_set_subsystem (udev_device, "drivers");
+ return udev_device->subsystem;
+ }
+ if (startswith (udev_device->devpath, "/subsystem/") ||
+ startswith (udev_device->devpath, "/class/") ||
+ startswith (udev_device->devpath, "/bus/"))
+ {
+ udev_device_set_subsystem (udev_device, "subsystem");
+ return udev_device->subsystem;
+ }
+ }
+ return udev_device->subsystem;
}
-mode_t udev_device_get_devnode_mode(struct udev_device *udev_device)
+mode_t
+udev_device_get_devnode_mode (struct udev_device * udev_device)
{
- if (!udev_device->info_loaded)
- udev_device_read_uevent_file(udev_device);
- return udev_device->devnode_mode;
+ if (!udev_device->info_loaded)
+ udev_device_read_uevent_file (udev_device);
+ return udev_device->devnode_mode;
}
-static int udev_device_set_devnode_mode(struct udev_device *udev_device, mode_t mode)
+static int
+udev_device_set_devnode_mode (struct udev_device *udev_device, mode_t mode)
{
- char num[32];
+ char num[32];
- udev_device->devnode_mode = mode;
- snprintf(num, sizeof(num), "%#o", mode);
- udev_device_add_property_internal(udev_device, "DEVMODE", num);
- return 0;
+ udev_device->devnode_mode = mode;
+ snprintf (num, sizeof (num), "%#o", mode);
+ udev_device_add_property_internal (udev_device, "DEVMODE", num);
+ return 0;
}
-uid_t udev_device_get_devnode_uid(struct udev_device *udev_device)
+uid_t
+udev_device_get_devnode_uid (struct udev_device * udev_device)
{
- if (!udev_device->info_loaded)
- udev_device_read_uevent_file(udev_device);
- return udev_device->devnode_uid;
+ if (!udev_device->info_loaded)
+ udev_device_read_uevent_file (udev_device);
+ return udev_device->devnode_uid;
}
-static int udev_device_set_devnode_uid(struct udev_device *udev_device, uid_t uid)
+static int
+udev_device_set_devnode_uid (struct udev_device *udev_device, uid_t uid)
{
- char num[32];
+ char num[32];
- udev_device->devnode_uid = uid;
- snprintf(num, sizeof(num), "%u", uid);
- udev_device_add_property_internal(udev_device, "DEVUID", num);
- return 0;
-}
+ udev_device->devnode_uid = uid;
+ snprintf (num, sizeof (num), "%u", uid);
+ udev_device_add_property_internal (udev_device, "DEVUID", num);
+ return 0;
+}
+
+gid_t
+udev_device_get_devnode_gid (struct udev_device * udev_device)
+{
+ if (!udev_device->info_loaded)
+ udev_device_read_uevent_file (udev_device);
+ return udev_device->devnode_gid;
+}
+
+static int
+udev_device_set_devnode_gid (struct udev_device *udev_device, gid_t gid)
+{
+ char num[32];
-gid_t udev_device_get_devnode_gid(struct udev_device *udev_device)
-{
- if (!udev_device->info_loaded)
- udev_device_read_uevent_file(udev_device);
- return udev_device->devnode_gid;
+ udev_device->devnode_gid = gid;
+ snprintf (num, sizeof (num), "%u", gid);
+ udev_device_add_property_internal (udev_device, "DEVGID", num);
+ return 0;
}
-static int udev_device_set_devnode_gid(struct udev_device *udev_device, gid_t gid)
+static struct udev_list_entry *
+udev_device_add_property_internal (struct
+ udev_device
+ *udev_device,
+ const char *key, const char *value)
{
- char num[32];
+ udev_device->envp_uptodate = false;
+ if (value == NULL)
+ {
+ struct udev_list_entry *list_entry;
- udev_device->devnode_gid = gid;
- snprintf(num, sizeof(num), "%u", gid);
- udev_device_add_property_internal(udev_device, "DEVGID", num);
- return 0;
+ list_entry = udev_device_get_properties_list_entry (udev_device);
+ list_entry = udev_list_entry_get_by_name (list_entry, key);
+ if (list_entry != NULL)
+ udev_list_entry_delete (list_entry);
+ return NULL;
+ }
+ return udev_list_entry_add (&udev_device->properties_list, key, value);
}
-static struct udev_list_entry *udev_device_add_property_internal(struct udev_device *udev_device, const char *key, const char *value)
+int
+udev_device_add_property (struct udev_device *udev_device, const char *key,
+ const char *value)
{
- udev_device->envp_uptodate = false;
- if (value == NULL) {
- struct udev_list_entry *list_entry;
-
- list_entry = udev_device_get_properties_list_entry(udev_device);
- list_entry = udev_list_entry_get_by_name(list_entry, key);
- if (list_entry != NULL)
- udev_list_entry_delete(list_entry);
- return NULL;
- }
- return udev_list_entry_add(&udev_device->properties_list, key, value);
-}
+ struct udev_list_entry *property;
+ property = udev_device_add_property_internal (udev_device, key, value);
-int udev_device_add_property(struct udev_device *udev_device, const char *key, const char *value)
-{
- struct udev_list_entry *property;
+ /* store in db, skip private keys */
+ if (key[0] != '.')
+ udev_list_entry_set_num (property, true);
- property = udev_device_add_property_internal(udev_device, key, value);
-
- /* store in db, skip private keys */
- if (key[0] != '.')
- udev_list_entry_set_num(property, true);
-
- return 0;
+ return 0;
}
-static struct udev_list_entry *udev_device_add_property_from_string(struct udev_device *udev_device, const char *property)
+static struct udev_list_entry *
+udev_device_add_property_from_string (struct
+ udev_device
+ *udev_device, const char *property)
{
- char name[UTIL_LINE_SIZE];
- char *val;
+ char name[UTIL_LINE_SIZE];
+ char *val;
- strscpy(name, sizeof(name), property);
- val = strchr(name, '=');
- if (val == NULL)
- return NULL;
- val[0] = '\0';
- val = &val[1];
- if (val[0] == '\0')
- val = NULL;
- return udev_device_add_property_internal(udev_device, name, val);
+ strscpy (name, sizeof (name), property);
+ val = strchr (name, '=');
+ if (val == NULL)
+ return NULL;
+ val[0] = '\0';
+ val = &val[1];
+ if (val[0] == '\0')
+ val = NULL;
+ return udev_device_add_property_internal (udev_device, name, val);
}
-static int udev_device_set_syspath(struct udev_device *udev_device, const char *syspath)
+static int
+udev_device_set_syspath (struct udev_device *udev_device, const char *syspath)
{
- const char *pos;
- size_t len;
+ const char *pos;
+ size_t len;
- free(udev_device->syspath);
- udev_device->syspath = strdup(syspath);
- if (udev_device->syspath == NULL)
- return -ENOMEM;
- udev_device->devpath = udev_device->syspath + strlen("/sys");
- udev_device_add_property_internal(udev_device, "DEVPATH", udev_device->devpath);
+ free (udev_device->syspath);
+ udev_device->syspath = strdup (syspath);
+ if (udev_device->syspath == NULL)
+ return -ENOMEM;
+ udev_device->devpath = udev_device->syspath + strlen ("/sys");
+ udev_device_add_property_internal (udev_device, "DEVPATH",
+ udev_device->devpath);
- pos = strrchr(udev_device->syspath, '/');
- if (pos == NULL)
- return -EINVAL;
- udev_device->sysname = strdup(&pos[1]);
- if (udev_device->sysname == NULL)
- return -ENOMEM;
+ pos = strrchr (udev_device->syspath, '/');
+ if (pos == NULL)
+ return -EINVAL;
+ udev_device->sysname = strdup (&pos[1]);
+ if (udev_device->sysname == NULL)
+ return -ENOMEM;
- /* some devices have '!' in their name, change that to '/' */
- len = 0;
- while (udev_device->sysname[len] != '\0') {
- if (udev_device->sysname[len] == '!')
- udev_device->sysname[len] = '/';
- len++;
- }
+ /* some devices have '!' in their name, change that to '/' */
+ len = 0;
+ while (udev_device->sysname[len] != '\0')
+ {
+ if (udev_device->sysname[len] == '!')
+ udev_device->sysname[len] = '/';
+ len++;
+ }
- /* trailing number */
- while (len > 0 && isdigit(udev_device->sysname[--len]))
- udev_device->sysnum = &udev_device->sysname[len];
+ /* trailing number */
+ while (len > 0 && isdigit (udev_device->sysname[--len]))
+ udev_device->sysnum = &udev_device->sysname[len];
- /* sysname is completely numeric */
- if (len == 0)
- udev_device->sysnum = NULL;
+ /* sysname is completely numeric */
+ if (len == 0)
+ udev_device->sysnum = NULL;
- return 0;
+ return 0;
}
-static void udev_device_set_usec_initialized(struct udev_device *udev_device, usec_t usec_initialized)
+static void
+udev_device_set_usec_initialized (struct udev_device *udev_device,
+ usec_t usec_initialized)
{
- char num[DECIMAL_STR_MAX(usec_t)];
+ char num[DECIMAL_STR_MAX (usec_t)];
- udev_device->usec_initialized = usec_initialized;
- snprintf(num, sizeof(num), USEC_FMT, usec_initialized);
- udev_device_add_property_internal(udev_device, "USEC_INITIALIZED", num);
+ udev_device->usec_initialized = usec_initialized;
+ snprintf (num, sizeof (num), USEC_FMT, usec_initialized);
+ udev_device_add_property_internal (udev_device, "USEC_INITIALIZED", num);
}
-void udev_device_ensure_usec_initialized(struct udev_device *udev_device, struct udev_device *old_device)
+void
+udev_device_ensure_usec_initialized (struct udev_device *udev_device,
+ struct udev_device *old_device)
{
- if (old_device && old_device->usec_initialized != 0)
- udev_device_set_usec_initialized(udev_device, old_device->usec_initialized);
- else
- udev_device_set_usec_initialized(udev_device, now(CLOCK_MONOTONIC));
+ if (old_device && old_device->usec_initialized != 0)
+ udev_device_set_usec_initialized (udev_device,
+ old_device->usec_initialized);
+ else
+ udev_device_set_usec_initialized (udev_device, now (CLOCK_MONOTONIC));
}
-static int udev_device_set_action(struct udev_device *udev_device, const char *action)
+static int
+udev_device_set_action (struct udev_device *udev_device, const char *action)
{
- free(udev_device->action);
- udev_device->action = strdup(action);
- if (udev_device->action == NULL)
- return -ENOMEM;
- udev_device_add_property_internal(udev_device, "ACTION", udev_device->action);
- return 0;
+ free (udev_device->action);
+ udev_device->action = strdup (action);
+ if (udev_device->action == NULL)
+ return -ENOMEM;
+ udev_device_add_property_internal (udev_device, "ACTION",
+ udev_device->action);
+ return 0;
}
/*
@@ -512,92 +577,141 @@ static int udev_device_set_action(struct udev_device *udev_device, const char *a
* DEVUID=(device node UID???)
* DEVGID=(device node GID???)
*/
-static void udev_device_add_property_from_string_parse(struct udev_device *udev_device, const char *property)
-{
- if (startswith(property, "DEVPATH=")) {
- char path[UTIL_PATH_SIZE];
-
- strscpyl(path, sizeof(path), "/sys", &property[8], NULL);
- udev_device_set_syspath(udev_device, path);
- } else if (startswith(property, "SUBSYSTEM=")) {
- udev_device_set_subsystem(udev_device, &property[10]);
- } else if (startswith(property, "DEVTYPE=")) {
- udev_device_set_devtype(udev_device, &property[8]);
- } else if (startswith(property, "DEVNAME=")) {
- udev_device_set_devnode(udev_device, &property[8]);
- } else if (startswith(property, "DEVLINKS=")) {
- char devlinks[UTIL_PATH_SIZE];
- char *slink;
- char *next;
-
- strscpy(devlinks, sizeof(devlinks), &property[9]);
- slink = devlinks;
- next = strchr(slink, ' ');
- while (next != NULL) {
- next[0] = '\0';
- udev_device_add_devlink(udev_device, slink);
- slink = &next[1];
- next = strchr(slink, ' ');
- }
- if (slink[0] != '\0')
- udev_device_add_devlink(udev_device, slink);
- } else if (startswith(property, "TAGS=")) {
- char tags[UTIL_PATH_SIZE];
- char *next;
-
- strscpy(tags, sizeof(tags), &property[5]);
- next = strchr(tags, ':');
- if (next != NULL) {
- next++;
- while (next[0] != '\0') {
- char *tag;
-
- tag = next;
- next = strchr(tag, ':');
- if (next == NULL)
- break;
- next[0] = '\0';
- next++;
- udev_device_add_tag(udev_device, tag);
- }
- }
- } else if (startswith(property, "USEC_INITIALIZED=")) {
- udev_device_set_usec_initialized(udev_device, strtoull(&property[19], NULL, 10));
- } else if (startswith(property, "DRIVER=")) {
- udev_device_set_driver(udev_device, &property[7]);
- } else if (startswith(property, "ACTION=")) {
- udev_device_set_action(udev_device, &property[7]);
- } else if (startswith(property, "MAJOR=")) {
- udev_device->maj = strtoull(&property[6], NULL, 10);
- } else if (startswith(property, "MINOR=")) {
- udev_device->min = strtoull(&property[6], NULL, 10);
- } else if (startswith(property, "DEVPATH_OLD=")) {
- udev_device_set_devpath_old(udev_device, &property[12]);
- } else if (startswith(property, "SEQNUM=")) {
- udev_device_set_seqnum(udev_device, strtoull(&property[7], NULL, 10));
- } else if (startswith(property, "IFINDEX=")) {
- udev_device_set_ifindex(udev_device, strtoull(&property[8], NULL, 10));
- } else if (startswith(property, "DEVMODE=")) {
- udev_device_set_devnode_mode(udev_device, strtoul(&property[8], NULL, 8));
- } else if (startswith(property, "DEVUID=")) {
- udev_device_set_devnode_uid(udev_device, strtoul(&property[7], NULL, 10));
- } else if (startswith(property, "DEVGID=")) {
- udev_device_set_devnode_gid(udev_device, strtoul(&property[7], NULL, 10));
- } else {
- udev_device_add_property_from_string(udev_device, property);
- }
-}
-
-static int udev_device_add_property_from_string_parse_finish(struct udev_device *udev_device)
-{
- if (udev_device->maj > 0)
- udev_device_set_devnum(udev_device, makedev(udev_device->maj, udev_device->min));
- udev_device->maj = 0;
- udev_device->min = 0;
-
- if (udev_device->devpath == NULL || udev_device->subsystem == NULL)
- return -EINVAL;
- return 0;
+static void
+udev_device_add_property_from_string_parse (struct udev_device
+ *udev_device,
+ const char *property)
+{
+ if (startswith (property, "DEVPATH="))
+ {
+ char path[UTIL_PATH_SIZE];
+
+ strscpyl (path, sizeof (path), "/sys", &property[8], NULL);
+ udev_device_set_syspath (udev_device, path);
+ }
+ else if (startswith (property, "SUBSYSTEM="))
+ {
+ udev_device_set_subsystem (udev_device, &property[10]);
+ }
+ else if (startswith (property, "DEVTYPE="))
+ {
+ udev_device_set_devtype (udev_device, &property[8]);
+ }
+ else if (startswith (property, "DEVNAME="))
+ {
+ udev_device_set_devnode (udev_device, &property[8]);
+ }
+ else if (startswith (property, "DEVLINKS="))
+ {
+ char devlinks[UTIL_PATH_SIZE];
+ char *slink;
+ char *next;
+
+ strscpy (devlinks, sizeof (devlinks), &property[9]);
+ slink = devlinks;
+ next = strchr (slink, ' ');
+ while (next != NULL)
+ {
+ next[0] = '\0';
+ udev_device_add_devlink (udev_device, slink);
+ slink = &next[1];
+ next = strchr (slink, ' ');
+ }
+ if (slink[0] != '\0')
+ udev_device_add_devlink (udev_device, slink);
+ }
+ else if (startswith (property, "TAGS="))
+ {
+ char tags[UTIL_PATH_SIZE];
+ char *next;
+
+ strscpy (tags, sizeof (tags), &property[5]);
+ next = strchr (tags, ':');
+ if (next != NULL)
+ {
+ next++;
+ while (next[0] != '\0')
+ {
+ char *tag;
+
+ tag = next;
+ next = strchr (tag, ':');
+ if (next == NULL)
+ break;
+ next[0] = '\0';
+ next++;
+ udev_device_add_tag (udev_device, tag);
+ }
+ }
+ }
+ else if (startswith (property, "USEC_INITIALIZED="))
+ {
+ udev_device_set_usec_initialized (udev_device,
+ strtoull (&property[19], NULL, 10));
+ }
+ else if (startswith (property, "DRIVER="))
+ {
+ udev_device_set_driver (udev_device, &property[7]);
+ }
+ else if (startswith (property, "ACTION="))
+ {
+ udev_device_set_action (udev_device, &property[7]);
+ }
+ else if (startswith (property, "MAJOR="))
+ {
+ udev_device->maj = strtoull (&property[6], NULL, 10);
+ }
+ else if (startswith (property, "MINOR="))
+ {
+ udev_device->min = strtoull (&property[6], NULL, 10);
+ }
+ else if (startswith (property, "DEVPATH_OLD="))
+ {
+ udev_device_set_devpath_old (udev_device, &property[12]);
+ }
+ else if (startswith (property, "SEQNUM="))
+ {
+ udev_device_set_seqnum (udev_device, strtoull (&property[7], NULL, 10));
+ }
+ else if (startswith (property, "IFINDEX="))
+ {
+ udev_device_set_ifindex (udev_device,
+ strtoull (&property[8], NULL, 10));
+ }
+ else if (startswith (property, "DEVMODE="))
+ {
+ udev_device_set_devnode_mode (udev_device,
+ strtoul (&property[8], NULL, 8));
+ }
+ else if (startswith (property, "DEVUID="))
+ {
+ udev_device_set_devnode_uid (udev_device,
+ strtoul (&property[7], NULL, 10));
+ }
+ else if (startswith (property, "DEVGID="))
+ {
+ udev_device_set_devnode_gid (udev_device,
+ strtoul (&property[7], NULL, 10));
+ }
+ else
+ {
+ udev_device_add_property_from_string (udev_device, property);
+ }
+}
+
+static int
+udev_device_add_property_from_string_parse_finish (struct udev_device
+ *udev_device)
+{
+ if (udev_device->maj > 0)
+ udev_device_set_devnum (udev_device,
+ makedev (udev_device->maj, udev_device->min));
+ udev_device->maj = 0;
+ udev_device->min = 0;
+
+ if (udev_device->devpath == NULL || udev_device->subsystem == NULL)
+ return -EINVAL;
+ return 0;
}
/**
@@ -609,169 +723,187 @@ static int udev_device_add_property_from_string_parse_finish(struct udev_device
*
* Returns: the property string, or #NULL if there is no such property.
**/
-const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key)
-{
- struct udev_list_entry *list_entry;
-
- if (udev_device == NULL)
- return NULL;
- if (key == NULL)
- return NULL;
-
- list_entry = udev_device_get_properties_list_entry(udev_device);
- list_entry = udev_list_entry_get_by_name(list_entry, key);
- return udev_list_entry_get_value(list_entry);
-}
-
-static int udev_device_read_db(struct udev_device *udev_device)
-{
- char filename[UTIL_PATH_SIZE];
- char line[UTIL_LINE_SIZE];
- const char *id;
- FILE *f;
-
- if (udev_device->db_loaded)
- return 0;
-
- udev_device->db_loaded = true;
-
- id = udev_device_get_id_filename(udev_device);
- if (id == NULL)
- return -1;
-
- strscpyl(filename, sizeof(filename), "/run/udev/data/", id, NULL);
-
- f = fopen(filename, "re");
- if (f == NULL) {
- int errsv = errno;
- log_debug("no db file to read %s: %s", filename, strerror(errsv));
- return errsv;
- }
-
- /* devices with a database entry are initialized */
- udev_device->is_initialized = true;
-
- while (fgets(line, sizeof(line), f)) {
- ssize_t len;
- const char *val;
- struct udev_list_entry *entry;
-
- len = strlen(line);
- if (len < 4)
- break;
- line[len-1] = '\0';
- val = &line[2];
- switch(line[0]) {
- case 'S':
- strscpyl(filename, sizeof(filename), "/dev/", val, NULL);
- udev_device_add_devlink(udev_device, filename);
- break;
- case 'L':
- udev_device_set_devlink_priority(udev_device, atoi(val));
- break;
- case 'E':
- entry = udev_device_add_property_from_string(udev_device, val);
- udev_list_entry_set_num(entry, true);
- break;
- case 'G':
- udev_device_add_tag(udev_device, val);
- break;
- case 'W':
- udev_device_set_watch_handle(udev_device, atoi(val));
- break;
- case 'I':
- udev_device_set_usec_initialized(udev_device, strtoull(val, NULL, 10));
- break;
- }
- }
- fclose(f);
-
- log_trace("device %p filled with db file data", udev_device);
- return 0;
-}
-
-static int udev_device_read_uevent_file(struct udev_device *udev_device)
-{
- char filename[UTIL_PATH_SIZE];
- FILE *f;
- char line[UTIL_LINE_SIZE];
- int maj = 0;
- int min = 0;
-
- if (udev_device->uevent_loaded)
- return 0;
-
- strscpyl(filename, sizeof(filename), udev_device->syspath, "/uevent", NULL);
- f = fopen(filename, "re");
- if (f == NULL)
- return -errno;
- udev_device->uevent_loaded = true;
-
- while (fgets(line, sizeof(line), f)) {
- char *pos;
-
- pos = strchr(line, '\n');
- if (pos == NULL)
- continue;
- pos[0] = '\0';
-
- if (startswith(line, "DEVTYPE=")) {
- udev_device_set_devtype(udev_device, &line[8]);
- continue;
- }
- if (startswith(line, "IFINDEX=")) {
- udev_device_set_ifindex(udev_device, strtoull(&line[8], NULL, 10));
- continue;
- }
- if (startswith(line, "DEVNAME=")) {
- udev_device_set_devnode(udev_device, &line[8]);
- continue;
- }
-
- if (startswith(line, "MAJOR="))
- maj = strtoull(&line[6], NULL, 10);
- else if (startswith(line, "MINOR="))
- min = strtoull(&line[6], NULL, 10);
- else if (startswith(line, "DEVMODE="))
- udev_device->devnode_mode = strtoul(&line[8], NULL, 8);
-
- udev_device_add_property_from_string(udev_device, line);
- }
-
- udev_device->devnum = makedev(maj, min);
- fclose(f);
- return 0;
-}
-
-void udev_device_set_info_loaded(struct udev_device *device)
-{
- device->info_loaded = true;
-}
-
-static struct udev_device *udev_device_new(struct udev *udev)
-{
- struct udev_device *udev_device;
-
- if (udev == NULL) {
- errno = EINVAL;
- return NULL;
- }
-
- udev_device = new0(struct udev_device, 1);
- if (udev_device == NULL) {
- errno = ENOMEM;
- return NULL;
- }
- udev_device->refcount = 1;
- udev_device->udev = udev;
- udev_list_init(udev, &udev_device->devlinks_list, true);
- udev_list_init(udev, &udev_device->properties_list, true);
- udev_list_init(udev, &udev_device->sysattr_value_list, true);
- udev_list_init(udev, &udev_device->sysattr_list, false);
- udev_list_init(udev, &udev_device->tags_list, true);
- udev_device->watch_handle = -1;
-
- return udev_device;
+const char *
+udev_device_get_property_value (struct udev_device *udev_device,
+ const char *key)
+{
+ struct udev_list_entry *list_entry;
+
+ if (udev_device == NULL)
+ return NULL;
+ if (key == NULL)
+ return NULL;
+
+ list_entry = udev_device_get_properties_list_entry (udev_device);
+ list_entry = udev_list_entry_get_by_name (list_entry, key);
+ return udev_list_entry_get_value (list_entry);
+}
+
+static int
+udev_device_read_db (struct udev_device *udev_device)
+{
+ char filename[UTIL_PATH_SIZE];
+ char line[UTIL_LINE_SIZE];
+ const char *id;
+ FILE *f;
+
+ if (udev_device->db_loaded)
+ return 0;
+
+ udev_device->db_loaded = true;
+
+ id = udev_device_get_id_filename (udev_device);
+ if (id == NULL)
+ return -1;
+
+ strscpyl (filename, sizeof (filename), "/run/udev/data/", id, NULL);
+
+ f = fopen (filename, "re");
+ if (f == NULL)
+ {
+ int errsv = errno;
+ log_debug ("no db file to read %s: %s", filename, strerror (errsv));
+ return errsv;
+ }
+
+ /* devices with a database entry are initialized */
+ udev_device->is_initialized = true;
+
+ while (fgets (line, sizeof (line), f))
+ {
+ ssize_t len;
+ const char *val;
+ struct udev_list_entry *entry;
+
+ len = strlen (line);
+ if (len < 4)
+ break;
+ line[len - 1] = '\0';
+ val = &line[2];
+ switch (line[0])
+ {
+ case 'S':
+ strscpyl (filename, sizeof (filename), "/dev/", val, NULL);
+ udev_device_add_devlink (udev_device, filename);
+ break;
+ case 'L':
+ udev_device_set_devlink_priority (udev_device, atoi (val));
+ break;
+ case 'E':
+ entry = udev_device_add_property_from_string (udev_device, val);
+ udev_list_entry_set_num (entry, true);
+ break;
+ case 'G':
+ udev_device_add_tag (udev_device, val);
+ break;
+ case 'W':
+ udev_device_set_watch_handle (udev_device, atoi (val));
+ break;
+ case 'I':
+ udev_device_set_usec_initialized (udev_device,
+ strtoull (val, NULL, 10));
+ break;
+ }
+ }
+ fclose (f);
+
+ log_trace ("device %p filled with db file data", udev_device);
+ return 0;
+}
+
+static int
+udev_device_read_uevent_file (struct udev_device *udev_device)
+{
+ char filename[UTIL_PATH_SIZE];
+ FILE *f;
+ char line[UTIL_LINE_SIZE];
+ int maj = 0;
+ int min = 0;
+
+ if (udev_device->uevent_loaded)
+ return 0;
+
+ strscpyl (filename, sizeof (filename), udev_device->syspath, "/uevent",
+ NULL);
+ f = fopen (filename, "re");
+ if (f == NULL)
+ return -errno;
+ udev_device->uevent_loaded = true;
+
+ while (fgets (line, sizeof (line), f))
+ {
+ char *pos;
+
+ pos = strchr (line, '\n');
+ if (pos == NULL)
+ continue;
+ pos[0] = '\0';
+
+ if (startswith (line, "DEVTYPE="))
+ {
+ udev_device_set_devtype (udev_device, &line[8]);
+ continue;
+ }
+ if (startswith (line, "IFINDEX="))
+ {
+ udev_device_set_ifindex (udev_device,
+ strtoull (&line[8], NULL, 10));
+ continue;
+ }
+ if (startswith (line, "DEVNAME="))
+ {
+ udev_device_set_devnode (udev_device, &line[8]);
+ continue;
+ }
+
+ if (startswith (line, "MAJOR="))
+ maj = strtoull (&line[6], NULL, 10);
+ else if (startswith (line, "MINOR="))
+ min = strtoull (&line[6], NULL, 10);
+ else if (startswith (line, "DEVMODE="))
+ udev_device->devnode_mode = strtoul (&line[8], NULL, 8);
+
+ udev_device_add_property_from_string (udev_device, line);
+ }
+
+ udev_device->devnum = makedev (maj, min);
+ fclose (f);
+ return 0;
+}
+
+void
+udev_device_set_info_loaded (struct udev_device *device)
+{
+ device->info_loaded = true;
+}
+
+static struct udev_device *
+udev_device_new (struct udev *udev)
+{
+ struct udev_device *udev_device;
+
+ if (udev == NULL)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ udev_device = new0 (struct udev_device, 1);
+ if (udev_device == NULL)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ udev_device->refcount = 1;
+ udev_device->udev = udev;
+ udev_list_init (udev, &udev_device->devlinks_list, true);
+ udev_list_init (udev, &udev_device->properties_list, true);
+ udev_list_init (udev, &udev_device->sysattr_value_list, true);
+ udev_list_init (udev, &udev_device->sysattr_list, false);
+ udev_list_init (udev, &udev_device->tags_list, true);
+ udev_device->watch_handle = -1;
+
+ return udev_device;
}
/**
@@ -788,69 +920,79 @@ static struct udev_device *udev_device_new(struct udev *udev)
*
* Returns: a new udev device, or #NULL, if it does not exist
**/
-struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath)
-{
- const char *subdir;
- char path[UTIL_PATH_SIZE];
- char *pos;
- struct stat statbuf;
- struct udev_device *udev_device;
-
- if (udev == NULL) {
- errno = EINVAL;
- return NULL;
- }
-
- if (syspath == NULL) {
- errno = EINVAL;
- return NULL;
- }
-
- /* path starts in sys */
- if (!startswith(syspath, "/sys")) {
- log_debug("not in sys :%s", syspath);
- errno = EINVAL;
- return NULL;
- }
-
- /* path is not a root directory */
- subdir = syspath + strlen("/sys");
- pos = strrchr(subdir, '/');
- if (pos == NULL || pos[1] == '\0' || pos < &subdir[2]) {
- errno = EINVAL;
- return NULL;
- }
-
- /* resolve possible symlink to real path */
- strscpy(path, sizeof(path), syspath);
- util_resolve_sys_link(udev, path, sizeof(path));
-
- if (startswith(path + strlen("/sys"), "/devices/")) {
- char file[UTIL_PATH_SIZE];
-
- /* all "devices" require a "uevent" file */
- strscpyl(file, sizeof(file), path, "/uevent", NULL);
- if (stat(file, &statbuf) != 0)
- return NULL;
- } else {
- /* everything else just needs to be a directory */
- if (stat(path, &statbuf) != 0)
- return NULL;
-
- if (!S_ISDIR(statbuf.st_mode)) {
- errno = EISDIR;
- return NULL;
- }
- }
-
- udev_device = udev_device_new(udev);
- if (udev_device == NULL)
- return NULL;
-
- udev_device_set_syspath(udev_device, path);
- log_trace("device %p has devpath '%s'", udev_device, udev_device_get_devpath(udev_device));
-
- return udev_device;
+struct udev_device *
+udev_device_new_from_syspath (struct udev *udev, const char *syspath)
+{
+ const char *subdir;
+ char path[UTIL_PATH_SIZE];
+ char *pos;
+ struct stat statbuf;
+ struct udev_device *udev_device;
+
+ if (udev == NULL)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (syspath == NULL)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /* path starts in sys */
+ if (!startswith (syspath, "/sys"))
+ {
+ log_debug ("not in sys :%s", syspath);
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /* path is not a root directory */
+ subdir = syspath + strlen ("/sys");
+ pos = strrchr (subdir, '/');
+ if (pos == NULL || pos[1] == '\0' || pos < &subdir[2])
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /* resolve possible symlink to real path */
+ strscpy (path, sizeof (path), syspath);
+ util_resolve_sys_link (udev, path, sizeof (path));
+
+ if (startswith (path + strlen ("/sys"), "/devices/"))
+ {
+ char file[UTIL_PATH_SIZE];
+
+ /* all "devices" require a "uevent" file */
+ strscpyl (file, sizeof (file), path, "/uevent", NULL);
+ if (stat (file, &statbuf) != 0)
+ return NULL;
+ }
+ else
+ {
+ /* everything else just needs to be a directory */
+ if (stat (path, &statbuf) != 0)
+ return NULL;
+
+ if (!S_ISDIR (statbuf.st_mode))
+ {
+ errno = EISDIR;
+ return NULL;
+ }
+ }
+
+ udev_device = udev_device_new (udev);
+ if (udev_device == NULL)
+ return NULL;
+
+ udev_device_set_syspath (udev_device, path);
+ log_trace ("device %p has devpath '%s'", udev_device,
+ udev_device_get_devpath (udev_device));
+
+ return udev_device;
}
/**
@@ -869,24 +1011,26 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *
*
* Returns: a new udev device, or #NULL, if it does not exist
**/
-struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum)
+struct udev_device *
+udev_device_new_from_devnum (struct udev *udev, char type, dev_t devnum)
{
- char path[UTIL_PATH_SIZE];
- const char *type_str;
+ char path[UTIL_PATH_SIZE];
+ const char *type_str;
- if (type == 'b')
- type_str = "block";
- else if (type == 'c')
- type_str = "char";
- else {
- errno = EINVAL;
- return NULL;
- }
+ if (type == 'b')
+ type_str = "block";
+ else if (type == 'c')
+ type_str = "char";
+ else
+ {
+ errno = EINVAL;
+ return NULL;
+ }
- /* use /sys/dev/{block,char}/: link */
- snprintf(path, sizeof(path), "/sys/dev/%s/%u:%u",
- type_str, major(devnum), minor(devnum));
- return udev_device_new_from_syspath(udev, path);
+ /* use /sys/dev/{block,char}/: link */
+ snprintf (path, sizeof (path), "/sys/dev/%s/%u:%u",
+ type_str, major (devnum), minor (devnum));
+ return udev_device_new_from_syspath (udev, path);
}
/**
@@ -907,67 +1051,74 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de
*
* Returns: a new udev device, or #NULL, if it does not exist
**/
-struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id)
-{
- char type;
- int maj, min;
- char subsys[UTIL_PATH_SIZE];
- char *sysname;
-
- switch(id[0]) {
- case 'b':
- case 'c':
- if (sscanf(id, "%c%i:%i", &type, &maj, &min) != 3)
- return NULL;
- return udev_device_new_from_devnum(udev, type, makedev(maj, min));
- case 'n': {
- int sk;
- struct ifreq ifr;
- struct udev_device *dev;
- int ifindex;
-
- ifindex = strtoul(&id[1], NULL, 10);
- if (ifindex <= 0) {
- errno = EINVAL;
- return NULL;
- }
-
- sk = socket(PF_INET, SOCK_DGRAM, 0);
- if (sk < 0)
- return NULL;
- memzero(&ifr, sizeof(struct ifreq));
- ifr.ifr_ifindex = ifindex;
- if (ioctl(sk, SIOCGIFNAME, &ifr) != 0) {
- close(sk);
- return NULL;
- }
- close(sk);
-
- dev = udev_device_new_from_subsystem_sysname(udev, "net", ifr.ifr_name);
- if (dev == NULL)
- return NULL;
- if (udev_device_get_ifindex(dev) == ifindex)
- return dev;
-
- /* this is racy, so we may end up with the wrong device */
- udev_device_unref(dev);
- errno = ENODEV;
- return NULL;
- }
- case '+':
- strscpy(subsys, sizeof(subsys), &id[1]);
- sysname = strchr(subsys, ':');
- if (sysname == NULL) {
- errno = EINVAL;
- return NULL;
- }
- sysname[0] = '\0';
- sysname = &sysname[1];
- return udev_device_new_from_subsystem_sysname(udev, subsys, sysname);
- default:
- errno = EINVAL;
- return NULL;
- }
+struct udev_device *
+udev_device_new_from_device_id (struct udev *udev, const char *id)
+{
+ char type;
+ int maj, min;
+ char subsys[UTIL_PATH_SIZE];
+ char *sysname;
+
+ switch (id[0])
+ {
+ case 'b':
+ case 'c':
+ if (sscanf (id, "%c%i:%i", &type, &maj, &min) != 3)
+ return NULL;
+ return udev_device_new_from_devnum (udev, type, makedev (maj, min));
+ case 'n':
+ {
+ int sk;
+ struct ifreq ifr;
+ struct udev_device *dev;
+ int ifindex;
+
+ ifindex = strtoul (&id[1], NULL, 10);
+ if (ifindex <= 0)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ sk = socket (PF_INET, SOCK_DGRAM, 0);
+ if (sk < 0)
+ return NULL;
+ memzero (&ifr, sizeof (struct ifreq));
+ ifr.ifr_ifindex = ifindex;
+ if (ioctl (sk, SIOCGIFNAME, &ifr) != 0)
+ {
+ close (sk);
+ return NULL;
+ }
+ close (sk);
+
+ dev =
+ udev_device_new_from_subsystem_sysname (udev, "net", ifr.ifr_name);
+ if (dev == NULL)
+ return NULL;
+ if (udev_device_get_ifindex (dev) == ifindex)
+ return dev;
+
+ /* this is racy, so we may end up with the wrong device */
+ udev_device_unref (dev);
+ errno = ENODEV;
+ return NULL;
+ }
+ case '+':
+ strscpy (subsys, sizeof (subsys), &id[1]);
+ sysname = strchr (subsys, ':');
+ if (sysname == NULL)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+ sysname[0] = '\0';
+ sysname = &sysname[1];
+ return udev_device_new_from_subsystem_sysname (udev, subsys, sysname);
+ default:
+ errno = EINVAL;
+ return NULL;
+ }
}
/**
@@ -985,71 +1136,84 @@ struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char
*
* Returns: a new udev device, or #NULL, if it does not exist
**/
-struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname)
-{
- char path[UTIL_PATH_SIZE];
- struct stat statbuf;
-
- if (streq(subsystem, "subsystem")) {
- strscpyl(path, sizeof(path), "/sys/subsystem/", sysname, NULL);
- if (stat(path, &statbuf) == 0)
- goto found;
-
- strscpyl(path, sizeof(path), "/sys/bus/", sysname, NULL);
- if (stat(path, &statbuf) == 0)
- goto found;
-
- strscpyl(path, sizeof(path), "/sys/class/", sysname, NULL);
- if (stat(path, &statbuf) == 0)
- goto found;
- goto out;
- }
-
- if (streq(subsystem, "module")) {
- strscpyl(path, sizeof(path), "/sys/module/", sysname, NULL);
- if (stat(path, &statbuf) == 0)
- goto found;
- goto out;
- }
-
- if (streq(subsystem, "drivers")) {
- char subsys[UTIL_NAME_SIZE];
- char *driver;
-
- strscpy(subsys, sizeof(subsys), sysname);
- driver = strchr(subsys, ':');
- if (driver != NULL) {
- driver[0] = '\0';
- driver = &driver[1];
-
- strscpyl(path, sizeof(path), "/sys/subsystem/", subsys, "/drivers/", driver, NULL);
- if (stat(path, &statbuf) == 0)
- goto found;
-
- strscpyl(path, sizeof(path), "/sys/bus/", subsys, "/drivers/", driver, NULL);
- if (stat(path, &statbuf) == 0)
- goto found;
- } else
- errno = EINVAL;
-
- goto out;
- }
-
- strscpyl(path, sizeof(path), "/sys/subsystem/", subsystem, "/devices/", sysname, NULL);
- if (stat(path, &statbuf) == 0)
- goto found;
-
- strscpyl(path, sizeof(path), "/sys/bus/", subsystem, "/devices/", sysname, NULL);
- if (stat(path, &statbuf) == 0)
- goto found;
-
- strscpyl(path, sizeof(path), "/sys/class/", subsystem, "/", sysname, NULL);
- if (stat(path, &statbuf) == 0)
- goto found;
+struct udev_device *
+udev_device_new_from_subsystem_sysname (struct udev *udev,
+ const char
+ *subsystem, const char *sysname)
+{
+ char path[UTIL_PATH_SIZE];
+ struct stat statbuf;
+
+ if (streq (subsystem, "subsystem"))
+ {
+ strscpyl (path, sizeof (path), "/sys/subsystem/", sysname, NULL);
+ if (stat (path, &statbuf) == 0)
+ goto found;
+
+ strscpyl (path, sizeof (path), "/sys/bus/", sysname, NULL);
+ if (stat (path, &statbuf) == 0)
+ goto found;
+
+ strscpyl (path, sizeof (path), "/sys/class/", sysname, NULL);
+ if (stat (path, &statbuf) == 0)
+ goto found;
+ goto out;
+ }
+
+ if (streq (subsystem, "module"))
+ {
+ strscpyl (path, sizeof (path), "/sys/module/", sysname, NULL);
+ if (stat (path, &statbuf) == 0)
+ goto found;
+ goto out;
+ }
+
+ if (streq (subsystem, "drivers"))
+ {
+ char subsys[UTIL_NAME_SIZE];
+ char *driver;
+
+ strscpy (subsys, sizeof (subsys), sysname);
+ driver = strchr (subsys, ':');
+ if (driver != NULL)
+ {
+ driver[0] = '\0';
+ driver = &driver[1];
+
+ strscpyl (path, sizeof (path), "/sys/subsystem/", subsys,
+ "/drivers/", driver, NULL);
+ if (stat (path, &statbuf) == 0)
+ goto found;
+
+ strscpyl (path, sizeof (path), "/sys/bus/", subsys,
+ "/drivers/", driver, NULL);
+ if (stat (path, &statbuf) == 0)
+ goto found;
+ }
+ else
+ errno = EINVAL;
+
+ goto out;
+ }
+
+ strscpyl (path, sizeof (path), "/sys/subsystem/", subsystem, "/devices/",
+ sysname, NULL);
+ if (stat (path, &statbuf) == 0)
+ goto found;
+
+ strscpyl (path, sizeof (path), "/sys/bus/", subsystem, "/devices/",
+ sysname, NULL);
+ if (stat (path, &statbuf) == 0)
+ goto found;
+
+ strscpyl (path, sizeof (path), "/sys/class/", subsystem, "/", sysname,
+ NULL);
+ if (stat (path, &statbuf) == 0)
+ goto found;
out:
- return NULL;
+ return NULL;
found:
- return udev_device_new_from_syspath(udev, path);
+ return udev_device_new_from_syspath (udev, path);
}
/**
@@ -1066,50 +1230,55 @@ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, co
*
* Returns: a new udev device, or #NULL, if it does not exist
**/
-struct udev_device *udev_device_new_from_environment(struct udev *udev)
+struct udev_device *
+udev_device_new_from_environment (struct udev *udev)
{
- int i;
- struct udev_device *udev_device;
+ int i;
+ struct udev_device *udev_device;
- udev_device = udev_device_new(udev);
- if (udev_device == NULL)
- return NULL;
- udev_device_set_info_loaded(udev_device);
+ udev_device = udev_device_new (udev);
+ if (udev_device == NULL)
+ return NULL;
+ udev_device_set_info_loaded (udev_device);
- for (i = 0; environ[i] != NULL; i++)
- udev_device_add_property_from_string_parse(udev_device, environ[i]);
+ for (i = 0; environ[i] != NULL; i++)
+ udev_device_add_property_from_string_parse (udev_device, environ[i]);
- if (udev_device_add_property_from_string_parse_finish(udev_device) < 0) {
- log_debug("%s", "missing values, invalid device");
- udev_device_unref(udev_device);
- udev_device = NULL;
- }
+ if (udev_device_add_property_from_string_parse_finish (udev_device) < 0)
+ {
+ log_debug ("%s", "missing values, invalid device");
+ udev_device_unref (udev_device);
+ udev_device = NULL;
+ }
- return udev_device;
+ return udev_device;
}
-static struct udev_device *device_new_from_parent(struct udev_device *udev_device)
+static struct udev_device *
+device_new_from_parent (struct udev_device *udev_device)
{
- struct udev_device *udev_device_parent = NULL;
- char path[UTIL_PATH_SIZE];
- const char *subdir;
+ struct udev_device *udev_device_parent = NULL;
+ char path[UTIL_PATH_SIZE];
+ const char *subdir;
- strscpy(path, sizeof(path), udev_device->syspath);
- subdir = path + strlen("/sys/");
- for (;;) {
- char *pos;
+ strscpy (path, sizeof (path), udev_device->syspath);
+ subdir = path + strlen ("/sys/");
+ for (;;)
+ {
+ char *pos;
- pos = strrchr(subdir, '/');
- if (pos == NULL || pos < &subdir[2])
- break;
- pos[0] = '\0';
- udev_device_parent = udev_device_new_from_syspath(udev_device->udev, path);
- if (udev_device_parent != NULL)
- return udev_device_parent;
- }
+ pos = strrchr (subdir, '/');
+ if (pos == NULL || pos < &subdir[2])
+ break;
+ pos[0] = '\0';
+ udev_device_parent =
+ udev_device_new_from_syspath (udev_device->udev, path);
+ if (udev_device_parent != NULL)
+ return udev_device_parent;
+ }
- errno = ENOENT;
- return NULL;
+ errno = ENOENT;
+ return NULL;
}
/**
@@ -1130,17 +1299,20 @@ static struct udev_device *device_new_from_parent(struct udev_device *udev_devic
*
* Returns: a new udev device, or #NULL, if it no parent exist.
**/
-struct udev_device *udev_device_get_parent(struct udev_device *udev_device)
-{
- if (udev_device == NULL) {
- errno = EINVAL;
- return NULL;
- }
- if (!udev_device->parent_set) {
- udev_device->parent_set = true;
- udev_device->parent_device = device_new_from_parent(udev_device);
- }
- return udev_device->parent_device;
+struct udev_device *
+udev_device_get_parent (struct udev_device *udev_device)
+{
+ if (udev_device == NULL)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+ if (!udev_device->parent_set)
+ {
+ udev_device->parent_set = true;
+ udev_device->parent_device = device_new_from_parent (udev_device);
+ }
+ return udev_device->parent_device;
}
/**
@@ -1164,35 +1336,44 @@ struct udev_device *udev_device_get_parent(struct udev_device *udev_device)
*
* Returns: a new udev device, or #NULL if no matching parent exists.
**/
-struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype)
-{
- struct udev_device *parent;
-
- if (subsystem == NULL) {
- errno = EINVAL;
- return NULL;
- }
-
- parent = udev_device_get_parent(udev_device);
- while (parent != NULL) {
- const char *parent_subsystem;
- const char *parent_devtype;
-
- parent_subsystem = udev_device_get_subsystem(parent);
- if (parent_subsystem != NULL && streq(parent_subsystem, subsystem)) {
- if (devtype == NULL)
- break;
- parent_devtype = udev_device_get_devtype(parent);
- if (parent_devtype != NULL && streq(parent_devtype, devtype))
- break;
- }
- parent = udev_device_get_parent(parent);
- }
-
- if (!parent)
- errno = ENOENT;
-
- return parent;
+struct udev_device *
+udev_device_get_parent_with_subsystem_devtype (struct
+ udev_device
+ *udev_device,
+ const char
+ *subsystem,
+ const char *devtype)
+{
+ struct udev_device *parent;
+
+ if (subsystem == NULL)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ parent = udev_device_get_parent (udev_device);
+ while (parent != NULL)
+ {
+ const char *parent_subsystem;
+ const char *parent_devtype;
+
+ parent_subsystem = udev_device_get_subsystem (parent);
+ if (parent_subsystem != NULL && streq (parent_subsystem, subsystem))
+ {
+ if (devtype == NULL)
+ break;
+ parent_devtype = udev_device_get_devtype (parent);
+ if (parent_devtype != NULL && streq (parent_devtype, devtype))
+ break;
+ }
+ parent = udev_device_get_parent (parent);
+ }
+
+ if (!parent)
+ errno = ENOENT;
+
+ return parent;
}
/**
@@ -1203,11 +1384,12 @@ struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_de
*
* Returns: the udev library context
**/
-struct udev *udev_device_get_udev(struct udev_device *udev_device)
+struct udev *
+udev_device_get_udev (struct udev_device *udev_device)
{
- if (udev_device == NULL)
- return NULL;
- return udev_device->udev;
+ if (udev_device == NULL)
+ return NULL;
+ return udev_device->udev;
}
/**
@@ -1218,12 +1400,13 @@ struct udev *udev_device_get_udev(struct udev_device *udev_device)
*
* Returns: the passed udev device
**/
-struct udev_device *udev_device_ref(struct udev_device *udev_device)
+struct udev_device *
+udev_device_ref (struct udev_device *udev_device)
{
- if (udev_device == NULL)
- return NULL;
- udev_device->refcount++;
- return udev_device;
+ if (udev_device == NULL)
+ return NULL;
+ udev_device->refcount++;
+ return udev_device;
}
/**
@@ -1235,33 +1418,34 @@ struct udev_device *udev_device_ref(struct udev_device *udev_device)
*
* Returns: #NULL
**/
-struct udev_device *udev_device_unref(struct udev_device *udev_device)
-{
- if (udev_device == NULL)
- return NULL;
- udev_device->refcount--;
- if (udev_device->refcount > 0)
- return NULL;
- if (udev_device->parent_device != NULL)
- udev_device_unref(udev_device->parent_device);
- free(udev_device->syspath);
- free(udev_device->sysname);
- free(udev_device->devnode);
- free(udev_device->subsystem);
- free(udev_device->devtype);
- udev_list_cleanup(&udev_device->devlinks_list);
- udev_list_cleanup(&udev_device->properties_list);
- udev_list_cleanup(&udev_device->sysattr_value_list);
- udev_list_cleanup(&udev_device->sysattr_list);
- udev_list_cleanup(&udev_device->tags_list);
- free(udev_device->action);
- free(udev_device->driver);
- free(udev_device->devpath_old);
- free(udev_device->id_filename);
- free(udev_device->envp);
- free(udev_device->monitor_buf);
- free(udev_device);
- return NULL;
+struct udev_device *
+udev_device_unref (struct udev_device *udev_device)
+{
+ if (udev_device == NULL)
+ return NULL;
+ udev_device->refcount--;
+ if (udev_device->refcount > 0)
+ return NULL;
+ if (udev_device->parent_device != NULL)
+ udev_device_unref (udev_device->parent_device);
+ free (udev_device->syspath);
+ free (udev_device->sysname);
+ free (udev_device->devnode);
+ free (udev_device->subsystem);
+ free (udev_device->devtype);
+ udev_list_cleanup (&udev_device->devlinks_list);
+ udev_list_cleanup (&udev_device->properties_list);
+ udev_list_cleanup (&udev_device->sysattr_value_list);
+ udev_list_cleanup (&udev_device->sysattr_list);
+ udev_list_cleanup (&udev_device->tags_list);
+ free (udev_device->action);
+ free (udev_device->driver);
+ free (udev_device->devpath_old);
+ free (udev_device->id_filename);
+ free (udev_device->envp);
+ free (udev_device->monitor_buf);
+ free (udev_device);
+ return NULL;
}
/**
@@ -1273,11 +1457,12 @@ struct udev_device *udev_device_unref(struct udev_device *udev_device)
*
* Returns: the devpath of the udev device
**/
-const char *udev_device_get_devpath(struct udev_device *udev_device)
+const char *
+udev_device_get_devpath (struct udev_device *udev_device)
{
- if (udev_device == NULL)
- return NULL;
- return udev_device->devpath;
+ if (udev_device == NULL)
+ return NULL;
+ return udev_device->devpath;
}
/**
@@ -1289,11 +1474,12 @@ const char *udev_device_get_devpath(struct udev_device *udev_device)
*
* Returns: the sys path of the udev device
**/
-const char *udev_device_get_syspath(struct udev_device *udev_device)
+const char *
+udev_device_get_syspath (struct udev_device *udev_device)
{
- if (udev_device == NULL)
- return NULL;
- return udev_device->syspath;
+ if (udev_device == NULL)
+ return NULL;
+ return udev_device->syspath;
}
/**
@@ -1304,11 +1490,12 @@ const char *udev_device_get_syspath(struct udev_device *udev_device)
*
* Returns: the name string of the device device
**/
-const char *udev_device_get_sysname(struct udev_device *udev_device)
+const char *
+udev_device_get_sysname (struct udev_device *udev_device)
{
- if (udev_device == NULL)
- return NULL;
- return udev_device->sysname;
+ if (udev_device == NULL)
+ return NULL;
+ return udev_device->sysname;
}
/**
@@ -1319,11 +1506,12 @@ const char *udev_device_get_sysname(struct udev_device *udev_device)
*
* Returns: the trailing number string of the device name
**/
-const char *udev_device_get_sysnum(struct udev_device *udev_device)
+const char *
+udev_device_get_sysnum (struct udev_device *udev_device)
{
- if (udev_device == NULL)
- return NULL;
- return udev_device->sysnum;
+ if (udev_device == NULL)
+ return NULL;
+ return udev_device->sysnum;
}
/**
@@ -1335,15 +1523,16 @@ const char *udev_device_get_sysnum(struct udev_device *udev_device)
*
* Returns: the device node file name of the udev device, or #NULL if no device node exists
**/
-const char *udev_device_get_devnode(struct udev_device *udev_device)
+const char *
+udev_device_get_devnode (struct udev_device *udev_device)
{
- if (udev_device == NULL)
- return NULL;
- if (udev_device->devnode != NULL)
- return udev_device->devnode;
- if (!udev_device->info_loaded)
- udev_device_read_uevent_file(udev_device);
- return udev_device->devnode;
+ if (udev_device == NULL)
+ return NULL;
+ if (udev_device->devnode != NULL)
+ return udev_device->devnode;
+ if (!udev_device->info_loaded)
+ udev_device_read_uevent_file (udev_device);
+ return udev_device->devnode;
}
/**
@@ -1359,19 +1548,21 @@ const char *udev_device_get_devnode(struct udev_device *udev_device)
*
* Returns: the first entry of the device node link list
**/
-struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device)
+struct udev_list_entry *
+udev_device_get_devlinks_list_entry (struct udev_device *udev_device)
{
- if (udev_device == NULL)
- return NULL;
- if (!udev_device->info_loaded)
- udev_device_read_db(udev_device);
- return udev_list_get_entry(&udev_device->devlinks_list);
+ if (udev_device == NULL)
+ return NULL;
+ if (!udev_device->info_loaded)
+ udev_device_read_db (udev_device);
+ return udev_list_get_entry (&udev_device->devlinks_list);
}
-void udev_device_cleanup_devlinks_list(struct udev_device *udev_device)
+void
+udev_device_cleanup_devlinks_list (struct udev_device *udev_device)
{
- udev_device->devlinks_uptodate = false;
- udev_list_cleanup(&udev_device->devlinks_list);
+ udev_device->devlinks_uptodate = false;
+ udev_list_cleanup (&udev_device->devlinks_list);
}
/**
@@ -1386,47 +1577,63 @@ void udev_device_cleanup_devlinks_list(struct udev_device *udev_device)
*
* Returns: the first entry of the property list
**/
-struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device)
-{
- if (udev_device == NULL)
- return NULL;
- if (!udev_device->info_loaded) {
- udev_device_read_uevent_file(udev_device);
- udev_device_read_db(udev_device);
- }
- if (!udev_device->devlinks_uptodate) {
- char symlinks[UTIL_PATH_SIZE];
- struct udev_list_entry *list_entry;
-
- udev_device->devlinks_uptodate = true;
- list_entry = udev_device_get_devlinks_list_entry(udev_device);
- if (list_entry != NULL) {
- char *s;
- size_t l;
-
- s = symlinks;
- l = strpcpyl(&s, sizeof(symlinks), udev_list_entry_get_name(list_entry), NULL);
- udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry))
- l = strpcpyl(&s, l, " ", udev_list_entry_get_name(list_entry), NULL);
- udev_device_add_property_internal(udev_device, "DEVLINKS", symlinks);
- }
- }
- if (!udev_device->tags_uptodate) {
- udev_device->tags_uptodate = true;
- if (udev_device_get_tags_list_entry(udev_device) != NULL) {
- char tags[UTIL_PATH_SIZE];
- struct udev_list_entry *list_entry;
- char *s;
- size_t l;
-
- s = tags;
- l = strpcpyl(&s, sizeof(tags), ":", NULL);
- udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(udev_device))
- l = strpcpyl(&s, l, udev_list_entry_get_name(list_entry), ":", NULL);
- udev_device_add_property_internal(udev_device, "TAGS", tags);
- }
- }
- return udev_list_get_entry(&udev_device->properties_list);
+struct udev_list_entry *
+udev_device_get_properties_list_entry (struct udev_device *udev_device)
+{
+ if (udev_device == NULL)
+ return NULL;
+ if (!udev_device->info_loaded)
+ {
+ udev_device_read_uevent_file (udev_device);
+ udev_device_read_db (udev_device);
+ }
+ if (!udev_device->devlinks_uptodate)
+ {
+ char symlinks[UTIL_PATH_SIZE];
+ struct udev_list_entry *list_entry;
+
+ udev_device->devlinks_uptodate = true;
+ list_entry = udev_device_get_devlinks_list_entry (udev_device);
+ if (list_entry != NULL)
+ {
+ char *s;
+ size_t l;
+
+ s = symlinks;
+ l = strpcpyl (&s, sizeof (symlinks),
+ udev_list_entry_get_name (list_entry), NULL);
+ udev_list_entry_foreach (list_entry,
+ udev_list_entry_get_next
+ (list_entry))
+ l =
+ strpcpyl (&s, l, " ",
+ udev_list_entry_get_name (list_entry), NULL);
+ udev_device_add_property_internal (udev_device,
+ "DEVLINKS", symlinks);
+ }
+ }
+ if (!udev_device->tags_uptodate)
+ {
+ udev_device->tags_uptodate = true;
+ if (udev_device_get_tags_list_entry (udev_device) != NULL)
+ {
+ char tags[UTIL_PATH_SIZE];
+ struct udev_list_entry *list_entry;
+ char *s;
+ size_t l;
+
+ s = tags;
+ l = strpcpyl (&s, sizeof (tags), ":", NULL);
+ udev_list_entry_foreach (list_entry,
+ udev_device_get_tags_list_entry
+ (udev_device))
+ l =
+ strpcpyl (&s, l,
+ udev_list_entry_get_name (list_entry), ":", NULL);
+ udev_device_add_property_internal (udev_device, "TAGS", tags);
+ }
+ }
+ return udev_list_get_entry (&udev_device->properties_list);
}
/**
@@ -1439,11 +1646,12 @@ struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device
*
* Returns: the kernel action value, or #NULL if there is no action value available.
**/
-const char *udev_device_get_action(struct udev_device *udev_device)
+const char *
+udev_device_get_action (struct udev_device *udev_device)
{
- if (udev_device == NULL)
- return NULL;
- return udev_device->action;
+ if (udev_device == NULL)
+ return NULL;
+ return udev_device->action;
}
/**
@@ -1458,25 +1666,27 @@ const char *udev_device_get_action(struct udev_device *udev_device)
*
* Returns: the number of microseconds since the device was first seen.
**/
-unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device)
+unsigned long long int
+udev_device_get_usec_since_initialized (struct udev_device *udev_device)
{
- usec_t now_ts;
+ usec_t now_ts;
- if (udev_device == NULL)
- return 0;
- if (!udev_device->info_loaded)
- udev_device_read_db(udev_device);
- if (udev_device->usec_initialized == 0)
- return 0;
- now_ts = now(CLOCK_MONOTONIC);
- if (now_ts == 0)
- return 0;
- return now_ts - udev_device->usec_initialized;
+ if (udev_device == NULL)
+ return 0;
+ if (!udev_device->info_loaded)
+ udev_device_read_db (udev_device);
+ if (udev_device->usec_initialized == 0)
+ return 0;
+ now_ts = now (CLOCK_MONOTONIC);
+ if (now_ts == 0)
+ return 0;
+ return now_ts - udev_device->usec_initialized;
}
-usec_t udev_device_get_usec_initialized(struct udev_device *udev_device)
+usec_t
+udev_device_get_usec_initialized (struct udev_device * udev_device)
{
- return udev_device->usec_initialized;
+ return udev_device->usec_initialized;
}
/**
@@ -1489,78 +1699,87 @@ usec_t udev_device_get_usec_initialized(struct udev_device *udev_device)
*
* Returns: the content of a sys attribute file, or #NULL if there is no sys attribute value.
**/
-const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr)
-{
- struct udev_list_entry *list_entry;
- char path[UTIL_PATH_SIZE];
- char value[4096];
- struct stat statbuf;
- int fd;
- ssize_t size;
- const char *val = NULL;
-
- if (udev_device == NULL)
- return NULL;
- if (sysattr == NULL)
- return NULL;
-
- /* look for possibly already cached result */
- list_entry = udev_list_get_entry(&udev_device->sysattr_value_list);
- list_entry = udev_list_entry_get_by_name(list_entry, sysattr);
- if (list_entry != NULL)
- return udev_list_entry_get_value(list_entry);
-
- strscpyl(path, sizeof(path), udev_device_get_syspath(udev_device), "/", sysattr, NULL);
- if (lstat(path, &statbuf) != 0) {
- udev_list_entry_add(&udev_device->sysattr_value_list, sysattr, NULL);
- goto out;
- }
-
- if (S_ISLNK(statbuf.st_mode)) {
- /*
- * Some core links return only the last element of the target path,
- * these are just values, the paths should not be exposed.
- */
- if (streq(sysattr, "driver") ||
- streq(sysattr, "subsystem") ||
- streq(sysattr, "module")) {
- if (util_get_sys_core_link_value(udev_device->udev, sysattr,
- udev_device->syspath, value, sizeof(value)) < 0)
- return NULL;
- list_entry = udev_list_entry_add(&udev_device->sysattr_value_list, sysattr, value);
- val = udev_list_entry_get_value(list_entry);
- goto out;
- }
-
- goto out;
- }
-
- /* skip directories */
- if (S_ISDIR(statbuf.st_mode))
- goto out;
-
- /* skip non-readable files */
- if ((statbuf.st_mode & S_IRUSR) == 0)
- goto out;
-
- /* read attribute value */
- fd = open(path, O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- goto out;
- size = read(fd, value, sizeof(value));
- close(fd);
- if (size < 0)
- goto out;
- if (size == sizeof(value))
- goto out;
-
- /* got a valid value, store it in cache and return it */
- value[size] = '\0';
- util_remove_trailing_chars(value, '\n');
- list_entry = udev_list_entry_add(&udev_device->sysattr_value_list, sysattr, value);
- val = udev_list_entry_get_value(list_entry);
+const char *
+udev_device_get_sysattr_value (struct udev_device *udev_device,
+ const char *sysattr)
+{
+ struct udev_list_entry *list_entry;
+ char path[UTIL_PATH_SIZE];
+ char value[4096];
+ struct stat statbuf;
+ int fd;
+ ssize_t size;
+ const char *val = NULL;
+
+ if (udev_device == NULL)
+ return NULL;
+ if (sysattr == NULL)
+ return NULL;
+
+ /* look for possibly already cached result */
+ list_entry = udev_list_get_entry (&udev_device->sysattr_value_list);
+ list_entry = udev_list_entry_get_by_name (list_entry, sysattr);
+ if (list_entry != NULL)
+ return udev_list_entry_get_value (list_entry);
+
+ strscpyl (path, sizeof (path), udev_device_get_syspath (udev_device), "/",
+ sysattr, NULL);
+ if (lstat (path, &statbuf) != 0)
+ {
+ udev_list_entry_add (&udev_device->sysattr_value_list, sysattr, NULL);
+ goto out;
+ }
+
+ if (S_ISLNK (statbuf.st_mode))
+ {
+ /*
+ * Some core links return only the last element of the target path,
+ * these are just values, the paths should not be exposed.
+ */
+ if (streq (sysattr, "driver") ||
+ streq (sysattr, "subsystem") || streq (sysattr, "module"))
+ {
+ if (util_get_sys_core_link_value
+ (udev_device->udev, sysattr, udev_device->syspath,
+ value, sizeof (value)) < 0)
+ return NULL;
+ list_entry =
+ udev_list_entry_add (&udev_device->sysattr_value_list, sysattr,
+ value);
+ val = udev_list_entry_get_value (list_entry);
+ goto out;
+ }
+
+ goto out;
+ }
+
+ /* skip directories */
+ if (S_ISDIR (statbuf.st_mode))
+ goto out;
+
+ /* skip non-readable files */
+ if ((statbuf.st_mode & S_IRUSR) == 0)
+ goto out;
+
+ /* read attribute value */
+ fd = open (path, O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
+ goto out;
+ size = read (fd, value, sizeof (value));
+ close (fd);
+ if (size < 0)
+ goto out;
+ if (size == sizeof (value))
+ goto out;
+
+ /* got a valid value, store it in cache and return it */
+ value[size] = '\0';
+ util_remove_trailing_chars (value, '\n');
+ list_entry =
+ udev_list_entry_add (&udev_device->sysattr_value_list, sysattr, value);
+ val = udev_list_entry_get_value (list_entry);
out:
- return val;
+ return val;
}
/**
@@ -1573,118 +1792,133 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const
*
* Returns: Negative error code on failure or 0 on success.
**/
-int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value)
-{
- struct udev_device *dev;
- char path[UTIL_PATH_SIZE];
- struct stat statbuf;
- int fd;
- ssize_t size, value_len;
- int ret = 0;
-
- if (udev_device == NULL)
- return -EINVAL;
- dev = udev_device;
- if (sysattr == NULL)
- return -EINVAL;
- if (value == NULL)
- value_len = 0;
- else
- value_len = strlen(value);
-
- strscpyl(path, sizeof(path), udev_device_get_syspath(dev), "/", sysattr, NULL);
- if (lstat(path, &statbuf) != 0) {
- udev_list_entry_add(&dev->sysattr_value_list, sysattr, NULL);
- ret = -ENXIO;
- goto out;
- }
-
- if (S_ISLNK(statbuf.st_mode)) {
- ret = -EINVAL;
- goto out;
- }
-
- /* skip directories */
- if (S_ISDIR(statbuf.st_mode)) {
- ret = -EISDIR;
- goto out;
- }
-
- /* skip non-readable files */
- if ((statbuf.st_mode & S_IRUSR) == 0) {
- ret = -EACCES;
- goto out;
- }
-
- /* Value is limited to 4k */
- if (value_len > 4096) {
- ret = -EINVAL;
- goto out;
- }
- util_remove_trailing_chars(value, '\n');
-
- /* write attribute value */
- fd = open(path, O_WRONLY|O_CLOEXEC);
- if (fd < 0) {
- ret = -errno;
- goto out;
- }
- size = write(fd, value, value_len);
- close(fd);
- if (size < 0) {
- ret = -errno;
- goto out;
- }
- if (size < value_len) {
- ret = -EIO;
- goto out;
- }
-
- /* wrote a valid value, store it in cache and return it */
- udev_list_entry_add(&dev->sysattr_value_list, sysattr, value);
+int
+udev_device_set_sysattr_value (struct udev_device *udev_device,
+ const char *sysattr, char *value)
+{
+ struct udev_device *dev;
+ char path[UTIL_PATH_SIZE];
+ struct stat statbuf;
+ int fd;
+ ssize_t size, value_len;
+ int ret = 0;
+
+ if (udev_device == NULL)
+ return -EINVAL;
+ dev = udev_device;
+ if (sysattr == NULL)
+ return -EINVAL;
+ if (value == NULL)
+ value_len = 0;
+ else
+ value_len = strlen (value);
+
+ strscpyl (path, sizeof (path), udev_device_get_syspath (dev), "/", sysattr,
+ NULL);
+ if (lstat (path, &statbuf) != 0)
+ {
+ udev_list_entry_add (&dev->sysattr_value_list, sysattr, NULL);
+ ret = -ENXIO;
+ goto out;
+ }
+
+ if (S_ISLNK (statbuf.st_mode))
+ {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* skip directories */
+ if (S_ISDIR (statbuf.st_mode))
+ {
+ ret = -EISDIR;
+ goto out;
+ }
+
+ /* skip non-readable files */
+ if ((statbuf.st_mode & S_IRUSR) == 0)
+ {
+ ret = -EACCES;
+ goto out;
+ }
+
+ /* Value is limited to 4k */
+ if (value_len > 4096)
+ {
+ ret = -EINVAL;
+ goto out;
+ }
+ util_remove_trailing_chars (value, '\n');
+
+ /* write attribute value */
+ fd = open (path, O_WRONLY | O_CLOEXEC);
+ if (fd < 0)
+ {
+ ret = -errno;
+ goto out;
+ }
+ size = write (fd, value, value_len);
+ close (fd);
+ if (size < 0)
+ {
+ ret = -errno;
+ goto out;
+ }
+ if (size < value_len)
+ {
+ ret = -EIO;
+ goto out;
+ }
+
+ /* wrote a valid value, store it in cache and return it */
+ udev_list_entry_add (&dev->sysattr_value_list, sysattr, value);
out:
- if (dev != udev_device)
- udev_device_unref(dev);
- return ret;
+ if (dev != udev_device)
+ udev_device_unref (dev);
+ return ret;
}
-static int udev_device_sysattr_list_read(struct udev_device *udev_device)
+static int
+udev_device_sysattr_list_read (struct udev_device *udev_device)
{
- struct dirent *dent;
- DIR *dir;
- int num = 0;
+ struct dirent *dent;
+ DIR *dir;
+ int num = 0;
- if (udev_device == NULL)
- return -EINVAL;
- if (udev_device->sysattr_list_read)
- return 0;
+ if (udev_device == NULL)
+ return -EINVAL;
+ if (udev_device->sysattr_list_read)
+ return 0;
- dir = opendir(udev_device_get_syspath(udev_device));
- if (!dir)
- return -errno;
+ dir = opendir (udev_device_get_syspath (udev_device));
+ if (!dir)
+ return -errno;
- for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
- char path[UTIL_PATH_SIZE];
- struct stat statbuf;
+ for (dent = readdir (dir); dent != NULL; dent = readdir (dir))
+ {
+ char path[UTIL_PATH_SIZE];
+ struct stat statbuf;
- /* only handle symlinks and regular files */
- if (dent->d_type != DT_LNK && dent->d_type != DT_REG)
- continue;
+ /* only handle symlinks and regular files */
+ if (dent->d_type != DT_LNK && dent->d_type != DT_REG)
+ continue;
- strscpyl(path, sizeof(path), udev_device_get_syspath(udev_device), "/", dent->d_name, NULL);
- if (lstat(path, &statbuf) != 0)
- continue;
- if ((statbuf.st_mode & S_IRUSR) == 0)
- continue;
+ strscpyl (path, sizeof (path),
+ udev_device_get_syspath (udev_device), "/",
+ dent->d_name, NULL);
+ if (lstat (path, &statbuf) != 0)
+ continue;
+ if ((statbuf.st_mode & S_IRUSR) == 0)
+ continue;
- udev_list_entry_add(&udev_device->sysattr_list, dent->d_name, NULL);
- num++;
- }
+ udev_list_entry_add (&udev_device->sysattr_list, dent->d_name, NULL);
+ num++;
+ }
- closedir(dir);
- udev_device->sysattr_list_read = true;
+ closedir (dir);
+ udev_device->sysattr_list_read = true;
- return num;
+ return num;
}
/**
@@ -1697,76 +1931,97 @@ static int udev_device_sysattr_list_read(struct udev_device *udev_device)
*
* Returns: the first entry of the property list
**/
-struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device)
-{
- if (!udev_device->sysattr_list_read) {
- int ret;
- ret = udev_device_sysattr_list_read(udev_device);
- if (0 > ret)
- return NULL;
- }
-
- return udev_list_get_entry(&udev_device->sysattr_list);
-}
-
-static int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode)
-{
- free(udev_device->devnode);
- if (devnode[0] != '/') {
- if (asprintf(&udev_device->devnode, "/dev/%s", devnode) < 0)
- udev_device->devnode = NULL;
- } else {
- udev_device->devnode = strdup(devnode);
- }
- if (udev_device->devnode == NULL)
- return -ENOMEM;
- udev_device_add_property_internal(udev_device, "DEVNAME", udev_device->devnode);
- return 0;
-}
-
-int udev_device_add_devlink(struct udev_device *udev_device, const char *devlink)
-{
- struct udev_list_entry *list_entry;
-
- udev_device->devlinks_uptodate = false;
- list_entry = udev_list_entry_add(&udev_device->devlinks_list, devlink, NULL);
- if (list_entry == NULL)
- return -ENOMEM;
- return 0;
-}
-
-const char *udev_device_get_id_filename(struct udev_device *udev_device)
-{
- if (udev_device->id_filename == NULL) {
- if (udev_device_get_subsystem(udev_device) == NULL)
- return NULL;
-
- if (major(udev_device_get_devnum(udev_device)) > 0) {
- /* use dev_t -- b259:131072, c254:0 */
- if (asprintf(&udev_device->id_filename, "%c%u:%u",
- streq(udev_device_get_subsystem(udev_device), "block") ? 'b' : 'c',
- major(udev_device_get_devnum(udev_device)),
- minor(udev_device_get_devnum(udev_device))) < 0)
- udev_device->id_filename = NULL;
- } else if (udev_device_get_ifindex(udev_device) > 0) {
- /* use netdev ifindex -- n3 */
- if (asprintf(&udev_device->id_filename, "n%i", udev_device_get_ifindex(udev_device)) < 0)
- udev_device->id_filename = NULL;
- } else {
- /*
- * use $subsys:$syname -- pci:0000:00:1f.2
- * sysname() has '!' translated, get it from devpath
- */
- const char *sysname;
- sysname = strrchr(udev_device->devpath, '/');
- if (sysname == NULL)
- return NULL;
- sysname = &sysname[1];
- if (asprintf(&udev_device->id_filename, "+%s:%s", udev_device_get_subsystem(udev_device), sysname) < 0)
- udev_device->id_filename = NULL;
- }
- }
- return udev_device->id_filename;
+struct udev_list_entry *
+udev_device_get_sysattr_list_entry (struct udev_device *udev_device)
+{
+ if (!udev_device->sysattr_list_read)
+ {
+ int ret;
+ ret = udev_device_sysattr_list_read (udev_device);
+ if (0 > ret)
+ return NULL;
+ }
+
+ return udev_list_get_entry (&udev_device->sysattr_list);
+}
+
+static int
+udev_device_set_devnode (struct udev_device *udev_device, const char *devnode)
+{
+ free (udev_device->devnode);
+ if (devnode[0] != '/')
+ {
+ if (asprintf (&udev_device->devnode, "/dev/%s", devnode) < 0)
+ udev_device->devnode = NULL;
+ }
+ else
+ {
+ udev_device->devnode = strdup (devnode);
+ }
+ if (udev_device->devnode == NULL)
+ return -ENOMEM;
+ udev_device_add_property_internal (udev_device, "DEVNAME",
+ udev_device->devnode);
+ return 0;
+}
+
+int
+udev_device_add_devlink (struct udev_device *udev_device, const char *devlink)
+{
+ struct udev_list_entry *list_entry;
+
+ udev_device->devlinks_uptodate = false;
+ list_entry =
+ udev_list_entry_add (&udev_device->devlinks_list, devlink, NULL);
+ if (list_entry == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+const char *
+udev_device_get_id_filename (struct udev_device *udev_device)
+{
+ if (udev_device->id_filename == NULL)
+ {
+ if (udev_device_get_subsystem (udev_device) == NULL)
+ return NULL;
+
+ if (major (udev_device_get_devnum (udev_device)) > 0)
+ {
+ /* use dev_t -- b259:131072, c254:0 */
+ if (asprintf (&udev_device->id_filename, "%c%u:%u",
+ streq (udev_device_get_subsystem
+ (udev_device), "block") ? 'b' : 'c',
+ major (udev_device_get_devnum (udev_device)),
+ minor (udev_device_get_devnum (udev_device))) < 0)
+ udev_device->id_filename = NULL;
+ }
+ else if (udev_device_get_ifindex (udev_device) > 0)
+ {
+ /* use netdev ifindex -- n3 */
+ if (asprintf
+ (&udev_device->id_filename, "n%i",
+ udev_device_get_ifindex (udev_device)) < 0)
+ udev_device->id_filename = NULL;
+ }
+ else
+ {
+ /*
+ * use $subsys:$syname -- pci:0000:00:1f.2
+ * sysname() has '!' translated, get it from devpath
+ */
+ const char *sysname;
+ sysname = strrchr (udev_device->devpath, '/');
+ if (sysname == NULL)
+ return NULL;
+ sysname = &sysname[1];
+ if (asprintf
+ (&udev_device->id_filename, "+%s:%s",
+ udev_device_get_subsystem (udev_device), sysname) < 0)
+ udev_device->id_filename = NULL;
+ }
+ }
+ return udev_device->id_filename;
}
/**
@@ -1782,51 +2037,58 @@ const char *udev_device_get_id_filename(struct udev_device *udev_device)
*
* Returns: 1 if the device is set up. 0 otherwise.
**/
-int udev_device_get_is_initialized(struct udev_device *udev_device)
+int
+udev_device_get_is_initialized (struct udev_device *udev_device)
{
- if (!udev_device->info_loaded)
- udev_device_read_db(udev_device);
- return udev_device->is_initialized;
+ if (!udev_device->info_loaded)
+ udev_device_read_db (udev_device);
+ return udev_device->is_initialized;
}
-void udev_device_set_is_initialized(struct udev_device *udev_device)
+void
+udev_device_set_is_initialized (struct udev_device *udev_device)
{
- udev_device->is_initialized = true;
+ udev_device->is_initialized = true;
}
-static bool is_valid_tag(const char *tag)
+static bool
+is_valid_tag (const char *tag)
{
- return !strchr(tag, ':') && !strchr(tag, ' ');
+ return !strchr (tag, ':') && !strchr (tag, ' ');
}
-int udev_device_add_tag(struct udev_device *udev_device, const char *tag)
+int
+udev_device_add_tag (struct udev_device *udev_device, const char *tag)
{
- if (!is_valid_tag(tag))
- return -EINVAL;
- udev_device->tags_uptodate = false;
- if (udev_list_entry_add(&udev_device->tags_list, tag, NULL) != NULL)
- return 0;
- return -ENOMEM;
+ if (!is_valid_tag (tag))
+ return -EINVAL;
+ udev_device->tags_uptodate = false;
+ if (udev_list_entry_add (&udev_device->tags_list, tag, NULL) != NULL)
+ return 0;
+ return -ENOMEM;
}
-void udev_device_remove_tag(struct udev_device *udev_device, const char *tag)
+void
+udev_device_remove_tag (struct udev_device *udev_device, const char *tag)
{
- struct udev_list_entry *e;
+ struct udev_list_entry *e;
- if (!is_valid_tag(tag))
- return;
- e = udev_list_get_entry(&udev_device->tags_list);
- e = udev_list_entry_get_by_name(e, tag);
- if (e) {
- udev_device->tags_uptodate = false;
- udev_list_entry_delete(e);
- }
+ if (!is_valid_tag (tag))
+ return;
+ e = udev_list_get_entry (&udev_device->tags_list);
+ e = udev_list_entry_get_by_name (e, tag);
+ if (e)
+ {
+ udev_device->tags_uptodate = false;
+ udev_list_entry_delete (e);
+ }
}
-void udev_device_cleanup_tags_list(struct udev_device *udev_device)
+void
+udev_device_cleanup_tags_list (struct udev_device *udev_device)
{
- udev_device->tags_uptodate = false;
- udev_list_cleanup(&udev_device->tags_list);
+ udev_device->tags_uptodate = false;
+ udev_list_cleanup (&udev_device->tags_list);
}
/**
@@ -1840,13 +2102,14 @@ void udev_device_cleanup_tags_list(struct udev_device *udev_device)
*
* Returns: the first entry of the tag list
**/
-struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device)
+struct udev_list_entry *
+udev_device_get_tags_list_entry (struct udev_device *udev_device)
{
- if (udev_device == NULL)
- return NULL;
- if (!udev_device->info_loaded)
- udev_device_read_db(udev_device);
- return udev_list_get_entry(&udev_device->tags_list);
+ if (udev_device == NULL)
+ return NULL;
+ if (!udev_device->info_loaded)
+ udev_device_read_db (udev_device);
+ return udev_list_get_entry (&udev_device->tags_list);
}
/**
@@ -1858,282 +2121,320 @@ struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev
*
* Returns: 1 if the tag is found. 0 otherwise.
**/
-int udev_device_has_tag(struct udev_device *udev_device, const char *tag)
+int
+udev_device_has_tag (struct udev_device *udev_device, const char *tag)
{
- struct udev_list_entry *list_entry;
+ struct udev_list_entry *list_entry;
- if (udev_device == NULL)
- return false;
- if (!udev_device->info_loaded)
- udev_device_read_db(udev_device);
- list_entry = udev_device_get_tags_list_entry(udev_device);
- if (udev_list_entry_get_by_name(list_entry, tag) != NULL)
- return true;
- return false;
+ if (udev_device == NULL)
+ return false;
+ if (!udev_device->info_loaded)
+ udev_device_read_db (udev_device);
+ list_entry = udev_device_get_tags_list_entry (udev_device);
+ if (udev_list_entry_get_by_name (list_entry, tag) != NULL)
+ return true;
+ return false;
}
#define ENVP_SIZE 128
#define MONITOR_BUF_SIZE 4096
-static int update_envp_monitor_buf(struct udev_device *udev_device)
+static int
+update_envp_monitor_buf (struct udev_device *udev_device)
{
- struct udev_list_entry *list_entry;
- char *s;
- size_t l;
- unsigned int i;
+ struct udev_list_entry *list_entry;
+ char *s;
+ size_t l;
+ unsigned int i;
- /* monitor buffer of property strings */
- free(udev_device->monitor_buf);
- udev_device->monitor_buf_len = 0;
- udev_device->monitor_buf = malloc(MONITOR_BUF_SIZE);
- if (udev_device->monitor_buf == NULL)
- return -ENOMEM;
+ /* monitor buffer of property strings */
+ free (udev_device->monitor_buf);
+ udev_device->monitor_buf_len = 0;
+ udev_device->monitor_buf = malloc (MONITOR_BUF_SIZE);
+ if (udev_device->monitor_buf == NULL)
+ return -ENOMEM;
- /* envp array, strings will point into monitor buffer */
- if (udev_device->envp == NULL)
- udev_device->envp = malloc(sizeof(char *) * ENVP_SIZE);
- if (udev_device->envp == NULL)
- return -ENOMEM;
+ /* envp array, strings will point into monitor buffer */
+ if (udev_device->envp == NULL)
+ udev_device->envp = malloc (sizeof (char *) * ENVP_SIZE);
+ if (udev_device->envp == NULL)
+ return -ENOMEM;
- i = 0;
- s = udev_device->monitor_buf;
- l = MONITOR_BUF_SIZE;
- udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(udev_device)) {
- const char *key;
+ i = 0;
+ s = udev_device->monitor_buf;
+ l = MONITOR_BUF_SIZE;
+ udev_list_entry_foreach (list_entry,
+ udev_device_get_properties_list_entry
+ (udev_device))
+ {
+ const char *key;
- key = udev_list_entry_get_name(list_entry);
- /* skip private variables */
- if (key[0] == '.')
- continue;
+ key = udev_list_entry_get_name (list_entry);
+ /* skip private variables */
+ if (key[0] == '.')
+ continue;
- /* add string to envp array */
- udev_device->envp[i++] = s;
- if (i+1 >= ENVP_SIZE)
- return -EINVAL;
+ /* add string to envp array */
+ udev_device->envp[i++] = s;
+ if (i + 1 >= ENVP_SIZE)
+ return -EINVAL;
- /* add property string to monitor buffer */
- l = strpcpyl(&s, l, key, "=", udev_list_entry_get_value(list_entry), NULL);
- if (l == 0)
- return -EINVAL;
- /* advance past the trailing '\0' that strpcpyl() guarantees */
- s++;
- l--;
- }
- udev_device->envp[i] = NULL;
- udev_device->monitor_buf_len = s - udev_device->monitor_buf;
- udev_device->envp_uptodate = true;
- return 0;
+ /* add property string to monitor buffer */
+ l = strpcpyl (&s, l, key, "=",
+ udev_list_entry_get_value (list_entry), NULL);
+ if (l == 0)
+ return -EINVAL;
+ /* advance past the trailing '\0' that strpcpyl() guarantees */
+ s++;
+ l--;
+ }
+ udev_device->envp[i] = NULL;
+ udev_device->monitor_buf_len = s - udev_device->monitor_buf;
+ udev_device->envp_uptodate = true;
+ return 0;
}
-char **udev_device_get_properties_envp(struct udev_device *udev_device)
+char **
+udev_device_get_properties_envp (struct udev_device *udev_device)
{
- if (!udev_device->envp_uptodate)
- if (update_envp_monitor_buf(udev_device) != 0)
- return NULL;
- return udev_device->envp;
+ if (!udev_device->envp_uptodate)
+ if (update_envp_monitor_buf (udev_device) != 0)
+ return NULL;
+ return udev_device->envp;
}
-ssize_t udev_device_get_properties_monitor_buf(struct udev_device *udev_device, const char **buf)
+ssize_t
+udev_device_get_properties_monitor_buf (struct udev_device * udev_device,
+ const char **buf)
{
- if (!udev_device->envp_uptodate)
- if (update_envp_monitor_buf(udev_device) != 0)
- return -EINVAL;
- *buf = udev_device->monitor_buf;
- return udev_device->monitor_buf_len;
+ if (!udev_device->envp_uptodate)
+ if (update_envp_monitor_buf (udev_device) != 0)
+ return -EINVAL;
+ *buf = udev_device->monitor_buf;
+ return udev_device->monitor_buf_len;
}
-int udev_device_get_devlink_priority(struct udev_device *udev_device)
+int
+udev_device_get_devlink_priority (struct udev_device *udev_device)
{
- if (!udev_device->info_loaded)
- udev_device_read_db(udev_device);
- return udev_device->devlink_priority;
+ if (!udev_device->info_loaded)
+ udev_device_read_db (udev_device);
+ return udev_device->devlink_priority;
}
-int udev_device_set_devlink_priority(struct udev_device *udev_device, int prio)
+int
+udev_device_set_devlink_priority (struct udev_device *udev_device, int prio)
{
- udev_device->devlink_priority = prio;
- return 0;
+ udev_device->devlink_priority = prio;
+ return 0;
}
-int udev_device_get_watch_handle(struct udev_device *udev_device)
+int
+udev_device_get_watch_handle (struct udev_device *udev_device)
{
- if (!udev_device->info_loaded)
- udev_device_read_db(udev_device);
- return udev_device->watch_handle;
+ if (!udev_device->info_loaded)
+ udev_device_read_db (udev_device);
+ return udev_device->watch_handle;
}
-int udev_device_set_watch_handle(struct udev_device *udev_device, int handle)
+int
+udev_device_set_watch_handle (struct udev_device *udev_device, int handle)
{
- udev_device->watch_handle = handle;
- return 0;
+ udev_device->watch_handle = handle;
+ return 0;
}
-bool udev_device_get_db_persist(struct udev_device *udev_device)
+bool
+udev_device_get_db_persist (struct udev_device * udev_device)
{
- return udev_device->db_persist;
+ return udev_device->db_persist;
}
-void udev_device_set_db_persist(struct udev_device *udev_device)
+void
+udev_device_set_db_persist (struct udev_device *udev_device)
{
- udev_device->db_persist = true;
+ udev_device->db_persist = true;
}
-int udev_device_rename(struct udev_device *udev_device, const char *name)
+int
+udev_device_rename (struct udev_device *udev_device, const char *name)
{
- char *dirname = NULL;
- const char *interface;
- char *new_syspath;
- int r;
+ char *dirname = NULL;
+ const char *interface;
+ char *new_syspath;
+ int r;
- if (udev_device == NULL || name == NULL)
- return -EINVAL;
+ if (udev_device == NULL || name == NULL)
+ return -EINVAL;
- dirname = dirname_malloc(udev_device->syspath);
- if (!dirname)
- return -ENOMEM;
+ dirname = dirname_malloc (udev_device->syspath);
+ if (!dirname)
+ return -ENOMEM;
- new_syspath = strjoina(dirname, "/", name);
+ new_syspath = strjoina (dirname, "/", name);
- r = udev_device_set_syspath(udev_device, new_syspath);
- if (r < 0) {
- libudev_safe_free( dirname );
- return r;
- }
+ r = udev_device_set_syspath (udev_device, new_syspath);
+ if (r < 0)
+ {
+ libudev_safe_free (dirname);
+ return r;
+ }
- interface = udev_device_get_property_value(udev_device, "INTERFACE");
- if (interface) {
- /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
- udev_device_add_property_internal(udev_device, "INTERFACE_OLD", interface);
- udev_device_add_property_internal(udev_device, "INTERFACE", name);
- }
+ interface = udev_device_get_property_value (udev_device, "INTERFACE");
+ if (interface)
+ {
+ /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
+ udev_device_add_property_internal (udev_device, "INTERFACE_OLD",
+ interface);
+ udev_device_add_property_internal (udev_device, "INTERFACE", name);
+ }
- libudev_safe_free( dirname );
- return 0;
+ libudev_safe_free (dirname);
+ return 0;
}
-struct udev_device *udev_device_shallow_clone(struct udev_device *old_device)
+struct udev_device *
+udev_device_shallow_clone (struct udev_device *old_device)
{
- struct udev_device *device;
+ struct udev_device *device;
- if (old_device == NULL)
- return NULL;
+ if (old_device == NULL)
+ return NULL;
- device = udev_device_new(old_device->udev);
- if (!device) {
- errno = ENOMEM;
+ device = udev_device_new (old_device->udev);
+ if (!device)
+ {
+ errno = ENOMEM;
- return NULL;
- }
+ return NULL;
+ }
- udev_device_set_syspath(device, udev_device_get_syspath(old_device));
- udev_device_set_subsystem(device, udev_device_get_subsystem(old_device));
- udev_device_set_devnum(device, udev_device_get_devnum(old_device));
+ udev_device_set_syspath (device, udev_device_get_syspath (old_device));
+ udev_device_set_subsystem (device, udev_device_get_subsystem (old_device));
+ udev_device_set_devnum (device, udev_device_get_devnum (old_device));
- return device;
+ return device;
}
-struct udev_device *udev_device_clone_with_db(struct udev_device *old_device)
+struct udev_device *
+udev_device_clone_with_db (struct udev_device *old_device)
{
- struct udev_device *device;
+ struct udev_device *device;
- device = udev_device_shallow_clone(old_device);
- if (!device)
- return NULL;
+ device = udev_device_shallow_clone (old_device);
+ if (!device)
+ return NULL;
- udev_device_read_db(device);
- udev_device_set_info_loaded(device);
+ udev_device_read_db (device);
+ udev_device_set_info_loaded (device);
- return device;
+ return device;
}
// NOTE: expects "key=value" pairs separated by exactly one '\0'
-struct udev_device *udev_device_new_from_nulstr(struct udev *udev, char *nulstr, ssize_t buflen) {
-
- struct udev_device *device = NULL;
- ssize_t bufpos = 0;
+struct udev_device *
+udev_device_new_from_nulstr (struct udev *udev, char *nulstr, ssize_t buflen)
+{
- if (nulstr == NULL || buflen <= 0) {
-
- errno = EINVAL;
-
- return NULL;
- }
+ struct udev_device *device = NULL;
+ ssize_t bufpos = 0;
- device = udev_device_new(udev);
- if (!device) {
-
- errno = ENOMEM;
- return NULL;
- }
+ if (nulstr == NULL || buflen <= 0)
+ {
- udev_device_set_info_loaded(device);
+ errno = EINVAL;
- while (bufpos < buflen) {
- char *key;
- size_t keylen;
+ return NULL;
+ }
- key = nulstr + bufpos;
- keylen = strlen(key);
- if (keylen == 0)
- break;
+ device = udev_device_new (udev);
+ if (!device)
+ {
- bufpos += keylen + 1;
- udev_device_add_property_from_string_parse(device, key);
- }
+ errno = ENOMEM;
+ return NULL;
+ }
- if (udev_device_add_property_from_string_parse_finish(device) < 0) {
- log_debug("%s", "missing values, invalid device");
-
- udev_device_unref(device);
+ udev_device_set_info_loaded (device);
- errno = EINVAL;
+ while (bufpos < buflen)
+ {
+ char *key;
+ size_t keylen;
- return NULL;
- }
+ key = nulstr + bufpos;
+ keylen = strlen (key);
+ if (keylen == 0)
+ break;
- return device;
+ bufpos += keylen + 1;
+ udev_device_add_property_from_string_parse (device, key);
+ }
+
+ if (udev_device_add_property_from_string_parse_finish (device) < 0)
+ {
+ log_debug ("%s", "missing values, invalid device");
+
+ udev_device_unref (device);
+
+ errno = EINVAL;
+
+ return NULL;
+ }
+
+ return device;
}
-struct udev_device *udev_device_new_from_synthetic_event(struct udev *udev, const char *syspath, const char *action) {
- struct udev_device *ret;
- int r;
+struct udev_device *
+udev_device_new_from_synthetic_event (struct udev *udev,
+ const char *syspath, const char *action)
+{
+ struct udev_device *ret;
+ int r;
- if (!action) {
- errno = EINVAL;
- return NULL;
- }
+ if (!action)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
- ret = udev_device_new_from_syspath(udev, syspath);
- if (!ret)
- return NULL;
+ ret = udev_device_new_from_syspath (udev, syspath);
+ if (!ret)
+ return NULL;
- r = udev_device_read_uevent_file(ret);
- if (r < 0) {
- udev_device_unref(ret);
- errno = -r;
- return NULL;
- }
+ r = udev_device_read_uevent_file (ret);
+ if (r < 0)
+ {
+ udev_device_unref (ret);
+ errno = -r;
+ return NULL;
+ }
- r = udev_device_set_action(ret, action);
- if (r < 0) {
- udev_device_unref(ret);
- errno = -r;
- return NULL;
- }
+ r = udev_device_set_action (ret, action);
+ if (r < 0)
+ {
+ udev_device_unref (ret);
+ errno = -r;
+ return NULL;
+ }
- return ret;
+ return ret;
}
-int udev_device_copy_properties(struct udev_device *dst, struct udev_device *src) {
- struct udev_list_entry *entry;
+int
+udev_device_copy_properties (struct udev_device *dst, struct udev_device *src)
+{
+ struct udev_list_entry *entry;
- for ((entry = udev_device_get_properties_list_entry(src)); entry; entry = udev_list_entry_get_next(entry)) {
- const char *key, *value;
+ for ((entry = udev_device_get_properties_list_entry (src)); entry;
+ entry = udev_list_entry_get_next (entry))
+ {
+ const char *key, *value;
- key = udev_list_entry_get_name(entry);
- value = udev_list_entry_get_value(entry);
+ key = udev_list_entry_get_name (entry);
+ value = udev_list_entry_get_value (entry);
- udev_device_add_property(dst, key, value);
- }
+ udev_device_add_property (dst, key, value);
+ }
- return 0;
+ return 0;
}
diff --git a/libudev-compat/libudev-enumerate.c b/libudev-compat/libudev-enumerate.c
index 7046020..79ccc38 100644
--- a/libudev-compat/libudev-enumerate.c
+++ b/libudev-compat/libudev-enumerate.c
@@ -47,9 +47,10 @@
* and return a sorted list of devices.
*/
-struct syspath {
- char *syspath;
- size_t len;
+struct syspath
+{
+ char *syspath;
+ size_t len;
};
/**
@@ -57,23 +58,24 @@ struct syspath {
*
* Opaque object representing one device lookup/sort context.
*/
-struct udev_enumerate {
- struct udev *udev;
- int refcount;
- struct udev_list sysattr_match_list;
- struct udev_list sysattr_nomatch_list;
- struct udev_list subsystem_match_list;
- struct udev_list subsystem_nomatch_list;
- struct udev_list sysname_match_list;
- struct udev_list properties_match_list;
- struct udev_list tags_match_list;
- struct udev_device *parent_match;
- struct udev_list devices_list;
- struct syspath *devices;
- unsigned int devices_cur;
- unsigned int devices_max;
- bool devices_uptodate:1;
- bool match_is_initialized;
+struct udev_enumerate
+{
+ struct udev *udev;
+ int refcount;
+ struct udev_list sysattr_match_list;
+ struct udev_list sysattr_nomatch_list;
+ struct udev_list subsystem_match_list;
+ struct udev_list subsystem_nomatch_list;
+ struct udev_list sysname_match_list;
+ struct udev_list properties_match_list;
+ struct udev_list tags_match_list;
+ struct udev_device *parent_match;
+ struct udev_list devices_list;
+ struct syspath *devices;
+ unsigned int devices_cur;
+ unsigned int devices_max;
+ bool devices_uptodate:1;
+ bool match_is_initialized;
};
/**
@@ -84,26 +86,27 @@ struct udev_enumerate {
*
* Returns: an enumeration context.
**/
-struct udev_enumerate *udev_enumerate_new(struct udev *udev)
-{
- struct udev_enumerate *udev_enumerate;
-
- if (udev == NULL)
- return NULL;
- udev_enumerate = new0(struct udev_enumerate, 1);
- if (udev_enumerate == NULL)
- return NULL;
- udev_enumerate->refcount = 1;
- udev_enumerate->udev = udev;
- udev_list_init(udev, &udev_enumerate->sysattr_match_list, false);
- udev_list_init(udev, &udev_enumerate->sysattr_nomatch_list, false);
- udev_list_init(udev, &udev_enumerate->subsystem_match_list, true);
- udev_list_init(udev, &udev_enumerate->subsystem_nomatch_list, true);
- udev_list_init(udev, &udev_enumerate->sysname_match_list, true);
- udev_list_init(udev, &udev_enumerate->properties_match_list, false);
- udev_list_init(udev, &udev_enumerate->tags_match_list, true);
- udev_list_init(udev, &udev_enumerate->devices_list, false);
- return udev_enumerate;
+struct udev_enumerate *
+udev_enumerate_new (struct udev *udev)
+{
+ struct udev_enumerate *udev_enumerate;
+
+ if (udev == NULL)
+ return NULL;
+ udev_enumerate = new0 (struct udev_enumerate, 1);
+ if (udev_enumerate == NULL)
+ return NULL;
+ udev_enumerate->refcount = 1;
+ udev_enumerate->udev = udev;
+ udev_list_init (udev, &udev_enumerate->sysattr_match_list, false);
+ udev_list_init (udev, &udev_enumerate->sysattr_nomatch_list, false);
+ udev_list_init (udev, &udev_enumerate->subsystem_match_list, true);
+ udev_list_init (udev, &udev_enumerate->subsystem_nomatch_list, true);
+ udev_list_init (udev, &udev_enumerate->sysname_match_list, true);
+ udev_list_init (udev, &udev_enumerate->properties_match_list, false);
+ udev_list_init (udev, &udev_enumerate->tags_match_list, true);
+ udev_list_init (udev, &udev_enumerate->devices_list, false);
+ return udev_enumerate;
}
/**
@@ -114,12 +117,13 @@ struct udev_enumerate *udev_enumerate_new(struct udev *udev)
*
* Returns: the passed enumeration context
**/
-struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate)
+struct udev_enumerate *
+udev_enumerate_ref (struct udev_enumerate *udev_enumerate)
{
- if (udev_enumerate == NULL)
- return NULL;
- udev_enumerate->refcount++;
- return udev_enumerate;
+ if (udev_enumerate == NULL)
+ return NULL;
+ udev_enumerate->refcount++;
+ return udev_enumerate;
}
/**
@@ -131,29 +135,30 @@ struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate)
*
* Returns: #NULL
**/
-struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate)
-{
- unsigned int i;
-
- if (udev_enumerate == NULL)
- return NULL;
- udev_enumerate->refcount--;
- if (udev_enumerate->refcount > 0)
- return NULL;
- udev_list_cleanup(&udev_enumerate->sysattr_match_list);
- udev_list_cleanup(&udev_enumerate->sysattr_nomatch_list);
- udev_list_cleanup(&udev_enumerate->subsystem_match_list);
- udev_list_cleanup(&udev_enumerate->subsystem_nomatch_list);
- udev_list_cleanup(&udev_enumerate->sysname_match_list);
- udev_list_cleanup(&udev_enumerate->properties_match_list);
- udev_list_cleanup(&udev_enumerate->tags_match_list);
- udev_device_unref(udev_enumerate->parent_match);
- udev_list_cleanup(&udev_enumerate->devices_list);
- for (i = 0; i < udev_enumerate->devices_cur; i++)
- free(udev_enumerate->devices[i].syspath);
- free(udev_enumerate->devices);
- free(udev_enumerate);
- return NULL;
+struct udev_enumerate *
+udev_enumerate_unref (struct udev_enumerate *udev_enumerate)
+{
+ unsigned int i;
+
+ if (udev_enumerate == NULL)
+ return NULL;
+ udev_enumerate->refcount--;
+ if (udev_enumerate->refcount > 0)
+ return NULL;
+ udev_list_cleanup (&udev_enumerate->sysattr_match_list);
+ udev_list_cleanup (&udev_enumerate->sysattr_nomatch_list);
+ udev_list_cleanup (&udev_enumerate->subsystem_match_list);
+ udev_list_cleanup (&udev_enumerate->subsystem_nomatch_list);
+ udev_list_cleanup (&udev_enumerate->sysname_match_list);
+ udev_list_cleanup (&udev_enumerate->properties_match_list);
+ udev_list_cleanup (&udev_enumerate->tags_match_list);
+ udev_device_unref (udev_enumerate->parent_match);
+ udev_list_cleanup (&udev_enumerate->devices_list);
+ for (i = 0; i < udev_enumerate->devices_cur; i++)
+ free (udev_enumerate->devices[i].syspath);
+ free (udev_enumerate->devices);
+ free (udev_enumerate);
+ return NULL;
}
/**
@@ -164,103 +169,115 @@ struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerat
*
* Returns: a pointer to the context.
*/
-struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate)
-{
- if (udev_enumerate == NULL)
- return NULL;
- return udev_enumerate->udev;
-}
-
-static int syspath_add(struct udev_enumerate *udev_enumerate, const char *syspath)
-{
- char *path;
- struct syspath *entry;
-
- /* double array size if needed */
- if (udev_enumerate->devices_cur >= udev_enumerate->devices_max) {
- struct syspath *buf;
- unsigned int add;
-
- add = udev_enumerate->devices_max;
- if (add < 1024)
- add = 1024;
- buf = realloc(udev_enumerate->devices, (udev_enumerate->devices_max + add) * sizeof(struct syspath));
- if (buf == NULL)
- return -ENOMEM;
- udev_enumerate->devices = buf;
- udev_enumerate->devices_max += add;
- }
-
- path = strdup(syspath);
- if (path == NULL)
- return -ENOMEM;
- entry = &udev_enumerate->devices[udev_enumerate->devices_cur];
- entry->syspath = path;
- entry->len = strlen(path);
- udev_enumerate->devices_cur++;
- udev_enumerate->devices_uptodate = false;
- return 0;
-}
-
-static int syspath_cmp(const void *p1, const void *p2)
-{
- const struct syspath *path1 = p1;
- const struct syspath *path2 = p2;
- size_t len;
- int ret;
-
- len = MIN(path1->len, path2->len);
- ret = memcmp(path1->syspath, path2->syspath, len);
- if (ret == 0) {
- if (path1->len < path2->len)
- ret = -1;
- else if (path1->len > path2->len)
- ret = 1;
- }
- return ret;
+struct udev *
+udev_enumerate_get_udev (struct udev_enumerate *udev_enumerate)
+{
+ if (udev_enumerate == NULL)
+ return NULL;
+ return udev_enumerate->udev;
}
-/* For devices that should be moved to the absolute end of the list */
-static bool devices_delay_end(struct udev *udev, const char *syspath)
+static int
+syspath_add (struct udev_enumerate *udev_enumerate, const char *syspath)
{
- static const char *delay_device_list[] = {
- "/block/md",
- "/block/dm-",
- NULL
- };
- int i;
+ char *path;
+ struct syspath *entry;
+
+ /* double array size if needed */
+ if (udev_enumerate->devices_cur >= udev_enumerate->devices_max)
+ {
+ struct syspath *buf;
+ unsigned int add;
+
+ add = udev_enumerate->devices_max;
+ if (add < 1024)
+ add = 1024;
+ buf =
+ realloc (udev_enumerate->devices,
+ (udev_enumerate->devices_max +
+ add) * sizeof (struct syspath));
+ if (buf == NULL)
+ return -ENOMEM;
+ udev_enumerate->devices = buf;
+ udev_enumerate->devices_max += add;
+ }
+
+ path = strdup (syspath);
+ if (path == NULL)
+ return -ENOMEM;
+ entry = &udev_enumerate->devices[udev_enumerate->devices_cur];
+ entry->syspath = path;
+ entry->len = strlen (path);
+ udev_enumerate->devices_cur++;
+ udev_enumerate->devices_uptodate = false;
+ return 0;
+}
- for (i = 0; delay_device_list[i] != NULL; i++) {
- if (strstr(syspath + strlen("/sys"), delay_device_list[i]) != NULL)
- return true;
- }
- return false;
+static int
+syspath_cmp (const void *p1, const void *p2)
+{
+ const struct syspath *path1 = p1;
+ const struct syspath *path2 = p2;
+ size_t len;
+ int ret;
+
+ len = MIN (path1->len, path2->len);
+ ret = memcmp (path1->syspath, path2->syspath, len);
+ if (ret == 0)
+ {
+ if (path1->len < path2->len)
+ ret = -1;
+ else if (path1->len > path2->len)
+ ret = 1;
+ }
+ return ret;
+}
+
+/* For devices that should be moved to the absolute end of the list */
+static bool
+devices_delay_end (struct udev *udev, const char *syspath)
+{
+ static const char *delay_device_list[] = {
+ "/block/md",
+ "/block/dm-",
+ NULL
+ };
+ int i;
+
+ for (i = 0; delay_device_list[i] != NULL; i++)
+ {
+ if (strstr (syspath + strlen ("/sys"), delay_device_list[i]) != NULL)
+ return true;
+ }
+ return false;
}
/* For devices that should just be moved a little bit later, just
* before the point where some common path prefix changes. Returns the
* number of characters that make up that common prefix */
-static size_t devices_delay_later(struct udev *udev, const char *syspath)
+static size_t
+devices_delay_later (struct udev *udev, const char *syspath)
{
- const char *c;
-
- /* For sound cards the control device must be enumerated last
- * to make sure it's the final device node that gets ACLs
- * applied. Applications rely on this fact and use ACL changes
- * on the control node as an indicator that the ACL change of
- * the entire sound card completed. The kernel makes this
- * guarantee when creating those devices, and hence we should
- * too when enumerating them. */
-
- if ((c = strstr(syspath, "/sound/card"))) {
- c += 11;
- c += strcspn(c, "/");
-
- if (startswith(c, "/controlC"))
- return c - syspath + 1;
- }
-
- return 0;
+ const char *c;
+
+ /* For sound cards the control device must be enumerated last
+ * to make sure it's the final device node that gets ACLs
+ * applied. Applications rely on this fact and use ACL changes
+ * on the control node as an indicator that the ACL change of
+ * the entire sound card completed. The kernel makes this
+ * guarantee when creating those devices, and hence we should
+ * too when enumerating them. */
+
+ if ((c = strstr (syspath, "/sound/card")))
+ {
+ c += 11;
+ c += strcspn (c, "/");
+
+ if (startswith (c, "/controlC"))
+ return c - syspath + 1;
+ }
+
+ return 0;
}
/**
@@ -271,78 +288,94 @@ static size_t devices_delay_later(struct udev *udev, const char *syspath)
*
* Returns: a udev_list_entry.
*/
-struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate)
-{
- if (udev_enumerate == NULL)
- return NULL;
- if (!udev_enumerate->devices_uptodate) {
- unsigned int i;
- int move_later = -1;
- unsigned int max;
- struct syspath *prev = NULL;
- size_t move_later_prefix = 0;
-
- udev_list_cleanup(&udev_enumerate->devices_list);
- qsort_safe(udev_enumerate->devices, udev_enumerate->devices_cur, sizeof(struct syspath), syspath_cmp);
-
- max = udev_enumerate->devices_cur;
- for (i = 0; i < max; i++) {
- struct syspath *entry = &udev_enumerate->devices[i];
-
- /* skip duplicated entries */
- if (prev != NULL &&
- entry->len == prev->len &&
- memcmp(entry->syspath, prev->syspath, entry->len) == 0)
- continue;
- prev = entry;
-
- /* skip to be delayed devices, and add them to the end of the list */
- if (devices_delay_end(udev_enumerate->udev, entry->syspath)) {
- syspath_add(udev_enumerate, entry->syspath);
- /* need to update prev here for the case realloc() gives a different address */
- prev = &udev_enumerate->devices[i];
- continue;
- }
-
- /* skip to be delayed devices, and move the to
- * the point where the prefix changes. We can
- * only move one item at a time. */
- if (move_later == -1) {
- move_later_prefix = devices_delay_later(udev_enumerate->udev, entry->syspath);
-
- if (move_later_prefix > 0) {
- move_later = i;
- continue;
- }
- }
-
- if ((move_later >= 0) &&
- !strneq(entry->syspath, udev_enumerate->devices[move_later].syspath, move_later_prefix)) {
-
- udev_list_entry_add(&udev_enumerate->devices_list,
- udev_enumerate->devices[move_later].syspath, NULL);
- move_later = -1;
- }
-
- udev_list_entry_add(&udev_enumerate->devices_list, entry->syspath, NULL);
- }
-
- if (move_later >= 0)
- udev_list_entry_add(&udev_enumerate->devices_list,
- udev_enumerate->devices[move_later].syspath, NULL);
-
- /* add and cleanup delayed devices from end of list */
- for (i = max; i < udev_enumerate->devices_cur; i++) {
- struct syspath *entry = &udev_enumerate->devices[i];
-
- udev_list_entry_add(&udev_enumerate->devices_list, entry->syspath, NULL);
- free(entry->syspath);
- }
- udev_enumerate->devices_cur = max;
-
- udev_enumerate->devices_uptodate = true;
- }
- return udev_list_get_entry(&udev_enumerate->devices_list);
+struct udev_list_entry *
+udev_enumerate_get_list_entry (struct udev_enumerate *udev_enumerate)
+{
+ if (udev_enumerate == NULL)
+ return NULL;
+ if (!udev_enumerate->devices_uptodate)
+ {
+ unsigned int i;
+ int move_later = -1;
+ unsigned int max;
+ struct syspath *prev = NULL;
+ size_t move_later_prefix = 0;
+
+ udev_list_cleanup (&udev_enumerate->devices_list);
+ qsort_safe (udev_enumerate->devices, udev_enumerate->devices_cur,
+ sizeof (struct syspath), syspath_cmp);
+
+ max = udev_enumerate->devices_cur;
+ for (i = 0; i < max; i++)
+ {
+ struct syspath *entry = &udev_enumerate->devices[i];
+
+ /* skip duplicated entries */
+ if (prev != NULL &&
+ entry->len == prev->len &&
+ memcmp (entry->syspath, prev->syspath, entry->len) == 0)
+ continue;
+ prev = entry;
+
+ /* skip to be delayed devices, and add them to the end of the list */
+ if (devices_delay_end (udev_enumerate->udev, entry->syspath))
+ {
+ syspath_add (udev_enumerate, entry->syspath);
+ /* need to update prev here for the case realloc() gives a different address */
+ prev = &udev_enumerate->devices[i];
+ continue;
+ }
+
+ /* skip to be delayed devices, and move the to
+ * the point where the prefix changes. We can
+ * only move one item at a time. */
+ if (move_later == -1)
+ {
+ move_later_prefix =
+ devices_delay_later (udev_enumerate->udev, entry->syspath);
+
+ if (move_later_prefix > 0)
+ {
+ move_later = i;
+ continue;
+ }
+ }
+
+ if ((move_later >= 0) &&
+ !strneq (entry->syspath,
+ udev_enumerate->devices[move_later].syspath,
+ move_later_prefix))
+ {
+
+ udev_list_entry_add (&udev_enumerate->devices_list,
+ udev_enumerate->devices[move_later].
+ syspath, NULL);
+ move_later = -1;
+ }
+
+ udev_list_entry_add (&udev_enumerate->devices_list,
+ entry->syspath, NULL);
+ }
+
+ if (move_later >= 0)
+ udev_list_entry_add (&udev_enumerate->devices_list,
+ udev_enumerate->devices[move_later].syspath,
+ NULL);
+
+ /* add and cleanup delayed devices from end of list */
+ for (i = max; i < udev_enumerate->devices_cur; i++)
+ {
+ struct syspath *entry = &udev_enumerate->devices[i];
+
+ udev_list_entry_add (&udev_enumerate->devices_list,
+ entry->syspath, NULL);
+ free (entry->syspath);
+ }
+ udev_enumerate->devices_cur = max;
+
+ udev_enumerate->devices_uptodate = true;
+ }
+ return udev_list_get_entry (&udev_enumerate->devices_list);
}
/**
@@ -354,15 +387,18 @@ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *ude
*
* Returns: 0 on success, otherwise a negative error value.
*/
-int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem)
+int
+udev_enumerate_add_match_subsystem (struct udev_enumerate *udev_enumerate,
+ const char *subsystem)
{
- if (udev_enumerate == NULL)
- return -EINVAL;
- if (subsystem == NULL)
- return 0;
- if (udev_list_entry_add(&udev_enumerate->subsystem_match_list, subsystem, NULL) == NULL)
- return -ENOMEM;
- return 0;
+ if (udev_enumerate == NULL)
+ return -EINVAL;
+ if (subsystem == NULL)
+ return 0;
+ if (udev_list_entry_add
+ (&udev_enumerate->subsystem_match_list, subsystem, NULL) == NULL)
+ return -ENOMEM;
+ return 0;
}
/**
@@ -374,15 +410,18 @@ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, co
*
* Returns: 0 on success, otherwise a negative error value.
*/
-int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem)
+int
+udev_enumerate_add_nomatch_subsystem (struct udev_enumerate *udev_enumerate,
+ const char *subsystem)
{
- if (udev_enumerate == NULL)
- return -EINVAL;
- if (subsystem == NULL)
- return 0;
- if (udev_list_entry_add(&udev_enumerate->subsystem_nomatch_list, subsystem, NULL) == NULL)
- return -ENOMEM;
- return 0;
+ if (udev_enumerate == NULL)
+ return -EINVAL;
+ if (subsystem == NULL)
+ return 0;
+ if (udev_list_entry_add
+ (&udev_enumerate->subsystem_nomatch_list, subsystem, NULL) == NULL)
+ return -ENOMEM;
+ return 0;
}
/**
@@ -395,15 +434,18 @@ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate,
*
* Returns: 0 on success, otherwise a negative error value.
*/
-int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value)
+int
+udev_enumerate_add_match_sysattr (struct udev_enumerate *udev_enumerate,
+ const char *sysattr, const char *value)
{
- if (udev_enumerate == NULL)
- return -EINVAL;
- if (sysattr == NULL)
- return 0;
- if (udev_list_entry_add(&udev_enumerate->sysattr_match_list, sysattr, value) == NULL)
- return -ENOMEM;
- return 0;
+ if (udev_enumerate == NULL)
+ return -EINVAL;
+ if (sysattr == NULL)
+ return 0;
+ if (udev_list_entry_add
+ (&udev_enumerate->sysattr_match_list, sysattr, value) == NULL)
+ return -ENOMEM;
+ return 0;
}
/**
@@ -416,35 +458,42 @@ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, cons
*
* Returns: 0 on success, otherwise a negative error value.
*/
-int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value)
-{
- if (udev_enumerate == NULL)
- return -EINVAL;
- if (sysattr == NULL)
- return 0;
- if (udev_list_entry_add(&udev_enumerate->sysattr_nomatch_list, sysattr, value) == NULL)
- return -ENOMEM;
- return 0;
-}
-
-static int match_sysattr_value(struct udev_device *dev, const char *sysattr, const char *match_val)
-{
- const char *val = NULL;
- bool match = false;
-
- val = udev_device_get_sysattr_value(dev, sysattr);
- if (val == NULL)
- goto exit;
- if (match_val == NULL) {
- match = true;
- goto exit;
- }
- if (fnmatch(match_val, val, 0) == 0) {
- match = true;
- goto exit;
- }
+int
+udev_enumerate_add_nomatch_sysattr (struct udev_enumerate *udev_enumerate,
+ const char *sysattr, const char *value)
+{
+ if (udev_enumerate == NULL)
+ return -EINVAL;
+ if (sysattr == NULL)
+ return 0;
+ if (udev_list_entry_add
+ (&udev_enumerate->sysattr_nomatch_list, sysattr, value) == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+static int
+match_sysattr_value (struct udev_device *dev, const char *sysattr,
+ const char *match_val)
+{
+ const char *val = NULL;
+ bool match = false;
+
+ val = udev_device_get_sysattr_value (dev, sysattr);
+ if (val == NULL)
+ goto exit;
+ if (match_val == NULL)
+ {
+ match = true;
+ goto exit;
+ }
+ if (fnmatch (match_val, val, 0) == 0)
+ {
+ match = true;
+ goto exit;
+ }
exit:
- return match;
+ return match;
}
/**
@@ -457,15 +506,18 @@ static int match_sysattr_value(struct udev_device *dev, const char *sysattr, con
*
* Returns: 0 on success, otherwise a negative error value.
*/
-int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value)
+int
+udev_enumerate_add_match_property (struct udev_enumerate *udev_enumerate,
+ const char *property, const char *value)
{
- if (udev_enumerate == NULL)
- return -EINVAL;
- if (property == NULL)
- return 0;
- if (udev_list_entry_add(&udev_enumerate->properties_match_list, property, value) == NULL)
- return -ENOMEM;
- return 0;
+ if (udev_enumerate == NULL)
+ return -EINVAL;
+ if (property == NULL)
+ return 0;
+ if (udev_list_entry_add
+ (&udev_enumerate->properties_match_list, property, value) == NULL)
+ return -ENOMEM;
+ return 0;
}
/**
@@ -477,15 +529,18 @@ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, con
*
* Returns: 0 on success, otherwise a negative error value.
*/
-int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag)
+int
+udev_enumerate_add_match_tag (struct udev_enumerate *udev_enumerate,
+ const char *tag)
{
- if (udev_enumerate == NULL)
- return -EINVAL;
- if (tag == NULL)
- return 0;
- if (udev_list_entry_add(&udev_enumerate->tags_match_list, tag, NULL) == NULL)
- return -ENOMEM;
- return 0;
+ if (udev_enumerate == NULL)
+ return -EINVAL;
+ if (tag == NULL)
+ return 0;
+ if (udev_list_entry_add (&udev_enumerate->tags_match_list, tag, NULL) ==
+ NULL)
+ return -ENOMEM;
+ return 0;
}
/**
@@ -501,16 +556,18 @@ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const ch
*
* Returns: 0 on success, otherwise a negative error value.
*/
-int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent)
+int
+udev_enumerate_add_match_parent (struct udev_enumerate *udev_enumerate,
+ struct udev_device *parent)
{
- if (udev_enumerate == NULL)
- return -EINVAL;
- if (parent == NULL)
- return 0;
- if (udev_enumerate->parent_match != NULL)
- udev_device_unref(udev_enumerate->parent_match);
- udev_enumerate->parent_match = udev_device_ref(parent);
- return 0;
+ if (udev_enumerate == NULL)
+ return -EINVAL;
+ if (parent == NULL)
+ return 0;
+ if (udev_enumerate->parent_match != NULL)
+ udev_device_unref (udev_enumerate->parent_match);
+ udev_enumerate->parent_match = udev_device_ref (parent);
+ return 0;
}
/**
@@ -531,12 +588,14 @@ int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struc
*
* Returns: 0 on success, otherwise a negative error value.
*/
-int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate)
+int
+udev_enumerate_add_match_is_initialized (struct udev_enumerate
+ *udev_enumerate)
{
- if (udev_enumerate == NULL)
- return -EINVAL;
- udev_enumerate->match_is_initialized = true;
- return 0;
+ if (udev_enumerate == NULL)
+ return -EINVAL;
+ udev_enumerate->match_is_initialized = true;
+ return 0;
}
/**
@@ -548,224 +607,274 @@ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerat
*
* Returns: 0 on success, otherwise a negative error value.
*/
-int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname)
-{
- if (udev_enumerate == NULL)
- return -EINVAL;
- if (sysname == NULL)
- return 0;
- if (udev_list_entry_add(&udev_enumerate->sysname_match_list, sysname, NULL) == NULL)
- return -ENOMEM;
- return 0;
-}
-
-static bool match_sysattr(struct udev_enumerate *udev_enumerate, struct udev_device *dev)
-{
- struct udev_list_entry *list_entry;
-
- /* skip list */
- udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->sysattr_nomatch_list)) {
- if (match_sysattr_value(dev, udev_list_entry_get_name(list_entry),
- udev_list_entry_get_value(list_entry)))
- return false;
- }
- /* include list */
- if (udev_list_get_entry(&udev_enumerate->sysattr_match_list) != NULL) {
- udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->sysattr_match_list)) {
- /* anything that does not match, will make it FALSE */
- if (!match_sysattr_value(dev, udev_list_entry_get_name(list_entry),
- udev_list_entry_get_value(list_entry)))
- return false;
- }
- return true;
- }
- return true;
-}
-
-static bool match_property(struct udev_enumerate *udev_enumerate, struct udev_device *dev)
-{
- struct udev_list_entry *list_entry;
- bool match = false;
-
- /* no match always matches */
- if (udev_list_get_entry(&udev_enumerate->properties_match_list) == NULL)
- return true;
-
- /* loop over matches */
- udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->properties_match_list)) {
- const char *match_key = udev_list_entry_get_name(list_entry);
- const char *match_value = udev_list_entry_get_value(list_entry);
- struct udev_list_entry *property_entry;
-
- /* loop over device properties */
- udev_list_entry_foreach(property_entry, udev_device_get_properties_list_entry(dev)) {
- const char *dev_key = udev_list_entry_get_name(property_entry);
- const char *dev_value = udev_list_entry_get_value(property_entry);
-
- if (fnmatch(match_key, dev_key, 0) != 0)
- continue;
- if (match_value == NULL && dev_value == NULL) {
- match = true;
- goto out;
- }
- if (match_value == NULL || dev_value == NULL)
- continue;
- if (fnmatch(match_value, dev_value, 0) == 0) {
- match = true;
- goto out;
- }
- }
- }
+int
+udev_enumerate_add_match_sysname (struct udev_enumerate *udev_enumerate,
+ const char *sysname)
+{
+ if (udev_enumerate == NULL)
+ return -EINVAL;
+ if (sysname == NULL)
+ return 0;
+ if (udev_list_entry_add
+ (&udev_enumerate->sysname_match_list, sysname, NULL) == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+static bool
+match_sysattr (struct udev_enumerate *udev_enumerate, struct udev_device *dev)
+{
+ struct udev_list_entry *list_entry;
+
+ /* skip list */
+ udev_list_entry_foreach (list_entry,
+ udev_list_get_entry
+ (&udev_enumerate->sysattr_nomatch_list))
+ {
+ if (match_sysattr_value
+ (dev, udev_list_entry_get_name (list_entry),
+ udev_list_entry_get_value (list_entry)))
+ return false;
+ }
+ /* include list */
+ if (udev_list_get_entry (&udev_enumerate->sysattr_match_list) != NULL)
+ {
+ udev_list_entry_foreach (list_entry,
+ udev_list_get_entry
+ (&udev_enumerate->sysattr_match_list))
+ {
+ /* anything that does not match, will make it FALSE */
+ if (!match_sysattr_value
+ (dev, udev_list_entry_get_name (list_entry),
+ udev_list_entry_get_value (list_entry)))
+ return false;
+ }
+ return true;
+ }
+ return true;
+}
+
+static bool
+match_property (struct udev_enumerate *udev_enumerate,
+ struct udev_device *dev)
+{
+ struct udev_list_entry *list_entry;
+ bool match = false;
+
+ /* no match always matches */
+ if (udev_list_get_entry (&udev_enumerate->properties_match_list) == NULL)
+ return true;
+
+ /* loop over matches */
+ udev_list_entry_foreach (list_entry,
+ udev_list_get_entry
+ (&udev_enumerate->properties_match_list))
+ {
+ const char *match_key = udev_list_entry_get_name (list_entry);
+ const char *match_value = udev_list_entry_get_value (list_entry);
+ struct udev_list_entry *property_entry;
+
+ /* loop over device properties */
+ udev_list_entry_foreach (property_entry,
+ udev_device_get_properties_list_entry (dev))
+ {
+ const char *dev_key = udev_list_entry_get_name (property_entry);
+ const char *dev_value = udev_list_entry_get_value (property_entry);
+
+ if (fnmatch (match_key, dev_key, 0) != 0)
+ continue;
+ if (match_value == NULL && dev_value == NULL)
+ {
+ match = true;
+ goto out;
+ }
+ if (match_value == NULL || dev_value == NULL)
+ continue;
+ if (fnmatch (match_value, dev_value, 0) == 0)
+ {
+ match = true;
+ goto out;
+ }
+ }
+ }
out:
- return match;
-}
-
-static bool match_tag(struct udev_enumerate *udev_enumerate, struct udev_device *dev)
-{
- struct udev_list_entry *list_entry;
-
- /* no match always matches */
- if (udev_list_get_entry(&udev_enumerate->tags_match_list) == NULL)
- return true;
-
- /* loop over matches */
- udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->tags_match_list))
- if (!udev_device_has_tag(dev, udev_list_entry_get_name(list_entry)))
- return false;
-
- return true;
-}
-
-static bool match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *dev)
-{
- if (udev_enumerate->parent_match == NULL)
- return true;
-
- return startswith(udev_device_get_devpath(dev), udev_device_get_devpath(udev_enumerate->parent_match));
-}
-
-static bool match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname)
-{
- struct udev_list_entry *list_entry;
-
- if (udev_list_get_entry(&udev_enumerate->sysname_match_list) == NULL)
- return true;
-
- udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->sysname_match_list)) {
- if (fnmatch(udev_list_entry_get_name(list_entry), sysname, 0) != 0)
- continue;
- return true;
- }
- return false;
-}
-
-static int scan_dir_and_add_devices(struct udev_enumerate *udev_enumerate,
- const char *basedir, const char *subdir1, const char *subdir2)
-{
- char path[UTIL_PATH_SIZE];
- size_t l;
- char *s;
- DIR *dir;
- struct dirent *dent;
-
- s = path;
- l = strpcpyl(&s, sizeof(path), "/sys/", basedir, NULL);
- if (subdir1 != NULL)
- l = strpcpyl(&s, l, "/", subdir1, NULL);
- if (subdir2 != NULL)
- strpcpyl(&s, l, "/", subdir2, NULL);
- dir = opendir(path);
- if (dir == NULL)
- return -ENOENT;
- for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
- char syspath[UTIL_PATH_SIZE];
- struct udev_device *dev;
-
- if (dent->d_name[0] == '.')
- continue;
-
- if (!match_sysname(udev_enumerate, dent->d_name))
- continue;
-
- strscpyl(syspath, sizeof(syspath), path, "/", dent->d_name, NULL);
- dev = udev_device_new_from_syspath(udev_enumerate->udev, syspath);
- if (dev == NULL)
- continue;
-
- if (udev_enumerate->match_is_initialized) {
- /*
- * All devices with a device node or network interfaces
- * possibly need udev to adjust the device node permission
- * or context, or rename the interface before it can be
- * reliably used from other processes.
- *
- * For now, we can only check these types of devices, we
- * might not store a database, and have no way to find out
- * for all other types of devices.
- */
- if (!udev_device_get_is_initialized(dev) &&
- (major(udev_device_get_devnum(dev)) > 0 || udev_device_get_ifindex(dev) > 0))
- goto nomatch;
- }
- if (!match_parent(udev_enumerate, dev))
- goto nomatch;
- if (!match_tag(udev_enumerate, dev))
- goto nomatch;
- if (!match_property(udev_enumerate, dev))
- goto nomatch;
- if (!match_sysattr(udev_enumerate, dev))
- goto nomatch;
-
- syspath_add(udev_enumerate, udev_device_get_syspath(dev));
-nomatch:
- udev_device_unref(dev);
- }
- closedir(dir);
- return 0;
+ return match;
}
-static bool match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem)
+static bool
+match_tag (struct udev_enumerate *udev_enumerate, struct udev_device *dev)
{
- struct udev_list_entry *list_entry;
+ struct udev_list_entry *list_entry;
- if (!subsystem)
- return false;
+ /* no match always matches */
+ if (udev_list_get_entry (&udev_enumerate->tags_match_list) == NULL)
+ return true;
- udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->subsystem_nomatch_list)) {
- if (fnmatch(udev_list_entry_get_name(list_entry), subsystem, 0) == 0)
- return false;
- }
+ /* loop over matches */
+ udev_list_entry_foreach (list_entry,
+ udev_list_get_entry
+ (&udev_enumerate->tags_match_list))
+ if (!udev_device_has_tag (dev, udev_list_entry_get_name (list_entry)))
+ return false;
- if (udev_list_get_entry(&udev_enumerate->subsystem_match_list) != NULL) {
- udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->subsystem_match_list)) {
- if (fnmatch(udev_list_entry_get_name(list_entry), subsystem, 0) == 0)
- return true;
- }
- return false;
- }
+ return true;
+}
+
+static bool
+match_parent (struct udev_enumerate *udev_enumerate, struct udev_device *dev)
+{
+ if (udev_enumerate->parent_match == NULL)
+ return true;
- return true;
+ return startswith (udev_device_get_devpath (dev),
+ udev_device_get_devpath (udev_enumerate->parent_match));
}
-static int scan_dir(struct udev_enumerate *udev_enumerate, const char *basedir, const char *subdir, const char *subsystem)
+static bool
+match_sysname (struct udev_enumerate *udev_enumerate, const char *sysname)
{
- char path[UTIL_PATH_SIZE];
- DIR *dir;
- struct dirent *dent;
+ struct udev_list_entry *list_entry;
+
+ if (udev_list_get_entry (&udev_enumerate->sysname_match_list) == NULL)
+ return true;
+
+ udev_list_entry_foreach (list_entry,
+ udev_list_get_entry
+ (&udev_enumerate->sysname_match_list))
+ {
+ if (fnmatch (udev_list_entry_get_name (list_entry), sysname, 0) != 0)
+ continue;
+ return true;
+ }
+ return false;
+}
+
+static int
+scan_dir_and_add_devices (struct udev_enumerate *udev_enumerate,
+ const char *basedir, const char *subdir1,
+ const char *subdir2)
+{
+ char path[UTIL_PATH_SIZE];
+ size_t l;
+ char *s;
+ DIR *dir;
+ struct dirent *dent;
+
+ s = path;
+ l = strpcpyl (&s, sizeof (path), "/sys/", basedir, NULL);
+ if (subdir1 != NULL)
+ l = strpcpyl (&s, l, "/", subdir1, NULL);
+ if (subdir2 != NULL)
+ strpcpyl (&s, l, "/", subdir2, NULL);
+ dir = opendir (path);
+ if (dir == NULL)
+ return -ENOENT;
+ for (dent = readdir (dir); dent != NULL; dent = readdir (dir))
+ {
+ char syspath[UTIL_PATH_SIZE];
+ struct udev_device *dev;
+
+ if (dent->d_name[0] == '.')
+ continue;
+
+ if (!match_sysname (udev_enumerate, dent->d_name))
+ continue;
+
+ strscpyl (syspath, sizeof (syspath), path, "/", dent->d_name, NULL);
+ dev = udev_device_new_from_syspath (udev_enumerate->udev, syspath);
+ if (dev == NULL)
+ continue;
+
+ if (udev_enumerate->match_is_initialized)
+ {
+ /*
+ * All devices with a device node or network interfaces
+ * possibly need udev to adjust the device node permission
+ * or context, or rename the interface before it can be
+ * reliably used from other processes.
+ *
+ * For now, we can only check these types of devices, we
+ * might not store a database, and have no way to find out
+ * for all other types of devices.
+ */
+ if (!udev_device_get_is_initialized (dev) &&
+ (major (udev_device_get_devnum (dev)) > 0
+ || udev_device_get_ifindex (dev) > 0))
+ goto nomatch;
+ }
+ if (!match_parent (udev_enumerate, dev))
+ goto nomatch;
+ if (!match_tag (udev_enumerate, dev))
+ goto nomatch;
+ if (!match_property (udev_enumerate, dev))
+ goto nomatch;
+ if (!match_sysattr (udev_enumerate, dev))
+ goto nomatch;
+
+ syspath_add (udev_enumerate, udev_device_get_syspath (dev));
+ nomatch:
+ udev_device_unref (dev);
+ }
+ closedir (dir);
+ return 0;
+}
- strscpyl(path, sizeof(path), "/sys/", basedir, NULL);
- dir = opendir(path);
- if (dir == NULL)
- return -1;
- for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
- if (dent->d_name[0] == '.')
- continue;
- if (!match_subsystem(udev_enumerate, subsystem != NULL ? subsystem : dent->d_name))
- continue;
- scan_dir_and_add_devices(udev_enumerate, basedir, dent->d_name, subdir);
- }
- closedir(dir);
- return 0;
+static bool
+match_subsystem (struct udev_enumerate *udev_enumerate, const char *subsystem)
+{
+ struct udev_list_entry *list_entry;
+
+ if (!subsystem)
+ return false;
+
+ udev_list_entry_foreach (list_entry,
+ udev_list_get_entry
+ (&udev_enumerate->subsystem_nomatch_list))
+ {
+ if (fnmatch (udev_list_entry_get_name (list_entry), subsystem, 0) == 0)
+ return false;
+ }
+
+ if (udev_list_get_entry (&udev_enumerate->subsystem_match_list) != NULL)
+ {
+ udev_list_entry_foreach (list_entry,
+ udev_list_get_entry
+ (&udev_enumerate->subsystem_match_list))
+ {
+ if (fnmatch
+ (udev_list_entry_get_name (list_entry), subsystem, 0) == 0)
+ return true;
+ }
+ return false;
+ }
+
+ return true;
+}
+
+static int
+scan_dir (struct udev_enumerate *udev_enumerate, const char *basedir,
+ const char *subdir, const char *subsystem)
+{
+ char path[UTIL_PATH_SIZE];
+ DIR *dir;
+ struct dirent *dent;
+
+ strscpyl (path, sizeof (path), "/sys/", basedir, NULL);
+ dir = opendir (path);
+ if (dir == NULL)
+ return -1;
+ for (dent = readdir (dir); dent != NULL; dent = readdir (dir))
+ {
+ if (dent->d_name[0] == '.')
+ continue;
+ if (!match_subsystem
+ (udev_enumerate, subsystem != NULL ? subsystem : dent->d_name))
+ continue;
+ scan_dir_and_add_devices (udev_enumerate, basedir, dent->d_name,
+ subdir);
+ }
+ closedir (dir);
+ return 0;
}
/**
@@ -777,142 +886,161 @@ static int scan_dir(struct udev_enumerate *udev_enumerate, const char *basedir,
*
* Returns: 0 on success, otherwise a negative error value.
*/
-int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath)
-{
- struct udev_device *udev_device;
-
- if (udev_enumerate == NULL)
- return -EINVAL;
- if (syspath == NULL)
- return 0;
- /* resolve to real syspath */
- udev_device = udev_device_new_from_syspath(udev_enumerate->udev, syspath);
- if (udev_device == NULL)
- return -EINVAL;
- syspath_add(udev_enumerate, udev_device_get_syspath(udev_device));
- udev_device_unref(udev_device);
- return 0;
-}
-
-static int scan_devices_tags(struct udev_enumerate *udev_enumerate)
-{
- struct udev_list_entry *list_entry;
-
- /* scan only tagged devices, use tags reverse-index, instead of searching all devices in /sys */
- udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->tags_match_list)) {
- DIR *dir;
- struct dirent *dent;
- char path[UTIL_PATH_SIZE];
-
- strscpyl(path, sizeof(path), "/run/udev/tags/", udev_list_entry_get_name(list_entry), NULL);
- dir = opendir(path);
- if (dir == NULL)
- continue;
- for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
- struct udev_device *dev;
-
- if (dent->d_name[0] == '.')
- continue;
-
- dev = udev_device_new_from_device_id(udev_enumerate->udev, dent->d_name);
- if (dev == NULL)
- continue;
-
- if (!match_subsystem(udev_enumerate, udev_device_get_subsystem(dev)))
- goto nomatch;
- if (!match_sysname(udev_enumerate, udev_device_get_sysname(dev)))
- goto nomatch;
- if (!match_parent(udev_enumerate, dev))
- goto nomatch;
- if (!match_property(udev_enumerate, dev))
- goto nomatch;
- if (!match_sysattr(udev_enumerate, dev))
- goto nomatch;
-
- syspath_add(udev_enumerate, udev_device_get_syspath(dev));
-nomatch:
- udev_device_unref(dev);
- }
- closedir(dir);
- }
- return 0;
+int
+udev_enumerate_add_syspath (struct udev_enumerate *udev_enumerate,
+ const char *syspath)
+{
+ struct udev_device *udev_device;
+
+ if (udev_enumerate == NULL)
+ return -EINVAL;
+ if (syspath == NULL)
+ return 0;
+ /* resolve to real syspath */
+ udev_device = udev_device_new_from_syspath (udev_enumerate->udev, syspath);
+ if (udev_device == NULL)
+ return -EINVAL;
+ syspath_add (udev_enumerate, udev_device_get_syspath (udev_device));
+ udev_device_unref (udev_device);
+ return 0;
+}
+
+static int
+scan_devices_tags (struct udev_enumerate *udev_enumerate)
+{
+ struct udev_list_entry *list_entry;
+
+ /* scan only tagged devices, use tags reverse-index, instead of searching all devices in /sys */
+ udev_list_entry_foreach (list_entry,
+ udev_list_get_entry
+ (&udev_enumerate->tags_match_list))
+ {
+ DIR *dir;
+ struct dirent *dent;
+ char path[UTIL_PATH_SIZE];
+
+ strscpyl (path, sizeof (path), "/run/udev/tags/",
+ udev_list_entry_get_name (list_entry), NULL);
+ dir = opendir (path);
+ if (dir == NULL)
+ continue;
+ for (dent = readdir (dir); dent != NULL; dent = readdir (dir))
+ {
+ struct udev_device *dev;
+
+ if (dent->d_name[0] == '.')
+ continue;
+
+ dev =
+ udev_device_new_from_device_id (udev_enumerate->udev, dent->d_name);
+ if (dev == NULL)
+ continue;
+
+ if (!match_subsystem
+ (udev_enumerate, udev_device_get_subsystem (dev)))
+ goto nomatch;
+ if (!match_sysname (udev_enumerate, udev_device_get_sysname (dev)))
+ goto nomatch;
+ if (!match_parent (udev_enumerate, dev))
+ goto nomatch;
+ if (!match_property (udev_enumerate, dev))
+ goto nomatch;
+ if (!match_sysattr (udev_enumerate, dev))
+ goto nomatch;
+
+ syspath_add (udev_enumerate, udev_device_get_syspath (dev));
+ nomatch:
+ udev_device_unref (dev);
+ }
+ closedir (dir);
+ }
+ return 0;
}
-static int parent_add_child(struct udev_enumerate *enumerate, const char *path)
+static int
+parent_add_child (struct udev_enumerate *enumerate, const char *path)
{
- struct udev_device *dev;
- int r = 0;
+ struct udev_device *dev;
+ int r = 0;
- dev = udev_device_new_from_syspath(enumerate->udev, path);
- if (dev == NULL)
- return -ENODEV;
+ dev = udev_device_new_from_syspath (enumerate->udev, path);
+ if (dev == NULL)
+ return -ENODEV;
- if (!match_subsystem(enumerate, udev_device_get_subsystem(dev)))
- goto nomatch;
- if (!match_sysname(enumerate, udev_device_get_sysname(dev)))
- goto nomatch;
- if (!match_property(enumerate, dev))
- goto nomatch;
- if (!match_sysattr(enumerate, dev))
- goto nomatch;
+ if (!match_subsystem (enumerate, udev_device_get_subsystem (dev)))
+ goto nomatch;
+ if (!match_sysname (enumerate, udev_device_get_sysname (dev)))
+ goto nomatch;
+ if (!match_property (enumerate, dev))
+ goto nomatch;
+ if (!match_sysattr (enumerate, dev))
+ goto nomatch;
- syspath_add(enumerate, udev_device_get_syspath(dev));
- r = 1;
+ syspath_add (enumerate, udev_device_get_syspath (dev));
+ r = 1;
nomatch:
- udev_device_unref(dev);
- return r;
+ udev_device_unref (dev);
+ return r;
}
-static int parent_crawl_children(struct udev_enumerate *enumerate, const char *path, int maxdepth)
+static int
+parent_crawl_children (struct udev_enumerate *enumerate,
+ const char *path, int maxdepth)
{
- DIR *d;
- struct dirent *dent;
-
- d = opendir(path);
- if (d == NULL)
- return -errno;
-
- for (dent = readdir(d); dent != NULL; dent = readdir(d)) {
- char *child;
-
- if (dent->d_name[0] == '.')
- continue;
- if (dent->d_type != DT_DIR)
- continue;
- if (asprintf(&child, "%s/%s", path, dent->d_name) < 0)
- continue;
- parent_add_child(enumerate, child);
- if (maxdepth > 0)
- parent_crawl_children(enumerate, child, maxdepth-1);
- free(child);
- }
-
- closedir(d);
- return 0;
+ DIR *d;
+ struct dirent *dent;
+
+ d = opendir (path);
+ if (d == NULL)
+ return -errno;
+
+ for (dent = readdir (d); dent != NULL; dent = readdir (d))
+ {
+ char *child;
+
+ if (dent->d_name[0] == '.')
+ continue;
+ if (dent->d_type != DT_DIR)
+ continue;
+ if (asprintf (&child, "%s/%s", path, dent->d_name) < 0)
+ continue;
+ parent_add_child (enumerate, child);
+ if (maxdepth > 0)
+ parent_crawl_children (enumerate, child, maxdepth - 1);
+ free (child);
+ }
+
+ closedir (d);
+ return 0;
}
-static int scan_devices_children(struct udev_enumerate *enumerate)
+static int
+scan_devices_children (struct udev_enumerate *enumerate)
{
- const char *path;
+ const char *path;
- path = udev_device_get_syspath(enumerate->parent_match);
- parent_add_child(enumerate, path);
- return parent_crawl_children(enumerate, path, 256);
+ path = udev_device_get_syspath (enumerate->parent_match);
+ parent_add_child (enumerate, path);
+ return parent_crawl_children (enumerate, path, 256);
}
-static int scan_devices_all(struct udev_enumerate *udev_enumerate)
+static int
+scan_devices_all (struct udev_enumerate *udev_enumerate)
{
- struct stat statbuf;
-
- if (stat("/sys/subsystem", &statbuf) == 0) {
- /* we have /subsystem/, forget all the old stuff */
- scan_dir(udev_enumerate, "subsystem", "devices", NULL);
- } else {
- scan_dir(udev_enumerate, "bus", "devices", NULL);
- scan_dir(udev_enumerate, "class", NULL, NULL);
- }
- return 0;
+ struct stat statbuf;
+
+ if (stat ("/sys/subsystem", &statbuf) == 0)
+ {
+ /* we have /subsystem/, forget all the old stuff */
+ scan_dir (udev_enumerate, "subsystem", "devices", NULL);
+ }
+ else
+ {
+ scan_dir (udev_enumerate, "bus", "devices", NULL);
+ scan_dir (udev_enumerate, "class", NULL, NULL);
+ }
+ return 0;
}
/**
@@ -924,21 +1052,22 @@ static int scan_devices_all(struct udev_enumerate *udev_enumerate)
*
* Returns: 0 on success, otherwise a negative error value.
**/
-int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate)
+int
+udev_enumerate_scan_devices (struct udev_enumerate *udev_enumerate)
{
- if (udev_enumerate == NULL)
- return -EINVAL;
+ if (udev_enumerate == NULL)
+ return -EINVAL;
- /* efficiently lookup tags only, we maintain a reverse-index */
- if (udev_list_get_entry(&udev_enumerate->tags_match_list) != NULL)
- return scan_devices_tags(udev_enumerate);
+ /* efficiently lookup tags only, we maintain a reverse-index */
+ if (udev_list_get_entry (&udev_enumerate->tags_match_list) != NULL)
+ return scan_devices_tags (udev_enumerate);
- /* walk the subtree of one parent device only */
- if (udev_enumerate->parent_match != NULL)
- return scan_devices_children(udev_enumerate);
+ /* walk the subtree of one parent device only */
+ if (udev_enumerate->parent_match != NULL)
+ return scan_devices_children (udev_enumerate);
- /* scan devices of all subsystems */
- return scan_devices_all(udev_enumerate);
+ /* scan devices of all subsystems */
+ return scan_devices_all (udev_enumerate);
}
/**
@@ -949,29 +1078,30 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate)
*
* Returns: 0 on success, otherwise a negative error value.
**/
-int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate)
+int
+udev_enumerate_scan_subsystems (struct udev_enumerate *udev_enumerate)
{
- struct stat statbuf;
- const char *subsysdir;
+ struct stat statbuf;
+ const char *subsysdir;
- if (udev_enumerate == NULL)
- return -EINVAL;
+ if (udev_enumerate == NULL)
+ return -EINVAL;
- /* all kernel modules */
- if (match_subsystem(udev_enumerate, "module"))
- scan_dir_and_add_devices(udev_enumerate, "module", NULL, NULL);
+ /* all kernel modules */
+ if (match_subsystem (udev_enumerate, "module"))
+ scan_dir_and_add_devices (udev_enumerate, "module", NULL, NULL);
- if (stat("/sys/subsystem", &statbuf) == 0)
- subsysdir = "subsystem";
- else
- subsysdir = "bus";
+ if (stat ("/sys/subsystem", &statbuf) == 0)
+ subsysdir = "subsystem";
+ else
+ subsysdir = "bus";
- /* all subsystems (only buses support coldplug) */
- if (match_subsystem(udev_enumerate, "subsystem"))
- scan_dir_and_add_devices(udev_enumerate, subsysdir, NULL, NULL);
+ /* all subsystems (only buses support coldplug) */
+ if (match_subsystem (udev_enumerate, "subsystem"))
+ scan_dir_and_add_devices (udev_enumerate, subsysdir, NULL, NULL);
- /* all subsystem drivers */
- if (match_subsystem(udev_enumerate, "drivers"))
- scan_dir(udev_enumerate, subsysdir, "drivers", "drivers");
- return 0;
+ /* all subsystem drivers */
+ if (match_subsystem (udev_enumerate, "drivers"))
+ scan_dir (udev_enumerate, subsysdir, "drivers", "drivers");
+ return 0;
}
diff --git a/libudev-compat/libudev-fs.c b/libudev-compat/libudev-fs.c
index be138dc..9e69929 100644
--- a/libudev-compat/libudev-fs.c
+++ b/libudev-compat/libudev-fs.c
@@ -23,11 +23,11 @@
#define UDEV_FS_WATCH_DIR_FLAGS (IN_CREATE | IN_ONESHOT)
-#ifdef TEST
+#ifdef TEST
#define UDEV_FS_EVENTS_DIR "/tmp/events"
#else
#define UDEV_FS_EVENTS_DIR "/dev/metadata/udev/events"
-#endif
+#endif
// how many monitors can there be per process?
// this is probably big enough.
@@ -36,724 +36,835 @@
#define UDEV_MAX_MONITORS 32768
#endif
-static int udev_monitor_fs_events_path( char const* name, char* pathbuf, int nonce );
+static int udev_monitor_fs_events_path (char const *name, char *pathbuf,
+ int nonce);
// We need to make sure that on fork, a udev_monitor listening to the underlying filesystem
// will listen to its *own* process's events directory, at all times. To do this, we will
// track every monitor that exists, by holding a reference internally. When the process
// forks, we'll re-initialize all monitors to point to the new process's events directory.
-static struct udev_monitor* g_monitor_table[ UDEV_MAX_MONITORS ];
-static int g_monitor_lock = 0; // primitive mutex that can work across forks
-static pid_t g_pid = 0; // tells us when to re-target the monitors
-
+static struct udev_monitor *g_monitor_table[UDEV_MAX_MONITORS];
+static int g_monitor_lock = 0; // primitive mutex that can work across forks
+static pid_t g_pid = 0; // tells us when to re-target the monitors
// spin-lock to lock the monitor table
-static void g_monitor_table_spinlock() {
-
- bool locked = false;
- while( 1 ) {
-
- locked = __sync_bool_compare_and_swap( &g_monitor_lock, 0, 1 );
- if( locked ) {
- break;
- }
- }
+static void
+g_monitor_table_spinlock ()
+{
+
+ bool locked = false;
+ while (1)
+ {
+
+ locked = __sync_bool_compare_and_swap (&g_monitor_lock, 0, 1);
+ if (locked)
+ {
+ break;
+ }
+ }
}
// unlock the monitor table
-static void g_monitor_table_unlock() {
-
- g_monitor_lock = 0;
-
- // make sure spinners see it.
- __sync_synchronize();
+static void
+g_monitor_table_unlock ()
+{
+
+ g_monitor_lock = 0;
+
+ // make sure spinners see it.
+ __sync_synchronize ();
}
// on fork(), create a new events directory for each of this process's monitors
// and point them all to them. This way, both the parent and child can continue
// to receive device packets.
// NOTE: can only call async-safe methods
-static void udev_monitor_atfork(void) {
-
- int errsv = errno;
- int rc = 0;
- int i = 0;
- int cnt = 0;
- pid_t pid = getpid();
- struct udev_monitor* monitor = NULL;
- int socket_fds[2];
- struct epoll_event ev;
-
- write( STDERR_FILENO, "forked! begin split\n", strlen("forked! begin split\n") );
-
- memset( &ev, 0, sizeof(struct epoll_event) );
-
- // reset each monitor's inotify fd to point to a new PID-specific directory instead
- g_monitor_table_spinlock();
-
- if( g_pid != pid ) {
-
+static void
+udev_monitor_atfork (void)
+{
+
+ int errsv = errno;
+ int rc = 0;
+ int i = 0;
+ int cnt = 0;
+ pid_t pid = getpid ();
+ struct udev_monitor *monitor = NULL;
+ int socket_fds[2];
+ struct epoll_event ev;
+
+ write (STDERR_FILENO, "forked! begin split\n",
+ strlen ("forked! begin split\n"));
+
+ memset (&ev, 0, sizeof (struct epoll_event));
+
+ // reset each monitor's inotify fd to point to a new PID-specific directory instead
+ g_monitor_table_spinlock ();
+
+ if (g_pid != pid)
+ {
+
// child; do the fork
- for( i = 0; i < UDEV_MAX_MONITORS; i++ ) {
-
- if( g_monitor_table[i] == NULL ) {
- continue;
- }
-
- monitor = g_monitor_table[i];
-
- if( monitor->type != UDEV_MONITOR_TYPE_UDEV ) {
- continue;
- }
-
- if( monitor->inotify_fd < 0 ) {
- continue;
- }
-
- if( monitor->epoll_fd < 0 ) {
- continue;
- }
-
- if( monitor->events_wd < 0 ) {
- continue;
- }
-
- // reset the socket buffer--the parent will be said to have
- // received intermittent events before the child was created.
- if( monitor->sock >= 0 ) {
-
- // stop watching this socket--we'll regenerate it later
- epoll_ctl( monitor->epoll_fd, EPOLL_CTL_DEL, monitor->sock, NULL );
- close( monitor->sock );
- monitor->sock = -1;
- }
-
- if( monitor->sock_fs >= 0 ) {
- close( monitor->sock_fs );
- monitor->sock_fs = -1;
- }
-
- rc = socketpair( AF_LOCAL, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, socket_fds );
- if( rc < 0 ) {
-
- // not much we can do here, except log an error
- write( STDERR_FILENO, "Failed to generate a socketpair\n", strlen( "Failed to generate a socketpair\n" ) );
-
- udev_monitor_fs_shutdown( monitor );
- g_monitor_table[i] = NULL;
- continue;
- }
-
- // child's copy of the monitor has its own socketpair
- monitor->sock = socket_fds[0];
- monitor->sock_fs = socket_fds[1];
-
- // reinstall its filter
- udev_monitor_filter_update( monitor );
-
- // watch the child's socket
- ev.events = EPOLLIN;
- ev.data.fd = monitor->sock;
- rc = epoll_ctl( monitor->epoll_fd, EPOLL_CTL_ADD, monitor->sock, &ev );
- if( rc < 0 ) {
-
- // not much we can do here, except log an error
- write( STDERR_FILENO, "Failed to add monitor socket\n", strlen("Failed to add monitor socket\n") );
-
- udev_monitor_fs_shutdown( monitor );
- g_monitor_table[i] = NULL;
- continue;
- }
-
- // reset the inotify watch
- rc = inotify_rm_watch( monitor->inotify_fd, monitor->events_wd );
- monitor->events_wd = -1;
-
- if( rc < 0 ) {
-
- rc = -errno;
- if( rc == -EINVAL ) {
-
- // monitor->events_wd was invalid
- rc = 0;
- }
- else if( rc == -EBADF ) {
-
- // monitor->inotify_fd is invalid.
- // not much we can do here, except log an error
- write( STDERR_FILENO, "Invalid inotify handle\n", strlen("Invalid inotify handle"));
-
- udev_monitor_fs_shutdown( monitor );
- g_monitor_table[i] = NULL;
- continue;
- }
- }
-
- if( rc == 0 ) {
-
- udev_monitor_fs_events_path( "", monitor->events_dir, i );
-
- // try to create a new directory for this monitor
- rc = mkdir( monitor->events_dir, 0700 );
-
- if( rc < 0 ) {
- // failed, we have.
- // child will not get any notifications from this monitor
- rc = -errno;
- write( STDERR_FILENO, "Failed to mkdir ", strlen("Failed to mkdir ") );
- write( STDERR_FILENO, monitor->events_dir, strlen(monitor->events_dir) );
- write( STDERR_FILENO, "\n", 1 );
-
- udev_monitor_fs_shutdown( monitor );
- g_monitor_table[i] = NULL;
- return;
- }
-
- // reconnect to the new directory
- monitor->events_wd = inotify_add_watch( monitor->inotify_fd, monitor->events_dir, UDEV_FS_WATCH_DIR_FLAGS );
- if( monitor->events_wd < 0 ) {
-
- // there's not much we can safely do here, besides log an error
- write( STDERR_FILENO, "Failed to watch ", strlen( "Failed to watch " ) );
- write( STDERR_FILENO, monitor->events_dir, strlen(monitor->events_dir) );
- write( STDERR_FILENO, "\n", 1 );
- }
- }
- else {
-
- // there's not much we can safely do here, besides log an error
- rc = -errno;
- write( STDERR_FILENO, "Failed to disconnect!\n", strlen("Failed to disconnect!\n") );
- }
- }
-
+ for (i = 0; i < UDEV_MAX_MONITORS; i++)
+ {
+
+ if (g_monitor_table[i] == NULL)
+ {
+ continue;
+ }
+
+ monitor = g_monitor_table[i];
+
+ if (monitor->type != UDEV_MONITOR_TYPE_UDEV)
+ {
+ continue;
+ }
+
+ if (monitor->inotify_fd < 0)
+ {
+ continue;
+ }
+
+ if (monitor->epoll_fd < 0)
+ {
+ continue;
+ }
+
+ if (monitor->events_wd < 0)
+ {
+ continue;
+ }
+ // reset the socket buffer--the parent will be said to have
+ // received intermittent events before the child was created.
+ if (monitor->sock >= 0)
+ {
+
+ // stop watching this socket--we'll regenerate it later
+ epoll_ctl (monitor->epoll_fd, EPOLL_CTL_DEL,
+ monitor->sock, NULL);
+ close (monitor->sock);
+ monitor->sock = -1;
+ }
+
+ if (monitor->sock_fs >= 0)
+ {
+ close (monitor->sock_fs);
+ monitor->sock_fs = -1;
+ }
+
+ rc = socketpair (AF_LOCAL,
+ SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC,
+ 0, socket_fds);
+ if (rc < 0)
+ {
+
+ // not much we can do here, except log an error
+ write (STDERR_FILENO,
+ "Failed to generate a socketpair\n",
+ strlen ("Failed to generate a socketpair\n"));
+
+ udev_monitor_fs_shutdown (monitor);
+ g_monitor_table[i] = NULL;
+ continue;
+ }
+ // child's copy of the monitor has its own socketpair
+ monitor->sock = socket_fds[0];
+ monitor->sock_fs = socket_fds[1];
+
+ // reinstall its filter
+ udev_monitor_filter_update (monitor);
+
+ // watch the child's socket
+ ev.events = EPOLLIN;
+ ev.data.fd = monitor->sock;
+ rc = epoll_ctl (monitor->epoll_fd, EPOLL_CTL_ADD,
+ monitor->sock, &ev);
+ if (rc < 0)
+ {
+
+ // not much we can do here, except log an error
+ write (STDERR_FILENO,
+ "Failed to add monitor socket\n",
+ strlen ("Failed to add monitor socket\n"));
+
+ udev_monitor_fs_shutdown (monitor);
+ g_monitor_table[i] = NULL;
+ continue;
+ }
+ // reset the inotify watch
+ rc = inotify_rm_watch (monitor->inotify_fd, monitor->events_wd);
+ monitor->events_wd = -1;
+
+ if (rc < 0)
+ {
+
+ rc = -errno;
+ if (rc == -EINVAL)
+ {
+
+ // monitor->events_wd was invalid
+ rc = 0;
+ }
+ else if (rc == -EBADF)
+ {
+
+ // monitor->inotify_fd is invalid.
+ // not much we can do here, except log an error
+ write (STDERR_FILENO,
+ "Invalid inotify handle\n",
+ strlen ("Invalid inotify handle"));
+
+ udev_monitor_fs_shutdown (monitor);
+ g_monitor_table[i] = NULL;
+ continue;
+ }
+ }
+
+ if (rc == 0)
+ {
+
+ udev_monitor_fs_events_path ("", monitor->events_dir, i);
+
+ // try to create a new directory for this monitor
+ rc = mkdir (monitor->events_dir, 0700);
+
+ if (rc < 0)
+ {
+ // failed, we have.
+ // child will not get any notifications from this monitor
+ rc = -errno;
+ write (STDERR_FILENO, "Failed to mkdir ",
+ strlen ("Failed to mkdir "));
+ write (STDERR_FILENO,
+ monitor->events_dir, strlen (monitor->events_dir));
+ write (STDERR_FILENO, "\n", 1);
+
+ udev_monitor_fs_shutdown (monitor);
+ g_monitor_table[i] = NULL;
+ return;
+ }
+ // reconnect to the new directory
+ monitor->events_wd =
+ inotify_add_watch (monitor->inotify_fd,
+ monitor->events_dir,
+ UDEV_FS_WATCH_DIR_FLAGS);
+ if (monitor->events_wd < 0)
+ {
+
+ // there's not much we can safely do here, besides log an error
+ write (STDERR_FILENO, "Failed to watch ",
+ strlen ("Failed to watch "));
+ write (STDERR_FILENO,
+ monitor->events_dir, strlen (monitor->events_dir));
+ write (STDERR_FILENO, "\n", 1);
+ }
+ }
+ else
+ {
+
+ // there's not much we can safely do here, besides log an error
+ rc = -errno;
+ write (STDERR_FILENO, "Failed to disconnect!\n",
+ strlen ("Failed to disconnect!\n"));
+ }
+ }
+
g_pid = pid;
- }
-
- g_monitor_table_unlock();
-
- write( STDERR_FILENO, "end atfork()\n", strlen("end atfork()\n") );
-
- // restore...
- errno = errsv;
-}
+ }
+
+ g_monitor_table_unlock ();
+ write (STDERR_FILENO, "end atfork()\n", strlen ("end atfork()\n"));
+
+ // restore...
+ errno = errsv;
+}
// register a monitor in our list of monitors
// return 0 on success
// return -ENOSPC if we're out of slots
-static int udev_monitor_register( struct udev_monitor* monitor ) {
-
- g_monitor_table_spinlock();
-
- // find a free slot
- int i = 0;
- int rc = -ENOSPC;
- for( i = 0; i < UDEV_MAX_MONITORS; i++ ) {
-
- if( g_monitor_table[i] == NULL ) {
-
- g_monitor_table[i] = monitor;
- monitor->slot = i;
- rc = 0;
- break;
- }
- }
-
- if( g_pid == 0 ) {
-
+static int
+udev_monitor_register (struct udev_monitor *monitor)
+{
+
+ g_monitor_table_spinlock ();
+
+ // find a free slot
+ int i = 0;
+ int rc = -ENOSPC;
+ for (i = 0; i < UDEV_MAX_MONITORS; i++)
+ {
+
+ if (g_monitor_table[i] == NULL)
+ {
+
+ g_monitor_table[i] = monitor;
+ monitor->slot = i;
+ rc = 0;
+ break;
+ }
+ }
+
+ if (g_pid == 0)
+ {
+
// first monitor ever.
// register our fork handler.
- g_pid = getpid();
- pthread_atfork( NULL, NULL, udev_monitor_atfork );
- }
-
- g_monitor_table_unlock();
+ g_pid = getpid ();
+ pthread_atfork (NULL, NULL, udev_monitor_atfork);
+ }
- return rc;
-}
+ g_monitor_table_unlock ();
+ return rc;
+}
// unregister a monitor in our list of monitors
-static void udev_monitor_unregister( struct udev_monitor* monitor ) {
-
- if( monitor->slot < 0 ) {
+static void
+udev_monitor_unregister (struct udev_monitor *monitor)
+{
+
+ if (monitor->slot < 0)
+ {
return;
- }
-
- g_monitor_table_spinlock();
-
- g_monitor_table[ monitor->slot ] = NULL;
-
- g_monitor_table_unlock();
-
- monitor->slot = -1;
-}
+ }
+ g_monitor_table_spinlock ();
+
+ g_monitor_table[monitor->slot] = NULL;
+
+ g_monitor_table_unlock ();
+
+ monitor->slot = -1;
+}
// write, but mask EINTR
// return number of bytes written on success
// return -errno on I/O error
-ssize_t udev_write_uninterrupted( int fd, char const* buf, size_t len ) {
-
- ssize_t num_written = 0;
-
- if( buf == NULL ) {
+ssize_t
+udev_write_uninterrupted (int fd, char const *buf, size_t len)
+{
+
+ ssize_t num_written = 0;
+
+ if (buf == NULL)
+ {
return -EINVAL;
- }
-
- while( (unsigned)num_written < len ) {
- ssize_t nw = write( fd, buf + num_written, len - num_written );
- if( nw < 0 ) {
-
- int errsv = -errno;
- if( errsv == -EINTR ) {
- continue;
- }
-
- return errsv;
- }
- if( nw == 0 ) {
- break;
- }
-
+ }
+
+ while ((unsigned) num_written < len)
+ {
+ ssize_t nw = write (fd, buf + num_written, len - num_written);
+ if (nw < 0)
+ {
+
+ int errsv = -errno;
+ if (errsv == -EINTR)
+ {
+ continue;
+ }
+
+ return errsv;
+ }
+ if (nw == 0)
+ {
+ break;
+ }
+
num_written += nw;
- }
-
- return num_written;
-}
+ }
+ return num_written;
+}
// read, but mask EINTR
// return number of bytes read on success
// return -errno on I/O error
// NOTE: must be async-safe!
-ssize_t udev_read_uninterrupted( int fd, char* buf, size_t len ) {
-
- ssize_t num_read = 0;
-
- if( buf == NULL ) {
+ssize_t
+udev_read_uninterrupted (int fd, char *buf, size_t len)
+{
+
+ ssize_t num_read = 0;
+
+ if (buf == NULL)
+ {
return -EINVAL;
- }
-
- while( (unsigned)num_read < len ) {
- ssize_t nr = read( fd, buf + num_read, len - num_read );
- if( nr < 0 ) {
-
- int errsv = -errno;
- if( errsv == -EINTR ) {
- continue;
- }
-
- return errsv;
- }
- if( nr == 0 ) {
- break;
- }
-
+ }
+
+ while ((unsigned) num_read < len)
+ {
+ ssize_t nr = read (fd, buf + num_read, len - num_read);
+ if (nr < 0)
+ {
+
+ int errsv = -errno;
+ if (errsv == -EINTR)
+ {
+ continue;
+ }
+
+ return errsv;
+ }
+ if (nr == 0)
+ {
+ break;
+ }
+
num_read += nr;
- }
-
- return num_read;
-}
+ }
+ return num_read;
+}
// set up a filesystem monitor
// register pthread_atfork() handlers to ensure that its children
// get their own filesystem monitor state.
// * set up /dev/events/libudev-$PID/
// * start watching /dev/events/libudev-$PID for new files
-int udev_monitor_fs_setup( struct udev_monitor* monitor ) {
-
- int rc = 0;
- struct epoll_event ev;
-
- monitor->inotify_fd = -1;
- monitor->epoll_fd = -1;
- monitor->sock = -1;
- monitor->sock_fs = -1;
- monitor->slot = -1;
-
- int socket_fd[2] = { -1, -1 };
-
- memset( &monitor->events_dir, 0, PATH_MAX+1 );
- memset( &ev, 0, sizeof(struct epoll_event) );
-
- // make sure this monitor can't disappear on us
- udev_monitor_register( monitor );
-
- // set up inotify
- monitor->inotify_fd = inotify_init1( IN_NONBLOCK | IN_CLOEXEC );
- if( monitor->inotify_fd < 0 ) {
-
+int
+udev_monitor_fs_setup (struct udev_monitor *monitor)
+{
+
+ int rc = 0;
+ struct epoll_event ev;
+
+ monitor->inotify_fd = -1;
+ monitor->epoll_fd = -1;
+ monitor->sock = -1;
+ monitor->sock_fs = -1;
+ monitor->slot = -1;
+
+ int socket_fd[2] = { -1, -1 };
+
+ memset (&monitor->events_dir, 0, PATH_MAX + 1);
+ memset (&ev, 0, sizeof (struct epoll_event));
+
+ // make sure this monitor can't disappear on us
+ udev_monitor_register (monitor);
+
+ // set up inotify
+ monitor->inotify_fd = inotify_init1 (IN_NONBLOCK | IN_CLOEXEC);
+ if (monitor->inotify_fd < 0)
+ {
+
rc = -errno;
- log_error("inotify_init rc = %d", rc );
-
- udev_monitor_fs_shutdown( monitor );
+ log_error ("inotify_init rc = %d", rc);
+
+ udev_monitor_fs_shutdown (monitor);
return rc;
- }
-
- // epoll descriptor unifying inotify and event counter
- monitor->epoll_fd = epoll_create1( EPOLL_CLOEXEC );
- if( monitor->epoll_fd < 0 ) {
-
+ }
+ // epoll descriptor unifying inotify and event counter
+ monitor->epoll_fd = epoll_create1 (EPOLL_CLOEXEC);
+ if (monitor->epoll_fd < 0)
+ {
+
rc = -errno;
- log_error("epoll_create rc = %d", rc );
-
- udev_monitor_fs_shutdown( monitor );
+ log_error ("epoll_create rc = %d", rc);
+
+ udev_monitor_fs_shutdown (monitor);
return rc;
- }
-
- // create our monitor directory /dev/events/libudev-$PID
- udev_monitor_fs_events_path( "", monitor->events_dir, monitor->slot );
- rc = mkdir( monitor->events_dir, 0700 );
- if( rc != 0 ) {
-
+ }
+ // create our monitor directory /dev/events/libudev-$PID
+ udev_monitor_fs_events_path ("", monitor->events_dir, monitor->slot);
+ rc = mkdir (monitor->events_dir, 0700);
+ if (rc != 0)
+ {
+
rc = -errno;
- log_error("mkdir('%s') rc = %d", monitor->events_dir, rc );
-
- udev_monitor_fs_destroy( monitor );
+ log_error ("mkdir('%s') rc = %d", monitor->events_dir, rc);
+
+ udev_monitor_fs_destroy (monitor);
return rc;
- }
-
- // begin watching /dev/events/libudev-$PID
- monitor->events_wd = inotify_add_watch( monitor->inotify_fd, monitor->events_dir, UDEV_FS_WATCH_DIR_FLAGS );
- if( monitor->events_wd < 0 ) {
-
+ }
+ // begin watching /dev/events/libudev-$PID
+ monitor->events_wd =
+ inotify_add_watch (monitor->inotify_fd, monitor->events_dir,
+ UDEV_FS_WATCH_DIR_FLAGS);
+ if (monitor->events_wd < 0)
+ {
+
rc = -errno;
- log_error("inotify_add_watch('%s') rc = %d", monitor->events_dir, rc );
-
- udev_monitor_fs_destroy( monitor );
+ log_error ("inotify_add_watch('%s') rc = %d", monitor->events_dir, rc);
+
+ udev_monitor_fs_destroy (monitor);
return rc;
- }
-
- // set up local socket pair with the parent process
- // needs to be a socket (not a pipe) since we're going to attach a BPF to it.
- rc = socketpair( AF_LOCAL, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, socket_fd );
- if( rc < 0 ) {
-
+ }
+ // set up local socket pair with the parent process
+ // needs to be a socket (not a pipe) since we're going to attach a BPF to it.
+ rc = socketpair (AF_LOCAL, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, 0,
+ socket_fd);
+ if (rc < 0)
+ {
+
rc = -errno;
- log_error("socketpair(AF_LOCAL, SOCK_RAW|SOCK_CLOEXEC, 0) rc = %d", rc );
-
- udev_monitor_fs_destroy( monitor );
+ log_error
+ ("socketpair(AF_LOCAL, SOCK_RAW|SOCK_CLOEXEC, 0) rc = %d", rc);
+
+ udev_monitor_fs_destroy (monitor);
return rc;
- }
-
- monitor->sock = socket_fd[0]; // receiving end
- monitor->sock_fs = socket_fd[1]; // sending end
-
- // unify inotify and sock behind epoll_fd, set to poll for reading
- ev.events = EPOLLIN;
- ev.data.fd = monitor->inotify_fd;
- rc = epoll_ctl( monitor->epoll_fd, EPOLL_CTL_ADD, monitor->inotify_fd, &ev );
- if( rc != 0 ) {
-
+ }
+
+ monitor->sock = socket_fd[0]; // receiving end
+ monitor->sock_fs = socket_fd[1]; // sending end
+
+ // unify inotify and sock behind epoll_fd, set to poll for reading
+ ev.events = EPOLLIN;
+ ev.data.fd = monitor->inotify_fd;
+ rc = epoll_ctl (monitor->epoll_fd, EPOLL_CTL_ADD, monitor->inotify_fd, &ev);
+ if (rc != 0)
+ {
+
rc = -errno;
- log_error("epoll_ctl(%d on inotify_fd %d) rc = %d", monitor->epoll_fd, monitor->inotify_fd, rc );
-
- udev_monitor_fs_shutdown( monitor );
+ log_error ("epoll_ctl(%d on inotify_fd %d) rc = %d",
+ monitor->epoll_fd, monitor->inotify_fd, rc);
+
+ udev_monitor_fs_shutdown (monitor);
return rc;
- }
-
- ev.data.fd = monitor->sock;
- rc = epoll_ctl( monitor->epoll_fd, EPOLL_CTL_ADD, monitor->sock, &ev );
- if( rc != 0 ) {
-
+ }
+
+ ev.data.fd = monitor->sock;
+ rc = epoll_ctl (monitor->epoll_fd, EPOLL_CTL_ADD, monitor->sock, &ev);
+ if (rc != 0)
+ {
+
rc = -errno;
- log_error("epoll_ctl(%d on inotify_fd %d) rc = %d", monitor->sock, monitor->sock, rc );
-
- udev_monitor_fs_shutdown( monitor );
+ log_error ("epoll_ctl(%d on inotify_fd %d) rc = %d",
+ monitor->sock, monitor->sock, rc);
+
+ udev_monitor_fs_shutdown (monitor);
return rc;
- }
-
- monitor->pid = getpid();
-
- return rc;
-}
+ }
+ monitor->pid = getpid ();
+
+ return rc;
+}
// shut down a monitor's filesystem-specific state
// not much we can do if any shutdown step fails, so try them all
-int udev_monitor_fs_shutdown( struct udev_monitor* monitor ) {
-
- int rc = 0;
-
- // stop tracking this monitor
- udev_monitor_unregister( monitor );
-
- if( monitor->sock >= 0 ) {
- rc = shutdown( monitor->sock, SHUT_RDWR );
- if( rc < 0 ) {
- rc = -errno;
- log_error("shutdown(socket %d) rc = %d", monitor->sock, rc );
- }
- }
-
- if( monitor->sock_fs >= 0 ) {
- rc = shutdown( monitor->sock_fs, SHUT_RDWR );
- if( rc < 0 ) {
- rc = -errno;
- log_error("shutdown(socket %d) rc = %d", monitor->sock_fs, rc );
- }
- }
-
- if( monitor->sock >= 0 ) {
- rc = close( monitor->sock );
- if( rc < 0 ) {
- rc = -errno;
- log_error("close(socket %d) rc = %d", monitor->sock, rc );
- }
- else {
- monitor->sock = -1;
- }
- }
-
- if( monitor->sock_fs >= 0 ) {
- rc = close( monitor->sock_fs );
- if( rc < 0 ) {
- rc = -errno;
- log_error("close(socket %d) rc = %d", monitor->sock_fs, rc );
- }
- else {
- monitor->sock_fs = -1;
- }
- }
-
- if( monitor->epoll_fd >= 0 ) {
- rc = close( monitor->epoll_fd );
- if( rc < 0 ) {
- rc = -errno;
- log_error("close(epoll_fd %d) rc = %d", monitor->epoll_fd, rc );
- }
- else {
- monitor->epoll_fd = -1;
- }
- }
-
- if( monitor->events_wd >= 0 ) {
-
- if( monitor->inotify_fd >= 0 ) {
- rc = inotify_rm_watch( monitor->inotify_fd, monitor->events_wd );
- if( rc < 0 ) {
- rc = -errno;
- log_error("close(events_wd %d) rc = %d", monitor->events_wd, rc );
- }
- else {
- monitor->events_wd = -1;
- }
- }
- }
- if( monitor->inotify_fd >= 0 ) {
- rc = close( monitor->inotify_fd );
- if( rc < 0 ) {
- rc = -errno;
- log_error("close(inotify_fd %d) rc = %d", monitor->inotify_fd, rc );
- }
- else {
- monitor->inotify_fd = -1;
- }
- }
-
- return rc;
-}
+int
+udev_monitor_fs_shutdown (struct udev_monitor *monitor)
+{
+
+ int rc = 0;
+
+ // stop tracking this monitor
+ udev_monitor_unregister (monitor);
+
+ if (monitor->sock >= 0)
+ {
+ rc = shutdown (monitor->sock, SHUT_RDWR);
+ if (rc < 0)
+ {
+ rc = -errno;
+ log_error ("shutdown(socket %d) rc = %d", monitor->sock, rc);
+ }
+ }
+
+ if (monitor->sock_fs >= 0)
+ {
+ rc = shutdown (monitor->sock_fs, SHUT_RDWR);
+ if (rc < 0)
+ {
+ rc = -errno;
+ log_error ("shutdown(socket %d) rc = %d", monitor->sock_fs, rc);
+ }
+ }
+ if (monitor->sock >= 0)
+ {
+ rc = close (monitor->sock);
+ if (rc < 0)
+ {
+ rc = -errno;
+ log_error ("close(socket %d) rc = %d", monitor->sock, rc);
+ }
+ else
+ {
+ monitor->sock = -1;
+ }
+ }
+
+ if (monitor->sock_fs >= 0)
+ {
+ rc = close (monitor->sock_fs);
+ if (rc < 0)
+ {
+ rc = -errno;
+ log_error ("close(socket %d) rc = %d", monitor->sock_fs, rc);
+ }
+ else
+ {
+ monitor->sock_fs = -1;
+ }
+ }
+
+ if (monitor->epoll_fd >= 0)
+ {
+ rc = close (monitor->epoll_fd);
+ if (rc < 0)
+ {
+ rc = -errno;
+ log_error ("close(epoll_fd %d) rc = %d", monitor->epoll_fd, rc);
+ }
+ else
+ {
+ monitor->epoll_fd = -1;
+ }
+ }
+
+ if (monitor->events_wd >= 0)
+ {
+
+ if (monitor->inotify_fd >= 0)
+ {
+ rc = inotify_rm_watch (monitor->inotify_fd, monitor->events_wd);
+ if (rc < 0)
+ {
+ rc = -errno;
+ log_error ("close(events_wd %d) rc = %d",
+ monitor->events_wd, rc);
+ }
+ else
+ {
+ monitor->events_wd = -1;
+ }
+ }
+ }
+ if (monitor->inotify_fd >= 0)
+ {
+ rc = close (monitor->inotify_fd);
+ if (rc < 0)
+ {
+ rc = -errno;
+ log_error ("close(inotify_fd %d) rc = %d", monitor->inotify_fd, rc);
+ }
+ else
+ {
+ monitor->inotify_fd = -1;
+ }
+ }
+
+ return rc;
+}
// blow away all local filesystem state for a monitor
-int udev_monitor_fs_destroy( struct udev_monitor* monitor ) {
-
- char pathbuf[ PATH_MAX+1 ];
- int dirfd = 0;
- int rc = 0;
- DIR* dirh = NULL;
- struct dirent entry;
- struct dirent* result = NULL;
- bool can_rmdir = true;
-
- // stop listening
- udev_monitor_fs_shutdown( monitor );
-
- // remove events dir contents
- dirfd = open( monitor->events_dir, O_DIRECTORY | O_CLOEXEC );
- if( dirfd < 0 ) {
-
+int
+udev_monitor_fs_destroy (struct udev_monitor *monitor)
+{
+
+ char pathbuf[PATH_MAX + 1];
+ int dirfd = 0;
+ int rc = 0;
+ DIR *dirh = NULL;
+ struct dirent entry;
+ struct dirent *result = NULL;
+ bool can_rmdir = true;
+
+ // stop listening
+ udev_monitor_fs_shutdown (monitor);
+
+ // remove events dir contents
+ dirfd = open (monitor->events_dir, O_DIRECTORY | O_CLOEXEC);
+ if (dirfd < 0)
+ {
+
rc = -errno;
- log_error("open('%s') rc = %d", monitor->events_dir, rc );
+ log_error ("open('%s') rc = %d", monitor->events_dir, rc);
return rc;
- }
-
- dirh = fdopendir( dirfd );
- if( dirh == NULL ) {
-
+ }
+
+ dirh = fdopendir (dirfd);
+ if (dirh == NULL)
+ {
+
// OOM
rc = -errno;
- close( dirfd );
+ close (dirfd);
return rc;
- }
-
- do {
-
+ }
+
+ do
+ {
+
// next entry
- rc = readdir_r( dirh, &entry, &result );
- if( rc != 0 ) {
-
- // I/O error
- log_error("readdir_r('%s') rc = %d", monitor->events_dir, rc );
- break;
- }
-
+ rc = readdir_r (dirh, &entry, &result);
+ if (rc != 0)
+ {
+
+ // I/O error
+ log_error ("readdir_r('%s') rc = %d", monitor->events_dir, rc);
+ break;
+ }
// skip . and ..
- if( strcmp( entry.d_name, "." ) == 0 || strcmp( entry.d_name, ".." ) == 0 ) {
- continue;
- }
-
+ if (strcmp (entry.d_name, ".") == 0 || strcmp (entry.d_name, "..") == 0)
+ {
+ continue;
+ }
// generate full path
- memset( pathbuf, 0, PATH_MAX+1 );
-
- snprintf( pathbuf, PATH_MAX, "%s/%s", monitor->events_dir, entry.d_name );
-
+ memset (pathbuf, 0, PATH_MAX + 1);
+
+ snprintf (pathbuf, PATH_MAX, "%s/%s", monitor->events_dir,
+ entry.d_name);
+
// optimistically remove
- if( entry.d_type == DT_DIR ) {
- rc = rmdir( pathbuf );
- }
- else {
- rc = unlink( pathbuf );
- }
-
- if( rc != 0 ) {
-
- rc = -errno;
- log_error("remove '%s' rc = %d", pathbuf, rc );
-
- can_rmdir = false;
- rc = 0;
- }
-
- } while( result != NULL );
-
- // NOTE: closes dirfd
- closedir( dirh );
-
- if( can_rmdir ) {
- rc = rmdir( monitor->events_dir );
- if( rc != 0 ) {
-
- rc = -errno;
- log_error("rmdir('%s') rc = %d\n", monitor->events_dir, rc);
- }
- }
- else {
+ if (entry.d_type == DT_DIR)
+ {
+ rc = rmdir (pathbuf);
+ }
+ else
+ {
+ rc = unlink (pathbuf);
+ }
+
+ if (rc != 0)
+ {
+
+ rc = -errno;
+ log_error ("remove '%s' rc = %d", pathbuf, rc);
+
+ can_rmdir = false;
+ rc = 0;
+ }
+
+ }
+ while (result != NULL);
+
+ // NOTE: closes dirfd
+ closedir (dirh);
+
+ if (can_rmdir)
+ {
+ rc = rmdir (monitor->events_dir);
+ if (rc != 0)
+ {
+
+ rc = -errno;
+ log_error ("rmdir('%s') rc = %d\n", monitor->events_dir, rc);
+ }
+ }
+ else
+ {
// let the caller know...
rc = -ENOTEMPTY;
- }
-
- return rc;
-}
+ }
+ return rc;
+}
// thread-safe and async-safe int to string for base 10
-void itoa10_safe( int val, char* str ) {
-
- int rc = 0;
- int i = 0;
- int len = 0;
- int j = 0;
- bool neg = false;
-
- // sign check
- if( val < 0 ) {
+void
+itoa10_safe (int val, char *str)
+{
+
+ int rc = 0;
+ int i = 0;
+ int len = 0;
+ int j = 0;
+ bool neg = false;
+
+ // sign check
+ if (val < 0)
+ {
val = -val;
neg = true;
- }
-
- // consume, lowest-order to highest-order
- if( val == 0 ) {
+ }
+ // consume, lowest-order to highest-order
+ if (val == 0)
+ {
str[i] = '0';
i++;
- }
- else {
- while( val > 0 ) {
-
- int r = val % 10;
-
- str[i] = '0' + r;
- i++;
-
- val /= 10;
- }
- }
-
- if( neg ) {
-
+ }
+ else
+ {
+ while (val > 0)
+ {
+
+ int r = val % 10;
+
+ str[i] = '0' + r;
+ i++;
+
+ val /= 10;
+ }
+ }
+
+ if (neg)
+ {
+
str[i] = '-';
i++;
- }
-
- len = i;
- i--;
-
- // reverse order to get the number
- while( j < i ) {
-
+ }
+
+ len = i;
+ i--;
+
+ // reverse order to get the number
+ while (j < i)
+ {
+
char tmp = *(str + i);
*(str + i) = *(str + j);
*(str + j) = tmp;
-
+
j++;
i--;
- }
-
- str[len] = '\0';
+ }
+
+ str[len] = '\0';
}
// path to a named event for this process to consume
// pathbuf must have at least PATH_MAX bytes
// NOTE: must be async-safe, since it's used in a pthread_atfork() callback
-static int udev_monitor_fs_events_path( char const* name, char* pathbuf, int nonce ) {
-
- // do the equivalent of:
- // snprintf( pathbuf, PATH_MAX, UDEV_FS_EVENTS_DIR "/libudev-%d-%d/%s", getpid(), nonce, name );
-
- char pidbuf[10];
- pidbuf[9] = 0;
+static int
+udev_monitor_fs_events_path (char const *name, char *pathbuf, int nonce)
+{
- char nonce_buf[50];
- nonce_buf[49] = 0;
-
- pid_t pid = getpid();
-
- itoa10_safe( pid, pidbuf );
- itoa10_safe( nonce, nonce_buf );
-
- size_t pidbuf_len = strnlen(pidbuf, 10);
- size_t nonce_buf_len = strnlen( nonce_buf, 50 );
- size_t prefix_len = strlen( UDEV_FS_EVENTS_DIR );
- size_t dirname_prefix_len = strlen( "/libudev-" );
- int off = 0;
-
- memcpy( pathbuf, UDEV_FS_EVENTS_DIR, prefix_len );
- off += prefix_len;
-
- memcpy( pathbuf + off, "/libudev-", dirname_prefix_len );
- off += dirname_prefix_len;
-
- memcpy( pathbuf + off, pidbuf, pidbuf_len );
- off += pidbuf_len;
+ // do the equivalent of:
+ // snprintf( pathbuf, PATH_MAX, UDEV_FS_EVENTS_DIR "/libudev-%d-%d/%s", getpid(), nonce, name );
- memcpy( pathbuf + off, "-", 1 );
- off += 1;
+ char pidbuf[10];
+ pidbuf[9] = 0;
- memcpy( pathbuf + off, nonce_buf, nonce_buf_len );
- off += nonce_buf_len;
-
- pathbuf[off] = '/';
- off++;
-
- memcpy( pathbuf + off, name, strlen(name) );
- off += strlen(name);
-
- pathbuf[off] = '\0';
-
- return off + strlen(name);
+ char nonce_buf[50];
+ nonce_buf[49] = 0;
+
+ pid_t pid = getpid ();
+
+ itoa10_safe (pid, pidbuf);
+ itoa10_safe (nonce, nonce_buf);
+
+ size_t pidbuf_len = strnlen (pidbuf, 10);
+ size_t nonce_buf_len = strnlen (nonce_buf, 50);
+ size_t prefix_len = strlen (UDEV_FS_EVENTS_DIR);
+ size_t dirname_prefix_len = strlen ("/libudev-");
+ int off = 0;
+
+ memcpy (pathbuf, UDEV_FS_EVENTS_DIR, prefix_len);
+ off += prefix_len;
+
+ memcpy (pathbuf + off, "/libudev-", dirname_prefix_len);
+ off += dirname_prefix_len;
+
+ memcpy (pathbuf + off, pidbuf, pidbuf_len);
+ off += pidbuf_len;
+
+ memcpy (pathbuf + off, "-", 1);
+ off += 1;
+
+ memcpy (pathbuf + off, nonce_buf, nonce_buf_len);
+ off += nonce_buf_len;
+
+ pathbuf[off] = '/';
+ off++;
+
+ memcpy (pathbuf + off, name, strlen (name));
+ off += strlen (name);
+
+ pathbuf[off] = '\0';
+
+ return off + strlen (name);
}
// send the contents of a file containing a serialized packet to the libudev client:
@@ -769,220 +880,252 @@ static int udev_monitor_fs_events_path( char const* name, char* pathbuf, int non
// return -EBADMSG if the file is invalid
// return -EAGAIN if we'd block on send
// TODO: can we use sendfile(2)?
-static int udev_monitor_fs_push_event( int fd, struct udev_monitor* monitor ) {
-
- int rc = 0;
- off_t len = 0;
- size_t hdrlen = 0;
- char buf[8192];
- struct stat sb;
- struct msghdr msg;
- struct iovec iov;
- struct udev_device* dev = NULL;
- size_t i = 0;
-
- memset( &msg, 0, sizeof(struct msghdr) );
- memset( &iov, 0, sizeof(struct iovec) );
-
- // first, get the size
- rc = fstat( fd, &sb );
- if( rc < 0 ) {
-
+static int
+udev_monitor_fs_push_event (int fd, struct udev_monitor *monitor)
+{
+
+ int rc = 0;
+ off_t len = 0;
+ size_t hdrlen = 0;
+ char buf[8192];
+ struct stat sb;
+ struct msghdr msg;
+ struct iovec iov;
+ struct udev_device *dev = NULL;
+ size_t i = 0;
+
+ memset (&msg, 0, sizeof (struct msghdr));
+ memset (&iov, 0, sizeof (struct iovec));
+
+ // first, get the size
+ rc = fstat (fd, &sb);
+ if (rc < 0)
+ {
+
rc = -errno;
- log_error("fstat(%d) rc = %d", fd, rc );
+ log_error ("fstat(%d) rc = %d", fd, rc);
return rc;
- }
-
- if( sb.st_size >= 8192 ) {
-
+ }
+
+ if (sb.st_size >= 8192)
+ {
+
rc = -EMSGSIZE;
return rc;
- }
-
- rc = udev_read_uninterrupted( fd, buf, sb.st_size );
- if( rc < 0 ) {
-
- log_error("udev_read_uninterrupted(%d) rc = %d", fd, rc );
+ }
+
+ rc = udev_read_uninterrupted (fd, buf, sb.st_size);
+ if (rc < 0)
+ {
+
+ log_error ("udev_read_uninterrupted(%d) rc = %d", fd, rc);
return rc;
- }
-
- // replace all '\n' with '\0', in case the caller wrote
- // the file line by line.
- for( i = 0; i < sb.st_size; i++ ) {
-
- if( buf[i] == '\n' ) {
- buf[i] = '\0';
- }
- }
-
- // should be a uevent packet, and should start with [add|change|move|remove]@[devpath]\0
- hdrlen = strnlen( buf, sb.st_size ) + 1;
- if( hdrlen < sizeof("a@/d") || hdrlen >= sb.st_size ) {
-
- log_error("invalid message header: length = %zu, message length = %zd", hdrlen, sb.st_size );
+ }
+ // replace all '\n' with '\0', in case the caller wrote
+ // the file line by line.
+ for (i = 0; i < sb.st_size; i++)
+ {
+
+ if (buf[i] == '\n')
+ {
+ buf[i] = '\0';
+ }
+ }
+
+ // should be a uevent packet, and should start with [add|change|move|remove]@[devpath]\0
+ hdrlen = strnlen (buf, sb.st_size) + 1;
+ if (hdrlen < sizeof ("a@/d") || hdrlen >= sb.st_size)
+ {
+
+ log_error
+ ("invalid message header: length = %zu, message length = %zd",
+ hdrlen, sb.st_size);
return -EBADMSG;
- }
-
- if( strstr( buf, "@/" ) == NULL ) {
-
+ }
+
+ if (strstr (buf, "@/") == NULL)
+ {
+
// invalid header
- log_error("%s", "invalid message header: missing '@' directive" );
+ log_error ("%s", "invalid message header: missing '@' directive");
return -EBADMSG;
- }
-
- // make a udev device
- dev = udev_device_new_from_nulstr( monitor->udev, &buf[hdrlen], sb.st_size - hdrlen );
- if( dev == NULL ) {
-
+ }
+ // make a udev device
+ dev =
+ udev_device_new_from_nulstr (monitor->udev, &buf[hdrlen],
+ sb.st_size - hdrlen);
+ if (dev == NULL)
+ {
+
rc = -errno;
- log_error("udev_device_new_from_nulstr() rc = %d", rc);
-
+ log_error ("udev_device_new_from_nulstr() rc = %d", rc);
+
return rc;
- }
-
- // send it along
- // TODO: sendfile(2)?
- rc = udev_monitor_send_device( monitor, NULL, dev );
- if( rc < 0 ) {
-
- log_error("udev_monitor_send_device rc = %d", rc );
- }
- else {
-
+ }
+ // send it along
+ // TODO: sendfile(2)?
+ rc = udev_monitor_send_device (monitor, NULL, dev);
+ if (rc < 0)
+ {
+
+ log_error ("udev_monitor_send_device rc = %d", rc);
+ }
+ else
+ {
+
rc = 0;
- }
-
- udev_device_unref( dev );
- return rc;
-}
+ }
+ udev_device_unref (dev);
+ return rc;
+}
// reset the oneshot inotify watch, so it will trip on the next create.
// consume pending events, if there are any, and re-watch the directory.
// if the pid has changed since last time, watch the new directory.
// return 0 on success
// return negative on error (errno)
-static int udev_monitor_fs_watch_reset( struct udev_monitor* monitor ) {
-
- int rc = 0;
- bool inotify_triggerred = false; // was inotify triggerred?
- char buf[4096] __attribute__ ((aligned(__alignof__(struct inotify_event)))); // see inotify(7)
- struct pollfd pfd[1];
-
- pfd[0].fd = monitor->inotify_fd;
- pfd[0].events = POLLIN;
-
- // reset the watch by consuming all its events (should be at most one)
- while( 1 ) {
-
+static int
+udev_monitor_fs_watch_reset (struct udev_monitor *monitor)
+{
+
+ int rc = 0;
+ bool inotify_triggerred = false; // was inotify triggerred?
+ char buf[4096] __attribute__ ((aligned (__alignof__ (struct inotify_event)))); // see inotify(7)
+ struct pollfd pfd[1];
+
+ pfd[0].fd = monitor->inotify_fd;
+ pfd[0].events = POLLIN;
+
+ // reset the watch by consuming all its events (should be at most one)
+ while (1)
+ {
+
// do we have data?
- rc = poll( pfd, 1, 0 );
- if( rc <= 0 ) {
-
- // out of data, or error
- if( rc < 0 ) {
-
- rc = -errno;
- if( rc == -EINTR ) {
-
- // shouldn't really happen since the timeout for poll is zero,
- // but you never know...
- continue;
- }
-
- log_error("poll(%d) rc = %d\n", monitor->inotify_fd, rc );
- rc = 0;
- }
-
- break;
- }
-
+ rc = poll (pfd, 1, 0);
+ if (rc <= 0)
+ {
+
+ // out of data, or error
+ if (rc < 0)
+ {
+
+ rc = -errno;
+ if (rc == -EINTR)
+ {
+
+ // shouldn't really happen since the timeout for poll is zero,
+ // but you never know...
+ continue;
+ }
+
+ log_error ("poll(%d) rc = %d\n", monitor->inotify_fd, rc);
+ rc = 0;
+ }
+
+ break;
+ }
// at least one event remaining
// consume it
- rc = read( monitor->inotify_fd, buf, 4096 );
- if( rc == 0 ) {
- break;
- }
-
- if( rc < 0 ) {
-
- rc = -errno;
-
- if( rc == -EINTR ) {
- continue;
- }
- else if( rc == -EAGAIN || rc == -EWOULDBLOCK ) {
- rc = 0;
- break;
- }
- }
-
+ rc = read (monitor->inotify_fd, buf, 4096);
+ if (rc == 0)
+ {
+ break;
+ }
+
+ if (rc < 0)
+ {
+
+ rc = -errno;
+
+ if (rc == -EINTR)
+ {
+ continue;
+ }
+ else if (rc == -EAGAIN || rc == -EWOULDBLOCK)
+ {
+ rc = 0;
+ break;
+ }
+ }
// got one event
inotify_triggerred = true;
- }
+ }
+
+ // has the PID changed?
+ // need to regenerate events path
+ if (getpid () != monitor->pid)
+ {
+
+ log_trace ("Switch PID from %d to %d", monitor->pid, getpid ());
+
+ udev_monitor_fs_events_path ("", monitor->events_dir, monitor->slot);
+
+ rc = mkdir (monitor->events_dir, 0700);
+ if (rc != 0)
+ {
+
+ rc = -errno;
+ if (rc != -EEXIST)
+ {
+
+ log_error ("mkdir('%s') rc = %d\n", monitor->events_dir, rc);
+ return rc;
+ }
+ else
+ {
+ rc = 0;
+ }
+ }
+
+ monitor->events_wd =
+ inotify_add_watch (monitor->inotify_fd, monitor->events_dir,
+ UDEV_FS_WATCH_DIR_FLAGS);
+ if (monitor->events_wd < 0)
+ {
+
+ rc = -errno;
+
+ log_error ("inotify_add_watch('%s') rc = %d\n",
+ monitor->events_dir, rc);
+ return rc;
+ }
+
+ monitor->pid = getpid ();
-
- // has the PID changed?
- // need to regenerate events path
- if( getpid() != monitor->pid ) {
-
- log_trace("Switch PID from %d to %d", monitor->pid, getpid());
-
- udev_monitor_fs_events_path( "", monitor->events_dir, monitor->slot );
-
- rc = mkdir( monitor->events_dir, 0700 );
- if( rc != 0 ) {
-
- rc = -errno;
- if( rc != -EEXIST ) {
-
- log_error("mkdir('%s') rc = %d\n", monitor->events_dir, rc );
- return rc;
- }
- else {
- rc = 0;
- }
- }
-
- monitor->events_wd = inotify_add_watch( monitor->inotify_fd, monitor->events_dir, UDEV_FS_WATCH_DIR_FLAGS );
- if( monitor->events_wd < 0 ) {
-
- rc = -errno;
-
- log_error("inotify_add_watch('%s') rc = %d\n", monitor->events_dir, rc );
- return rc;
- }
-
- monitor->pid = getpid();
-
// TODO: what about events that the child was supposed to receive?
// the parent forks, receives one or more events, and the child wakes up, and will miss them
// if we only do the above.
// we need to (try to) consume them here
- }
+ }
+
+ rc = inotify_add_watch (monitor->inotify_fd, monitor->events_dir,
+ UDEV_FS_WATCH_DIR_FLAGS);
+ if (rc < 0)
+ {
- rc = inotify_add_watch( monitor->inotify_fd, monitor->events_dir, UDEV_FS_WATCH_DIR_FLAGS );
- if( rc < 0 ) {
-
rc = -errno;
- log_error("inotify_add_watch(%d) rc = %d", monitor->inotify_fd, rc );
- }
-
- return rc;
+ log_error ("inotify_add_watch(%d) rc = %d", monitor->inotify_fd, rc);
+ }
+
+ return rc;
}
// scandir: skip . and ..
-static int udev_monitor_fs_scandir_filter( const struct dirent* dent ) {
-
- if( strcmp( dent->d_name, "." ) == 0 || strcmp( dent->d_name, ".." ) == 0 ) {
+static int
+udev_monitor_fs_scandir_filter (const struct dirent *dent)
+{
+
+ if (strcmp (dent->d_name, ".") == 0 || strcmp (dent->d_name, "..") == 0)
+ {
return 0;
- }
- else {
+ }
+ else
+ {
return 1;
- }
+ }
}
-
// push as many available events from our filesystem buffer of events off to the monitor's socketpair.
// the order is determined lexicographically (i.e. we assume that whatever is writing events is naming them in
// a monotonically increasing order, such as e.g. the SEQNUM field)
@@ -992,307 +1135,378 @@ static int udev_monitor_fs_scandir_filter( const struct dirent* dent ) {
// return -errno if we can't re-watch the directory
// NOTE: this method should only be used if the underlying filesystem holding the events can't help us preserve the order.
// NOTE: not thread-safe
-int udev_monitor_fs_push_events( struct udev_monitor* monitor ) {
-
- char pathbuf[ PATH_MAX+1 ];
- int dirfd = -1;
- int fd = -1;
- int rc = 0;
- int num_events = 0;
- int num_valid_events = 0;
- int num_sent = 0;
- struct dirent** events = NULL; // names of events to buffer
- int i = 0;
-
- // reset the watch on this directory, and ensure we're watching the right one.
- rc = udev_monitor_fs_watch_reset( monitor );
- if( rc < 0 ) {
-
- log_error("Failed to re-watch '%s', rc = %d", monitor->events_dir, rc );
+int
+udev_monitor_fs_push_events (struct udev_monitor *monitor)
+{
+
+ char pathbuf[PATH_MAX + 1];
+ int dirfd = -1;
+ int fd = -1;
+ int rc = 0;
+ int num_events = 0;
+ int num_valid_events = 0;
+ int num_sent = 0;
+ struct dirent **events = NULL; // names of events to buffer
+ int i = 0;
+
+ // reset the watch on this directory, and ensure we're watching the right one.
+ rc = udev_monitor_fs_watch_reset (monitor);
+ if (rc < 0)
+ {
+
+ log_error ("Failed to re-watch '%s', rc = %d", monitor->events_dir, rc);
goto udev_monitor_fs_push_events_cleanup;
- }
-
- // find new events...
- dirfd = open( monitor->events_dir, O_DIRECTORY | O_CLOEXEC );
- if( dirfd < 0 ) {
-
+ }
+ // find new events...
+ dirfd = open (monitor->events_dir, O_DIRECTORY | O_CLOEXEC);
+ if (dirfd < 0)
+ {
+
rc = -errno;
- log_error("open('%s') rc = %d", monitor->events_dir, rc );
+ log_error ("open('%s') rc = %d", monitor->events_dir, rc);
goto udev_monitor_fs_push_events_cleanup;
- }
-
- num_events = scandirat( dirfd, ".", &events, udev_monitor_fs_scandir_filter, alphasort );
-
- if( num_events < 0 ) {
-
+ }
+
+ num_events =
+ scandirat (dirfd, ".", &events, udev_monitor_fs_scandir_filter,
+ alphasort);
+
+ if (num_events < 0)
+ {
+
rc = -errno;
- log_error("scandir('%s') rc = %d", monitor->events_dir, rc );
+ log_error ("scandir('%s') rc = %d", monitor->events_dir, rc);
goto udev_monitor_fs_push_events_cleanup;
- }
-
-
- if( num_events == 0 ) {
-
+ }
+
+ if (num_events == 0)
+ {
+
// got nothing
rc = -ENODATA;
goto udev_monitor_fs_push_events_cleanup;
- }
-
- num_valid_events = num_events;
-
- // send them all off!
- for( i = 0; i < num_events; i++ ) {
-
- snprintf( pathbuf, PATH_MAX, "%s/%s", monitor->events_dir, events[i]->d_name );
-
- fd = open( pathbuf, O_RDONLY | O_CLOEXEC );
- if( fd < 0 ) {
-
- rc = -errno;
- log_error("cannot open event: open('%s') rc = %d", pathbuf, rc );
-
- // we consider it more important to preserve order and drop events
- // than to try to resend later.
- unlink( pathbuf );
- }
- else {
-
- // propagate to the monitor's socket
- rc = udev_monitor_fs_push_event( fd, monitor );
-
- // garbage-collect
- close( fd );
- unlink( pathbuf );
-
- if( rc == -EBADMSG || rc == -EMSGSIZE ) {
-
- // invalid message anyway
- rc = 0;
- num_valid_events--;
- continue;
- }
-
- else if( rc < 0 ) {
-
- if( rc != -EAGAIN ) {
-
- // socket-level error
- log_error("failed to push event '%s', rc = %d", pathbuf, rc );
- break;
- }
- else {
-
- // sent as many as we could
- rc = 0;
- break;
- }
- }
- else if( rc == 0 ) {
-
- num_sent++;
- }
- }
- }
-
+ }
+
+ num_valid_events = num_events;
+
+ // send them all off!
+ for (i = 0; i < num_events; i++)
+ {
+
+ snprintf (pathbuf, PATH_MAX, "%s/%s", monitor->events_dir,
+ events[i]->d_name);
+
+ fd = open (pathbuf, O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
+ {
+
+ rc = -errno;
+ log_error ("cannot open event: open('%s') rc = %d", pathbuf, rc);
+
+ // we consider it more important to preserve order and drop events
+ // than to try to resend later.
+ unlink (pathbuf);
+ }
+ else
+ {
+
+ // propagate to the monitor's socket
+ rc = udev_monitor_fs_push_event (fd, monitor);
+
+ // garbage-collect
+ close (fd);
+ unlink (pathbuf);
+
+ if (rc == -EBADMSG || rc == -EMSGSIZE)
+ {
+
+ // invalid message anyway
+ rc = 0;
+ num_valid_events--;
+ continue;
+ }
+
+ else if (rc < 0)
+ {
+
+ if (rc != -EAGAIN)
+ {
+
+ // socket-level error
+ log_error
+ ("failed to push event '%s', rc = %d", pathbuf, rc);
+ break;
+ }
+ else
+ {
+
+ // sent as many as we could
+ rc = 0;
+ break;
+ }
+ }
+ else if (rc == 0)
+ {
+
+ num_sent++;
+ }
+ }
+ }
+
udev_monitor_fs_push_events_cleanup:
-
- if( dirfd >= 0 ) {
- close( dirfd );
- }
-
- if( events != NULL ) {
- for( i = 0; i < num_events; i++ ) {
-
- if( events[i] != NULL ) {
- free( events[i] );
- events[i] = NULL;
- }
- }
-
- free( events );
- }
-
- if( num_sent == 0 && num_valid_events > 0 ) {
-
+
+ if (dirfd >= 0)
+ {
+ close (dirfd);
+ }
+
+ if (events != NULL)
+ {
+ for (i = 0; i < num_events; i++)
+ {
+
+ if (events[i] != NULL)
+ {
+ free (events[i]);
+ events[i] = NULL;
+ }
+ }
+
+ free (events);
+ }
+
+ if (num_sent == 0 && num_valid_events > 0)
+ {
+
// there are pending events, but we couldn't push any.
rc = -EAGAIN;
- }
-
- return rc;
-}
+ }
+ return rc;
+}
-#ifdef TEST
+#ifdef TEST
#include "libudev.h"
-int main( int argc, char** argv ) {
-
- int rc = 0;
- char pathbuf[PATH_MAX+1];
- struct udev* udev_client = NULL;
- struct udev_monitor* monitor = NULL;
- int monitor_fd = 0;
- struct udev_device* dev = NULL;
- struct pollfd pfd[1];
- int num_events = INT_MAX;
- int num_forks = 0;
-
- // usage: $0 [num events to process [num times to fork]]
- if( argc > 1 ) {
- char* tmp = NULL;
- num_events = (int)strtol( argv[1], &tmp, 10 );
- if( tmp == argv[1] || *tmp != '\0' ) {
- fprintf(stderr, "Usage: %s [number of events to process [number of times to fork]]\n", argv[0] );
- exit(1);
- }
-
- if( argc > 2 ) {
-
- num_forks = (int)strtol( argv[2], &tmp, 10 );
- if( tmp == argv[2] || *tmp != '\0' ) {
- fprintf(stderr, "Usage: %s [number of events to process [number of times to fork]]\n", argv[0] );
- exit(1);
- }
- }
- }
-
- // make sure events dir exists
- log_trace("events directory '%s'", UDEV_FS_EVENTS_DIR);
-
- rc = mkdir( UDEV_FS_EVENTS_DIR, 0700 );
- if( rc != 0 ) {
-
+int
+main (int argc, char **argv)
+{
+
+ int rc = 0;
+ char pathbuf[PATH_MAX + 1];
+ struct udev *udev_client = NULL;
+ struct udev_monitor *monitor = NULL;
+ int monitor_fd = 0;
+ struct udev_device *dev = NULL;
+ struct pollfd pfd[1];
+ int num_events = INT_MAX;
+ int num_forks = 0;
+
+ // usage: $0 [num events to process [num times to fork]]
+ if (argc > 1)
+ {
+ char *tmp = NULL;
+ num_events = (int) strtol (argv[1], &tmp, 10);
+ if (tmp == argv[1] || *tmp != '\0')
+ {
+ fprintf (stderr,
+ "Usage: %s [number of events to process [number of times to fork]]\n",
+ argv[0]);
+ exit (1);
+ }
+
+ if (argc > 2)
+ {
+
+ num_forks = (int) strtol (argv[2], &tmp, 10);
+ if (tmp == argv[2] || *tmp != '\0')
+ {
+ fprintf (stderr,
+ "Usage: %s [number of events to process [number of times to fork]]\n",
+ argv[0]);
+ exit (1);
+ }
+ }
+ }
+ // make sure events dir exists
+ log_trace ("events directory '%s'", UDEV_FS_EVENTS_DIR);
+
+ rc = mkdir (UDEV_FS_EVENTS_DIR, 0700);
+ if (rc != 0)
+ {
+
rc = -errno;
- if( rc != -EEXIST ) {
- log_error("mkdir('%s') rc = %d", UDEV_FS_EVENTS_DIR, rc );
- exit(1);
- }
- }
-
- udev_monitor_fs_events_path( "", pathbuf, 0 );
-
- printf("Watching '%s'\n", pathbuf );
-
- udev_client = udev_new();
- if( udev_client == NULL ) {
-
+ if (rc != -EEXIST)
+ {
+ log_error ("mkdir('%s') rc = %d", UDEV_FS_EVENTS_DIR, rc);
+ exit (1);
+ }
+ }
+
+ udev_monitor_fs_events_path ("", pathbuf, 0);
+
+ printf ("Watching '%s'\n", pathbuf);
+
+ udev_client = udev_new ();
+ if (udev_client == NULL)
+ {
+
// OOM
- exit(2);
- }
-
- monitor = udev_monitor_new_from_netlink( udev_client, "udev" );
- if( monitor == NULL ) {
-
+ exit (2);
+ }
+
+ monitor = udev_monitor_new_from_netlink (udev_client, "udev");
+ if (monitor == NULL)
+ {
+
// OOM or error
- udev_unref( udev_client );
- exit(2);
- }
-
- printf("Press Ctrl-C to quit\n");
-
- monitor_fd = udev_monitor_get_fd( monitor );
- if( monitor_fd < 0 ) {
-
+ udev_unref (udev_client);
+ exit (2);
+ }
+
+ printf ("Press Ctrl-C to quit\n");
+
+ monitor_fd = udev_monitor_get_fd (monitor);
+ if (monitor_fd < 0)
+ {
+
rc = -errno;
- log_error("udev_monitor_get_fd rc = %d\n", rc );
- exit(3);
- }
-
- pfd[0].fd = monitor_fd;
- pfd[0].events = POLLIN;
-
- while( num_events > 0 ) {
-
+ log_error ("udev_monitor_get_fd rc = %d\n", rc);
+ exit (3);
+ }
+
+ pfd[0].fd = monitor_fd;
+ pfd[0].events = POLLIN;
+
+ while (num_events > 0)
+ {
+
// wait for the next device
- rc = poll( pfd, 1, -1 );
- if( rc < 0 ) {
-
- log_error("poll(%d) rc = %d\n", monitor_fd, rc );
- break;
- }
-
+ rc = poll (pfd, 1, -1);
+ if (rc < 0)
+ {
+
+ log_error ("poll(%d) rc = %d\n", monitor_fd, rc);
+ break;
+ }
// get devices
- while( num_events > 0 ) {
-
- dev = udev_monitor_receive_device( monitor );
- if( dev == NULL ) {
- break;
- }
-
- int pid = getpid();
- struct udev_list_entry *list_entry = NULL;
-
- printf("[%d] [%d] ACTION: '%s'\n", pid, num_events, udev_device_get_action( dev ) );
- printf("[%d] [%d] SEQNUM: %llu\n", pid, num_events, udev_device_get_seqnum( dev ) );
- printf("[%d] [%d] USEC: %llu\n", pid, num_events, udev_device_get_usec_since_initialized( dev ) );
- printf("[%d] [%d] DEVNODE: '%s'\n", pid, num_events, udev_device_get_devnode( dev ) );
- printf("[%d] [%d] DEVPATH: '%s'\n", pid, num_events, udev_device_get_devpath( dev ) );
- printf("[%d] [%d] SYSNAME: '%s'\n", pid, num_events, udev_device_get_sysname( dev ) );
- printf("[%d] [%d] SYSPATH: '%s'\n", pid, num_events, udev_device_get_syspath( dev ) );
- printf("[%d] [%d] SUBSYSTEM: '%s'\n", pid, num_events, udev_device_get_subsystem( dev ) );
- printf("[%d] [%d] DEVTYPE: '%s'\n", pid, num_events, udev_device_get_devtype( dev ) );
- printf("[%d] [%d] SYSNUM: '%s'\n", pid, num_events, udev_device_get_sysnum( dev ) );
- printf("[%d] [%d] DRIVER: '%s'\n", pid, num_events, udev_device_get_driver( dev ) );
- printf("[%d] [%d] DEVNUM: %d:%d\n", pid, num_events, major( udev_device_get_devnum( dev ) ), minor( udev_device_get_devnum( dev ) ) );
- printf("[%d] [%d] IFINDEX: '%s'\n", pid, num_events, udev_device_get_property_value( dev, "IFINDEX" ) );
- printf("[%d] [%d] DEVMODE: '%s'\n", pid, num_events, udev_device_get_property_value( dev, "DEVMODE" ) );
- printf("[%d] [%d] DEVUID: '%s'\n", pid, num_events, udev_device_get_property_value( dev, "DEVUID" ) );
- printf("[%d] [%d] DEVGID: '%s'\n", pid, num_events, udev_device_get_property_value( dev, "DEVGID" ) );
-
- list_entry = udev_device_get_devlinks_list_entry( dev );
- udev_list_entry_foreach( list_entry, udev_list_entry_get_next( list_entry )) {
-
- printf("[%d] [%d] devlink: '%s'\n", pid, num_events, udev_list_entry_get_name( list_entry ) );
- }
-
- list_entry = udev_device_get_properties_list_entry( dev );
- udev_list_entry_foreach( list_entry, udev_list_entry_get_next( list_entry )) {
-
- printf("[%d] [%d] property: '%s' = '%s'\n", pid, num_events, udev_list_entry_get_name( list_entry ), udev_list_entry_get_value( list_entry ) );
- }
-
- list_entry = udev_device_get_tags_list_entry( dev );
- udev_list_entry_foreach( list_entry, udev_list_entry_get_next( list_entry )) {
-
- printf("[%d] [%d] tag: '%s'\n", pid, num_events, udev_list_entry_get_name( list_entry ) );
- }
-
- list_entry = udev_device_get_sysattr_list_entry( dev );
- udev_list_entry_foreach( list_entry, udev_list_entry_get_next( list_entry )) {
-
- printf("[%d] [%d] sysattr: '%s'\n", pid, num_events, udev_list_entry_get_name( list_entry ) );
- }
-
- printf("\n");
-
- udev_device_unref( dev );
-
- num_events--;
- }
-
+ while (num_events > 0)
+ {
+
+ dev = udev_monitor_receive_device (monitor);
+ if (dev == NULL)
+ {
+ break;
+ }
+
+ int pid = getpid ();
+ struct udev_list_entry *list_entry = NULL;
+
+ printf ("[%d] [%d] ACTION: '%s'\n", pid, num_events,
+ udev_device_get_action (dev));
+ printf ("[%d] [%d] SEQNUM: %llu\n", pid, num_events,
+ udev_device_get_seqnum (dev));
+ printf ("[%d] [%d] USEC: %llu\n", pid, num_events,
+ udev_device_get_usec_since_initialized (dev));
+ printf ("[%d] [%d] DEVNODE: '%s'\n", pid, num_events,
+ udev_device_get_devnode (dev));
+ printf ("[%d] [%d] DEVPATH: '%s'\n", pid, num_events,
+ udev_device_get_devpath (dev));
+ printf ("[%d] [%d] SYSNAME: '%s'\n", pid, num_events,
+ udev_device_get_sysname (dev));
+ printf ("[%d] [%d] SYSPATH: '%s'\n", pid, num_events,
+ udev_device_get_syspath (dev));
+ printf ("[%d] [%d] SUBSYSTEM: '%s'\n", pid, num_events,
+ udev_device_get_subsystem (dev));
+ printf ("[%d] [%d] DEVTYPE: '%s'\n", pid, num_events,
+ udev_device_get_devtype (dev));
+ printf ("[%d] [%d] SYSNUM: '%s'\n", pid, num_events,
+ udev_device_get_sysnum (dev));
+ printf ("[%d] [%d] DRIVER: '%s'\n", pid, num_events,
+ udev_device_get_driver (dev));
+ printf ("[%d] [%d] DEVNUM: %d:%d\n", pid,
+ num_events, major (udev_device_get_devnum (dev)),
+ minor (udev_device_get_devnum (dev)));
+ printf ("[%d] [%d] IFINDEX: '%s'\n", pid, num_events,
+ udev_device_get_property_value (dev, "IFINDEX"));
+ printf ("[%d] [%d] DEVMODE: '%s'\n", pid, num_events,
+ udev_device_get_property_value (dev, "DEVMODE"));
+ printf ("[%d] [%d] DEVUID: '%s'\n", pid, num_events,
+ udev_device_get_property_value (dev, "DEVUID"));
+ printf ("[%d] [%d] DEVGID: '%s'\n", pid, num_events,
+ udev_device_get_property_value (dev, "DEVGID"));
+
+ list_entry = udev_device_get_devlinks_list_entry (dev);
+ udev_list_entry_foreach (list_entry,
+ udev_list_entry_get_next (list_entry))
+ {
+
+ printf ("[%d] [%d] devlink: '%s'\n", pid,
+ num_events, udev_list_entry_get_name (list_entry));
+ }
+
+ list_entry = udev_device_get_properties_list_entry (dev);
+ udev_list_entry_foreach (list_entry,
+ udev_list_entry_get_next (list_entry))
+ {
+
+ printf ("[%d] [%d] property: '%s' = '%s'\n",
+ pid, num_events,
+ udev_list_entry_get_name (list_entry),
+ udev_list_entry_get_value (list_entry));
+ }
+
+ list_entry = udev_device_get_tags_list_entry (dev);
+ udev_list_entry_foreach (list_entry,
+ udev_list_entry_get_next (list_entry))
+ {
+
+ printf ("[%d] [%d] tag: '%s'\n", pid,
+ num_events, udev_list_entry_get_name (list_entry));
+ }
+
+ list_entry = udev_device_get_sysattr_list_entry (dev);
+ udev_list_entry_foreach (list_entry,
+ udev_list_entry_get_next (list_entry))
+ {
+
+ printf ("[%d] [%d] sysattr: '%s'\n", pid,
+ num_events, udev_list_entry_get_name (list_entry));
+ }
+
+ printf ("\n");
+
+ udev_device_unref (dev);
+
+ num_events--;
+ }
+
// do our forks
- if( num_forks > 0 ) {
-
- num_forks--;
-
- int pid = fork();
- if( pid < 0 ) {
-
- rc = -errno;
- fprintf(stderr, "fork: %s\n", strerror( -rc ) );
- break;
- }
- else if( pid == 0 ) {
-
- printf("[%d]\n", getpid() );
- }
- }
- }
-
- udev_monitor_fs_destroy( monitor );
-
- exit(0);
+ if (num_forks > 0)
+ {
+
+ num_forks--;
+
+ int pid = fork ();
+ if (pid < 0)
+ {
+
+ rc = -errno;
+ fprintf (stderr, "fork: %s\n", strerror (-rc));
+ break;
+ }
+ else if (pid == 0)
+ {
+
+ printf ("[%d]\n", getpid ());
+ }
+ }
+ }
+
+ udev_monitor_fs_destroy (monitor);
+
+ exit (0);
}
-#endif
+#endif
diff --git a/libudev-compat/libudev-fs.h b/libudev-compat/libudev-fs.h
index 23b3f59..e5b1c51 100644
--- a/libudev-compat/libudev-fs.h
+++ b/libudev-compat/libudev-fs.h
@@ -25,17 +25,17 @@
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
-#endif
+#endif
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 700
-#endif
+#endif
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
-#ifndef _GNU_SOURCE
+#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
@@ -66,9 +66,9 @@
#include "libudev-private.h"
-int udev_monitor_fs_setup( struct udev_monitor* monitor );
-int udev_monitor_fs_destroy( struct udev_monitor* monitor );
-int udev_monitor_fs_shutdown( struct udev_monitor* monitor );
-int udev_monitor_fs_push_events( struct udev_monitor* monitor );
+int udev_monitor_fs_setup (struct udev_monitor *monitor);
+int udev_monitor_fs_destroy (struct udev_monitor *monitor);
+int udev_monitor_fs_shutdown (struct udev_monitor *monitor);
+int udev_monitor_fs_push_events (struct udev_monitor *monitor);
-#endif
\ No newline at end of file
+#endif
diff --git a/libudev-compat/libudev-hwdb.c b/libudev-compat/libudev-hwdb.c
index fb16b88..b04a437 100644
--- a/libudev-compat/libudev-hwdb.c
+++ b/libudev-compat/libudev-hwdb.c
@@ -43,13 +43,14 @@
*
* Opaque object representing the hardware database.
*/
-struct udev_hwdb {
- struct udev *udev;
- int refcount;
+struct udev_hwdb
+{
+ struct udev *udev;
+ int refcount;
- sd_hwdb *hwdb;
+ sd_hwdb *hwdb;
- struct udev_list properties_list;
+ struct udev_list properties_list;
};
/**
@@ -60,28 +61,30 @@ struct udev_hwdb {
*
* Returns: a hwdb context.
**/
-_public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) {
- _cleanup_hwdb_unref_ sd_hwdb *hwdb_internal = NULL;
- struct udev_hwdb *hwdb;
- int r;
+_public_ struct udev_hwdb *
+udev_hwdb_new (struct udev *udev)
+{
+ _cleanup_hwdb_unref_ sd_hwdb *hwdb_internal = NULL;
+ struct udev_hwdb *hwdb;
+ int r;
- assert_return(udev, NULL);
+ assert_return (udev, NULL);
- r = sd_hwdb_new(&hwdb_internal);
- if (r < 0)
- return NULL;
+ r = sd_hwdb_new (&hwdb_internal);
+ if (r < 0)
+ return NULL;
- hwdb = new0(struct udev_hwdb, 1);
- if (!hwdb)
- return NULL;
+ hwdb = new0 (struct udev_hwdb, 1);
+ if (!hwdb)
+ return NULL;
- hwdb->refcount = 1;
- hwdb->hwdb = hwdb_internal;
- hwdb_internal = NULL;
+ hwdb->refcount = 1;
+ hwdb->hwdb = hwdb_internal;
+ hwdb_internal = NULL;
- udev_list_init(udev, &hwdb->properties_list, true);
+ udev_list_init (udev, &hwdb->properties_list, true);
- return hwdb;
+ return hwdb;
}
/**
@@ -92,11 +95,13 @@ _public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) {
*
* Returns: the passed enumeration context
**/
-_public_ struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) {
- if (!hwdb)
- return NULL;
- hwdb->refcount++;
- return hwdb;
+_public_ struct udev_hwdb *
+udev_hwdb_ref (struct udev_hwdb *hwdb)
+{
+ if (!hwdb)
+ return NULL;
+ hwdb->refcount++;
+ return hwdb;
}
/**
@@ -108,16 +113,18 @@ _public_ struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb) {
*
* Returns: #NULL
**/
-_public_ struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) {
- if (!hwdb)
- return NULL;
- hwdb->refcount--;
- if (hwdb->refcount > 0)
- return NULL;
- sd_hwdb_unref(hwdb->hwdb);
- udev_list_cleanup(&hwdb->properties_list);
- free(hwdb);
- return NULL;
+_public_ struct udev_hwdb *
+udev_hwdb_unref (struct udev_hwdb *hwdb)
+{
+ if (!hwdb)
+ return NULL;
+ hwdb->refcount--;
+ if (hwdb->refcount > 0)
+ return NULL;
+ sd_hwdb_unref (hwdb->hwdb);
+ udev_list_cleanup (&hwdb->properties_list);
+ free (hwdb);
+ return NULL;
}
/**
@@ -133,22 +140,30 @@ _public_ struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) {
*
* Returns: a udev_list_entry.
*/
-_public_ struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags) {
- const char *key, *value;
-
- if (!hwdb || !modalias) {
- errno = EINVAL;
- return NULL;
- }
-
- udev_list_cleanup(&hwdb->properties_list);
-
- SD_HWDB_FOREACH_PROPERTY(hwdb->hwdb, modalias, key, value) {
- if (udev_list_entry_add(&hwdb->properties_list, key, value) == NULL) {
- errno = ENOMEM;
- return NULL;
- }
- }
-
- return udev_list_get_entry(&hwdb->properties_list);
+_public_ struct udev_list_entry *
+udev_hwdb_get_properties_list_entry (struct
+ udev_hwdb
+ *hwdb,
+ const char *modalias, unsigned int flags)
+{
+ const char *key, *value;
+
+ if (!hwdb || !modalias)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ udev_list_cleanup (&hwdb->properties_list);
+
+ SD_HWDB_FOREACH_PROPERTY (hwdb->hwdb, modalias, key, value)
+ {
+ if (udev_list_entry_add (&hwdb->properties_list, key, value) == NULL)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ }
+
+ return udev_list_get_entry (&hwdb->properties_list);
}
diff --git a/libudev-compat/libudev-list.c b/libudev-compat/libudev-list.c
index f1dd4c6..e32025d 100644
--- a/libudev-compat/libudev-list.c
+++ b/libudev-compat/libudev-list.c
@@ -46,228 +46,265 @@
* Opaque object representing one entry in a list. An entry contains
* contains a name, and optionally a value.
*/
-struct udev_list_entry {
- struct udev_list_node node;
- struct udev_list *list;
- char *name;
- char *value;
- int num;
+struct udev_list_entry
+{
+ struct udev_list_node node;
+ struct udev_list *list;
+ char *name;
+ char *value;
+ int num;
};
/* the list's head points to itself if empty */
-void udev_list_node_init(struct udev_list_node *list)
+void
+udev_list_node_init (struct udev_list_node *list)
{
- list->next = list;
- list->prev = list;
+ list->next = list;
+ list->prev = list;
}
-int udev_list_node_is_empty(struct udev_list_node *list)
+int
+udev_list_node_is_empty (struct udev_list_node *list)
{
- return list->next == list;
+ return list->next == list;
}
-static void udev_list_node_insert_between(struct udev_list_node *new,
- struct udev_list_node *prev,
- struct udev_list_node *next)
+static void
+udev_list_node_insert_between (struct udev_list_node *new,
+ struct udev_list_node *prev,
+ struct udev_list_node *next)
{
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
}
-void udev_list_node_append(struct udev_list_node *new, struct udev_list_node *list)
+void
+udev_list_node_append (struct udev_list_node *new,
+ struct udev_list_node *list)
{
- udev_list_node_insert_between(new, list->prev, list);
+ udev_list_node_insert_between (new, list->prev, list);
}
-void udev_list_node_remove(struct udev_list_node *entry)
+void
+udev_list_node_remove (struct udev_list_node *entry)
{
- struct udev_list_node *prev = entry->prev;
- struct udev_list_node *next = entry->next;
+ struct udev_list_node *prev = entry->prev;
+ struct udev_list_node *next = entry->next;
- next->prev = prev;
- prev->next = next;
+ next->prev = prev;
+ prev->next = next;
- entry->prev = NULL;
- entry->next = NULL;
+ entry->prev = NULL;
+ entry->next = NULL;
}
/* return list entry which embeds this node */
-static inline struct udev_list_entry *list_node_to_entry(struct udev_list_node *node)
+static inline struct udev_list_entry *
+list_node_to_entry (struct udev_list_node *node)
{
- return container_of(node, struct udev_list_entry, node);
+ return container_of (node, struct udev_list_entry, node);
}
-void udev_list_init(struct udev *udev, struct udev_list *list, bool unique)
+void
+udev_list_init (struct udev *udev, struct udev_list *list, bool unique)
{
- memzero(list, sizeof(struct udev_list));
- list->udev = udev;
- list->unique = unique;
- udev_list_node_init(&list->node);
+ memzero (list, sizeof (struct udev_list));
+ list->udev = udev;
+ list->unique = unique;
+ udev_list_node_init (&list->node);
}
/* insert entry into a list as the last element */
-static void udev_list_entry_append(struct udev_list_entry *new, struct udev_list *list)
+static void
+udev_list_entry_append (struct udev_list_entry *new, struct udev_list *list)
{
- /* inserting before the list head make the node the last node in the list */
- udev_list_node_insert_between(&new->node, list->node.prev, &list->node);
- new->list = list;
+ /* inserting before the list head make the node the last node in the list */
+ udev_list_node_insert_between (&new->node, list->node.prev, &list->node);
+ new->list = list;
}
/* insert entry into a list, before a given existing entry */
-static void udev_list_entry_insert_before(struct udev_list_entry *new, struct udev_list_entry *entry)
+static void
+udev_list_entry_insert_before (struct udev_list_entry *new,
+ struct udev_list_entry *entry)
{
- udev_list_node_insert_between(&new->node, entry->node.prev, &entry->node);
- new->list = entry->list;
+ udev_list_node_insert_between (&new->node, entry->node.prev, &entry->node);
+ new->list = entry->list;
}
/* binary search in sorted array */
-static int list_search(struct udev_list *list, const char *name)
+static int
+list_search (struct udev_list *list, const char *name)
{
- unsigned int first, last;
-
- first = 0;
- last = list->entries_cur;
- while (first < last) {
- unsigned int i;
- int cmp;
-
- i = (first + last)/2;
- cmp = strcmp(name, list->entries[i]->name);
- if (cmp < 0)
- last = i;
- else if (cmp > 0)
- first = i+1;
- else
- return i;
- }
-
- /* not found, return negative insertion-index+1 */
- return -(first+1);
+ unsigned int first, last;
+
+ first = 0;
+ last = list->entries_cur;
+ while (first < last)
+ {
+ unsigned int i;
+ int cmp;
+
+ i = (first + last) / 2;
+ cmp = strcmp (name, list->entries[i]->name);
+ if (cmp < 0)
+ last = i;
+ else if (cmp > 0)
+ first = i + 1;
+ else
+ return i;
+ }
+
+ /* not found, return negative insertion-index+1 */
+ return -(first + 1);
}
-struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *name, const char *value)
+struct udev_list_entry *
+udev_list_entry_add (struct udev_list *list,
+ const char *name, const char *value)
{
- struct udev_list_entry *entry;
- int i = 0;
-
- if (list->unique) {
- /* lookup existing name or insertion-index */
- i = list_search(list, name);
- if (i >= 0) {
- entry = list->entries[i];
-
- free(entry->value);
- if (value == NULL) {
- entry->value = NULL;
- return entry;
- }
- entry->value = strdup(value);
- if (entry->value == NULL)
- return NULL;
- return entry;
- }
- }
-
- /* add new name */
- entry = new0(struct udev_list_entry, 1);
- if (entry == NULL)
- return NULL;
- entry->name = strdup(name);
- if (entry->name == NULL) {
- free(entry);
- return NULL;
- }
- if (value != NULL) {
- entry->value = strdup(value);
- if (entry->value == NULL) {
- free(entry->name);
- free(entry);
- return NULL;
- }
- }
-
- if (list->unique) {
- /* allocate or enlarge sorted array if needed */
- if (list->entries_cur >= list->entries_max) {
- struct udev_list_entry **entries;
- unsigned int add;
-
- add = list->entries_max;
- if (add < 1)
- add = 64;
- entries = realloc(list->entries, (list->entries_max + add) * sizeof(struct udev_list_entry *));
- if (entries == NULL) {
- free(entry->name);
- free(entry->value);
- free(entry);
- return NULL;
- }
- list->entries = entries;
- list->entries_max += add;
- }
-
- /* the negative i returned the insertion index */
- i = (-i)-1;
-
- /* insert into sorted list */
- if ((unsigned int)i < list->entries_cur)
- udev_list_entry_insert_before(entry, list->entries[i]);
- else
- udev_list_entry_append(entry, list);
-
- /* insert into sorted array */
- memmove(&list->entries[i+1], &list->entries[i],
- (list->entries_cur - i) * sizeof(struct udev_list_entry *));
- list->entries[i] = entry;
- list->entries_cur++;
- } else {
- udev_list_entry_append(entry, list);
- }
-
- return entry;
+ struct udev_list_entry *entry;
+ int i = 0;
+
+ if (list->unique)
+ {
+ /* lookup existing name or insertion-index */
+ i = list_search (list, name);
+ if (i >= 0)
+ {
+ entry = list->entries[i];
+
+ free (entry->value);
+ if (value == NULL)
+ {
+ entry->value = NULL;
+ return entry;
+ }
+ entry->value = strdup (value);
+ if (entry->value == NULL)
+ return NULL;
+ return entry;
+ }
+ }
+
+ /* add new name */
+ entry = new0 (struct udev_list_entry, 1);
+ if (entry == NULL)
+ return NULL;
+ entry->name = strdup (name);
+ if (entry->name == NULL)
+ {
+ free (entry);
+ return NULL;
+ }
+ if (value != NULL)
+ {
+ entry->value = strdup (value);
+ if (entry->value == NULL)
+ {
+ free (entry->name);
+ free (entry);
+ return NULL;
+ }
+ }
+
+ if (list->unique)
+ {
+ /* allocate or enlarge sorted array if needed */
+ if (list->entries_cur >= list->entries_max)
+ {
+ struct udev_list_entry **entries;
+ unsigned int add;
+
+ add = list->entries_max;
+ if (add < 1)
+ add = 64;
+ entries =
+ realloc (list->entries,
+ (list->entries_max +
+ add) * sizeof (struct udev_list_entry *));
+ if (entries == NULL)
+ {
+ free (entry->name);
+ free (entry->value);
+ free (entry);
+ return NULL;
+ }
+ list->entries = entries;
+ list->entries_max += add;
+ }
+
+ /* the negative i returned the insertion index */
+ i = (-i) - 1;
+
+ /* insert into sorted list */
+ if ((unsigned int) i < list->entries_cur)
+ udev_list_entry_insert_before (entry, list->entries[i]);
+ else
+ udev_list_entry_append (entry, list);
+
+ /* insert into sorted array */
+ memmove (&list->entries[i + 1], &list->entries[i],
+ (list->entries_cur - i) * sizeof (struct udev_list_entry *));
+ list->entries[i] = entry;
+ list->entries_cur++;
+ }
+ else
+ {
+ udev_list_entry_append (entry, list);
+ }
+
+ return entry;
}
-void udev_list_entry_delete(struct udev_list_entry *entry)
+void
+udev_list_entry_delete (struct udev_list_entry *entry)
{
- if (entry->list->entries != NULL) {
- int i;
- struct udev_list *list = entry->list;
-
- /* remove entry from sorted array */
- i = list_search(list, entry->name);
- if (i >= 0) {
- memmove(&list->entries[i], &list->entries[i+1],
- ((list->entries_cur-1) - i) * sizeof(struct udev_list_entry *));
- list->entries_cur--;
- }
- }
-
- udev_list_node_remove(&entry->node);
- free(entry->name);
- free(entry->value);
- free(entry);
+ if (entry->list->entries != NULL)
+ {
+ int i;
+ struct udev_list *list = entry->list;
+
+ /* remove entry from sorted array */
+ i = list_search (list, entry->name);
+ if (i >= 0)
+ {
+ memmove (&list->entries[i], &list->entries[i + 1],
+ ((list->entries_cur - 1) -
+ i) * sizeof (struct udev_list_entry *));
+ list->entries_cur--;
+ }
+ }
+
+ udev_list_node_remove (&entry->node);
+ free (entry->name);
+ free (entry->value);
+ free (entry);
}
-void udev_list_cleanup(struct udev_list *list)
+void
+udev_list_cleanup (struct udev_list *list)
{
- struct udev_list_entry *entry_loop;
- struct udev_list_entry *entry_tmp;
-
- free(list->entries);
- list->entries = NULL;
- list->entries_cur = 0;
- list->entries_max = 0;
- udev_list_entry_foreach_safe(entry_loop, entry_tmp, udev_list_get_entry(list))
- udev_list_entry_delete(entry_loop);
+ struct udev_list_entry *entry_loop;
+ struct udev_list_entry *entry_tmp;
+
+ free (list->entries);
+ list->entries = NULL;
+ list->entries_cur = 0;
+ list->entries_max = 0;
+ udev_list_entry_foreach_safe (entry_loop, entry_tmp,
+ udev_list_get_entry (list))
+ udev_list_entry_delete (entry_loop);
}
-struct udev_list_entry *udev_list_get_entry(struct udev_list *list)
+struct udev_list_entry *
+udev_list_get_entry (struct udev_list *list)
{
- if (udev_list_node_is_empty(&list->node))
- return NULL;
- return list_node_to_entry(list->node.next);
+ if (udev_list_node_is_empty (&list->node))
+ return NULL;
+ return list_node_to_entry (list->node.next);
}
/**
@@ -278,17 +315,18 @@ struct udev_list_entry *udev_list_get_entry(struct udev_list *list)
*
* Returns: udev_list_entry, #NULL if no more entries are available.
*/
-struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry)
+struct udev_list_entry *
+udev_list_entry_get_next (struct udev_list_entry *list_entry)
{
- struct udev_list_node *next;
-
- if (list_entry == NULL)
- return NULL;
- next = list_entry->node.next;
- /* empty list or no more entries */
- if (next == &list_entry->list->node)
- return NULL;
- return list_node_to_entry(next);
+ struct udev_list_node *next;
+
+ if (list_entry == NULL)
+ return NULL;
+ next = list_entry->node.next;
+ /* empty list or no more entries */
+ if (next == &list_entry->list->node)
+ return NULL;
+ return list_node_to_entry (next);
}
/**
@@ -300,20 +338,22 @@ struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_en
*
* Returns: udev_list_entry, #NULL if no matching entry is found.
*/
-struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name)
+struct udev_list_entry *
+udev_list_entry_get_by_name (struct udev_list_entry
+ *list_entry, const char *name)
{
- int i;
+ int i;
- if (list_entry == NULL)
- return NULL;
+ if (list_entry == NULL)
+ return NULL;
- if (!list_entry->list->unique)
- return NULL;
+ if (!list_entry->list->unique)
+ return NULL;
- i = list_search(list_entry->list, name);
- if (i < 0)
- return NULL;
- return list_entry->list->entries[i];
+ i = list_search (list_entry->list, name);
+ if (i < 0)
+ return NULL;
+ return list_entry->list->entries[i];
}
/**
@@ -324,11 +364,12 @@ struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list
*
* Returns: the name string of this entry.
*/
-const char *udev_list_entry_get_name(struct udev_list_entry *list_entry)
+const char *
+udev_list_entry_get_name (struct udev_list_entry *list_entry)
{
- if (list_entry == NULL)
- return NULL;
- return list_entry->name;
+ if (list_entry == NULL)
+ return NULL;
+ return list_entry->name;
}
/**
@@ -339,23 +380,26 @@ const char *udev_list_entry_get_name(struct udev_list_entry *list_entry)
*
* Returns: the value string of this entry.
*/
-const char *udev_list_entry_get_value(struct udev_list_entry *list_entry)
+const char *
+udev_list_entry_get_value (struct udev_list_entry *list_entry)
{
- if (list_entry == NULL)
- return NULL;
- return list_entry->value;
+ if (list_entry == NULL)
+ return NULL;
+ return list_entry->value;
}
-int udev_list_entry_get_num(struct udev_list_entry *list_entry)
+int
+udev_list_entry_get_num (struct udev_list_entry *list_entry)
{
- if (list_entry == NULL)
- return -EINVAL;
- return list_entry->num;
+ if (list_entry == NULL)
+ return -EINVAL;
+ return list_entry->num;
}
-void udev_list_entry_set_num(struct udev_list_entry *list_entry, int num)
+void
+udev_list_entry_set_num (struct udev_list_entry *list_entry, int num)
{
- if (list_entry == NULL)
- return;
- list_entry->num = num;
+ if (list_entry == NULL)
+ return;
+ list_entry->num = num;
}
diff --git a/libudev-compat/libudev-monitor.c b/libudev-compat/libudev-monitor.c
index 77e682c..9aae7b6 100644
--- a/libudev-compat/libudev-monitor.c
+++ b/libudev-compat/libudev-monitor.c
@@ -44,96 +44,103 @@
#include "libudev-private.h"
#include "libudev-fs.h"
-
-enum udev_monitor_netlink_group {
- UDEV_MONITOR_NONE,
- UDEV_MONITOR_KERNEL,
- UDEV_MONITOR_UDEV,
- UDEV_MONITOR_ANY
+enum udev_monitor_netlink_group
+{
+ UDEV_MONITOR_NONE,
+ UDEV_MONITOR_KERNEL,
+ UDEV_MONITOR_UDEV,
+ UDEV_MONITOR_ANY
};
#define UDEV_MONITOR_MAGIC 0xfeedcafe
-struct udev_monitor_netlink_header {
- /* "libudev" prefix to distinguish libudev and kernel messages */
- char prefix[8];
- /*
- * magic to protect against daemon <-> library message format mismatch
- * used in the kernel from socket filter rules; needs to be stored in network order
- */
- unsigned int magic;
- /* total length of header structure known to the sender */
- unsigned int header_size;
- /* properties string buffer */
- unsigned int properties_off;
- unsigned int properties_len;
- /*
- * hashes of primary device properties strings, to let libudev subscribers
- * use in-kernel socket filters; values need to be stored in network order
- */
- unsigned int filter_subsystem_hash;
- unsigned int filter_devtype_hash;
- unsigned int filter_tag_bloom_hi;
- unsigned int filter_tag_bloom_lo;
+struct udev_monitor_netlink_header
+{
+ /* "libudev" prefix to distinguish libudev and kernel messages */
+ char prefix[8];
+ /*
+ * magic to protect against daemon <-> library message format mismatch
+ * used in the kernel from socket filter rules; needs to be stored in network order
+ */
+ unsigned int magic;
+ /* total length of header structure known to the sender */
+ unsigned int header_size;
+ /* properties string buffer */
+ unsigned int properties_off;
+ unsigned int properties_len;
+ /*
+ * hashes of primary device properties strings, to let libudev subscribers
+ * use in-kernel socket filters; values need to be stored in network order
+ */
+ unsigned int filter_subsystem_hash;
+ unsigned int filter_devtype_hash;
+ unsigned int filter_tag_bloom_hi;
+ unsigned int filter_tag_bloom_lo;
};
-static struct udev_monitor *udev_monitor_new(struct udev *udev)
+static struct udev_monitor *
+udev_monitor_new (struct udev *udev)
{
- struct udev_monitor *udev_monitor;
-
- udev_monitor = new0(struct udev_monitor, 1);
- if (udev_monitor == NULL)
- return NULL;
-
- udev_monitor->type = 0;
- udev_monitor->refcount = 1;
- udev_monitor->udev = udev;
- udev_list_init(udev, &udev_monitor->filter_subsystem_list, false);
- udev_list_init(udev, &udev_monitor->filter_tag_list, true);
- return udev_monitor;
+ struct udev_monitor *udev_monitor;
+
+ udev_monitor = new0 (struct udev_monitor, 1);
+ if (udev_monitor == NULL)
+ return NULL;
+
+ udev_monitor->type = 0;
+ udev_monitor->refcount = 1;
+ udev_monitor->udev = udev;
+ udev_list_init (udev, &udev_monitor->filter_subsystem_list, false);
+ udev_list_init (udev, &udev_monitor->filter_tag_list, true);
+ return udev_monitor;
}
-static struct udev_monitor *udev_monitor_new_from_filesystem(struct udev *udev ) {
-
- // The approach taken here is to have the device manager
- // record device events to well-known subdirectories in /dev.
- // Then, the device manager in the root context can be instructed to
- // record all relevant device events, and the admin can bind-mount
- // subdirectory trees into container contexts. In doing so, the
- // admin both controls fine-grained device information visibility
- // (through permission bits) and aggregate device visibility
- // (through bind-mounts) for both root and container contexts,
- // all without requiring extra help from the kernel. Moreover,
- // this approach is generic enough to not specific to a particular
- // kernel or device manager.
- //
- // The purpose of libudev-compat is to help would-be
- // udev listeners find and read the device information in the
- // underlying /dev filesystem.
- //
- // --Jude Nelson
-
- struct udev_monitor *udev_monitor = NULL;
- int rc = 0;
-
- if (udev == NULL) {
+static struct udev_monitor *
+udev_monitor_new_from_filesystem (struct udev *udev)
+{
+
+ // The approach taken here is to have the device manager
+ // record device events to well-known subdirectories in /dev.
+ // Then, the device manager in the root context can be instructed to
+ // record all relevant device events, and the admin can bind-mount
+ // subdirectory trees into container contexts. In doing so, the
+ // admin both controls fine-grained device information visibility
+ // (through permission bits) and aggregate device visibility
+ // (through bind-mounts) for both root and container contexts,
+ // all without requiring extra help from the kernel. Moreover,
+ // this approach is generic enough to not specific to a particular
+ // kernel or device manager.
+ //
+ // The purpose of libudev-compat is to help would-be
+ // udev listeners find and read the device information in the
+ // underlying /dev filesystem.
+ //
+ // --Jude Nelson
+
+ struct udev_monitor *udev_monitor = NULL;
+ int rc = 0;
+
+ if (udev == NULL)
+ {
return NULL;
- }
-
- udev_monitor = udev_monitor_new(udev);
- if (udev_monitor == NULL) {
+ }
+
+ udev_monitor = udev_monitor_new (udev);
+ if (udev_monitor == NULL)
+ {
return NULL;
- }
-
- rc = udev_monitor_fs_setup( udev_monitor );
- if( rc < 0 ) {
-
- log_error("udev_monitor_fs_setup() rc = %d\n", rc );
+ }
+
+ rc = udev_monitor_fs_setup (udev_monitor);
+ if (rc < 0)
+ {
+
+ log_error ("udev_monitor_fs_setup() rc = %d\n", rc);
return NULL;
- }
-
- udev_monitor->type = UDEV_MONITOR_TYPE_UDEV;
-
- return udev_monitor;
+ }
+
+ udev_monitor->type = UDEV_MONITOR_TYPE_UDEV;
+
+ return udev_monitor;
}
/**
@@ -163,111 +170,134 @@ static struct udev_monitor *udev_monitor_new_from_filesystem(struct udev *udev )
*
* Returns: a new udev monitor, or #NULL, in case of an error
**/
-struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name)
+struct udev_monitor *
+udev_monitor_new_from_netlink (struct udev *udev, const char *name)
{
-
- if( strcmp( name, "udev" ) == 0 ) {
- return udev_monitor_new_from_filesystem(udev);
- }
- else {
- return udev_monitor_new_from_netlink_fd(udev, name, -1);
- }
+
+ if (strcmp (name, "udev") == 0)
+ {
+ return udev_monitor_new_from_filesystem (udev);
+ }
+ else
+ {
+ return udev_monitor_new_from_netlink_fd (udev, name, -1);
+ }
}
-static void monitor_set_nl_address(struct udev_monitor *udev_monitor) {
- union sockaddr_union snl;
- socklen_t addrlen;
- int r;
-
- assert(udev_monitor);
-
- /* get the address the kernel has assigned us
- * it is usually, but not necessarily the pid
- */
- addrlen = sizeof(struct sockaddr_nl);
- r = getsockname(udev_monitor->sock, &snl.sa, &addrlen);
- if (r >= 0) {
- udev_monitor->snl.nl.nl_pid = snl.nl.nl_pid;
- }
+static void
+monitor_set_nl_address (struct udev_monitor *udev_monitor)
+{
+ union sockaddr_union snl;
+ socklen_t addrlen;
+ int r;
+
+ assert (udev_monitor);
+
+ /* get the address the kernel has assigned us
+ * it is usually, but not necessarily the pid
+ */
+ addrlen = sizeof (struct sockaddr_nl);
+ r = getsockname (udev_monitor->sock, &snl.sa, &addrlen);
+ if (r >= 0)
+ {
+ udev_monitor->snl.nl.nl_pid = snl.nl.nl_pid;
+ }
}
// NOTE: this method is here only for compatibility.
-struct udev_monitor *udev_monitor_new_from_netlink_fd( struct udev* udev, char const* name, int fd ) {
-
- struct udev_monitor *udev_monitor;
- unsigned int group;
+struct udev_monitor *
+udev_monitor_new_from_netlink_fd (struct udev *udev, char const *name, int fd)
+{
+
+ struct udev_monitor *udev_monitor;
+ unsigned int group;
- if (udev == NULL) {
+ if (udev == NULL)
+ {
return NULL;
- }
-
- if (name == NULL) {
+ }
+
+ if (name == NULL)
+ {
group = UDEV_MONITOR_NONE;
- }
-
- else if (streq(name, "udev")) {
-
+ }
+
+ else if (streq (name, "udev"))
+ {
+
// libudev-compat: read from an event buffer on the fs
- return udev_monitor_new_from_filesystem( udev );
-
- } else if (streq(name, "kernel")) {
+ return udev_monitor_new_from_filesystem (udev);
+
+ }
+ else if (streq (name, "kernel"))
+ {
group = UDEV_MONITOR_KERNEL;
- }
- else {
+ }
+ else
+ {
return NULL;
- }
+ }
- udev_monitor = udev_monitor_new(udev);
- if (udev_monitor == NULL) {
+ udev_monitor = udev_monitor_new (udev);
+ if (udev_monitor == NULL)
+ {
return NULL;
- }
-
- if (fd < 0) {
- udev_monitor->sock = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT);
- if (udev_monitor->sock < 0) {
- log_debug("error getting socket: %s", strerror(errno));
- free(udev_monitor);
- return NULL;
- }
- } else {
+ }
+
+ if (fd < 0)
+ {
+ udev_monitor->sock =
+ socket (PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
+ NETLINK_KOBJECT_UEVENT);
+ if (udev_monitor->sock < 0)
+ {
+ log_debug ("error getting socket: %s", strerror (errno));
+ free (udev_monitor);
+ return NULL;
+ }
+ }
+ else
+ {
udev_monitor->bound = true;
udev_monitor->sock = fd;
- monitor_set_nl_address(udev_monitor);
- }
+ monitor_set_nl_address (udev_monitor);
+ }
+
+ udev_monitor->snl.nl.nl_family = AF_NETLINK;
+ udev_monitor->snl.nl.nl_groups = group;
- udev_monitor->snl.nl.nl_family = AF_NETLINK;
- udev_monitor->snl.nl.nl_groups = group;
+ /* default destination for sending */
+ udev_monitor->snl_destination.nl.nl_family = AF_NETLINK;
+ udev_monitor->snl_destination.nl.nl_groups = UDEV_MONITOR_UDEV;
- /* default destination for sending */
- udev_monitor->snl_destination.nl.nl_family = AF_NETLINK;
- udev_monitor->snl_destination.nl.nl_groups = UDEV_MONITOR_UDEV;
+ udev_monitor->type = UDEV_MONITOR_TYPE_KERNEL;
- udev_monitor->type = UDEV_MONITOR_TYPE_KERNEL;
-
- return udev_monitor;
+ return udev_monitor;
}
-static inline void bpf_stmt(struct sock_filter *inss, unsigned int *i,
- unsigned short code, unsigned int data)
+static inline void
+bpf_stmt (struct sock_filter *inss, unsigned int *i,
+ unsigned short code, unsigned int data)
{
- struct sock_filter *ins = &inss[*i];
+ struct sock_filter *ins = &inss[*i];
- ins->code = code;
- ins->k = data;
- (*i)++;
+ ins->code = code;
+ ins->k = data;
+ (*i)++;
}
-static inline void bpf_jmp(struct sock_filter *inss, unsigned int *i,
- unsigned short code, unsigned int data,
- unsigned short jt, unsigned short jf)
+static inline void
+bpf_jmp (struct sock_filter *inss, unsigned int *i,
+ unsigned short code, unsigned int data,
+ unsigned short jt, unsigned short jf)
{
- struct sock_filter *ins = &inss[*i];
+ struct sock_filter *ins = &inss[*i];
- ins->code = code;
- ins->jt = jt;
- ins->jf = jf;
- ins->k = data;
- (*i)++;
+ ins->code = code;
+ ins->jt = jt;
+ ins->jf = jf;
+ ins->k = data;
+ (*i)++;
}
/**
@@ -279,118 +309,149 @@ static inline void bpf_jmp(struct sock_filter *inss, unsigned int *i,
*
* Returns: 0 on success, otherwise a negative error value.
*/
-int udev_monitor_filter_update(struct udev_monitor *udev_monitor)
+int
+udev_monitor_filter_update (struct udev_monitor *udev_monitor)
{
- struct sock_filter ins[512];
- struct sock_fprog filter;
- unsigned int i;
- struct udev_list_entry *list_entry;
- int err;
-
- if (udev_list_get_entry(&udev_monitor->filter_subsystem_list) == NULL &&
- udev_list_get_entry(&udev_monitor->filter_tag_list) == NULL)
- return 0;
-
- memzero(ins, sizeof(ins));
- i = 0;
-
- /* load magic in A */
- bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, magic));
- /* jump if magic matches */
- bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, UDEV_MONITOR_MAGIC, 1, 0);
- /* wrong magic, pass packet */
- bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff);
-
- if (udev_list_get_entry(&udev_monitor->filter_tag_list) != NULL) {
- int tag_matches;
-
- /* count tag matches, to calculate end of tag match block */
- tag_matches = 0;
- udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_tag_list))
- tag_matches++;
-
- /* add all tags matches */
- udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_tag_list)) {
- uint64_t tag_bloom_bits = util_string_bloom64(udev_list_entry_get_name(list_entry));
- uint32_t tag_bloom_hi = tag_bloom_bits >> 32;
- uint32_t tag_bloom_lo = tag_bloom_bits & 0xffffffff;
-
- /* load device bloom bits in A */
- bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_tag_bloom_hi));
- /* clear bits (tag bits & bloom bits) */
- bpf_stmt(ins, &i, BPF_ALU|BPF_AND|BPF_K, tag_bloom_hi);
- /* jump to next tag if it does not match */
- bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, tag_bloom_hi, 0, 3);
-
- /* load device bloom bits in A */
- bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_tag_bloom_lo));
- /* clear bits (tag bits & bloom bits) */
- bpf_stmt(ins, &i, BPF_ALU|BPF_AND|BPF_K, tag_bloom_lo);
- /* jump behind end of tag match block if tag matches */
- tag_matches--;
- bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, tag_bloom_lo, 1 + (tag_matches * 6), 0);
- }
-
- /* nothing matched, drop packet */
- bpf_stmt(ins, &i, BPF_RET|BPF_K, 0);
- }
-
- /* add all subsystem matches */
- if (udev_list_get_entry(&udev_monitor->filter_subsystem_list) != NULL) {
- udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_subsystem_list)) {
- unsigned int hash = util_string_hash32(udev_list_entry_get_name(list_entry));
-
- /* load device subsystem value in A */
- bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_subsystem_hash));
- if (udev_list_entry_get_value(list_entry) == NULL) {
- /* jump if subsystem does not match */
- bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1);
- } else {
- /* jump if subsystem does not match */
- bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 3);
-
- /* load device devtype value in A */
- bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(struct udev_monitor_netlink_header, filter_devtype_hash));
- /* jump if value does not match */
- hash = util_string_hash32(udev_list_entry_get_value(list_entry));
- bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1);
- }
-
- /* matched, pass packet */
- bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff);
-
- if (i+1 >= ELEMENTSOF(ins))
- return -E2BIG;
- }
-
- /* nothing matched, drop packet */
- bpf_stmt(ins, &i, BPF_RET|BPF_K, 0);
- }
-
- /* matched, pass packet */
- bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff);
-
- /* install filter */
- // NOTE: attaches to either netlink or sockpair
- memzero(&filter, sizeof(filter));
- filter.len = i;
- filter.filter = ins;
- err = setsockopt(udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter));
- return err < 0 ? -errno : 0;
-}
+ struct sock_filter ins[512];
+ struct sock_fprog filter;
+ unsigned int i;
+ struct udev_list_entry *list_entry;
+ int err;
+
+ if (udev_list_get_entry (&udev_monitor->filter_subsystem_list) == NULL &&
+ udev_list_get_entry (&udev_monitor->filter_tag_list) == NULL)
+ return 0;
+
+ memzero (ins, sizeof (ins));
+ i = 0;
+
+ /* load magic in A */
+ bpf_stmt (ins, &i, BPF_LD | BPF_W | BPF_ABS,
+ offsetof (struct udev_monitor_netlink_header, magic));
+ /* jump if magic matches */
+ bpf_jmp (ins, &i, BPF_JMP | BPF_JEQ | BPF_K, UDEV_MONITOR_MAGIC, 1, 0);
+ /* wrong magic, pass packet */
+ bpf_stmt (ins, &i, BPF_RET | BPF_K, 0xffffffff);
+
+ if (udev_list_get_entry (&udev_monitor->filter_tag_list) != NULL)
+ {
+ int tag_matches;
+
+ /* count tag matches, to calculate end of tag match block */
+ tag_matches = 0;
+ udev_list_entry_foreach (list_entry,
+ udev_list_get_entry
+ (&udev_monitor->filter_tag_list))
+ tag_matches++;
+
+ /* add all tags matches */
+ udev_list_entry_foreach (list_entry,
+ udev_list_get_entry
+ (&udev_monitor->filter_tag_list))
+ {
+ uint64_t tag_bloom_bits =
+ util_string_bloom64 (udev_list_entry_get_name (list_entry));
+ uint32_t tag_bloom_hi = tag_bloom_bits >> 32;
+ uint32_t tag_bloom_lo = tag_bloom_bits & 0xffffffff;
+
+ /* load device bloom bits in A */
+ bpf_stmt (ins, &i, BPF_LD | BPF_W | BPF_ABS,
+ offsetof (struct udev_monitor_netlink_header,
+ filter_tag_bloom_hi));
+ /* clear bits (tag bits & bloom bits) */
+ bpf_stmt (ins, &i, BPF_ALU | BPF_AND | BPF_K, tag_bloom_hi);
+ /* jump to next tag if it does not match */
+ bpf_jmp (ins, &i, BPF_JMP | BPF_JEQ | BPF_K, tag_bloom_hi, 0, 3);
+
+ /* load device bloom bits in A */
+ bpf_stmt (ins, &i, BPF_LD | BPF_W | BPF_ABS,
+ offsetof (struct udev_monitor_netlink_header,
+ filter_tag_bloom_lo));
+ /* clear bits (tag bits & bloom bits) */
+ bpf_stmt (ins, &i, BPF_ALU | BPF_AND | BPF_K, tag_bloom_lo);
+ /* jump behind end of tag match block if tag matches */
+ tag_matches--;
+ bpf_jmp (ins, &i, BPF_JMP | BPF_JEQ | BPF_K,
+ tag_bloom_lo, 1 + (tag_matches * 6), 0);
+ }
+
+ /* nothing matched, drop packet */
+ bpf_stmt (ins, &i, BPF_RET | BPF_K, 0);
+ }
+
+ /* add all subsystem matches */
+ if (udev_list_get_entry (&udev_monitor->filter_subsystem_list) != NULL)
+ {
+ udev_list_entry_foreach (list_entry,
+ udev_list_get_entry
+ (&udev_monitor->filter_subsystem_list))
+ {
+ unsigned int hash =
+ util_string_hash32 (udev_list_entry_get_name (list_entry));
+
+ /* load device subsystem value in A */
+ bpf_stmt (ins, &i, BPF_LD | BPF_W | BPF_ABS,
+ offsetof (struct udev_monitor_netlink_header,
+ filter_subsystem_hash));
+ if (udev_list_entry_get_value (list_entry) == NULL)
+ {
+ /* jump if subsystem does not match */
+ bpf_jmp (ins, &i, BPF_JMP | BPF_JEQ | BPF_K, hash, 0, 1);
+ }
+ else
+ {
+ /* jump if subsystem does not match */
+ bpf_jmp (ins, &i, BPF_JMP | BPF_JEQ | BPF_K, hash, 0, 3);
+
+ /* load device devtype value in A */
+ bpf_stmt (ins, &i, BPF_LD | BPF_W | BPF_ABS,
+ offsetof (struct
+ udev_monitor_netlink_header,
+ filter_devtype_hash));
+ /* jump if value does not match */
+ hash =
+ util_string_hash32 (udev_list_entry_get_value (list_entry));
+ bpf_jmp (ins, &i, BPF_JMP | BPF_JEQ | BPF_K, hash, 0, 1);
+ }
+
+ /* matched, pass packet */
+ bpf_stmt (ins, &i, BPF_RET | BPF_K, 0xffffffff);
+
+ if (i + 1 >= ELEMENTSOF (ins))
+ return -E2BIG;
+ }
+ /* nothing matched, drop packet */
+ bpf_stmt (ins, &i, BPF_RET | BPF_K, 0);
+ }
+
+ /* matched, pass packet */
+ bpf_stmt (ins, &i, BPF_RET | BPF_K, 0xffffffff);
+
+ /* install filter */
+ // NOTE: attaches to either netlink or sockpair
+ memzero (&filter, sizeof (filter));
+ filter.len = i;
+ filter.filter = ins;
+ err =
+ setsockopt (udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER,
+ &filter, sizeof (filter));
+ return err < 0 ? -errno : 0;
+}
-int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct udev_monitor *sender)
+int
+udev_monitor_allow_unicast_sender (struct udev_monitor *udev_monitor,
+ struct udev_monitor *sender)
{
- // only for kernel-type links
- if( udev_monitor->type != UDEV_MONITOR_TYPE_KERNEL ) {
+ // only for kernel-type links
+ if (udev_monitor->type != UDEV_MONITOR_TYPE_KERNEL)
+ {
return -EINVAL;
- }
-
- udev_monitor->snl_trusted_sender.nl.nl_pid = sender->snl.nl.nl_pid;
- return 0;
-}
+ }
+ udev_monitor->snl_trusted_sender.nl.nl_pid = sender->snl.nl.nl_pid;
+ return 0;
+}
/**
* udev_monitor_enable_receiving:
@@ -402,60 +463,73 @@ int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct
*
* NOTE: in libudev-compat, this only works for "kernel" udev monitors.
*/
-int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor)
+int
+udev_monitor_enable_receiving (struct udev_monitor *udev_monitor)
{
-
- if( udev_monitor == NULL ) {
+
+ if (udev_monitor == NULL)
+ {
return -EINVAL;
- }
-
- // libudev-compat: only for kernel types
- // udev-types are already in a receiving state
- if( udev_monitor->type != UDEV_MONITOR_TYPE_KERNEL ) {
+ }
+ // libudev-compat: only for kernel types
+ // udev-types are already in a receiving state
+ if (udev_monitor->type != UDEV_MONITOR_TYPE_KERNEL)
+ {
return 0;
- }
-
- int err = 0;
- const int on = 1;
-
- udev_monitor_filter_update(udev_monitor);
-
- if (!udev_monitor->bound) {
- err = bind(udev_monitor->sock, &udev_monitor->snl.sa, sizeof(struct sockaddr_nl));
- if (err == 0) {
- udev_monitor->bound = true;
- }
- }
-
- if (err >= 0) {
- union sockaddr_union snl;
- socklen_t addrlen;
-
- // get the address the kernel has assigned us
- // it is usually, but not necessarily the pid
-
- addrlen = sizeof(struct sockaddr_nl);
- err = getsockname(udev_monitor->sock, &snl.sa, &addrlen);
- if (err == 0) {
- udev_monitor->snl.nl.nl_pid = snl.nl.nl_pid;
- }
- } else {
-
+ }
+
+ int err = 0;
+ const int on = 1;
+
+ udev_monitor_filter_update (udev_monitor);
+
+ if (!udev_monitor->bound)
+ {
+ err =
+ bind (udev_monitor->sock, &udev_monitor->snl.sa,
+ sizeof (struct sockaddr_nl));
+ if (err == 0)
+ {
+ udev_monitor->bound = true;
+ }
+ }
+
+ if (err >= 0)
+ {
+ union sockaddr_union snl;
+ socklen_t addrlen;
+
+ // get the address the kernel has assigned us
+ // it is usually, but not necessarily the pid
+
+ addrlen = sizeof (struct sockaddr_nl);
+ err = getsockname (udev_monitor->sock, &snl.sa, &addrlen);
+ if (err == 0)
+ {
+ udev_monitor->snl.nl.nl_pid = snl.nl.nl_pid;
+ }
+ }
+ else
+ {
+
int errsv = errno;
- log_debug("bind failed: %s", strerror(errsv));
+ log_debug ("bind failed: %s", strerror (errsv));
return -errsv;
- }
+ }
+
+ // enable receiving of sender credentials
+ err =
+ setsockopt (udev_monitor->sock, SOL_SOCKET, SO_PASSCRED, &on,
+ sizeof (on));
+ if (err < 0)
+ {
- // enable receiving of sender credentials
- err = setsockopt(udev_monitor->sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
- if (err < 0) {
-
int errsv = errno;
- log_debug("setting SO_PASSCRED failed: %s", strerror(errsv));
+ log_debug ("setting SO_PASSCRED failed: %s", strerror (errsv));
return -errsv;
- }
+ }
- return 0;
+ return 0;
}
/**
@@ -468,27 +542,34 @@ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor)
*
* Returns: 0 on success, otherwise -1 on error.
*/
-int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size)
+int
+udev_monitor_set_receive_buffer_size (struct udev_monitor *udev_monitor,
+ int size)
{
- if (udev_monitor == NULL) {
- return -EINVAL;
- }
-
- return setsockopt(udev_monitor->sock, SOL_SOCKET, SO_RCVBUFFORCE, &size, sizeof(size));
+ if (udev_monitor == NULL)
+ {
+ return -EINVAL;
+ }
+
+ return setsockopt (udev_monitor->sock, SOL_SOCKET, SO_RCVBUFFORCE, &size,
+ sizeof (size));
}
-int udev_monitor_disconnect(struct udev_monitor *udev_monitor)
+int
+udev_monitor_disconnect (struct udev_monitor *udev_monitor)
{
- if( udev_monitor->type == UDEV_MONITOR_TYPE_UDEV ) {
- return udev_monitor_fs_shutdown( udev_monitor );
- }
- else {
-
+ if (udev_monitor->type == UDEV_MONITOR_TYPE_UDEV)
+ {
+ return udev_monitor_fs_shutdown (udev_monitor);
+ }
+ else
+ {
+
int err = 0;
- err = close(udev_monitor->sock);
+ err = close (udev_monitor->sock);
udev_monitor->sock = -1;
return err < 0 ? -errno : 0;
- }
+ }
}
/**
@@ -499,14 +580,16 @@ int udev_monitor_disconnect(struct udev_monitor *udev_monitor)
*
* Returns: the passed udev monitor
**/
-struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor)
+struct udev_monitor *
+udev_monitor_ref (struct udev_monitor *udev_monitor)
{
- if (udev_monitor == NULL) {
- return NULL;
- }
-
- udev_monitor->refcount++;
- return udev_monitor;
+ if (udev_monitor == NULL)
+ {
+ return NULL;
+ }
+
+ udev_monitor->refcount++;
+ return udev_monitor;
}
/**
@@ -519,32 +602,38 @@ struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor)
*
* Returns: #NULL
**/
-struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor)
+struct udev_monitor *
+udev_monitor_unref (struct udev_monitor *udev_monitor)
{
- if (udev_monitor == NULL) {
- return NULL;
- }
-
- udev_monitor->refcount--;
-
- if (udev_monitor->refcount > 0) {
- return NULL;
- }
-
- udev_list_cleanup(&udev_monitor->filter_subsystem_list);
- udev_list_cleanup(&udev_monitor->filter_tag_list);
-
- if( udev_monitor->type == UDEV_MONITOR_TYPE_UDEV ) {
- udev_monitor_fs_destroy( udev_monitor );
- }
- else {
- if (udev_monitor->sock >= 0) {
- close(udev_monitor->sock);
- }
- }
-
- free(udev_monitor);
- return NULL;
+ if (udev_monitor == NULL)
+ {
+ return NULL;
+ }
+
+ udev_monitor->refcount--;
+
+ if (udev_monitor->refcount > 0)
+ {
+ return NULL;
+ }
+
+ udev_list_cleanup (&udev_monitor->filter_subsystem_list);
+ udev_list_cleanup (&udev_monitor->filter_tag_list);
+
+ if (udev_monitor->type == UDEV_MONITOR_TYPE_UDEV)
+ {
+ udev_monitor_fs_destroy (udev_monitor);
+ }
+ else
+ {
+ if (udev_monitor->sock >= 0)
+ {
+ close (udev_monitor->sock);
+ }
+ }
+
+ free (udev_monitor);
+ return NULL;
}
/**
@@ -555,12 +644,14 @@ struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor)
*
* Returns: the udev library context
**/
-struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor)
+struct udev *
+udev_monitor_get_udev (struct udev_monitor *udev_monitor)
{
- if (udev_monitor == NULL) {
- return NULL;
- }
- return udev_monitor->udev;
+ if (udev_monitor == NULL)
+ {
+ return NULL;
+ }
+ return udev_monitor->udev;
}
/**
@@ -577,341 +668,399 @@ struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor)
* for udev-type monitors, or a netlink socket for kernel-type
* monitors.
**/
-int udev_monitor_get_fd(struct udev_monitor *udev_monitor)
+int
+udev_monitor_get_fd (struct udev_monitor *udev_monitor)
{
- if (udev_monitor == NULL) {
- return -EINVAL;
- }
-
- if( udev_monitor->type == UDEV_MONITOR_TYPE_UDEV ) {
- return udev_monitor->epoll_fd;
- }
- else {
- return udev_monitor->sock;
- }
+ if (udev_monitor == NULL)
+ {
+ return -EINVAL;
+ }
+
+ if (udev_monitor->type == UDEV_MONITOR_TYPE_UDEV)
+ {
+ return udev_monitor->epoll_fd;
+ }
+ else
+ {
+ return udev_monitor->sock;
+ }
}
-static int passes_filter(struct udev_monitor *udev_monitor, struct udev_device *udev_device)
+static int
+passes_filter (struct udev_monitor *udev_monitor,
+ struct udev_device *udev_device)
{
- struct udev_list_entry *list_entry;
-
- if (udev_list_get_entry(&udev_monitor->filter_subsystem_list) == NULL)
- goto tag;
- udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_subsystem_list)) {
- const char *subsys = udev_list_entry_get_name(list_entry);
- const char *dsubsys = udev_device_get_subsystem(udev_device);
- const char *devtype;
- const char *ddevtype;
-
- if (!streq(dsubsys, subsys))
- continue;
-
- devtype = udev_list_entry_get_value(list_entry);
- if (devtype == NULL)
- goto tag;
- ddevtype = udev_device_get_devtype(udev_device);
- if (ddevtype == NULL)
- continue;
- if (streq(ddevtype, devtype))
- goto tag;
- }
- return 0;
+ struct udev_list_entry *list_entry;
+
+ if (udev_list_get_entry (&udev_monitor->filter_subsystem_list) == NULL)
+ goto tag;
+ udev_list_entry_foreach (list_entry,
+ udev_list_get_entry
+ (&udev_monitor->filter_subsystem_list))
+ {
+ const char *subsys = udev_list_entry_get_name (list_entry);
+ const char *dsubsys = udev_device_get_subsystem (udev_device);
+ const char *devtype;
+ const char *ddevtype;
+
+ if (!streq (dsubsys, subsys))
+ continue;
+
+ devtype = udev_list_entry_get_value (list_entry);
+ if (devtype == NULL)
+ goto tag;
+ ddevtype = udev_device_get_devtype (udev_device);
+ if (ddevtype == NULL)
+ continue;
+ if (streq (ddevtype, devtype))
+ goto tag;
+ }
+ return 0;
tag:
- if (udev_list_get_entry(&udev_monitor->filter_tag_list) == NULL)
- return 1;
- udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_monitor->filter_tag_list)) {
- const char *tag = udev_list_entry_get_name(list_entry);
-
- if (udev_device_has_tag(udev_device, tag))
- return 1;
- }
- return 0;
+ if (udev_list_get_entry (&udev_monitor->filter_tag_list) == NULL)
+ return 1;
+ udev_list_entry_foreach (list_entry,
+ udev_list_get_entry
+ (&udev_monitor->filter_tag_list))
+ {
+ const char *tag = udev_list_entry_get_name (list_entry);
+
+ if (udev_device_has_tag (udev_device, tag))
+ return 1;
+ }
+ return 0;
}
-
// receive a device from netlink
-static struct udev_device* udev_monitor_receive_device_netlink( struct udev_monitor* udev_monitor ) {
-
- if( udev_monitor == NULL ) {
+static struct udev_device *
+udev_monitor_receive_device_netlink (struct udev_monitor *udev_monitor)
+{
+
+ if (udev_monitor == NULL)
+ {
return NULL;
- }
-
- if( udev_monitor->type != UDEV_MONITOR_TYPE_KERNEL ) {
-
+ }
+
+ if (udev_monitor->type != UDEV_MONITOR_TYPE_KERNEL)
+ {
+
errno = EINVAL;
return NULL;
- }
-
- struct udev_device *udev_device;
- struct msghdr smsg;
- struct iovec iov;
- char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
- struct cmsghdr *cmsg;
- union sockaddr_union snl;
- struct ucred *cred;
- union {
- struct udev_monitor_netlink_header nlh;
- char raw[8192];
- } buf;
- ssize_t buflen;
- ssize_t bufpos;
- bool is_initialized = false;
+ }
+
+ struct udev_device *udev_device;
+ struct msghdr smsg;
+ struct iovec iov;
+ char cred_msg[CMSG_SPACE (sizeof (struct ucred))];
+ struct cmsghdr *cmsg;
+ union sockaddr_union snl;
+ struct ucred *cred;
+ union
+ {
+ struct udev_monitor_netlink_header nlh;
+ char raw[8192];
+ } buf;
+ ssize_t buflen;
+ ssize_t bufpos;
+ bool is_initialized = false;
retry:
- if (udev_monitor == NULL)
- return NULL;
- iov.iov_base = &buf;
- iov.iov_len = sizeof(buf);
- memzero(&smsg, sizeof(struct msghdr));
- smsg.msg_iov = &iov;
- smsg.msg_iovlen = 1;
- smsg.msg_control = cred_msg;
- smsg.msg_controllen = sizeof(cred_msg);
- smsg.msg_name = &snl;
- smsg.msg_namelen = sizeof(snl);
-
- buflen = recvmsg(udev_monitor->sock, &smsg, 0);
- if (buflen < 0) {
- if (errno != EINTR) {
- log_debug("%s", "unable to receive message");
- }
- return NULL;
- }
-
- if (buflen < 32 || (smsg.msg_flags & MSG_TRUNC)) {
- log_debug("%s", "invalid message length");
- return NULL;
- }
-
- if (snl.nl.nl_groups == 0) {
- /* unicast message, check if we trust the sender */
- if (udev_monitor->snl_trusted_sender.nl.nl_pid == 0 ||
- snl.nl.nl_pid != udev_monitor->snl_trusted_sender.nl.nl_pid) {
- log_debug("%s", "unicast netlink message ignored");
- return NULL;
- }
- } else if (snl.nl.nl_groups == UDEV_MONITOR_KERNEL) {
- if (snl.nl.nl_pid > 0) {
- log_debug("multicast kernel netlink message from PID %"PRIu32" ignored",
- snl.nl.nl_pid);
- return NULL;
- }
- }
-
- cmsg = CMSG_FIRSTHDR(&smsg);
- if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
- log_debug("%s", "no sender credentials received, message ignored");
- return NULL;
- }
-
- cred = (struct ucred *)CMSG_DATA(cmsg);
- if (cred->uid != 0) {
- log_debug("sender uid="UID_FMT", message ignored", cred->uid);
- return NULL;
- }
-
- if (memcmp(buf.raw, "libudev", 8) == 0) {
- /* udev message needs proper version magic */
- if (buf.nlh.magic != htonl(UDEV_MONITOR_MAGIC)) {
- log_debug("%s", "unrecognized message signature (%x != %x)",
- buf.nlh.magic, htonl(UDEV_MONITOR_MAGIC));
- return NULL;
- }
- if (buf.nlh.properties_off+32 > (size_t)buflen) {
- log_debug("%s", "message smaller than expected (%u > %zd)",
- buf.nlh.properties_off+32, buflen);
- return NULL;
- }
-
- bufpos = buf.nlh.properties_off;
-
- /* devices received from udev are always initialized */
- is_initialized = true;
- } else {
- /* kernel message with header */
- bufpos = strlen(buf.raw) + 1;
- if ((size_t)bufpos < sizeof("a@/d") || bufpos >= buflen) {
- log_debug("%s", "invalid message length");
- return NULL;
- }
-
- /* check message header */
- if (strstr(buf.raw, "@/") == NULL) {
- log_debug("%s", "unrecognized message header");
- return NULL;
- }
- }
-
- udev_device = udev_device_new_from_nulstr(udev_monitor->udev, &buf.raw[bufpos], buflen - bufpos);
- if (!udev_device) {
- log_debug("could not create device: %s", strerror(errno));
- return NULL;
- }
-
- if (is_initialized)
- udev_device_set_is_initialized(udev_device);
-
- /* skip device, if it does not pass the current filter */
- if (!passes_filter(udev_monitor, udev_device)) {
- struct pollfd pfd[1];
- int rc;
-
- udev_device_unref(udev_device);
-
- /* if something is queued, get next device */
- pfd[0].fd = udev_monitor->sock;
- pfd[0].events = POLLIN;
- rc = poll(pfd, 1, 0);
- if (rc > 0)
- goto retry;
- return NULL;
- }
-
- return udev_device;
-}
+ if (udev_monitor == NULL)
+ return NULL;
+ iov.iov_base = &buf;
+ iov.iov_len = sizeof (buf);
+ memzero (&smsg, sizeof (struct msghdr));
+ smsg.msg_iov = &iov;
+ smsg.msg_iovlen = 1;
+ smsg.msg_control = cred_msg;
+ smsg.msg_controllen = sizeof (cred_msg);
+ smsg.msg_name = &snl;
+ smsg.msg_namelen = sizeof (snl);
+
+ buflen = recvmsg (udev_monitor->sock, &smsg, 0);
+ if (buflen < 0)
+ {
+ if (errno != EINTR)
+ {
+ log_debug ("%s", "unable to receive message");
+ }
+ return NULL;
+ }
+
+ if (buflen < 32 || (smsg.msg_flags & MSG_TRUNC))
+ {
+ log_debug ("%s", "invalid message length");
+ return NULL;
+ }
+
+ if (snl.nl.nl_groups == 0)
+ {
+ /* unicast message, check if we trust the sender */
+ if (udev_monitor->snl_trusted_sender.nl.nl_pid == 0 ||
+ snl.nl.nl_pid != udev_monitor->snl_trusted_sender.nl.nl_pid)
+ {
+ log_debug ("%s", "unicast netlink message ignored");
+ return NULL;
+ }
+ }
+ else if (snl.nl.nl_groups == UDEV_MONITOR_KERNEL)
+ {
+ if (snl.nl.nl_pid > 0)
+ {
+ log_debug ("multicast kernel netlink message from PID %"
+ PRIu32 " ignored", snl.nl.nl_pid);
+ return NULL;
+ }
+ }
+
+ cmsg = CMSG_FIRSTHDR (&smsg);
+ if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS)
+ {
+ log_debug ("%s", "no sender credentials received, message ignored");
+ return NULL;
+ }
+
+ cred = (struct ucred *) CMSG_DATA (cmsg);
+ if (cred->uid != 0)
+ {
+ log_debug ("sender uid=" UID_FMT ", message ignored", cred->uid);
+ return NULL;
+ }
+
+ if (memcmp (buf.raw, "libudev", 8) == 0)
+ {
+ /* udev message needs proper version magic */
+ if (buf.nlh.magic != htonl (UDEV_MONITOR_MAGIC))
+ {
+ log_debug ("%s",
+ "unrecognized message signature (%x != %x)",
+ buf.nlh.magic, htonl (UDEV_MONITOR_MAGIC));
+ return NULL;
+ }
+ if (buf.nlh.properties_off + 32 > (size_t) buflen)
+ {
+ log_debug ("%s",
+ "message smaller than expected (%u > %zd)",
+ buf.nlh.properties_off + 32, buflen);
+ return NULL;
+ }
+
+ bufpos = buf.nlh.properties_off;
+
+ /* devices received from udev are always initialized */
+ is_initialized = true;
+ }
+ else
+ {
+ /* kernel message with header */
+ bufpos = strlen (buf.raw) + 1;
+ if ((size_t) bufpos < sizeof ("a@/d") || bufpos >= buflen)
+ {
+ log_debug ("%s", "invalid message length");
+ return NULL;
+ }
+
+ /* check message header */
+ if (strstr (buf.raw, "@/") == NULL)
+ {
+ log_debug ("%s", "unrecognized message header");
+ return NULL;
+ }
+ }
+
+ udev_device =
+ udev_device_new_from_nulstr (udev_monitor->udev, &buf.raw[bufpos],
+ buflen - bufpos);
+ if (!udev_device)
+ {
+ log_debug ("could not create device: %s", strerror (errno));
+ return NULL;
+ }
+
+ if (is_initialized)
+ udev_device_set_is_initialized (udev_device);
+ /* skip device, if it does not pass the current filter */
+ if (!passes_filter (udev_monitor, udev_device))
+ {
+ struct pollfd pfd[1];
+ int rc;
+
+ udev_device_unref (udev_device);
+
+ /* if something is queued, get next device */
+ pfd[0].fd = udev_monitor->sock;
+ pfd[0].events = POLLIN;
+ rc = poll (pfd, 1, 0);
+ if (rc > 0)
+ goto retry;
+ return NULL;
+ }
+
+ return udev_device;
+}
// receive a device from the filesystem (i.e. for udev-type monitors)
-static struct udev_device *udev_monitor_receive_device_fs(struct udev_monitor *udev_monitor)
+static struct udev_device *
+udev_monitor_receive_device_fs (struct udev_monitor *udev_monitor)
{
- struct udev_device *udev_device;
- struct msghdr smsg;
- struct iovec iov;
- int rc = 0;
- union {
- struct udev_monitor_netlink_header nlh;
- char raw[8192];
- } buf;
- ssize_t buflen;
- ssize_t bufpos;
- bool is_initialized = false;
- bool rescan = false;
-
- struct pollfd pfd[1];
+ struct udev_device *udev_device;
+ struct msghdr smsg;
+ struct iovec iov;
+ int rc = 0;
+ union
+ {
+ struct udev_monitor_netlink_header nlh;
+ char raw[8192];
+ } buf;
+ ssize_t buflen;
+ ssize_t bufpos;
+ bool is_initialized = false;
+ bool rescan = false;
+
+ struct pollfd pfd[1];
retry:
- if (udev_monitor == NULL) {
- return NULL;
- }
-
- // are there pending events?
- pfd[0].fd = udev_monitor->sock;
- pfd[0].events = POLLIN;
-
- rc = poll( pfd, 1, 0 );
- if( rc < 0 ) {
-
- rc = -errno;
- log_error("poll(%d) rc = %d\n", udev_monitor->sock, rc );
-
- return NULL;
- }
-
- if( rc == 0 ) {
-
- // no events bufferred.
- // push as many events as we can into the socketpair
- rc = udev_monitor_fs_push_events( udev_monitor );
- if( rc < 0 ) {
-
- if( rc == -ENODATA ) {
- // the socketpair was empty, and there were no bufferred events.
- // can only mean that whatever event got created, was unlinked before we could scan it.
- // shouldn't happen unless the admin is meddling...
- return NULL;
- }
-
- if( rc != -EAGAIN ) {
-
- log_error("udev_monitor_fs_push_events rc = %d\n", rc );
- return NULL;
- }
- else {
-
- // there are pending events, but we couldn't push any at this time.
- // this means the socket buffer is too small, or there was some
- // socket-level error.
- goto retry;
- }
- }
- }
-
- // prepare to receive
- iov.iov_base = &buf;
- iov.iov_len = sizeof(buf);
- memzero(&smsg, sizeof(struct msghdr));
- smsg.msg_iov = &iov;
- smsg.msg_iovlen = 1;
-
- // get a message we sent to ourselves through the filter
- buflen = recvmsg(udev_monitor->sock, &smsg, 0);
- if (buflen < 0) {
- if (errno != EINTR) {
- log_debug("%s", "unable to receive message");
- }
- return NULL;
- }
-
- if (buflen < 32 || (smsg.msg_flags & MSG_TRUNC)) {
-
- log_debug("%s", "invalid message length");
- return NULL;
- }
-
- if (memcmp(buf.raw, "libudev", 8) == 0) {
-
- /* udev message needs proper version magic */
- if (buf.nlh.magic != htonl(UDEV_MONITOR_MAGIC)) {
- log_debug("unrecognized message signature (%x != %x)",
- buf.nlh.magic, htonl(UDEV_MONITOR_MAGIC));
- return NULL;
- }
- if (buf.nlh.properties_off+32 > (size_t)buflen) {
- return NULL;
- }
-
- bufpos = buf.nlh.properties_off;
-
- /* devices received from udev are always initialized */
- is_initialized = true;
-
- } else {
-
- // libudev-compat: should never be reached, since we don't listen to netlink
- log_error("%s", "Invalid message: missing 'libudev' header");
- return NULL;
- }
-
- udev_device = udev_device_new_from_nulstr(udev_monitor->udev, &buf.raw[bufpos], buflen - bufpos);
- if (!udev_device) {
- return NULL;
- }
-
- if (is_initialized) {
- udev_device_set_is_initialized(udev_device);
- }
-
- /* skip device, if it does not pass the current filter */
- if (!passes_filter(udev_monitor, udev_device)) {
-
- udev_device_unref(udev_device);
-
- /* if something is queued, get next device */
- pfd[0].fd = udev_monitor->epoll_fd;
- pfd[0].events = POLLIN;
- rc = poll(pfd, 1, 0);
-
- if (rc > 0) {
- goto retry;
- }
-
- return NULL;
- }
-
- return udev_device;
-}
+ if (udev_monitor == NULL)
+ {
+ return NULL;
+ }
+ // are there pending events?
+ pfd[0].fd = udev_monitor->sock;
+ pfd[0].events = POLLIN;
+
+ rc = poll (pfd, 1, 0);
+ if (rc < 0)
+ {
+ rc = -errno;
+ log_error ("poll(%d) rc = %d\n", udev_monitor->sock, rc);
+
+ return NULL;
+ }
+
+ if (rc == 0)
+ {
+
+ // no events bufferred.
+ // push as many events as we can into the socketpair
+ rc = udev_monitor_fs_push_events (udev_monitor);
+ if (rc < 0)
+ {
+
+ if (rc == -ENODATA)
+ {
+ // the socketpair was empty, and there were no bufferred events.
+ // can only mean that whatever event got created, was unlinked before we could scan it.
+ // shouldn't happen unless the admin is meddling...
+ return NULL;
+ }
+
+ if (rc != -EAGAIN)
+ {
+
+ log_error ("udev_monitor_fs_push_events rc = %d\n", rc);
+ return NULL;
+ }
+ else
+ {
+
+ // there are pending events, but we couldn't push any at this time.
+ // this means the socket buffer is too small, or there was some
+ // socket-level error.
+ goto retry;
+ }
+ }
+ }
+ // prepare to receive
+ iov.iov_base = &buf;
+ iov.iov_len = sizeof (buf);
+ memzero (&smsg, sizeof (struct msghdr));
+ smsg.msg_iov = &iov;
+ smsg.msg_iovlen = 1;
+
+ // get a message we sent to ourselves through the filter
+ buflen = recvmsg (udev_monitor->sock, &smsg, 0);
+ if (buflen < 0)
+ {
+ if (errno != EINTR)
+ {
+ log_debug ("%s", "unable to receive message");
+ }
+ return NULL;
+ }
+
+ if (buflen < 32 || (smsg.msg_flags & MSG_TRUNC))
+ {
+
+ log_debug ("%s", "invalid message length");
+ return NULL;
+ }
+
+ if (memcmp (buf.raw, "libudev", 8) == 0)
+ {
+
+ /* udev message needs proper version magic */
+ if (buf.nlh.magic != htonl (UDEV_MONITOR_MAGIC))
+ {
+ log_debug ("unrecognized message signature (%x != %x)",
+ buf.nlh.magic, htonl (UDEV_MONITOR_MAGIC));
+ return NULL;
+ }
+ if (buf.nlh.properties_off + 32 > (size_t) buflen)
+ {
+ return NULL;
+ }
+
+ bufpos = buf.nlh.properties_off;
+
+ /* devices received from udev are always initialized */
+ is_initialized = true;
+
+ }
+ else
+ {
+
+ // libudev-compat: should never be reached, since we don't listen to netlink
+ log_error ("%s", "Invalid message: missing 'libudev' header");
+ return NULL;
+ }
+
+ udev_device =
+ udev_device_new_from_nulstr (udev_monitor->udev, &buf.raw[bufpos],
+ buflen - bufpos);
+ if (!udev_device)
+ {
+ return NULL;
+ }
+
+ if (is_initialized)
+ {
+ udev_device_set_is_initialized (udev_device);
+ }
+
+ /* skip device, if it does not pass the current filter */
+ if (!passes_filter (udev_monitor, udev_device))
+ {
+
+ udev_device_unref (udev_device);
+
+ /* if something is queued, get next device */
+ pfd[0].fd = udev_monitor->epoll_fd;
+ pfd[0].events = POLLIN;
+ rc = poll (pfd, 1, 0);
+
+ if (rc > 0)
+ {
+ goto retry;
+ }
+
+ return NULL;
+ }
+
+ return udev_device;
+}
/**
* udev_monitor_receive_device:
@@ -933,123 +1082,146 @@ static struct udev_device *udev_monitor_receive_device_fs(struct udev_monitor *u
* Returns: a new udev device, or #NULL, in case of an error
**/
-struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) {
-
- if( udev_monitor == NULL ) {
+struct udev_device *
+udev_monitor_receive_device (struct udev_monitor *udev_monitor)
+{
+
+ if (udev_monitor == NULL)
+ {
return NULL;
- }
-
- if( udev_monitor->type == UDEV_MONITOR_TYPE_KERNEL ) {
-
- return udev_monitor_receive_device_netlink( udev_monitor );
- }
- else if( udev_monitor->type == UDEV_MONITOR_TYPE_UDEV ) {
-
- return udev_monitor_receive_device_fs( udev_monitor );
- }
- else {
-
+ }
+
+ if (udev_monitor->type == UDEV_MONITOR_TYPE_KERNEL)
+ {
+
+ return udev_monitor_receive_device_netlink (udev_monitor);
+ }
+ else if (udev_monitor->type == UDEV_MONITOR_TYPE_UDEV)
+ {
+
+ return udev_monitor_receive_device_fs (udev_monitor);
+ }
+ else
+ {
+
errno = EINVAL;
return NULL;
- }
+ }
}
-
-int udev_monitor_send_device(struct udev_monitor *udev_monitor, struct udev_monitor *destination, struct udev_device *udev_device)
+int
+udev_monitor_send_device (struct udev_monitor *udev_monitor,
+ struct udev_monitor *destination,
+ struct udev_device *udev_device)
{
-
- if( udev_monitor == NULL ) {
- return -EINVAL;
- }
-
- const char *buf, *val;
- ssize_t blen, count;
- struct msghdr smsg;
- int sock = -1;
- struct udev_monitor_netlink_header nlh = {
- .prefix = "libudev",
- .magic = htonl(UDEV_MONITOR_MAGIC),
- .header_size = sizeof nlh,
- };
- struct iovec iov[2] = {
- { .iov_base = &nlh, .iov_len = sizeof nlh },
- };
-
- memset( &smsg, 0, sizeof(struct msghdr) );
-
- smsg.msg_iov = iov;
- smsg.msg_iovlen = 2;
-
- struct udev_list_entry *list_entry;
- uint64_t tag_bloom_bits;
-
- // serialize the device
- blen = udev_device_get_properties_monitor_buf(udev_device, &buf);
- if (blen < 32) {
- return -EINVAL;
- }
-
- /* fill in versioned header */
- val = udev_device_get_subsystem(udev_device);
- nlh.filter_subsystem_hash = htonl(util_string_hash32(val));
-
- val = udev_device_get_devtype(udev_device);
- if (val != NULL) {
- nlh.filter_devtype_hash = htonl(util_string_hash32(val));
- }
-
- /* add tag bloom filter */
- tag_bloom_bits = 0;
- udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(udev_device))
- tag_bloom_bits |= util_string_bloom64(udev_list_entry_get_name(list_entry));
-
- if (tag_bloom_bits > 0) {
- nlh.filter_tag_bloom_hi = htonl(tag_bloom_bits >> 32);
- nlh.filter_tag_bloom_lo = htonl(tag_bloom_bits & 0xffffffff);
- }
-
- /* add properties list */
- nlh.properties_off = iov[0].iov_len;
- nlh.properties_len = blen;
- iov[1].iov_base = (char *)buf;
- iov[1].iov_len = blen;
-
- /*
- * Use custom address for target, or the default one.
- *
- * If we send to a multicast group, we will get
- * ECONNREFUSED, which is expected.
- */
-
- if( udev_monitor->type == UDEV_MONITOR_TYPE_KERNEL ) {
-
- sock = udev_monitor->sock;
-
- if (destination)
- smsg.msg_name = &destination->snl;
- else
- smsg.msg_name = &udev_monitor->snl_destination;
-
- smsg.msg_namelen = sizeof(struct sockaddr_nl);
- }
- else {
-
- sock = udev_monitor->sock_fs;
- }
-
- count = sendmsg( sock, &smsg, 0);
- if (count < 0) {
-
- if (!destination) {
- log_debug("passed unknown number of bytes to netlink monitor %p", udev_monitor);
- return 0;
- } else {
- return -errno;
- }
- }
-
- log_debug("passed %zi bytes to netlink monitor %p", count, udev_monitor);
- return count;
+
+ if (udev_monitor == NULL)
+ {
+ return -EINVAL;
+ }
+
+ const char *buf, *val;
+ ssize_t blen, count;
+ struct msghdr smsg;
+ int sock = -1;
+ struct udev_monitor_netlink_header nlh = {
+ .prefix = "libudev",
+ .magic = htonl (UDEV_MONITOR_MAGIC),
+ .header_size = sizeof nlh,
+ };
+ struct iovec iov[2] = {
+ {.iov_base = &nlh,.iov_len = sizeof nlh}
+ ,
+ };
+
+ memset (&smsg, 0, sizeof (struct msghdr));
+
+ smsg.msg_iov = iov;
+ smsg.msg_iovlen = 2;
+
+ struct udev_list_entry *list_entry;
+ uint64_t tag_bloom_bits;
+
+ // serialize the device
+ blen = udev_device_get_properties_monitor_buf (udev_device, &buf);
+ if (blen < 32)
+ {
+ return -EINVAL;
+ }
+
+ /* fill in versioned header */
+ val = udev_device_get_subsystem (udev_device);
+ nlh.filter_subsystem_hash = htonl (util_string_hash32 (val));
+
+ val = udev_device_get_devtype (udev_device);
+ if (val != NULL)
+ {
+ nlh.filter_devtype_hash = htonl (util_string_hash32 (val));
+ }
+
+ /* add tag bloom filter */
+ tag_bloom_bits = 0;
+ udev_list_entry_foreach (list_entry,
+ udev_device_get_tags_list_entry (udev_device))
+ tag_bloom_bits |=
+ util_string_bloom64 (udev_list_entry_get_name (list_entry));
+
+ if (tag_bloom_bits > 0)
+ {
+ nlh.filter_tag_bloom_hi = htonl (tag_bloom_bits >> 32);
+ nlh.filter_tag_bloom_lo = htonl (tag_bloom_bits & 0xffffffff);
+ }
+
+ /* add properties list */
+ nlh.properties_off = iov[0].iov_len;
+ nlh.properties_len = blen;
+ iov[1].iov_base = (char *) buf;
+ iov[1].iov_len = blen;
+
+ /*
+ * Use custom address for target, or the default one.
+ *
+ * If we send to a multicast group, we will get
+ * ECONNREFUSED, which is expected.
+ */
+
+ if (udev_monitor->type == UDEV_MONITOR_TYPE_KERNEL)
+ {
+
+ sock = udev_monitor->sock;
+
+ if (destination)
+ smsg.msg_name = &destination->snl;
+ else
+ smsg.msg_name = &udev_monitor->snl_destination;
+
+ smsg.msg_namelen = sizeof (struct sockaddr_nl);
+ }
+ else
+ {
+
+ sock = udev_monitor->sock_fs;
+ }
+
+ count = sendmsg (sock, &smsg, 0);
+ if (count < 0)
+ {
+
+ if (!destination)
+ {
+ log_debug
+ ("passed unknown number of bytes to netlink monitor %p",
+ udev_monitor);
+ return 0;
+ }
+ else
+ {
+ return -errno;
+ }
+ }
+
+ log_debug ("passed %zi bytes to netlink monitor %p", count, udev_monitor);
+ return count;
}
/**
@@ -1065,15 +1237,20 @@ int udev_monitor_send_device(struct udev_monitor *udev_monitor, struct udev_moni
*
* Returns: 0 on success, otherwise a negative error value.
*/
-int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype)
+int
+udev_monitor_filter_add_match_subsystem_devtype (struct udev_monitor
+ *udev_monitor,
+ const char *subsystem,
+ const char *devtype)
{
- if (udev_monitor == NULL)
- return -EINVAL;
- if (subsystem == NULL)
- return -EINVAL;
- if (udev_list_entry_add(&udev_monitor->filter_subsystem_list, subsystem, devtype) == NULL)
- return -ENOMEM;
- return 0;
+ if (udev_monitor == NULL)
+ return -EINVAL;
+ if (subsystem == NULL)
+ return -EINVAL;
+ if (udev_list_entry_add
+ (&udev_monitor->filter_subsystem_list, subsystem, devtype) == NULL)
+ return -ENOMEM;
+ return 0;
}
/**
@@ -1088,15 +1265,17 @@ int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_mo
*
* Returns: 0 on success, otherwise a negative error value.
*/
-int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag)
+int
+udev_monitor_filter_add_match_tag (struct udev_monitor *udev_monitor,
+ const char *tag)
{
- if (udev_monitor == NULL)
- return -EINVAL;
- if (tag == NULL)
- return -EINVAL;
- if (udev_list_entry_add(&udev_monitor->filter_tag_list, tag, NULL) == NULL)
- return -ENOMEM;
- return 0;
+ if (udev_monitor == NULL)
+ return -EINVAL;
+ if (tag == NULL)
+ return -EINVAL;
+ if (udev_list_entry_add (&udev_monitor->filter_tag_list, tag, NULL) == NULL)
+ return -ENOMEM;
+ return 0;
}
/**
@@ -1107,10 +1286,12 @@ int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const c
*
* Returns: 0 on success, otherwise a negative error value.
*/
-int udev_monitor_filter_remove(struct udev_monitor *udev_monitor)
+int
+udev_monitor_filter_remove (struct udev_monitor *udev_monitor)
{
- static struct sock_fprog filter = { 0, NULL };
+ static struct sock_fprog filter = { 0, NULL };
- udev_list_cleanup(&udev_monitor->filter_subsystem_list);
- return setsockopt(udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter));
+ udev_list_cleanup (&udev_monitor->filter_subsystem_list);
+ return setsockopt (udev_monitor->sock, SOL_SOCKET, SO_ATTACH_FILTER,
+ &filter, sizeof (filter));
}
diff --git a/libudev-compat/libudev-private.h b/libudev-compat/libudev-private.h
index 8fc7459..366b443 100644
--- a/libudev-compat/libudev-private.h
+++ b/libudev-compat/libudev-private.h
@@ -48,63 +48,83 @@
#define WRITE_END 1
/* libudev.c */
-int udev_get_rules_path(struct udev *udev, char **path[], usec_t *ts_usec[]);
+int udev_get_rules_path (struct udev *udev, char **path[],
+ usec_t * ts_usec[]);
/* libudev-device.c */
-struct udev_device *udev_device_new_from_nulstr(struct udev *udev, char *nulstr, ssize_t buflen);
-struct udev_device *udev_device_new_from_synthetic_event(struct udev *udev, const char *syspath, const char *action);
-struct udev_device *udev_device_shallow_clone(struct udev_device *old_device);
-struct udev_device *udev_device_clone_with_db(struct udev_device *old_device);
-int udev_device_copy_properties(struct udev_device *dst, struct udev_device *src);
-mode_t udev_device_get_devnode_mode(struct udev_device *udev_device);
-uid_t udev_device_get_devnode_uid(struct udev_device *udev_device);
-gid_t udev_device_get_devnode_gid(struct udev_device *udev_device);
-int udev_device_rename(struct udev_device *udev_device, const char *new_name);
-int udev_device_add_devlink(struct udev_device *udev_device, const char *devlink);
-void udev_device_cleanup_devlinks_list(struct udev_device *udev_device);
-int udev_device_add_property(struct udev_device *udev_device, const char *key, const char *value);
-char **udev_device_get_properties_envp(struct udev_device *udev_device);
-ssize_t udev_device_get_properties_monitor_buf(struct udev_device *udev_device, const char **buf);
-const char *udev_device_get_devpath_old(struct udev_device *udev_device);
-const char *udev_device_get_id_filename(struct udev_device *udev_device);
-void udev_device_set_is_initialized(struct udev_device *udev_device);
-int udev_device_add_tag(struct udev_device *udev_device, const char *tag);
-void udev_device_remove_tag(struct udev_device *udev_device, const char *tag);
-void udev_device_cleanup_tags_list(struct udev_device *udev_device);
-usec_t udev_device_get_usec_initialized(struct udev_device *udev_device);
-void udev_device_ensure_usec_initialized(struct udev_device *udev_device, struct udev_device *old_device);
-int udev_device_get_devlink_priority(struct udev_device *udev_device);
-int udev_device_set_devlink_priority(struct udev_device *udev_device, int prio);
-int udev_device_get_watch_handle(struct udev_device *udev_device);
-int udev_device_set_watch_handle(struct udev_device *udev_device, int handle);
-int udev_device_get_ifindex(struct udev_device *udev_device);
-void udev_device_set_info_loaded(struct udev_device *device);
-bool udev_device_get_db_persist(struct udev_device *udev_device);
-void udev_device_set_db_persist(struct udev_device *udev_device);
+struct udev_device *udev_device_new_from_nulstr (struct udev *udev,
+ char *nulstr,
+ ssize_t buflen);
+struct udev_device *udev_device_new_from_synthetic_event (struct udev *udev,
+ const char *syspath,
+ const char *action);
+struct udev_device *udev_device_shallow_clone (struct udev_device
+ *old_device);
+struct udev_device *udev_device_clone_with_db (struct udev_device
+ *old_device);
+int udev_device_copy_properties (struct udev_device *dst,
+ struct udev_device *src);
+mode_t udev_device_get_devnode_mode (struct udev_device *udev_device);
+uid_t udev_device_get_devnode_uid (struct udev_device *udev_device);
+gid_t udev_device_get_devnode_gid (struct udev_device *udev_device);
+int udev_device_rename (struct udev_device *udev_device,
+ const char *new_name);
+int udev_device_add_devlink (struct udev_device *udev_device,
+ const char *devlink);
+void udev_device_cleanup_devlinks_list (struct udev_device *udev_device);
+int udev_device_add_property (struct udev_device *udev_device,
+ const char *key, const char *value);
+char **udev_device_get_properties_envp (struct udev_device *udev_device);
+ssize_t udev_device_get_properties_monitor_buf (struct udev_device
+ *udev_device,
+ const char **buf);
+const char *udev_device_get_devpath_old (struct udev_device *udev_device);
+const char *udev_device_get_id_filename (struct udev_device *udev_device);
+void udev_device_set_is_initialized (struct udev_device *udev_device);
+int udev_device_add_tag (struct udev_device *udev_device, const char *tag);
+void udev_device_remove_tag (struct udev_device *udev_device,
+ const char *tag);
+void udev_device_cleanup_tags_list (struct udev_device *udev_device);
+usec_t udev_device_get_usec_initialized (struct udev_device *udev_device);
+void udev_device_ensure_usec_initialized (struct udev_device *udev_device,
+ struct udev_device *old_device);
+int udev_device_get_devlink_priority (struct udev_device *udev_device);
+int udev_device_set_devlink_priority (struct udev_device *udev_device,
+ int prio);
+int udev_device_get_watch_handle (struct udev_device *udev_device);
+int udev_device_set_watch_handle (struct udev_device *udev_device,
+ int handle);
+int udev_device_get_ifindex (struct udev_device *udev_device);
+void udev_device_set_info_loaded (struct udev_device *device);
+bool udev_device_get_db_persist (struct udev_device *udev_device);
+void udev_device_set_db_persist (struct udev_device *udev_device);
/* libudev-device-private.c */
-int udev_device_update_db(struct udev_device *udev_device);
-int udev_device_delete_db(struct udev_device *udev_device);
-int udev_device_tag_index(struct udev_device *dev, struct udev_device *dev_old, bool add);
-
+int udev_device_update_db (struct udev_device *udev_device);
+int udev_device_delete_db (struct udev_device *udev_device);
+int udev_device_tag_index (struct udev_device *dev,
+ struct udev_device *dev_old, bool add);
/* libudev-list.c */
-struct udev_list_node {
- struct udev_list_node *next, *prev;
+struct udev_list_node
+{
+ struct udev_list_node *next, *prev;
};
-struct udev_list {
- struct udev *udev;
- struct udev_list_node node;
- struct udev_list_entry **entries;
- unsigned int entries_cur;
- unsigned int entries_max;
- bool unique;
+struct udev_list
+{
+ struct udev *udev;
+ struct udev_list_node node;
+ struct udev_list_entry **entries;
+ unsigned int entries_cur;
+ unsigned int entries_max;
+ bool unique;
};
#define UDEV_LIST(list) struct udev_list_node list = { &(list), &(list) }
-void udev_list_node_init(struct udev_list_node *list);
-int udev_list_node_is_empty(struct udev_list_node *list);
-void udev_list_node_append(struct udev_list_node *new, struct udev_list_node *list);
-void udev_list_node_remove(struct udev_list_node *entry);
+void udev_list_node_init (struct udev_list_node *list);
+int udev_list_node_is_empty (struct udev_list_node *list);
+void udev_list_node_append (struct udev_list_node *new,
+ struct udev_list_node *list);
+void udev_list_node_remove (struct udev_list_node *entry);
#define udev_list_node_foreach(node, list) \
for (node = (list)->next; \
node != list; \
@@ -113,18 +133,20 @@ void udev_list_node_remove(struct udev_list_node *entry);
for (node = (list)->next, tmp = (node)->next; \
node != list; \
node = tmp, tmp = (tmp)->next)
-void udev_list_init(struct udev *udev, struct udev_list *list, bool unique);
-void udev_list_cleanup(struct udev_list *list);
-struct udev_list_entry *udev_list_get_entry(struct udev_list *list);
-struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *name, const char *value);
-void udev_list_entry_delete(struct udev_list_entry *entry);
-int udev_list_entry_get_num(struct udev_list_entry *list_entry);
-void udev_list_entry_set_num(struct udev_list_entry *list_entry, int num);
+void udev_list_init (struct udev *udev, struct udev_list *list, bool unique);
+void udev_list_cleanup (struct udev_list *list);
+struct udev_list_entry *udev_list_get_entry (struct udev_list *list);
+struct udev_list_entry *udev_list_entry_add (struct udev_list *list,
+ const char *name,
+ const char *value);
+void udev_list_entry_delete (struct udev_list_entry *entry);
+int udev_list_entry_get_num (struct udev_list_entry *list_entry);
+void udev_list_entry_set_num (struct udev_list_entry *list_entry, int num);
#define udev_list_entry_foreach_safe(entry, tmp, first) \
for (entry = first, tmp = udev_list_entry_get_next(entry); \
entry != NULL; \
entry = tmp, tmp = udev_list_entry_get_next(tmp))
-
+
/* libudev-monitor.c - netlink/unix socket communication */
/**
@@ -134,89 +156,104 @@ void udev_list_entry_set_num(struct udev_list_entry *list_entry, int num);
* Connects to a device event source.
*/
-union sockaddr_union {
- struct sockaddr sa;
- struct sockaddr_in in;
- struct sockaddr_in6 in6;
- struct sockaddr_un un;
- struct sockaddr_nl nl;
- struct sockaddr_storage storage;
- struct sockaddr_ll ll;
+union sockaddr_union
+{
+ struct sockaddr sa;
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ struct sockaddr_un un;
+ struct sockaddr_nl nl;
+ struct sockaddr_storage storage;
+ struct sockaddr_ll ll;
};
-
/**
* udev_monitor:
*
* Opaque object handling an event source.
*/
-struct udev_monitor {
- struct udev *udev;
- int refcount;
-
- int type; // libudev-compat: kernel or udev link?
- int sock; // libudev-compat: for udev-links, this is a socketpair sink which receives udev devices
- // libudev-compat: for kernel-links, this is a netlink socket
- union sockaddr_union snl;
- union sockaddr_union snl_trusted_sender;
- union sockaddr_union snl_destination;
- socklen_t addrlen;
- struct udev_list filter_subsystem_list;
- struct udev_list filter_tag_list;
- bool bound;
-
- // new in libudev-compat
- int sock_fs; // socketpair source into which we send udev_devices
- int events_wd; // watch descriptor for our events directory
- int inotify_fd; // pollable one-shot inotify file descriptor watching the events directory for IN_CREATE. Oneshot because it can overflow.
- int epoll_fd; // pollable handle for detecting either the availability of previously-found events (signaled by sock_fs) or new events (inotify_fd)
-
- pid_t pid; // the PID of the process at the time this monitor was created
- char events_dir[PATH_MAX+1]; // path to the directory we watch
-
- int slot; // monitor slot in our global monitor table
+struct udev_monitor
+{
+ struct udev *udev;
+ int refcount;
+
+ int type; // libudev-compat: kernel or udev link?
+ int sock; // libudev-compat: for udev-links, this is a socketpair sink which receives udev devices
+ // libudev-compat: for kernel-links, this is a netlink socket
+ union sockaddr_union snl;
+ union sockaddr_union snl_trusted_sender;
+ union sockaddr_union snl_destination;
+ socklen_t addrlen;
+ struct udev_list filter_subsystem_list;
+ struct udev_list filter_tag_list;
+ bool bound;
+
+ // new in libudev-compat
+ int sock_fs; // socketpair source into which we send udev_devices
+ int events_wd; // watch descriptor for our events directory
+ int inotify_fd; // pollable one-shot inotify file descriptor watching the events directory for IN_CREATE. Oneshot because it can overflow.
+ int epoll_fd; // pollable handle for detecting either the availability of previously-found events (signaled by sock_fs) or new events (inotify_fd)
+
+ pid_t pid; // the PID of the process at the time this monitor was created
+ char events_dir[PATH_MAX + 1]; // path to the directory we watch
+
+ int slot; // monitor slot in our global monitor table
};
// types of monitors
#define UDEV_MONITOR_TYPE_KERNEL 1
#define UDEV_MONITOR_TYPE_UDEV 2
-int udev_monitor_disconnect(struct udev_monitor *udev_monitor);
-int udev_monitor_allow_unicast_sender(struct udev_monitor *udev_monitor, struct udev_monitor *sender);
-int udev_monitor_send_device(struct udev_monitor *udev_monitor,
- struct udev_monitor *destination, struct udev_device *udev_device);
-struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const char *name, int fd);
-int udev_monitor_filter_update(struct udev_monitor *udev_monitor);
+int udev_monitor_disconnect (struct udev_monitor *udev_monitor);
+int udev_monitor_allow_unicast_sender (struct udev_monitor *udev_monitor,
+ struct udev_monitor *sender);
+int udev_monitor_send_device (struct udev_monitor *udev_monitor,
+ struct udev_monitor *destination,
+ struct udev_device *udev_device);
+struct udev_monitor *udev_monitor_new_from_netlink_fd (struct udev *udev,
+ const char *name,
+ int fd);
+int udev_monitor_filter_update (struct udev_monitor *udev_monitor);
/* libudev-queue.c */
-unsigned long long int udev_get_kernel_seqnum(struct udev *udev);
-int udev_queue_read_seqnum(FILE *queue_file, unsigned long long int *seqnum);
-ssize_t udev_queue_read_devpath(FILE *queue_file, char *devpath, size_t size);
-ssize_t udev_queue_skip_devpath(FILE *queue_file);
+unsigned long long int udev_get_kernel_seqnum (struct udev *udev);
+int udev_queue_read_seqnum (FILE * queue_file,
+ unsigned long long int *seqnum);
+ssize_t udev_queue_read_devpath (FILE * queue_file, char *devpath,
+ size_t size);
+ssize_t udev_queue_skip_devpath (FILE * queue_file);
/* libudev-queue-private.c */
-struct udev_queue_export *udev_queue_export_new(struct udev *udev);
-struct udev_queue_export *udev_queue_export_unref(struct udev_queue_export *udev_queue_export);
-void udev_queue_export_cleanup(struct udev_queue_export *udev_queue_export);
-int udev_queue_export_device_queued(struct udev_queue_export *udev_queue_export, struct udev_device *udev_device);
-int udev_queue_export_device_finished(struct udev_queue_export *udev_queue_export, struct udev_device *udev_device);
+struct udev_queue_export *udev_queue_export_new (struct udev *udev);
+struct udev_queue_export *udev_queue_export_unref (struct udev_queue_export
+ *udev_queue_export);
+void udev_queue_export_cleanup (struct udev_queue_export *udev_queue_export);
+int udev_queue_export_device_queued (struct udev_queue_export
+ *udev_queue_export,
+ struct udev_device *udev_device);
+int udev_queue_export_device_finished (struct udev_queue_export
+ *udev_queue_export,
+ struct udev_device *udev_device);
/* libudev-util.c */
#define UTIL_PATH_SIZE 1024
#define UTIL_NAME_SIZE 512
#define UTIL_LINE_SIZE 16384
#define UDEV_ALLOWED_CHARS_INPUT "/ $%?,"
-ssize_t util_get_sys_core_link_value(struct udev *udev, const char *slink, const char *syspath, char *value, size_t size);
-int util_resolve_sys_link(struct udev *udev, char *syspath, size_t size);
-int util_log_priority(const char *priority);
-size_t util_path_encode(const char *src, char *dest, size_t size);
-void util_remove_trailing_chars(char *path, char c);
-int util_replace_whitespace(const char *str, char *to, size_t len);
-int util_replace_chars(char *str, const char *white);
-unsigned int util_string_hash32(const char *key);
-uint64_t util_string_bloom64(const char *str);
+ssize_t util_get_sys_core_link_value (struct udev *udev, const char *slink,
+ const char *syspath, char *value,
+ size_t size);
+int util_resolve_sys_link (struct udev *udev, char *syspath, size_t size);
+int util_log_priority (const char *priority);
+size_t util_path_encode (const char *src, char *dest, size_t size);
+void util_remove_trailing_chars (char *path, char c);
+int util_replace_whitespace (const char *str, char *to, size_t len);
+int util_replace_chars (char *str, const char *white);
+unsigned int util_string_hash32 (const char *key);
+uint64_t util_string_bloom64 (const char *str);
/* libudev-util-private.c */
-int util_resolve_subsys_kernel(struct udev *udev, const char *string, char *result, size_t maxsize, int read_value);
+int util_resolve_subsys_kernel (struct udev *udev, const char *string,
+ char *result, size_t maxsize, int read_value);
#endif
diff --git a/libudev-compat/libudev-queue.c b/libudev-compat/libudev-queue.c
index 3f7b364..b57a48b 100644
--- a/libudev-compat/libudev-queue.c
+++ b/libudev-compat/libudev-queue.c
@@ -47,10 +47,11 @@
*
* Opaque object representing the current event queue in the udev daemon.
*/
-struct udev_queue {
- struct udev *udev;
- int refcount;
- int fd;
+struct udev_queue
+{
+ struct udev *udev;
+ int refcount;
+ int fd;
};
/**
@@ -62,21 +63,22 @@ struct udev_queue {
*
* Returns: the udev queue context, or #NULL on error.
**/
-_public_ struct udev_queue *udev_queue_new(struct udev *udev)
+_public_ struct udev_queue *
+udev_queue_new (struct udev *udev)
{
- struct udev_queue *udev_queue;
+ struct udev_queue *udev_queue;
- if (udev == NULL)
- return NULL;
+ if (udev == NULL)
+ return NULL;
- udev_queue = new0(struct udev_queue, 1);
- if (udev_queue == NULL)
- return NULL;
+ udev_queue = new0 (struct udev_queue, 1);
+ if (udev_queue == NULL)
+ return NULL;
- udev_queue->refcount = 1;
- udev_queue->udev = udev;
- udev_queue->fd = -1;
- return udev_queue;
+ udev_queue->refcount = 1;
+ udev_queue->udev = udev;
+ udev_queue->fd = -1;
+ return udev_queue;
}
/**
@@ -87,13 +89,14 @@ _public_ struct udev_queue *udev_queue_new(struct udev *udev)
*
* Returns: the same udev queue context.
**/
-_public_ struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue)
+_public_ struct udev_queue *
+udev_queue_ref (struct udev_queue *udev_queue)
{
- if (udev_queue == NULL)
- return NULL;
+ if (udev_queue == NULL)
+ return NULL;
- udev_queue->refcount++;
- return udev_queue;
+ udev_queue->refcount++;
+ return udev_queue;
}
/**
@@ -105,19 +108,20 @@ _public_ struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue)
*
* Returns: #NULL
**/
-_public_ struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue)
+_public_ struct udev_queue *
+udev_queue_unref (struct udev_queue *udev_queue)
{
- if (udev_queue == NULL)
- return NULL;
+ if (udev_queue == NULL)
+ return NULL;
- udev_queue->refcount--;
- if (udev_queue->refcount > 0)
- return NULL;
+ udev_queue->refcount--;
+ if (udev_queue->refcount > 0)
+ return NULL;
- safe_close(udev_queue->fd);
+ safe_close (udev_queue->fd);
- free(udev_queue);
- return NULL;
+ free (udev_queue);
+ return NULL;
}
/**
@@ -128,11 +132,12 @@ _public_ struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue)
*
* Returns: the udev library context.
**/
-_public_ struct udev *udev_queue_get_udev(struct udev_queue *udev_queue)
+_public_ struct udev *
+udev_queue_get_udev (struct udev_queue *udev_queue)
{
- if (udev_queue == NULL)
- return NULL;
- return udev_queue->udev;
+ if (udev_queue == NULL)
+ return NULL;
+ return udev_queue->udev;
}
/**
@@ -143,9 +148,10 @@ _public_ struct udev *udev_queue_get_udev(struct udev_queue *udev_queue)
*
* Returns: 0.
**/
-_public_ unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue)
+_public_ unsigned long long int
+udev_queue_get_kernel_seqnum (struct udev_queue *udev_queue)
{
- return 0;
+ return 0;
}
/**
@@ -156,9 +162,10 @@ _public_ unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *
*
* Returns: 0.
**/
-_public_ unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue)
+_public_ unsigned long long int
+udev_queue_get_udev_seqnum (struct udev_queue *udev_queue)
{
- return 0;
+ return 0;
}
/**
@@ -169,9 +176,10 @@ _public_ unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *ud
*
* Returns: a flag indicating if udev is active.
**/
-_public_ int udev_queue_get_udev_is_active(struct udev_queue *udev_queue)
+_public_ int
+udev_queue_get_udev_is_active (struct udev_queue *udev_queue)
{
- return access("/run/udev/control", F_OK) >= 0;
+ return access ("/run/udev/control", F_OK) >= 0;
}
/**
@@ -182,9 +190,10 @@ _public_ int udev_queue_get_udev_is_active(struct udev_queue *udev_queue)
*
* Returns: a flag indicating if udev is currently handling events.
**/
-_public_ int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue)
+_public_ int
+udev_queue_get_queue_is_empty (struct udev_queue *udev_queue)
{
- return access("/run/udev/queue", F_OK) < 0;
+ return access ("/run/udev/queue", F_OK) < 0;
}
/**
@@ -198,10 +207,13 @@ _public_ int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue)
*
* Returns: a flag indicating if udev is currently handling events.
**/
-_public_ int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue,
- unsigned long long int start, unsigned long long int end)
+_public_ int
+udev_queue_get_seqnum_sequence_is_finished (struct udev_queue
+ *udev_queue,
+ unsigned long long int
+ start, unsigned long long int end)
{
- return udev_queue_get_queue_is_empty(udev_queue);
+ return udev_queue_get_queue_is_empty (udev_queue);
}
/**
@@ -214,9 +226,11 @@ _public_ int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_
*
* Returns: a flag indicating if udev is currently handling events.
**/
-_public_ int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum)
+_public_ int
+udev_queue_get_seqnum_is_finished (struct udev_queue *udev_queue,
+ unsigned long long int seqnum)
{
- return udev_queue_get_queue_is_empty(udev_queue);
+ return udev_queue_get_queue_is_empty (udev_queue);
}
/**
@@ -227,9 +241,10 @@ _public_ int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, un
*
* Returns: NULL.
**/
-_public_ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue)
+_public_ struct udev_list_entry *
+udev_queue_get_queued_list_entry (struct udev_queue *udev_queue)
{
- return NULL;
+ return NULL;
}
/**
@@ -238,26 +253,29 @@ _public_ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_qu
*
* Returns: a file descriptor to watch for a queue to become empty.
*/
-_public_ int udev_queue_get_fd(struct udev_queue *udev_queue) {
- int fd;
- int r;
-
- if (udev_queue->fd >= 0)
- return udev_queue->fd;
-
- fd = inotify_init1(IN_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- r = inotify_add_watch(fd, "/run/udev" , IN_DELETE);
- if (r < 0) {
- r = -errno;
- close(fd);
- return r;
- }
-
- udev_queue->fd = fd;
- return fd;
+_public_ int
+udev_queue_get_fd (struct udev_queue *udev_queue)
+{
+ int fd;
+ int r;
+
+ if (udev_queue->fd >= 0)
+ return udev_queue->fd;
+
+ fd = inotify_init1 (IN_CLOEXEC);
+ if (fd < 0)
+ return -errno;
+
+ r = inotify_add_watch (fd, "/run/udev", IN_DELETE);
+ if (r < 0)
+ {
+ r = -errno;
+ close (fd);
+ return r;
+ }
+
+ udev_queue->fd = fd;
+ return fd;
}
/**
@@ -266,9 +284,11 @@ _public_ int udev_queue_get_fd(struct udev_queue *udev_queue) {
*
* Returns: the result of clearing the watch for queue changes.
*/
-_public_ int udev_queue_flush(struct udev_queue *udev_queue) {
- if (udev_queue->fd < 0)
- return -EINVAL;
+_public_ int
+udev_queue_flush (struct udev_queue *udev_queue)
+{
+ if (udev_queue->fd < 0)
+ return -EINVAL;
- return flush_fd(udev_queue->fd);
+ return flush_fd (udev_queue->fd);
}
diff --git a/libudev-compat/libudev-util.c b/libudev-compat/libudev-util.c
index 8af200f..c8ff9af 100644
--- a/libudev-compat/libudev-util.c
+++ b/libudev-compat/libudev-util.c
@@ -47,257 +47,290 @@
*/
/* handle "[/]" format */
-int util_resolve_subsys_kernel(struct udev *udev, const char *string,
- char *result, size_t maxsize, int read_value)
+int
+util_resolve_subsys_kernel (struct udev *udev, const char *string,
+ char *result, size_t maxsize, int read_value)
{
- char temp[UTIL_PATH_SIZE];
- char *subsys;
- char *sysname;
- struct udev_device *dev;
- char *attr;
-
- if (string[0] != '[')
- return -1;
-
- strscpy(temp, sizeof(temp), string);
-
- subsys = &temp[1];
-
- sysname = strchr(subsys, '/');
- if (sysname == NULL)
- return -1;
- sysname[0] = '\0';
- sysname = &sysname[1];
-
- attr = strchr(sysname, ']');
- if (attr == NULL)
- return -1;
- attr[0] = '\0';
- attr = &attr[1];
- if (attr[0] == '/')
- attr = &attr[1];
- if (attr[0] == '\0')
- attr = NULL;
-
- if (read_value && attr == NULL)
- return -1;
-
- dev = udev_device_new_from_subsystem_sysname(udev, subsys, sysname);
- if (dev == NULL)
- return -1;
-
- if (read_value) {
- const char *val;
-
- val = udev_device_get_sysattr_value(dev, attr);
- if (val != NULL)
- strscpy(result, maxsize, val);
- else
- result[0] = '\0';
- log_debug("value '[%s/%s]%s' is '%s'", subsys, sysname, attr, result);
- } else {
- size_t l;
- char *s;
-
- s = result;
- l = strpcpyl(&s, maxsize, udev_device_get_syspath(dev), NULL);
- if (attr != NULL)
- strpcpyl(&s, l, "/", attr, NULL);
- log_debug("path '[%s/%s]%s' is '%s'", subsys, sysname, attr, result);
- }
- udev_device_unref(dev);
- return 0;
+ char temp[UTIL_PATH_SIZE];
+ char *subsys;
+ char *sysname;
+ struct udev_device *dev;
+ char *attr;
+
+ if (string[0] != '[')
+ return -1;
+
+ strscpy (temp, sizeof (temp), string);
+
+ subsys = &temp[1];
+
+ sysname = strchr (subsys, '/');
+ if (sysname == NULL)
+ return -1;
+ sysname[0] = '\0';
+ sysname = &sysname[1];
+
+ attr = strchr (sysname, ']');
+ if (attr == NULL)
+ return -1;
+ attr[0] = '\0';
+ attr = &attr[1];
+ if (attr[0] == '/')
+ attr = &attr[1];
+ if (attr[0] == '\0')
+ attr = NULL;
+
+ if (read_value && attr == NULL)
+ return -1;
+
+ dev = udev_device_new_from_subsystem_sysname (udev, subsys, sysname);
+ if (dev == NULL)
+ return -1;
+
+ if (read_value)
+ {
+ const char *val;
+
+ val = udev_device_get_sysattr_value (dev, attr);
+ if (val != NULL)
+ strscpy (result, maxsize, val);
+ else
+ result[0] = '\0';
+ log_debug ("value '[%s/%s]%s' is '%s'", subsys, sysname, attr, result);
+ }
+ else
+ {
+ size_t l;
+ char *s;
+
+ s = result;
+ l = strpcpyl (&s, maxsize, udev_device_get_syspath (dev), NULL);
+ if (attr != NULL)
+ strpcpyl (&s, l, "/", attr, NULL);
+ log_debug ("path '[%s/%s]%s' is '%s'", subsys, sysname, attr, result);
+ }
+ udev_device_unref (dev);
+ return 0;
}
-ssize_t util_get_sys_core_link_value(struct udev *udev, const char *slink, const char *syspath, char *value, size_t size)
+ssize_t
+util_get_sys_core_link_value (struct udev * udev, const char *slink,
+ const char *syspath, char *value, size_t size)
{
- char path[UTIL_PATH_SIZE];
- char target[UTIL_PATH_SIZE];
- ssize_t len;
- const char *pos;
-
- strscpyl(path, sizeof(path), syspath, "/", slink, NULL);
- len = readlink(path, target, sizeof(target));
- if (len <= 0 || len == (ssize_t)sizeof(target))
- return -1;
- target[len] = '\0';
- pos = strrchr(target, '/');
- if (pos == NULL)
- return -1;
- pos = &pos[1];
- return strscpy(value, size, pos);
+ char path[UTIL_PATH_SIZE];
+ char target[UTIL_PATH_SIZE];
+ ssize_t len;
+ const char *pos;
+
+ strscpyl (path, sizeof (path), syspath, "/", slink, NULL);
+ len = readlink (path, target, sizeof (target));
+ if (len <= 0 || len == (ssize_t) sizeof (target))
+ return -1;
+ target[len] = '\0';
+ pos = strrchr (target, '/');
+ if (pos == NULL)
+ return -1;
+ pos = &pos[1];
+ return strscpy (value, size, pos);
}
-int util_resolve_sys_link(struct udev *udev, char *syspath, size_t size)
+int
+util_resolve_sys_link (struct udev *udev, char *syspath, size_t size)
{
- char link_target[UTIL_PATH_SIZE];
-
- ssize_t len;
- int i;
- int back;
- char *base = NULL;
-
- len = readlink(syspath, link_target, sizeof(link_target));
- if (len <= 0 || len == (ssize_t)sizeof(link_target))
- return -1;
- link_target[len] = '\0';
-
- for (back = 0; startswith(&link_target[back * 3], "../"); back++)
- ;
- for (i = 0; i <= back; i++) {
- base = strrchr(syspath, '/');
- if (base == NULL)
- return -EINVAL;
- base[0] = '\0';
- }
-
- strscpyl(base, size - (base - syspath), "/", &link_target[back * 3], NULL);
- return 0;
+ char link_target[UTIL_PATH_SIZE];
+
+ ssize_t len;
+ int i;
+ int back;
+ char *base = NULL;
+
+ len = readlink (syspath, link_target, sizeof (link_target));
+ if (len <= 0 || len == (ssize_t) sizeof (link_target))
+ return -1;
+ link_target[len] = '\0';
+
+ for (back = 0; startswith (&link_target[back * 3], "../"); back++);
+ for (i = 0; i <= back; i++)
+ {
+ base = strrchr (syspath, '/');
+ if (base == NULL)
+ return -EINVAL;
+ base[0] = '\0';
+ }
+
+ strscpyl (base, size - (base - syspath), "/", &link_target[back * 3], NULL);
+ return 0;
}
-int util_log_priority(const char *priority)
+int
+util_log_priority (const char *priority)
{
- char *endptr;
- int prio;
-
- prio = strtoul(priority, &endptr, 10);
- if (endptr[0] == '\0' || isspace(endptr[0])) {
- if (prio >= 0 && prio <= 7) {
- return prio;
- }
- else {
- return -ERANGE;
- }
- }
-
- // So, I can't find this method anywhere... -Jude
- // return log_level_from_string(priority);
-
- if( strcasecmp( priority, "err" ) == 0 ) {
- return LOG_ERR;
- }
- else if( strcasecmp( priority, "debug" ) == 0 ) {
- return LOG_DEBUG;
- }
- else if( strcasecmp( priority, "info" ) == 0 ) {
- return LOG_INFO;
- }
-
- return -EINVAL;
+ char *endptr;
+ int prio;
+
+ prio = strtoul (priority, &endptr, 10);
+ if (endptr[0] == '\0' || isspace (endptr[0]))
+ {
+ if (prio >= 0 && prio <= 7)
+ {
+ return prio;
+ }
+ else
+ {
+ return -ERANGE;
+ }
+ }
+ // So, I can't find this method anywhere... -Jude
+ // return log_level_from_string(priority);
+
+ if (strcasecmp (priority, "err") == 0)
+ {
+ return LOG_ERR;
+ }
+ else if (strcasecmp (priority, "debug") == 0)
+ {
+ return LOG_DEBUG;
+ }
+ else if (strcasecmp (priority, "info") == 0)
+ {
+ return LOG_INFO;
+ }
+
+ return -EINVAL;
}
-size_t util_path_encode(const char *src, char *dest, size_t size)
+size_t
+util_path_encode (const char *src, char *dest, size_t size)
{
- size_t i, j;
-
- for (i = 0, j = 0; src[i] != '\0'; i++) {
- if (src[i] == '/') {
- if (j+4 >= size) {
- j = 0;
- break;
- }
- memcpy(&dest[j], "\\x2f", 4);
- j += 4;
- } else if (src[i] == '\\') {
- if (j+4 >= size) {
- j = 0;
- break;
- }
- memcpy(&dest[j], "\\x5c", 4);
- j += 4;
- } else {
- if (j+1 >= size) {
- j = 0;
- break;
- }
- dest[j] = src[i];
- j++;
- }
- }
- dest[j] = '\0';
- return j;
+ size_t i, j;
+
+ for (i = 0, j = 0; src[i] != '\0'; i++)
+ {
+ if (src[i] == '/')
+ {
+ if (j + 4 >= size)
+ {
+ j = 0;
+ break;
+ }
+ memcpy (&dest[j], "\\x2f", 4);
+ j += 4;
+ }
+ else if (src[i] == '\\')
+ {
+ if (j + 4 >= size)
+ {
+ j = 0;
+ break;
+ }
+ memcpy (&dest[j], "\\x5c", 4);
+ j += 4;
+ }
+ else
+ {
+ if (j + 1 >= size)
+ {
+ j = 0;
+ break;
+ }
+ dest[j] = src[i];
+ j++;
+ }
+ }
+ dest[j] = '\0';
+ return j;
}
-void util_remove_trailing_chars(char *path, char c)
+void
+util_remove_trailing_chars (char *path, char c)
{
- size_t len;
+ size_t len;
- if (path == NULL)
- return;
- len = strlen(path);
- while (len > 0 && path[len-1] == c)
- path[--len] = '\0';
+ if (path == NULL)
+ return;
+ len = strlen (path);
+ while (len > 0 && path[len - 1] == c)
+ path[--len] = '\0';
}
-int util_replace_whitespace(const char *str, char *to, size_t len)
+int
+util_replace_whitespace (const char *str, char *to, size_t len)
{
- size_t i, j;
-
- /* strip trailing whitespace */
- len = strnlen(str, len);
- while (len && isspace(str[len-1]))
- len--;
-
- /* strip leading whitespace */
- i = 0;
- while (isspace(str[i]) && (i < len))
- i++;
-
- j = 0;
- while (i < len) {
- /* substitute multiple whitespace with a single '_' */
- if (isspace(str[i])) {
- while (isspace(str[i]))
- i++;
- to[j++] = '_';
- }
- to[j++] = str[i++];
- }
- to[j] = '\0';
- return 0;
+ size_t i, j;
+
+ /* strip trailing whitespace */
+ len = strnlen (str, len);
+ while (len && isspace (str[len - 1]))
+ len--;
+
+ /* strip leading whitespace */
+ i = 0;
+ while (isspace (str[i]) && (i < len))
+ i++;
+
+ j = 0;
+ while (i < len)
+ {
+ /* substitute multiple whitespace with a single '_' */
+ if (isspace (str[i]))
+ {
+ while (isspace (str[i]))
+ i++;
+ to[j++] = '_';
+ }
+ to[j++] = str[i++];
+ }
+ to[j] = '\0';
+ return 0;
}
/* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */
-int util_replace_chars(char *str, const char *white)
+int
+util_replace_chars (char *str, const char *white)
{
- size_t i = 0;
- int replaced = 0;
-
- while (str[i] != '\0') {
- int len;
-
- if (whitelisted_char_for_devnode(str[i], white)) {
- i++;
- continue;
- }
-
- /* accept hex encoding */
- if (str[i] == '\\' && str[i+1] == 'x') {
- i += 2;
- continue;
- }
-
- /* accept valid utf8 */
- len = utf8_encoded_valid_unichar(&str[i]);
- if (len > 1) {
- i += len;
- continue;
- }
-
- /* if space is allowed, replace whitespace with ordinary space */
- if (isspace(str[i]) && white != NULL && strchr(white, ' ') != NULL) {
- str[i] = ' ';
- i++;
- replaced++;
- continue;
- }
-
- /* everything else is replaced with '_' */
- str[i] = '_';
- i++;
- replaced++;
- }
- return replaced;
+ size_t i = 0;
+ int replaced = 0;
+
+ while (str[i] != '\0')
+ {
+ int len;
+
+ if (whitelisted_char_for_devnode (str[i], white))
+ {
+ i++;
+ continue;
+ }
+
+ /* accept hex encoding */
+ if (str[i] == '\\' && str[i + 1] == 'x')
+ {
+ i += 2;
+ continue;
+ }
+
+ /* accept valid utf8 */
+ len = utf8_encoded_valid_unichar (&str[i]);
+ if (len > 1)
+ {
+ i += len;
+ continue;
+ }
+
+ /* if space is allowed, replace whitespace with ordinary space */
+ if (isspace (str[i]) && white != NULL && strchr (white, ' ') != NULL)
+ {
+ str[i] = ' ';
+ i++;
+ replaced++;
+ continue;
+ }
+
+ /* everything else is replaced with '_' */
+ str[i] = '_';
+ i++;
+ replaced++;
+ }
+ return replaced;
}
/**
@@ -312,25 +345,28 @@ int util_replace_chars(char *str, const char *white)
*
* Returns: 0 if the entire string was copied, non-zero otherwise.
**/
-_public_ int udev_util_encode_string(const char *str, char *str_enc, size_t len)
+_public_ int
+udev_util_encode_string (const char *str, char *str_enc, size_t len)
{
- return encode_devnode_name(str, str_enc, len);
+ return encode_devnode_name (str, str_enc, len);
}
-unsigned int util_string_hash32(const char *str)
+unsigned int
+util_string_hash32 (const char *str)
{
- return MurmurHash2(str, strlen(str), 0);
+ return MurmurHash2 (str, strlen (str), 0);
}
/* get a bunch of bit numbers out of the hash, and set the bits in our bit field */
-uint64_t util_string_bloom64(const char *str)
+uint64_t
+util_string_bloom64 (const char *str)
{
- uint64_t bits = 0;
- unsigned int hash = util_string_hash32(str);
-
- bits |= 1LLU << (hash & 63);
- bits |= 1LLU << ((hash >> 6) & 63);
- bits |= 1LLU << ((hash >> 12) & 63);
- bits |= 1LLU << ((hash >> 18) & 63);
- return bits;
+ uint64_t bits = 0;
+ unsigned int hash = util_string_hash32 (str);
+
+ bits |= 1LLU << (hash & 63);
+ bits |= 1LLU << ((hash >> 6) & 63);
+ bits |= 1LLU << ((hash >> 12) & 63);
+ bits |= 1LLU << ((hash >> 18) & 63);
+ return bits;
}
diff --git a/libudev-compat/libudev.c b/libudev-compat/libudev.c
index d65415d..47a14af 100644
--- a/libudev-compat/libudev.c
+++ b/libudev-compat/libudev.c
@@ -49,12 +49,13 @@
*
* Opaque object representing the library context.
*/
-struct udev {
- int refcount;
- void (*log_fn)(struct udev *udev,
- int priority, const char *file, int line, const char *fn,
- const char *format, va_list args);
- void *userdata;
+struct udev
+{
+ int refcount;
+ void (*log_fn) (struct udev * udev,
+ int priority, const char *file, int line,
+ const char *fn, const char *format, va_list args);
+ void *userdata;
};
/**
@@ -66,10 +67,12 @@ struct udev {
*
* Returns: stored userdata
**/
-void *udev_get_userdata(struct udev *udev) {
- if (udev == NULL)
- return NULL;
- return udev->userdata;
+void *
+udev_get_userdata (struct udev *udev)
+{
+ if (udev == NULL)
+ return NULL;
+ return udev->userdata;
}
/**
@@ -79,10 +82,12 @@ void *udev_get_userdata(struct udev *udev) {
*
* Store custom @userdata in the library context.
**/
-void udev_set_userdata(struct udev *udev, void *userdata) {
- if (udev == NULL)
- return;
- udev->userdata = userdata;
+void
+udev_set_userdata (struct udev *udev, void *userdata)
+{
+ if (udev == NULL)
+ return;
+ udev->userdata = userdata;
}
/**
@@ -96,94 +101,110 @@ void udev_set_userdata(struct udev *udev, void *userdata) {
*
* Returns: a new udev library context
**/
-struct udev *udev_new(void) {
- struct udev *udev;
- _cleanup_fclose_ FILE *f = NULL;
+struct udev *
+udev_new (void)
+{
+ struct udev *udev;
+ _cleanup_fclose_ FILE *f = NULL;
- udev = new0(struct udev, 1);
- if (udev == NULL)
- return NULL;
- udev->refcount = 1;
+ udev = new0 (struct udev, 1);
+ if (udev == NULL)
+ return NULL;
+ udev->refcount = 1;
- f = fopen("/etc/udev/udev.conf", "re");
- if (f != NULL) {
- char line[UTIL_LINE_SIZE];
- unsigned line_nr = 0;
+ f = fopen ("/etc/udev/udev.conf", "re");
+ if (f != NULL)
+ {
+ char line[UTIL_LINE_SIZE];
+ unsigned line_nr = 0;
- while (fgets(line, sizeof(line), f)) {
- size_t len;
- char *key;
- char *val;
+ while (fgets (line, sizeof (line), f))
+ {
+ size_t len;
+ char *key;
+ char *val;
- line_nr++;
+ line_nr++;
- /* find key */
- key = line;
- while (isspace(key[0]))
- key++;
+ /* find key */
+ key = line;
+ while (isspace (key[0]))
+ key++;
- /* comment or empty line */
- if (key[0] == '#' || key[0] == '\0')
- continue;
+ /* comment or empty line */
+ if (key[0] == '#' || key[0] == '\0')
+ continue;
- /* split key/value */
- val = strchr(key, '=');
- if (val == NULL) {
- log_debug("/etc/udev/udev.conf:%u: missing assignment, skipping line.", line_nr);
- continue;
- }
- val[0] = '\0';
- val++;
+ /* split key/value */
+ val = strchr (key, '=');
+ if (val == NULL)
+ {
+ log_debug
+ ("/etc/udev/udev.conf:%u: missing assignment, skipping line.",
+ line_nr);
+ continue;
+ }
+ val[0] = '\0';
+ val++;
- /* find value */
- while (isspace(val[0]))
- val++;
+ /* find value */
+ while (isspace (val[0]))
+ val++;
- /* terminate key */
- len = strlen(key);
- if (len == 0)
- continue;
- while (isspace(key[len-1]))
- len--;
- key[len] = '\0';
+ /* terminate key */
+ len = strlen (key);
+ if (len == 0)
+ continue;
+ while (isspace (key[len - 1]))
+ len--;
+ key[len] = '\0';
- /* terminate value */
- len = strlen(val);
- if (len == 0)
- continue;
- while (isspace(val[len-1]))
- len--;
- val[len] = '\0';
+ /* terminate value */
+ len = strlen (val);
+ if (len == 0)
+ continue;
+ while (isspace (val[len - 1]))
+ len--;
+ val[len] = '\0';
- if (len == 0)
- continue;
+ if (len == 0)
+ continue;
- /* unquote */
- if (val[0] == '"' || val[0] == '\'') {
- if (val[len-1] != val[0]) {
- log_debug("/etc/udev/udev.conf:%u: inconsistent quoting, skipping line.", line_nr);
- continue;
- }
- val[len-1] = '\0';
- val++;
- }
+ /* unquote */
+ if (val[0] == '"' || val[0] == '\'')
+ {
+ if (val[len - 1] != val[0])
+ {
+ log_debug
+ ("/etc/udev/udev.conf:%u: inconsistent quoting, skipping line.",
+ line_nr);
+ continue;
+ }
+ val[len - 1] = '\0';
+ val++;
+ }
- if (streq(key, "udev_log")) {
- int prio;
+ if (streq (key, "udev_log"))
+ {
+ int prio;
- prio = util_log_priority(val);
- if (prio < 0) {
- log_debug("/etc/udev/udev.conf:%u: invalid log level '%s', ignoring.", line_nr, val);
- }
- else {
- log_set_max_level(prio);
- }
- continue;
- }
- }
- }
+ prio = util_log_priority (val);
+ if (prio < 0)
+ {
+ log_debug
+ ("/etc/udev/udev.conf:%u: invalid log level '%s', ignoring.",
+ line_nr, val);
+ }
+ else
+ {
+ log_set_max_level (prio);
+ }
+ continue;
+ }
+ }
+ }
- return udev;
+ return udev;
}
/**
@@ -194,11 +215,13 @@ struct udev *udev_new(void) {
*
* Returns: the passed udev library context
**/
-struct udev *udev_ref(struct udev *udev) {
- if (udev == NULL)
- return NULL;
- udev->refcount++;
- return udev;
+struct udev *
+udev_ref (struct udev *udev)
+{
+ if (udev == NULL)
+ return NULL;
+ udev->refcount++;
+ return udev;
}
/**
@@ -210,14 +233,16 @@ struct udev *udev_ref(struct udev *udev) {
*
* Returns: the passed udev library context if it has still an active reference, or #NULL otherwise.
**/
-struct udev *udev_unref(struct udev *udev) {
- if (udev == NULL)
- return NULL;
- udev->refcount--;
- if (udev->refcount > 0)
- return udev;
- free(udev);
- return NULL;
+struct udev *
+udev_unref (struct udev *udev)
+{
+ if (udev == NULL)
+ return NULL;
+ udev->refcount--;
+ if (udev->refcount > 0)
+ return udev;
+ free (udev);
+ return NULL;
}
/**
@@ -228,11 +253,14 @@ struct udev *udev_unref(struct udev *udev) {
* This function is deprecated.
*
**/
-void udev_set_log_fn(struct udev *udev,
- void (*log_fn)(struct udev *udev,
- int priority, const char *file, int line, const char *fn,
- const char *format, va_list args)) {
- return;
+void
+udev_set_log_fn (struct udev *udev,
+ void (*log_fn) (struct udev * udev,
+ int priority, const char *file, int line,
+ const char *fn, const char *format,
+ va_list args))
+{
+ return;
}
/**
@@ -242,8 +270,10 @@ void udev_set_log_fn(struct udev *udev,
* This function is deprecated.
*
**/
-int udev_get_log_priority(struct udev *udev) {
- return log_get_max_level();
+int
+udev_get_log_priority (struct udev *udev)
+{
+ return log_get_max_level ();
}
/**
@@ -254,6 +284,8 @@ int udev_get_log_priority(struct udev *udev) {
* This function is deprecated.
*
**/
-void udev_set_log_priority(struct udev *udev, int priority) {
- log_set_max_level(priority);
+void
+udev_set_log_priority (struct udev *udev, int priority)
+{
+ log_set_max_level (priority);
}
diff --git a/libudev-compat/libudev.h b/libudev-compat/libudev.h
index b1d3a16..69d9a75 100644
--- a/libudev-compat/libudev.h
+++ b/libudev-compat/libudev.h
@@ -35,7 +35,8 @@
#include
#ifdef __cplusplus
-extern "C" {
+extern "C"
+{
#endif
/*
@@ -45,29 +46,34 @@ extern "C" {
* allows custom logging
*/
-struct udev;
-struct udev *udev_ref(struct udev *udev);
-struct udev *udev_unref(struct udev *udev);
-struct udev *udev_new(void);
-void udev_set_log_fn(struct udev *udev,
- void (*log_fn)(struct udev *udev,
- int priority, const char *file, int line, const char *fn,
- const char *format, va_list args));
-int udev_get_log_priority(struct udev *udev);
-void udev_set_log_priority(struct udev *udev, int priority);
-void *udev_get_userdata(struct udev *udev);
-void udev_set_userdata(struct udev *udev, void *userdata);
+ struct udev;
+ struct udev *udev_ref (struct udev *udev);
+ struct udev *udev_unref (struct udev *udev);
+ struct udev *udev_new (void);
+ void udev_set_log_fn (struct udev *udev,
+ void (*log_fn) (struct udev * udev,
+ int priority, const char *file,
+ int line, const char *fn,
+ const char *format, va_list args));
+ int udev_get_log_priority (struct udev *udev);
+ void udev_set_log_priority (struct udev *udev, int priority);
+ void *udev_get_userdata (struct udev *udev);
+ void udev_set_userdata (struct udev *udev, void *userdata);
/*
* udev_list
*
* access to libudev generated lists
*/
-struct udev_list_entry;
-struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry);
-struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name);
-const char *udev_list_entry_get_name(struct udev_list_entry *list_entry);
-const char *udev_list_entry_get_value(struct udev_list_entry *list_entry);
+ struct udev_list_entry;
+ struct udev_list_entry *udev_list_entry_get_next (struct udev_list_entry
+ *list_entry);
+ struct udev_list_entry *udev_list_entry_get_by_name (struct
+ udev_list_entry
+ *list_entry,
+ const char *name);
+ const char *udev_list_entry_get_name (struct udev_list_entry *list_entry);
+ const char *udev_list_entry_get_value (struct udev_list_entry *list_entry);
/**
* udev_list_entry_foreach:
* @list_entry: entry to store the current position
@@ -85,134 +91,208 @@ const char *udev_list_entry_get_value(struct udev_list_entry *list_entry);
*
* access to sysfs/kernel devices
*/
-struct udev_device;
-struct udev_device *udev_device_ref(struct udev_device *udev_device);
-struct udev_device *udev_device_unref(struct udev_device *udev_device);
-struct udev *udev_device_get_udev(struct udev_device *udev_device);
-struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath);
-struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum);
-struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname);
-struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id);
-struct udev_device *udev_device_new_from_environment(struct udev *udev);
+ struct udev_device;
+ struct udev_device *udev_device_ref (struct udev_device *udev_device);
+ struct udev_device *udev_device_unref (struct udev_device *udev_device);
+ struct udev *udev_device_get_udev (struct udev_device *udev_device);
+ struct udev_device *udev_device_new_from_syspath (struct udev *udev,
+ const char *syspath);
+ struct udev_device *udev_device_new_from_devnum (struct udev *udev,
+ char type, dev_t devnum);
+ struct udev_device *udev_device_new_from_subsystem_sysname (struct udev
+ *udev,
+ const char
+ *subsystem,
+ const char
+ *sysname);
+ struct udev_device *udev_device_new_from_device_id (struct udev *udev,
+ const char *id);
+ struct udev_device *udev_device_new_from_environment (struct udev *udev);
/* udev_device_get_parent_*() does not take a reference on the returned device, it is automatically unref'd with the parent */
-struct udev_device *udev_device_get_parent(struct udev_device *udev_device);
-struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device,
- const char *subsystem, const char *devtype);
+ struct udev_device *udev_device_get_parent (struct udev_device
+ *udev_device);
+ struct udev_device *udev_device_get_parent_with_subsystem_devtype (struct
+ udev_device
+ *udev_device,
+ const
+ char
+ *subsystem,
+ const
+ char
+ *devtype);
/* retrieve device properties */
-const char *udev_device_get_devpath(struct udev_device *udev_device);
-const char *udev_device_get_subsystem(struct udev_device *udev_device);
-const char *udev_device_get_devtype(struct udev_device *udev_device);
-const char *udev_device_get_syspath(struct udev_device *udev_device);
-const char *udev_device_get_sysname(struct udev_device *udev_device);
-const char *udev_device_get_sysnum(struct udev_device *udev_device);
-const char *udev_device_get_devnode(struct udev_device *udev_device);
-int udev_device_get_is_initialized(struct udev_device *udev_device);
-struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device);
-struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device);
-struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device);
-struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device);
-const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key);
-const char *udev_device_get_driver(struct udev_device *udev_device);
-dev_t udev_device_get_devnum(struct udev_device *udev_device);
-const char *udev_device_get_action(struct udev_device *udev_device);
-unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device);
-unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device);
-const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr);
-int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value);
-int udev_device_has_tag(struct udev_device *udev_device, const char *tag);
+ const char *udev_device_get_devpath (struct udev_device *udev_device);
+ const char *udev_device_get_subsystem (struct udev_device *udev_device);
+ const char *udev_device_get_devtype (struct udev_device *udev_device);
+ const char *udev_device_get_syspath (struct udev_device *udev_device);
+ const char *udev_device_get_sysname (struct udev_device *udev_device);
+ const char *udev_device_get_sysnum (struct udev_device *udev_device);
+ const char *udev_device_get_devnode (struct udev_device *udev_device);
+ int udev_device_get_is_initialized (struct udev_device *udev_device);
+ struct udev_list_entry *udev_device_get_devlinks_list_entry (struct
+ udev_device
+ *udev_device);
+ struct udev_list_entry *udev_device_get_properties_list_entry (struct
+ udev_device
+ *udev_device);
+ struct udev_list_entry *udev_device_get_tags_list_entry (struct
+ udev_device
+ *udev_device);
+ struct udev_list_entry *udev_device_get_sysattr_list_entry (struct
+ udev_device
+ *udev_device);
+ const char *udev_device_get_property_value (struct udev_device
+ *udev_device, const char *key);
+ const char *udev_device_get_driver (struct udev_device *udev_device);
+ dev_t udev_device_get_devnum (struct udev_device *udev_device);
+ const char *udev_device_get_action (struct udev_device *udev_device);
+ unsigned long long int udev_device_get_seqnum (struct udev_device
+ *udev_device);
+ unsigned long long int udev_device_get_usec_since_initialized (struct
+ udev_device
+ *udev_device);
+ const char *udev_device_get_sysattr_value (struct udev_device
+ *udev_device,
+ const char *sysattr);
+ int udev_device_set_sysattr_value (struct udev_device *udev_device,
+ const char *sysattr, char *value);
+ int udev_device_has_tag (struct udev_device *udev_device, const char *tag);
/*
* udev_monitor
*
* access to kernel uevents and udev events
*/
-struct udev_monitor;
-struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor);
-struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor);
-struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor);
+ struct udev_monitor;
+ struct udev_monitor *udev_monitor_ref (struct udev_monitor *udev_monitor);
+ struct udev_monitor *udev_monitor_unref (struct udev_monitor *udev_monitor);
+ struct udev *udev_monitor_get_udev (struct udev_monitor *udev_monitor);
/* kernel and udev generated events over netlink */
-struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name);
+ struct udev_monitor *udev_monitor_new_from_netlink (struct udev *udev,
+ const char *name);
/* bind socket */
-int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor);
-int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size);
-int udev_monitor_get_fd(struct udev_monitor *udev_monitor);
-struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor);
+ int udev_monitor_enable_receiving (struct udev_monitor *udev_monitor);
+ int udev_monitor_set_receive_buffer_size (struct udev_monitor
+ *udev_monitor, int size);
+ int udev_monitor_get_fd (struct udev_monitor *udev_monitor);
+ struct udev_device *udev_monitor_receive_device (struct udev_monitor
+ *udev_monitor);
/* in-kernel socket filters to select messages that get delivered to a listener */
-int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor,
- const char *subsystem, const char *devtype);
-int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag);
-int udev_monitor_filter_update(struct udev_monitor *udev_monitor);
-int udev_monitor_filter_remove(struct udev_monitor *udev_monitor);
+ int udev_monitor_filter_add_match_subsystem_devtype (struct udev_monitor
+ *udev_monitor,
+ const char
+ *subsystem,
+ const char *devtype);
+ int udev_monitor_filter_add_match_tag (struct udev_monitor *udev_monitor,
+ const char *tag);
+ int udev_monitor_filter_update (struct udev_monitor *udev_monitor);
+ int udev_monitor_filter_remove (struct udev_monitor *udev_monitor);
/*
* udev_enumerate
*
* search sysfs for specific devices and provide a sorted list
*/
-struct udev_enumerate;
-struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate);
-struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate);
-struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate);
-struct udev_enumerate *udev_enumerate_new(struct udev *udev);
+ struct udev_enumerate;
+ struct udev_enumerate *udev_enumerate_ref (struct udev_enumerate
+ *udev_enumerate);
+ struct udev_enumerate *udev_enumerate_unref (struct udev_enumerate
+ *udev_enumerate);
+ struct udev *udev_enumerate_get_udev (struct udev_enumerate
+ *udev_enumerate);
+ struct udev_enumerate *udev_enumerate_new (struct udev *udev);
/* device properties filter */
-int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
-int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
-int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
-int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
-int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value);
-int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname);
-int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag);
-int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent);
-int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate);
-int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath);
+ int udev_enumerate_add_match_subsystem (struct udev_enumerate
+ *udev_enumerate,
+ const char *subsystem);
+ int udev_enumerate_add_nomatch_subsystem (struct udev_enumerate
+ *udev_enumerate,
+ const char *subsystem);
+ int udev_enumerate_add_match_sysattr (struct udev_enumerate
+ *udev_enumerate,
+ const char *sysattr,
+ const char *value);
+ int udev_enumerate_add_nomatch_sysattr (struct udev_enumerate
+ *udev_enumerate,
+ const char *sysattr,
+ const char *value);
+ int udev_enumerate_add_match_property (struct udev_enumerate
+ *udev_enumerate,
+ const char *property,
+ const char *value);
+ int udev_enumerate_add_match_sysname (struct udev_enumerate
+ *udev_enumerate, const char *sysname);
+ int udev_enumerate_add_match_tag (struct udev_enumerate *udev_enumerate,
+ const char *tag);
+ int udev_enumerate_add_match_parent (struct udev_enumerate
+ *udev_enumerate,
+ struct udev_device *parent);
+ int udev_enumerate_add_match_is_initialized (struct udev_enumerate
+ *udev_enumerate);
+ int udev_enumerate_add_syspath (struct udev_enumerate *udev_enumerate,
+ const char *syspath);
/* run enumeration with active filters */
-int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate);
-int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate);
+ int udev_enumerate_scan_devices (struct udev_enumerate *udev_enumerate);
+ int udev_enumerate_scan_subsystems (struct udev_enumerate *udev_enumerate);
/* return device list */
-struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate);
+ struct udev_list_entry *udev_enumerate_get_list_entry (struct
+ udev_enumerate
+ *udev_enumerate);
/*
* udev_queue
*
* access to the currently running udev events
*/
-struct udev_queue;
-struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue);
-struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue);
-struct udev *udev_queue_get_udev(struct udev_queue *udev_queue);
-struct udev_queue *udev_queue_new(struct udev *udev);
-unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue);
-unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue);
-int udev_queue_get_udev_is_active(struct udev_queue *udev_queue);
-int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue);
-int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum);
-int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue,
- unsigned long long int start, unsigned long long int end);
-int udev_queue_get_fd(struct udev_queue *udev_queue);
-int udev_queue_flush(struct udev_queue *udev_queue);
-struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue);
+ struct udev_queue;
+ struct udev_queue *udev_queue_ref (struct udev_queue *udev_queue);
+ struct udev_queue *udev_queue_unref (struct udev_queue *udev_queue);
+ struct udev *udev_queue_get_udev (struct udev_queue *udev_queue);
+ struct udev_queue *udev_queue_new (struct udev *udev);
+ unsigned long long int udev_queue_get_kernel_seqnum (struct udev_queue
+ *udev_queue);
+ unsigned long long int udev_queue_get_udev_seqnum (struct udev_queue
+ *udev_queue);
+ int udev_queue_get_udev_is_active (struct udev_queue *udev_queue);
+ int udev_queue_get_queue_is_empty (struct udev_queue *udev_queue);
+ int udev_queue_get_seqnum_is_finished (struct udev_queue *udev_queue,
+ unsigned long long int seqnum);
+ int udev_queue_get_seqnum_sequence_is_finished (struct udev_queue
+ *udev_queue,
+ unsigned long long int
+ start,
+ unsigned long long int end);
+ int udev_queue_get_fd (struct udev_queue *udev_queue);
+ int udev_queue_flush (struct udev_queue *udev_queue);
+ struct udev_list_entry *udev_queue_get_queued_list_entry (struct
+ udev_queue
+ *udev_queue);
/*
* udev_hwdb
*
* access to the static hardware properties database
*/
-struct udev_hwdb;
-struct udev_hwdb *udev_hwdb_new(struct udev *udev);
-struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb);
-struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb);
-struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned int flags);
+ struct udev_hwdb;
+ struct udev_hwdb *udev_hwdb_new (struct udev *udev);
+ struct udev_hwdb *udev_hwdb_ref (struct udev_hwdb *hwdb);
+ struct udev_hwdb *udev_hwdb_unref (struct udev_hwdb *hwdb);
+ struct udev_list_entry *udev_hwdb_get_properties_list_entry (struct
+ udev_hwdb
+ *hwdb,
+ const char
+ *modalias,
+ unsigned int
+ flags);
/*
* udev_util
*
* udev specific utilities
*/
-int udev_util_encode_string(const char *str, char *str_enc, size_t len);
-
+ int udev_util_encode_string (const char *str, char *str_enc, size_t len);
#ifdef __cplusplus
-} /* extern "C" */
+} /* extern "C" */
#endif
-
#endif
diff --git a/libudev-compat/log.c b/libudev-compat/log.c
index 7ee5b7f..312af6c 100644
--- a/libudev-compat/log.c
+++ b/libudev-compat/log.c
@@ -30,45 +30,59 @@
// undefined by default...
static int log_max_level = -1;
-void log_set_max_level(int level) {
- // don't allow invalid log levels (only these methods can do so)
- assert((level & LOG_PRIMASK) == level);
+void
+log_set_max_level (int level)
+{
+ // don't allow invalid log levels (only these methods can do so)
+ assert ((level & LOG_PRIMASK) == level);
- log_max_level = level;
+ log_max_level = level;
}
-static void log_check_disabled(void) {
-
- if( log_max_level == -1 ) {
-
- // undefined default max log level
- char* libudev_compat_loglevel_str = secure_getenv( LIBUDEV_COMPAT_DEBUG_ENVAR );
- if( libudev_compat_loglevel_str != NULL && strlen(libudev_compat_loglevel_str) > 0 ) {
-
- // enable debugging
- log_max_level = LIBUDEV_COMPAT_DEBUG;
- }
- else {
-
- // disable debugging
- log_max_level = LIBUDEV_COMPAT_NO_DEBUG;
- }
+static void
+log_check_disabled (void)
+{
+
+ if (log_max_level == -1)
+ {
+
+ // undefined default max log level
+ char *libudev_compat_loglevel_str =
+ secure_getenv (LIBUDEV_COMPAT_DEBUG_ENVAR);
+ if (libudev_compat_loglevel_str != NULL
+ && strlen (libudev_compat_loglevel_str) > 0)
+ {
+
+ // enable debugging
+ log_max_level = LIBUDEV_COMPAT_DEBUG;
+ }
+ else
+ {
+
+ // disable debugging
+ log_max_level = LIBUDEV_COMPAT_NO_DEBUG;
+ }
}
}
-int log_get_max_level(void) {
-
- log_check_disabled();
- return log_max_level;
+int
+log_get_max_level (void)
+{
+
+ log_check_disabled ();
+ return log_max_level;
}
-void log_impl( int level, char const* fmt, ... ) {
-
- log_check_disabled();
- if( level <= log_max_level ) {
+void
+log_impl (int level, char const *fmt, ...)
+{
+
+ log_check_disabled ();
+ if (level <= log_max_level)
+ {
va_list args;
- va_start( args, fmt );
- vfprintf( stderr, fmt, args );
- va_end( args );
- }
+ va_start (args, fmt);
+ vfprintf (stderr, fmt, args);
+ va_end (args);
+ }
}
diff --git a/libudev-compat/log.h b/libudev-compat/log.h
index 3439690..63a39b9 100644
--- a/libudev-compat/log.h
+++ b/libudev-compat/log.h
@@ -38,9 +38,9 @@
#define log_debug( fmt, ... ) log_impl( LOG_DEBUG, LIBUDEV_COMPAT_WHERESTR fmt "\n", (int)getpid(), __FILE__, __LINE__, __func__, __VA_ARGS__ )
#define log_error( fmt, ... ) log_impl( LOG_ERR, LIBUDEV_COMPAT_WHERESTR fmt "\n", (int)getpid(), __FILE__, __LINE__, __func__, __VA_ARGS__ )
-void log_set_max_level(int level);
-int log_get_max_level(void);
+void log_set_max_level (int level);
+int log_get_max_level (void);
+
+void log_impl (int level, char const *fmt, ...);
-void log_impl( int level, char const* fmt, ... );
-
#endif
diff --git a/libudev-compat/macro.h b/libudev-compat/macro.h
index 402652a..fea2edf 100644
--- a/libudev-compat/macro.h
+++ b/libudev-compat/macro.h
@@ -112,23 +112,27 @@
#define ALIGN4_PTR(p) ((void*) ALIGN4((unsigned long) (p)))
#define ALIGN8_PTR(p) ((void*) ALIGN8((unsigned long) (p)))
-static inline size_t ALIGN_TO(size_t l, size_t ali) {
- return ((l + ali - 1) & ~(ali - 1));
+static inline size_t
+ALIGN_TO (size_t l, size_t ali)
+{
+ return ((l + ali - 1) & ~(ali - 1));
}
#define ALIGN_TO_PTR(p, ali) ((void*) ALIGN_TO((unsigned long) (p), (ali)))
/* align to next higher power-of-2 (except for: 0 => 0, overflow => 0) */
-static inline unsigned long ALIGN_POWER2(unsigned long u) {
- /* clz(0) is undefined */
- if (u == 1)
- return 1;
-
- /* left-shift overflow is undefined */
- if (__builtin_clzl(u - 1UL) < 1)
- return 0;
-
- return 1UL << (sizeof(u) * 8 - __builtin_clzl(u - 1UL));
+static inline unsigned long
+ALIGN_POWER2 (unsigned long u)
+{
+ /* clz(0) is undefined */
+ if (u == 1)
+ return 1;
+
+ /* left-shift overflow is undefined */
+ if (__builtin_clzl (u - 1UL) < 1)
+ return 0;
+
+ return 1UL << (sizeof (u) * 8 - __builtin_clzl (u - 1UL));
}
#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
@@ -311,32 +315,37 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
_i->iov_len = strlen(_s); \
} while(false)
-static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) {
- unsigned j;
- size_t r = 0;
+static inline size_t
+IOVEC_TOTAL_SIZE (const struct iovec *i, unsigned n)
+{
+ unsigned j;
+ size_t r = 0;
- for (j = 0; j < n; j++)
- r += i[j].iov_len;
+ for (j = 0; j < n; j++)
+ r += i[j].iov_len;
- return r;
+ return r;
}
-static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
- unsigned j;
+static inline size_t
+IOVEC_INCREMENT (struct iovec *i, unsigned n, size_t k)
+{
+ unsigned j;
- for (j = 0; j < n; j++) {
- size_t sub;
+ for (j = 0; j < n; j++)
+ {
+ size_t sub;
- if (_unlikely_(k <= 0))
- break;
+ if (_unlikely_ (k <= 0))
+ break;
- sub = MIN(i[j].iov_len, k);
- i[j].iov_len -= sub;
- i[j].iov_base = (uint8_t*) i[j].iov_base + sub;
- k -= sub;
- }
+ sub = MIN (i[j].iov_len, k);
+ i[j].iov_len -= sub;
+ i[j].iov_base = (uint8_t *) i[j].iov_base + sub;
+ k -= sub;
+ }
- return k;
+ return k;
}
#define VA_FORMAT_ADVANCE(format, ap) \
@@ -387,7 +396,7 @@ do { \
/* Because statfs.t_type can be int on some architectures, we have to cast
* the const magic to the type, otherwise the compiler warns about
* signed/unsigned comparison, because the magic can be 32 bit unsigned.
- */
+ */
#define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b)
/* Returns the number of chars needed to format variables of the
@@ -469,4 +478,4 @@ do { \
#include "log.h"
-#endif
\ No newline at end of file
+#endif
diff --git a/libudev-compat/mempool.c b/libudev-compat/mempool.c
index 718d768..fb6fe4d 100644
--- a/libudev-compat/mempool.c
+++ b/libudev-compat/mempool.c
@@ -28,80 +28,93 @@
// #include "macro.h"
#include "util.h"
-struct pool {
- struct pool *next;
- unsigned n_tiles;
- unsigned n_used;
+struct pool
+{
+ struct pool *next;
+ unsigned n_tiles;
+ unsigned n_used;
};
-void* mempool_alloc_tile(struct mempool *mp) {
- unsigned i;
+void *
+mempool_alloc_tile (struct mempool *mp)
+{
+ unsigned i;
- /* When a tile is released we add it to the list and simply
- * place the next pointer at its offset 0. */
+ /* When a tile is released we add it to the list and simply
+ * place the next pointer at its offset 0. */
- assert(mp->tile_size >= sizeof(void*));
- assert(mp->at_least > 0);
+ assert (mp->tile_size >= sizeof (void *));
+ assert (mp->at_least > 0);
- if (mp->freelist) {
- void *r;
+ if (mp->freelist)
+ {
+ void *r;
- r = mp->freelist;
- mp->freelist = * (void**) mp->freelist;
- return r;
- }
+ r = mp->freelist;
+ mp->freelist = *(void **) mp->freelist;
+ return r;
+ }
- if (_unlikely_(!mp->first_pool) ||
- _unlikely_(mp->first_pool->n_used >= mp->first_pool->n_tiles)) {
- unsigned n;
- size_t size;
- struct pool *p;
+ if (_unlikely_ (!mp->first_pool) ||
+ _unlikely_ (mp->first_pool->n_used >= mp->first_pool->n_tiles))
+ {
+ unsigned n;
+ size_t size;
+ struct pool *p;
- n = mp->first_pool ? mp->first_pool->n_tiles : 0;
- n = MAX(mp->at_least, n * 2);
- size = PAGE_ALIGN(ALIGN(sizeof(struct pool)) + n*mp->tile_size);
- n = (size - ALIGN(sizeof(struct pool))) / mp->tile_size;
+ n = mp->first_pool ? mp->first_pool->n_tiles : 0;
+ n = MAX (mp->at_least, n * 2);
+ size = PAGE_ALIGN (ALIGN (sizeof (struct pool)) + n * mp->tile_size);
+ n = (size - ALIGN (sizeof (struct pool))) / mp->tile_size;
- p = malloc(size);
- if (!p)
- return NULL;
+ p = malloc (size);
+ if (!p)
+ return NULL;
- p->next = mp->first_pool;
- p->n_tiles = n;
- p->n_used = 0;
+ p->next = mp->first_pool;
+ p->n_tiles = n;
+ p->n_used = 0;
- mp->first_pool = p;
- }
+ mp->first_pool = p;
+ }
- i = mp->first_pool->n_used++;
+ i = mp->first_pool->n_used++;
- return ((uint8_t*) mp->first_pool) + ALIGN(sizeof(struct pool)) + i*mp->tile_size;
+ return ((uint8_t *) mp->first_pool) + ALIGN (sizeof (struct pool)) +
+ i * mp->tile_size;
}
-void* mempool_alloc0_tile(struct mempool *mp) {
- void *p;
+void *
+mempool_alloc0_tile (struct mempool *mp)
+{
+ void *p;
- p = mempool_alloc_tile(mp);
- if (p)
- memzero(p, mp->tile_size);
- return p;
+ p = mempool_alloc_tile (mp);
+ if (p)
+ memzero (p, mp->tile_size);
+ return p;
}
-void mempool_free_tile(struct mempool *mp, void *p) {
- * (void**) p = mp->freelist;
- mp->freelist = p;
+void
+mempool_free_tile (struct mempool *mp, void *p)
+{
+ *(void **) p = mp->freelist;
+ mp->freelist = p;
}
#ifdef VALGRIND
-void mempool_drop(struct mempool *mp) {
- struct pool *p = mp->first_pool;
- while (p) {
- struct pool *n;
- n = p->next;
- free(p);
- p = n;
- }
+void
+mempool_drop (struct mempool *mp)
+{
+ struct pool *p = mp->first_pool;
+ while (p)
+ {
+ struct pool *n;
+ n = p->next;
+ free (p);
+ p = n;
+ }
}
#endif
diff --git a/libudev-compat/mempool.h b/libudev-compat/mempool.h
index 1484ca7..5a96316 100644
--- a/libudev-compat/mempool.h
+++ b/libudev-compat/mempool.h
@@ -31,16 +31,17 @@
struct pool;
-struct mempool {
- struct pool *first_pool;
- void *freelist;
- size_t tile_size;
- unsigned at_least;
+struct mempool
+{
+ struct pool *first_pool;
+ void *freelist;
+ size_t tile_size;
+ unsigned at_least;
};
-void* mempool_alloc_tile(struct mempool *mp);
-void* mempool_alloc0_tile(struct mempool *mp);
-void mempool_free_tile(struct mempool *mp, void *p);
+void *mempool_alloc_tile (struct mempool *mp);
+void *mempool_alloc0_tile (struct mempool *mp);
+void mempool_free_tile (struct mempool *mp, void *p);
#define DEFINE_MEMPOOL(pool_name, tile_type, alloc_at_least) \
struct mempool pool_name = { \
@@ -48,9 +49,8 @@ struct mempool pool_name = { \
.at_least = alloc_at_least, \
}
-
#ifdef VALGRIND
-void mempool_drop(struct mempool *mp);
+void mempool_drop (struct mempool *mp);
#endif
-#endif
\ No newline at end of file
+#endif
diff --git a/libudev-compat/mkdir.c b/libudev-compat/mkdir.c
index 0382274..7eaeb82 100644
--- a/libudev-compat/mkdir.c
+++ b/libudev-compat/mkdir.c
@@ -29,136 +29,154 @@
#include "util.h"
#include "mkdir.h"
-char* path_startswith(const char *path, const char *prefix) {
- assert(path);
- assert(prefix);
+char *
+path_startswith (const char *path, const char *prefix)
+{
+ assert (path);
+ assert (prefix);
- if ((path[0] == '/') != (prefix[0] == '/'))
- return NULL;
+ if ((path[0] == '/') != (prefix[0] == '/'))
+ return NULL;
- for (;;) {
- size_t a, b;
+ for (;;)
+ {
+ size_t a, b;
- path += strspn(path, "/");
- prefix += strspn(prefix, "/");
+ path += strspn (path, "/");
+ prefix += strspn (prefix, "/");
- if (*prefix == 0)
- return (char*) path;
+ if (*prefix == 0)
+ return (char *) path;
- if (*path == 0)
- return NULL;
+ if (*path == 0)
+ return NULL;
- a = strcspn(path, "/");
- b = strcspn(prefix, "/");
+ a = strcspn (path, "/");
+ b = strcspn (prefix, "/");
- if (a != b)
- return NULL;
+ if (a != b)
+ return NULL;
- if (memcmp(path, prefix, a) != 0)
- return NULL;
+ if (memcmp (path, prefix, a) != 0)
+ return NULL;
- path += a;
- prefix += b;
- }
+ path += a;
+ prefix += b;
+ }
}
-
-int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkdir_func_t _mkdir) {
- struct stat st;
-
- if (_mkdir(path, mode) >= 0)
- if (chmod_and_chown(path, mode, uid, gid) < 0)
- return -errno;
-
- if (lstat(path, &st) < 0)
- return -errno;
-
- if ((st.st_mode & 0007) > (mode & 0007) ||
- (st.st_mode & 0070) > (mode & 0070) ||
- (st.st_mode & 0700) > (mode & 0700) ||
- (uid != UID_INVALID && st.st_uid != uid) ||
- (gid != GID_INVALID && st.st_gid != gid) ||
- !S_ISDIR(st.st_mode)) {
- errno = EEXIST;
- return -errno;
- }
-
- return 0;
+int
+mkdir_safe_internal (const char *path, mode_t mode, uid_t uid, gid_t gid,
+ mkdir_func_t _mkdir)
+{
+ struct stat st;
+
+ if (_mkdir (path, mode) >= 0)
+ if (chmod_and_chown (path, mode, uid, gid) < 0)
+ return -errno;
+
+ if (lstat (path, &st) < 0)
+ return -errno;
+
+ if ((st.st_mode & 0007) > (mode & 0007) ||
+ (st.st_mode & 0070) > (mode & 0070) ||
+ (st.st_mode & 0700) > (mode & 0700) ||
+ (uid != UID_INVALID && st.st_uid != uid) ||
+ (gid != GID_INVALID && st.st_gid != gid) || !S_ISDIR (st.st_mode))
+ {
+ errno = EEXIST;
+ return -errno;
+ }
+
+ return 0;
}
-int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid) {
- return mkdir_safe_internal(path, mode, uid, gid, mkdir);
+int
+mkdir_safe (const char *path, mode_t mode, uid_t uid, gid_t gid)
+{
+ return mkdir_safe_internal (path, mode, uid, gid, mkdir);
}
-int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) {
- const char *p, *e;
- int r;
-
- assert(path);
-
- if (prefix && !path_startswith(path, prefix))
- return -ENOTDIR;
-
- /* return immediately if directory exists */
- e = strrchr(path, '/');
- if (!e)
- return -EINVAL;
-
- if (e == path)
- return 0;
-
- p = strndupa(path, e - path);
- r = is_dir(p, true);
- if (r > 0)
- return 0;
- if (r == 0)
- return -ENOTDIR;
-
- /* create every parent directory in the path, except the last component */
- p = path + strspn(path, "/");
- for (;;) {
- char t[strlen(path) + 1];
-
- e = p + strcspn(p, "/");
- p = e + strspn(e, "/");
-
- /* Is this the last component? If so, then we're
- * done */
- if (*p == 0)
- return 0;
-
- memcpy(t, path, e - path);
- t[e-path] = 0;
-
- if (prefix && path_startswith(prefix, t))
- continue;
-
- r = _mkdir(t, mode);
- if (r < 0 && errno != EEXIST)
- return -errno;
- }
+int
+mkdir_parents_internal (const char *prefix, const char *path, mode_t mode,
+ mkdir_func_t _mkdir)
+{
+ const char *p, *e;
+ int r;
+
+ assert (path);
+
+ if (prefix && !path_startswith (path, prefix))
+ return -ENOTDIR;
+
+ /* return immediately if directory exists */
+ e = strrchr (path, '/');
+ if (!e)
+ return -EINVAL;
+
+ if (e == path)
+ return 0;
+
+ p = strndupa (path, e - path);
+ r = is_dir (p, true);
+ if (r > 0)
+ return 0;
+ if (r == 0)
+ return -ENOTDIR;
+
+ /* create every parent directory in the path, except the last component */
+ p = path + strspn (path, "/");
+ for (;;)
+ {
+ char t[strlen (path) + 1];
+
+ e = p + strcspn (p, "/");
+ p = e + strspn (e, "/");
+
+ /* Is this the last component? If so, then we're
+ * done */
+ if (*p == 0)
+ return 0;
+
+ memcpy (t, path, e - path);
+ t[e - path] = 0;
+
+ if (prefix && path_startswith (prefix, t))
+ continue;
+
+ r = _mkdir (t, mode);
+ if (r < 0 && errno != EEXIST)
+ return -errno;
+ }
}
-int mkdir_parents(const char *path, mode_t mode) {
- return mkdir_parents_internal(NULL, path, mode, mkdir);
+int
+mkdir_parents (const char *path, mode_t mode)
+{
+ return mkdir_parents_internal (NULL, path, mode, mkdir);
}
-int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) {
- int r;
+int
+mkdir_p_internal (const char *prefix, const char *path, mode_t mode,
+ mkdir_func_t _mkdir)
+{
+ int r;
- /* Like mkdir -p */
+ /* Like mkdir -p */
- r = mkdir_parents_internal(prefix, path, mode, _mkdir);
- if (r < 0)
- return r;
+ r = mkdir_parents_internal (prefix, path, mode, _mkdir);
+ if (r < 0)
+ return r;
- r = _mkdir(path, mode);
- if (r < 0 && (errno != EEXIST || is_dir(path, true) <= 0))
- return -errno;
+ r = _mkdir (path, mode);
+ if (r < 0 && (errno != EEXIST || is_dir (path, true) <= 0))
+ return -errno;
- return 0;
+ return 0;
}
-int mkdir_p(const char *path, mode_t mode) {
- return mkdir_p_internal(NULL, path, mode, mkdir);
+int
+mkdir_p (const char *path, mode_t mode)
+{
+ return mkdir_p_internal (NULL, path, mode, mkdir);
}
diff --git a/libudev-compat/mkdir.h b/libudev-compat/mkdir.h
index 0516777..1a2dcee 100644
--- a/libudev-compat/mkdir.h
+++ b/libudev-compat/mkdir.h
@@ -34,14 +34,17 @@
#include
#include
-int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid);
-int mkdir_parents(const char *path, mode_t mode);
-int mkdir_p(const char *path, mode_t mode);
+int mkdir_safe (const char *path, mode_t mode, uid_t uid, gid_t gid);
+int mkdir_parents (const char *path, mode_t mode);
+int mkdir_p (const char *path, mode_t mode);
/* internally used */
-typedef int (*mkdir_func_t)(const char *pathname, mode_t mode);
-int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkdir_func_t _mkdir);
-int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir);
-int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir);
-
-#endif
\ No newline at end of file
+typedef int (*mkdir_func_t) (const char *pathname, mode_t mode);
+int mkdir_safe_internal (const char *path, mode_t mode, uid_t uid, gid_t gid,
+ mkdir_func_t _mkdir);
+int mkdir_parents_internal (const char *prefix, const char *path, mode_t mode,
+ mkdir_func_t _mkdir);
+int mkdir_p_internal (const char *prefix, const char *path, mode_t mode,
+ mkdir_func_t _mkdir);
+
+#endif
diff --git a/libudev-compat/sd-hwdb.c b/libudev-compat/sd-hwdb.c
index c69a2ac..4bb63f6 100644
--- a/libudev-compat/sd-hwdb.c
+++ b/libudev-compat/sd-hwdb.c
@@ -45,449 +45,550 @@
#include "hwdb-util.h"
#include "hwdb-internal.h"
-struct sd_hwdb {
- RefCount n_ref;
- int refcount;
-
- FILE *f;
- struct stat st;
- union {
- struct trie_header_f *head;
- const char *map;
- };
-
- char *modalias;
-
- OrderedHashmap *properties;
- Iterator properties_iterator;
- bool properties_modified;
+struct sd_hwdb
+{
+ RefCount n_ref;
+ int refcount;
+
+ FILE *f;
+ struct stat st;
+ union
+ {
+ struct trie_header_f *head;
+ const char *map;
+ };
+
+ char *modalias;
+
+ OrderedHashmap *properties;
+ Iterator properties_iterator;
+ bool properties_modified;
};
-struct linebuf {
- char bytes[LINE_MAX];
- size_t size;
- size_t len;
+struct linebuf
+{
+ char bytes[LINE_MAX];
+ size_t size;
+ size_t len;
};
-static void linebuf_init(struct linebuf *buf) {
- buf->size = 0;
- buf->len = 0;
+static void
+linebuf_init (struct linebuf *buf)
+{
+ buf->size = 0;
+ buf->len = 0;
}
-static const char *linebuf_get(struct linebuf *buf) {
- if (buf->len + 1 >= sizeof(buf->bytes))
- return NULL;
- buf->bytes[buf->len] = '\0';
- return buf->bytes;
+static const char *
+linebuf_get (struct linebuf *buf)
+{
+ if (buf->len + 1 >= sizeof (buf->bytes))
+ return NULL;
+ buf->bytes[buf->len] = '\0';
+ return buf->bytes;
}
-static bool linebuf_add(struct linebuf *buf, const char *s, size_t len) {
- if (buf->len + len >= sizeof(buf->bytes))
- return false;
- memcpy(buf->bytes + buf->len, s, len);
- buf->len += len;
- return true;
+static bool
+linebuf_add (struct linebuf *buf, const char *s, size_t len)
+{
+ if (buf->len + len >= sizeof (buf->bytes))
+ return false;
+ memcpy (buf->bytes + buf->len, s, len);
+ buf->len += len;
+ return true;
}
-static bool linebuf_add_char(struct linebuf *buf, char c)
+static bool
+linebuf_add_char (struct linebuf *buf, char c)
{
- if (buf->len + 1 >= sizeof(buf->bytes))
- return false;
- buf->bytes[buf->len++] = c;
- return true;
+ if (buf->len + 1 >= sizeof (buf->bytes))
+ return false;
+ buf->bytes[buf->len++] = c;
+ return true;
}
-static void linebuf_rem(struct linebuf *buf, size_t count) {
- assert(buf->len >= count);
- buf->len -= count;
+static void
+linebuf_rem (struct linebuf *buf, size_t count)
+{
+ assert (buf->len >= count);
+ buf->len -= count;
}
-static void linebuf_rem_char(struct linebuf *buf) {
- linebuf_rem(buf, 1);
+static void
+linebuf_rem_char (struct linebuf *buf)
+{
+ linebuf_rem (buf, 1);
}
-static const struct trie_child_entry_f *trie_node_children(sd_hwdb *hwdb, const struct trie_node_f *node) {
- return (const struct trie_child_entry_f *)((const char *)node + le64toh(hwdb->head->node_size));
+static const struct trie_child_entry_f *
+trie_node_children (sd_hwdb * hwdb, const struct trie_node_f *node)
+{
+ return (const struct trie_child_entry_f *) ((const char *) node +
+ le64toh (hwdb->
+ head->node_size));
}
-static const struct trie_value_entry_f *trie_node_values(sd_hwdb *hwdb, const struct trie_node_f *node) {
- const char *base = (const char *)node;
+static const struct trie_value_entry_f *
+trie_node_values (sd_hwdb * hwdb, const struct trie_node_f *node)
+{
+ const char *base = (const char *) node;
- base += le64toh(hwdb->head->node_size);
- base += node->children_count * le64toh(hwdb->head->child_entry_size);
- return (const struct trie_value_entry_f *)base;
+ base += le64toh (hwdb->head->node_size);
+ base += node->children_count * le64toh (hwdb->head->child_entry_size);
+ return (const struct trie_value_entry_f *) base;
}
-static const struct trie_node_f *trie_node_from_off(sd_hwdb *hwdb, le64_t off) {
- return (const struct trie_node_f *)(hwdb->map + le64toh(off));
+static const struct trie_node_f *
+trie_node_from_off (sd_hwdb * hwdb, le64_t off)
+{
+ return (const struct trie_node_f *) (hwdb->map + le64toh (off));
}
-static const char *trie_string(sd_hwdb *hwdb, le64_t off) {
- return hwdb->map + le64toh(off);
+static const char *
+trie_string (sd_hwdb * hwdb, le64_t off)
+{
+ return hwdb->map + le64toh (off);
}
-static int trie_children_cmp_f(const void *v1, const void *v2) {
- const struct trie_child_entry_f *n1 = v1;
- const struct trie_child_entry_f *n2 = v2;
+static int
+trie_children_cmp_f (const void *v1, const void *v2)
+{
+ const struct trie_child_entry_f *n1 = v1;
+ const struct trie_child_entry_f *n2 = v2;
- return n1->c - n2->c;
+ return n1->c - n2->c;
}
-static const struct trie_node_f *node_lookup_f(sd_hwdb *hwdb, const struct trie_node_f *node, uint8_t c) {
- struct trie_child_entry_f *child;
- struct trie_child_entry_f search;
-
- search.c = c;
- child = bsearch(&search, trie_node_children(hwdb, node), node->children_count,
- le64toh(hwdb->head->child_entry_size), trie_children_cmp_f);
- if (child)
- return trie_node_from_off(hwdb, child->child_off);
- return NULL;
+static const struct trie_node_f *
+node_lookup_f (sd_hwdb * hwdb, const struct trie_node_f *node, uint8_t c)
+{
+ struct trie_child_entry_f *child;
+ struct trie_child_entry_f search;
+
+ search.c = c;
+ child =
+ bsearch (&search, trie_node_children (hwdb, node),
+ node->children_count, le64toh (hwdb->head->child_entry_size),
+ trie_children_cmp_f);
+ if (child)
+ return trie_node_from_off (hwdb, child->child_off);
+ return NULL;
}
-static int hwdb_add_property(sd_hwdb *hwdb, const char *key, const char *value) {
- int r;
+static int
+hwdb_add_property (sd_hwdb * hwdb, const char *key, const char *value)
+{
+ int r;
- assert(hwdb);
- assert(key);
- assert(value);
+ assert (hwdb);
+ assert (key);
+ assert (value);
- /*
- * Silently ignore all properties which do not start with a
- * space; future extensions might use additional prefixes.
- */
- if (key[0] != ' ')
- return 0;
+ /*
+ * Silently ignore all properties which do not start with a
+ * space; future extensions might use additional prefixes.
+ */
+ if (key[0] != ' ')
+ return 0;
- key++;
+ key++;
- r = ordered_hashmap_ensure_allocated(&hwdb->properties, &string_hash_ops);
- if (r < 0)
- return r;
+ r = ordered_hashmap_ensure_allocated (&hwdb->properties, &string_hash_ops);
+ if (r < 0)
+ return r;
- r = ordered_hashmap_replace(hwdb->properties, key, (char*)value);
- if (r < 0)
- return r;
+ r = ordered_hashmap_replace (hwdb->properties, key, (char *) value);
+ if (r < 0)
+ return r;
- hwdb->properties_modified = true;
+ hwdb->properties_modified = true;
- return 0;
+ return 0;
}
-static int trie_fnmatch_f(sd_hwdb *hwdb, const struct trie_node_f *node, size_t p,
- struct linebuf *buf, const char *search) {
- size_t len;
- size_t i;
- const char *prefix;
- int err;
-
- prefix = trie_string(hwdb, node->prefix_off);
- len = strlen(prefix + p);
- linebuf_add(buf, prefix + p, len);
-
- for (i = 0; i < node->children_count; i++) {
- const struct trie_child_entry_f *child = &trie_node_children(hwdb, node)[i];
-
- linebuf_add_char(buf, child->c);
- err = trie_fnmatch_f(hwdb, trie_node_from_off(hwdb, child->child_off), 0, buf, search);
- if (err < 0)
- return err;
- linebuf_rem_char(buf);
- }
-
- if (le64toh(node->values_count) && fnmatch(linebuf_get(buf), search, 0) == 0)
- for (i = 0; i < le64toh(node->values_count); i++) {
- err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_values(hwdb, node)[i].key_off),
- trie_string(hwdb, trie_node_values(hwdb, node)[i].value_off));
- if (err < 0)
- return err;
- }
-
- linebuf_rem(buf, len);
- return 0;
+static int
+trie_fnmatch_f (sd_hwdb * hwdb, const struct trie_node_f *node,
+ size_t p, struct linebuf *buf, const char *search)
+{
+ size_t len;
+ size_t i;
+ const char *prefix;
+ int err;
+
+ prefix = trie_string (hwdb, node->prefix_off);
+ len = strlen (prefix + p);
+ linebuf_add (buf, prefix + p, len);
+
+ for (i = 0; i < node->children_count; i++)
+ {
+ const struct trie_child_entry_f *child =
+ &trie_node_children (hwdb, node)[i];
+
+ linebuf_add_char (buf, child->c);
+ err =
+ trie_fnmatch_f (hwdb,
+ trie_node_from_off (hwdb, child->child_off),
+ 0, buf, search);
+ if (err < 0)
+ return err;
+ linebuf_rem_char (buf);
+ }
+
+ if (le64toh (node->values_count)
+ && fnmatch (linebuf_get (buf), search, 0) == 0)
+ for (i = 0; i < le64toh (node->values_count); i++)
+ {
+ err =
+ hwdb_add_property (hwdb,
+ trie_string (hwdb,
+ trie_node_values (hwdb,
+ node)
+ [i].key_off),
+ trie_string (hwdb,
+ trie_node_values (hwdb,
+ node)
+ [i].value_off));
+ if (err < 0)
+ return err;
+ }
+
+ linebuf_rem (buf, len);
+ return 0;
}
-static int trie_search_f(sd_hwdb *hwdb, const char *search) {
- struct linebuf buf;
- const struct trie_node_f *node;
- size_t i = 0;
- int err;
-
- linebuf_init(&buf);
-
- node = trie_node_from_off(hwdb, hwdb->head->nodes_root_off);
- while (node) {
- const struct trie_node_f *child;
- size_t p = 0;
-
- if (node->prefix_off) {
- uint8_t c;
-
- for (; (c = trie_string(hwdb, node->prefix_off)[p]); p++) {
- if (c == '*' || c == '?' || c == '[')
- return trie_fnmatch_f(hwdb, node, p, &buf, search + i + p);
- if (c != search[i + p])
- return 0;
- }
- i += p;
- }
-
- child = node_lookup_f(hwdb, node, '*');
- if (child) {
- linebuf_add_char(&buf, '*');
- err = trie_fnmatch_f(hwdb, child, 0, &buf, search + i);
- if (err < 0)
- return err;
- linebuf_rem_char(&buf);
- }
-
- child = node_lookup_f(hwdb, node, '?');
- if (child) {
- linebuf_add_char(&buf, '?');
- err = trie_fnmatch_f(hwdb, child, 0, &buf, search + i);
- if (err < 0)
- return err;
- linebuf_rem_char(&buf);
- }
-
- child = node_lookup_f(hwdb, node, '[');
- if (child) {
- linebuf_add_char(&buf, '[');
- err = trie_fnmatch_f(hwdb, child, 0, &buf, search + i);
- if (err < 0)
- return err;
- linebuf_rem_char(&buf);
- }
-
- if (search[i] == '\0') {
- size_t n;
-
- for (n = 0; n < le64toh(node->values_count); n++) {
- err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_values(hwdb, node)[n].key_off),
- trie_string(hwdb, trie_node_values(hwdb, node)[n].value_off));
- if (err < 0)
- return err;
- }
- return 0;
- }
-
- child = node_lookup_f(hwdb, node, search[i]);
- node = child;
- i++;
- }
- return 0;
+static int
+trie_search_f (sd_hwdb * hwdb, const char *search)
+{
+ struct linebuf buf;
+ const struct trie_node_f *node;
+ size_t i = 0;
+ int err;
+
+ linebuf_init (&buf);
+
+ node = trie_node_from_off (hwdb, hwdb->head->nodes_root_off);
+ while (node)
+ {
+ const struct trie_node_f *child;
+ size_t p = 0;
+
+ if (node->prefix_off)
+ {
+ uint8_t c;
+
+ for (; (c = trie_string (hwdb, node->prefix_off)[p]); p++)
+ {
+ if (c == '*' || c == '?' || c == '[')
+ return trie_fnmatch_f (hwdb, node, p, &buf, search + i + p);
+ if (c != search[i + p])
+ return 0;
+ }
+ i += p;
+ }
+
+ child = node_lookup_f (hwdb, node, '*');
+ if (child)
+ {
+ linebuf_add_char (&buf, '*');
+ err = trie_fnmatch_f (hwdb, child, 0, &buf, search + i);
+ if (err < 0)
+ return err;
+ linebuf_rem_char (&buf);
+ }
+
+ child = node_lookup_f (hwdb, node, '?');
+ if (child)
+ {
+ linebuf_add_char (&buf, '?');
+ err = trie_fnmatch_f (hwdb, child, 0, &buf, search + i);
+ if (err < 0)
+ return err;
+ linebuf_rem_char (&buf);
+ }
+
+ child = node_lookup_f (hwdb, node, '[');
+ if (child)
+ {
+ linebuf_add_char (&buf, '[');
+ err = trie_fnmatch_f (hwdb, child, 0, &buf, search + i);
+ if (err < 0)
+ return err;
+ linebuf_rem_char (&buf);
+ }
+
+ if (search[i] == '\0')
+ {
+ size_t n;
+
+ for (n = 0; n < le64toh (node->values_count); n++)
+ {
+ err =
+ hwdb_add_property (hwdb,
+ trie_string (hwdb,
+ trie_node_values
+ (hwdb,
+ node)[n].key_off),
+ trie_string (hwdb,
+ trie_node_values
+ (hwdb, node)[n].value_off));
+ if (err < 0)
+ return err;
+ }
+ return 0;
+ }
+
+ child = node_lookup_f (hwdb, node, search[i]);
+ node = child;
+ i++;
+ }
+ return 0;
}
static const char hwdb_bin_paths[] =
- "/etc/systemd/hwdb/hwdb.bin\0"
- "/etc/udev/hwdb.bin\0"
- "/usr/lib/systemd/hwdb/hwdb.bin\0"
+ "/etc/systemd/hwdb/hwdb.bin\0"
+ "/etc/udev/hwdb.bin\0" "/usr/lib/systemd/hwdb/hwdb.bin\0"
#ifdef HAVE_SPLIT_USR
- "/lib/systemd/hwdb/hwdb.bin\0"
+ "/lib/systemd/hwdb/hwdb.bin\0"
#endif
- "/lib/systemd/hwdb.bin\0";
-
-_public_ int sd_hwdb_new(sd_hwdb **ret) {
- _cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL;
- const char *hwdb_bin_path;
- const char sig[] = HWDB_SIG;
-
- assert_return(ret, -EINVAL);
-
- hwdb = new0(sd_hwdb, 1);
- if (!hwdb)
- return -ENOMEM;
-
- hwdb->n_ref = REFCNT_INIT;
-
- /* find hwdb.bin in hwdb_bin_paths */
- NULSTR_FOREACH(hwdb_bin_path, hwdb_bin_paths) {
- hwdb->f = fopen(hwdb_bin_path, "re");
- if (hwdb->f) {
- break;
- }
- else if (errno == ENOENT) {
- continue;
- }
- else {
-
- int errsv = -errno;
- log_debug("error reading %s: %s", hwdb_bin_path, strerror(errsv));
- return errsv;
- }
- }
-
- if (!hwdb->f) {
- log_debug("%s", "hwdb.bin does not exist, please run udevadm hwdb --update");
- return -ENOENT;
- }
-
- if (fstat(fileno(hwdb->f), &hwdb->st) < 0 ||
- (size_t)hwdb->st.st_size < offsetof(struct trie_header_f, strings_len) + 8) {
-
- int errsv = errno;
- log_debug("error reading %s: %s", hwdb_bin_path, strerror(errsv));
- return errsv;
- }
-
- hwdb->map = mmap(0, hwdb->st.st_size, PROT_READ, MAP_SHARED, fileno(hwdb->f), 0);
- if (hwdb->map == MAP_FAILED) {
-
- int errsv = errno;
- log_debug("error mapping %s: %s", hwdb_bin_path, strerror(errsv));
- return errsv;
- }
-
- if (memcmp(hwdb->map, sig, sizeof(hwdb->head->signature)) != 0 ||
- (size_t)hwdb->st.st_size != le64toh(hwdb->head->file_size)) {
- log_debug("error recognizing the format of %s", hwdb_bin_path);
- return -EINVAL;;
- }
-
- log_debug("%s\n", "=== trie on-disk ===");
- log_debug("tool version: %"PRIu64, le64toh(hwdb->head->tool_version));
- log_debug("file size: %8"PRIi64" bytes", hwdb->st.st_size);
- log_debug("header size %8"PRIu64" bytes", le64toh(hwdb->head->header_size));
- log_debug("strings %8"PRIu64" bytes", le64toh(hwdb->head->strings_len));
- log_debug("nodes %8"PRIu64" bytes", le64toh(hwdb->head->nodes_len));
-
- *ret = hwdb;
- hwdb = NULL;
-
- return 0;
+ "/lib/systemd/hwdb.bin\0";
+
+_public_ int
+sd_hwdb_new (sd_hwdb ** ret)
+{
+ _cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL;
+ const char *hwdb_bin_path;
+ const char sig[] = HWDB_SIG;
+
+ assert_return (ret, -EINVAL);
+
+ hwdb = new0 (sd_hwdb, 1);
+ if (!hwdb)
+ return -ENOMEM;
+
+ hwdb->n_ref = REFCNT_INIT;
+
+ /* find hwdb.bin in hwdb_bin_paths */
+ NULSTR_FOREACH (hwdb_bin_path, hwdb_bin_paths)
+ {
+ hwdb->f = fopen (hwdb_bin_path, "re");
+ if (hwdb->f)
+ {
+ break;
+ }
+ else if (errno == ENOENT)
+ {
+ continue;
+ }
+ else
+ {
+
+ int errsv = -errno;
+ log_debug ("error reading %s: %s", hwdb_bin_path, strerror (errsv));
+ return errsv;
+ }
+ }
+
+ if (!hwdb->f)
+ {
+ log_debug ("%s",
+ "hwdb.bin does not exist, please run udevadm hwdb --update");
+ return -ENOENT;
+ }
+
+ if (fstat (fileno (hwdb->f), &hwdb->st) < 0 ||
+ (size_t) hwdb->st.st_size < offsetof (struct trie_header_f,
+ strings_len) + 8)
+ {
+
+ int errsv = errno;
+ log_debug ("error reading %s: %s", hwdb_bin_path, strerror (errsv));
+ return errsv;
+ }
+
+ hwdb->map =
+ mmap (0, hwdb->st.st_size, PROT_READ, MAP_SHARED, fileno (hwdb->f), 0);
+ if (hwdb->map == MAP_FAILED)
+ {
+
+ int errsv = errno;
+ log_debug ("error mapping %s: %s", hwdb_bin_path, strerror (errsv));
+ return errsv;
+ }
+
+ if (memcmp (hwdb->map, sig, sizeof (hwdb->head->signature)) != 0 ||
+ (size_t) hwdb->st.st_size != le64toh (hwdb->head->file_size))
+ {
+ log_debug ("error recognizing the format of %s", hwdb_bin_path);
+ return -EINVAL;;
+ }
+
+ log_debug ("%s\n", "=== trie on-disk ===");
+ log_debug ("tool version: %" PRIu64,
+ le64toh (hwdb->head->tool_version));
+ log_debug ("file size: %8" PRIi64 " bytes", hwdb->st.st_size);
+ log_debug ("header size %8" PRIu64 " bytes",
+ le64toh (hwdb->head->header_size));
+ log_debug ("strings %8" PRIu64 " bytes",
+ le64toh (hwdb->head->strings_len));
+ log_debug ("nodes %8" PRIu64 " bytes",
+ le64toh (hwdb->head->nodes_len));
+
+ *ret = hwdb;
+ hwdb = NULL;
+
+ return 0;
}
-_public_ sd_hwdb *sd_hwdb_ref(sd_hwdb *hwdb) {
- assert_return(hwdb, NULL);
+_public_ sd_hwdb *
+sd_hwdb_ref (sd_hwdb * hwdb)
+{
+ assert_return (hwdb, NULL);
- assert_se(REFCNT_INC(hwdb->n_ref) >= 2);
+ assert_se (REFCNT_INC (hwdb->n_ref) >= 2);
- return hwdb;
+ return hwdb;
}
-_public_ sd_hwdb *sd_hwdb_unref(sd_hwdb *hwdb) {
- if (hwdb && REFCNT_DEC(hwdb->n_ref) == 0) {
- if (hwdb->map)
- munmap((void *)hwdb->map, hwdb->st.st_size);
- if (hwdb->f)
- fclose(hwdb->f);
- free(hwdb->modalias);
- ordered_hashmap_free(hwdb->properties);
- free(hwdb);
- }
-
- return NULL;
+_public_ sd_hwdb *
+sd_hwdb_unref (sd_hwdb * hwdb)
+{
+ if (hwdb && REFCNT_DEC (hwdb->n_ref) == 0)
+ {
+ if (hwdb->map)
+ munmap ((void *) hwdb->map, hwdb->st.st_size);
+ if (hwdb->f)
+ fclose (hwdb->f);
+ free (hwdb->modalias);
+ ordered_hashmap_free (hwdb->properties);
+ free (hwdb);
+ }
+
+ return NULL;
}
-bool hwdb_validate(sd_hwdb *hwdb) {
- bool found = false;
- const char* p;
- struct stat st;
-
- if (!hwdb)
- return false;
- if (!hwdb->f)
- return false;
-
- /* if hwdb.bin doesn't exist anywhere, we need to update */
- NULSTR_FOREACH(p, hwdb_bin_paths) {
- if (stat(p, &st) >= 0) {
- found = true;
- break;
- }
- }
- if (!found)
- return true;
-
- if (timespec_load(&hwdb->st.st_mtim) != timespec_load(&st.st_mtim))
- return true;
- return false;
+bool
+hwdb_validate (sd_hwdb * hwdb)
+{
+ bool found = false;
+ const char *p;
+ struct stat st;
+
+ if (!hwdb)
+ return false;
+ if (!hwdb->f)
+ return false;
+
+ /* if hwdb.bin doesn't exist anywhere, we need to update */
+ NULSTR_FOREACH (p, hwdb_bin_paths)
+ {
+ if (stat (p, &st) >= 0)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return true;
+
+ if (timespec_load (&hwdb->st.st_mtim) != timespec_load (&st.st_mtim))
+ return true;
+ return false;
}
-static int properties_prepare(sd_hwdb *hwdb, const char *modalias) {
- char *mod = NULL;
- int r;
+static int
+properties_prepare (sd_hwdb * hwdb, const char *modalias)
+{
+ char *mod = NULL;
+ int r;
- assert(hwdb);
- assert(modalias);
+ assert (hwdb);
+ assert (modalias);
- if (streq_ptr(modalias, hwdb->modalias))
- return 0;
+ if (streq_ptr (modalias, hwdb->modalias))
+ return 0;
- mod = strdup(modalias);
- if (!mod)
- return -ENOMEM;
+ mod = strdup (modalias);
+ if (!mod)
+ return -ENOMEM;
- ordered_hashmap_clear(hwdb->properties);
+ ordered_hashmap_clear (hwdb->properties);
- hwdb->properties_modified = true;
+ hwdb->properties_modified = true;
- r = trie_search_f(hwdb, modalias);
- if (r < 0)
- return r;
+ r = trie_search_f (hwdb, modalias);
+ if (r < 0)
+ return r;
- free(hwdb->modalias);
- hwdb->modalias = mod;
- mod = NULL;
+ free (hwdb->modalias);
+ hwdb->modalias = mod;
+ mod = NULL;
- return 0;
+ return 0;
}
-_public_ int sd_hwdb_get(sd_hwdb *hwdb, const char *modalias, const char *key, const char **_value) {
- const char *value;
- int r;
+_public_ int
+sd_hwdb_get (sd_hwdb * hwdb, const char *modalias, const char *key,
+ const char **_value)
+{
+ const char *value;
+ int r;
- assert_return(hwdb, -EINVAL);
- assert_return(hwdb->f, -EINVAL);
- assert_return(modalias, -EINVAL);
- assert_return(_value, -EINVAL);
+ assert_return (hwdb, -EINVAL);
+ assert_return (hwdb->f, -EINVAL);
+ assert_return (modalias, -EINVAL);
+ assert_return (_value, -EINVAL);
- r = properties_prepare(hwdb, modalias);
- if (r < 0)
- return r;
+ r = properties_prepare (hwdb, modalias);
+ if (r < 0)
+ return r;
- value = ordered_hashmap_get(hwdb->properties, key);
- if (!value)
- return -ENOENT;
+ value = ordered_hashmap_get (hwdb->properties, key);
+ if (!value)
+ return -ENOENT;
- *_value = value;
+ *_value = value;
- return 0;
+ return 0;
}
-_public_ int sd_hwdb_seek(sd_hwdb *hwdb, const char *modalias) {
- int r;
+_public_ int
+sd_hwdb_seek (sd_hwdb * hwdb, const char *modalias)
+{
+ int r;
- assert_return(hwdb, -EINVAL);
- assert_return(hwdb->f, -EINVAL);
- assert_return(modalias, -EINVAL);
+ assert_return (hwdb, -EINVAL);
+ assert_return (hwdb->f, -EINVAL);
+ assert_return (modalias, -EINVAL);
- r = properties_prepare(hwdb, modalias);
- if (r < 0)
- return r;
+ r = properties_prepare (hwdb, modalias);
+ if (r < 0)
+ return r;
- hwdb->properties_modified = false;
- hwdb->properties_iterator = ITERATOR_FIRST;
+ hwdb->properties_modified = false;
+ hwdb->properties_iterator = ITERATOR_FIRST;
- return 0;
+ return 0;
}
-_public_ int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **value) {
- const void *k, *v;
+_public_ int
+sd_hwdb_enumerate (sd_hwdb * hwdb, const char **key, const char **value)
+{
+ const void *k, *v;
- assert_return(hwdb, -EINVAL);
- assert_return(key, -EINVAL);
- assert_return(value, -EINVAL);
+ assert_return (hwdb, -EINVAL);
+ assert_return (key, -EINVAL);
+ assert_return (value, -EINVAL);
- if (hwdb->properties_modified)
- return -EAGAIN;
+ if (hwdb->properties_modified)
+ return -EAGAIN;
- v = ordered_hashmap_iterate(hwdb->properties, &hwdb->properties_iterator, &k);
- if (!k)
- return 0;
+ v = ordered_hashmap_iterate (hwdb->properties,
+ &hwdb->properties_iterator, &k);
+ if (!k)
+ return 0;
- *key = k;
- *value = v;
+ *key = k;
+ *value = v;
- return 1;
+ return 1;
}
diff --git a/libudev-compat/sd-hwdb.h b/libudev-compat/sd-hwdb.h
index 9959fff..a967f0e 100644
--- a/libudev-compat/sd-hwdb.h
+++ b/libudev-compat/sd-hwdb.h
@@ -34,15 +34,16 @@
typedef struct sd_hwdb sd_hwdb;
-sd_hwdb *sd_hwdb_ref(sd_hwdb *hwdb);
-sd_hwdb *sd_hwdb_unref(sd_hwdb *hwdb);
+sd_hwdb *sd_hwdb_ref (sd_hwdb * hwdb);
+sd_hwdb *sd_hwdb_unref (sd_hwdb * hwdb);
-int sd_hwdb_new(sd_hwdb **ret);
+int sd_hwdb_new (sd_hwdb ** ret);
-int sd_hwdb_get(sd_hwdb *hwdb, const char *modalias, const char *key, const char **value);
+int sd_hwdb_get (sd_hwdb * hwdb, const char *modalias, const char *key,
+ const char **value);
-int sd_hwdb_seek(sd_hwdb *hwdb, const char *modalias);
-int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **value);
+int sd_hwdb_seek (sd_hwdb * hwdb, const char *modalias);
+int sd_hwdb_enumerate (sd_hwdb * hwdb, const char **key, const char **value);
/* the inverse condition avoids ambiguity of danling 'else' after the macro */
#define SD_HWDB_FOREACH_PROPERTY(hwdb, modalias, key, value) \
diff --git a/libudev-compat/set.h b/libudev-compat/set.h
index 97cf83d..9c70bd2 100644
--- a/libudev-compat/set.h
+++ b/libudev-compat/set.h
@@ -28,113 +28,150 @@
#include "hashmap.h"
-Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
+Set *internal_set_new (const struct hash_ops * hash_ops HASHMAP_DEBUG_PARAMS);
#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS)
-
-static inline void set_free(Set *s) {
- internal_hashmap_free(HASHMAP_BASE(s));
+static inline void
+set_free (Set * s)
+{
+ internal_hashmap_free (HASHMAP_BASE (s));
}
-static inline void set_free_free(Set *s) {
- internal_hashmap_free_free(HASHMAP_BASE(s));
+static inline void
+set_free_free (Set * s)
+{
+ internal_hashmap_free_free (HASHMAP_BASE (s));
}
/* no set_free_free_free */
-static inline Set *set_copy(Set *s) {
- return (Set*) internal_hashmap_copy(HASHMAP_BASE(s));
+static inline Set *
+set_copy (Set * s)
+{
+ return (Set *) internal_hashmap_copy (HASHMAP_BASE (s));
}
-int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
+int internal_set_ensure_allocated (Set ** s,
+ const struct hash_ops *hash_ops
+ HASHMAP_DEBUG_PARAMS);
#define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
-int set_put(Set *s, const void *key);
+int set_put (Set * s, const void *key);
/* no set_update */
/* no set_replace */
-static inline void *set_get(Set *s, void *key) {
- return internal_hashmap_get(HASHMAP_BASE(s), key);
+static inline void *
+set_get (Set * s, void *key)
+{
+ return internal_hashmap_get (HASHMAP_BASE (s), key);
}
+
/* no set_get2 */
-static inline bool set_contains(Set *s, const void *key) {
- return internal_hashmap_contains(HASHMAP_BASE(s), key);
+static inline bool
+set_contains (Set * s, const void *key)
+{
+ return internal_hashmap_contains (HASHMAP_BASE (s), key);
}
-static inline void *set_remove(Set *s, void *key) {
- return internal_hashmap_remove(HASHMAP_BASE(s), key);
+static inline void *
+set_remove (Set * s, void *key)
+{
+ return internal_hashmap_remove (HASHMAP_BASE (s), key);
}
/* no set_remove2 */
/* no set_remove_value */
-int set_remove_and_put(Set *s, const void *old_key, const void *new_key);
+int set_remove_and_put (Set * s, const void *old_key, const void *new_key);
/* no set_remove_and_replace */
-int set_merge(Set *s, Set *other);
+int set_merge (Set * s, Set * other);
-static inline int set_reserve(Set *h, unsigned entries_add) {
- return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add);
+static inline int
+set_reserve (Set * h, unsigned entries_add)
+{
+ return internal_hashmap_reserve (HASHMAP_BASE (h), entries_add);
}
-static inline int set_move(Set *s, Set *other) {
- return internal_hashmap_move(HASHMAP_BASE(s), HASHMAP_BASE(other));
+static inline int
+set_move (Set * s, Set * other)
+{
+ return internal_hashmap_move (HASHMAP_BASE (s), HASHMAP_BASE (other));
}
-static inline int set_move_one(Set *s, Set *other, const void *key) {
- return internal_hashmap_move_one(HASHMAP_BASE(s), HASHMAP_BASE(other), key);
+static inline int
+set_move_one (Set * s, Set * other, const void *key)
+{
+ return internal_hashmap_move_one (HASHMAP_BASE (s), HASHMAP_BASE (other),
+ key);
}
-static inline unsigned set_size(Set *s) {
- return internal_hashmap_size(HASHMAP_BASE(s));
+static inline unsigned
+set_size (Set * s)
+{
+ return internal_hashmap_size (HASHMAP_BASE (s));
}
-static inline bool set_isempty(Set *s) {
- return set_size(s) == 0;
+static inline bool
+set_isempty (Set * s)
+{
+ return set_size (s) == 0;
}
-static inline unsigned set_buckets(Set *s) {
- return internal_hashmap_buckets(HASHMAP_BASE(s));
+static inline unsigned
+set_buckets (Set * s)
+{
+ return internal_hashmap_buckets (HASHMAP_BASE (s));
}
-void *set_iterate(Set *s, Iterator *i);
+void *set_iterate (Set * s, Iterator * i);
-static inline void set_clear(Set *s) {
- internal_hashmap_clear(HASHMAP_BASE(s));
+static inline void
+set_clear (Set * s)
+{
+ internal_hashmap_clear (HASHMAP_BASE (s));
}
-static inline void set_clear_free(Set *s) {
- internal_hashmap_clear_free(HASHMAP_BASE(s));
+static inline void
+set_clear_free (Set * s)
+{
+ internal_hashmap_clear_free (HASHMAP_BASE (s));
}
/* no set_clear_free_free */
-static inline void *set_steal_first(Set *s) {
- return internal_hashmap_steal_first(HASHMAP_BASE(s));
+static inline void *
+set_steal_first (Set * s)
+{
+ return internal_hashmap_steal_first (HASHMAP_BASE (s));
}
/* no set_steal_first_key */
/* no set_first_key */
-static inline void *set_first(Set *s) {
- return internal_hashmap_first(HASHMAP_BASE(s));
+static inline void *
+set_first (Set * s)
+{
+ return internal_hashmap_first (HASHMAP_BASE (s));
}
/* no set_next */
-static inline char **set_get_strv(Set *s) {
- return internal_hashmap_get_strv(HASHMAP_BASE(s));
+static inline char **
+set_get_strv (Set * s)
+{
+ return internal_hashmap_get_strv (HASHMAP_BASE (s));
}
-int set_consume(Set *s, void *value);
-int set_put_strdup(Set *s, const char *p);
-int set_put_strdupv(Set *s, char **l);
+int set_consume (Set * s, void *value);
+int set_put_strdup (Set * s, const char *p);
+int set_put_strdupv (Set * s, char **l);
#define SET_FOREACH(e, s, i) \
for ((i) = ITERATOR_FIRST, (e) = set_iterate((s), &(i)); (e); (e) = set_iterate((s), &(i)))
-DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free);
-DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC (Set *, set_free);
+DEFINE_TRIVIAL_CLEANUP_FUNC (Set *, set_free_free);
#define _cleanup_set_free_ _cleanup_(set_freep)
#define _cleanup_set_free_free_ _cleanup_(set_free_freep)
-#endif
\ No newline at end of file
+#endif
diff --git a/libudev-compat/siphash24.c b/libudev-compat/siphash24.c
index 51e4b6e..29bf033 100644
--- a/libudev-compat/siphash24.c
+++ b/libudev-compat/siphash24.c
@@ -58,7 +58,8 @@ typedef uint8_t u8;
} while(0)
/* SipHash-2-4 */
-void siphash24(uint8_t out[8], const void *_in, size_t inlen, const uint8_t k[16])
+void
+siphash24 (uint8_t out[8], const void *_in, size_t inlen, const uint8_t k[16])
{
/* "somepseudorandomlygeneratedbytes" */
u64 v0 = 0x736f6d6570736575ULL;
@@ -66,75 +67,90 @@ void siphash24(uint8_t out[8], const void *_in, size_t inlen, const uint8_t k[16
u64 v2 = 0x6c7967656e657261ULL;
u64 v3 = 0x7465646279746573ULL;
u64 b;
- u64 k0 = U8TO64_LE( k );
- u64 k1 = U8TO64_LE( k + 8 );
+ u64 k0 = U8TO64_LE (k);
+ u64 k1 = U8TO64_LE (k + 8);
u64 m;
const u8 *in = _in;
- const u8 *end = in + inlen - ( inlen % sizeof( u64 ) );
+ const u8 *end = in + inlen - (inlen % sizeof (u64));
const int left = inlen & 7;
- b = ( ( u64 )inlen ) << 56;
+ b = ((u64) inlen) << 56;
v3 ^= k1;
v2 ^= k0;
v1 ^= k1;
v0 ^= k0;
- for ( ; in != end; in += 8 )
- {
- m = U8TO64_LE( in );
+ for (; in != end; in += 8)
+ {
+ m = U8TO64_LE (in);
#ifdef DEBUG
- printf( "(%3d) v0 %08x %08x\n", ( int )inlen, ( u32 )( v0 >> 32 ), ( u32 )v0 );
- printf( "(%3d) v1 %08x %08x\n", ( int )inlen, ( u32 )( v1 >> 32 ), ( u32 )v1 );
- printf( "(%3d) v2 %08x %08x\n", ( int )inlen, ( u32 )( v2 >> 32 ), ( u32 )v2 );
- printf( "(%3d) v3 %08x %08x\n", ( int )inlen, ( u32 )( v3 >> 32 ), ( u32 )v3 );
- printf( "(%3d) compress %08x %08x\n", ( int )inlen, ( u32 )( m >> 32 ), ( u32 )m );
+ printf ("(%3d) v0 %08x %08x\n", (int) inlen, (u32) (v0 >> 32),
+ (u32) v0);
+ printf ("(%3d) v1 %08x %08x\n", (int) inlen, (u32) (v1 >> 32),
+ (u32) v1);
+ printf ("(%3d) v2 %08x %08x\n", (int) inlen, (u32) (v2 >> 32),
+ (u32) v2);
+ printf ("(%3d) v3 %08x %08x\n", (int) inlen, (u32) (v3 >> 32),
+ (u32) v3);
+ printf ("(%3d) compress %08x %08x\n", (int) inlen,
+ (u32) (m >> 32), (u32) m);
#endif
- v3 ^= m;
- SIPROUND;
- SIPROUND;
- v0 ^= m;
- }
+ v3 ^= m;
+ SIPROUND;
+ SIPROUND;
+ v0 ^= m;
+ }
- switch( left )
- {
- case 7: b |= ( ( u64 )in[ 6] ) << 48;
+ switch (left)
+ {
+ case 7:
+ b |= ((u64) in[6]) << 48;
- case 6: b |= ( ( u64 )in[ 5] ) << 40;
+ case 6:
+ b |= ((u64) in[5]) << 40;
- case 5: b |= ( ( u64 )in[ 4] ) << 32;
+ case 5:
+ b |= ((u64) in[4]) << 32;
- case 4: b |= ( ( u64 )in[ 3] ) << 24;
+ case 4:
+ b |= ((u64) in[3]) << 24;
- case 3: b |= ( ( u64 )in[ 2] ) << 16;
+ case 3:
+ b |= ((u64) in[2]) << 16;
- case 2: b |= ( ( u64 )in[ 1] ) << 8;
+ case 2:
+ b |= ((u64) in[1]) << 8;
- case 1: b |= ( ( u64 )in[ 0] ); break;
+ case 1:
+ b |= ((u64) in[0]);
+ break;
- case 0: break;
- }
+ case 0:
+ break;
+ }
#ifdef DEBUG
- printf( "(%3d) v0 %08x %08x\n", ( int )inlen, ( u32 )( v0 >> 32 ), ( u32 )v0 );
- printf( "(%3d) v1 %08x %08x\n", ( int )inlen, ( u32 )( v1 >> 32 ), ( u32 )v1 );
- printf( "(%3d) v2 %08x %08x\n", ( int )inlen, ( u32 )( v2 >> 32 ), ( u32 )v2 );
- printf( "(%3d) v3 %08x %08x\n", ( int )inlen, ( u32 )( v3 >> 32 ), ( u32 )v3 );
- printf( "(%3d) padding %08x %08x\n", ( int )inlen, ( u32 )( b >> 32 ), ( u32 )b );
+ printf ("(%3d) v0 %08x %08x\n", (int) inlen, (u32) (v0 >> 32), (u32) v0);
+ printf ("(%3d) v1 %08x %08x\n", (int) inlen, (u32) (v1 >> 32), (u32) v1);
+ printf ("(%3d) v2 %08x %08x\n", (int) inlen, (u32) (v2 >> 32), (u32) v2);
+ printf ("(%3d) v3 %08x %08x\n", (int) inlen, (u32) (v3 >> 32), (u32) v3);
+ printf ("(%3d) padding %08x %08x\n", (int) inlen, (u32) (b >> 32),
+ (u32) b);
#endif
v3 ^= b;
SIPROUND;
SIPROUND;
v0 ^= b;
#ifdef DEBUG
- printf( "(%3d) v0 %08x %08x\n", ( int )inlen, ( u32 )( v0 >> 32 ), ( u32 )v0 );
- printf( "(%3d) v1 %08x %08x\n", ( int )inlen, ( u32 )( v1 >> 32 ), ( u32 )v1 );
- printf( "(%3d) v2 %08x %08x\n", ( int )inlen, ( u32 )( v2 >> 32 ), ( u32 )v2 );
- printf( "(%3d) v3 %08x %08x\n", ( int )inlen, ( u32 )( v3 >> 32 ), ( u32 )v3 );
+ printf ("(%3d) v0 %08x %08x\n", (int) inlen, (u32) (v0 >> 32), (u32) v0);
+ printf ("(%3d) v1 %08x %08x\n", (int) inlen, (u32) (v1 >> 32), (u32) v1);
+ printf ("(%3d) v2 %08x %08x\n", (int) inlen, (u32) (v2 >> 32), (u32) v2);
+ printf ("(%3d) v3 %08x %08x\n", (int) inlen, (u32) (v3 >> 32), (u32) v3);
#endif
v2 ^= 0xff;
SIPROUND;
SIPROUND;
SIPROUND;
SIPROUND;
- b = v0 ^ v1 ^ v2 ^ v3;
- U64TO8_LE( out, b );
-}
\ No newline at end of file
+ b = v0 ^ v1 ^ v2 ^ v3;
+ U64TO8_LE (out, b);
+}
diff --git a/libudev-compat/siphash24.h b/libudev-compat/siphash24.h
index 859a852..888cded 100644
--- a/libudev-compat/siphash24.h
+++ b/libudev-compat/siphash24.h
@@ -12,6 +12,7 @@
#include
#include
-void siphash24(uint8_t out[8], const void *in, size_t inlen, const uint8_t k[16]);
+void siphash24 (uint8_t out[8], const void *in, size_t inlen,
+ const uint8_t k[16]);
-#endif
\ No newline at end of file
+#endif
diff --git a/libudev-compat/sparse-endian.h b/libudev-compat/sparse-endian.h
index 11145ed..8ace142 100644
--- a/libudev-compat/sparse-endian.h
+++ b/libudev-compat/sparse-endian.h
@@ -78,20 +78,76 @@ typedef uint64_t __bitwise be64_t;
#define bswap_64_on_be(x) __bswap_64(x)
#endif
-static inline le16_t htole16(uint16_t value) { return (le16_t __force) bswap_16_on_be(value); }
-static inline le32_t htole32(uint32_t value) { return (le32_t __force) bswap_32_on_be(value); }
-static inline le64_t htole64(uint64_t value) { return (le64_t __force) bswap_64_on_be(value); }
+static inline le16_t
+htole16 (uint16_t value)
+{
+ return (le16_t __force) bswap_16_on_be (value);
+}
-static inline be16_t htobe16(uint16_t value) { return (be16_t __force) bswap_16_on_le(value); }
-static inline be32_t htobe32(uint32_t value) { return (be32_t __force) bswap_32_on_le(value); }
-static inline be64_t htobe64(uint64_t value) { return (be64_t __force) bswap_64_on_le(value); }
+static inline le32_t
+htole32 (uint32_t value)
+{
+ return (le32_t __force) bswap_32_on_be (value);
+}
-static inline uint16_t le16toh(le16_t value) { return bswap_16_on_be((uint16_t __force)value); }
-static inline uint32_t le32toh(le32_t value) { return bswap_32_on_be((uint32_t __force)value); }
-static inline uint64_t le64toh(le64_t value) { return bswap_64_on_be((uint64_t __force)value); }
+static inline le64_t
+htole64 (uint64_t value)
+{
+ return (le64_t __force) bswap_64_on_be (value);
+}
-static inline uint16_t be16toh(be16_t value) { return bswap_16_on_le((uint16_t __force)value); }
-static inline uint32_t be32toh(be32_t value) { return bswap_32_on_le((uint32_t __force)value); }
-static inline uint64_t be64toh(be64_t value) { return bswap_64_on_le((uint64_t __force)value); }
+static inline be16_t
+htobe16 (uint16_t value)
+{
+ return (be16_t __force) bswap_16_on_le (value);
+}
+
+static inline be32_t
+htobe32 (uint32_t value)
+{
+ return (be32_t __force) bswap_32_on_le (value);
+}
+
+static inline be64_t
+htobe64 (uint64_t value)
+{
+ return (be64_t __force) bswap_64_on_le (value);
+}
+
+static inline uint16_t
+le16toh (le16_t value)
+{
+ return bswap_16_on_be ((uint16_t __force) value);
+}
+
+static inline uint32_t
+le32toh (le32_t value)
+{
+ return bswap_32_on_be ((uint32_t __force) value);
+}
+
+static inline uint64_t
+le64toh (le64_t value)
+{
+ return bswap_64_on_be ((uint64_t __force) value);
+}
+
+static inline uint16_t
+be16toh (be16_t value)
+{
+ return bswap_16_on_le ((uint16_t __force) value);
+}
+
+static inline uint32_t
+be32toh (be32_t value)
+{
+ return bswap_32_on_le ((uint32_t __force) value);
+}
+
+static inline uint64_t
+be64toh (be64_t value)
+{
+ return bswap_64_on_le ((uint64_t __force) value);
+}
#endif /* SPARSE_ENDIAN_H */
diff --git a/libudev-compat/strxcpyx.c b/libudev-compat/strxcpyx.c
index 88a14db..9fee918 100644
--- a/libudev-compat/strxcpyx.c
+++ b/libudev-compat/strxcpyx.c
@@ -36,72 +36,93 @@
#include
#include "strxcpyx.h"
-size_t strpcpy(char **dest, size_t size, const char *src) {
- size_t len;
-
- len = strlen(src);
- if (len >= size) {
- if (size > 1)
- *dest = mempcpy(*dest, src, size-1);
- size = 0;
- } else {
- if (len > 0) {
- *dest = mempcpy(*dest, src, len);
- size -= len;
- }
- }
- *dest[0] = '\0';
- return size;
+size_t
+strpcpy (char **dest, size_t size, const char *src)
+{
+ size_t len;
+
+ len = strlen (src);
+ if (len >= size)
+ {
+ if (size > 1)
+ *dest = mempcpy (*dest, src, size - 1);
+ size = 0;
+ }
+ else
+ {
+ if (len > 0)
+ {
+ *dest = mempcpy (*dest, src, len);
+ size -= len;
+ }
+ }
+ *dest[0] = '\0';
+ return size;
}
-size_t strpcpyf(char **dest, size_t size, const char *src, ...) {
- va_list va;
- int i;
-
- va_start(va, src);
- i = vsnprintf(*dest, size, src, va);
- if (i < (int)size) {
- *dest += i;
- size -= i;
- } else {
- *dest += size;
- size = 0;
- }
- va_end(va);
- *dest[0] = '\0';
- return size;
+size_t
+strpcpyf (char **dest, size_t size, const char *src, ...)
+{
+ va_list va;
+ int i;
+
+ va_start (va, src);
+ i = vsnprintf (*dest, size, src, va);
+ if (i < (int) size)
+ {
+ *dest += i;
+ size -= i;
+ }
+ else
+ {
+ *dest += size;
+ size = 0;
+ }
+ va_end (va);
+ *dest[0] = '\0';
+ return size;
}
-size_t strpcpyl(char **dest, size_t size, const char *src, ...) {
- va_list va;
-
- va_start(va, src);
- do {
- size = strpcpy(dest, size, src);
- src = va_arg(va, char *);
- } while (src != NULL);
- va_end(va);
- return size;
+size_t
+strpcpyl (char **dest, size_t size, const char *src, ...)
+{
+ va_list va;
+
+ va_start (va, src);
+ do
+ {
+ size = strpcpy (dest, size, src);
+ src = va_arg (va, char *);
+ }
+ while (src != NULL);
+ va_end (va);
+ return size;
}
-size_t strscpy(char *dest, size_t size, const char *src) {
- char *s;
+size_t
+strscpy (char *dest, size_t size, const char *src)
+{
+ char *s;
- s = dest;
- return strpcpy(&s, size, src);
+ s = dest;
+ return strpcpy (&s, size, src);
}
-size_t strscpyl(char *dest, size_t size, const char *src, ...) {
- va_list va;
- char *s;
-
- va_start(va, src);
- s = dest;
- do {
- size = strpcpy(&s, size, src);
- src = va_arg(va, char *);
- } while (src != NULL);
- va_end(va);
-
- return size;
+size_t
+strscpyl (char *dest, size_t size, const char *src, ...)
+{
+ va_list va;
+ char *s;
+
+ va_start (va, src);
+ s = dest;
+ do
+ {
+ size = strpcpy (&s, size, src);
+ src = va_arg (va, char *);
+ }
+ while (src != NULL);
+ va_end (va);
+
+ return size;
}
diff --git a/libudev-compat/strxcpyx.h b/libudev-compat/strxcpyx.h
index 7d8276a..db496e4 100644
--- a/libudev-compat/strxcpyx.h
+++ b/libudev-compat/strxcpyx.h
@@ -35,10 +35,14 @@
// #include "macro.h"
#include "util.h"
-size_t strpcpy(char **dest, size_t size, const char *src);
-size_t strpcpyf(char **dest, size_t size, const char *src, ...) _printf_(3, 4);
-size_t strpcpyl(char **dest, size_t size, const char *src, ...) _sentinel_;
-size_t strscpy(char *dest, size_t size, const char *src);
-size_t strscpyl(char *dest, size_t size, const char *src, ...) _sentinel_;
-
-#endif
\ No newline at end of file
+size_t strpcpy (char **dest, size_t size, const char *src);
+size_t
+strpcpyf (char **dest, size_t size, const char *src, ...)
+_printf_ (3, 4);
+ size_t strpcpyl (char **dest, size_t size, const char *src,
+ ...) _sentinel_;
+ size_t strscpy (char *dest, size_t size, const char *src);
+ size_t strscpyl (char *dest, size_t size, const char *src,
+ ...) _sentinel_;
+
+#endif
diff --git a/libudev-compat/utf8.c b/libudev-compat/utf8.c
index 4f2bffd..3d4df40 100644
--- a/libudev-compat/utf8.c
+++ b/libudev-compat/utf8.c
@@ -59,215 +59,245 @@
#include "utf8.h"
#include "util.h"
-static inline bool is_unicode_valid(uint32_t ch) {
-
- if (ch >= 0x110000) /* End of unicode space */
- return false;
- if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */
- return false;
- if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) /* Reserved */
- return false;
- if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */
- return false;
-
- return true;
+static inline bool
+is_unicode_valid (uint32_t ch)
+{
+
+ if (ch >= 0x110000) /* End of unicode space */
+ return false;
+ if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */
+ return false;
+ if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) /* Reserved */
+ return false;
+ if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */
+ return false;
+
+ return true;
}
-static bool is_unicode_control(uint32_t ch) {
+static bool
+is_unicode_control (uint32_t ch)
+{
- /*
- 0 to ' '-1 is the C0 range.
- DEL=0x7F, and DEL+1 to 0x9F is C1 range.
- '\t' is in C0 range, but more or less harmless and commonly used.
- */
+ /*
+ 0 to ' '-1 is the C0 range.
+ DEL=0x7F, and DEL+1 to 0x9F is C1 range.
+ '\t' is in C0 range, but more or less harmless and commonly used.
+ */
- return (ch < ' ' && ch != '\t' && ch != '\n') ||
- (0x7F <= ch && ch <= 0x9F);
+ return (ch < ' ' && ch != '\t' && ch != '\n') || (0x7F <= ch && ch <= 0x9F);
}
/* count of characters used to encode one unicode char */
-static int utf8_encoded_expected_len(const char *str) {
- unsigned char c;
-
- assert(str);
-
- c = (unsigned char) str[0];
- if (c < 0x80)
- return 1;
- if ((c & 0xe0) == 0xc0)
- return 2;
- if ((c & 0xf0) == 0xe0)
- return 3;
- if ((c & 0xf8) == 0xf0)
- return 4;
- if ((c & 0xfc) == 0xf8)
- return 5;
- if ((c & 0xfe) == 0xfc)
- return 6;
-
- return 0;
+static int
+utf8_encoded_expected_len (const char *str)
+{
+ unsigned char c;
+
+ assert (str);
+
+ c = (unsigned char) str[0];
+ if (c < 0x80)
+ return 1;
+ if ((c & 0xe0) == 0xc0)
+ return 2;
+ if ((c & 0xf0) == 0xe0)
+ return 3;
+ if ((c & 0xf8) == 0xf0)
+ return 4;
+ if ((c & 0xfc) == 0xf8)
+ return 5;
+ if ((c & 0xfe) == 0xfc)
+ return 6;
+
+ return 0;
}
/* decode one unicode char */
-int utf8_encoded_to_unichar(const char *str) {
- int unichar, len, i;
-
- assert(str);
-
- len = utf8_encoded_expected_len(str);
-
- switch (len) {
- case 1:
- return (int)str[0];
- case 2:
- unichar = str[0] & 0x1f;
- break;
- case 3:
- unichar = (int)str[0] & 0x0f;
- break;
- case 4:
- unichar = (int)str[0] & 0x07;
- break;
- case 5:
- unichar = (int)str[0] & 0x03;
- break;
- case 6:
- unichar = (int)str[0] & 0x01;
- break;
- default:
- return -EINVAL;
- }
-
- for (i = 1; i < len; i++) {
- if (((int)str[i] & 0xc0) != 0x80)
- return -EINVAL;
- unichar <<= 6;
- unichar |= (int)str[i] & 0x3f;
- }
-
- return unichar;
+int
+utf8_encoded_to_unichar (const char *str)
+{
+ int unichar, len, i;
+
+ assert (str);
+
+ len = utf8_encoded_expected_len (str);
+
+ switch (len)
+ {
+ case 1:
+ return (int) str[0];
+ case 2:
+ unichar = str[0] & 0x1f;
+ break;
+ case 3:
+ unichar = (int) str[0] & 0x0f;
+ break;
+ case 4:
+ unichar = (int) str[0] & 0x07;
+ break;
+ case 5:
+ unichar = (int) str[0] & 0x03;
+ break;
+ case 6:
+ unichar = (int) str[0] & 0x01;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 1; i < len; i++)
+ {
+ if (((int) str[i] & 0xc0) != 0x80)
+ return -EINVAL;
+ unichar <<= 6;
+ unichar |= (int) str[i] & 0x3f;
+ }
+
+ return unichar;
}
-bool utf8_is_printable_newline(const char* str, size_t length, bool newline) {
- const char *p;
+bool
+utf8_is_printable_newline (const char *str, size_t length, bool newline)
+{
+ const char *p;
- assert(str);
+ assert (str);
- for (p = str; length;) {
- int encoded_len, val;
+ for (p = str; length;)
+ {
+ int encoded_len, val;
- encoded_len = utf8_encoded_valid_unichar(p);
- if (encoded_len < 0 ||
- (size_t) encoded_len > length)
- return false;
+ encoded_len = utf8_encoded_valid_unichar (p);
+ if (encoded_len < 0 || (size_t) encoded_len > length)
+ return false;
- val = utf8_encoded_to_unichar(p);
- if (val < 0 ||
- is_unicode_control(val) ||
- (!newline && val == '\n'))
- return false;
+ val = utf8_encoded_to_unichar (p);
+ if (val < 0 || is_unicode_control (val) || (!newline && val == '\n'))
+ return false;
- length -= encoded_len;
- p += encoded_len;
- }
+ length -= encoded_len;
+ p += encoded_len;
+ }
- return true;
+ return true;
}
-const char *utf8_is_valid(const char *str) {
- const uint8_t *p;
+const char *
+utf8_is_valid (const char *str)
+{
+ const uint8_t *p;
- assert(str);
+ assert (str);
- for (p = (const uint8_t*) str; *p; ) {
- int len;
+ for (p = (const uint8_t *) str; *p;)
+ {
+ int len;
- len = utf8_encoded_valid_unichar((const char *)p);
- if (len < 0)
- return NULL;
+ len = utf8_encoded_valid_unichar ((const char *) p);
+ if (len < 0)
+ return NULL;
- p += len;
- }
+ p += len;
+ }
- return str;
+ return str;
}
-char *utf8_escape_invalid(const char *str) {
- char *p, *s;
-
- assert(str);
-
- p = s = malloc(strlen(str) * 4 + 1);
- if (!p)
- return NULL;
-
- while (*str) {
- int len;
-
- len = utf8_encoded_valid_unichar(str);
- if (len > 0) {
- s = mempcpy(s, str, len);
- str += len;
- } else {
- s = stpcpy(s, UTF8_REPLACEMENT_CHARACTER);
- str += 1;
- }
- }
-
- *s = '\0';
-
- return p;
+char *
+utf8_escape_invalid (const char *str)
+{
+ char *p, *s;
+
+ assert (str);
+
+ p = s = malloc (strlen (str) * 4 + 1);
+ if (!p)
+ return NULL;
+
+ while (*str)
+ {
+ int len;
+
+ len = utf8_encoded_valid_unichar (str);
+ if (len > 0)
+ {
+ s = mempcpy (s, str, len);
+ str += len;
+ }
+ else
+ {
+ s = stpcpy (s, UTF8_REPLACEMENT_CHARACTER);
+ str += 1;
+ }
+ }
+
+ *s = '\0';
+
+ return p;
}
-char *utf8_escape_non_printable(const char *str) {
- char *p, *s;
-
- assert(str);
-
- p = s = malloc(strlen(str) * 4 + 1);
- if (!p)
- return NULL;
-
- while (*str) {
- int len;
-
- len = utf8_encoded_valid_unichar(str);
- if (len > 0) {
- if (utf8_is_printable(str, len)) {
- s = mempcpy(s, str, len);
- str += len;
- } else {
- while (len > 0) {
- *(s++) = '\\';
- *(s++) = 'x';
- *(s++) = hexchar((int) *str >> 4);
- *(s++) = hexchar((int) *str);
-
- str += 1;
- len --;
- }
- }
- } else {
- s = stpcpy(s, UTF8_REPLACEMENT_CHARACTER);
- str += 1;
- }
- }
-
- *s = '\0';
-
- return p;
+char *
+utf8_escape_non_printable (const char *str)
+{
+ char *p, *s;
+
+ assert (str);
+
+ p = s = malloc (strlen (str) * 4 + 1);
+ if (!p)
+ return NULL;
+
+ while (*str)
+ {
+ int len;
+
+ len = utf8_encoded_valid_unichar (str);
+ if (len > 0)
+ {
+ if (utf8_is_printable (str, len))
+ {
+ s = mempcpy (s, str, len);
+ str += len;
+ }
+ else
+ {
+ while (len > 0)
+ {
+ *(s++) = '\\';
+ *(s++) = 'x';
+ *(s++) = hexchar ((int) *str >> 4);
+ *(s++) = hexchar ((int) *str);
+
+ str += 1;
+ len--;
+ }
+ }
+ }
+ else
+ {
+ s = stpcpy (s, UTF8_REPLACEMENT_CHARACTER);
+ str += 1;
+ }
+ }
+
+ *s = '\0';
+
+ return p;
}
-char *ascii_is_valid(const char *str) {
- const char *p;
+char *
+ascii_is_valid (const char *str)
+{
+ const char *p;
- assert(str);
+ assert (str);
- for (p = str; *p; p++)
- if ((unsigned char) *p >= 128)
- return NULL;
+ for (p = str; *p; p++)
+ if ((unsigned char) *p >= 128)
+ return NULL;
- return (char*) str;
+ return (char *) str;
}
/**
@@ -282,127 +312,150 @@ char *ascii_is_valid(const char *str) {
* Returns: The length in bytes that the UTF-8 representation does or would
* occupy.
*/
-size_t utf8_encode_unichar(char *out_utf8, uint32_t g) {
- if (g < (1 << 7)) {
- if (out_utf8)
- out_utf8[0] = g & 0x7f;
- return 1;
- } else if (g < (1 << 11)) {
- if (out_utf8) {
- out_utf8[0] = 0xc0 | ((g >> 6) & 0x1f);
- out_utf8[1] = 0x80 | (g & 0x3f);
- }
- return 2;
- } else if (g < (1 << 16)) {
- if (out_utf8) {
- out_utf8[0] = 0xe0 | ((g >> 12) & 0x0f);
- out_utf8[1] = 0x80 | ((g >> 6) & 0x3f);
- out_utf8[2] = 0x80 | (g & 0x3f);
- }
- return 3;
- } else if (g < (1 << 21)) {
- if (out_utf8) {
- out_utf8[0] = 0xf0 | ((g >> 18) & 0x07);
- out_utf8[1] = 0x80 | ((g >> 12) & 0x3f);
- out_utf8[2] = 0x80 | ((g >> 6) & 0x3f);
- out_utf8[3] = 0x80 | (g & 0x3f);
- }
- return 4;
- } else {
- return 0;
- }
+size_t
+utf8_encode_unichar (char *out_utf8, uint32_t g)
+{
+ if (g < (1 << 7))
+ {
+ if (out_utf8)
+ out_utf8[0] = g & 0x7f;
+ return 1;
+ }
+ else if (g < (1 << 11))
+ {
+ if (out_utf8)
+ {
+ out_utf8[0] = 0xc0 | ((g >> 6) & 0x1f);
+ out_utf8[1] = 0x80 | (g & 0x3f);
+ }
+ return 2;
+ }
+ else if (g < (1 << 16))
+ {
+ if (out_utf8)
+ {
+ out_utf8[0] = 0xe0 | ((g >> 12) & 0x0f);
+ out_utf8[1] = 0x80 | ((g >> 6) & 0x3f);
+ out_utf8[2] = 0x80 | (g & 0x3f);
+ }
+ return 3;
+ }
+ else if (g < (1 << 21))
+ {
+ if (out_utf8)
+ {
+ out_utf8[0] = 0xf0 | ((g >> 18) & 0x07);
+ out_utf8[1] = 0x80 | ((g >> 12) & 0x3f);
+ out_utf8[2] = 0x80 | ((g >> 6) & 0x3f);
+ out_utf8[3] = 0x80 | (g & 0x3f);
+ }
+ return 4;
+ }
+ else
+ {
+ return 0;
+ }
}
-char *utf16_to_utf8(const void *s, size_t length) {
- const uint8_t *f;
- char *r, *t;
+char *
+utf16_to_utf8 (const void *s, size_t length)
+{
+ const uint8_t *f;
+ char *r, *t;
- r = new(char, (length * 4 + 1) / 2 + 1);
- if (!r)
- return NULL;
+ r = new (char, (length * 4 + 1) / 2 + 1);
+ if (!r)
+ return NULL;
- f = s;
- t = r;
+ f = s;
+ t = r;
- while (f < (const uint8_t*) s + length) {
- uint16_t w1, w2;
+ while (f < (const uint8_t *) s + length)
+ {
+ uint16_t w1, w2;
- /* see RFC 2781 section 2.2 */
+ /* see RFC 2781 section 2.2 */
- w1 = f[1] << 8 | f[0];
- f += 2;
+ w1 = f[1] << 8 | f[0];
+ f += 2;
- if (!utf16_is_surrogate(w1)) {
- t += utf8_encode_unichar(t, w1);
+ if (!utf16_is_surrogate (w1))
+ {
+ t += utf8_encode_unichar (t, w1);
- continue;
- }
+ continue;
+ }
- if (utf16_is_trailing_surrogate(w1))
- continue;
- else if (f >= (const uint8_t*) s + length)
- break;
+ if (utf16_is_trailing_surrogate (w1))
+ continue;
+ else if (f >= (const uint8_t *) s + length)
+ break;
- w2 = f[1] << 8 | f[0];
- f += 2;
+ w2 = f[1] << 8 | f[0];
+ f += 2;
- if (!utf16_is_trailing_surrogate(w2)) {
- f -= 2;
- continue;
- }
+ if (!utf16_is_trailing_surrogate (w2))
+ {
+ f -= 2;
+ continue;
+ }
- t += utf8_encode_unichar(t, utf16_surrogate_pair_to_unichar(w1, w2));
- }
+ t += utf8_encode_unichar (t, utf16_surrogate_pair_to_unichar (w1, w2));
+ }
- *t = 0;
- return r;
+ *t = 0;
+ return r;
}
/* expected size used to encode one unicode char */
-static int utf8_unichar_to_encoded_len(int unichar) {
-
- if (unichar < 0x80)
- return 1;
- if (unichar < 0x800)
- return 2;
- if (unichar < 0x10000)
- return 3;
- if (unichar < 0x200000)
- return 4;
- if (unichar < 0x4000000)
- return 5;
-
- return 6;
+static int
+utf8_unichar_to_encoded_len (int unichar)
+{
+
+ if (unichar < 0x80)
+ return 1;
+ if (unichar < 0x800)
+ return 2;
+ if (unichar < 0x10000)
+ return 3;
+ if (unichar < 0x200000)
+ return 4;
+ if (unichar < 0x4000000)
+ return 5;
+
+ return 6;
}
/* validate one encoded unicode char and return its length */
-int utf8_encoded_valid_unichar(const char *str) {
- int len, unichar, i;
+int
+utf8_encoded_valid_unichar (const char *str)
+{
+ int len, unichar, i;
- assert(str);
+ assert (str);
- len = utf8_encoded_expected_len(str);
- if (len == 0)
- return -EINVAL;
+ len = utf8_encoded_expected_len (str);
+ if (len == 0)
+ return -EINVAL;
- /* ascii is valid */
- if (len == 1)
- return 1;
+ /* ascii is valid */
+ if (len == 1)
+ return 1;
- /* check if expected encoded chars are available */
- for (i = 0; i < len; i++)
- if ((str[i] & 0x80) != 0x80)
- return -EINVAL;
+ /* check if expected encoded chars are available */
+ for (i = 0; i < len; i++)
+ if ((str[i] & 0x80) != 0x80)
+ return -EINVAL;
- unichar = utf8_encoded_to_unichar(str);
+ unichar = utf8_encoded_to_unichar (str);
- /* check if encoded length matches encoded value */
- if (utf8_unichar_to_encoded_len(unichar) != len)
- return -EINVAL;
+ /* check if encoded length matches encoded value */
+ if (utf8_unichar_to_encoded_len (unichar) != len)
+ return -EINVAL;
- /* check if value has valid range */
- if (!is_unicode_valid(unichar))
- return -EINVAL;
+ /* check if value has valid range */
+ if (!is_unicode_valid (unichar))
+ return -EINVAL;
- return len;
+ return len;
}
diff --git a/libudev-compat/utf8.h b/libudev-compat/utf8.h
index 0a23888..58211b8 100644
--- a/libudev-compat/utf8.h
+++ b/libudev-compat/utf8.h
@@ -36,31 +36,39 @@
#define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd"
-const char *utf8_is_valid(const char *s) _pure_;
-char *ascii_is_valid(const char *s) _pure_;
+const char *
+utf8_is_valid (const char *s)
+ _pure_;
+ char *ascii_is_valid (const char *s) _pure_;
-bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pure_;
+ bool utf8_is_printable_newline (const char *str, size_t length,
+ bool newline) _pure_;
#define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true)
-char *utf8_escape_invalid(const char *s);
-char *utf8_escape_non_printable(const char *str);
+ char *utf8_escape_invalid (const char *s);
+ char *utf8_escape_non_printable (const char *str);
-size_t utf8_encode_unichar(char *out_utf8, uint32_t g);
-char *utf16_to_utf8(const void *s, size_t length);
+ size_t utf8_encode_unichar (char *out_utf8, uint32_t g);
+ char *utf16_to_utf8 (const void *s, size_t length);
-int utf8_encoded_valid_unichar(const char *str);
-int utf8_encoded_to_unichar(const char *str);
+ int utf8_encoded_valid_unichar (const char *str);
+ int utf8_encoded_to_unichar (const char *str);
-static inline bool utf16_is_surrogate(uint16_t c) {
- return (0xd800 <= c && c <= 0xdfff);
+ static inline bool utf16_is_surrogate (uint16_t c)
+{
+ return (0xd800 <= c && c <= 0xdfff);
}
-static inline bool utf16_is_trailing_surrogate(uint16_t c) {
- return (0xdc00 <= c && c <= 0xdfff);
+static inline bool
+utf16_is_trailing_surrogate (uint16_t c)
+{
+ return (0xdc00 <= c && c <= 0xdfff);
}
-static inline uint32_t utf16_surrogate_pair_to_unichar(uint16_t lead, uint16_t trail) {
- return ((lead - 0xd800) << 10) + (trail - 0xdc00) + 0x10000;
+static inline uint32_t
+utf16_surrogate_pair_to_unichar (uint16_t lead, uint16_t trail)
+{
+ return ((lead - 0xd800) << 10) + (trail - 0xdc00) + 0x10000;
}
-#endif
\ No newline at end of file
+#endif
diff --git a/libudev-compat/util.c b/libudev-compat/util.c
index 0fb1f69..ce69ff7 100644
--- a/libudev-compat/util.c
+++ b/libudev-compat/util.c
@@ -79,367 +79,417 @@
#include
#undef basename
-usec_t now(clockid_t clock_id) {
- struct timespec ts;
+usec_t
+now (clockid_t clock_id)
+{
+ struct timespec ts;
- assert_se(clock_gettime(clock_id, &ts) == 0);
+ assert_se (clock_gettime (clock_id, &ts) == 0);
- return timespec_load(&ts);
+ return timespec_load (&ts);
}
-struct timespec *timespec_store(struct timespec *ts, usec_t u) {
- assert(ts);
+struct timespec *
+timespec_store (struct timespec *ts, usec_t u)
+{
+ assert (ts);
- if (u == USEC_INFINITY) {
- ts->tv_sec = (time_t) -1;
- ts->tv_nsec = (long) -1;
- return ts;
- }
+ if (u == USEC_INFINITY)
+ {
+ ts->tv_sec = (time_t) - 1;
+ ts->tv_nsec = (long) -1;
+ return ts;
+ }
- ts->tv_sec = (time_t) (u / USEC_PER_SEC);
- ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
+ ts->tv_sec = (time_t) (u / USEC_PER_SEC);
+ ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
- return ts;
+ return ts;
}
-usec_t timespec_load(const struct timespec *ts) {
- assert(ts);
+usec_t
+timespec_load (const struct timespec * ts)
+{
+ assert (ts);
- if (ts->tv_sec == (time_t) -1 &&
- ts->tv_nsec == (long) -1)
- return USEC_INFINITY;
+ if (ts->tv_sec == (time_t) - 1 && ts->tv_nsec == (long) -1)
+ return USEC_INFINITY;
- if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC)
- return USEC_INFINITY;
+ if ((usec_t) ts->tv_sec >
+ (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC)
+ return USEC_INFINITY;
- return
- (usec_t) ts->tv_sec * USEC_PER_SEC +
- (usec_t) ts->tv_nsec / NSEC_PER_USEC;
+ return
+ (usec_t) ts->tv_sec * USEC_PER_SEC + (usec_t) ts->tv_nsec / NSEC_PER_USEC;
}
-char* dirname_malloc(const char *path) {
- char *d, *dir, *dir2;
-
- d = strdup(path);
- if (!d)
- return NULL;
- dir = dirname(d);
- assert(dir);
-
- if (dir != d) {
- dir2 = strdup(dir);
- free(d);
- return dir2;
- }
-
- return dir;
+char *
+dirname_malloc (const char *path)
+{
+ char *d, *dir, *dir2;
+
+ d = strdup (path);
+ if (!d)
+ return NULL;
+ dir = dirname (d);
+ assert (dir);
+
+ if (dir != d)
+ {
+ dir2 = strdup (dir);
+ free (d);
+ return dir2;
+ }
+
+ return dir;
}
-char hexchar(int x) {
- static const char table[16] = "0123456789abcdef";
+char
+hexchar (int x)
+{
+ static const char table[16] = "0123456789abcdef";
- return table[x & 15];
+ return table[x & 15];
}
-int unhexchar(char c) {
+int
+unhexchar (char c)
+{
- if (c >= '0' && c <= '9')
- return c - '0';
+ if (c >= '0' && c <= '9')
+ return c - '0';
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
- if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
- return -EINVAL;
+ return -EINVAL;
}
-int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
- assert(path);
+int
+chmod_and_chown (const char *path, mode_t mode, uid_t uid, gid_t gid)
+{
+ assert (path);
- /* Under the assumption that we are running privileged we
- * first change the access mode and only then hand out
- * ownership to avoid a window where access is too open. */
+ /* Under the assumption that we are running privileged we
+ * first change the access mode and only then hand out
+ * ownership to avoid a window where access is too open. */
- if (mode != MODE_INVALID)
- if (chmod(path, mode) < 0)
- return -errno;
+ if (mode != MODE_INVALID)
+ if (chmod (path, mode) < 0)
+ return -errno;
- if (uid != UID_INVALID || gid != GID_INVALID)
- if (chown(path, uid, gid) < 0)
- return -errno;
+ if (uid != UID_INVALID || gid != GID_INVALID)
+ if (chown (path, uid, gid) < 0)
+ return -errno;
- return 0;
+ return 0;
}
-int is_dir(const char* path, bool follow) {
- struct stat st;
- int r;
+int
+is_dir (const char *path, bool follow)
+{
+ struct stat st;
+ int r;
- if (follow)
- r = stat(path, &st);
- else
- r = lstat(path, &st);
- if (r < 0)
- return -errno;
+ if (follow)
+ r = stat (path, &st);
+ else
+ r = lstat (path, &st);
+ if (r < 0)
+ return -errno;
- return !!S_ISDIR(st.st_mode);
+ return ! !S_ISDIR (st.st_mode);
}
-int close_nointr(int fd) {
- assert(fd >= 0);
-
- if (close(fd) >= 0)
- return 0;
-
- /*
- * Just ignore EINTR; a retry loop is the wrong thing to do on
- * Linux.
- *
- * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
- * https://bugzilla.gnome.org/show_bug.cgi?id=682819
- * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
- * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
- */
- if (errno == EINTR)
- return 0;
-
- return -errno;
+int
+close_nointr (int fd)
+{
+ assert (fd >= 0);
+
+ if (close (fd) >= 0)
+ return 0;
+
+ /*
+ * Just ignore EINTR; a retry loop is the wrong thing to do on
+ * Linux.
+ *
+ * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
+ * https://bugzilla.gnome.org/show_bug.cgi?id=682819
+ * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
+ * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
+ */
+ if (errno == EINTR)
+ return 0;
+
+ return -errno;
}
-int flush_fd(int fd) {
- struct pollfd pollfd = {
- .fd = fd,
- .events = POLLIN,
- };
-
- for (;;) {
- char buf[LINE_MAX];
- ssize_t l;
- int r;
-
- r = poll(&pollfd, 1, 0);
- if (r < 0) {
- if (errno == EINTR)
- continue;
-
- return -errno;
-
- } else if (r == 0)
- return 0;
-
- l = read(fd, buf, sizeof(buf));
- if (l < 0) {
-
- if (errno == EINTR)
- continue;
-
- if (errno == EAGAIN)
- return 0;
-
- return -errno;
- } else if (l == 0)
- return 0;
- }
+int
+flush_fd (int fd)
+{
+ struct pollfd pollfd = {
+ .fd = fd,
+ .events = POLLIN,
+ };
+
+ for (;;)
+ {
+ char buf[LINE_MAX];
+ ssize_t l;
+ int r;
+
+ r = poll (&pollfd, 1, 0);
+ if (r < 0)
+ {
+ if (errno == EINTR)
+ continue;
+
+ return -errno;
+
+ }
+ else if (r == 0)
+ return 0;
+
+ l = read (fd, buf, sizeof (buf));
+ if (l < 0)
+ {
+
+ if (errno == EINTR)
+ continue;
+
+ if (errno == EAGAIN)
+ return 0;
+
+ return -errno;
+ }
+ else if (l == 0)
+ return 0;
+ }
}
+int
+safe_close (int fd)
+{
-int safe_close(int fd) {
+ /*
+ * Like close_nointr() but cannot fail. Guarantees errno is
+ * unchanged. Is a NOP with negative fds passed, and returns
+ * -1, so that it can be used in this syntax:
+ *
+ * fd = safe_close(fd);
+ */
- /*
- * Like close_nointr() but cannot fail. Guarantees errno is
- * unchanged. Is a NOP with negative fds passed, and returns
- * -1, so that it can be used in this syntax:
- *
- * fd = safe_close(fd);
- */
+ if (fd >= 0)
+ {
+ int errsv = errno;
- if (fd >= 0) {
- int errsv = errno;
+ /* The kernel might return pretty much any error code
+ * via close(), but the fd will be closed anyway. The
+ * only condition we want to check for here is whether
+ * the fd was invalid at all... */
- /* The kernel might return pretty much any error code
- * via close(), but the fd will be closed anyway. The
- * only condition we want to check for here is whether
- * the fd was invalid at all... */
+ assert_se (close_nointr (fd) != -EBADF);
- assert_se(close_nointr(fd) != -EBADF);
-
- errno = errsv;
- }
+ errno = errsv;
+ }
- return -1;
+ return -1;
}
+int
+fd_wait_for_event (int fd, int event, usec_t t)
+{
-int fd_wait_for_event(int fd, int event, usec_t t) {
-
- struct pollfd pollfd = {
- .fd = fd,
- .events = event,
- };
+ struct pollfd pollfd = {
+ .fd = fd,
+ .events = event,
+ };
- struct timespec ts;
- int r;
+ struct timespec ts;
+ int r;
- r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
- if (r < 0)
- return -errno;
+ r = ppoll (&pollfd, 1,
+ t == USEC_INFINITY ? NULL : timespec_store (&ts, t), NULL);
+ if (r < 0)
+ return -errno;
- if (r == 0)
- return 0;
+ if (r == 0)
+ return 0;
- return pollfd.revents;
+ return pollfd.revents;
}
-ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
- uint8_t *p = buf;
- ssize_t n = 0;
+ssize_t
+loop_read (int fd, void *buf, size_t nbytes, bool do_poll)
+{
+ uint8_t *p = buf;
+ ssize_t n = 0;
- assert(fd >= 0);
- assert(buf);
+ assert (fd >= 0);
+ assert (buf);
- while (nbytes > 0) {
- ssize_t k;
+ while (nbytes > 0)
+ {
+ ssize_t k;
- k = read(fd, p, nbytes);
- if (k < 0) {
- if (errno == EINTR)
- continue;
+ k = read (fd, p, nbytes);
+ if (k < 0)
+ {
+ if (errno == EINTR)
+ continue;
- if (errno == EAGAIN && do_poll) {
+ if (errno == EAGAIN && do_poll)
+ {
- /* We knowingly ignore any return value here,
- * and expect that any error/EOF is reported
- * via read() */
+ /* We knowingly ignore any return value here,
+ * and expect that any error/EOF is reported
+ * via read() */
- fd_wait_for_event(fd, POLLIN, USEC_INFINITY);
- continue;
- }
+ fd_wait_for_event (fd, POLLIN, USEC_INFINITY);
+ continue;
+ }
- return n > 0 ? n : -errno;
- }
+ return n > 0 ? n : -errno;
+ }
- if (k == 0)
- return n;
+ if (k == 0)
+ return n;
- p += k;
- nbytes -= k;
- n += k;
- }
+ p += k;
+ nbytes -= k;
+ n += k;
+ }
- return n;
+ return n;
}
-int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) {
- ssize_t n;
-
- n = loop_read(fd, buf, nbytes, do_poll);
- if (n < 0)
- return n;
- if ((size_t) n != nbytes)
- return -EIO;
- return 0;
+int
+loop_read_exact (int fd, void *buf, size_t nbytes, bool do_poll)
+{
+ ssize_t n;
+
+ n = loop_read (fd, buf, nbytes, do_poll);
+ if (n < 0)
+ return n;
+ if ((size_t) n != nbytes)
+ return -EIO;
+ return 0;
}
-
// get task ID (no glibc wrapper around this...)
-pid_t gettid(void) {
- return syscall( __NR_gettid );
+pid_t
+gettid (void)
+{
+ return syscall (__NR_gettid);
}
-int dev_urandom(void *p, size_t n) {
- static int have_syscall = -1;
-
- int fd = -1;
- int r;
-
- /* Gathers some randomness from the kernel. This call will
- * never block, and will always return some data from the
- * kernel, regardless if the random pool is fully initialized
- * or not. It thus makes no guarantee for the quality of the
- * returned entropy, but is good enough for or usual usecases
- * of seeding the hash functions for hashtable */
-
- fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0) {
- return errno == ENOENT ? -ENOSYS : -errno;
- }
-
- int rc = loop_read_exact(fd, p, n, true);
- close( fd );
- return rc;
+int
+dev_urandom (void *p, size_t n)
+{
+ static int have_syscall = -1;
+
+ int fd = -1;
+ int r;
+
+ /* Gathers some randomness from the kernel. This call will
+ * never block, and will always return some data from the
+ * kernel, regardless if the random pool is fully initialized
+ * or not. It thus makes no guarantee for the quality of the
+ * returned entropy, but is good enough for or usual usecases
+ * of seeding the hash functions for hashtable */
+
+ fd = open ("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOCTTY);
+ if (fd < 0)
+ {
+ return errno == ENOENT ? -ENOSYS : -errno;
+ }
+
+ int rc = loop_read_exact (fd, p, n, true);
+ close (fd);
+ return rc;
}
-void initialize_srand(void) {
- static bool srand_called = false;
- unsigned x;
+void
+initialize_srand (void)
+{
+ static bool srand_called = false;
+ unsigned x;
#ifdef HAVE_SYS_AUXV_H
- void *auxv;
+ void *auxv;
#endif
- if (srand_called)
- return;
+ if (srand_called)
+ return;
- x = 0;
+ x = 0;
#ifdef HAVE_SYS_AUXV_H
- /* The kernel provides us with a bit of entropy in auxv, so
- * let's try to make use of that to seed the pseudo-random
- * generator. It's better than nothing... */
+ /* The kernel provides us with a bit of entropy in auxv, so
+ * let's try to make use of that to seed the pseudo-random
+ * generator. It's better than nothing... */
- auxv = (void*) getauxval(AT_RANDOM);
- if (auxv)
- x ^= *(unsigned*) auxv;
+ auxv = (void *) getauxval (AT_RANDOM);
+ if (auxv)
+ x ^= *(unsigned *) auxv;
#endif
- x ^= (unsigned) now(CLOCK_REALTIME);
- x ^= (unsigned) gettid();
+ x ^= (unsigned) now (CLOCK_REALTIME);
+ x ^= (unsigned) gettid ();
- srand(x);
- srand_called = true;
+ srand (x);
+ srand_called = true;
}
-void random_bytes(void *p, size_t n) {
- uint8_t *q;
- int r;
+void
+random_bytes (void *p, size_t n)
+{
+ uint8_t *q;
+ int r;
- r = dev_urandom(p, n);
- if (r >= 0)
- return;
+ r = dev_urandom (p, n);
+ if (r >= 0)
+ return;
- /* If some idiot made /dev/urandom unavailable to us, he'll
- * get a PRNG instead. */
+ /* If some idiot made /dev/urandom unavailable to us, he'll
+ * get a PRNG instead. */
- initialize_srand();
+ initialize_srand ();
- for (q = p; q < (uint8_t*) p + n; q ++)
- *q = rand();
+ for (q = p; q < (uint8_t *) p + n; q++)
+ *q = rand ();
}
-bool is_main_thread(void) {
-
- return (getpid() == gettid());
-}
+bool
+is_main_thread (void)
+{
-size_t page_size(void) {
-
- int r = sysconf(_SC_PAGESIZE);
- assert(r > 0);
-
- return r;
+ return (getpid () == gettid ());
}
+size_t
+page_size (void)
+{
-bool streq_ptr(const char *a, const char *b) {
+ int r = sysconf (_SC_PAGESIZE);
+ assert (r > 0);
- /* Like streq(), but tries to make sense of NULL pointers */
+ return r;
+}
+
+bool
+streq_ptr (const char *a, const char *b)
+{
- if (a && b)
- return streq(a, b);
+ /* Like streq(), but tries to make sense of NULL pointers */
- if (!a && !b)
- return true;
+ if (a && b)
+ return streq (a, b);
- return false;
-}
\ No newline at end of file
+ if (!a && !b)
+ return true;
+
+ return false;
+}
diff --git a/libudev-compat/util.h b/libudev-compat/util.h
index 1a3ba1d..1208306 100644
--- a/libudev-compat/util.h
+++ b/libudev-compat/util.h
@@ -56,7 +56,7 @@
#include
#include
#include
-#include // for gettid()
+#include // for gettid()
#include "log.h"
@@ -83,7 +83,7 @@
#define streq(a,b) (strcmp((a),(b)) == 0)
-bool streq_ptr(const char *a, const char *b);
+bool streq_ptr (const char *a, const char *b);
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
@@ -136,9 +136,10 @@ struct file_handle
};
#endif
-union file_handle_union {
- struct file_handle handle;
- char padding[sizeof(struct file_handle) + MAX_HANDLE_SZ];
+union file_handle_union
+{
+ struct file_handle handle;
+ char padding[sizeof (struct file_handle) + MAX_HANDLE_SZ];
};
#define FILE_HANDLE_INIT { .handle.handle_bytes = MAX_HANDLE_SZ }
@@ -150,20 +151,24 @@ union file_handle_union {
} \
break; \
} else
-
-static inline size_t ALIGN_TO(size_t l, size_t ali) {
- return ((l + ali - 1) & ~(ali - 1));
+static inline size_t
+ALIGN_TO (size_t l, size_t ali)
+{
+ return ((l + ali - 1) & ~(ali - 1));
}
-size_t page_size(void) _pure_;
+size_t
+page_size (void)
+ _pure_;
#define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
-
+
////////// reference counting
-typedef struct {
- volatile unsigned _value;
-} RefCount;
+ typedef struct
+ {
+ volatile unsigned _value;
+ } RefCount;
#define REFCNT_GET(r) ((r)._value)
#define REFCNT_INC(r) (__sync_add_and_fetch(&(r)._value, 1))
@@ -173,8 +178,8 @@ typedef struct {
////////// time functions
-typedef uint64_t usec_t;
-typedef uint64_t nsec_t;
+ typedef uint64_t usec_t;
+ typedef uint64_t nsec_t;
#define NSEC_FMT "%" PRIu64
#define USEC_FMT "%" PRIu64
@@ -189,20 +194,21 @@ typedef uint64_t nsec_t;
#define NSEC_PER_MSEC ((nsec_t) 1000000ULL)
#define NSEC_PER_USEC ((nsec_t) 1000ULL)
-usec_t now(clockid_t clock);
-usec_t timespec_load(const struct timespec *ts);
-struct timespec *timespec_store(struct timespec *ts, usec_t u);
+ usec_t now (clockid_t clock);
+ usec_t timespec_load (const struct timespec *ts);
+ struct timespec *timespec_store (struct timespec *ts, usec_t u);
////////// string functions
-static inline char *startswith(const char *s, const char *prefix) {
- size_t l;
+ static inline char *startswith (const char *s, const char *prefix)
+{
+ size_t l;
- l = strlen(prefix);
- if (strncmp(s, prefix, l) == 0)
- return (char*) s + l;
+ l = strlen (prefix);
+ if (strncmp (s, prefix, l) == 0)
+ return (char *) s + l;
- return NULL;
+ return NULL;
}
#define strjoina(a, ...) \
@@ -230,17 +236,18 @@ static inline char *startswith(const char *s, const char *prefix) {
sizeof(type) <= 4 ? 10 : \
sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)])))
-char* dirname_malloc(const char *path);
-char hexchar(int x) _const_;
-int unhexchar(char c) _const_;
+char *dirname_malloc (const char *path);
+char
+hexchar (int x)
+ _const_;
+ int unhexchar (char c) _const_;
#define NULSTR_FOREACH(i, l) \
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
#define STRV_FOREACH(s, l) \
for ((s) = (l); (s) && *(s); (s)++)
-
-
+
//////////// memory functions
#define _cleanup_(x) __attribute__((cleanup(x)))
@@ -252,11 +259,10 @@ int unhexchar(char c) _const_;
} \
struct __useless_struct_to_allow_trailing_semicolon__
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, fclose);
-DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, pclose);
-DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
-DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent);
+DEFINE_TRIVIAL_CLEANUP_FUNC (FILE *, fclose);
+DEFINE_TRIVIAL_CLEANUP_FUNC (FILE *, pclose);
+DEFINE_TRIVIAL_CLEANUP_FUNC (DIR *, closedir);
+DEFINE_TRIVIAL_CLEANUP_FUNC (FILE *, endmntent);
#define _cleanup_free_ _cleanup_(freep)
#define _cleanup_close_ _cleanup_(closep)
@@ -268,21 +274,24 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent);
#define _cleanup_endmntent_ _cleanup_(endmntentp)
#define _cleanup_close_pair_ _cleanup_(close_pairp)
-_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) {
- if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
- return NULL;
+ _malloc_ _alloc_ (1, 2)
+ static inline void *malloc_multiply (size_t a, size_t b)
+{
+ if (_unlikely_ (b != 0 && a > ((size_t) - 1) / b))
+ return NULL;
- return malloc(a * b);
+ return malloc (a * b);
}
-_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b) {
- if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
- return NULL;
+_alloc_ (2, 3)
+ static inline void *realloc_multiply (void *p, size_t a, size_t b)
+{
+ if (_unlikely_ (b != 0 && a > ((size_t) - 1) / b))
+ return NULL;
- return realloc(p, a * b);
+ return realloc (p, a * b);
}
-
////////// sanity checks
#define assert_return(expr, r) \
@@ -293,21 +302,19 @@ _alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b)
} \
} while (false)
-
#define assert_se(expr) \
do { \
if (_unlikely_(!(expr))) \
log_error("Assertion failure: '%s'", #expr); \
- } while (false)
-
-
+ } while (false)
+
#define DISABLE_WARNING_DECLARATION_AFTER_STATEMENT \
_Pragma("GCC diagnostic push"); \
_Pragma("GCC diagnostic ignored \"-Wdeclaration-after-statement\"")
-
+
#define REENABLE_WARNING \
_Pragma("GCC diagnostic pop")
-
+
#if defined(static_assert)
/* static_assert() is sometimes defined in a way that trips up
* -Wdeclaration-after-statement, hence let's temporarily turn off
@@ -329,7 +336,7 @@ _alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b)
do { \
log_error("Not reached: %s", t); \
} while (false)
-
+
////////// type functions
#define MIN( a, b ) ((a) < (b) ? (a) : (b))
@@ -350,50 +357,58 @@ _alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b)
///////// misc inline functions
-
/**
* Normal qsort requires base to be nonnull. Here were require
* that only if nmemb > 0.
*/
-static inline void qsort_safe(void *base, size_t nmemb, size_t size,
- int (*compar)(const void *, const void *)) {
- if (nmemb) {
- assert(base);
- qsort(base, nmemb, size, compar);
- }
+static inline void
+qsort_safe (void *base, size_t nmemb, size_t size,
+ int (*compar) (const void *, const void *))
+{
+ if (nmemb)
+ {
+ assert (base);
+ qsort (base, nmemb, size, compar);
+ }
}
-static inline void *mempset(void *s, int c, size_t n) {
- memset(s, c, n);
- return (uint8_t*)s + n;
+static inline void *
+mempset (void *s, int c, size_t n)
+{
+ memset (s, c, n);
+ return (uint8_t *) s + n;
}
-static inline unsigned log2u(unsigned x) {
- assert(x > 0);
+static inline unsigned
+log2u (unsigned x)
+{
+ assert (x > 0);
- return sizeof(unsigned) * 8 - __builtin_clz(x) - 1;
+ return sizeof (unsigned) * 8 - __builtin_clz (x) - 1;
}
-static inline unsigned log2u_round_up(unsigned x) {
- assert(x > 0);
+static inline unsigned
+log2u_round_up (unsigned x)
+{
+ assert (x > 0);
- if (x == 1)
- return 0;
+ if (x == 1)
+ return 0;
- return log2u(x - 1) + 1;
+ return log2u (x - 1) + 1;
}
///////// misc functions
-int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
-int is_dir(const char *path, bool follow);
-int close_nointr(int fd);
-int flush_fd(int fd);
-int safe_close(int fd);
+int chmod_and_chown (const char *path, mode_t mode, uid_t uid, gid_t gid);
+int is_dir (const char *path, bool follow);
+int close_nointr (int fd);
+int flush_fd (int fd);
+int safe_close (int fd);
-int dev_urandom(void *p, size_t n);
-void initialize_srand(void);
-void random_bytes(void *p, size_t n);
+int dev_urandom (void *p, size_t n);
+void initialize_srand (void);
+void random_bytes (void *p, size_t n);
-bool is_main_thread(void);
+bool is_main_thread (void);
#endif
diff --git a/libvdev/config.c b/libvdev/config.c
index fa7a84a..c1fb7f9 100644
--- a/libvdev/config.c
+++ b/libvdev/config.c
@@ -27,441 +27,527 @@
#include "ini.h"
// FUSE reserved options
-static const char* FUSE_OPT_S = "-s";
-static const char* FUSE_OPT_O = "-o";
-static const char* FUSE_OPT_D = "-d";
-static const char* FUSE_OPT_F = "-f";
+static const char *FUSE_OPT_S = "-s";
+static const char *FUSE_OPT_O = "-o";
+static const char *FUSE_OPT_D = "-d";
+static const char *FUSE_OPT_F = "-f";
// ini parser callback
// return 1 on parsed (WARNING: masks OOM)
// return 0 on not parsed
-static int vdev_config_ini_parser( void* userdata, char const* section, char const* name, char const* value ) {
-
- struct vdev_config* conf = (struct vdev_config*)userdata;
- bool success = false;
- int rc = 0;
-
- if( strcmp( section, VDEV_CONFIG_NAME ) == 0 ) {
-
- if( strcmp( name, VDEV_CONFIG_ACLS ) == 0 ) {
-
- if( conf->acls_dir == NULL ) {
- // save this
- conf->acls_dir = vdev_strdup_or_null( value );
- }
- return 1;
- }
-
- if( strcmp( name, VDEV_CONFIG_ACTIONS ) == 0 ) {
-
- if( conf->acts_dir == NULL ) {
- // save this
- conf->acts_dir = vdev_strdup_or_null( value );
- }
-
- return 1;
- }
-
- if( strcmp( name, VDEV_CONFIG_HELPERS ) == 0 ) {
-
- if( conf->helpers_dir == NULL ) {
- // save this
- conf->helpers_dir = vdev_strdup_or_null( value );
- }
-
- return 1;
- }
-
- if( strcmp( name, VDEV_CONFIG_DEFAULT_MODE ) == 0 ) {
-
- char* tmp = NULL;
- conf->default_mode = (mode_t)strtoul( value, &tmp, 8 );
-
- if( *tmp != '\0' ) {
-
- fprintf(stderr, "Invalid value '%s' for '%s'\n", value, name );
- return 0;
- }
- else {
-
- return 1;
- }
- }
-
- if( strcmp( name, VDEV_CONFIG_DEFAULT_POLICY ) == 0 ) {
-
- conf->default_policy = strcasecmp( value, "allow" ) ? 1 : 0;
- return 1;
- }
-
- if( strcmp( name, VDEV_CONFIG_PIDFILE_PATH ) == 0 ) {
-
- if( conf->pidfile_path == NULL ) {
- conf->pidfile_path = vdev_strdup_or_null( value );
- }
-
- return 1;
- }
-
- if( strcmp( name, VDEV_CONFIG_LOGFILE_PATH ) == 0 ) {
-
- if( conf->logfile_path == NULL ) {
- conf->logfile_path = vdev_strdup_or_null( value );
- }
-
- return 1;
- }
-
- if( strcmp( name, VDEV_CONFIG_LOG_LEVEL ) == 0 ) {
-
- if( strcasecmp( value, "debug" ) == 0 ) {
-
- conf->debug_level = VDEV_LOGLEVEL_DEBUG;
- conf->error_level = VDEV_LOGLEVEL_WARN;
- }
- else if( strcasecmp( value, "info" ) == 0 ) {
-
- conf->debug_level = VDEV_LOGLEVEL_INFO;
- conf->error_level = VDEV_LOGLEVEL_WARN;
- }
- else if( strcasecmp( value, "warn" ) == 0 || strcasecmp( value, "warning" ) == 0 ) {
-
- conf->debug_level = VDEV_LOGLEVEL_NONE;
- conf->error_level = VDEV_LOGLEVEL_WARN;
- }
- else if( strcasecmp( value, "error" ) == 0 || strcasecmp( value, "critical" ) == 0 ) {
-
- conf->debug_level = VDEV_LOGLEVEL_NONE;
- conf->error_level = VDEV_LOGLEVEL_ERROR;
- }
- else {
-
- fprintf(stderr, "Unrecognized value '%s' for '%s'\n", value, name );
- return 0;
- }
-
- return 1;
- }
-
- if( strcmp( name, VDEV_CONFIG_MOUNTPOINT ) == 0 ) {
-
- if( conf->mountpoint == NULL ) {
- conf->mountpoint = vdev_strdup_or_null( value );
- }
-
- return 1;
- }
-
- if( strcmp( name, VDEV_CONFIG_COLDPLUG_ONLY ) == 0 ) {
-
- if( strcasecmp( name, "true" ) == 0 ) {
-
- conf->coldplug_only = true;
- }
- else if( strcasecmp( name, "false" ) == 0 ) {
-
- conf->coldplug_only = false;
- }
- else if( !conf->coldplug_only ) {
-
- // maybe it's 0 or non-zero?
- conf->coldplug_only = (bool)vdev_parse_uint64( value, &success );
- if( !success ) {
-
- fprintf(stderr, "Invalid value '%s' for '%s'\n", value, name );
- return 0;
- }
- else {
-
- return 1;
- }
- }
- }
-
- if( strcmp( name, VDEV_CONFIG_PRESEED ) == 0 ) {
-
- if( conf->preseed_path == NULL ) {
-
- conf->preseed_path = vdev_strdup_or_null( value );
- }
-
- return 1;
- }
-
+static int
+vdev_config_ini_parser (void *userdata, char const *section,
+ char const *name, char const *value)
+{
+
+ struct vdev_config *conf = (struct vdev_config *) userdata;
+ bool success = false;
+ int rc = 0;
+
+ if (strcmp (section, VDEV_CONFIG_NAME) == 0)
+ {
+
+ if (strcmp (name, VDEV_CONFIG_ACLS) == 0)
+ {
+
+ if (conf->acls_dir == NULL)
+ {
+ // save this
+ conf->acls_dir = vdev_strdup_or_null (value);
+ }
+ return 1;
+ }
+
+ if (strcmp (name, VDEV_CONFIG_ACTIONS) == 0)
+ {
+
+ if (conf->acts_dir == NULL)
+ {
+ // save this
+ conf->acts_dir = vdev_strdup_or_null (value);
+ }
+
+ return 1;
+ }
+
+ if (strcmp (name, VDEV_CONFIG_HELPERS) == 0)
+ {
+
+ if (conf->helpers_dir == NULL)
+ {
+ // save this
+ conf->helpers_dir = vdev_strdup_or_null (value);
+ }
+
+ return 1;
+ }
+
+ if (strcmp (name, VDEV_CONFIG_DEFAULT_MODE) == 0)
+ {
+
+ char *tmp = NULL;
+ conf->default_mode = (mode_t) strtoul (value, &tmp, 8);
+
+ if (*tmp != '\0')
+ {
+
+ fprintf (stderr, "Invalid value '%s' for '%s'\n", value, name);
+ return 0;
+ }
+ else
+ {
+
+ return 1;
+ }
+ }
+
+ if (strcmp (name, VDEV_CONFIG_DEFAULT_POLICY) == 0)
+ {
+
+ conf->default_policy = strcasecmp (value, "allow") ? 1 : 0;
+ return 1;
+ }
+
+ if (strcmp (name, VDEV_CONFIG_PIDFILE_PATH) == 0)
+ {
+
+ if (conf->pidfile_path == NULL)
+ {
+ conf->pidfile_path = vdev_strdup_or_null (value);
+ }
+
+ return 1;
+ }
+
+ if (strcmp (name, VDEV_CONFIG_LOGFILE_PATH) == 0)
+ {
+
+ if (conf->logfile_path == NULL)
+ {
+ conf->logfile_path = vdev_strdup_or_null (value);
+ }
+
+ return 1;
+ }
+
+ if (strcmp (name, VDEV_CONFIG_LOG_LEVEL) == 0)
+ {
+
+ if (strcasecmp (value, "debug") == 0)
+ {
+
+ conf->debug_level = VDEV_LOGLEVEL_DEBUG;
+ conf->error_level = VDEV_LOGLEVEL_WARN;
+ }
+ else if (strcasecmp (value, "info") == 0)
+ {
+
+ conf->debug_level = VDEV_LOGLEVEL_INFO;
+ conf->error_level = VDEV_LOGLEVEL_WARN;
+ }
+ else if (strcasecmp (value, "warn") == 0
+ || strcasecmp (value, "warning") == 0)
+ {
+
+ conf->debug_level = VDEV_LOGLEVEL_NONE;
+ conf->error_level = VDEV_LOGLEVEL_WARN;
+ }
+ else if (strcasecmp (value, "error") == 0
+ || strcasecmp (value, "critical") == 0)
+ {
+
+ conf->debug_level = VDEV_LOGLEVEL_NONE;
+ conf->error_level = VDEV_LOGLEVEL_ERROR;
+ }
+ else
+ {
+ // warn about unknown option value
+ // fallover to debug and warn
+ fprintf (stderr,
+ "Unrecognized value '%s' for '%s'\n", value, name);
+ conf->debug_level = VDEV_LOGLEVEL_DEBUG;
+ conf->error_level = VDEV_LOGLEVEL_WARN;
+ // return 0;
+ }
+
+ return 1;
+ }
+
+ if (strcmp (name, VDEV_CONFIG_MOUNTPOINT) == 0)
+ {
+
+ if (conf->mountpoint == NULL)
+ {
+ conf->mountpoint = vdev_strdup_or_null (value);
+ }
+
+ return 1;
+ }
+
+ if (strcmp (name, VDEV_CONFIG_COLDPLUG_ONLY) == 0)
+ {
+
+ if (strcasecmp (name, "true") == 0)
+ {
+
+ conf->coldplug_only = true;
+ }
+ else if (strcasecmp (name, "false") == 0)
+ {
+
+ conf->coldplug_only = false;
+ }
+ else if (!conf->coldplug_only)
+ {
+
+ // maybe it's 0 or non-zero?
+ conf->coldplug_only =
+ (bool) vdev_parse_uint64 (value, &success);
+ if (!success)
+ {
+
+ fprintf (stderr,
+ "Invalid value '%s' for '%s'\n", value, name);
+ return 0;
+ }
+ else
+ {
+
+ return 1;
+ }
+ }
+ }
+
+ if (strcmp (name, VDEV_CONFIG_PRESEED) == 0)
+ {
+
+ if (conf->preseed_path == NULL)
+ {
+
+ conf->preseed_path = vdev_strdup_or_null (value);
+ }
+
+ return 1;
+ }
+
return 1;
- }
-
- if( strcmp( section, VDEV_OS_CONFIG_NAME ) == 0 ) {
-
+ }
+
+ if (strcmp (section, VDEV_OS_CONFIG_NAME) == 0)
+ {
+
// OS-specific config value
- rc = vdev_params_add( &conf->os_config, name, value );
- if( rc != 0 ) {
-
- return 0;
- }
+ rc = vdev_params_add (&conf->os_config, name, value);
+ if (rc != 0)
+ {
+
+ return 0;
+ }
return 1;
- }
-
- fprintf(stderr, "Unrecognized field '%s'\n", name);
- return 1;
-}
+ }
+ fprintf (stderr, "Unrecognized field '%s'\n", name);
+ return 1;
+}
// config sanity check
-int vdev_config_sanity_check( struct vdev_config* conf ) {
-
- int rc = 0;
-
- if( conf->acls_dir == NULL ) {
-
- fprintf(stderr, "[ERROR]: missing acls\n");
+int
+vdev_config_sanity_check (struct vdev_config *conf)
+{
+
+ int rc = 0;
+
+ if (conf->acls_dir == NULL)
+ {
+
+ fprintf (stderr, "[ERROR]: missing acls\n");
rc = -EINVAL;
- }
-
- if( conf->acts_dir == NULL ) {
-
- fprintf(stderr, "[ERROR]: missing actions\n");
+ }
+
+ if (conf->acts_dir == NULL)
+ {
+
+ fprintf (stderr, "[ERROR]: missing actions\n");
rc = -EINVAL;
- }
-
- if( conf->mountpoint == NULL ) {
-
- fprintf(stderr, "[ERROR]: missing mountpoint\n");
+ }
+
+ if (conf->mountpoint == NULL)
+ {
+
+ fprintf (stderr, "[ERROR]: missing mountpoint\n");
rc = -EINVAL;
- }
-
- return rc;
-}
+ }
+ return rc;
+}
// convert a number between 0 and 16 to its hex representation
// hex must have at least 2 characters
// always succeeds
-void vdev_bin_to_hex( unsigned char num, char* hex ) {
-
- unsigned char upper = num >> 4;
- unsigned char lower = num & 0xf;
-
- if( upper < 10 ) {
+void
+vdev_bin_to_hex (unsigned char num, char *hex)
+{
+
+ unsigned char upper = num >> 4;
+ unsigned char lower = num & 0xf;
+
+ if (upper < 10)
+ {
hex[0] = upper + '0';
- }
- else {
+ }
+ else
+ {
hex[0] = upper + 'A';
- }
-
- if( lower < 10 ) {
+ }
+
+ if (lower < 10)
+ {
hex[1] = lower + '0';
- }
- else {
+ }
+ else
+ {
hex[1] = lower + 'A';
- }
+ }
}
// generate an instance nonce
// NOTE: not thread-safe, since it uses mrand48(3) (can't use /dev/urandom, since it doesn't exist yet)
// always succeeds
-static void vdev_config_make_instance_nonce( struct vdev_config* conf ) {
-
- char instance[VDEV_CONFIG_INSTANCE_NONCE_LEN];
-
- // generate an instance nonce
- for( int i = 0; i < VDEV_CONFIG_INSTANCE_NONCE_LEN; i++ ) {
-
- instance[i] = (char)mrand48();
- }
-
- memset( conf->instance_str, 0, VDEV_CONFIG_INSTANCE_NONCE_STRLEN );
-
- for( int i = 0; i < VDEV_CONFIG_INSTANCE_NONCE_LEN; i++ ) {
-
- vdev_bin_to_hex( (unsigned char)instance[i], &conf->instance_str[2*i] );
- }
+static void
+vdev_config_make_instance_nonce (struct vdev_config *conf)
+{
+
+ char instance[VDEV_CONFIG_INSTANCE_NONCE_LEN];
+
+ // generate an instance nonce
+ for (int i = 0; i < VDEV_CONFIG_INSTANCE_NONCE_LEN; i++)
+ {
+
+ instance[i] = (char) mrand48 ();
+ }
+
+ memset (conf->instance_str, 0, VDEV_CONFIG_INSTANCE_NONCE_STRLEN);
+
+ for (int i = 0; i < VDEV_CONFIG_INSTANCE_NONCE_LEN; i++)
+ {
+
+ vdev_bin_to_hex ((unsigned char) instance[i],
+ &conf->instance_str[2 * i]);
+ }
}
-
// initialize a config
// always succeeds
-int vdev_config_init( struct vdev_config* conf ) {
-
- memset( conf, 0, sizeof(struct vdev_config) );
- return 0;
+int
+vdev_config_init (struct vdev_config *conf)
+{
+
+ memset (conf, 0, sizeof (struct vdev_config));
+ return 0;
}
// load from a file, by path
// return on on success
// return -errno on failure to open
-int vdev_config_load( char const* path, struct vdev_config* conf ) {
-
- FILE* f = NULL;
- int rc = 0;
-
- f = fopen( path, "r" );
- if( f == NULL ) {
+int
+vdev_config_load (char const *path, struct vdev_config *conf)
+{
+
+ FILE *f = NULL;
+ int rc = 0;
+
+ f = fopen (path, "r");
+ if (f == NULL)
+ {
rc = -errno;
return rc;
- }
-
- rc = vdev_config_load_file( f, conf );
-
- fclose( f );
-
- if( rc == 0 ) {
-
- vdev_config_make_instance_nonce( conf );
- }
- return rc;
+ }
+
+ rc = vdev_config_load_file (f, conf);
+
+ fclose (f);
+
+ if (rc == 0)
+ {
+
+ vdev_config_make_instance_nonce (conf);
+ }
+ return rc;
}
// load from a file
// return 0 on success
// return -errno on failure to load
-int vdev_config_load_file( FILE* file, struct vdev_config* conf ) {
-
- int rc = 0;
-
- rc = ini_parse_file( file, vdev_config_ini_parser, conf );
- if( rc != 0 ) {
- vdev_error("ini_parse_file(config) rc = %d\n", rc );
- vdev_config_free( conf );
+int
+vdev_config_load_file (FILE * file, struct vdev_config *conf)
+{
- return rc;
- }
+ int rc = 0;
- // convert paths
- rc = vdev_config_fullpaths( conf );
- if( rc != 0 ) {
+ rc = ini_parse_file (file, vdev_config_ini_parser, conf);
+ if (rc != 0)
+ {
+ vdev_error ("ini_parse_file(config) rc = %d\n", rc);
+ vdev_config_free (conf);
- vdev_error("vdev_config_fullpaths: %s\n", strerror(-rc) );
- vdev_config_free( conf );
return rc;
- }
-
- return rc;
+ }
+ // convert paths
+ rc = vdev_config_fullpaths (conf);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_config_fullpaths: %s\n", strerror (-rc));
+ vdev_config_free (conf);
+ return rc;
+ }
+
+ return rc;
}
// free a config
// always succeeds
-int vdev_config_free( struct vdev_config* conf ) {
-
- if( conf->acls_dir != NULL ) {
-
- free( conf->acls_dir );
+int
+vdev_config_free (struct vdev_config *conf)
+{
+
+ if (conf->acls_dir != NULL)
+ {
+
+ free (conf->acls_dir);
conf->acls_dir = NULL;
- }
-
- if( conf->acts_dir != NULL ) {
-
- free( conf->acts_dir );
+ }
+
+ if (conf->acts_dir != NULL)
+ {
+
+ free (conf->acts_dir);
conf->acts_dir = NULL;
- }
-
- if( conf->os_config != NULL ) {
-
- vdev_params_free( conf->os_config );
+ }
+
+ if (conf->os_config != NULL)
+ {
+
+ vdev_params_free (conf->os_config);
conf->os_config = NULL;
- }
-
- if( conf->helpers_dir != NULL ) {
-
- free( conf->helpers_dir );
+ }
+
+ if (conf->helpers_dir != NULL)
+ {
+
+ free (conf->helpers_dir);
conf->helpers_dir = NULL;
- }
-
- if( conf->config_path != NULL ) {
-
- free( conf->config_path );
+ }
+
+ if (conf->config_path != NULL)
+ {
+
+ free (conf->config_path);
conf->config_path = NULL;
- }
-
- if( conf->mountpoint != NULL ) {
-
- free( conf->mountpoint );
+ }
+
+ if (conf->mountpoint != NULL)
+ {
+
+ free (conf->mountpoint);
conf->mountpoint = NULL;
- }
-
- if( conf->preseed_path != NULL ) {
-
- free( conf->preseed_path );
+ }
+
+ if (conf->preseed_path != NULL)
+ {
+
+ free (conf->preseed_path);
conf->preseed_path = NULL;
- }
-
- if( conf->logfile_path != NULL ) {
-
- free( conf->logfile_path );
+ }
+
+ if (conf->logfile_path != NULL)
+ {
+
+ free (conf->logfile_path);
conf->logfile_path = NULL;
- }
-
- if( conf->pidfile_path != NULL ) {
-
- free( conf->pidfile_path );
+ }
+
+ if (conf->pidfile_path != NULL)
+ {
+
+ free (conf->pidfile_path);
conf->pidfile_path = NULL;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// convert all paths in the config to absolute paths
// return 0 on success
// return -ENOMEM on OOM
// return -ERANGE if cwd is too long
-int vdev_config_fullpaths( struct vdev_config* conf ) {
-
- int rc = 0;
-
- char** need_fullpath[] = {
- &conf->config_path,
- &conf->acls_dir,
- &conf->acts_dir,
- &conf->helpers_dir,
- &conf->pidfile_path,
- &conf->logfile_path,
- &conf->preseed_path,
- NULL
- };
-
- char cwd_buf[ PATH_MAX + 1 ];
- memset( cwd_buf, 0, PATH_MAX + 1 );
-
- char* tmp = getcwd( cwd_buf, PATH_MAX );
- if( tmp == NULL ) {
-
- vdev_error("Current working directory exceeds %u bytes\n", PATH_MAX);
+int
+vdev_config_fullpaths (struct vdev_config *conf)
+{
+ // this int does not seem to be used here
+ // int rc = 0;
+
+ char **need_fullpath[] = {
+ &conf->config_path,
+ &conf->acls_dir,
+ &conf->acts_dir,
+ &conf->helpers_dir,
+ &conf->pidfile_path,
+ &conf->logfile_path,
+ &conf->preseed_path,
+ NULL
+ };
+
+ char cwd_buf[PATH_MAX + 1];
+ memset (cwd_buf, 0, PATH_MAX + 1);
+
+ char *tmp = getcwd (cwd_buf, PATH_MAX);
+ if (tmp == NULL)
+ {
+
+ vdev_error ("Current working directory exceeds %u bytes\n", PATH_MAX);
return -ERANGE;
- }
-
- for( int i = 0; need_fullpath[i] != NULL; i++ ) {
-
- if( need_fullpath[i] != NULL && (*need_fullpath[i]) != NULL ) {
-
- // if special sentinel string "syslog" is found, don't process it
- if( need_fullpath[i] == &conf->logfile_path && strncmp((*need_fullpath[i]), "syslog",7) == 0 ) {
- continue;
- }
-
- if( *(need_fullpath[i])[0] != '/' ) {
-
- // relative path
- char* new_path = vdev_fullpath( cwd_buf, *(need_fullpath)[i], NULL );
- if( new_path == NULL ) {
-
- return -ENOMEM;
- }
-
- free( *(need_fullpath[i]) );
- *(need_fullpath[i]) = new_path;
- }
- }
- }
-
- return 0;
-}
+ }
+
+ for (int i = 0; need_fullpath[i] != NULL; i++)
+ {
+
+ if (need_fullpath[i] != NULL && (*need_fullpath[i]) != NULL)
+ {
+
+ // if special sentinel string "syslog" is found, don't process it
+ if (need_fullpath[i] == &conf->logfile_path
+ && strncmp ((*need_fullpath[i]), "syslog", 7) == 0)
+ {
+ continue;
+ }
+
+ if (*(need_fullpath[i])[0] != '/')
+ {
+ // relative path
+ char *new_path = vdev_fullpath (cwd_buf, *(need_fullpath)[i],
+ NULL);
+ if (new_path == NULL)
+ {
+ return -ENOMEM;
+ }
+
+ free (*(need_fullpath[i]));
+ *(need_fullpath[i]) = new_path;
+ }
+ }
+ }
+
+ return 0;
+}
// print usage statement
-int vdev_config_usage( char const* progname ) {
- fprintf(stderr, "\
+int
+vdev_config_usage (char const *progname)
+{
+ fprintf (stderr, "\
\
Usage: %s [options] mountpoint\n\
Options include:\n\
@@ -487,205 +573,253 @@ Options include:\n\
\n\
-p, --pidfile PATH\n\
Write the PID of the daemon to PATH.\n\
-", progname );
-
+ -h, --help\n\
+ prints this help message.\n\
+ and exits early.\n\
+", progname);
+
return 0;
}
// get the mountpoint option, by taking the last argument that wasn't an optarg
-static int vdev_config_get_mountpoint_from_fuse( int fuse_argc, char** fuse_argv, char** ret_mountpoint ) {
-
- *ret_mountpoint = realpath( fuse_argv[ fuse_argc - 1 ], NULL );
-
- if( *ret_mountpoint == NULL ) {
-
+static int
+vdev_config_get_mountpoint_from_fuse (int fuse_argc, char **fuse_argv,
+ char **ret_mountpoint)
+{
+
+ *ret_mountpoint = realpath (fuse_argv[fuse_argc - 1], NULL);
+
+ if (*ret_mountpoint == NULL)
+ {
+
int rc = -errno;
- printf("No mountpoint, rc = %d\n", rc);
-
- for( int i = 0; i < fuse_argc; i++ ) {
- printf("argv[%d]: '%s'\n", i, fuse_argv[i]);
- }
-
+ printf ("No mountpoint, rc = %d\n", rc);
+
+ for (int i = 0; i < fuse_argc; i++)
+ {
+ printf ("argv[%d]: '%s'\n", i, fuse_argv[i]);
+ }
+
return -EINVAL;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// parse command-line options from argv.
// fill in fuse_argv with fuse-specific options.
// config must be initialized; this method simply augments it
// return 0 on success
// return -1 on unrecognized option
-int vdev_config_load_from_args( struct vdev_config* config, int argc, char** argv, int* fuse_argc, char** fuse_argv ) {
-
- static struct option vdev_options[] = {
- {"config-file", required_argument, 0, 'c'},
- {"verbose-level", required_argument, 0, 'v'},
- {"logfile", required_argument, 0, 'l'},
- {"pidfile", required_argument, 0, 'p'},
- {"once", no_argument, 0, '1'},
- {"coldplug-only", no_argument, 0, 'n'},
- {"foreground", no_argument, 0, 'f'},
- {0, 0, 0, 0}
- };
-
- int rc = 0;
- int opt_index = 0;
- int c = 0;
- int fuse_optind = 0;
-
- char const* optstr = "c:v:l:o:f1np:ds";
-
- if( fuse_argv != NULL ) {
- fuse_argv[fuse_optind] = argv[0];
- fuse_optind++;
- }
-
- while(rc == 0 && c != -1) {
-
- c = getopt_long(argc, argv, optstr, vdev_options, &opt_index);
-
- if( c == -1 ) {
- break;
- }
-
- switch( c ) {
-
- case 'c': {
-
- if( config->config_path != NULL ) {
- free( config->config_path );
- }
-
- config->config_path = vdev_strdup_or_null( optarg );
- break;
- }
-
- case 'l': {
-
- if( config->logfile_path != NULL ) {
- free( config->logfile_path );
- }
-
- config->logfile_path = vdev_strdup_or_null( optarg );
- break;
- }
-
- case 'p': {
-
- if( config->pidfile_path != NULL ) {
- free( config->pidfile_path );
- }
-
- config->pidfile_path = vdev_strdup_or_null( optarg );
- break;
- }
-
- case 'v': {
-
- long debug_level = 0;
- char* tmp = NULL;
-
- debug_level = strtol( optarg, &tmp, 10 );
-
- if( *tmp != '\0' ) {
- fprintf(stderr, "Invalid argument for -d\n");
- rc = -1;
- }
- else {
- config->debug_level = debug_level;
- }
- break;
- }
-
- case 'n':
- case '1': {
-
- config->coldplug_only = true;
- break;
- }
-
- case 's': {
- // FUSE Option
- if( fuse_argv != NULL ) {
- fuse_argv[fuse_optind] = (char*)FUSE_OPT_S;
- fuse_optind++;
- }
-
- break;
- }
-
- case 'd': {
- // FUSE option
- if( fuse_argv != NULL ) {
- fuse_argv[fuse_optind] = (char*)FUSE_OPT_D;
- fuse_optind++;
- }
-
- break;
- }
-
- case 'f': {
- // FUSE option
- if( fuse_argv != NULL ) {
- fuse_argv[fuse_optind] = (char*)FUSE_OPT_F;
- fuse_optind++;
- }
-
- config->foreground = true;
- break;
- }
-
- case 'o': {
- // FUSE option
- if( fuse_argv != NULL ) {
- fuse_argv[fuse_optind] = (char*)FUSE_OPT_O;
- fuse_optind++;
-
- fuse_argv[fuse_optind] = optarg;
- fuse_optind++;
- }
-
- break;
- }
-
- default: {
-
- fprintf(stderr, "Unrecognized option -%c\n", c );
- rc = -1;
- break;
- }
- }
- }
-
- if( rc != 0 ) {
+int
+vdev_config_load_from_args (struct vdev_config *config, int argc,
+ char **argv, int *fuse_argc, char **fuse_argv)
+{
+
+ static struct option vdev_options[] = {
+ {"config-file", required_argument, 0, 'c'},
+ {"verbose-level", required_argument, 0, 'v'},
+ {"logfile", required_argument, 0, 'l'},
+ {"pidfile", required_argument, 0, 'p'},
+ {"once", no_argument, 0, '1'},
+ {"coldplug-only", no_argument, 0, 'n'},
+ {"foreground", no_argument, 0, 'f'},
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+
+ int rc = 0;
+ int opt_index = 0;
+ int c = 0;
+ int fuse_optind = 0;
+
+ char const *optstr = "c:v:l:o:hf1np:ds";
+
+ if (fuse_argv != NULL)
+ {
+ fuse_argv[fuse_optind] = argv[0];
+ fuse_optind++;
+ }
+
+ while (rc == 0 && c != -1)
+ {
+
+ c = getopt_long (argc, argv, optstr, vdev_options, &opt_index);
+ // break on -1 missing arguments and -2 help
+ if (c == -1 || c == -2)
+ {
+ break;
+ }
+
+ switch (c)
+ {
+
+ case 'c':
+ {
+
+ if (config->config_path != NULL)
+ {
+ free (config->config_path);
+ }
+
+ config->config_path = vdev_strdup_or_null (optarg);
+ break;
+ }
+
+ case 'l':
+ {
+
+ if (config->logfile_path != NULL)
+ {
+ free (config->logfile_path);
+ }
+
+ config->logfile_path = vdev_strdup_or_null (optarg);
+ break;
+ }
+
+ case 'p':
+ {
+
+ if (config->pidfile_path != NULL)
+ {
+ free (config->pidfile_path);
+ }
+
+ config->pidfile_path = vdev_strdup_or_null (optarg);
+ break;
+ }
+
+ case 'v':
+ {
+
+ long debug_level = 0;
+ char *tmp = NULL;
+
+ debug_level = strtol (optarg, &tmp, 10);
+
+ if (*tmp != '\0')
+ {
+ fprintf (stderr, "Invalid argument for -d\n");
+ rc = -1;
+ }
+ else
+ {
+ config->debug_level = debug_level;
+ }
+ break;
+ }
+
+ case 'n':
+ case '1':
+ {
+
+ config->coldplug_only = true;
+ break;
+ }
+
+ case 's':
+ {
+ // FUSE Option
+ if (fuse_argv != NULL)
+ {
+ fuse_argv[fuse_optind] = (char *) FUSE_OPT_S;
+ fuse_optind++;
+ }
+
+ break;
+ }
+
+ case 'd':
+ {
+ // FUSE option
+ if (fuse_argv != NULL)
+ {
+ fuse_argv[fuse_optind] = (char *) FUSE_OPT_D;
+ fuse_optind++;
+ }
+
+ break;
+ }
+
+ case 'f':
+ {
+ // FUSE option
+ if (fuse_argv != NULL)
+ {
+ fuse_argv[fuse_optind] = (char *) FUSE_OPT_F;
+ fuse_optind++;
+ }
+
+ config->foreground = true;
+ break;
+ }
+
+ case 'o':
+ {
+ // FUSE option
+ if (fuse_argv != NULL)
+ {
+ fuse_argv[fuse_optind] = (char *) FUSE_OPT_O;
+ fuse_optind++;
+
+ fuse_argv[fuse_optind] = optarg;
+ fuse_optind++;
+ }
+
+ break;
+ }
+
+ case 'h':
+ {
+ // command args line help
+ fprintf (stderr, "Command Line Options Help \n");
+ rc = -2;
+ break;
+ }
+
+ default:
+ {
+
+ fprintf (stderr, "Unrecognized option -%c\n", c);
+ rc = -1;
+ break;
+ }
+ }
+ }
+
+ if (rc != 0)
+ {
return rc;
- }
-
- if( fuse_argv != NULL ) {
- // copy over non-option arguments to fuse_argv
- for( int i = optind; i < argc; i++ ) {
-
- fuse_argv[ fuse_optind ] = argv[i];
- fuse_optind++;
- }
-
- *fuse_argc = fuse_optind;
-
- // parse FUSE args to get the mountpoint
- rc = vdev_config_get_mountpoint_from_fuse( *fuse_argc, fuse_argv, &config->mountpoint );
- }
- else {
-
- // extract mountpoint
- config->mountpoint = realpath( argv[ optind ], NULL );
- if( config->mountpoint == NULL ) {
- rc = -errno;
- fprintf(stderr, "Failed to evaluate '%s': %s\n", argv[optind], strerror(-rc) );
- }
- }
- return rc;
+ }
+
+ if (fuse_argv != NULL)
+ {
+ // copy over non-option arguments to fuse_argv
+ for (int i = optind; i < argc; i++)
+ {
+
+ fuse_argv[fuse_optind] = argv[i];
+ fuse_optind++;
+ }
+
+ *fuse_argc = fuse_optind;
+
+ // parse FUSE args to get the mountpoint
+ rc = vdev_config_get_mountpoint_from_fuse (*fuse_argc, fuse_argv,
+ &config->mountpoint);
+ }
+ else
+ {
+
+ // extract mountpoint
+ config->mountpoint = realpath (argv[optind], NULL);
+ if (config->mountpoint == NULL)
+ {
+ rc = -errno;
+ fprintf (stderr, "Failed to evaluate '%s': %s\n",
+ argv[optind], strerror (-rc));
+ }
+ }
+ return rc;
}
-
diff --git a/libvdev/config.h b/libvdev/config.h
index 0496b03..ac3336c 100644
--- a/libvdev/config.h
+++ b/libvdev/config.h
@@ -34,7 +34,7 @@
#define VDEV_CONFIG_ACTIONS "actions"
#define VDEV_CONFIG_HELPERS "helpers"
#define VDEV_CONFIG_DEFAULT_MODE "default_permissions"
-#define VDEV_CONFIG_DEFAULT_POLICY "default_policy" // ACL allow or deny
+#define VDEV_CONFIG_DEFAULT_POLICY "default_policy" // ACL allow or deny
#define VDEV_CONFIG_PIDFILE_PATH "pidfile"
#define VDEV_CONFIG_LOGFILE_PATH "logfile"
#define VDEV_CONFIG_LOG_LEVEL "loglevel"
@@ -42,81 +42,84 @@
#define VDEV_CONFIG_COLDPLUG_ONLY "coldplug_only"
#define VDEV_CONFIG_FOREGROUND "foreground"
#define VDEV_CONFIG_PRESEED "preseed"
+#define VDEV_CONFIG_HELP "help" // simple commandline help
#define VDEV_CONFIG_INSTANCE_NONCE_LEN 32
#define VDEV_CONFIG_INSTANCE_NONCE_STRLEN (2*VDEV_CONFIG_INSTANCE_NONCE_LEN + 1)
-#define VDEV_OS_QUIRK_DEVICE_EXISTS 0x1 // set this bit if the OS already has the device file--i.e. vdevd is not expected to create it
+#define VDEV_OS_QUIRK_DEVICE_EXISTS 0x1 // set this bit if the OS already has the device file--i.e. vdevd is not expected to create it
#define vdev_config_has_OS_quirk( quirk_field, quirk ) (((quirk_field) & (quirk)) != 0)
#define vdev_config_set_OS_quirk( quirk_field, quirk ) quirk_field |= (quirk)
// structure for both file configuration and command-line options
-struct vdev_config {
-
- // config file path (used by opts)
- char* config_path;
-
- // preseed script
- char* preseed_path;
-
- // ACLs directory
- char* acls_dir;
-
- // actions directory
- char* acts_dir;
-
- // helpers directory
- char* helpers_dir;
-
- // default policy (0 for deny, 1 for allow)
- int default_policy;
-
- // debug level
- int debug_level;
-
- // error level
- int error_level;
-
- // PID file path
- char* pidfile_path;
-
- // logfile path (set to "syslog" to send directly to syslog)
- char* logfile_path;
-
- // path to where /dev lives
- char* mountpoint;
-
- // coldplug only?
- bool coldplug_only;
-
- // run in the foreground
- bool foreground;
-
- // OS-specific configuration (for keys under "OS")
- vdev_params* os_config;
-
- // default permission bits for mknod
- mode_t default_mode;
-
- // printable 256-bit instance nonce--randomly generated and unique per execution
- char instance_str[VDEV_CONFIG_INSTANCE_NONCE_STRLEN];
-
- // bitfield of OS-specific quirks
- uint64_t OS_quirks;
-};
+struct vdev_config
+{
-C_LINKAGE_BEGIN
+ // config file path (used by opts)
+ char *config_path;
-int vdev_config_init( struct vdev_config* conf );
-int vdev_config_load( char const* path, struct vdev_config* conf );
-int vdev_config_load_file( FILE* file, struct vdev_config* conf );
-int vdev_config_free( struct vdev_config* conf );
+ // preseed script
+ char *preseed_path;
-int vdev_config_usage( char const* progname );
-int vdev_config_load_from_args( struct vdev_config* config, int argc, char** argv, int* fuse_argc, char** fuse_argv );
-int vdev_config_fullpaths( struct vdev_config* config );
+ // ACLs directory
+ char *acls_dir;
-C_LINKAGE_END
+ // actions directory
+ char *acts_dir;
+
+ // helpers directory
+ char *helpers_dir;
+
+ // default policy (0 for deny, 1 for allow)
+ int default_policy;
+
+ // debug level
+ int debug_level;
+
+ // error level
+ int error_level;
+
+ // PID file path
+ char *pidfile_path;
+
+ // logfile path (set to "syslog" to send directly to syslog)
+ char *logfile_path;
+
+ // path to where /dev lives
+ char *mountpoint;
+
+ // coldplug only?
+ bool coldplug_only;
+ // run in the foreground
+ bool foreground;
+
+ // OS-specific configuration (for keys under "OS")
+ vdev_params *os_config;
+
+ // default permission bits for mknod
+ mode_t default_mode;
+
+ // printable 256-bit instance nonce--randomly generated and unique per execution
+ char instance_str[VDEV_CONFIG_INSTANCE_NONCE_STRLEN];
+
+ // bitfield of OS-specific quirks
+ uint64_t OS_quirks;
+
+ // help holder
+ char help;
+};
+
+C_LINKAGE_BEGIN int vdev_config_init (struct vdev_config *conf);
+int vdev_config_load (char const *path, struct vdev_config *conf);
+int vdev_config_load_file (FILE * file, struct vdev_config *conf);
+int vdev_config_free (struct vdev_config *conf);
+int vdev_config_usage (char const *progname);
+int vdev_config_load_from_args (struct vdev_config *config, int argc,
+ char **argv, int *fuse_argc,
+ char **fuse_argv);
+int vdev_config_fullpaths (struct vdev_config *config);
+
+C_LINKAGE_END
#endif
diff --git a/libvdev/ini.c b/libvdev/ini.c
index 56426cd..df66584 100644
--- a/libvdev/ini.c
+++ b/libvdev/ini.c
@@ -1,181 +1,218 @@
/* inih -- simple .INI file parser
-inih is released under the New BSD license (see LICENSE.txt). Go to the project
-home page for more info:
-
+inih is released under the New BSD license (see LICENSE.txt).
+Go to the project home page for more info:
http://code.google.com/p/inih/
-*/
-
+*/
+
#include
#include
#include
-
+
#include "ini.h"
-
+
#if !INI_USE_STACK
#include
-#endif
-
+#endif /*
*/
+
#define MAX_SECTION 50
#define MAX_NAME 50
-
-/* Strip whitespace chars off end of given string, in place. Return s. */
-static char* rstrip(char* s)
-{
- char* p = s + strlen(s);
- while (p > s && isspace((unsigned char)(*--p)))
- *p = '\0';
- return s;
-}
-
-/* Return pointer to first non-whitespace char in given string. */
-static char* lskip(const char* s)
-{
- while (*s && isspace((unsigned char)(*s)))
- s++;
- return (char*)s;
-}
-
-/* Return pointer to first char c or ';' comment in given string, or pointer to
- null at end of string if neither found. ';' must be prefixed by a whitespace
- character to register as a comment. */
-static char* find_char_or_comment(const char* s, char c)
-{
- int was_whitespace = 0;
- while (*s && *s != c && !(was_whitespace && *s == ';')) {
- was_whitespace = isspace((unsigned char)(*s));
- s++;
- }
- return (char*)s;
-}
-
-/* Version of strncpy that ensures dest (size bytes) is null-terminated. */
-static char* strncpy0(char* dest, const char* src, size_t size)
-{
- strncpy(dest, src, size);
- dest[size - 1] = '\0';
- return dest;
-}
-
-/* See documentation in header file. */
-int ini_parse_file(FILE* file,
- int (*handler)(void*, const char*, const char*,
- const char*),
- void* user)
-{
- /* Uses a fair bit of stack (use heap instead if you need to) */
+
+/* Strip whitespace chars off end of given string, in place. Return s. */
+static char *
+rstrip (char *s)
+{
+
char *p = s + strlen (s);
+
while (p > s && isspace ((unsigned char) (*--p)))
+
*p = '\0';
+
return s;
+
}
+
+
+/* Return pointer to first non-whitespace char in given string. */
+static char *
+lskip (const char *s)
+{
+
while (*s && isspace ((unsigned char) (*s)))
+
s++;
+
return (char *) s;
+
}
+
+/*
+Return pointer to first char c or ';' comment in given string,
+or pointer to null at end of string if neither found.
+';' must be prefixed by a whitespace character to register as a comment.
+*/
+static char *
+find_char_or_comment (const char *s, char c)
+{
+
int was_whitespace = 0;
+
while (*s && *s != c && !(was_whitespace && *s == ';'))
+ {
+
was_whitespace = isspace ((unsigned char) (*s));
+
s++;
+
}
return (char *) s;
+
}
+
+/* Version of strncpy that ensures dest (size bytes) is null-terminated. */
+static char *
+strncpy0 (char *dest, const char *src, size_t size)
+{
+
strncpy (dest, src, size);
+
dest[size - 1] = '\0';
+
return dest;
+
}
+
+
+/* See documentation in header file. */
+ int
+ini_parse_file (FILE * file,
+
int (*handler) (void *, const char *, const char *,
+
const char *),
void *user)
+{
+
+ /* Uses a fair bit of stack (use heap instead if you need to) */
#if INI_USE_STACK
- char line[INI_MAX_LINE];
-#else
- char* line;
-#endif
- char section[MAX_SECTION] = "";
- char prev_name[MAX_NAME] = "";
-
- char* start;
- char* end;
- char* name;
- char* value;
- int lineno = 0;
- int error = 0;
-
+ char line[INI_MAX_LINE];
+
+#else /*
*/
+ char *line;
+
+#endif /*
*/
+ char section[MAX_SECTION] = "";
+
char prev_name[MAX_NAME] = "";
+
char *start;
+
char *end;
+
char *name;
+
char *value;
+
int lineno = 0;
+
int error = 0;
+
#if !INI_USE_STACK
- line = (char*)malloc(INI_MAX_LINE);
- if (!line) {
- return -2;
- }
-#endif
-
- /* Scan through file line by line */
- while (fgets(line, INI_MAX_LINE, file) != NULL) {
- lineno++;
-
- start = line;
+ line = (char *) malloc (INI_MAX_LINE);
+
if (!line)
+ {
+
return -2;
+
}
+
+#endif /*
*/
+
+ /* Scan through file line by line */
+ while (fgets (line, INI_MAX_LINE, file) != NULL)
+ {
+
lineno++;
+
start = line;
+
#if INI_ALLOW_BOM
- if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
- (unsigned char)start[1] == 0xBB &&
- (unsigned char)start[2] == 0xBF) {
- start += 3;
- }
-#endif
- start = lskip(rstrip(start));
-
- if (*start == ';' || *start == '#') {
- /* Per Python ConfigParser, allow '#' comments at start of line */
- }
+ if (lineno == 1 && (unsigned char) start[0] == 0xEF &&
+ (unsigned char) start[1] == 0xBB &&
+ (unsigned char) start[2] == 0xBF)
+ {
+
start += 3;
+
}
+
+#endif /*
*/
+ start = lskip (rstrip (start));
+
if (*start == ';' || *start == '#')
+ {
+
+ /* Per Python ConfigParser, allow '#' comments at start of line */
+ }
+
#if INI_ALLOW_MULTILINE
- else if (*prev_name && *start && start > line) {
- /* Non-black line with leading whitespace, treat as continuation
- of previous name's value (as per Python ConfigParser). */
- if (!handler(user, section, prev_name, start) && !error)
- error = lineno;
- }
-#endif
- else if (*start == '[') {
- /* A "[section]" line */
- end = find_char_or_comment(start + 1, ']');
- if (*end == ']') {
- *end = '\0';
- strncpy0(section, start + 1, sizeof(section));
- *prev_name = '\0';
- }
- else if (!error) {
- /* No ']' found on section line */
- error = lineno;
- }
- }
- else if (*start && *start != ';') {
- /* Not a comment, must be a name[=:]value pair */
- end = find_char_or_comment(start, '=');
- if (*end != '=') {
- end = find_char_or_comment(start, ':');
- }
- if (*end == '=' || *end == ':') {
- *end = '\0';
- name = rstrip(start);
- value = lskip(end + 1);
- end = find_char_or_comment(value, '\0');
- if (*end == ';')
- *end = '\0';
- rstrip(value);
-
- /* Valid name[=:]value pair found, call handler */
- strncpy0(prev_name, name, sizeof(prev_name));
- if (!handler(user, section, name, value) && !error)
- error = lineno;
- }
- else if (!error) {
- /* No '=' or ':' found on name[=:]value line */
- error = lineno;
- }
- }
-
+ else if (*prev_name && *start && start > line)
+ {
+
+ /* Non-black line with leading whitespace, treat as continuation
+ of previous name's value (as per Python ConfigParser). */
+ if (!handler (user, section, prev_name, start) && !error)
+
error = lineno;
+
}
+
+#endif /*
*/
+ else if (*start == '[')
+ {
+
+ /* A "[section]" line */
+ end = find_char_or_comment (start + 1, ']');
+
if (*end == ']')
+ {
+
*end = '\0';
+
strncpy0 (section, start + 1, sizeof (section));
+
*prev_name = '\0';
+
}
+
+ else if (!error)
+ {
+
+ /* No ']' found on section line */
+ error = lineno;
+
}
+
}
+
+ else if (*start && *start != ';')
+ {
+
+ /* Not a comment, must be a name[=:]value pair */
+ end = find_char_or_comment (start, '=');
+
if (*end != '=')
+ {
+
end = find_char_or_comment (start, ':');
+
}
+
if (*end == '=' || *end == ':')
+ {
+
*end = '\0';
+
name = rstrip (start);
+
value = lskip (end + 1);
+
end = find_char_or_comment (value, '\0');
+
if (*end == ';')
+
*end = '\0';
+
rstrip (value);
+
+ /* Valid name[=:]value pair found, call handler */
+ strncpy0 (prev_name, name, sizeof (prev_name));
+
if (!handler (user, section, name, value) && !error)
+
error = lineno;
+
}
+
+ else if (!error)
+ {
+
+ /* No '=' or ':' found on name[=:]value line */
+ error = lineno;
+
}
+
}
+
#if INI_STOP_ON_FIRST_ERROR
- if (error)
- break;
-#endif
- }
-
+ if (error)
+
break;
+
+#endif /*
*/
+ }
+
#if !INI_USE_STACK
- free(line);
-#endif
-
- return error;
-}
-
-/* See documentation in header file. */
-int ini_parse(const char* filename,
- int (*handler)(void*, const char*, const char*, const char*),
- void* user)
-{
- FILE* file;
- int error;
+ free (line);
+
+#endif /*
*/
+
return error;
+
}
+
+
+/* See documentation in header file. */
+ int
+ini_parse (const char *filename,
+
int (*handler) (void *, const char *, const char *,
+ const char *),
void *user)
+{
+
FILE * file;
+
int error;
+
file = fopen (filename, "r");
+
if (!file)
+
return -1;
+
error = ini_parse_file (file, handler, user);
+
fclose (file);
+
return error;
+
}
+
- file = fopen(filename, "r");
- if (!file)
- return -1;
- error = ini_parse_file(file, handler, user);
- fclose(file);
- return error;
-}
diff --git a/libvdev/ini.h b/libvdev/ini.h
index b267da6..6cbd784 100644
--- a/libvdev/ini.h
+++ b/libvdev/ini.h
@@ -1,22 +1,22 @@
/* inih -- simple .INI file parser
-inih is released under the New BSD license (see LICENSE.txt). Go to the project
-home page for more info:
-
+inih is released under the New BSD license (see LICENSE.txt).
+Go to the project home page for more info:
http://code.google.com/p/inih/
-
-*/
-
+*/
+
#ifndef __INI_H__
#define __INI_H__
-
-/* Make this header file easier to include in C++ code */
+
+/* Make this header file easier to include in C++ code */
#ifdef __cplusplus
-extern "C" {
-#endif
-
+extern "C"
+{
+
+#endif /*
*/
+
#include
-
+
/* Parse given INI-style file. May have [section]s, name=value pairs
(whitespace stripped), and comments starting with ';' (semicolon). Section
is "" if name=value pair parsed before any section heading. name:value
@@ -29,49 +29,50 @@ extern "C" {
Returns 0 on success, line number of first error on parse error (doesn't
stop on first error), -1 on file open error, or -2 on memory allocation
error (only when INI_USE_STACK is zero).
-*/
-int ini_parse(const char* filename,
- int (*handler)(void* user, const char* section,
- const char* name, const char* value),
- void* user);
-
+*/
+ int ini_parse (const char *filename,
+
int (*handler) (void *user, const char *section,
+
const char *name, const char *value),
+
void *user);
+
/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
- close the file when it's finished -- the caller must do that. */
-int ini_parse_file(FILE* file,
- int (*handler)(void* user, const char* section,
- const char* name, const char* value),
- void* user);
-
-/* Nonzero to allow multi-line value parsing, in the style of Python's
- ConfigParser. If allowed, ini_parse() will call the handler with the same
- name for each subsequent line parsed. */
+ close the file when it's finished -- the caller must do that. */
+
int ini_parse_file (FILE * file,
+
int (*handler) (void *user, const char *section,
+
const char *name,
+ const char *value),
void *user);
+
+ /* Nonzero to allow multi-line value parsing, in the style of Python's
+ ConfigParser. If allowed, ini_parse() will call the handler with the same
+ name for each subsequent line parsed. */
+
#ifndef INI_ALLOW_MULTILINE
#define INI_ALLOW_MULTILINE 0
-#endif
-
+#endif /*
*/
+
/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
- the file. See http://code.google.com/p/inih/issues/detail?id=21 */
+ the file. See http://code.google.com/p/inih/issues/detail?id=21 */
#ifndef INI_ALLOW_BOM
#define INI_ALLOW_BOM 1
-#endif
-
-/* Nonzero to use stack, zero to use heap (malloc/free). */
+#endif /*
*/
+
+/* Nonzero to use stack, zero to use heap (malloc/free). */
#ifndef INI_USE_STACK
#define INI_USE_STACK 1
-#endif
-
-/* Stop parsing on first error (default is to keep parsing). */
+#endif /*
*/
+
+/* Stop parsing on first error (default is to keep parsing). */
#ifndef INI_STOP_ON_FIRST_ERROR
#define INI_STOP_ON_FIRST_ERROR 1
-#endif
-
-/* Maximum line length for any line in INI file. */
+#endif /*
*/
+
+/* Maximum line length for any line in INI file. */
#ifndef INI_MAX_LINE
#define INI_MAX_LINE 4096
-#endif
-
+#endif /*
*/
+
#ifdef __cplusplus
-}
-#endif
-
-#endif /* __INI_H__ */
+}
+#endif /*
*/
+
+#endif /* __INI_H__ */
diff --git a/libvdev/match.c b/libvdev/match.c
index 585b754..f5c2e49 100644
--- a/libvdev/match.c
+++ b/libvdev/match.c
@@ -22,137 +22,164 @@
#include "match.h"
// parse a regex
-int vdev_match_regex_init( regex_t* regex, char const* str ) {
-
- int rc = 0;
-
- rc = regcomp( regex, str, REG_EXTENDED | REG_NEWLINE );
-
- if( rc != 0 ) {
-
+int
+vdev_match_regex_init (regex_t * regex, char const *str)
+{
+
+ int rc = 0;
+
+ rc = regcomp (regex, str, REG_EXTENDED | REG_NEWLINE);
+
+ if (rc != 0)
+ {
+
return -EINVAL;
- }
- else {
+ }
+ else
+ {
return 0;
- }
+ }
}
// parse a regex and append it to a list of regexes and strings
// return 0 on success
// return -EINVAL if the regex is invalid
// return -ENOMEM if we're out of memory
-int vdev_match_regex_append( char*** strings, regex_t** regexes, size_t* len, char const* next ) {
-
- // verify that this is a valid regex
- regex_t reg;
- int rc = 0;
-
- memset( ®, 0, sizeof(regex_t) );
-
- rc = regcomp( ®, next, REG_EXTENDED | REG_NEWLINE | REG_NOSUB );
- if( rc != 0 ) {
-
- vdev_error("regcomp(%s) rc = %d\n", next, rc );
+int
+vdev_match_regex_append (char ***strings, regex_t ** regexes, size_t * len,
+ char const *next)
+{
+
+ // verify that this is a valid regex
+ regex_t reg;
+ int rc = 0;
+
+ memset (®, 0, sizeof (regex_t));
+
+ rc = regcomp (®, next, REG_EXTENDED | REG_NEWLINE | REG_NOSUB);
+ if (rc != 0)
+ {
+
+ vdev_error ("regcomp(%s) rc = %d\n", next, rc);
return -EINVAL;
- }
-
- char** new_strings = (char**)realloc( *strings, sizeof(char**) * (*len + 2) );
- regex_t* new_regexes = (regex_t*)realloc( *regexes, sizeof(regex_t) * (*len + 1) );
-
- if( new_strings == NULL || new_regexes == NULL ) {
+ }
+
+ char **new_strings =
+ (char **) realloc (*strings, sizeof (char **) * (*len + 2));
+ regex_t *new_regexes =
+ (regex_t *) realloc (*regexes, sizeof (regex_t) * (*len + 1));
+
+ if (new_strings == NULL || new_regexes == NULL)
+ {
return -ENOMEM;
- }
-
- new_strings[*len] = vdev_strdup_or_null( next );
- new_strings[*len + 1] = NULL;
-
- new_regexes[*len] = reg;
-
- *strings = new_strings;
- *regexes = new_regexes;
-
- *len = *len + 1;
-
- return 0;
-}
+ }
+
+ new_strings[*len] = vdev_strdup_or_null (next);
+ new_strings[*len + 1] = NULL;
+
+ new_regexes[*len] = reg;
+
+ *strings = new_strings;
+ *regexes = new_regexes;
+ *len = *len + 1;
+
+ return 0;
+}
// free a list of regexes and their associated paths
-int vdev_match_regexes_free( char** regex_strs, regex_t* regexes, size_t len ) {
-
- if( regex_strs != NULL || regexes != NULL ) {
-
- for( unsigned int i = 0; i < len; i++ ) {
-
- if( regex_strs != NULL && regex_strs[i] != NULL ) {
-
- free( regex_strs[i] );
- regex_strs[i] = NULL;
- }
-
- if( regexes != NULL ) {
- regfree( ®exes[i] );
- }
- }
-
- if( regex_strs != NULL ) {
-
- free( regex_strs );
- }
-
- if( regexes != NULL ) {
-
- free( regexes );
- }
- }
-
- return 0;
+int
+vdev_match_regexes_free (char **regex_strs, regex_t * regexes, size_t len)
+{
+
+ if (regex_strs != NULL || regexes != NULL)
+ {
+
+ for (unsigned int i = 0; i < len; i++)
+ {
+
+ if (regex_strs != NULL && regex_strs[i] != NULL)
+ {
+
+ free (regex_strs[i]);
+ regex_strs[i] = NULL;
+ }
+
+ if (regexes != NULL)
+ {
+ regfree (®exes[i]);
+ }
+ }
+
+ if (regex_strs != NULL)
+ {
+
+ free (regex_strs);
+ }
+
+ if (regexes != NULL)
+ {
+
+ free (regexes);
+ }
+ }
+
+ return 0;
}
// does a path match a regex?
// return 1 if so, 0 if not, negative on error
-int vdev_match_regex( char const* path, regex_t* regex ) {
-
- int rc = 0;
-
- rc = regexec( regex, path, 0, NULL, 0 );
-
- if( rc != 0 ) {
- if( rc == REG_NOMATCH ) {
-
- // no match
- return 0;
- }
- else {
- vdev_error("regexec(%s) rc = %d\n", path, rc );
- return -abs(rc);
- }
- }
-
- // match!
- return 1;
-}
+int
+vdev_match_regex (char const *path, regex_t * regex)
+{
+ int rc = 0;
+
+ rc = regexec (regex, path, 0, NULL, 0);
+
+ if (rc != 0)
+ {
+ if (rc == REG_NOMATCH)
+ {
+
+ // no match
+ return 0;
+ }
+ else
+ {
+ vdev_error ("regexec(%s) rc = %d\n", path, rc);
+ return -abs (rc);
+ }
+ }
+ // match!
+ return 1;
+}
// does a path match any regexes in a list?
// return the index of the match if so (>= 0)
// return the size if not
// return negative on error
-int vdev_match_first_regex( char const* path, regex_t* regexes, size_t num_regexes ) {
-
- int matched = 0;
-
- for( unsigned int i = 0; i < num_regexes; i++ ) {
-
- matched = vdev_match_regex( path, ®exes[i] );
- if( matched > 0 ) {
- return i;
- }
- else if( matched < 0 ) {
- vdev_error("vdev_acl_regex_match(%s) rc = %d\n", path, matched );
- return matched;
- }
- }
-
- return num_regexes;
+int
+vdev_match_first_regex (char const *path, regex_t * regexes,
+ size_t num_regexes)
+{
+
+ int matched = 0;
+
+ for (unsigned int i = 0; i < num_regexes; i++)
+ {
+
+ matched = vdev_match_regex (path, ®exes[i]);
+ if (matched > 0)
+ {
+ return i;
+ }
+ else if (matched < 0)
+ {
+ vdev_error ("vdev_acl_regex_match(%s) rc = %d\n", path, matched);
+ return matched;
+ }
+ }
+
+ return num_regexes;
}
diff --git a/libvdev/match.h b/libvdev/match.h
index eb580be..e61062c 100644
--- a/libvdev/match.h
+++ b/libvdev/match.h
@@ -26,15 +26,14 @@
#include
+C_LINKAGE_BEGIN int vdev_match_regex_init (regex_t * regex, char const *str);
+int vdev_match_regex_append (char ***strings, regex_t ** regexes,
+ size_t * len, char const *next);
+int vdev_match_regexes_free (char **regex_strs, regex_t * regexes,
+ size_t len);
+int vdev_match_regex (char const *path, regex_t * regex);
+int vdev_match_first_regex (char const *path, regex_t * regexes,
+ size_t num_regexes);
-C_LINKAGE_BEGIN
-
-int vdev_match_regex_init( regex_t* regex, char const* str );
-int vdev_match_regex_append( char*** strings, regex_t** regexes, size_t* len, char const* next );
-int vdev_match_regexes_free( char** regex_strs, regex_t* regexes, size_t len );
-int vdev_match_regex( char const* path, regex_t* regex );
-int vdev_match_first_regex( char const* path, regex_t* regexes, size_t num_regexes );
-
C_LINKAGE_END
-
-#endif
\ No newline at end of file
+#endif
diff --git a/libvdev/param.c b/libvdev/param.c
index 0d4b629..86ec31d 100644
--- a/libvdev/param.c
+++ b/libvdev/param.c
@@ -22,87 +22,101 @@
#include "param.h"
// sglib methods
-SGLIB_DEFINE_RBTREE_FUNCTIONS(vdev_params, left, right, color, VDEV_PARAM_CMP);
+SGLIB_DEFINE_RBTREE_FUNCTIONS (vdev_params, left, right, color,
+ VDEV_PARAM_CMP);
// add a parameter to a params set
// return 0 on success
// return -EEXIST if the parameter exists
// return -ENOMEM if OOM
-int vdev_params_add( vdev_params** params, char const* key, char const* value ) {
-
- char* key_dup = NULL;
- char* value_dup = NULL;
- struct vdev_param_t* new_param = NULL;
-
- struct vdev_param_t lookup;
-
- // exists? fill in requisite comparator information and check
- memset( &lookup, 0, sizeof(lookup) );
- lookup.key = (char*)key;
-
- new_param = sglib_vdev_params_find_member( *params, &lookup );
-
- if( new_param != NULL ) {
+int
+vdev_params_add (vdev_params ** params, char const *key, char const *value)
+{
+
+ char *key_dup = NULL;
+ char *value_dup = NULL;
+ struct vdev_param_t *new_param = NULL;
+
+ struct vdev_param_t lookup;
+
+ // exists? fill in requisite comparator information and check
+ memset (&lookup, 0, sizeof (lookup));
+ lookup.key = (char *) key;
+
+ new_param = sglib_vdev_params_find_member (*params, &lookup);
+
+ if (new_param != NULL)
+ {
return -EEXIST;
- }
-
- new_param = VDEV_CALLOC( struct vdev_param_t, 1 );
-
- if( new_param == NULL ) {
+ }
+
+ new_param = VDEV_CALLOC (struct vdev_param_t, 1);
+
+ if (new_param == NULL)
+ {
return -ENOMEM;
- }
-
- key_dup = vdev_strdup_or_null( key );
-
- if( key_dup == NULL ) {
-
- free( new_param );
+ }
+
+ key_dup = vdev_strdup_or_null (key);
+
+ if (key_dup == NULL)
+ {
+
+ free (new_param);
return -ENOMEM;
- }
-
- value_dup = vdev_strdup_or_null( value );
-
- if( value_dup == NULL ) {
-
- free( new_param );
- free( key_dup );
+ }
+
+ value_dup = vdev_strdup_or_null (value);
+
+ if (value_dup == NULL)
+ {
+
+ free (new_param);
+ free (key_dup);
return -ENOMEM;
- }
-
- new_param->key = key_dup;
- new_param->value = value_dup;
-
- sglib_vdev_params_add( params, new_param );
-
- return 0;
+ }
+
+ new_param->key = key_dup;
+ new_param->value = value_dup;
+
+ sglib_vdev_params_add (params, new_param);
+
+ return 0;
}
// free params
-int vdev_params_free( vdev_params* params ) {
-
- struct sglib_vdev_params_iterator itr;
- struct vdev_param_t* dp = NULL;
-
- for( dp = sglib_vdev_params_it_init_inorder( &itr, params ); dp != NULL; dp = sglib_vdev_params_it_next( &itr ) ) {
-
- if( dp->key != NULL ) {
-
- free( dp->key );
- dp->key = NULL;
- }
-
- if( dp->value != NULL ) {
-
- free( dp->value );
- dp->value = NULL;
- }
- }
-
- for( dp = sglib_vdev_params_it_init( &itr, params ); dp != NULL; dp = sglib_vdev_params_it_next( &itr ) ) {
-
- free( dp );
- }
-
- return 0;
-}
+int
+vdev_params_free (vdev_params * params)
+{
+
+ struct sglib_vdev_params_iterator itr;
+ struct vdev_param_t *dp = NULL;
+
+ for (dp = sglib_vdev_params_it_init_inorder (&itr, params); dp != NULL;
+ dp = sglib_vdev_params_it_next (&itr))
+ {
+
+ if (dp->key != NULL)
+ {
+ free (dp->key);
+ dp->key = NULL;
+ }
+
+ if (dp->value != NULL)
+ {
+
+ free (dp->value);
+ dp->value = NULL;
+ }
+ }
+
+ for (dp = sglib_vdev_params_it_init (&itr, params); dp != NULL;
+ dp = sglib_vdev_params_it_next (&itr))
+ {
+
+ free (dp);
+ }
+
+ return 0;
+}
diff --git a/libvdev/param.h b/libvdev/param.h
index 54b73b0..532403d 100644
--- a/libvdev/param.h
+++ b/libvdev/param.h
@@ -26,14 +26,15 @@
#include "sglib.h"
// red-black tree for (string, string) pairs (i.e. named parameter pairs)
-struct vdev_param_t {
-
- char* key;
- char* value;
-
- struct vdev_param_t* left;
- struct vdev_param_t* right;
- char color;
+struct vdev_param_t
+{
+
+ char *key;
+ char *value;
+
+ struct vdev_param_t *left;
+ struct vdev_param_t *right;
+ char color;
};
typedef struct vdev_param_t vdev_params;
@@ -41,12 +42,12 @@ typedef struct vdev_param_t vdev_params;
#define VDEV_PARAM_CMP( dp1, dp2 ) (strcmp( (dp1)->key, (dp2)->key ))
C_LINKAGE_BEGIN
-
// vdev_param_t
-SGLIB_DEFINE_RBTREE_PROTOTYPES(vdev_params, left, right, color, VDEV_PARAM_CMP);
-int vdev_params_add( vdev_params** params, char const* key, char const* value );
-int vdev_params_free( vdev_params* params );
+SGLIB_DEFINE_RBTREE_PROTOTYPES (vdev_params, left, right, color,
+ VDEV_PARAM_CMP)
+ int vdev_params_add (vdev_params ** params, char const *key,
+ char const *value);
+ int vdev_params_free (vdev_params * params);
C_LINKAGE_END
-
-#endif
\ No newline at end of file
+#endif
diff --git a/libvdev/sglib.h b/libvdev/sglib.h
index 1a2f8af..0e91da0 100644
--- a/libvdev/sglib.h
+++ b/libvdev/sglib.h
@@ -12,24 +12,20 @@
under any other license conditions, contact the author.
-
*/
-
#ifndef _SGLIB__h_
#define _SGLIB__h_
/* the assert is used exclusively to write unexpected error messages */
#include
-
/* ---------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------- */
/* - LEVEL - 0 INTERFACE - */
/* ---------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------- */
-
/* ---------------------------------------------------------------------------- */
/* ------------------------------ STATIC ARRAYS ------------------------------- */
/* ---------------------------------------------------------------------------- */
@@ -79,7 +75,6 @@
} while (_m_ != _i_);\
}
-
/* QUICK - SORT (level 0) */
#define SGLIB_ARRAY_SINGLE_QUICK_SORT(type, a, max, comparator) {\
@@ -242,7 +237,6 @@
SGLIB_HEAP_DELETE_FIRST(type, a, i, dim, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\
}
-
/* ----------------- hashed table of pointers (in an array) -------------------- */
/*
@@ -322,7 +316,6 @@
}\
}
-
/* ---------------------------------------------------------------------------- */
/* ------------------------- DYNAMIC DATA STRUCTURES -------------------------- */
/* ---------------------------------------------------------------------------- */
@@ -455,7 +448,6 @@
this property.
*/
-
#define SGLIB_SORTED_LIST_ADD(type, list, elem, comparator, next) {\
type **_e_;\
int _cmpres_;\
@@ -523,7 +515,6 @@
SGLIB_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, next, command);\
}
-
/* ------------------------------- double linked list (level 0) ------------------------- */
/*
Lists with back pointer to previous element. Those lists implements deletion
@@ -720,10 +711,8 @@
}\
}
-
/* ------------------------------- binary tree traversal (level 0) -------------------- */
-
#define SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, iteratedVariable, order, left, right, command) {\
/* this is non-recursive implementation of tree traversal */\
/* it maintains the path to the current node in the array '_path_' */\
@@ -799,8 +788,6 @@
/* ---------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------- */
-
-
/* ---------------------------------------------------------------------------- */
/* ------------------------------ STATIC ARRAYS ------------------------------- */
/* ---------------------------------------------------------------------------- */
@@ -830,7 +817,6 @@
/* dim is the size of the array afield */
/* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */
-
#define SGLIB_DEFINE_QUEUE_PROTOTYPES(queue_type, elem_type, afield, ifield, jfield, dim) \
extern void sglib_##queue_type##_init(queue_type *q); \
extern int sglib_##queue_type##_is_empty(queue_type *q); \
@@ -842,7 +828,6 @@
extern void sglib_##queue_type##_delete_first(queue_type *q); \
extern void sglib_##queue_type##_delete(queue_type *q);
-
#define SGLIB_DEFINE_QUEUE_FUNCTIONS(queue_type, elem_type, afield, ifield, jfield, dim) \
void sglib_##queue_type##_init(queue_type *q) {\
SGLIB_QUEUE_INIT(elem_type, q->afield, q->ifield, q->jfield);\
@@ -872,7 +857,6 @@
SGLIB_QUEUE_DELETE_FIRST(elem_type, q->afield, q->ifield, q->jfield, dim);\
}
-
/* ------------------------ array heap (level 1) ------------------------- */
/* sglib's heap is a priority queue implemented in a fixed sized array */
/* heap_type MUST be a structure containing fields: */
@@ -880,7 +864,6 @@
/* ifield is the index of the first free element after the queue */
/* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */
-
#define SGLIB_DEFINE_HEAP_PROTOTYPES(heap_type, elem_type, afield, ifield, dim, comparator, elem_exchanger) \
extern void sglib_##heap_type##_init(heap_type *q); \
extern int sglib_##heap_type##_is_empty(heap_type *q); \
@@ -921,7 +904,6 @@
SGLIB_HEAP_DELETE_FIRST(elem_type, q->afield, q->ifield, dim, comparator, elem_exchanger);\
}
-
/* ------------------------ hashed table (level 1) ------------------------- */
/*
@@ -1005,7 +987,6 @@
return(NULL);\
}
-
/* ------------------- hashed container (only for level 1) -------------------- */
/*
hashed container is a table of given fixed size containing another
@@ -1104,14 +1085,10 @@
return(e);\
}
-
-
/* ---------------------------------------------------------------------------- */
/* ------------------------- DYNAMIC DATA STRUCTURES -------------------------- */
/* ---------------------------------------------------------------------------- */
-
-
/* ------------------------------------ list (level 1) -------------------------------- */
#define SGLIB_DEFINE_LIST_PROTOTYPES(type, comparator, next) \
@@ -1136,7 +1113,6 @@
extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \
extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it);
-
#define SGLIB_DEFINE_LIST_FUNCTIONS(type, comparator, next) \
int sglib_##type##_is_member(type *list, type *elem) {\
int result;\
@@ -1206,7 +1182,6 @@
/* ----------------------------- sorted list (level 1) ----------------------------------- */
-
#define SGLIB_DEFINE_SORTED_LIST_PROTOTYPES(type, comparator, next) \
struct sglib_##type##_iterator {\
type *currentelem;\
@@ -1227,7 +1202,6 @@
extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \
extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it);
-
#define SGLIB_DEFINE_SORTED_LIST_FUNCTIONS(type, comparator, next) \
int sglib_##type##_is_member(type *list, type *elem) {\
int result;\
@@ -1291,10 +1265,8 @@
return(ce);\
}
-
/* ----------------------------- double linked list (level 1) ------------------------------ */
-
#define SGLIB_DEFINE_DL_LIST_PROTOTYPES(type, comparator, previous, next) \
struct sglib_##type##_iterator {\
type *currentelem;\
@@ -1324,7 +1296,6 @@
extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \
extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it);
-
#define SGLIB_DEFINE_DL_LIST_FUNCTIONS(type, comparator, previous, next) \
void sglib_##type##_add(type **list, type *elem) {\
SGLIB_DL_LIST_ADD(type, *list, elem, previous, next);\
@@ -1429,7 +1400,6 @@
return(ce);\
}
-
/* --------------------------------- red-black trees (level 1) -------------------------------- */
/*
@@ -1600,7 +1570,6 @@ fixing rules from:
}\
}
-
#define SGLIB_DEFINE_RBTREE_FUNCTIONS_GENERAL(type, left, right, bits, comparator, RED, BLACK) \
static void sglib___##type##_fix_left_insertion_discrepancy(type **tree) {\
SGLIB___RBTREE_FIX_INSERTION_DISCREPANCY(type, tree, left, right, bits, RED, BLACK);\
@@ -1887,7 +1856,6 @@ void sglib___##type##_consistency_check(type *t) {\
sglib___##type##_consistency_check_recursive(t, &pathDeep, 0);\
}
-
#define SGLIB_DEFINE_RBTREE_PROTOTYPES(type, left, right, colorbit, comparator) \
struct sglib_##type##_iterator {\
type *currentelem;\
@@ -1918,7 +1886,6 @@ void sglib___##type##_consistency_check(type *t) {\
#define SGLIB_DEFINE_RBTREE_FUNCTIONS(type, left, right, colorbit, comparator) \
SGLIB_DEFINE_RBTREE_FUNCTIONS_GENERAL(type, left, right, colorbit, comparator, 1, 0)
-
/***********************************
* vector implementation
* Copyright (C) 2015 Jude Nelson
@@ -1942,7 +1909,6 @@ void sglib___##type##_consistency_check(type *t) {\
extern unsigned long sglib_##type##_vector_size( struct sglib_##type##_vector* v ); \
extern void sglib_##type##_vector_yoink( struct sglib_##type##_vector* v, type** buf, unsigned long* len );
-
#define SGLIB_DEFINE_VECTOR_FUNCTIONS( type ) \
\
int sglib___##type##_vector_grow( struct sglib_##type##_vector* v ) { \
@@ -1986,7 +1952,7 @@ void sglib___##type##_consistency_check(type *t) {\
\
type sglib_##type##_vector_pop_back( struct sglib_##type##_vector* v ) { \
if( v->len <= 0 ) { \
- fprintf( stderr, "FATAL: pop_back on zero-length vector %p\n", v ); \
+ fprintf( stderr, "FATAL: pop_back on zero-length vector\n" ); \
abort(); \
} \
type ret = v->buf[ v->len - 1 ]; \
@@ -2032,20 +1998,17 @@ void sglib___##type##_consistency_check(type *t) {\
} \
\
-
-
+
/* ---------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------- */
/* - SUPPLEMENTARY DEFINITIONS - */
/* ---------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------- */
-
#define SGLIB___GET_VALUE(x) (x)
#define SGLIB___SET_VALUE(x, value) {(x) = (value);}
#define SGLIB_ARRAY_ELEMENTS_EXCHANGER(type, a, i, j) {type _sgl_aee_tmp_; _sgl_aee_tmp_=(a)[(i)]; (a)[(i)]=(a)[(j)]; (a)[(j)]= _sgl_aee_tmp_;}
-
#define SGLIB_SAFE_NUMERIC_COMPARATOR(x, y) (((x)>(y)?1:((x)<(y)?-1:0)))
#define SGLIB_SAFE_REVERSE_NUMERIC_COMPARATOR(x, y) (((x)>(y)?-1:((x)<(y)?1:0)))
#define SGLIB_FAST_NUMERIC_COMPARATOR(x, y) ((int)((x) - (y)))
@@ -2058,8 +2021,8 @@ void sglib___##type##_consistency_check(type *t) {\
#endif
#ifndef SGLIB_HASH_TAB_SHIFT_CONSTANT
-#define SGLIB_HASH_TAB_SHIFT_CONSTANT 16381 /* should be a prime */
-/* #define SGLIB_HASH_TAB_SHIFT_CONSTANT 536870912*/ /* for large tables :) */
+#define SGLIB_HASH_TAB_SHIFT_CONSTANT 16381 /* should be a prime */
+ /* #define SGLIB_HASH_TAB_SHIFT_CONSTANT 536870912 *//* for large tables :) */
#endif
#endif /* _SGLIB__h_ */
diff --git a/libvdev/util.c b/libvdev/util.c
index d2c99c9..41720be 100644
--- a/libvdev/util.c
+++ b/libvdev/util.c
@@ -18,7 +18,7 @@
For the terms of this license, see LICENSE.ISC or
.
*/
-
+
#include "util.h"
int _VDEV_DEBUG_MESSAGES = 0;
@@ -27,347 +27,405 @@ int _VDEV_WARN_MESSAGES = 1;
int _VDEV_ERROR_MESSAGES = 1;
int _VDEV_SYSLOG = 0;
-
// set debug level, by setting for info and debug messages
-void vdev_set_debug_level( int d ) {
-
- if( d >= 1 ) {
+void
+vdev_set_debug_level (int d)
+{
+
+ if (d >= 1)
+ {
_VDEV_INFO_MESSAGES = 1;
- }
- if( d >= 2 ) {
+ }
+ if (d >= 2)
+ {
_VDEV_DEBUG_MESSAGES = 1;
- }
+ }
}
// set error level, by setting for warning and error messages
-void vdev_set_error_level( int e ) {
-
- if( e >= 1 ) {
+void
+vdev_set_error_level (int e)
+{
+
+ if (e >= 1)
+ {
_VDEV_ERROR_MESSAGES = 1;
- }
- if( e >= 2 ) {
+ }
+ if (e >= 2)
+ {
_VDEV_WARN_MESSAGES = 1;
- }
+ }
}
// debug level is the sum of the levels enabled
-int vdev_get_debug_level() {
- return _VDEV_DEBUG_MESSAGES + _VDEV_INFO_MESSAGES;
+int
+vdev_get_debug_level ()
+{
+ return _VDEV_DEBUG_MESSAGES + _VDEV_INFO_MESSAGES;
}
// error level is the sum of the errors enable
-int vdev_get_error_level() {
- return _VDEV_ERROR_MESSAGES + _VDEV_WARN_MESSAGES;
+int
+vdev_get_error_level ()
+{
+ return _VDEV_ERROR_MESSAGES + _VDEV_WARN_MESSAGES;
}
// turn on syslog logging
// always succeeds
-int vdev_enable_syslog() {
-
- _VDEV_SYSLOG = 1;
- openlog( VDEV_SYSLOG_IDENT, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON );
-
- return 0;
+int
+vdev_enable_syslog ()
+{
+
+ _VDEV_SYSLOG = 1;
+ openlog (VDEV_SYSLOG_IDENT, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON);
+
+ return 0;
}
// become a daemon: fork, setsid, fork, umask
// return 0 on child
// return 1 on parent
// return -errno on failure to fork
-int vdev_daemonize(void) {
-
- int rc = 0;
- pid_t pid = 0;
-
- pid = fork();
- if( pid == 0 ) {
-
+int
+vdev_daemonize (void)
+{
+
+ int rc = 0;
+ pid_t pid = 0;
+
+ pid = fork ();
+ if (pid == 0)
+ {
+
// child--no tty
// become process group leader
- rc = setsid();
- if( rc < 0 ) {
-
- rc = -errno;
- vdev_error("setsid() rc = %d\n", rc );
- return rc;
- }
-
+ rc = setsid ();
+ if (rc < 0)
+ {
+
+ rc = -errno;
+ vdev_error ("setsid() rc = %d\n", rc);
+ return rc;
+ }
// fork again
// stop us from ever regaining the tty
- pid = fork();
- if( pid == 0 ) {
-
- // child
- // switch to /
- rc = chdir("/");
- if( rc != 0 ) {
-
- rc = -errno;
- vdev_error("chdir('/') rc = %d\n", rc );
- return rc;
- }
-
- // own everything we create
- umask(0);
-
- // now a daemon!
- return 0;
- }
- else if( pid > 0 ) {
-
- // parent--die, but don't call userspace clean-up
- _exit(0);
- }
- else {
-
- // failed to fork
- rc = -errno;
- vdev_error("fork( parent=%d ) rc = %d\n", getpid(), rc );
- return rc;
- }
- }
- else if( pid > 0 ) {
-
+ pid = fork ();
+ if (pid == 0)
+ {
+
+ // child
+ // switch to /
+ rc = chdir ("/");
+ if (rc != 0)
+ {
+
+ rc = -errno;
+ vdev_error ("chdir('/') rc = %d\n", rc);
+ return rc;
+ }
+ // own everything we create
+ umask (0);
+
+ // now a daemon!
+ return 0;
+ }
+ else if (pid > 0)
+ {
+
+ // parent--die, but don't call userspace clean-up
+ _exit (0);
+ }
+ else
+ {
+
+ // failed to fork
+ rc = -errno;
+ vdev_error ("fork( parent=%d ) rc = %d\n", getpid (), rc);
+ return rc;
+ }
+ }
+ else if (pid > 0)
+ {
+
// parent--we're done
return 1;
- }
- else {
-
+ }
+ else
+ {
+
// error
rc = -errno;
- vdev_error( "fork( parent=%d ) rc = %d\n", getpid(), rc );
+ vdev_error ("fork( parent=%d ) rc = %d\n", getpid (), rc);
return rc;
- }
+ }
}
-
// redirect stdout and stderr to a logfile
// return 0 on success
-int vdev_log_redirect( char const* logfile_path ) {
-
- int logfd = 0;
- int rc = 0;
- FILE* f = NULL;
-
- f = fopen( logfile_path, "a" );
- if( f == NULL ) {
-
+int
+vdev_log_redirect (char const *logfile_path)
+{
+
+ int logfd = 0;
+ int rc = 0;
+ FILE *f = NULL;
+
+ f = fopen (logfile_path, "a");
+ if (f == NULL)
+ {
+
rc = -errno;
- vdev_error("fopen('%s') rc = %d\n", logfile_path, rc );
+ vdev_error ("fopen('%s') rc = %d\n", logfile_path, rc);
return rc;
- }
-
- logfd = fileno(f);
-
- close( STDOUT_FILENO );
- close( STDERR_FILENO );
-
- rc = dup2( logfd, STDOUT_FILENO );
- if( rc < 0 ) {
-
+ }
+
+ logfd = fileno (f);
+
+ close (STDOUT_FILENO);
+ close (STDERR_FILENO);
+
+ rc = dup2 (logfd, STDOUT_FILENO);
+ if (rc < 0)
+ {
+
rc = -errno;
- vdev_error("dup2(STDOUT) rc = %d\n", rc );
+ vdev_error ("dup2(STDOUT) rc = %d\n", rc);
return rc;
- }
-
- rc = dup2( logfd, STDERR_FILENO );
- if( rc < 0 ) {
-
+ }
+
+ rc = dup2 (logfd, STDERR_FILENO);
+ if (rc < 0)
+ {
+
rc = -errno;
- vdev_error("dup2(STDERR) rc = %d\n", rc );
-
+ vdev_error ("dup2(STDERR) rc = %d\n", rc);
+
return rc;
- }
-
- fclose( f );
- logfd = -1;
-
- return 0;
-}
+ }
+
+ fclose (f);
+ logfd = -1;
+ return 0;
+}
// write a pidfile to a path
-int vdev_pidfile_write( char const* pidfile_path ) {
-
- char pidbuf[50];
- FILE* f = NULL;
- size_t nw = 0;
- int rc = 0;
-
- f = fopen( pidfile_path, "w+" );
- if( f == NULL ) {
-
+int
+vdev_pidfile_write (char const *pidfile_path)
+{
+
+ char pidbuf[50];
+ FILE *f = NULL;
+ size_t nw = 0;
+ int rc = 0;
+
+ f = fopen (pidfile_path, "w+");
+ if (f == NULL)
+ {
+
rc = -errno;
- vdev_error("fopen('%s') rc = %d\n", pidfile_path, rc );
+ vdev_error ("fopen('%s') rc = %d\n", pidfile_path, rc);
return rc;
- }
-
- memset( pidbuf, 0, 50 );
- sprintf( pidbuf, "%d\n", getpid() );
-
- rc = vdev_write_uninterrupted( fileno(f), pidbuf, strlen(pidbuf) + 1 );
-
- fclose( f );
-
- if( rc < 0 ) {
-
- vdev_error("vdev_write_uninterrupted('%d') rc = %d\n", getpid(), rc );
+ }
+
+ memset (pidbuf, 0, 50);
+ sprintf (pidbuf, "%d\n", getpid ());
+
+ rc = vdev_write_uninterrupted (fileno (f), pidbuf, strlen (pidbuf) + 1);
+
+ fclose (f);
+
+ if (rc < 0)
+ {
+
+ vdev_error ("vdev_write_uninterrupted('%d') rc = %d\n", getpid (), rc);
return rc;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// join two paths, writing the result to dest if dest is not NULL.
// otherwise, allocate and return a buffer containing the joined paths.
// return NULL on OOM
-char* vdev_fullpath( char const* root, char const* path, char* dest ) {
+char *
+vdev_fullpath (char const *root, char const *path, char *dest)
+{
- char delim = 0;
- int path_off = 0;
- int len = 0;
-
- if( root == NULL || path == NULL ) {
+ char delim = 0;
+ int path_off = 0;
+ int len = 0;
+
+ if (root == NULL || path == NULL)
+ {
return NULL;
- }
-
- len = strlen(path) + strlen(root) + 2;
-
- if( strlen(root) > 0 ) {
- size_t root_delim_off = strlen(root) - 1;
- if( root[root_delim_off] != '/' && path[0] != '/' ) {
- len++;
- delim = '/';
- }
- else if( root[root_delim_off] == '/' && path[0] == '/' ) {
- path_off = 1;
- }
- }
-
- if( dest == NULL ) {
- dest = VDEV_CALLOC( char, len );
- if( dest == NULL ) {
- return NULL;
- }
- }
-
- memset(dest, 0, len);
-
- strcpy( dest, root );
- if( delim != 0 ) {
- dest[strlen(dest)] = '/';
- }
- strcat( dest, path + path_off );
-
- return dest;
+ }
+
+ len = strlen (path) + strlen (root) + 2;
+
+ if (strlen (root) > 0)
+ {
+ size_t root_delim_off = strlen (root) - 1;
+ if (root[root_delim_off] != '/' && path[0] != '/')
+ {
+ len++;
+ delim = '/';
+ }
+ else if (root[root_delim_off] == '/' && path[0] == '/')
+ {
+ path_off = 1;
+ }
+ }
+
+ if (dest == NULL)
+ {
+ dest = VDEV_CALLOC (char, len);
+ if (dest == NULL)
+ {
+ return NULL;
+ }
+ }
+
+ memset (dest, 0, len);
+
+ strcpy (dest, root);
+ if (delim != 0)
+ {
+ dest[strlen (dest)] = '/';
+ }
+ strcat (dest, path + path_off);
+
+ return dest;
}
-
// get the directory name of a path.
// put it into dest if dest is not null.
// otherwise, allocate a buffer and return it.
// return NULL on OOM
-char* vdev_dirname( char const* path, char* dest ) {
-
- if( path == NULL ) {
+char *
+vdev_dirname (char const *path, char *dest)
+{
+
+ if (path == NULL)
+ {
return NULL;
- }
-
- if( dest == NULL ) {
- dest = VDEV_CALLOC( char, strlen(path) + 1 );
- if( dest == NULL ) {
- return NULL;
- }
- }
-
- // is this root?
- if( strlen(path) == 0 || strcmp( path, "/" ) == 0 ) {
- strcpy( dest, "/" );
+ }
+
+ if (dest == NULL)
+ {
+ dest = VDEV_CALLOC (char, strlen (path) + 1);
+ if (dest == NULL)
+ {
+ return NULL;
+ }
+ }
+ // is this root?
+ if (strlen (path) == 0 || strcmp (path, "/") == 0)
+ {
+ strcpy (dest, "/");
return dest;
- }
+ }
- int delim_i = strlen(path);
- if( path[delim_i] == '/' ) {
+ int delim_i = strlen (path);
+ if (path[delim_i] == '/')
+ {
delim_i--;
- }
-
- for( ; delim_i >= 0; delim_i-- ) {
- if( path[delim_i] == '/' ) {
- break;
- }
- }
-
- if( delim_i < 0 ) {
+ }
+
+ for (; delim_i >= 0; delim_i--)
+ {
+ if (path[delim_i] == '/')
+ {
+ break;
+ }
+ }
+
+ if (delim_i < 0)
+ {
delim_i = 0;
- }
+ }
- if( delim_i == 0 && path[0] == '/' ) {
+ if (delim_i == 0 && path[0] == '/')
+ {
delim_i = 1;
- }
+ }
- strncpy( dest, path, delim_i );
- dest[delim_i+1] = '\0';
- return dest;
+ strncpy (dest, path, delim_i);
+ dest[delim_i + 1] = '\0';
+ return dest;
}
// determine how long the basename of a path is
// return 0 if the length could not be determined
-size_t vdev_basename_len( char const* path ) {
-
- if( path == NULL ) {
+size_t
+vdev_basename_len (char const *path)
+{
+
+ if (path == NULL)
+ {
return 0;
- }
-
- int delim_i = strlen(path) - 1;
- if( delim_i <= 0 ) {
+ }
+
+ int delim_i = strlen (path) - 1;
+ if (delim_i <= 0)
+ {
return 0;
- }
- if( path[delim_i] == '/' ) {
+ }
+ if (path[delim_i] == '/')
+ {
// this path ends with '/', so skip over it if it isn't /
- if( delim_i > 0 ) {
- delim_i--;
- }
- }
- for( ; delim_i >= 0; delim_i-- ) {
- if( path[delim_i] == '/' ) {
- break;
- }
- }
- delim_i++;
-
- return strlen(path) - delim_i;
+ if (delim_i > 0)
+ {
+ delim_i--;
+ }
+ }
+ for (; delim_i >= 0; delim_i--)
+ {
+ if (path[delim_i] == '/')
+ {
+ break;
+ }
+ }
+ delim_i++;
+
+ return strlen (path) - delim_i;
}
-
// get the basename of a (non-directory) path.
// put it into dest, if dest is not null.
// otherwise, allocate a buffer with it and return the buffer
// return NULL on OOM, or if path is NULL
-char* vdev_basename( char const* path, char* dest ) {
+char *
+vdev_basename (char const *path, char *dest)
+{
+
+ size_t len = 0;
- size_t len = 0;
-
- if( path == NULL ) {
+ if (path == NULL)
+ {
return NULL;
- }
-
- len = vdev_basename_len( path );
-
- if( dest == NULL ) {
-
- dest = VDEV_CALLOC( char, len + 1 );
- if( dest == NULL ) {
-
- return NULL;
- }
- }
- else {
- memset( dest, 0, len + 1 );
- }
-
- strncpy( dest, path + strlen(path) - len, len );
- return dest;
+ }
+
+ len = vdev_basename_len (path);
+
+ if (dest == NULL)
+ {
+
+ dest = VDEV_CALLOC (char, len + 1);
+ if (dest == NULL)
+ {
+
+ return NULL;
+ }
+ }
+ else
+ {
+ memset (dest, 0, len + 1);
+ }
+
+ strncpy (dest, path + strlen (path) - len, len);
+ return dest;
}
// run a subprocess, optionally in the system shell.
@@ -378,508 +436,585 @@ char* vdev_basename( char const* path, char* dest ) {
// return 1 on output truncate
// return negative on error
// set the subprocess exit status in *exit_status
-int vdev_subprocess( char const* cmd, char* const env[], char** output, size_t max_output, int stderr_fd, int* exit_status, bool use_shell ) {
-
- int p[2];
- int rc = 0;
- pid_t pid = 0;
- int max_fd = 0;
- ssize_t nr = 0;
- size_t num_read = 0;
- int status = 0;
- bool alloced = false;
-
- if( cmd == NULL ) {
+int
+vdev_subprocess (char const *cmd, char *const env[], char **output,
+ size_t max_output, int stderr_fd, int *exit_status,
+ bool use_shell)
+{
+
+ int p[2];
+ int rc = 0;
+ pid_t pid = 0;
+ int max_fd = 0;
+ ssize_t nr = 0;
+ size_t num_read = 0;
+ int status = 0;
+ bool alloced = false;
+
+ if (cmd == NULL)
+ {
return -EINVAL;
- }
-
- // open the pipe
- rc = pipe( p );
- if( rc != 0 ) {
-
+ }
+ // open the pipe
+ rc = pipe (p);
+ if (rc != 0)
+ {
+
rc = -errno;
- vdev_error("pipe() rc = %d\n", rc );
+ vdev_error ("pipe() rc = %d\n", rc);
return rc;
- }
-
- max_fd = sysconf(_SC_OPEN_MAX);
-
- // fork the child
- pid = fork();
-
- if( pid == 0 ) {
-
+ }
+
+ max_fd = sysconf (_SC_OPEN_MAX);
+
+ // fork the child
+ pid = fork ();
+
+ if (pid == 0)
+ {
+
// send stdout to p[1]
- close( p[0] );
- rc = dup2( p[1], STDOUT_FILENO );
-
- if( rc < 0 ) {
-
- rc = errno;
- close( p[1] );
- exit(rc);
- }
+ close (p[0]);
+ rc = dup2 (p[1], STDOUT_FILENO);
+ if (rc < 0)
+ {
+
+ rc = errno;
+ close (p[1]);
+ exit (rc);
+ }
// optionally redirect stderr (or just close it)
- if( stderr_fd >= 0 ) {
- rc = dup2( stderr_fd, STDERR_FILENO );
- if( rc < 0 ) {
-
- rc = errno;
- close( p[1] );
- exit(rc);
- }
- }
-
+ if (stderr_fd >= 0)
+ {
+ rc = dup2 (stderr_fd, STDERR_FILENO);
+ if (rc < 0)
+ {
+
+ rc = errno;
+ close (p[1]);
+ exit (rc);
+ }
+ }
// close everything else but stdout and optionally stderr.
- for( int i = 0; i < max_fd; i++ ) {
-
- if( i != STDOUT_FILENO && i != stderr_fd ) {
- close( i );
- }
- }
-
+ for (int i = 0; i < max_fd; i++)
+ {
+
+ if (i != STDOUT_FILENO && i != stderr_fd)
+ {
+ close (i);
+ }
+ }
+
// run the command
- if( use_shell ) {
-
- if( env != NULL ) {
- rc = execle( "/bin/sh", "sh", "-c", cmd, (char*)0, env );
- }
- else {
-
- char** noenv = { NULL };
- rc = execle( "/bin/sh", "sh", "-c", cmd, (char*)0, noenv );
- }
- }
- else {
-
- if( env != NULL ) {
- rc = execle( cmd, cmd, (char*)0, env );
- }
- else {
-
- char** noenv = { NULL };
- rc = execle( cmd, cmd, (char*)0, noenv );
- }
- }
-
- if( rc != 0 ) {
-
- rc = errno;
- exit(rc);
- }
- else {
-
- // make gcc happy
- exit(0);
- }
- }
- else if( pid > 0 ) {
-
+ if (use_shell)
+ {
+
+ if (env != NULL)
+ {
+ rc = execle ("/bin/sh", "sh", "-c", cmd, (char *) 0, env);
+ }
+ else
+ {
+
+ char **noenv = { NULL };
+ rc = execle ("/bin/sh", "sh", "-c", cmd, (char *) 0, noenv);
+ }
+ }
+ else
+ {
+
+ if (env != NULL)
+ {
+ rc = execle (cmd, cmd, (char *) 0, env);
+ }
+ else
+ {
+
+ char **noenv = { NULL };
+ rc = execle (cmd, cmd, (char *) 0, noenv);
+ }
+ }
+
+ if (rc != 0)
+ {
+
+ rc = errno;
+ exit (rc);
+ }
+ else
+ {
+
+ // make gcc happy
+ exit (0);
+ }
+ }
+ else if (pid > 0)
+ {
+
// parent
- close(p[1]);
-
+ close (p[1]);
+
// allocate output
- if( output != NULL ) {
- if( *output == NULL && max_output > 0 ) {
-
- *output = VDEV_CALLOC( char, max_output );
- if( *output == NULL ) {
-
- // out of memory
- close( p[0] );
- return -ENOMEM;
- }
-
- alloced = true;
- }
- }
-
+ if (output != NULL)
+ {
+ if (*output == NULL && max_output > 0)
+ {
+
+ *output = VDEV_CALLOC (char, max_output);
+ if (*output == NULL)
+ {
+
+ // out of memory
+ close (p[0]);
+ return -ENOMEM;
+ }
+
+ alloced = true;
+ }
+ }
// get output
- if( output != NULL && *output != NULL && max_output > 0 ) {
-
- nr = vdev_read_uninterrupted( p[0], (*output) + num_read, max_output - num_read );
- if( nr < 0 ) {
-
- vdev_error("vdev_read_uninterrupted rc = %zd\n", nr );
- close( p[0] );
-
- if( alloced ) {
-
- free( *output );
- *output = NULL;
- }
- return nr;
- }
-
- num_read = nr;
- }
-
+ if (output != NULL && *output != NULL && max_output > 0)
+ {
+
+ nr = vdev_read_uninterrupted (p[0], (*output) + num_read,
+ max_output - num_read);
+ if (nr < 0)
+ {
+
+ vdev_error ("vdev_read_uninterrupted rc = %zd\n", nr);
+ close (p[0]);
+
+ if (alloced)
+ {
+
+ free (*output);
+ *output = NULL;
+ }
+ return nr;
+ }
+
+ num_read = nr;
+ }
// wait for child
- rc = waitpid( pid, &status, 0 );
- if( rc < 0 ) {
-
- rc = -errno;
- vdev_error("waitpid(%d) rc = %d\n", pid, rc );
-
- close( p[0] );
-
- if( alloced ) {
-
- free( *output );
- *output = NULL;
- }
-
- return rc;
- }
-
- if( WIFEXITED( status ) ) {
-
- *exit_status = WEXITSTATUS( status );
- }
- else if( WIFSIGNALED( status ) ) {
-
- vdev_error("WARN: command '%s' failed with signal %d\n", cmd, WTERMSIG( status ) );
- *exit_status = status;
- }
- else {
-
- // indicate start/stop
- *exit_status = -EPERM;
- }
-
- close( p[0] );
+ rc = waitpid (pid, &status, 0);
+ if (rc < 0)
+ {
+
+ rc = -errno;
+ vdev_error ("waitpid(%d) rc = %d\n", pid, rc);
+
+ close (p[0]);
+
+ if (alloced)
+ {
+
+ free (*output);
+ *output = NULL;
+ }
+
+ return rc;
+ }
+
+ if (WIFEXITED (status))
+ {
+
+ *exit_status = WEXITSTATUS (status);
+ }
+ else if (WIFSIGNALED (status))
+ {
+
+ vdev_error ("WARN: command '%s' failed with signal %d\n",
+ cmd, WTERMSIG (status));
+ *exit_status = status;
+ }
+ else
+ {
+
+ // indicate start/stop
+ *exit_status = -EPERM;
+ }
+
+ close (p[0]);
return 0;
- }
- else {
-
+ }
+ else
+ {
+
rc = -errno;
- vdev_error("fork() rc = %d\n", rc );
+ vdev_error ("fork() rc = %d\n", rc);
return rc;
- }
+ }
}
-
// write, but mask EINTR
// return number of bytes written on success
// return -errno on I/O error
-ssize_t vdev_write_uninterrupted( int fd, char const* buf, size_t len ) {
-
- ssize_t num_written = 0;
-
- if( buf == NULL ) {
+ssize_t
+vdev_write_uninterrupted (int fd, char const *buf, size_t len)
+{
+
+ ssize_t num_written = 0;
+
+ if (buf == NULL)
+ {
return -EINVAL;
- }
-
- while( (unsigned)num_written < len ) {
- ssize_t nw = write( fd, buf + num_written, len - num_written );
- if( nw < 0 ) {
-
- int errsv = -errno;
- if( errsv == -EINTR ) {
- continue;
- }
-
- return errsv;
- }
- if( nw == 0 ) {
- break;
- }
-
+ }
+
+ while ((unsigned) num_written < len)
+ {
+ ssize_t nw = write (fd, buf + num_written, len - num_written);
+ if (nw < 0)
+ {
+
+ int errsv = -errno;
+ if (errsv == -EINTR)
+ {
+ continue;
+ }
+
+ return errsv;
+ }
+ if (nw == 0)
+ {
+ break;
+ }
+
num_written += nw;
- }
-
- return num_written;
-}
+ }
+ return num_written;
+}
// read, but mask EINTR
// return number of bytes read on success
// return -errno on I/O error
-ssize_t vdev_read_uninterrupted( int fd, char* buf, size_t len ) {
-
- ssize_t num_read = 0;
-
- if( buf == NULL ) {
+ssize_t
+vdev_read_uninterrupted (int fd, char *buf, size_t len)
+{
+
+ ssize_t num_read = 0;
+
+ if (buf == NULL)
+ {
return -EINVAL;
- }
-
- while( (unsigned)num_read < len ) {
- ssize_t nr = read( fd, buf + num_read, len - num_read );
- if( nr < 0 ) {
-
- int errsv = -errno;
- if( errsv == -EINTR ) {
- continue;
- }
-
- return errsv;
- }
- if( nr == 0 ) {
- break;
- }
-
+ }
+
+ while ((unsigned) num_read < len)
+ {
+ ssize_t nr = read (fd, buf + num_read, len - num_read);
+ if (nr < 0)
+ {
+
+ int errsv = -errno;
+ if (errsv == -EINTR)
+ {
+ continue;
+ }
+
+ return errsv;
+ }
+ if (nr == 0)
+ {
+ break;
+ }
+
num_read += nr;
- }
-
- return num_read;
-}
+ }
+ return num_read;
+}
// read a whole file, masking EINTR
// return 0 on success, filling buf with up to len bytes
// return -errno on open or read errors
-int vdev_read_file( char const* path, char* buf, size_t len ) {
-
- int fd = 0;
- int rc = 0;
-
- if( path == NULL || buf == NULL ) {
+int
+vdev_read_file (char const *path, char *buf, size_t len)
+{
+
+ int fd = 0;
+ int rc = 0;
+
+ if (path == NULL || buf == NULL)
+ {
return -EINVAL;
- }
-
- fd = open( path, O_RDONLY );
- if( fd < 0 ) {
-
+ }
+
+ fd = open (path, O_RDONLY);
+ if (fd < 0)
+ {
+
rc = -errno;
- vdev_error("open('%s') rc = %d\n", path, rc );
+ vdev_error ("open('%s') rc = %d\n", path, rc);
return rc;
- }
-
- rc = vdev_read_uninterrupted( fd, buf, len );
- if( rc < 0 ) {
-
+ }
+
+ rc = vdev_read_uninterrupted (fd, buf, len);
+ if (rc < 0)
+ {
+
rc = -errno;
- vdev_error("vdev_read_uninterrupted('%s') rc = %d\n", path, rc );
-
- close( fd );
+ vdev_error ("vdev_read_uninterrupted('%s') rc = %d\n", path, rc);
+
+ close (fd);
return rc;
- }
-
- close( fd );
- return 0;
+ }
+
+ close (fd);
+ return 0;
}
// write a whole file, masking EINTR
// return 0 on success
// return -EINVAL if buf or path is null
// return -errno on failiure to open or write or fsync
-int vdev_write_file( char const* path, char const* buf, size_t len, int flags, mode_t mode ) {
-
- int fd = 0;
- int rc = 0;
-
- if( path == NULL || buf == NULL ) {
+int
+vdev_write_file (char const *path, char const *buf, size_t len, int flags,
+ mode_t mode)
+{
+
+ int fd = 0;
+ int rc = 0;
+
+ if (path == NULL || buf == NULL)
+ {
return -EINVAL;
- }
-
- fd = open( path, flags, mode );
- if( fd < 0 ) {
-
+ }
+
+ fd = open (path, flags, mode);
+ if (fd < 0)
+ {
+
rc = -errno;
- vdev_error("open('%s') rc = %d\n", path, rc );
+ vdev_error ("open('%s') rc = %d\n", path, rc);
return rc;
- }
-
- rc = vdev_write_uninterrupted( fd, buf, len );
- if( rc < 0 ) {
-
+ }
+
+ rc = vdev_write_uninterrupted (fd, buf, len);
+ if (rc < 0)
+ {
+
rc = -errno;
- vdev_error("vdev_write_uninterrupted('%s') rc = %d\n", path, rc );
-
- close( fd );
+ vdev_error ("vdev_write_uninterrupted('%s') rc = %d\n", path, rc);
+
+ close (fd);
return rc;
- }
-
- // NOTE: not much we can do if close() fails...
- close( fd );
-
- return rc;
-}
+ }
+ // NOTE: not much we can do if close() fails...
+ close (fd);
+ return rc;
+}
// free a list of dirents
// always succeeds
-static void vdev_dirents_free( struct dirent** dirents, int num_entries ) {
-
- if( dirents == NULL ) {
+static void
+vdev_dirents_free (struct dirent **dirents, int num_entries)
+{
+
+ if (dirents == NULL)
+ {
return;
- }
-
- for( int i = 0; i < num_entries; i++ ) {
-
- if( dirents[i] == NULL ) {
- continue;
- }
-
- free( dirents[i] );
+ }
+
+ for (int i = 0; i < num_entries; i++)
+ {
+
+ if (dirents[i] == NULL)
+ {
+ continue;
+ }
+
+ free (dirents[i]);
dirents[i] = NULL;
- }
-
- free( dirents );
-}
+ }
+ free (dirents);
+}
// portable scandirat() implementation--behaves as close to the Linux scandirat(3) interface as possible.
-int vdev_portable_scandirat( int dirfd, char const* dirp, struct dirent ***namelist, int (*filter)( const struct dirent* ), int (*compar)( const struct dirent**, const struct dirent** ) ) {
-
- int rc = 0;
-
- DIR* dirh = NULL;
- struct dirent next;
- struct dirent* result = NULL;
- struct dirent* next_dup = NULL;
- int dirp_fd = -1;
-
- struct dirent** namelist_buf = NULL;
- struct dirent** namelist_tmp = NULL;
- ssize_t num_dirents = 0;
- ssize_t num_dirents_capacity = 0;
-
- dirp_fd = openat( dirfd, dirp, O_DIRECTORY );
- if( dirp_fd < 0 ) {
-
+int
+vdev_portable_scandirat (int dirfd, char const *dirp,
+ struct dirent ***namelist,
+ int (*filter) (const struct dirent *),
+ int (*compar) (const struct dirent **,
+ const struct dirent **))
+{
+
+ int rc = 0;
+
+ DIR *dirh = NULL;
+ struct dirent next;
+ struct dirent *result = NULL;
+ struct dirent *next_dup = NULL;
+ int dirp_fd = -1;
+
+ struct dirent **namelist_buf = NULL;
+ struct dirent **namelist_tmp = NULL;
+ ssize_t num_dirents = 0;
+ ssize_t num_dirents_capacity = 0;
+
+ dirp_fd = openat (dirfd, dirp, O_DIRECTORY);
+ if (dirp_fd < 0)
+ {
+
rc = -errno;
return rc;
- }
-
- // open the duplicated handle instead
- dirh = fdopendir( dirp_fd );
- if( dirh == NULL ) {
-
+ }
+ // open the duplicated handle instead
+ dirh = fdopendir (dirp_fd);
+ if (dirh == NULL)
+ {
+
rc = -errno;
-
- close( dirp_fd );
+
+ close (dirp_fd);
return rc;
- }
-
- while( 1 ) {
-
+ }
+
+ while (1)
+ {
+
// next dirent
- rc = readdir_r( dirh, &next, &result );
-
+ rc = readdir_r (dirh, &next, &result);
+
// done?
- if( result == NULL ) {
- break;
- }
-
+ if (result == NULL)
+ {
+ break;
+ }
// error?
- if( rc != 0 ) {
-
- rc = -rc;
- break;
- }
-
+ if (rc != 0)
+ {
+
+ rc = -rc;
+ break;
+ }
// filter?
- if( filter != NULL ) {
-
- rc = (*filter)( &next );
- if( rc == 0 ) {
-
- // skip
- continue;
- }
- }
-
+ if (filter != NULL)
+ {
+
+ rc = (*filter) (&next);
+ if (rc == 0)
+ {
+
+ // skip
+ continue;
+ }
+ }
// increase (double) space?
- if( num_dirents >= num_dirents_capacity ) {
-
- if( num_dirents_capacity == 0 ) {
- num_dirents_capacity = 1;
- }
-
- num_dirents_capacity <<= 1;
-
- namelist_tmp = (struct dirent**)realloc( namelist_buf, (num_dirents_capacity + 1) * sizeof( struct dirent ) );
- if( namelist_tmp == NULL ) {
-
- // OOM
- rc = -ENOMEM;
- break;
- }
-
- namelist_buf = namelist_tmp;
- }
-
+ if (num_dirents >= num_dirents_capacity)
+ {
+
+ if (num_dirents_capacity == 0)
+ {
+ num_dirents_capacity = 1;
+ }
+
+ num_dirents_capacity <<= 1;
+
+ namelist_tmp =
+ (struct dirent **) realloc (namelist_buf,
+ (num_dirents_capacity +
+ 1) * sizeof (struct dirent));
+ if (namelist_tmp == NULL)
+ {
+
+ // OOM
+ rc = -ENOMEM;
+ break;
+ }
+
+ namelist_buf = namelist_tmp;
+ }
// duplicate
- next_dup = VDEV_CALLOC( struct dirent, 1 );
- if( next_dup == NULL ) {
-
- // OOM
- rc = -ENOMEM;
- break;
- }
-
- memcpy( next_dup, &next, sizeof( struct dirent ) );
-
+ next_dup = VDEV_CALLOC (struct dirent, 1);
+ if (next_dup == NULL)
+ {
+
+ // OOM
+ rc = -ENOMEM;
+ break;
+ }
+
+ memcpy (next_dup, &next, sizeof (struct dirent));
+
// insert
- namelist_buf[ num_dirents ] = next_dup;
- namelist_buf[ num_dirents+1 ] = NULL;
+ namelist_buf[num_dirents] = next_dup;
+ namelist_buf[num_dirents + 1] = NULL;
num_dirents++;
- }
-
- closedir( dirh );
-
- if( rc < 0 ) {
-
+ }
+
+ closedir (dirh);
+
+ if (rc < 0)
+ {
+
// error--clean up
- vdev_dirents_free( namelist_buf, num_dirents );
+ vdev_dirents_free (namelist_buf, num_dirents);
return rc;
- }
-
- // sort?
- if( compar != NULL ) {
-
- qsort( (void*)namelist_buf, num_dirents, sizeof(struct dirent*), (int (*)(const void*, const void*))compar );
- }
-
- // finished!
- *namelist = namelist_buf;
- return num_dirents;
+ }
+ // sort?
+ if (compar != NULL)
+ {
+
+ qsort ((void *) namelist_buf, num_dirents,
+ sizeof (struct dirent *),
+ (int (*)(const void *, const void *)) compar);
+ }
+ // finished!
+ *namelist = namelist_buf;
+ return num_dirents;
}
-
// process all files in a directory, given a descriptor to it. Search in alphanumeric order
// return 0 on success
// return -EINVAL if loader is NULL
// return -EBADF if dirfd is invalid
// return non-zero of loader_at returns non-zero
-int vdev_load_all_at( int dirfd, vdev_dirent_loader_at_t loader_at, void* cls ) {
-
- struct dirent** dirents = NULL;
- int num_entries = 0;
- int rc = 0;
-
- if( loader_at == NULL ) {
+int
+vdev_load_all_at (int dirfd, vdev_dirent_loader_at_t loader_at, void *cls)
+{
+
+ struct dirent **dirents = NULL;
+ int num_entries = 0;
+ int rc = 0;
+
+ if (loader_at == NULL)
+ {
return -EINVAL;
- }
-
- num_entries = vdev_portable_scandirat( dirfd, ".", &dirents, NULL, alphasort );
- if( num_entries < 0 ) {
-
+ }
+
+ num_entries =
+ vdev_portable_scandirat (dirfd, ".", &dirents, NULL, alphasort);
+ if (num_entries < 0)
+ {
+
rc = -errno;
- vdev_error("scandirat(%d) rc = %d\n", dirfd, rc );
+ vdev_error ("scandirat(%d) rc = %d\n", dirfd, rc);
return rc;
- }
-
- for( int i = 0; i < num_entries; i++ ) {
-
+ }
+
+ for (int i = 0; i < num_entries; i++)
+ {
+
// process this
- rc = (*loader_at)( dirfd, dirents[i], cls );
- if( rc != 0 ) {
-
- vdev_error("loader_at(%d, '%s') rc = %d\n", dirfd, dirents[i]->d_name, rc );
-
- vdev_dirents_free( dirents, num_entries );
- return rc;
- }
- }
-
- vdev_dirents_free( dirents, num_entries );
-
- return rc;
-}
+ rc = (*loader_at) (dirfd, dirents[i], cls);
+ if (rc != 0)
+ {
+
+ vdev_error ("loader_at(%d, '%s') rc = %d\n", dirfd,
+ dirents[i]->d_name, rc);
+ vdev_dirents_free (dirents, num_entries);
+ return rc;
+ }
+ }
+
+ vdev_dirents_free (dirents, num_entries);
+
+ return rc;
+}
// process all files in a directory with a loader, in alphanumeric order
// return 0 on success
@@ -887,242 +1022,272 @@ int vdev_load_all_at( int dirfd, vdev_dirent_loader_at_t loader_at, void* cls )
// return -ENOMEM if OOM
// return -errno on I/O error
// return non-zero if loader fails
-int vdev_load_all( char const* dir_path, vdev_dirent_loader_t loader, void* cls ) {
-
- struct dirent** dirents = NULL;
- int num_entries = 0;
- int rc = 0;
-
- if( dir_path == NULL || loader == NULL ) {
+int
+vdev_load_all (char const *dir_path, vdev_dirent_loader_t loader, void *cls)
+{
+
+ struct dirent **dirents = NULL;
+ int num_entries = 0;
+ int rc = 0;
+
+ if (dir_path == NULL || loader == NULL)
+ {
return -EINVAL;
- }
-
- num_entries = scandir( dir_path, &dirents, NULL, alphasort );
- if( num_entries < 0 ) {
-
+ }
+
+ num_entries = scandir (dir_path, &dirents, NULL, alphasort);
+ if (num_entries < 0)
+ {
+
rc = -errno;
- vdev_error("scandir('%s') rc = %d\n", dir_path, rc );
+ vdev_error ("scandir('%s') rc = %d\n", dir_path, rc);
return rc;
- }
-
- for( int i = 0; i < num_entries; i++ ) {
-
+ }
+
+ for (int i = 0; i < num_entries; i++)
+ {
+
// full path...
- char* fp = vdev_fullpath( dir_path, dirents[i]->d_name, NULL );
- if( fp == NULL ) {
-
- vdev_dirents_free( dirents, num_entries );
- return -ENOMEM;
- }
-
+ char *fp = vdev_fullpath (dir_path, dirents[i]->d_name, NULL);
+ if (fp == NULL)
+ {
+
+ vdev_dirents_free (dirents, num_entries);
+ return -ENOMEM;
+ }
// process this
- rc = (*loader)( fp, cls );
- if( rc != 0 ) {
-
- vdev_error("loader('%s') rc = %d\n", fp, rc );
-
- free( fp );
- vdev_dirents_free( dirents, num_entries );
- return rc;
- }
-
- free( fp );
- }
-
- vdev_dirents_free( dirents, num_entries );
-
- return 0;
-}
+ rc = (*loader) (fp, cls);
+ if (rc != 0)
+ {
+
+ vdev_error ("loader('%s') rc = %d\n", fp, rc);
+
+ free (fp);
+ vdev_dirents_free (dirents, num_entries);
+ return rc;
+ }
+
+ free (fp);
+ }
+
+ vdev_dirents_free (dirents, num_entries);
+ return 0;
+}
// make a string of directories, given the path dirp
// return 0 if the directory exists at the end of the call.
// return -EINVAL if dirp is NULL
// return -ENOMEM if OOM
// return negative if the directory could not be created.
-int vdev_mkdirs( char const* dirp, int start, mode_t mode ) {
-
- unsigned int i = start;
- char* currdir = NULL;
- struct stat statbuf;
- int rc = 0;
-
- if( dirp == NULL ) {
+int
+vdev_mkdirs (char const *dirp, int start, mode_t mode)
+{
+
+ unsigned int i = start;
+ char *currdir = NULL;
+ struct stat statbuf;
+ int rc = 0;
+
+ if (dirp == NULL)
+ {
return -EINVAL;
- }
-
- currdir = VDEV_CALLOC( char, strlen(dirp) + 1 );
- if( currdir == NULL ) {
+ }
+
+ currdir = VDEV_CALLOC (char, strlen (dirp) + 1);
+ if (currdir == NULL)
+ {
return -ENOMEM;
- }
-
- while( i <= strlen(dirp) ) {
-
+ }
+
+ while (i <= strlen (dirp))
+ {
+
// next '/'
- if( dirp[i] == '/' || i == strlen(dirp) ) {
-
- strncpy( currdir, dirp, i == 0 ? 1 : i );
-
- rc = stat( currdir, &statbuf );
- if( rc == 0 && !S_ISDIR( statbuf.st_mode ) ) {
-
- // something else exists here
- free( currdir );
- return -ENOTDIR;
- }
-
- if( rc != 0 ) {
-
- // try to make this directory
- rc = mkdir( currdir, mode );
- if( rc != 0 ) {
-
- rc = -errno;
- free(currdir);
- return rc;
- }
- }
- }
-
+ if (dirp[i] == '/' || i == strlen (dirp))
+ {
+
+ strncpy (currdir, dirp, i == 0 ? 1 : i);
+
+ rc = stat (currdir, &statbuf);
+ if (rc == 0 && !S_ISDIR (statbuf.st_mode))
+ {
+
+ // something else exists here
+ free (currdir);
+ return -ENOTDIR;
+ }
+
+ if (rc != 0)
+ {
+
+ // try to make this directory
+ rc = mkdir (currdir, mode);
+ if (rc != 0)
+ {
+
+ rc = -errno;
+ free (currdir);
+ return rc;
+ }
+ }
+ }
+
i++;
- }
-
- free(currdir);
- return 0;
-}
+ }
+ free (currdir);
+ return 0;
+}
// try to remove a path of directories
// the must all be emtpy
// return 0 on success
// return negative on error
-int vdev_rmdirs( char const* dirp ) {
-
- char* dirname = NULL;
- int rc = 0;
-
- if( dirp == NULL ) {
+int
+vdev_rmdirs (char const *dirp)
+{
+
+ char *dirname = NULL;
+ int rc = 0;
+
+ if (dirp == NULL)
+ {
return -EINVAL;
- }
-
- dirname = strdup( dirp );
-
- while( strlen(dirname) > 0 ) {
-
- rc = rmdir( dirname );
-
- if( rc != 0 ) {
-
- rc = -errno;
- break;
- }
- else {
-
- char* tmp = vdev_dirname( dirname, NULL );
- if( tmp == NULL ) {
- return -ENOMEM;
- }
-
- free( dirname );
-
- dirname = tmp;
- }
- }
-
- free( dirname );
- return rc;
-}
+ }
+
+ dirname = strdup (dirp);
+
+ while (strlen (dirname) > 0)
+ {
+
+ rc = rmdir (dirname);
+
+ if (rc != 0)
+ {
+
+ rc = -errno;
+ break;
+ }
+ else
+ {
+
+ char *tmp = vdev_dirname (dirname, NULL);
+ if (tmp == NULL)
+ {
+ return -ENOMEM;
+ }
+
+ free (dirname);
+ dirname = tmp;
+ }
+ }
+
+ free (dirname);
+ return rc;
+}
// parse an unsigned 64-bit number
// uint64_str must contain *only* the text of the number
// return the number, and set *success to true if we succeeded
// return -EINVAL if any of hte arguments were NULL
// return 0, LLONG_MAX, or LLONG_MIN if we failed
-uint64_t vdev_parse_uint64( char const* uint64_str, bool* success ) {
-
- if( uint64_str == NULL || success == NULL ) {
+uint64_t
+vdev_parse_uint64 (char const *uint64_str, bool * success)
+{
+
+ if (uint64_str == NULL || success == NULL)
+ {
return -EINVAL;
- }
-
- char* tmp = NULL;
- uint64_t uid = (uint64_t)strtoll( uint64_str, &tmp, 10 );
-
- if( tmp == uint64_str ) {
+ }
+
+ char *tmp = NULL;
+ uint64_t uid = (uint64_t) strtoll (uint64_str, &tmp, 10);
+
+ if (tmp == uint64_str)
+ {
*success = false;
- }
- else {
+ }
+ else
+ {
*success = true;
- }
-
- return uid;
-}
+ }
+ return uid;
+}
// given a null-terminated key=value string, chomp it into a null-terminated key and value.
// return the original length of the string.
// return -EINVAL if any argument is NULL
// return negative on error
-int vdev_keyvalue_next( char* keyvalue, char** key, char** value ) {
-
- if( keyvalue == NULL || key == NULL || value == NULL ) {
+int
+vdev_keyvalue_next (char *keyvalue, char **key, char **value)
+{
+
+ if (keyvalue == NULL || key == NULL || value == NULL)
+ {
return -EINVAL;
- }
-
- int ret = strlen(keyvalue);
- char* tmp = NULL;
-
- // find the '='
- tmp = strchr(keyvalue, '=');
- if( tmp == NULL ) {
-
+ }
+
+ int ret = strlen (keyvalue);
+ char *tmp = NULL;
+
+ // find the '='
+ tmp = strchr (keyvalue, '=');
+ if (tmp == NULL)
+ {
+
return -EINVAL;
- }
-
- *key = keyvalue;
- *tmp = '\0';
- tmp++;
-
- *value = tmp;
-
- return ret;
-}
+ }
+ *key = keyvalue;
+ *tmp = '\0';
+ tmp++;
+
+ *value = tmp;
+
+ return ret;
+}
// set up the library
// always succeeds
-void vdev_setup_global(void) {
-
- // seed random from monotonic clock
- struct timespec ts_mono;
- struct timespec ts_clock;
- int rc = 0;
- unsigned short seedv[3];
- int32_t lower_32;
-
- clock_gettime( CLOCK_MONOTONIC, &ts_mono );
- clock_gettime( CLOCK_REALTIME, &ts_clock );
-
- // NOTE: it's okay to use uninitialized memory for the random seed,
- // so we don't really care if clock_gettime fails
-
- lower_32 = ts_mono.tv_nsec + ts_clock.tv_nsec;
- memcpy( seedv, &lower_32, 3 );
-
- seed48( seedv );
-}
+void
+vdev_setup_global (void)
+{
+
+ // seed random from monotonic clock
+ struct timespec ts_mono;
+ struct timespec ts_clock;
+ int rc = 0;
+ unsigned short seedv[3];
+ int32_t lower_32;
+
+ clock_gettime (CLOCK_MONOTONIC, &ts_mono);
+ clock_gettime (CLOCK_REALTIME, &ts_clock);
+ // NOTE: it's okay to use uninitialized memory for the random seed,
+ // so we don't really care if clock_gettime fails
+
+ lower_32 = ts_mono.tv_nsec + ts_clock.tv_nsec;
+ memcpy (seedv, &lower_32, 3);
+
+ seed48 (seedv);
+}
// portable cast pthread_t to uint64_t
-unsigned long long int vdev_pthread_self(void) {
-
- union {
- pthread_t t;
- uint64_t i;
- } vdev_pthread;
-
- vdev_pthread.i = 0;
- vdev_pthread.t = pthread_self();
-
- return vdev_pthread.i;
+unsigned long long int
+vdev_pthread_self (void)
+{
+
+ union
+ {
+ pthread_t t;
+ uint64_t i;
+ } vdev_pthread;
+
+ vdev_pthread.i = 0;
+ vdev_pthread.t = pthread_self ();
+
+ return vdev_pthread.i;
}
diff --git a/libvdev/util.h b/libvdev/util.h
index 52a05f1..2c45d50 100644
--- a/libvdev/util.h
+++ b/libvdev/util.h
@@ -24,11 +24,11 @@
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
-#endif
+#endif
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 700
-#endif
+#endif
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
@@ -90,30 +90,28 @@ extern int _VDEV_SYSLOG;
#define vdev_debug( format, ... ) \
do { \
- if( _VDEV_DEBUG_MESSAGES ) { \
- if( _VDEV_SYSLOG ) { \
- syslog( LOG_DAEMON | LOG_DEBUG, format, __VA_ARGS__ ); \
- } \
- else { \
- fprintf(stderr, VDEV_WHERESTR "DEBUG: " format, VDEV_WHEREARG, __VA_ARGS__ ); fflush(stderr);\
- } \
- } \
+ if( _VDEV_DEBUG_MESSAGES ) { \
+ if( _VDEV_SYSLOG ) { \
+ syslog( LOG_DAEMON | LOG_DEBUG, format, __VA_ARGS__ ); \
+ } \
+ else { \
+ fprintf(stderr, VDEV_WHERESTR "DEBUG: " format, VDEV_WHEREARG, __VA_ARGS__ ); fflush(stderr); \
+ } \
+ } \
} while(0)
-
-#define vdev_info( format, ... ) \
- do { \
+#define vdev_info( format, ... ) \
+ do { \
if( _VDEV_INFO_MESSAGES ) { \
- if( _VDEV_SYSLOG ) { \
- syslog( LOG_DAEMON | LOG_INFO, format, __VA_ARGS__ ); \
- } \
- else { \
- fprintf(stderr, VDEV_WHERESTR "INFO: " format, VDEV_WHEREARG, __VA_ARGS__ ); fflush(stderr);\
+ if( _VDEV_SYSLOG ) { \
+ syslog( LOG_DAEMON | LOG_INFO, format, __VA_ARGS__ ); \
} \
- } \
- } while(0)
+ else { \
+ fprintf(stderr, VDEV_WHERESTR "INFO: " format, VDEV_WHEREARG, __VA_ARGS__ ); fflush(stderr); \
+ } \
+ } \
+ } while(0)
-
#define vdev_warn( format, ... ) \
do { \
if( _VDEV_WARN_MESSAGES ) { \
@@ -124,9 +122,8 @@ extern int _VDEV_SYSLOG;
fprintf(stderr, VDEV_WHERESTR "WARN: " format, VDEV_WHEREARG, __VA_ARGS__); fflush(stderr);\
} \
} \
- } while(0)
+ } while(0)
-
#define vdev_error( format, ... ) \
do { \
if( _VDEV_ERROR_MESSAGES ) { \
@@ -138,15 +135,14 @@ extern int _VDEV_SYSLOG;
} \
} \
} while(0)
-
-
+
#define vdev_error_async_safe( msg ) \
do { \
if( _VDEV_ERROR_MESSAGES ) { \
write( STDERR_FILENO, "[vdev error async] " msg, strlen( "[vdev error async] " msg ) ); \
} \
} while(0)
-
+
#define VDEV_CALLOC(type, count) (type*)calloc( sizeof(type) * (count), 1 )
#define VDEV_FREE_LIST(list) do { if( (list) != NULL ) { for(unsigned int __i = 0; (list)[__i] != NULL; ++ __i) { if( (list)[__i] != NULL ) { free( (list)[__i] ); (list)[__i] = NULL; }} free( (list) ); } } while(0)
#define VDEV_SIZE_LIST(sz, list) for( *(sz) = 0; (list)[*(sz)] != NULL; ++ *(sz) );
@@ -158,62 +154,65 @@ extern int _VDEV_SYSLOG;
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#endif
-#ifndef MIN
+#ifndef MIN
#define MIN(x,y) ((x) < (y) ? (x) : (y))
-#endif
+#endif
#ifdef __cplusplus
#define C_LINKAGE_BEGIN extern "C" {
#define C_LINKAGE_END }
#else
-#define C_LINKAGE_BEGIN
+#define C_LINKAGE_BEGIN
#define C_LINKAGE_END
-#endif
+#endif
-typedef int (*vdev_dirent_loader_t)( char const*, void* );
-typedef int (*vdev_dirent_loader_at_t)( int, struct dirent* dent, void* );
+typedef int (*vdev_dirent_loader_t) (char const *, void *);
+typedef int (*vdev_dirent_loader_at_t) (int, struct dirent * dent, void *);
C_LINKAGE_BEGIN
-
// debug functions
-void vdev_set_debug_level( int d );
-void vdev_set_error_level( int e );
-int vdev_get_debug_level();
-int vdev_get_error_level();
-int vdev_enable_syslog();
+void vdev_set_debug_level (int d);
+void vdev_set_error_level (int e);
+int vdev_get_debug_level ();
+int vdev_get_error_level ();
+int vdev_enable_syslog ();
// system functions
-int vdev_daemonize( void );
-int vdev_subprocess( char const* cmd, char* const env[], char** output, size_t max_output, int stderr_fd, int* exit_status, bool use_shell );
-int vdev_log_redirect( char const* logfile_path );
-int vdev_pidfile_write( char const* pidfile_path );
+int vdev_daemonize (void);
+int vdev_subprocess (char const *cmd, char *const env[], char **output,
+ size_t max_output, int stderr_fd, int *exit_status,
+ bool use_shell);
+int vdev_log_redirect (char const *logfile_path);
+int vdev_pidfile_write (char const *pidfile_path);
// parser functions
-int vdev_keyvalue_next( char* keyvalue, char** key, char** value );
-uint64_t vdev_parse_uint64( char const* uint64_str, bool* success );
+int vdev_keyvalue_next (char *keyvalue, char **key, char **value);
+uint64_t vdev_parse_uint64 (char const *uint64_str, bool * success);
// I/O functions
-ssize_t vdev_read_uninterrupted( int fd, char* buf, size_t len );
-ssize_t vdev_write_uninterrupted( int fd, char const* buf, size_t len );
-int vdev_read_file( char const* path, char* buf, size_t len );
-int vdev_write_file( char const* path, char const* buf, size_t len, int flags, mode_t mode );
+ssize_t vdev_read_uninterrupted (int fd, char *buf, size_t len);
+ssize_t vdev_write_uninterrupted (int fd, char const *buf, size_t len);
+int vdev_read_file (char const *path, char *buf, size_t len);
+int vdev_write_file (char const *path, char const *buf, size_t len, int flags,
+ mode_t mode);
// directory I/O
-int vdev_load_all( char const* dir_path, vdev_dirent_loader_t loader, void* cls );
-int vdev_load_all_at( int dirfd, vdev_dirent_loader_at_t loader_at, void* cls );
-int vdev_mkdirs( char const* dirp, int start, mode_t mode );
-int vdev_rmdirs( char const* dirp );
+int vdev_load_all (char const *dir_path, vdev_dirent_loader_t loader,
+ void *cls);
+int vdev_load_all_at (int dirfd, vdev_dirent_loader_at_t loader_at,
+ void *cls);
+int vdev_mkdirs (char const *dirp, int start, mode_t mode);
+int vdev_rmdirs (char const *dirp);
// misc
-char* vdev_fullpath( char const* root, char const* path, char* dest );
-char* vdev_dirname( char const* path, char* dest );
-size_t vdev_basename_len( char const* path );
-char* vdev_basename( char const* path, char* dest );
-unsigned long long int vdev_pthread_self(void);
+char *vdev_fullpath (char const *root, char const *path, char *dest);
+char *vdev_dirname (char const *path, char *dest);
+size_t vdev_basename_len (char const *path);
+char *vdev_basename (char const *path, char *dest);
+unsigned long long int vdev_pthread_self (void);
// setup
-void vdev_setup_global(void);
+void vdev_setup_global (void);
C_LINKAGE_END
-
#endif
diff --git a/tools/MAKEDEV.sh b/tools/MAKEDEV.sh
new file mode 100755
index 0000000..afdd663
--- /dev/null
+++ b/tools/MAKEDEV.sh
@@ -0,0 +1,2298 @@
+#! /bin/sh -
+
+# snap shot from debian i386 source August 2016
+
+#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
+# Customisation:
+# The devices fall into various classes. This section contains the mapping
+# from a class name into a group name and permission.
+# You will almost certainly need to edit the group name to match your
+# system, and you may change the permissions to suit your preference. These
+# lines _must_ be of the format "user group perm".
+#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
+
+public=" root root 0666"
+private=" root root 0600"
+system=" root root 0660"
+kmem=" root kmem 0640"
+tty=" root tty 0666"
+cons=" root tty 0600"
+dialout=" root dialout 0660"
+dip=" root dip 0660"
+mouse=" root root 0660"
+printer=" root lp 0660"
+floppy=" root floppy 0660"
+disk=" root disk 0660"
+scsi=" root root 0600"
+cdrom=" root cdrom 0660"
+tape=" root tape 0660"
+audio=" root audio 0660"
+video=" root video 0660"
+ibcs2=" root root 0666"
+scanner=" root root 0666"
+coda=" root root 0600"
+ipsec=" root root 0200"
+readable=" root root 0444"
+lirc=" root video 0640"
+
+MAXVT=63
+
+# defaults for $major_*
+major_ide0=3
+major_ide1=22
+major_sd=8
+major_lp=6
+
+# Remark: OSS/Linux becomes major_OSSLinux
+# NON default #---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
+
+# for exploration and testing
+testdir="test_devices"
+RUNAT=$(pwd)
+
+warning(){
+ # function to warn about spontaneous device creation.
+ # the intent here is as for the warning text and no more.
+ # This is not a manual page
+
+ cat < here
+ clear
+ export noloops=seen
+ ;;
+ No | n | N | no | nup | stop | halt | bail)
+ echo "Avoiding a potential mess"
+ echo "Probably a wise move"
+ exit 0
+ ;;
+ *)
+ clear
+ echo "$AFFIRM is an unforseen response"
+ sleep 2
+ echo "Leaving you to think about \"$AFFIRM\"."
+ exit 1
+ ;;
+esac
+
+return 0
+}
+
+
+if [ $@ ]; then
+ # this script calls itself possibly many times
+ # this test avoids ever hitting
+ # the warning guff when called with purpose
+ echo "$0 attempting $@"
+ : #true pass
+elif [ $noloops ]; then
+ # echo "seen this before"
+ export noloops=seen
+ : #true pass
+elif [ "${RUNAT}" != "/dev" ] || [ "$(basename ${RUNAT})" != "$testdir" ] ; then
+ warning
+else
+ noloops=seenandset
+fi
+
+#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
+# try to do the right things if udev is running
+#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
+if [ "$WRITE_ON_UDEV" ]; then
+ :
+elif [ -d /dev/.static/dev/ ] && [ "`pwd`" = /dev ] && [ -e /proc/mounts ] \
+ && grep -qE '^[^ ]+ /dev/\.static/dev' /proc/mounts; then
+ echo "udev active, devices will be created in /dev/.static/dev/"
+ cd /dev/.static/dev/
+elif [ -d /.dev/ ] && [ "`pwd`" = /dev ] && [ -e /proc/mounts ] \
+ && grep -qE '^[^ ]+ /\.dev' /proc/mounts; then
+ echo "udev active, devices will be created in /.dev/"
+ cd /.dev/
+elif [ -d /run/udev -o -d .udevdb/ -o -d .udev/ ] && [ "`pwd`" = /dev ]; then
+ echo "/run/udev or .udevdb or .udev presence implies active udev. Aborting MAKEDEV invocation."
+ # use exit 0, not 1, so postinst scripts don't fail on this
+ exit 0
+fi
+
+#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
+# don't stomp on devfs users
+#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
+if [ -c .devfsd ]
+then
+ echo ".devfsd presence implies active DevFS. Aborting MAKEDEV invocation."
+ # use exit 0, not 1, so postinst scripts don't fail on this
+ exit 0
+fi
+
+#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
+# don't stomp on non-Linux users
+#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
+if [ "$(uname -s)" != "Linux" ]
+then
+ echo "Results undefined on non-Linux systems, aborting MAKEDEV invocation."
+ # use exit 0, not 1, so postinst scripts don't fail on this
+ exit 0
+fi
+
+#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
+
+procfs=/proc
+
+opt_v=
+opt_d=
+opt_n=
+
+while [ $# -ge 1 ]
+do
+ case $1 in
+ --) shift; break ;;
+ -v) shift; opt_v=1 ;;
+ -d) shift; opt_d=1 ;;
+ -n) shift; opt_n=1; opt_v=1 ;;
+ -V) shift; opt_V=1 ;;
+ -*) echo "$0: unknown flag \"$1\"" >&2; exit 1 ;;
+ *) break ;;
+ esac
+done
+
+if [ "$opt_V" ]
+then
+ echo "This was Devuan | Debian MAKEDEV."
+ echo "For version info, try 'dpkg --list makedev'"
+ echo "See /usr/share/doc/makedev/ for more information on Devuan MAKEDEV."
+ exit 0
+fi
+
+opts="${opt_n:+-n} ${opt_v:+-v} ${opt_d:+-d}"
+
+#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
+#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
+
+devicename () { # translate device names to something safe
+ # A-Z is not full alphabet in all locales (e.g. in et_EE)
+ echo "$*" | LC_ALL=C sed -e 's/[^A-Za-z0-9_]/_/g'
+}
+
+makedev () { # usage: makedev name [bcu] major minor owner group mode
+ if [ "$opt_v" ]
+ then if [ "$opt_d" ]
+ then echo "delete $1"
+ else echo "create $1 $2 $3 $4 $5:$6 $7"
+ fi
+ fi
+ # missing parameters are a bug - bail - should we do an exit 1 here?
+ case :$1:$2:$3:$4:$5:$6:$7: in
+ *::*) echo "Warning: MAKEDEV $@ is missing parameter(s)." >&2;;
+ esac
+ if [ ! "$opt_n" ]
+ then
+ if [ "$opt_d" ]
+ then
+ rm -f $1
+ else
+ rm -f $1-
+ if mknod $1- $2 $3 $4 &&
+ chown $5:$6 $1- &&
+ chmod $7 $1- &&
+ mv $1- $1
+ then
+ : # it worked
+ else
+ # Didn't work, clean up any mess...
+ echo "makedev $@: failed"
+ rm -f $1-
+ fi
+ fi
+ fi
+}
+makefifo () { # usage: makefifo name owner group mode
+ if [ "$opt_v" ]
+ then if [ "$opt_d" ]
+ then echo "delete $1"
+ else echo "create $1 $2:$3 $4"
+ fi
+ fi
+ # missing parameters are a bug - bail - should we do an exit 1 here?
+ case :$1:$2:$3:$4: in
+ *::*) echo "Warning: MAKEFIFO $@ is missing parameter(s)." >&2;;
+ esac
+ if [ ! "$opt_n" ]
+ then
+ if [ "$opt_d" ]
+ then
+ rm -f $1
+ else
+ rm -f $1-
+ if mknod $1- p &&
+ chown $2:$3 $1- &&
+ chmod $4 $1- &&
+ mv $1- $1
+ then
+ : # it worked
+ else
+ # Didn't work, clean up any mess...
+ echo "makefifo $@: failed"
+ rm -f $1-
+ fi
+ fi
+ fi
+}
+symlink () { # usage: symlink name target
+ if [ "$opt_v" ]
+ then if [ "$opt_d" ]
+ then echo "delete $1"
+ else echo "create $1 -> $2"
+ fi
+ fi
+ [ ! "$opt_n" ] && rm -f $1 &&
+ [ ! "$opt_d" ] && ln -s $2 $1
+}
+
+#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
+
+# Debian allows us to assume /bin/sh is a POSIX compliant shell, so go for it!
+
+math () {
+ eval echo "\$(($*))"
+}
+index () { # index string c
+ eval "I=\${1%$2*}"
+ eval echo "\${#I}"
+}
+suffix () {
+ eval echo "\${1#$2}"
+}
+strip () {
+ eval echo "\${1% $2 *} \${1#* $2 }"
+}
+first () {
+ echo "${1%%?}"
+}
+second () {
+ echo "${1##?}"
+}
+substr () {
+ echo $1 | dd bs=1 count=1 skip=$(( $2 - 1 )) 2> /dev/null
+}
+
+#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
+
+devices=
+if [ ! -f $procfs/devices ]
+then
+ echo "$0: warning: can't read $procfs/devices" >&2
+else
+ exec 3<$procfs/devices
+ while read major device extra <&3
+ do
+ device=`echo $device | sed 's#/.*##'`
+ case "$major" in
+ Character|Block|'')
+ ;;
+ *)
+ safedevname=`devicename $device`
+ eval "major_$safedevname=$major"
+ devices="$devices $device"
+ ;;
+ esac
+ done
+ exec 3<&-
+fi
+
+Major () {
+ device=$2
+ devname=`devicename $1`
+ if [ "$opt_d" ]
+ then
+ echo -1 # don't care
+ else
+ eval echo \${major_$devname:-\${device:?\"unknown major number for $1\"}}
+ fi
+}
+
+cvt () {
+ while [ $# -ne 0 ]
+ do
+ case "$1" in
+ mem|tty|ttyp|cua|cub|cui) ;;
+ hd) (for d in a b c d e f g h i j k l m n o p ; do
+ echo -n hd$d " "
+ done) ; echo
+ ;;
+ ide0) echo hda hdb ;;
+ ide1) echo hdc hdd ;;
+ ide2) echo hde hdf ;;
+ ide3) echo hdg hdh ;;
+ ide4) echo hdi hdj ;;
+ ide5) echo hdk hdl ;;
+ ide6) echo hdm hdn ;;
+ ide7) echo hdo hdp ;;
+ ide8) echo hdq hdr ;;
+ ide9) echo hds hdt ;;
+ sd) (for d in a b c d e f g h i j k l m n o p ; do
+ echo -n sd$d " "
+ done) ; echo
+ ;;
+ dasd) (for d in a b c d e f g h i j k l m \
+ n o p q r s t u v w x y z ; do
+ echo -n dasd$d " "
+ done) ; echo
+ ;;
+ raw) echo raw ;;
+ sg) echo sg ;;
+ sr) echo scd ;;
+ st) echo st0 ;;
+ xd) echo xda xdb ;;
+ ad) echo ada adb ;;
+ lp) echo lp ;;
+ mt) echo ftape ;;
+ qft) echo ftape ;;
+ loop) echo loop ;;
+ md) echo md ;;
+ ibcs2) echo ibcs2 ;;
+ tpqic02) echo qic ;;
+ sound) echo audio ;;
+ logiscan) echo logiscan ;;
+ ac4096) echo ac4096 ;;
+ hw) echo helloworld ;; # cute
+ sbpcd | sbpcd[123]) echo $1 ;;
+ joystick) echo js ;;
+ input) echo input ;;
+ apm_bios) echo apm ;;
+ dcf) echo dcf ;;
+ aztcd) echo aztcd ;;
+ cm206cd) echo cm206cd ;;
+ gscd) echo gscd ;;
+ pcmcia) ;; # taken care of by its own driver
+ ttyC) echo cyclades ;;
+ isdn) echo isdnmodem isdnbri dcbri ;;
+ vcs) ;; # ummm ?
+ pty) echo pty ;;
+ misc) echo misc ;;
+ 3dfx) echo 3dfx ;;
+ agpgart) echo agpgart ;;
+ microcode) echo microcode ;;
+ ipmi|ipmikcs) echo ipmi ;;
+ fb) echo fb ;;
+ nb|drbd) echo nb0 nb1 nb2 nb3 nb4 nb5 nb6 nb7;;
+ netlink) echo netlink ;;
+ tap) echo netlink ;;
+ hamradio) echo hamradio ;;
+ snd) ;;
+ ptm) ;;
+ pts) ;;
+ ttyB) (for l in 0 1 2 3 4 5 6 7 ; do
+ echo -n ttyB$l " "
+ done) ; echo
+ ;;
+ ttyS) echo ttyS0 ttyS1 ttyS2 ttyS3 ttyS4 ;;
+ ttyI) echo ttyI0 ttyI1 ttyI2 ttyI3 ;;
+ ircomm|irlpt) irda ;;
+ ppp) echo ppp ;;
+ usb) echo usb ;;
+ dpt_i2o) echo dpti ;;
+ bluetooth) echo bluetooth ;;
+ lvm) ;; # taken care of by LVM userspace tools
+ ramdisk) echo ram ;;
+ null) echo std ;;
+ zero) echo std ;;
+ *) echo $1
+ esac
+ shift
+ done
+}
+
+for arg in `cvt $*`
+do
+ # this is to make the case patterns work as expected in all locales
+ LC_ALL=C
+ case $arg in
+ generic)
+ # pick the right generic- using dpkg's knowledge
+ case `dpkg --print-architecture` in
+ alpha)
+ $0 $opts generic-alpha
+ ;;
+ arm|armeb|armel)
+ $0 $opts generic-arm
+ ;;
+ hppa)
+ $0 $opts generic-hppa
+ ;;
+ i386|lpia)
+ $0 $opts generic-i386
+ ;;
+ amd64)
+ $0 $opts generic-i386
+ ;;
+ ia64)
+ $0 $opts generic-ia64
+ ;;
+ m68k)
+ $0 $opts generic-m68k
+ ;;
+ mips)
+ $0 $opts generic-mips
+ ;;
+ mipsel)
+ $0 $opts generic-mipsel
+ ;;
+ powerpc)
+ $0 $opts generic-powerpc
+ ;;
+ ppc64)
+ $0 $opts generic-powerpc
+ ;;
+ s390)
+ $0 $opts generic-s390
+ ;;
+ sh*)
+ $0 $opts generic-sh
+ ;;
+ sparc)
+ $0 $opts generic-sparc
+ ;;
+ *)
+ echo "$0: no support for generic on this arch" >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ generic-alpha)
+ $0 $opts std
+ $0 $opts fd
+ $0 $opts fd0 fd1
+ $0 $opts hd sd
+ $0 $opts xda xdb
+ $0 $opts scd0 scd1
+ $0 $opts st0 st1
+ $0 $opts sg
+ $0 $opts pty
+ $0 $opts console
+ $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 ttyS4
+ $0 $opts busmice
+ $0 $opts lp
+ $0 $opts par
+ $0 $opts audio
+ $0 $opts fb
+ $0 $opts dac960
+ ;;
+ generic-arm)
+ $0 $opts std
+ $0 $opts fd
+ $0 $opts fd0 fd1
+ $0 $opts hd sd
+ $0 $opts xda xdb
+ $0 $opts scd0 scd1
+ $0 $opts st0 st1
+ $0 $opts sg
+ $0 $opts pty
+ $0 $opts console
+ $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 ttyS4
+ $0 $opts busmice
+ makedev sunmouse c 10 6 $mouse
+ $0 $opts lp
+ $0 $opts par
+ $0 $opts audio
+ $0 $opts fb
+ ;;
+ generic-hppa)
+ $0 $opts std
+ $0 $opts fd
+ $0 $opts fd0 fd1
+ $0 $opts hd sd
+ $0 $opts scd0 scd1
+ $0 $opts st0 st1
+ $0 $opts sg
+ $0 $opts pty
+ $0 $opts console
+ $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 ttyS4
+ $0 $opts ttyB0 ttyB1 ttyB2 ttyB3 ttyB4 ttyB5 ttyB6 ttyB7
+ $0 $opts busmice
+ $0 $opts lp
+ $0 $opts par
+ $0 $opts audio
+ $0 $opts fb
+ $0 $opts rtc
+ ;;
+ generic-i386 | generic-i686)
+ $0 $opts std
+ $0 $opts fd
+ $0 $opts fd0 fd1
+ $0 $opts hd sd
+ $0 $opts xda xdb
+ $0 $opts scd0 scd1
+ $0 $opts st0 st1
+ $0 $opts sg
+ $0 $opts pty
+ $0 $opts console
+ $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 ttyS4
+ $0 $opts busmice
+ $0 $opts input
+ $0 $opts lp
+ $0 $opts par
+ $0 $opts audio
+ $0 $opts fb
+ $0 $opts isdn-io eda edb sonycd mcd mcdx cdu535
+ $0 $opts optcd sjcd cm206cd gscd
+ $0 $opts lmscd sbpcd aztcd bpcd dac960 dpti ida ataraid cciss
+ $0 $opts i2o.hda i2o.hdb i2o.hdc i2o.hdd
+ ;;
+ generic-ia64)
+ $0 $opts std
+ $0 $opts fd
+ $0 $opts fd0 fd1
+ $0 $opts hd sd
+ $0 $opts scd0 scd1
+ $0 $opts st0 st1
+ $0 $opts sg
+ $0 $opts pty
+ $0 $opts console
+ $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 ttyS4 ttyS5
+ $0 $opts busmice
+ $0 $opts input
+ $0 $opts lp
+ $0 $opts par
+ $0 $opts audio
+ $0 $opts fb
+ $0 $opts efirtc
+ ;;
+ generic-m68k)
+ $0 $opts std
+ $0 $opts fd
+ $0 $opts fd0 fd1
+ $0 $opts hd sd
+ $0 $opts scd0 scd1
+ $0 $opts sg
+ $0 $opts ada adb adc add ade adf
+ $0 $opts pty
+ $0 $opts console
+ $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 ttyS4 ttyS5
+ $0 $opts m68k-mice
+ $0 $opts lp
+ $0 $opts par
+ $0 $opts nvram
+ $0 $opts audio
+ $0 $opts fb
+ ;;
+ generic-mips)
+ $0 $opts std
+ $0 $opts fd
+ $0 $opts fd0 fd1
+ $0 $opts hd sd
+ $0 $opts scd0 scd1
+ $0 $opts st0 st1
+ $0 $opts sg
+ $0 $opts pty
+ $0 $opts console
+ $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 ttyS4
+ $0 $opts lp
+ $0 $opts par
+ $0 $opts audio
+ $0 $opts fb
+ $0 $opts busmice
+ ;;
+ generic-mipsel)
+ $0 $opts std
+ $0 $opts fd
+ $0 $opts fd0 fd1
+ $0 $opts hd sd
+ $0 $opts scd0 scd1
+ $0 $opts st0 st1
+ $0 $opts sg
+ $0 $opts pty
+ $0 $opts console
+ $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 ttyS4
+ $0 $opts lp
+ $0 $opts par
+ $0 $opts audio
+ $0 $opts fb
+ $0 $opts rtc
+ ;;
+ generic-powerpc)
+ $0 $opts std
+ $0 $opts fd
+ $0 $opts fd0 fd1
+ $0 $opts hd sd
+ $0 $opts scd0 scd1
+ $0 $opts st0 st1
+ $0 $opts sg
+ $0 $opts pty
+ $0 $opts console
+ $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 ttyS4
+ $0 $opts busmice
+ $0 $opts m68k-mice
+ $0 $opts input
+ $0 $opts lp
+ $0 $opts par
+ $0 $opts nvram
+ $0 $opts audio
+ $0 $opts adb
+ $0 $opts fb
+ $0 $opts rtc
+ $0 $opts isdn-io
+ ;;
+ generic-s390)
+ $0 $opts std
+ $0 $opts fd
+ $0 $opts dasda dasdb dasdc dasdd dasde dasdf dasdg dasdh \
+ dasdi dasdj dasdk dasdl dasdm dasdn dasdo dasdp \
+ dasdq dasdr dasds dasdt dasdu dasdv dasdw dasdx \
+ dasdy dasdz
+ $0 $opts pty
+ $0 $opts consoleonly
+ $0 $opts rtc
+ ;;
+ generic-sh)
+ $0 $opts std
+ $0 $opts fd
+ $0 $opts fd0 fd1
+ $0 $opts hd sd
+ $0 $opts scd0 scd1
+ $0 $opts st0 st1
+ $0 $opts sg
+ $0 $opts pty
+ $0 $opts console
+ $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 ttyS4
+ $0 $opts ttySC0 ttySC1 ttySC2 ttySC3
+ $0 $opts lp
+ $0 $opts par
+ $0 $opts audio
+ $0 $opts fb
+ $0 $opts rtc
+ ;;
+ generic-sparc)
+ $0 $opts std
+ $0 $opts fd
+ $0 $opts fd0 fd1
+ $0 $opts hd sd
+ $0 $opts scd0 scd1
+ $0 $opts st0 st1
+ $0 $opts sg
+ $0 $opts pty
+ $0 $opts console
+ $0 $opts ttyS0 ttyS1 ttyS2 ttyS3 ttyS4
+ $0 $opts busmice
+ $0 $opts fb
+ $0 $opts rtc
+ makedev kbd c 11 0 $cons
+ makedev sunmouse c 10 6 $mouse
+ symlink mouse sunmouse
+ makedev openprom c 10 139 root root 0664
+ ;;
+ local)
+ $0.local $opts
+ ;;
+ std)
+ makedev mem c 1 1 $kmem
+ makedev kmem c 1 2 $kmem
+ makedev null c 1 3 $public
+ makedev port c 1 4 $kmem
+ makedev zero c 1 5 $public
+ symlink core $procfs/kcore
+ makedev full c 1 7 $public
+ makedev random c 1 8 $public
+ makedev urandom c 1 9 $public
+ makedev tty c 5 0 $tty
+ $0 $opts ram
+ $0 $opts loop
+ ;;
+ hamradio)
+ $0 $opts scc
+ $0 $opts bc
+ ;;
+ scc)
+ for unit in 0 1 2 3 4 5 6 7
+ do
+ makedev scc$unit c 34 $unit $system
+ done
+ ;;
+ mtd)
+ for unit in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ makedev mtd$unit c 90 `math $unit \* 2` $system
+ done
+ ;;
+ bc)
+ for unit in 0 1 2 3
+ do
+ makedev bc$unit c 51 $unit $system
+ done
+ ;;
+ random)
+ makedev random c 1 8 $public
+ ;;
+ urandom)
+ makedev urandom c 1 9 $readable
+ ;;
+ ram)
+ for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
+ makedev ram$i b 1 $i $disk
+ done
+ symlink ram ram1
+ ;;
+ ram[0-9]|ram1[0-6])
+ unit=`suffix $arg ram`
+ makedev ram$unit b 1 $unit $disk
+ ;;
+ initrd)
+ makedev initrd b 1 250 $disk
+ ;;
+ raw)
+ makedev rawctl c 162 0 $disk
+ mkdir -p raw
+ for i in 1 2 3 4 5 6 7 8; do
+ makedev raw/raw$i c 162 $i $disk
+ done
+ ;;
+ consoleonly)
+ makedev tty0 c 4 0 $cons
+ # new kernels need a device, old ones a symlink... sigh
+ kern_rev1=`uname -r | sed -e 's@^\([^.]*\)\..*@\1@'`
+ kern_rev2=`uname -r | sed -e 's@^[^.]*\.\([^.]*\)\..*@\1@'`
+ if [ $kern_rev1 -gt 2 ]
+ then
+ makedev console c 5 1 $cons
+ else
+ if [ $kern_rev1 -eq 2 ] && [ $kern_rev2 -ge 1 ]
+ then
+ makedev console c 5 1 $cons
+ else
+ symlink console tty0
+ fi
+ fi
+ ;;
+ console)
+ $0 $opts consoleonly
+ major=`Major vcs 7` # not fatal
+ [ "$major" ] && makedev vcs0 c $major 0 $cons
+ symlink vcs vcs0
+ [ "$major" ] && makedev vcsa0 c $major 128 $cons
+ symlink vcsa vcsa0
+ # individual vts
+ line=1
+ while [ $line -le $MAXVT ] && [ $line -le 63 ]
+ do
+ makedev tty$line c 4 $line $cons
+ [ "$major" ] && makedev vcs$line c $major $line $cons
+ [ "$major" ] && makedev vcsa$line c $major `math $line + 128` $cons
+ line=`math $line + 1`
+ done
+ ;;
+ adb)
+ # pick the right arch device using dpkg's knowledge
+ case `dpkg --print-architecture` in
+ powerpc)
+ # ADB bus devices (char)
+ makedev adb c 56 0 $mouse
+ makedev adbmouse c 10 10 $mouse
+ ;;
+ m68k)
+ # ACSI disk 2, whole device (block)
+ makedev adb b 28 16 $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ minor=$(( 16 + $part ))
+ makedev adb$part b 28 $minor $disk
+ done
+ ;;
+ *)
+ echo "no support for adb on this arch" >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ raw1394)
+ makedev raw1394 c 171 0 $disk
+ ;;
+ video1394)
+ rm -f video1394
+ mkdir -p video1394
+ for i in `seq 0 15`
+ do
+ makedev video1394/$i c 171 `math 16 + $i` $video
+ done
+ ;;
+ alsa)
+ echo "You requested 'alsa' devices. Please install the alsa-base package instead,"
+ echo "which creates and maintains device information for ALSA."
+ ;;
+ nvram)
+ makedev nvram c 10 144 $mouse
+ ;;
+ tty[1-9]|tty[1-5][0-9]|tty[6][0-3])
+ line=`suffix $arg tty`
+ makedev tty$line c 4 $line $cons
+ ;;
+ ttyS[0-9]|ttyS[1-5][0-9]|ttyS[6][0-3])
+ line=`suffix $arg ttyS`
+ minor=`math 64 + $line`
+ makedev ttyS$line c 4 $minor $dialout
+ ;;
+ ttySC[0-3])
+ line=`suffix $arg ttySC`
+ minor=`math 8 + $line`
+ makedev ttySC$line c 204 $minor $dialout
+ ;;
+ ttyB[0-7])
+ minor=`suffix $arg ttyB`
+ makedev ttyB$minor c 11 $minor $dialout
+ ;;
+ pty[a-ep-z])
+ bank=`suffix $arg pty`
+ base=`index pqrstuvwxyzabcde $bank`
+ base=`math $base \* 16`
+ for i in 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ do
+ j=`index 0123456789abcdef $i`
+ makedev pty$bank$i c 2 `math $base + $j` $tty
+ makedev tty$bank$i c 3 `math $base + $j` $tty
+ done
+ ;;
+ pty)
+ ptysufs=""
+ for i in p q r s t u v w x y z a b c d e
+ do
+ ptysufs="$ptysufs pty$i"
+ done
+ $0 $opts $ptysufs ptmx
+ ;;
+ ptmx)
+ # master pty multiplexer for 2.1 kernels
+ makedev ptmx c 5 2 $tty
+ ;;
+ cyclades|ttyC)
+ major1=`Major ttyC 19` || continue
+ #major2=`Major cub 20` || continue
+ for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 \
+ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ do
+ makedev ttyC$i c $major1 $i $dialout
+ #makedev cub$i c $major2 $i $dialout
+ done
+ ;;
+ stallion|ttyE)
+ major1=`Major ttyE 24` || continue
+ #major2=`Major cue 25` || continue
+ majorc=28
+ minor=0
+ until [ $minor -gt 256 ]
+ do
+ makedev ttyE$minor c $major1 $minor $dialout
+ #makedev cue$minor c $major2 $minor $dialout
+ minor=`math $minor + 1`
+ done
+ for i in 0 1 2 3
+ do
+ makedev staliomem$i c $majorc $i $private
+ done
+ ;;
+ chase|ttyH)
+ major1=`Major ttyH 17` || continue
+ #major2=`Major cuh 18` || continue
+ minor=0
+ until [ $minor -gt 16 ] # tell me if 16 is wrong
+ do
+ makedev ttyH$minor c $major1 $minor $dialout
+ #makedev cuh$minor c $major2 $minor $dialout
+ minor=`math $minor + 1`
+ done
+ ;;
+ rocketport|ttyR)
+ major1=`Major ttyR 46` || continue
+ #major2=`Major cur 47` || continue
+ minor=0
+ until [ $minor -gt 64 ] # tell me if 64 is wrong
+ do
+ makedev ttyR$minor c $major1 $minor $dialout
+ #makedev cur$minor c $major2 $minor $dialout
+ minor=`math $minor + 1`
+ done
+ ;;
+ ttyV)
+ major1=`Major ttyV 105` || continue
+ #major2=`Major cuv 106` || continue
+ minor=0
+ until [ $minor -gt 16 ] # tell me if 16 is wrong
+ do
+ makedev ttyV$minor c $major1 $minor $dialout
+ #makedev cuv$minor c $major2 $minor $dialout
+ minor=`math $minor + 1`
+ done
+ ;;
+ digi|ttyD)
+ major1=`Major ttyD 22` || continue
+ #major2=`Major cud 23` || continue
+ minor=0
+ until [ $minor -gt 16 ] # tell me if 16 is wrong
+ do
+ makedev ttyD$minor c $major1 $minor $dialout
+ #makedev cud$minor c $major2 $minor $dialout
+ minor=`math $minor + 1`
+ done
+ ;;
+ specialix|ttyX)
+ major1=`Major ttyX 32` || continue
+ #major2=`Major cux 33` || continue
+ minor=0
+ until [ $minor -gt 16 ] # tell me if 16 is wrong
+ do
+ makedev ttyX$minor c $major1 $minor $dialout
+ #makedev cux$minor c $major2 $minor $dialout
+ minor=`math $minor + 1`
+ done
+ ;;
+ specialixIO8|ttyW)
+ major1=`Major ttyW 75` || continue
+ #major2=`Major cuw 76` || continue
+ minor=0
+ until [ $minor -gt 16 ] # tell me if 16 is wrong
+ do
+ makedev ttyW$minor c $major1 $minor $dialout
+ #makedev cuw$minor c $major2 $minor $dialout
+ minor=`math $minor + 1`
+ done
+ ;;
+ PAM|ttyM)
+ major1=`Major ttyM 79` || continue
+ #major2=`Major cum 80` || continue
+ minor=0
+ until [ $minor -gt 16 ] # tell me if 16 is wrong
+ do
+ makedev ttyM$minor c $major1 $minor $dialout
+ #makedev cum$minor c $major2 $minor $dialout
+ minor=`math $minor + 1`
+ done
+ ;;
+ riscom|ttyL)
+ major=`Major ttyL 48` || continue
+ minor=0
+ until [ $minor -gt 16 ] # tell me if 16 is wrong
+ do
+ makedev ttyL$minor c $major $minor $dialout
+ minor=`math $minor + 1`
+ done
+ ;;
+ computone|ttyF)
+ major=`Major ttyF 71` || continue
+ #major2=`Major cuf 72` || continue
+ minor=0
+ until [ $minor -gt 255 ]
+ do
+ makedev ttyF$minor c $major $minor $dialout
+ #makedev cuf$minor c $major2 $minor $dialout
+ minor=`math $minor + 1`
+ done
+ major=73
+ for i in 0 4 8 12
+ do
+ makedev ip2ipl$i c $major $i $private
+ makedev ip2stat$i c $major `math $i + 1` $private
+ done
+ ;;
+ ESP|ttyP)
+ major=`Major ttyP 57` || continue
+ #major2=`Major cup 58` || continue
+ minor=0
+ until [ $minor -gt 4 ] # tell me if 4 is wrong
+ do
+ makedev ttyP$minor c $major $minor $dialout
+ #makedev cup$minor c $major2 $minor $dialout
+ minor=`math $minor + 1`
+ done
+ ;;
+ COMX|comx)
+ major=`Major comx 88` || continue
+ minor=0
+ until [ $minor -gt 4 ] # tell me if 4 is wrong
+ do
+ makedev comx$minor c $major $minor $private
+ minor=`math $minor + 1`
+ done
+ ;;
+ isdnmodem|ttyI)
+ major1=`Major ttyI 43` || continue
+ #major2=`Major cui 44` || continue
+ minor=0
+ until [ $minor -gt 63 ]
+ do
+ makedev ttyI$minor c $major1 $minor $dialout
+ #makedev cui$minor c $major2 $minor $dialout
+ minor=`math $minor + 1`
+ done
+ ;;
+ isdnbri)
+ major=45
+ minor=0
+ until [ $minor -gt 63 ]
+ do
+ makedev isdn$minor c $major $minor $dialout
+ makedev isdnctrl$minor c $major `math $minor + 64` $dialout
+ makedev ippp$minor c $major `math $minor + 128` $dialout
+ minor=`math $minor + 1`
+ done
+ makedev isdninfo c $major 255 $private
+ ;;
+ dcbri)
+ major=52
+ for i in 0 1 2 3
+ do
+ makedev dcbri$i c $major $i $dialout
+ done
+ ;;
+ capi)
+ major=68
+ makedev capi20 c $major 0 $dialout
+ for i in 0 1 2 3 4 5 6 7 8 9
+ do
+ makedev capi20.0$i c $major `math $i + 1` $dialout
+ done
+ for i in 10 11 12 13 14 15 16 17 18 19
+ do
+ makedev capi20.$i c $major `math $i + 1` $dialout
+ done
+ ;;
+ ubd)
+ major=98
+ for devicenum in 0 1 2 3 4 5 6 7
+ do
+ device=ubd`substr abcdefgh $(($devicenum + 1))`
+ baseminor=`math $devicenum \* 16`
+ makedev $device b $major $baseminor $disk
+ for partition in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ minor=`math $baseminor + $partition`
+ makedev $device$partition b $major $minor $disk
+ done
+ done
+ ;;
+ fb)
+ for i in 0 1 2 3 4 5 6 7
+ do
+ makedev fb$i c 29 $i $video
+ done
+ ;;
+ fb[0-7])
+ dev=`suffix $arg fb`
+ makedev fb$dev c 29 $dev $video
+ ;;
+ netlink|tap|tap[0-9]|tap1[0-5])
+ makedev route c 36 0 $coda
+ makedev skip c 36 1 $coda
+ makedev fwmonitor c 36 3 $coda
+ for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ makedev tap$i c 36 `math $i + 16` $coda
+ done
+ ;;
+ tun)
+ mkdir -p net
+ makedev net/tun c 10 200 $system
+ ;;
+ lp)
+ major=`Major lp 6` || continue
+ makedev ${arg}0 c $major 0 $printer
+ makedev ${arg}1 c $major 1 $printer
+ makedev ${arg}2 c $major 2 $printer
+ ;;
+ par)
+ major=`Major lp 6` || continue
+ makedev ${arg}0 c $major 0 $printer
+ makedev ${arg}1 c $major 1 $printer
+ makedev ${arg}2 c $major 2 $printer
+ ;;
+ parport)
+ major=`Major parport 99` || continue
+ makedev ${arg}0 c $major 0 $printer
+ makedev ${arg}1 c $major 1 $printer
+ makedev ${arg}2 c $major 2 $printer
+ ;;
+ slm)
+ major=`Major slm 28` || continue
+ for i in 0 1 2 3
+ do
+ makedev slm c $major $i $printer
+ done
+ ;;
+ input)
+ major=`Major pcsp 13` || continue
+ mkdir -p input
+ for i in 0 1 2 3
+ do
+ makedev input/js$i c $major $i $mouse
+ makedev input/mouse$i c $major `math $i + 32` $mouse
+ makedev input/event$i c $major `math $i + 64` $mouse
+ done
+ makedev input/mice c $major 63 $mouse
+ ;;
+ busmice)
+ major=`Major mouse 10` || continue
+ makedev logibm c $major 0 $mouse
+ makedev psaux c $major 1 $mouse
+ makedev inportbm c $major 2 $mouse
+ makedev atibm c $major 3 $mouse
+ makedev jbm c $major 4 $mouse
+ ;;
+ m68k-mice)
+ major=`Major mouse 10` || continue
+ makedev amigamouse c $major 4 $mouse
+ makedev atarimouse c $major 5 $mouse
+ makedev amigamouse1 c $major 7 $mouse
+ makedev adbmouse c $major 10 $mouse
+ ;;
+ 3dfx)
+ major=`Major $arg 107` || continue
+ makedev $arg c $major 0 $video
+ ;;
+ agpgart)
+ major=`Major $arg 10` || continue
+ makedev $arg c $major 175 $video
+ ;;
+ hwrng)
+ major=`Major $arg 10` || continue
+ makedev $arg c $major 183 $private
+ ;;
+ mcelog)
+ major=`Major $arg 10` || continue
+ makedev $arg c $major 227 $private
+ ;;
+ cpu|microcode)
+ mkdir -p cpu
+ makedev cpu/microcode c 10 184 $private
+ for i in 0 1 2 3
+ do
+ mkdir -p cpu/$i
+ makedev cpu/$i/msr c 202 $i $private
+ makedev cpu/$i/cpuid c 203 $i $private
+ done
+ ;;
+ ipmi|ipmikcs)
+ major=`Major ipmikcs 10` || continue
+ makedev ipmikcs c $major 173 $private
+ ;;
+ irda)
+ for i in 0 1
+ do
+ makedev ircomm$i c 161 $i $dialout
+ makedev irlpt$i c 161 `math $i + 16` $printer
+ done
+ ;;
+ irnet)
+ makedev irnet c 10 187 $system
+ ;;
+ cbm)
+ makedev cbm c 10 177 $floppy
+ ;;
+ misc)
+ major=`Major mouse 10` || continue
+ makedev logibm c $major 0 $mouse
+ makedev psaux c $major 1 $mouse
+ makedev inportbm c $major 2 $mouse
+ makedev atibm c $major 3 $mouse
+ makedev jbm c $major 4 $mouse
+ makedev amigamouse c $major 4 $mouse
+ makedev atarimouse c $major 5 $mouse
+ makedev sunmouse c $major 6 $mouse
+ makedev amigamouse1 c $major 7 $mouse
+ makedev smouse c $major 8 $mouse
+ makedev pc110pad c $major 9 $mouse
+ makedev adbmouse c $major 10 $mouse
+ makedev beep c $major 128 $mouse
+ makedev modreq c $major 129 $mouse
+ makedev watchdog c $major 130 $mouse
+ makedev temperature c $major 131 $mouse
+ makedev hwtrap c $major 132 $mouse
+ makedev exttrp c $major 133 $mouse
+ makedev apm_bios c $major 134 $mouse
+ makedev rtc c $major 135 $mouse
+ makedev openprom c $major 139 root root 0664
+ makedev relay8 c $major 140 $mouse
+ makedev relay16 c $major 141 $mouse
+ makedev msr c $major 142 $mouse
+ makedev pciconf c $major 143 $mouse
+ makedev nvram c $major 144 $mouse
+ makedev hfmodem c $major 145 $mouse
+ makedev led c $major 151 $mouse
+ makedev mergemem c $major 153 $mouse
+ makedev pmu c $major 154 $mouse
+ ;;
+ fuse)
+ makedev fuse c 10 229 $system
+ ;;
+ pmu)
+ major=`Major mouse 10` || continue
+ makedev pmu c $major 154 $mouse
+ ;;
+ thinkpad)
+ major=`Major mouse 10` || continue
+ mkdir -p thinkpad
+ makedev thinkpad/thinkpad c $major 170 $mouse
+ ;;
+ rtc)
+ major=`Major mouse 10` || continue
+ makedev rtc c $major 135 $mouse
+ ;;
+ efirtc)
+ major=`Major mouse 10` || continue
+ makedev efirtc c $major 136 $mouse
+ ;;
+ mwave)
+ makedev mwave c 10 219 $mouse
+ ;;
+ systrace)
+ makedev systrace c 10 226 $private
+ ;;
+ uinput)
+ mkdir -p input
+ makedev input/uinput c 10 223 $mouse
+ ;;
+ js)
+ major=`Major Joystick 13` || continue
+ for unit in 0 1 2 3
+ do
+ makedev js$unit c $major $unit $readable
+ makedev djs$unit c $major `math $unit + 128` $readable
+ done
+ ;;
+ fd[0-7])
+ major=`Major fd 2` || continue
+ base=`suffix $arg fd`
+ if [ $base -ge 4 ]
+ then
+ base=`math $base + 124`
+ fi
+ makedev ${arg} b $major $base $floppy
+ makedev ${arg}d360 b $major `math $base + 4` $floppy
+ makedev ${arg}h1200 b $major `math $base + 8` $floppy
+ makedev ${arg}u360 b $major `math $base + 12` $floppy
+ makedev ${arg}u720 b $major `math $base + 16` $floppy
+ makedev ${arg}h360 b $major `math $base + 20` $floppy
+ makedev ${arg}h720 b $major `math $base + 24` $floppy
+ makedev ${arg}u1440 b $major `math $base + 28` $floppy
+ makedev ${arg}u2880 b $major `math $base + 32` $floppy
+ makedev ${arg}CompaQ b $major `math $base + 36` $floppy
+
+ makedev ${arg}h1440 b $major `math $base + 40` $floppy
+ makedev ${arg}u1680 b $major `math $base + 44` $floppy
+ makedev ${arg}h410 b $major `math $base + 48` $floppy
+ makedev ${arg}u820 b $major `math $base + 52` $floppy
+ makedev ${arg}h1476 b $major `math $base + 56` $floppy
+ makedev ${arg}u1722 b $major `math $base + 60` $floppy
+ makedev ${arg}h420 b $major `math $base + 64` $floppy
+ makedev ${arg}u830 b $major `math $base + 68` $floppy
+ makedev ${arg}h1494 b $major `math $base + 72` $floppy
+ makedev ${arg}u1743 b $major `math $base + 76` $floppy
+ makedev ${arg}h880 b $major `math $base + 80` $floppy
+ makedev ${arg}u1040 b $major `math $base + 84` $floppy
+ makedev ${arg}u1120 b $major `math $base + 88` $floppy
+ makedev ${arg}h1600 b $major `math $base + 92` $floppy
+ makedev ${arg}u1760 b $major `math $base + 96` $floppy
+ makedev ${arg}u1920 b $major `math $base + 100` $floppy
+ makedev ${arg}u3200 b $major `math $base + 104` $floppy
+ makedev ${arg}u3520 b $major `math $base + 108` $floppy
+ makedev ${arg}u3840 b $major `math $base + 112` $floppy
+ makedev ${arg}u1840 b $major `math $base + 116` $floppy
+ makedev ${arg}u800 b $major `math $base + 120` $floppy
+ makedev ${arg}u1600 b $major `math $base + 124` $floppy
+ ;;
+ ed[a-b])
+ major=`Major ed 36` || continue
+ unit=`suffix $arg ed`
+ base=`index ab $unit`
+ base=`math $base \* 64`
+ makedev ed$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 # 9 10 11 12 13 14 15 16 17 18 19 20
+ do
+ makedev ed$unit$part b $major `math $base + $part` $disk
+ done
+ ;;
+ hd[a-b])
+ major=`Major ide0` || major=`Major hd 3` || continue
+ unit=`suffix $arg hd`
+ base=`index ab $unit`
+ base=`math $base \* 64`
+ makedev hd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ do
+ makedev hd$unit$part b $major `math $base + $part` $disk
+ done
+ ;;
+ hd[c-d])
+ major=`Major ide1 22` || continue
+ unit=`suffix $arg hd`
+ base=`index cd $unit`
+ base=`math $base \* 64`
+ makedev hd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ do
+ makedev hd$unit$part b $major $(( $base + $part )) $disk
+ done
+ ;;
+ hd[e-f])
+ major=`Major ide2 33` || continue
+ unit=`suffix $arg hd`
+ base=`index ef $unit`
+ base=`math $base \* 64`
+ makedev hd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ do
+ makedev hd$unit$part b $major $(( $base + $part )) $disk
+ done
+ ;;
+ hd[g-h])
+ major=`Major ide3 34` || continue
+ unit=`suffix $arg hd`
+ base=`index gh $unit`
+ base=`math $base \* 64`
+ makedev hd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ do
+ makedev hd$unit$part b $major $(( $base + $part )) $disk
+ done
+ ;;
+ hd[i-j])
+ major=`Major ide4 56` || continue
+ unit=`suffix $arg hd`
+ base=`index ij $unit`
+ base=`math $base \* 64`
+ makedev hd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ do
+ makedev hd$unit$part b $major $(( $base + $part )) $disk
+ done
+ ;;
+ hd[k-l])
+ major=`Major ide5 57` || continue
+ unit=`suffix $arg hd`
+ base=`index kl $unit`
+ base=`math $base \* 64`
+ makedev hd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ do
+ makedev hd$unit$part b $major $(( $base + $part )) $disk
+ done
+ ;;
+ hd[m-n])
+ major=`Major ide6 88` || continue
+ unit=`suffix $arg hd`
+ base=`index mn $unit`
+ base=`math $base \* 64`
+ makedev hd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ do
+ makedev hd$unit$part b $major $(( $base + $part )) $disk
+ done
+ ;;
+ hd[o-p])
+ major=`Major ide7 89` || continue
+ unit=`suffix $arg hd`
+ base=`index op $unit`
+ base=`math $base \* 64`
+ makedev hd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ do
+ makedev hd$unit$part b $major $(( $base + $part )) $disk
+ done
+ ;;
+ hd[q-r])
+ major=`Major ide8 90` || continue
+ unit=`suffix $arg hd`
+ base=`index qr $unit`
+ base=`math $base \* 64`
+ makedev hd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ do
+ makedev hd$unit$part b $major $(( $base + $part )) $disk
+ done
+ ;;
+ hd[s-t])
+ major=`Major ide9 91` || continue
+ unit=`suffix $arg hd`
+ base=`index st $unit`
+ base=`math $base \* 64`
+ makedev hd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ do
+ makedev hd$unit$part b $major $(( $base + $part )) $disk
+ done
+ ;;
+ ub|uba)
+ major=180
+ makedev uba b $major 0 $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ makedev uba$part b $major $part $disk
+ done
+ ;;
+ ht0)
+ major=`Major ht0 37` || continue
+ # Only one IDE tape drive is currently supported; ht0.
+ makedev ht0 c $major 0 $tape
+ makedev nht0 c $major 128 $tape
+ ;;
+ pt)
+ major=`Major pt 96` || continue
+ for i in 0 1 2 3
+ do
+ makedev pt$i c $major $i $tape
+ makedev npt$i c $major `math $i + 128` $tape
+ done
+ ;;
+ xd[a-d])
+ major=`Major xd 13` || continue
+ unit=`suffix $arg xd`
+ base=`index abcd $unit`
+ base=`math $base \* 64`
+ makedev xd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 # 9 10 11 12 13 14 15 16 17 18 19 20
+ do
+ makedev xd$unit$part b $major $(( $base + $part )) $disk
+ done
+ ;;
+ sd[a-z])
+ major=`Major sd 8` || continue
+ unit=`suffix $arg sd`
+ base=`index abcdefghijklmnopqrstuvwxyz $unit`
+ base=$(( $base * 16 ))
+ if [ $base -lt 256 ]; then
+ major=8
+ else
+ major=65
+ base=$(( $base - 256 ))
+ fi
+ makedev sd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ minor=$(( $base + $part ))
+ makedev sd$unit$part b $major $minor $disk
+ done
+ ;;
+ sd[a-d][a-z])
+ unit=`suffix $arg sd`
+ unitmaj=`first $unit`
+ unitmin=`second $unit`
+ basemaj=`index Xabcd $unitmaj`
+ basemin=`index abcdefghijklmnopqrstuvwxyz $unitmin`
+ basemaj=`math $basemaj \* 416`
+ basemin=`math $basemin \* 16`
+ base=`math $basemaj + $basemin`
+ basemaj=`math $base / 256`
+ base=`math $base % 256`
+ major=`math basemaj \+ 64`
+ if [ $major -gt 71 ]; then
+ echo "$0: don't know how to make device \"$arg\"" >&2
+ exit 0
+ fi
+ makedev sd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ minor=$(( $base + $part ))
+ makedev sd$unit$part b $major $minor $disk
+ done
+ ;;
+ i2o.hd[a-z])
+ [ -d i2o ] || {
+ mkdir i2o
+ chown root:root i2o
+ chmod 755 i2o
+ [ -e i2o/ctl ] || makedev i2o/ctl c 10 166 $disk
+ }
+ unit=`suffix $arg i2o.hd`
+ base=`index abcdefghijklmnopqrstuvwxyz $unit`
+ base=$(( $base * 16 ))
+ if [ $base -lt 256 ]; then
+ major=80
+ else
+ major=81
+ base=$(( $base - 256 ))
+ fi
+ makedev i2o/hd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ minor=$(( $base + $part ))
+ makedev i2o/hd$unit$part b $major $minor $disk
+ done
+ ;;
+ i2o.hd[a-d][a-z])
+ [ -d i2o ] || {
+ mkdir i2o
+ chown root:root i2o
+ chmod 755 i2o
+ [ -e i2o/ctl ] || makedev i2o/ctl c 10 166 $disk
+ }
+ unit=`suffix $arg i2o.hd`
+ unitmaj=`first $unit`
+ unitmin=`second $unit`
+ basemaj=`index Xabcd $unitmaj`
+ basemin=`index abcdefghijklmnopqrstuvwxyz $unitmin`
+ basemaj=`math $basemaj \* 416`
+ basemin=`math $basemin \* 16`
+ base=`math $basemaj + $basemin`
+ basemaj=`math $base / 256`
+ base=`math $base % 256`
+ major=`math basemaj \+ 80`
+ if [ $major -gt 87 ]; then
+ echo "$0: don't know how to make device \"$arg\"" >&2
+ exit 0
+ fi
+ makedev i2o/hd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ minor=$(( $base + $part ))
+ makedev i2o/hd$unit$part b $major $minor $disk
+ done
+ ;;
+ dasd[a-z])
+ major=`Major dasd 94` || continue
+ unit=`suffix $arg dasd`
+ base=`index abcdefghijklmnopqrstuvwxyz $unit`
+ base=$(( $base * 4 ))
+ if [ $base -lt 256 ]; then
+ major=94
+ else
+ major=65
+ base=$(( $base - 256 ))
+ fi
+ makedev dasd$unit b $major $base $disk
+ for part in 1 2 3
+ do
+ minor=$(( $base + $part ))
+ makedev dasd$unit$part b $major $minor $disk
+ done
+ ;;
+ ad[a-p])
+ major=`Major ad 28` || continue
+ unit=`suffix $arg ad`
+ base=`index abcdefghijklmnop $unit`
+ base=`math $base \* 16`
+ makedev ad$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ minor=$(( $base + $part ))
+ makedev ad$unit$part b $major $minor $disk
+ done
+ ;;
+ dac960)
+ for ctr in 0 1 2 3 4 5 6 7
+ do
+ $0 $opts dac960.$ctr
+ done
+ makedev dac960_gam c 10 252 $disk
+ ;;
+ dac960.[0-7])
+ [ -d rd ] || {
+ mkdir rd
+ chown root:root rd
+ chmod 755 rd
+ }
+ unit=`suffix $arg dac960.`
+ major=`math 48 + $unit`
+ minor=0
+ for ld in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 \
+ 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ do
+ makedev rd/c${unit}d${ld} b $major $minor $disk
+ minor=`math $minor + 1`
+ for part in 1 2 3 4 5 6 7
+ do
+ makedev rd/c${unit}d${ld}p$part b $major $minor $disk
+ minor=`math $minor + 1`
+ done
+ done
+ ;;
+ dpti)
+ major=151
+ for ld in 1 2 3 4 5 6 7
+ do
+ minor=`math $ld -1`
+ makedev dpti${ld} c $major $minor $disk
+ done
+ ;;
+ ataraid)
+ for ctr in 0 1 2 # 3 4 5 6 7
+ do
+ $0 $opts ataraid.$ctr
+ done
+ ;;
+ ataraid.[0-7])
+ [ -d ataraid ] || {
+ mkdir ataraid
+ chown root:root ataraid
+ chmod 755 ataraid
+ }
+ unit=`suffix $arg ataraid.`
+ major=114
+ minor=`math $unit \* 16`
+ makedev ataraid/d${unit} b $major $minor $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ minor=`math $minor + 1`
+ makedev ataraid/d${unit}p$part b $major $minor $disk
+ done
+ ;;
+ ida)
+ for ctr in 0 1 2 # 3 4 5 6 7
+ do
+ $0 $opts ida.$ctr
+ done
+ ;;
+ ida.[0-7])
+ [ -d ida ] || {
+ mkdir ida
+ chown root:root ida
+ chmod 755 ida
+ }
+ unit=`suffix $arg ida.`
+ major=`math 72 + $unit`
+ minor=0
+ for ld in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ makedev ida/c${unit}d${ld} b $major $minor $disk
+ minor=`math $minor + 1`
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ makedev ida/c${unit}d${ld}p$part b $major $minor $disk
+ minor=`math $minor + 1`
+ done
+ done
+ ;;
+ cciss)
+ for ctr in 0 1 2 # 3 4 5 6 7
+ do
+ $0 $opts cciss.$ctr
+ done
+ ;;
+ cciss.[0-7])
+ [ -d cciss ] || {
+ mkdir cciss
+ chown root:root cciss
+ chmod 755 cciss
+ }
+ unit=`suffix $arg cciss.`
+ major=`math 104 + $unit`
+ minor=0
+ for ld in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ makedev cciss/c${unit}d${ld} b $major $minor $disk
+ minor=`math $minor + 1`
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ makedev cciss/c${unit}d${ld}p$part b $major $minor $disk
+ minor=`math $minor + 1`
+ done
+ done
+ ;;
+ rom)
+ major=`Major rom 31`
+ for i in 0 1 2 3 4 5 6 7
+ do
+ makedev rom$i b $major $i $disk
+ makedev rrom$i b $major `math $i +8` $disk
+ makedev flash$i b $major `math $i +16` $disk
+ makedev rflash$i b $major `math $i +24` $disk
+ done
+ ;;
+ nb[0-7])
+ major=`Major nbd 43` || continue
+ minor=`suffix $arg nb`
+ makedev nb$minor b $major $minor $disk
+ ;;
+ loop)
+ for part in 0 1 2 3 4 5 6 7
+ do
+ makedev loop$part b 7 $part $disk
+ done
+ ;;
+ loop[0-9]|loop[1-9][0-9]|loop1[0-9][0-9]|loop2[0-4][0-9]|loop25[0-5])
+ minor=`suffix $arg loop`
+ makedev loop$minor b 7 $minor $disk
+ ;;
+ md)
+ major=`Major md 9` || continue
+ for part in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 \
+ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ do
+ makedev md$part b $major $part $disk
+ done
+ ;;
+ st[0-7])
+ major=`Major st 9`
+ unit=`suffix $arg st`
+ makedev st${unit} c $major $unit $tape
+ makedev nst${unit} c $major `math 128 + $unit` $tape
+
+ makedev st${unit}l c $major `math 32 + $unit` $tape
+ makedev nst${unit}l c $major `math 160 + $unit` $tape
+
+ makedev st${unit}m c $major `math 64 + $unit` $tape
+ makedev nst${unit}m c $major `math 192 + $unit` $tape
+
+ makedev st${unit}a c $major `math 96 + $unit` $tape
+ makedev nst${unit}a c $major `math 224 + $unit` $tape
+ ;;
+ qic)
+ major=`Major tpqic02 12`
+ makedev ntpqic11 c $major 2 $tape
+ makedev tpqic11 c $major 3 $tape
+ makedev ntpqic24 c $major 4 $tape
+ makedev tpqic24 c $major 5 $tape
+ makedev ntpqic120 c $major 6 $tape
+ makedev tpqic120 c $major 7 $tape
+ makedev ntpqic150 c $major 8 $tape
+ makedev tpqic150 c $major 9 $tape
+ makedev rmt8 c $major 6 $tape
+ makedev rmt16 c $major 8 $tape
+ makedev tape-d c $major 136 $tape
+ makedev tape-reset c $major 255 $tape
+ $0 $opts qft
+ ;;
+ ftape)
+ major=`Major qft 27` || continue
+ for unit in 0 1 2 3
+ do
+ makedev qft$unit c $major $unit $tape
+ makedev nqft$unit c $major `math $unit + 4` $tape
+ makedev zqft$unit c $major `math $unit + 16` $tape
+ makedev nzqft$unit c $major `math $unit + 20` $tape
+ makedev rawqft$unit c $major `math $unit + 32` $tape
+ makedev nrawqft$unit c $major `math $unit + 36` $tape
+ done
+ symlink ftape qft0
+ symlink nftape nqft0
+ ;;
+ sr|scd|scd-all)
+ major=`Major sr 11` || continue
+ for unit in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ do
+ makedev scd$unit b $major $unit $cdrom
+ symlink sr$unit scd$unit
+ done
+ ;;
+ pktcdvd)
+ echo "pktcdvd major number is now dynamic, taking no action"
+ # major=97
+ # for unit in 0 1 2 3
+ # do
+ # makedev pktcdvd$unit b $major $unit $cdrom
+ # done
+ ;;
+ cfs0)
+ makedev cfs0 c 67 0 $coda
+ ;;
+ scd[0-9]|scd[0-1][0-9])
+ major=`Major sr 11` || continue
+ unit=`suffix $arg scd`
+ makedev scd$unit b $major $unit $cdrom
+ symlink sr$unit scd$unit
+ ;;
+ ttyI[0-9]|ttyI[1-5][0-9]|ttyI[6][0-3])
+ major=43
+ unit=`suffix $arg ttyI`
+ makedev ttyI$unit c $major $unit $dialout
+ ;;
+ ppp)
+ major=108
+ makedev ppp c $major 0 $dip
+ ;;
+ ippp[0-9]|ippp[1-5][0-9]|ippp[6][0-3])
+ major=45
+ unit=`suffix $arg ippp`
+ minor=`math $unit + 128`
+ makedev ippp$unit c $major $minor $dialout
+ ;;
+ isdn[0-9]|isdn[1-5][0-9]|isdn[6][0-3])
+ major=45
+ unit=`suffix $arg isdn`
+ minor=`math $unit + 0`
+ makedev isdn$unit c $major $minor $dialout
+ ;;
+ isdnctrl[0-9]|isdnctrl[1-5][0-9]|isdnctrl[6][0-3])
+ major=45
+ unit=`suffix $arg isdnctrl`
+ minor=`math $unit + 64`
+ makedev isdnctrl$unit c $major $minor $dialout
+ ;;
+ isdninfo)
+ makedev isdninfo c 45 255 $private
+ ;;
+ isdn-tty)
+ major=43
+ for unit in 0 1 2 3 4 5 6 7
+ do
+ makedev ttyI$unit c $major $unit $dialout
+ done
+ ;;
+ isdn-ippp)
+ major=45
+ for unit in 0 1 2 3 4 5 6 7
+ do
+ makedev ippp$unit c $major `math $unit + 128` $dialout
+ done
+ ;;
+ isdn-io)
+ for unit in 0 1 2 3 4 5 6 7
+ do
+ makedev isdn$unit c 45 $unit $dialout
+ makedev isdnctrl$unit c 45 `math $unit + 64` $dialout
+ makedev ippp$unit c 45 `math $unit + 128` $dialout
+ done
+ makedev isdninfo c 45 255 $dialout
+ ;;
+ sonycd)
+ major=`Major sonycd 15` || continue
+ makedev $arg b $major 0 $cdrom
+ ;;
+ mcd)
+ major=`Major mcd 23` || continue
+ makedev $arg b $major 0 $cdrom
+ ;;
+ mcdx|mcdx[0-4])
+ major=`Major $arg 20` || continue
+ for unit in 0 1 2 3 4
+ do
+ makedev mcdx$unit b $major $unit $cdrom
+ done
+ test -r mcdx || symlink mcdx mcdx0
+ ;;
+ cdu535)
+ makedev $arg b 24 0 $cdrom
+ ;;
+ lmscd)
+ makedev $arg b 24 0 $cdrom
+ ;;
+ sbpcd|sbpcd[123])
+ major=`Major $arg 25` || continue
+ base=`suffix ${arg}0 sbpcd`
+ for minor in 0 1 2 3
+ do
+ # XXX
+ unit=$(substr 0123456789abcdef $(( $base * 4 + $minor + 1 )) )
+ makedev sbpcd$unit b $major $minor $cdrom
+ done
+ [ $arg = sbpcd ] && symlink $arg ${arg}0
+ ;;
+ aztcd)
+ major=`Major $arg 29` || continue
+ makedev ${arg}0 b $major 0 $cdrom
+ ;;
+ cm206cd)
+ major=`Major $arg 30` || continue
+ makedev ${arg}0 b $major 0 $cdrom
+ ;;
+ gscd)
+ major=`Major $arg 16` || continue
+ makedev ${arg}0 b $major 0 $cdrom
+ ;;
+ pcd)
+ for unit in 0 1 2 3
+ do
+ makedev pcd$unit b 46 $unit $cdrom
+ done
+ ;;
+ bpcd)
+ makedev $arg b 41 0 $cdrom
+ ;;
+ optcd)
+ makedev $arg b 17 0 $cdrom
+ ;;
+ sjcd)
+ makedev $arg b 18 0 $cdrom
+ ;;
+ cfs|coda)
+ makedev cfs0 c 67 0 $private
+ ;;
+ xfs|nnpfs|arla)
+ makedev xfs0 c 103 0 $private
+ makedev nnpfs0 c 103 0 $private
+ ;;
+ logiscan)
+ major=`Major logiscan` || continue
+ makedev $arg c $major 0 $scanner
+ ;;
+ toshiba)
+ major=`Major $arg 10` || continue
+ makedev $arg c $major 181 root root 0666
+ ;;
+ m105scan)
+ major=`Major m105` || continue
+ makedev $arg c $major 0 $scanner
+ ;;
+ ac4096)
+ major=`Major ac4096` || continue
+ makedev $arg c $major 0 $scanner
+ ;;
+ audio)
+ major=`Major sound 14`
+ makedev mixer c $major 0 $audio
+ makedev mixer1 c $major 16 $audio
+ makedev mixer2 c $major 32 $audio
+ makedev mixer3 c $major 48 $audio
+ makedev sequencer c $major 1 $audio
+ makedev midi00 c $major 2 $audio
+ makedev midi01 c $major 18 $audio
+ makedev midi02 c $major 34 $audio
+ makedev midi03 c $major 50 $audio
+ makedev dsp c $major 3 $audio
+ makedev dsp1 c $major 19 $audio
+ makedev dsp2 c $major 35 $audio
+ makedev dsp3 c $major 51 $audio
+ makedev audio c $major 4 $audio
+ makedev audio1 c $major 20 $audio
+ makedev audio2 c $major 36 $audio
+ makedev audio3 c $major 52 $audio
+ makedev sndstat c $major 6 $audio
+ makedev audioctl c $major 7 $audio
+ major=31
+ makedev mpu401data c $major 0 $audio
+ makedev mpu401stat c $major 1 $audio
+ major=35
+ for i in 0 1 2 3
+ do
+ makedev midi$i c $major $i $audio
+ makedev rmidi$i c $major `math $i + 64` $audio
+ makedev smpte$i c $major `math $i + 128` $audio
+ done
+ ;;
+ pcaudio)
+ major=`Major pcsp 13` || continue
+ makedev pcmixer c $major 0 $audio
+ makedev pcsp c $major 3 $audio
+ makedev pcaudio c $major 4 $audio
+ ;;
+ video|video4linux|v4l|radio)
+ # video4linux api includes radio, teletext, etc.
+ major=`Major video 81` || continue
+ minor=0
+ until [ $minor -gt 63 ]
+ do
+ makedev video$minor c $major $minor $video
+ makedev radio$minor c $major `math $minor + 64` $video
+ minor=`math $minor + 1`
+ done
+ symlink radio radio0
+ minor=0
+ until [ $minor -gt 31 ]
+ do
+ makedev vtx$minor c $major `math $minor + 192` $video
+ makedev vbi$minor c $major `math $minor + 224` $video
+ minor=`math $minor + 1`
+ done
+ symlink video video0
+ symlink vbi vbi0
+ major=82
+ minor=0
+ until [ $minor -gt 1 ]
+ do
+ makedev winradio$minor c $major $minor $video
+ minor=`math $minor + 1`
+ done
+ major=83
+ makedev vtx c $major 0 $video
+ makedev vttuner c $major 16 $video
+ ;;
+ i2c)
+ # making it possible to create an arbitrary number of i2c
+ # devices might be good, but 8 should suffice for now
+ major=`Major i2c 89` || continue
+ minor=0
+ until [ $minor -gt 7 ]
+ do
+ makedev i2c-$minor c $major $minor $private
+ minor=`math $minor + 1`
+ done
+ ;;
+ tlk)
+ major=102
+ minor=0
+ until [ $minor -gt 3 ] # tell me if 3 is wrong...
+ do
+ makedev tlk$minor c $major $minor $video
+ minor=`math $minor + 1`
+ done
+ ;;
+ srnd)
+ makedev srnd0 c 110 0 $video
+ makedev srnd1 c 110 1 $video
+ ;;
+ fgrab)
+ makedev mmetfgrab c 40 0 $video
+ makedev wvisfgrab c 26 0 $video
+ for i in 0 1 # more?
+ do
+ makedev iscc$i c 93 $i $video
+ makedev isccctl$i c 93 `math $i + 128` $video
+ done
+ for i in 0 1 # more?
+ do
+ makedev dcxx$i c 94 $i $video
+ done
+ ;;
+ sg|sg-all)
+ major=`Major sg 21`
+ for unit in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ do
+ makedev sg$unit c $major $unit $scsi
+ done
+ ;;
+ pg)
+ major=`Major pg 97`
+ for unit in 0 1 2 3
+ do
+ makedev pg$unit c $major $unit $scsi
+ done
+ ;;
+ fd)
+ # not really devices, we use the /proc filesystem
+ symlink fd $procfs/self/fd
+ symlink stdin fd/0
+ symlink stdout fd/1
+ symlink stderr fd/2
+ ;;
+ ibcs2)
+ major=`Major ibcs2 30` || continue
+ makedev socksys c $major 0 $ibcs2
+ symlink nfsd socksys
+ makedev spx c $major 1 $ibcs2
+ symlink X0R null
+ ;;
+ netlink)
+ major=36
+ makedev route c $major 0 $private
+ makedev skip c $major 1 $private
+ ;;
+ enskip)
+ major=64
+ makedev enskip c $major 0 $private
+ ;;
+ ipfilt*)
+ major=95
+ makedev ipl c $major 0 $private
+ makedev ipnat c $major 1 $private
+ makedev ipstate c $major 2 $private
+ makedev ipauth c $major 3 $private
+ ;;
+ qng)
+ makedev qng c 77 0 $private
+ ;;
+ apm)
+ major=`Major mouse 10` || continue
+ makedev apm_bios c $major 134 $mouse
+ ;;
+ dcf)
+ major=`Major dcf` || continue
+ makedev $arg c $major 0 $system
+ ;;
+ helloworld)
+ major=`Major hw` || continue
+ makedev helloworld c $major 0 $public
+ ;;
+ ipsec)
+ # For the Free S/WAN (http://www.xs4all.nl/~freeswan/)
+ # implementation of IPSEC
+ makedev ipsec c 36 10 $ipsec
+ ;;
+ comedi)
+ major=98
+ for minor in 0 1 2 3
+ do
+ makedev comedi$minor c $major $minor $public
+ done
+ ;;
+ tilp)
+ for i in `seq 0 7`
+ do
+ makedev tipar$i c 115 $i $printer
+ makedev tiser$i c 115 `math 8 + $i` $dialout
+ done
+ for i in `seq 0 31`
+ do
+ makedev tiusb$i c 115 `math 16 + $i` $dialout
+ done
+ ;;
+ dvb)
+ # check if kernel-version is >= 2.6.8, if yes, create dvb-devices with
+ # major-number 212, in the other case 250
+
+ kern_rev1=`uname -r | sed -e 's@^\([^.]*\)\..*@\1@'`
+ kern_rev2=`uname -r | sed -e 's@^[^.]*\.\([^.]*\)\..*@\1@'`
+ kern_rev3=`uname -r | sed -e 's@^[^.]*\.[^.]*\.\([^.][0-9]*\).*@\1@'`
+
+ dvb_major=250
+
+ if [ $kern_rev1 -gt 2 ] || ([ $kern_rev1 -eq 2 ] && [ $kern_rev2 -gt 6 ]) \
+ || ([ $kern_rev1 -eq 2 ] && [ $kern_rev2 -eq 6 ] && [ $kern_rev3 -ge 8 ])
+ then
+ dvb_major=212
+ fi
+
+ mkdir -p dvb
+ for i in 0 1 2 3
+ do
+ mkdir -p dvb/adapter$i
+ makedev dvb/adapter$i/video0 c $dvb_major `math 64 \* $i + 0` $video
+ makedev dvb/adapter$i/audio0 c $dvb_major `math 64 \* $i + 1` $video
+ makedev dvb/adapter$i/frontend0 c $dvb_major `math 64 \* $i + 3` $video
+ makedev dvb/adapter$i/demux0 c $dvb_major `math 64 \* $i + 4` $video
+ makedev dvb/adapter$i/dvr0 c $dvb_major `math 64 \* $i + 5` $video
+ makedev dvb/adapter$i/ca0 c $dvb_major `math 64 \* $i + 6` $video
+ makedev dvb/adapter$i/net0 c $dvb_major `math 64 \* $i + 7` $video
+ makedev dvb/adapter$i/osd0 c $dvb_major `math 64 \* $i + 8` $video
+ done
+ ;;
+ usb)
+ mkdir -p usb
+ major=180
+ for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ makedev usb/lp$i c $major $i $printer
+ makedev usb/mouse$i c $major `math $i + 16` $mouse
+ makedev usb/ez$i c $major `math $i + 32` $system
+ makedev usb/scanner$i c $major `math $i + 48` $scanner
+ makedev usb/hiddev$i c $major `math $i + 96` $system
+ makedev ttyACM$i c 166 $i $dialout
+ makedev ttyUSB$i c 188 $i $dialout
+ done
+ makedev usb/rio500 c $major 64 $audio
+ makedev usb/usblcd c $major 65 $audio
+ makedev usb/cpad0 c $major 66 $audio
+ ;;
+ bluetooth)
+ major=216
+ for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 \
+ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ do
+ makedev rfcomm$i c $major $i $dialout
+ done
+ makedev vhci c 10 250 $dialout
+ for i in 0 1 2 3; do
+ makedev ttyUB$i c 216 $i $dialout
+ makedev ccub$i c 217 $i $dialout
+ done
+ ;;
+ paride)
+ major=45
+ for unit in a b c d
+ do
+ base=`index abcd $unit`
+ base=`math $base \* 16`
+ makedev pd$unit b $major $base $disk
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ do
+ makedev pd$unit$part b $major $(( $base + $part )) $disk
+ done
+ done
+ for i in 0 1 2 3
+ do
+ makedev pcd$i b 46 $i $cdrom
+ makedev pf$i b 47 $i $floppy
+ done
+ ;;
+ lirc)
+ makedev lirc c 61 0 $lirc
+ for i in d m; do
+ makefifo lirc${i} $lirc
+ done
+ ;;
+ update)
+ devices=
+ if [ ! -f $procfs/devices ]
+ then
+ echo "$0: warning: can't read $procfs/devices" >&2
+ else
+ exec 3<$procfs/devices
+ while read major device extra <&3
+ do
+ device=`echo $device | sed 's#/.*##'`
+ case "$major" in
+ Character|Block|'')
+ ;;
+ *)
+ eval "major_$device=$major"
+ devices="$devices $device"
+ ;;
+ esac
+ done
+ exec 3<&-
+ fi
+
+ if [ ! "$devices" ]
+ then
+ echo "$0: don't appear to have any devices" >&2
+ continue
+ fi
+ if [ "$opt_d" ]
+ then
+ echo "$0: can't delete an update" >&2
+ continue
+ fi
+ create=
+ delete=
+ devs="$devices"
+ if [ -f DEVICES ]
+ then
+ exec 3 DEVICES
+ ;;
+ *)
+ echo "$0: don't know how to make device \"$arg\"" >&2
+ exit 1
+ ;;
+ esac
+done
+
+exit 0
diff --git a/tools/udev_to_vdev/udev_rule.h b/tools/udev_to_vdev/udev_rule.h
index b4446a8..c9a46e6 100644
--- a/tools/udev_to_vdev/udev_rule.h
+++ b/tools/udev_to_vdev/udev_rule.h
@@ -14,14 +14,24 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH RE
#include
#include
-template
-class lockable : public type
+template < typename type > class lockable:public type
{
public:
- inline lockable(void) : m_locked(false) { }
- inline bool is_locked(void) const { return m_locked; }
- inline void lock (void) { m_locked = true ; }
- inline void unlock(void) { m_locked = false; }
+ inline lockable (void):m_locked (false)
+ {
+ }
+ inline bool is_locked (void) const
+ {
+ return m_locked;
+ }
+ inline void lock (void)
+ {
+ m_locked = true;
+ }
+ inline void unlock (void)
+ {
+ m_locked = false;
+ }
private:
bool m_locked;
};
@@ -29,38 +39,55 @@ class lockable : public type
// parser a single field
struct udev_field_t
{
- inline udev_field_t(void) { subname.lock(); }
- bool operator << (const char& input) throw(const char*); // returns false when full
- void clear(void);
- inline bool full(void) const { return value.is_locked(); }
- inline bool empty(void) const { return value.empty(); }
-
- lockable name;
- lockable subname;
- lockable op;
- lockable value;
+ inline udev_field_t (void)
+ {
+ subname.lock ();
+ } bool operator << (const char &input) throw (const char *); // returns false when full
+ void clear (void);
+ inline bool full (void) const
+ {
+ return value.is_locked ();
+ }
+ inline bool empty (void) const
+ {
+ return value.empty ();
+ }
+ lockable < std::string > name;
+ lockable < std::string > subname;
+ lockable < std::string > op;
+ lockable < std::string > value;
};
// parses all fields in rule
struct udev_rule_t
{
- inline udev_rule_t(void) : line_continues(false) { fields.emplace_back(); comment.lock(); }
- bool operator << (const char& input) throw(const char*); // returns false when full
- void clear(void);
- inline bool full(void) const { return fields.is_locked(); }
- inline bool empty(void) const { return fields.back().empty(); }
-
- lockable> fields;
+ inline udev_rule_t (void):line_continues (false)
+ {
+ fields.emplace_back ();
+ comment.lock ();
+ } bool operator << (const char &input) throw (const char *); // returns false when full
+ void clear (void);
+ inline bool full (void) const
+ {
+ return fields.is_locked ();
+ }
+ inline bool empty (void) const
+ {
+ return fields.back ().empty ();
+ }
+ lockable < std::list < udev_field_t >> fields;
bool line_continues;
- lockable comment;
+ lockable < std::string > comment;
};
struct udev_rule_file_t
{
- inline udev_rule_file_t(void) { rules.emplace_back(); }
- void operator << (const char& input) throw(const char*);
- void clear(void);
+ inline udev_rule_file_t (void)
+ {
+ rules.emplace_back ();
+ } void operator << (const char &input) throw (const char *);
+ void clear (void);
- std::list rules;
+ std::list < udev_rule_t > rules;
};
#endif // UDEV_FIELD_H
diff --git a/vdevd/action.c b/vdevd/action.c
index 9d3c845..ab8e1f4 100644
--- a/vdevd/action.c
+++ b/vdevd/action.c
@@ -29,802 +29,955 @@
#include "libvdev/ini.h"
// to be passed into the action loader loop
-struct vdev_action_loader_cls {
+struct vdev_action_loader_cls
+{
- struct sglib_vdev_action_vector* acts;
- struct vdev_config* config;
+ struct sglib_vdev_action_vector *acts;
+ struct vdev_config *config;
};
// prototypes
-SGLIB_DEFINE_VECTOR_PROTOTYPES( vdev_action );
-SGLIB_DEFINE_VECTOR_FUNCTIONS( vdev_action );
+SGLIB_DEFINE_VECTOR_PROTOTYPES (vdev_action);
+SGLIB_DEFINE_VECTOR_FUNCTIONS (vdev_action);
-static int vdev_action_daemonlet_stop( struct vdev_action* act );
+static int vdev_action_daemonlet_stop (struct vdev_action *act);
// initialize an action
// return 0 on success
// return -ENOMEM on OOM
-int vdev_action_init( struct vdev_action* act, vdev_device_request_t trigger, char* path, char* command, char* helper, bool async ) {
-
- int rc = 0;
- memset( act, 0, sizeof(struct vdev_action) );
-
- act->trigger = trigger;
- act->path = vdev_strdup_or_null( path );
- act->command = vdev_strdup_or_null( command );
- act->helper = vdev_strdup_or_null( helper );
- act->async = async;
-
- act->is_daemonlet = false;
- act->daemonlet_stdin = -1;
- act->daemonlet_stdout = -1;
- act->daemonlet_pid = -1;
-
- if( act->path != NULL ) {
-
- rc = vdev_match_regex_init( &act->path_regex, path );
-
- if( rc != 0 ) {
-
- vdev_error("vdev_match_regex_init('%s') rc = %d\n", path, rc );
- vdev_action_free( act );
- return rc;
- }
- }
-
- return 0;
+int
+vdev_action_init (struct vdev_action *act, vdev_device_request_t trigger,
+ char *path, char *command, char *helper, bool async)
+{
+
+ int rc = 0;
+ memset (act, 0, sizeof (struct vdev_action));
+
+ act->trigger = trigger;
+ act->path = vdev_strdup_or_null (path);
+ act->command = vdev_strdup_or_null (command);
+ act->helper = vdev_strdup_or_null (helper);
+ act->async = async;
+
+ act->is_daemonlet = false;
+ act->daemonlet_stdin = -1;
+ act->daemonlet_stdout = -1;
+ act->daemonlet_pid = -1;
+
+ if (act->path != NULL)
+ {
+
+ rc = vdev_match_regex_init (&act->path_regex, path);
+
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_match_regex_init('%s') rc = %d\n", path, rc);
+ vdev_action_free (act);
+ return rc;
+ }
+ }
+
+ return 0;
}
// add a device parameter to match on
// return 0 on success
// return -ENOMEM on OOM
// return -EEXIST if name already exists
-int vdev_action_add_param( struct vdev_action* act, char const* name, char const* value ) {
- return vdev_params_add( &act->dev_params, name, value );
+int
+vdev_action_add_param (struct vdev_action *act, char const *name,
+ char const *value)
+{
+ return vdev_params_add (&act->dev_params, name, value);
}
-
// add an environment variable to send to a helper
// return 0 on success
// return -ENOMEM on OOM
// return -EEXIST if the name already exists
-int vdev_action_add_var( struct vdev_action* act, char const* name, char const* value ) {
- return vdev_params_add( &act->helper_vars, name, value );
+int
+vdev_action_add_var (struct vdev_action *act, char const *name,
+ char const *value)
+{
+ return vdev_params_add (&act->helper_vars, name, value);
}
// free an action
// always succeeds
// NOTE: does NOT touch the daemonlet state.
-int vdev_action_free( struct vdev_action* act ) {
-
- if( act->name != NULL ) {
-
- free( act->name );
+int
+vdev_action_free (struct vdev_action *act)
+{
+
+ if (act->name != NULL)
+ {
+
+ free (act->name);
act->name = NULL;
- }
-
- if( act->command != NULL ) {
-
- free( act->command );
+ }
+
+ if (act->command != NULL)
+ {
+
+ free (act->command);
act->command = NULL;
- }
-
- if( act->rename_command != NULL ) {
-
- free( act->rename_command );
+ }
+
+ if (act->rename_command != NULL)
+ {
+
+ free (act->rename_command);
act->rename_command = NULL;
- }
-
- if( act->dev_params != NULL ) {
-
- vdev_params_free( act->dev_params );
+ }
+
+ if (act->dev_params != NULL)
+ {
+
+ vdev_params_free (act->dev_params);
act->dev_params = NULL;
- }
-
- if( act->helper_vars != NULL ) {
-
- vdev_params_free( act->helper_vars );
+ }
+
+ if (act->helper_vars != NULL)
+ {
+
+ vdev_params_free (act->helper_vars);
act->helper_vars = NULL;
- }
-
- if( act->helper != NULL ) {
-
- free( act->helper );
+ }
+
+ if (act->helper != NULL)
+ {
+
+ free (act->helper);
act->helper = NULL;
- }
-
- if( act->path != NULL ) {
-
- free( act->path );
+ }
+
+ if (act->path != NULL)
+ {
+
+ free (act->path);
act->path = NULL;
-
-
- regfree( &act->path_regex );
- }
-
- if( act->type != NULL ) {
-
- free( act->type );
+
+ regfree (&act->path_regex);
+ }
+
+ if (act->type != NULL)
+ {
+
+ free (act->type);
act->type = NULL;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// convert an action into a device request
// return the constant associated with the type on success
// return VDEV_DEVICE_INVALID if the type is not recognized
-vdev_device_request_t vdev_action_parse_trigger( char const* type ) {
-
- if( strcmp(type, VDEV_ACTION_EVENT_ADD) == 0 ) {
+vdev_device_request_t
+vdev_action_parse_trigger (char const *type)
+{
+
+ if (strcmp (type, VDEV_ACTION_EVENT_ADD) == 0)
+ {
return VDEV_DEVICE_ADD;
- }
- else if( strcmp(type, VDEV_ACTION_EVENT_REMOVE) == 0 ) {
+ }
+ else if (strcmp (type, VDEV_ACTION_EVENT_REMOVE) == 0)
+ {
return VDEV_DEVICE_REMOVE;
- }
- else if( strcmp(type, VDEV_ACTION_EVENT_CHANGE) == 0 ) {
+ }
+ else if (strcmp (type, VDEV_ACTION_EVENT_CHANGE) == 0)
+ {
return VDEV_DEVICE_CHANGE;
- }
- else if( strcmp(type, VDEV_ACTION_EVENT_ANY) == 0 ) {
+ }
+ else if (strcmp (type, VDEV_ACTION_EVENT_ANY) == 0)
+ {
return VDEV_DEVICE_ANY;
- }
-
- return VDEV_DEVICE_INVALID;
+ }
+
+ return VDEV_DEVICE_INVALID;
}
// parse an action from an ini file
// return 1 for parsed
// return 0 for not parsed
-static int vdev_action_ini_parser( void* userdata, char const* section, char const* name, char const* value ) {
-
- struct vdev_action* act = (struct vdev_action*)userdata;
- int rc = 0;
-
- if( strcmp(section, VDEV_ACTION_NAME) == 0 ) {
-
- if( strcmp(name, VDEV_ACTION_NAME_PATH) == 0 ) {
- // path?
- if( act->path != NULL ) {
-
- free( act->path );
- }
-
- act->path = vdev_strdup_or_null( value );
-
- if( act->path == NULL ) {
- // EOM
- return 0;
- }
- else {
- rc = vdev_match_regex_init( &act->path_regex, act->path );
-
- if( rc != 0 ) {
-
- vdev_error("vdev_match_regex_init('%s') rc = %d\n", act->path, rc );
- return 0;
- }
- }
- return 1;
- }
-
- if( strcmp(name, VDEV_ACTION_NAME_RENAME) == 0 ) {
-
- // rename command
- if( act->rename_command != NULL ) {
-
- free( act->rename_command );
- }
-
- act->rename_command = vdev_strdup_or_null( value );
- return 1;
- }
-
- if( strcmp(name, VDEV_ACTION_NAME_EVENT) == 0 ) {
-
- // event?
- act->trigger = vdev_action_parse_trigger( value );
-
- if( act->trigger == VDEV_DEVICE_INVALID ) {
-
- fprintf(stderr, "Invalid event type '%s'\n", value);
- return 0;
- }
- else {
- return 1;
- }
- }
-
- if( strcmp(name, VDEV_ACTION_NAME_COMMAND) == 0 ) {
-
- // shell command
- if( act->command != NULL ) {
-
- free( act->command );
- }
-
- act->command = vdev_strdup_or_null( value );
- return 1;
- }
-
- if( strcmp(name, VDEV_ACTION_NAME_HELPER) == 0 ) {
-
- // helper in /lib/vdev
- if( act->helper != NULL ) {
-
- free( act->helper );
- }
-
- act->helper = vdev_strdup_or_null( value );
- return 1;
- }
-
- if( strcmp(name, VDEV_ACTION_NAME_ASYNC) == 0 ) {
-
- // async?
- if( strcasecmp(value, "true") == 0 || strcmp(value, "1") == 0 ) {
-
- act->async = true;
- return 1;
- }
- else if( strcasecmp(value, "false") == 0 || strcmp(value, "0") == 0 ) {
-
- act->async = false;
- return 1;
- }
- else {
-
- fprintf(stderr, "Invalid async value '%s'\n", value);
- return 0;
- }
- }
-
- if( strcmp(name, VDEV_ACTION_NAME_TYPE) == 0 ) {
-
- // remember this
- act->has_type = true;
- act->type = vdev_strdup_or_null( value );
- return 1;
- }
-
- if( strcmp(name, VDEV_ACTION_NAME_IF_EXISTS) == 0 ) {
-
- // if-exists flag
- if( strcmp( value, VDEV_ACTION_IF_EXISTS_ERROR ) == 0 ) {
-
- act->if_exists = VDEV_IF_EXISTS_ERROR;
- return 1;
- }
-
- if( strcmp( value, VDEV_ACTION_IF_EXISTS_MASK ) == 0 ) {
-
- act->if_exists = VDEV_IF_EXISTS_MASK;
- return 1;
- }
-
- if( strcmp( value, VDEV_ACTION_IF_EXISTS_RUN ) == 0 ) {
-
- act->if_exists = VDEV_IF_EXISTS_RUN;
- return 1;
- }
-
- fprintf(stderr, "Invalid '%s' value '%s'\n", name, value );
- return 0;
- }
-
- if( strcmp(name, VDEV_ACTION_DAEMONLET) == 0 ) {
-
- // this is a daemonlet
- if( strcasecmp( value, "true" ) == 0 ) {
-
- act->is_daemonlet = true;
- }
-
- return 1;
- }
-
- if( strncmp(name, VDEV_ACTION_NAME_OS_PREFIX, strlen(VDEV_ACTION_NAME_OS_PREFIX)) == 0 ) {
-
- // OS-specific param
- rc = vdev_action_add_param( act, name + strlen(VDEV_ACTION_NAME_OS_PREFIX), value );
-
- if( rc == 0 ) {
- return 1;
- }
- else {
- vdev_error("vdev_action_add_param( '%s', '%s' ) rc = %d\n", name, value, rc );
- return 0;
- }
- }
-
- if( strncmp(name, VDEV_ACTION_NAME_VAR_PREFIX, strlen(VDEV_ACTION_NAME_VAR_PREFIX)) == 0 ) {
-
- // helper-specific variable
- rc = vdev_action_add_var( act, name + strlen(VDEV_ACTION_NAME_VAR_PREFIX), value );
-
- if( rc == 0 ) {
- return 1;
- }
- else {
- vdev_error("vdev_action_add_var( '%s', '%s' ) rc = %d\n", name, value, rc );
- return 0;
- }
- }
- fprintf(stderr, "Unknown field '%s' in section '%s'\n", name, section );
+static int
+vdev_action_ini_parser (void *userdata, char const *section,
+ char const *name, char const *value)
+{
+
+ struct vdev_action *act = (struct vdev_action *) userdata;
+ int rc = 0;
+
+ if (strcmp (section, VDEV_ACTION_NAME) == 0)
+ {
+
+ if (strcmp (name, VDEV_ACTION_NAME_PATH) == 0)
+ {
+ // path?
+ if (act->path != NULL)
+ {
+
+ free (act->path);
+ }
+
+ act->path = vdev_strdup_or_null (value);
+
+ if (act->path == NULL)
+ {
+ // EOM
+ return 0;
+ }
+ else
+ {
+ rc = vdev_match_regex_init (&act->path_regex, act->path);
+
+ if (rc != 0)
+ {
+
+ vdev_error
+ ("vdev_match_regex_init('%s') rc = %d\n", act->path, rc);
+ return 0;
+ }
+ }
+ return 1;
+ }
+
+ if (strcmp (name, VDEV_ACTION_NAME_RENAME) == 0)
+ {
+
+ // rename command
+ if (act->rename_command != NULL)
+ {
+
+ free (act->rename_command);
+ }
+
+ act->rename_command = vdev_strdup_or_null (value);
+ return 1;
+ }
+
+ if (strcmp (name, VDEV_ACTION_NAME_EVENT) == 0)
+ {
+
+ // event?
+ act->trigger = vdev_action_parse_trigger (value);
+
+ if (act->trigger == VDEV_DEVICE_INVALID)
+ {
+
+ fprintf (stderr, "Invalid event type '%s'\n", value);
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+
+ if (strcmp (name, VDEV_ACTION_NAME_COMMAND) == 0)
+ {
+
+ // shell command
+ if (act->command != NULL)
+ {
+
+ free (act->command);
+ }
+
+ act->command = vdev_strdup_or_null (value);
+ return 1;
+ }
+
+ if (strcmp (name, VDEV_ACTION_NAME_HELPER) == 0)
+ {
+
+ // helper in /lib/vdev
+ if (act->helper != NULL)
+ {
+
+ free (act->helper);
+ }
+
+ act->helper = vdev_strdup_or_null (value);
+ return 1;
+ }
+
+ if (strcmp (name, VDEV_ACTION_NAME_ASYNC) == 0)
+ {
+
+ // async?
+ if (strcasecmp (value, "true") == 0 || strcmp (value, "1") == 0)
+ {
+
+ act->async = true;
+ return 1;
+ }
+ else if (strcasecmp (value, "false") == 0
+ || strcmp (value, "0") == 0)
+ {
+
+ act->async = false;
+ return 1;
+ }
+ else
+ {
+
+ fprintf (stderr, "Invalid async value '%s'\n", value);
+ return 0;
+ }
+ }
+
+ if (strcmp (name, VDEV_ACTION_NAME_TYPE) == 0)
+ {
+
+ // remember this
+ act->has_type = true;
+ act->type = vdev_strdup_or_null (value);
+ return 1;
+ }
+
+ if (strcmp (name, VDEV_ACTION_NAME_IF_EXISTS) == 0)
+ {
+
+ // if-exists flag
+ if (strcmp (value, VDEV_ACTION_IF_EXISTS_ERROR) == 0)
+ {
+
+ act->if_exists = VDEV_IF_EXISTS_ERROR;
+ return 1;
+ }
+
+ if (strcmp (value, VDEV_ACTION_IF_EXISTS_MASK) == 0)
+ {
+
+ act->if_exists = VDEV_IF_EXISTS_MASK;
+ return 1;
+ }
+
+ if (strcmp (value, VDEV_ACTION_IF_EXISTS_RUN) == 0)
+ {
+
+ act->if_exists = VDEV_IF_EXISTS_RUN;
+ return 1;
+ }
+
+ fprintf (stderr, "Invalid '%s' value '%s'\n", name, value);
+ return 0;
+ }
+
+ if (strcmp (name, VDEV_ACTION_DAEMONLET) == 0)
+ {
+
+ // this is a daemonlet
+ if (strcasecmp (value, "true") == 0)
+ {
+
+ act->is_daemonlet = true;
+ }
+
+ return 1;
+ }
+
+ if (strncmp
+ (name, VDEV_ACTION_NAME_OS_PREFIX,
+ strlen (VDEV_ACTION_NAME_OS_PREFIX)) == 0)
+ {
+
+ // OS-specific param
+ rc = vdev_action_add_param (act,
+ name +
+ strlen
+ (VDEV_ACTION_NAME_OS_PREFIX), value);
+
+ if (rc == 0)
+ {
+ return 1;
+ }
+ else
+ {
+ vdev_error
+ ("vdev_action_add_param( '%s', '%s' ) rc = %d\n",
+ name, value, rc);
+ return 0;
+ }
+ }
+
+ if (strncmp
+ (name, VDEV_ACTION_NAME_VAR_PREFIX,
+ strlen (VDEV_ACTION_NAME_VAR_PREFIX)) == 0)
+ {
+
+ // helper-specific variable
+ rc = vdev_action_add_var (act,
+ name +
+ strlen
+ (VDEV_ACTION_NAME_VAR_PREFIX), value);
+
+ if (rc == 0)
+ {
+ return 1;
+ }
+ else
+ {
+ vdev_error
+ ("vdev_action_add_var( '%s', '%s' ) rc = %d\n",
+ name, value, rc);
+ return 0;
+ }
+ }
+ fprintf (stderr, "Unknown field '%s' in section '%s'\n", name, section);
return 0;
- }
-
- fprintf(stderr, "Unknown section '%s'\n", section);
- return 0;
+ }
+
+ fprintf (stderr, "Unknown section '%s'\n", section);
+ return 0;
}
// sanity check an action
// return 0 on success
// return -EINVAL if invalid
-int vdev_action_sanity_check( struct vdev_action* act ) {
-
- int rc = 0;
-
- if( act->command == NULL && act->rename_command == NULL && act->helper == NULL ) {
-
- fprintf(stderr, "Action is missing 'command=', 'rename_command=', and 'helper='\n");
+int
+vdev_action_sanity_check (struct vdev_action *act)
+{
+
+ int rc = 0;
+
+ if (act->command == NULL && act->rename_command == NULL
+ && act->helper == NULL)
+ {
+
+ fprintf (stderr,
+ "Action is missing 'command=', 'rename_command=', and 'helper='\n");
rc = -EINVAL;
- }
-
- if( act->command != NULL && act->helper != NULL ) {
-
- fprintf(stderr, "Action has both 'command=' and 'helper='\n");
+ }
+
+ if (act->command != NULL && act->helper != NULL)
+ {
+
+ fprintf (stderr, "Action has both 'command=' and 'helper='\n");
rc = -EINVAL;
- }
-
- if( act->trigger == VDEV_DEVICE_INVALID ) {
-
- fprintf(stderr, "Action is missing 'event='\n");
+ }
+
+ if (act->trigger == VDEV_DEVICE_INVALID)
+ {
+
+ fprintf (stderr, "Action is missing 'event='\n");
rc = -EINVAL;
- }
-
- return rc;
-}
+ }
+ return rc;
+}
// perform misc. post-processing on an action:
// * if the command is NULL but the helper is not, then set command to be the full path to the helper, and don't use a shell
// return 0 on success
// return -ENOMEM on OOM
-int vdev_action_postprocess( struct vdev_config* config, struct vdev_action* act ) {
-
- int rc = 0;
-
- if( act->command == NULL && act->helper != NULL ) {
-
- act->command = VDEV_CALLOC( char, strlen(config->helpers_dir) + 1 + strlen(act->helper) + 1 );
- if( act->command == NULL ) {
- return -ENOMEM;
- }
-
- sprintf( act->command, "%s/%s", config->helpers_dir, act->helper );
-
+int
+vdev_action_postprocess (struct vdev_config *config, struct vdev_action *act)
+{
+
+ int rc = 0;
+
+ if (act->command == NULL && act->helper != NULL)
+ {
+
+ act->command =
+ VDEV_CALLOC (char,
+ strlen (config->helpers_dir) + 1 +
+ strlen (act->helper) + 1);
+ if (act->command == NULL)
+ {
+ return -ENOMEM;
+ }
+
+ sprintf (act->command, "%s/%s", config->helpers_dir, act->helper);
+
act->use_shell = false;
- }
- else {
-
+ }
+ else
+ {
+
// given a shell command string
act->use_shell = true;
- }
-
- return rc;
+ }
+
+ return rc;
}
// load an action from a file
// return 0 on success
// return -errno on failure to open, read, parse, or close
// return -EINVAL if the loaded action fails our sanity tests
-int vdev_action_load_file( struct vdev_config* config, char const* path, struct vdev_action* act, FILE* f ) {
-
- int rc = 0;
-
- rc = ini_parse_file( f, vdev_action_ini_parser, act );
- if( rc != 0 ) {
- vdev_error("ini_parse_file(action) rc = %d\n", rc );
- }
- else {
- rc = vdev_action_sanity_check( act );
- if( rc != 0 ) {
- vdev_error("Invalid action '%s'\n", path );
- }
- }
-
- if( rc == 0 ) {
-
+int
+vdev_action_load_file (struct vdev_config *config, char const *path,
+ struct vdev_action *act, FILE * f)
+{
+
+ int rc = 0;
+
+ rc = ini_parse_file (f, vdev_action_ini_parser, act);
+ if (rc != 0)
+ {
+ vdev_error ("ini_parse_file(action) rc = %d\n", rc);
+ }
+ else
+ {
+ rc = vdev_action_sanity_check (act);
+ if (rc != 0)
+ {
+ vdev_error ("Invalid action '%s'\n", path);
+ }
+ }
+
+ if (rc == 0)
+ {
+
// postprocess
- rc = vdev_action_postprocess( config, act );
- }
- return rc;
+ rc = vdev_action_postprocess (config, act);
+ }
+ return rc;
}
-
// load an action from a path
// return -ENOMEM if OOM
// return -errno on failure to open or read the file
// return -EINVAL if the file could not be parsed
-int vdev_action_load( struct vdev_config* config, char const* path, struct vdev_action* act ) {
-
- int rc = 0;
- FILE* f = NULL;
-
- rc = vdev_action_init( act, VDEV_DEVICE_INVALID, NULL, NULL, NULL, false );
- if( rc != 0 ) {
-
- vdev_error("vdev_action_init('%s') rc = %d\n", path, rc );
+int
+vdev_action_load (struct vdev_config *config, char const *path,
+ struct vdev_action *act)
+{
+
+ int rc = 0;
+ FILE *f = NULL;
+
+ rc = vdev_action_init (act, VDEV_DEVICE_INVALID, NULL, NULL, NULL, false);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_action_init('%s') rc = %d\n", path, rc);
return rc;
- }
-
- f = fopen( path, "r" );
- if( f == NULL ) {
-
- vdev_action_free( act );
+ }
+
+ f = fopen (path, "r");
+ if (f == NULL)
+ {
+
+ vdev_action_free (act);
rc = -errno;
-
+
return rc;
- }
-
- rc = vdev_action_load_file( config, path, act, f );
-
- fclose( f );
-
- if( rc == -EINVAL ) {
-
- vdev_action_free( act );
- vdev_error("Invalid action '%s'\n", path );
- }
- else if( rc == 0 ) {
-
+ }
+
+ rc = vdev_action_load_file (config, path, act, f);
+
+ fclose (f);
+
+ if (rc == -EINVAL)
+ {
+
+ vdev_action_free (act);
+ vdev_error ("Invalid action '%s'\n", path);
+ }
+ else if (rc == 0)
+ {
+
// store the name
- act->name = vdev_strdup_or_null( path );
- if( act->name == NULL ) {
-
- // OOM
- vdev_action_free( act );
- rc = -ENOMEM;
- }
- }
-
- return rc;
-}
+ act->name = vdev_strdup_or_null (path);
+ if (act->name == NULL)
+ {
+
+ // OOM
+ vdev_action_free (act);
+ rc = -ENOMEM;
+ }
+ }
+ return rc;
+}
// free a C-style list of actions (including the list itself)
// always succeeds
-int vdev_action_free_all( struct vdev_action* act_list, size_t num_acts ) {
-
- int rc = 0;
-
- for( unsigned int i = 0; i < num_acts; i++ ) {
-
- rc = vdev_action_free( &act_list[i] );
- if( rc != 0 ) {
- return rc;
- }
- }
-
- free( act_list );
-
- return rc;
-}
+int
+vdev_action_free_all (struct vdev_action *act_list, size_t num_acts)
+{
+ int rc = 0;
+
+ for (unsigned int i = 0; i < num_acts; i++)
+ {
+
+ rc = vdev_action_free (&act_list[i]);
+ if (rc != 0)
+ {
+ return rc;
+ }
+ }
+
+ free (act_list);
+
+ return rc;
+}
// action loader
// return 0 on success
// return -errno on failure to stat(2)
// return -EINVAL if the file is invalid
// return -ENOMEM if OOM
-int vdev_action_loader( char const* path, void* cls ) {
-
- int rc = 0;
- struct vdev_action act;
- struct stat sb;
- struct vdev_action_loader_cls* loader_cls = (struct vdev_action_loader_cls*)cls;
-
- struct sglib_vdev_action_vector* acts = loader_cls->acts;
- struct vdev_config* config = loader_cls->config;
-
- // skip if not a regular file
- rc = stat( path, &sb );
- if( rc != 0 ) {
-
+int
+vdev_action_loader (char const *path, void *cls)
+{
+
+ int rc = 0;
+ struct vdev_action act;
+ struct stat sb;
+ struct vdev_action_loader_cls *loader_cls =
+ (struct vdev_action_loader_cls *) cls;
+
+ struct sglib_vdev_action_vector *acts = loader_cls->acts;
+ struct vdev_config *config = loader_cls->config;
+
+ // skip if not a regular file
+ rc = stat (path, &sb);
+ if (rc != 0)
+ {
+
rc = -errno;
- vdev_error("stat(%s) rc = %d\n", path, rc );
+ vdev_error ("stat(%s) rc = %d\n", path, rc);
return rc;
- }
-
- if( !S_ISREG( sb.st_mode ) ) {
-
+ }
+
+ if (!S_ISREG (sb.st_mode))
+ {
+
return 0;
- }
-
- vdev_debug("Load Action %s\n", path );
-
- memset( &act, 0, sizeof(struct vdev_action) );
-
- rc = vdev_action_load( config, path, &act );
- if( rc != 0 ) {
-
- vdev_error("vdev_acl_load(%s) rc = %d\n", path, rc );
+ }
+
+ vdev_debug ("Load Action %s\n", path);
+
+ memset (&act, 0, sizeof (struct vdev_action));
+
+ rc = vdev_action_load (config, path, &act);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_acl_load(%s) rc = %d\n", path, rc);
return rc;
- }
-
- // save this action
- rc = sglib_vdev_action_vector_push_back( acts, act );
- if( rc != 0 ) {
-
+ }
+ // save this action
+ rc = sglib_vdev_action_vector_push_back (acts, act);
+ if (rc != 0)
+ {
+
// OOM
- vdev_action_free( &act );
+ vdev_action_free (&act);
return rc;
- }
-
- return 0;
+ }
+
+ return 0;
}
// free a vector of actions
// always succeeds
-static int vdev_action_vector_free( struct sglib_vdev_action_vector* acts ) {
-
- for( unsigned long i = 0; i < sglib_vdev_action_vector_size( acts ); i++ ) {
-
- struct vdev_action* act = sglib_vdev_action_vector_at_ref( acts, i );
-
- vdev_action_free( act );
- }
-
- sglib_vdev_action_vector_clear( acts );
- return 0;
-}
+static int
+vdev_action_vector_free (struct sglib_vdev_action_vector *acts)
+{
+
+ for (unsigned long i = 0; i < sglib_vdev_action_vector_size (acts); i++)
+ {
+
+ struct vdev_action *act = sglib_vdev_action_vector_at_ref (acts, i);
+
+ vdev_action_free (act);
+ }
+ sglib_vdev_action_vector_clear (acts);
+ return 0;
+}
// load all actions in a directory
// return 0 on success
// return -ENOMEM if OOM
// return -EINVAL if at least one action file failed to load due to a sanity test failure
// return -errno if at least one action file failed to load due to an I/O error
-int vdev_action_load_all( struct vdev_config* config, struct vdev_action** ret_acts, size_t* ret_num_acts ) {
-
- int rc = 0;
- struct vdev_action_loader_cls loader_cls;
- struct sglib_vdev_action_vector acts;
-
- sglib_vdev_action_vector_init( &acts );
-
- loader_cls.acts = &acts;
- loader_cls.config = config;
-
- rc = vdev_load_all( config->acts_dir, vdev_action_loader, &loader_cls );
-
- if( rc != 0 ) {
-
- vdev_action_vector_free( &acts );
- sglib_vdev_action_vector_free( &acts );
-
+int
+vdev_action_load_all (struct vdev_config *config,
+ struct vdev_action **ret_acts, size_t * ret_num_acts)
+{
+
+ int rc = 0;
+ struct vdev_action_loader_cls loader_cls;
+ struct sglib_vdev_action_vector acts;
+
+ sglib_vdev_action_vector_init (&acts);
+
+ loader_cls.acts = &acts;
+ loader_cls.config = config;
+
+ rc = vdev_load_all (config->acts_dir, vdev_action_loader, &loader_cls);
+
+ if (rc != 0)
+ {
+
+ vdev_action_vector_free (&acts);
+ sglib_vdev_action_vector_free (&acts);
+
return rc;
- }
- else {
-
- if( sglib_vdev_action_vector_size( &acts ) == 0 ) {
-
- // nothing
- *ret_acts = NULL;
- *ret_num_acts = 0;
- }
- else {
-
- // extract values
- unsigned long len_acts = 0;
-
- sglib_vdev_action_vector_yoink( &acts, ret_acts, &len_acts );
-
- *ret_num_acts = len_acts;
- }
- }
-
- return 0;
-}
+ }
+ else
+ {
+
+ if (sglib_vdev_action_vector_size (&acts) == 0)
+ {
+
+ // nothing
+ *ret_acts = NULL;
+ *ret_num_acts = 0;
+ }
+ else
+ {
+
+ // extract values
+ unsigned long len_acts = 0;
+ sglib_vdev_action_vector_yoink (&acts, ret_acts, &len_acts);
+
+ *ret_num_acts = len_acts;
+ }
+ }
+
+ return 0;
+}
// carry out a command, synchronously, using an environment given by vreq.
// stdout will be captured to *output
// return the exit status on success (non-negative)
// return negative on error
-int vdev_action_run_sync( struct vdev_device_request* vreq, char const* command, vdev_params* helper_vars, bool use_shell, char** output, size_t max_output ) {
-
- int rc = 0;
- int exit_status = 0;
- char** req_env = NULL;
- size_t num_env = 0;
-
- // convert to environment variables
- rc = vdev_device_request_to_env( vreq, helper_vars, &req_env, &num_env, 0 );
- if( rc != 0 ) {
-
- vdev_error("vdev_device_request_to_env(%s) rc = %d\n", vreq->path, rc );
+int
+vdev_action_run_sync (struct vdev_device_request *vreq, char const *command,
+ vdev_params * helper_vars, bool use_shell,
+ char **output, size_t max_output)
+{
+
+ int rc = 0;
+ int exit_status = 0;
+ char **req_env = NULL;
+ size_t num_env = 0;
+
+ // convert to environment variables
+ rc = vdev_device_request_to_env (vreq, helper_vars, &req_env, &num_env, 0);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_device_request_to_env(%s) rc = %d\n", vreq->path, rc);
return rc;
- }
-
- vdev_debug("run command: '%s'\n", command );
-
- for( unsigned int i = 0; i < num_env; i++ ) {
- vdev_debug("command env: '%s'\n", req_env[i] );
- }
-
- rc = vdev_subprocess( command, req_env, output, max_output, vreq->state->error_fd, &exit_status, use_shell );
-
- vdev_debug("exit status %d\n", exit_status );
-
- if( output != NULL && *output != NULL ) {
-
- vdev_debug("command output: '%s'\n", *output );
- }
-
- VDEV_FREE_LIST( req_env );
-
- if( rc != 0 ) {
-
- vdev_error("vdev_subprocess('%s', use_shell=%d) rc = %d\n", command, use_shell, rc );
-
+ }
+
+ vdev_debug ("run command: '%s'\n", command);
+
+ for (unsigned int i = 0; i < num_env; i++)
+ {
+ vdev_debug ("command env: '%s'\n", req_env[i]);
+ }
+
+ rc = vdev_subprocess (command, req_env, output, max_output,
+ vreq->state->error_fd, &exit_status, use_shell);
+
+ vdev_debug ("exit status %d\n", exit_status);
+
+ if (output != NULL && *output != NULL)
+ {
+
+ vdev_debug ("command output: '%s'\n", *output);
+ }
+
+ VDEV_FREE_LIST (req_env);
+
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_subprocess('%s', use_shell=%d) rc = %d\n",
+ command, use_shell, rc);
+
return rc;
- }
-
- if( exit_status != 0 ) {
-
- vdev_error("vdev_subprocess('%s', use_shell=%d) exit status = %d\n", command, use_shell, exit_status );
- }
-
- return exit_status;
-}
+ }
+ if (exit_status != 0)
+ {
+
+ vdev_error
+ ("vdev_subprocess('%s', use_shell=%d) exit status = %d\n",
+ command, use_shell, exit_status);
+ }
+
+ return exit_status;
+}
// carry out an action, asynchronously.
// fork, setsid, fork, and exec, so the helper gets reparented to init.
// return 0 if we were able to fork
// return -errno on failure to fork
// TODO: configurable interpreter (defaults to /bin/dash)
-int vdev_action_run_async( struct vdev_device_request* req, char const* command, vdev_params* helper_vars, bool use_shell ) {
-
- int rc = 0;
- pid_t pid = 0;
- pid_t sid = 0;
- int max_fd = 0;
-
- // generate the environment
- char** env = NULL;
- size_t num_env = 0;
-
- rc = vdev_device_request_to_env( req, helper_vars, &env, &num_env, 0 );
- if( rc != 0 ) {
-
+int
+vdev_action_run_async (struct vdev_device_request *req, char const *command,
+ vdev_params * helper_vars, bool use_shell)
+{
+
+ int rc = 0;
+ pid_t pid = 0;
+ pid_t sid = 0;
+ int max_fd = 0;
+
+ // generate the environment
+ char **env = NULL;
+ size_t num_env = 0;
+
+ rc = vdev_device_request_to_env (req, helper_vars, &env, &num_env, 0);
+ if (rc != 0)
+ {
+
// NOTE: must be async-safe!
- vdev_error("vdev_device_request_to_env rc = %d\n", rc);
+ vdev_error ("vdev_device_request_to_env rc = %d\n", rc);
return rc;
- }
-
- vdev_debug("run command async: '%s'\n", command );
-
- for( unsigned int i = 0; i < num_env; i++ ) {
- vdev_debug("command async env: '%s'\n", env[i] );
- }
-
- pid = fork();
-
- if( pid == 0 ) {
-
+ }
+
+ vdev_debug ("run command async: '%s'\n", command);
+
+ for (unsigned int i = 0; i < num_env; i++)
+ {
+ vdev_debug ("command async env: '%s'\n", env[i]);
+ }
+
+ pid = fork ();
+
+ if (pid == 0)
+ {
+
// child
// detach from parent
- sid = setsid();
- if( sid < 0 ) {
-
- rc = -errno;
-
- // NOTE: must be async-safe!
- vdev_error_async_safe("setsid failed\n" );
- exit(1);
- }
-
- pid = fork();
-
- if( pid == 0 ) {
-
- // fully detached
- max_fd = sysconf(_SC_OPEN_MAX);
- if( max_fd < 0 ) {
-
- // should be big enough...
- max_fd = 1024;
- }
-
- // close everything except stderr, which should be directed to our log
- for( int i = 0; i < max_fd; i++ ) {
- if( i != STDERR_FILENO ) {
- close( i );
- }
- }
-
- clearenv();
-
- // run the command
- if( use_shell ) {
- execle( "/bin/dash", "dash", "-c", command, (char*)0, env );
- }
- else {
- execle( command, command, (char*)0, env );
- }
-
- // keep gcc happy
- exit(0);
- }
- else if( pid > 0 ) {
-
- exit(0);
- }
- else {
-
- rc = -errno;
- vdev_error_async_safe("fork() failed\n");
- exit(-rc);
- }
- }
- else if( pid > 0 ) {
-
+ sid = setsid ();
+ if (sid < 0)
+ {
+
+ rc = -errno;
+
+ // NOTE: must be async-safe!
+ vdev_error_async_safe ("setsid failed\n");
+ exit (1);
+ }
+
+ pid = fork ();
+
+ if (pid == 0)
+ {
+
+ // fully detached
+ max_fd = sysconf (_SC_OPEN_MAX);
+ if (max_fd < 0)
+ {
+
+ // should be big enough...
+ max_fd = 1024;
+ }
+ // close everything except stderr, which should be directed to our log
+ for (int i = 0; i < max_fd; i++)
+ {
+ if (i != STDERR_FILENO)
+ {
+ close (i);
+ }
+ }
+
+ clearenv ();
+
+ // run the command
+ if (use_shell)
+ {
+ execle ("/bin/dash", "dash", "-c", command, (char *) 0, env);
+ }
+ else
+ {
+ execle (command, command, (char *) 0, env);
+ }
+
+ // keep gcc happy
+ exit (0);
+ }
+ else if (pid > 0)
+ {
+
+ exit (0);
+ }
+ else
+ {
+
+ rc = -errno;
+ vdev_error_async_safe ("fork() failed\n");
+ exit (-rc);
+ }
+ }
+ else if (pid > 0)
+ {
+
rc = 0;
-
- VDEV_FREE_LIST( env );
-
+
+ VDEV_FREE_LIST (env);
+
// parent; succeeded
// wait for intermediate process
- pid_t child_pid = waitpid( pid, &rc, 0 );
- if( child_pid < 0 ) {
-
- rc = -errno;
- vdev_error("waitpid(%d) rc = %d\n", pid, rc );
- return rc;
- }
- else if( WIFEXITED( rc ) && WEXITSTATUS( rc ) != 0 ) {
-
- rc = -WEXITSTATUS( rc );
- vdev_error("fork() rc = %d\n", rc );
- }
-
+ pid_t child_pid = waitpid (pid, &rc, 0);
+ if (child_pid < 0)
+ {
+
+ rc = -errno;
+ vdev_error ("waitpid(%d) rc = %d\n", pid, rc);
+ return rc;
+ }
+ else if (WIFEXITED (rc) && WEXITSTATUS (rc) != 0)
+ {
+
+ rc = -WEXITSTATUS (rc);
+ vdev_error ("fork() rc = %d\n", rc);
+ }
+
return rc;
- }
- else {
-
+ }
+ else
+ {
+
// error
rc = -errno;
-
- VDEV_FREE_LIST( env );
-
- vdev_error("fork() rc = %d\n", rc);
-
+
+ VDEV_FREE_LIST (env);
+
+ vdev_error ("fork() rc = %d\n", rc);
+
return rc;
- }
+ }
}
-
// clean up a daemonlet's state in an action
// always succeeds
-static int vdev_action_daemonlet_clean( struct vdev_action* act ) {
-
- // dead
- act->daemonlet_pid = -1;
-
- if( act->daemonlet_stdin >= 0 ) {
- close( act->daemonlet_stdin );
+static int
+vdev_action_daemonlet_clean (struct vdev_action *act)
+{
+
+ // dead
+ act->daemonlet_pid = -1;
+
+ if (act->daemonlet_stdin >= 0)
+ {
+ close (act->daemonlet_stdin);
act->daemonlet_stdin = -1;
- }
-
- if( act->daemonlet_stdout >= 0 ) {
- close( act->daemonlet_stdout );
+ }
+
+ if (act->daemonlet_stdout >= 0)
+ {
+ close (act->daemonlet_stdout);
act->daemonlet_stdout = -1;
- }
-
- return 0;
+ }
+
+ return 0;
}
// start up a daemonlet, using the daemonlet helper program at $VDEV_HELPERS/daemonlet.
@@ -838,314 +991,363 @@ static int vdev_action_daemonlet_clean( struct vdev_action* act ) {
// return -errno from fork(2) if we could not fork
// return -ECHILD if the daemonlet died before it could signal readiness
// NOTE: /dev/null *must* exist already--this should be taken care of by the pre-seed script.
-static int vdev_action_daemonlet_start( struct vdev_state* state, struct vdev_action* act ) {
-
- int rc = 0;
- pid_t pid = 0;
- int daemonlet_pipe_stdin[2];
- int daemonlet_pipe_stdout[2];
- char daemonlet_runner_path[ PATH_MAX+1 ];
- char vdevd_global_metadata[ PATH_MAX+1 ];
- char null_path[ PATH_MAX+1 ];
- long max_open = sysconf( _SC_OPEN_MAX );
- struct stat sb;
- struct vdev_config* config = state->config;
-
- char* daemonlet_argv[] = {
- "vdevd-daemonlet",
- act->command,
- NULL
- };
-
- if( max_open <= 0 ) {
- max_open = 1024; // a good guess
- }
-
- if( act->daemonlet_pid > 0 ) {
+static int
+vdev_action_daemonlet_start (struct vdev_state *state,
+ struct vdev_action *act)
+{
+
+ int rc = 0;
+ pid_t pid = 0;
+ int daemonlet_pipe_stdin[2];
+ int daemonlet_pipe_stdout[2];
+ char daemonlet_runner_path[PATH_MAX + 1];
+ char vdevd_global_metadata[PATH_MAX + 1];
+ char null_path[PATH_MAX + 1];
+ long max_open = sysconf (_SC_OPEN_MAX);
+ struct stat sb;
+ struct vdev_config *config = state->config;
+
+ char *daemonlet_argv[] = {
+ "vdevd-daemonlet",
+ act->command,
+ NULL
+ };
+
+ if (max_open <= 0)
+ {
+ max_open = 1024; // a good guess
+ }
+
+ if (act->daemonlet_pid > 0)
+ {
return 0;
- }
-
- memset( daemonlet_runner_path, 0, PATH_MAX+1 );
- memset( vdevd_global_metadata, 0, PATH_MAX+1 );
-
- snprintf( daemonlet_runner_path, PATH_MAX, "%s/daemonlet", config->helpers_dir );
- snprintf( vdevd_global_metadata, PATH_MAX, "%s/" VDEV_METADATA_PREFIX, config->mountpoint );
-
- // the daemonlet runner must exist
- rc = stat( daemonlet_runner_path, &sb );
- if( rc != 0 ) {
-
- vdev_error("stat('%s') rc = %d\n", daemonlet_runner_path, rc );
+ }
+
+ memset (daemonlet_runner_path, 0, PATH_MAX + 1);
+ memset (vdevd_global_metadata, 0, PATH_MAX + 1);
+
+ snprintf (daemonlet_runner_path, PATH_MAX, "%s/daemonlet",
+ config->helpers_dir);
+ snprintf (vdevd_global_metadata, PATH_MAX, "%s/" VDEV_METADATA_PREFIX,
+ config->mountpoint);
+
+ // the daemonlet runner must exist
+ rc = stat (daemonlet_runner_path, &sb);
+ if (rc != 0)
+ {
+
+ vdev_error ("stat('%s') rc = %d\n", daemonlet_runner_path, rc);
return rc;
- }
-
- // the daemonlet runner must be executable
- if( !S_ISREG( sb.st_mode ) || !(((S_IXUSR & sb.st_mode) && sb.st_uid == geteuid()) || ((S_IXGRP & sb.st_mode) && sb.st_gid == getegid()) || (S_IXOTH & sb.st_mode )) ) {
-
- vdev_error("%s is not a regular file, or is not executable for vdevd\n", daemonlet_runner_path );
+ }
+ // the daemonlet runner must be executable
+ if (!S_ISREG (sb.st_mode)
+ || !(((S_IXUSR & sb.st_mode) && sb.st_uid == geteuid ())
+ || ((S_IXGRP & sb.st_mode) && sb.st_gid == getegid ())
+ || (S_IXOTH & sb.st_mode)))
+ {
+
+ vdev_error
+ ("%s is not a regular file, or is not executable for vdevd\n",
+ daemonlet_runner_path);
return -EPERM;
- }
-
- rc = pipe( daemonlet_pipe_stdin );
- if( rc < 0 ) {
-
+ }
+
+ rc = pipe (daemonlet_pipe_stdin);
+ if (rc < 0)
+ {
+
rc = -errno;
- vdev_error("pipe rc = %d\n", rc );
+ vdev_error ("pipe rc = %d\n", rc);
return rc;
- }
-
- rc = pipe( daemonlet_pipe_stdout );
- if( rc < 0 ) {
-
+ }
+
+ rc = pipe (daemonlet_pipe_stdout);
+ if (rc < 0)
+ {
+
rc = -errno;
- vdev_error("pipe rc = %d\n", rc );
-
- close( daemonlet_pipe_stdin[0] );
- close( daemonlet_pipe_stdin[1] );
+ vdev_error ("pipe rc = %d\n", rc);
+
+ close (daemonlet_pipe_stdin[0]);
+ close (daemonlet_pipe_stdin[1]);
return rc;
- }
-
- pid = fork();
- if( pid == 0 ) {
-
+ }
+
+ pid = fork ();
+ if (pid == 0)
+ {
+
// child
- close( daemonlet_pipe_stdin[1] );
- close( daemonlet_pipe_stdout[0] );
-
+ close (daemonlet_pipe_stdin[1]);
+ close (daemonlet_pipe_stdout[0]);
+
// redirect
- rc = dup2( daemonlet_pipe_stdin[0], STDIN_FILENO );
- if( rc < 0 ) {
-
- vdev_error_async_safe("dup2 stdin failed\n");
- exit(1);
- }
-
- rc = dup2( daemonlet_pipe_stdout[1], STDOUT_FILENO );
- if( rc < 0 ) {
-
- vdev_error_async_safe("dup2 stdout to vdevd failed\n");
- _exit(1);
- }
-
- rc = dup2( state->error_fd, STDERR_FILENO );
- if( rc < 0 ) {
-
- vdev_error_async_safe("dup2 stderr to null failed\n");
- _exit(1);
- }
-
+ rc = dup2 (daemonlet_pipe_stdin[0], STDIN_FILENO);
+ if (rc < 0)
+ {
+
+ vdev_error_async_safe ("dup2 stdin failed\n");
+ exit (1);
+ }
+
+ rc = dup2 (daemonlet_pipe_stdout[1], STDOUT_FILENO);
+ if (rc < 0)
+ {
+
+ vdev_error_async_safe ("dup2 stdout to vdevd failed\n");
+ _exit (1);
+ }
+
+ rc = dup2 (state->error_fd, STDERR_FILENO);
+ if (rc < 0)
+ {
+
+ vdev_error_async_safe ("dup2 stderr to null failed\n");
+ _exit (1);
+ }
// close everything else
// the daemonlet should capture stderr itself
- for( int i = 3; i < max_open; i++ ) {
-
- close( i );
- }
-
+ for (int i = 3; i < max_open; i++)
+ {
+
+ close (i);
+ }
+
// set basic environment variables
- clearenv();
- setenv( "VDEV_GLOBAL_METADATA", vdevd_global_metadata, 1 );
- setenv( "VDEV_MOUNTPOINT", config->mountpoint, 1 );
- setenv( "VDEV_HELPERS", config->helpers_dir, 1 );
- setenv( "VDEV_LOGFILE", config->logfile_path, 1 );
- setenv( "VDEV_CONFIG_FILE", config->config_path, 1 );
- setenv( "VDEV_INSTANCE", config->instance_str, 1 );
-
+ clearenv ();
+ setenv ("VDEV_GLOBAL_METADATA", vdevd_global_metadata, 1);
+ setenv ("VDEV_MOUNTPOINT", config->mountpoint, 1);
+ setenv ("VDEV_HELPERS", config->helpers_dir, 1);
+ setenv ("VDEV_LOGFILE", config->logfile_path, 1);
+ setenv ("VDEV_CONFIG_FILE", config->config_path, 1);
+ setenv ("VDEV_INSTANCE", config->instance_str, 1);
+
// start the daemonlet
- execv( daemonlet_runner_path, daemonlet_argv );
-
+ execv (daemonlet_runner_path, daemonlet_argv);
+
// keep gcc happy
- _exit(0);
- }
- else if( pid > 0 ) {
-
+ _exit (0);
+ }
+ else if (pid > 0)
+ {
+
// parent vdevd
- close( daemonlet_pipe_stdin[0] );
- close( daemonlet_pipe_stdout[1] );
-
+ close (daemonlet_pipe_stdin[0]);
+ close (daemonlet_pipe_stdout[1]);
+
// wait for child to indicate readiness, if running synchronously
- if( !act->async ) {
-
- while( 1 ) {
-
- char tmp = 0;
- rc = vdev_read_uninterrupted( daemonlet_pipe_stdout[0], &tmp, 1 );
-
- if( rc <= 0 ) {
-
- // some fatal error, or process has closed stdout
- // not much we can safely do at this point (don't want to risk SIGKILL'ing)
- close( daemonlet_pipe_stdin[1] );
- close( daemonlet_pipe_stdout[0] );
-
- if( rc == 0 ) {
-
- // process has closed stdout
- vdev_error("vdev_read_uninterrupted(%d PID=%d action='%s') rc = %d\n", daemonlet_pipe_stdout[0], pid, act->name, rc );
- rc = -ECHILD;
- }
-
- return rc;
- }
- else {
-
- // got back readiness hint
- break;
- }
- }
- }
-
+ if (!act->async)
+ {
+
+ while (1)
+ {
+
+ char tmp = 0;
+ rc = vdev_read_uninterrupted
+ (daemonlet_pipe_stdout[0], &tmp, 1);
+
+ if (rc <= 0)
+ {
+
+ // some fatal error, or process has closed stdout
+ // not much we can safely do at this point (don't want to risk SIGKILL'ing)
+ close (daemonlet_pipe_stdin[1]);
+ close (daemonlet_pipe_stdout[0]);
+
+ if (rc == 0)
+ {
+
+ // process has closed stdout
+ vdev_error
+ ("vdev_read_uninterrupted(%d PID=%d action='%s') rc = %d\n",
+ daemonlet_pipe_stdout[0], pid, act->name, rc);
+ rc = -ECHILD;
+ }
+
+ return rc;
+ }
+ else
+ {
+
+ // got back readiness hint
+ break;
+ }
+ }
+ }
// record runtime state
act->is_daemonlet = true;
act->daemonlet_pid = pid;
act->daemonlet_stdin = daemonlet_pipe_stdin[1];
act->daemonlet_stdout = daemonlet_pipe_stdout[0];
-
+
// daemonlet started!
return 0;
- }
- else {
-
+ }
+ else
+ {
+
// fork() error
rc = -errno;
- vdev_error("fork() rc = %d\n", rc );
-
- close( daemonlet_pipe_stdin[0] );
- close( daemonlet_pipe_stdin[1] );
- close( daemonlet_pipe_stdout[0] );
- close( daemonlet_pipe_stdout[1] );
-
+ vdev_error ("fork() rc = %d\n", rc);
+
+ close (daemonlet_pipe_stdin[0]);
+ close (daemonlet_pipe_stdin[1]);
+ close (daemonlet_pipe_stdout[0]);
+ close (daemonlet_pipe_stdout[1]);
+
return rc;
- }
+ }
}
-
// stop a daemonlet and join with it
// first, ask it by writing "exit" to its stdin pipe.
// wait 30 seconds before SIGTERM'ing the daemonlet.
// return 0 on success, even if the daemonlet is already dead
-static int vdev_action_daemonlet_stop( struct vdev_action* act ) {
-
- int rc = 0;
- pid_t child_pid = 0;
- struct timespec timeout;
- struct timespec stop_deadline;
- sigset_t sigchld_sigset;
- siginfo_t sigchld_info;
-
- timeout.tv_sec = 30;
- timeout.tv_nsec = 0;
-
- if( act->daemonlet_pid <= 0 || act->daemonlet_stdin < 0 || act->daemonlet_stdout < 0 ) {
+static int
+vdev_action_daemonlet_stop (struct vdev_action *act)
+{
+
+ int rc = 0;
+ pid_t child_pid = 0;
+ struct timespec timeout;
+ struct timespec stop_deadline;
+ sigset_t sigchld_sigset;
+ siginfo_t sigchld_info;
+
+ timeout.tv_sec = 30;
+ timeout.tv_nsec = 0;
+
+ if (act->daemonlet_pid <= 0 || act->daemonlet_stdin < 0
+ || act->daemonlet_stdout < 0)
+ {
// not running
return 0;
- }
-
- // confirm that it is still running by trying to join with it
- child_pid = waitpid( act->daemonlet_pid, &rc, WNOHANG );
- if( child_pid == act->daemonlet_pid || child_pid < 0 ) {
-
+ }
+ // confirm that it is still running by trying to join with it
+ child_pid = waitpid (act->daemonlet_pid, &rc, WNOHANG);
+ if (child_pid == act->daemonlet_pid || child_pid < 0)
+ {
+
// joined, or not running
- vdev_debug("Daemonlet %d (%s) dead\n", act->daemonlet_pid, act->name );
- vdev_action_daemonlet_clean( act );
+ vdev_debug ("Daemonlet %d (%s) dead\n", act->daemonlet_pid, act->name);
+ vdev_action_daemonlet_clean (act);
return 0;
- }
-
- // ask it to die: close stdin
- rc = close( act->daemonlet_stdin );
-
- if( rc < 0 ) {
-
- vdev_error("close(%d PID=%d name=%s) rc = %d\n", act->daemonlet_stdin, act->daemonlet_pid, act->name, rc );
+ }
+ // ask it to die: close stdin
+ rc = close (act->daemonlet_stdin);
+
+ if (rc < 0)
+ {
+
+ vdev_error ("close(%d PID=%d name=%s) rc = %d\n",
+ act->daemonlet_stdin, act->daemonlet_pid, act->name, rc);
act->daemonlet_stdin = -1;
-
+
// no choice but to kill this one
- kill( act->daemonlet_pid, SIGTERM );
- vdev_action_daemonlet_clean( act );
-
+ kill (act->daemonlet_pid, SIGTERM);
+ vdev_action_daemonlet_clean (act);
+
// join with it...
rc = 0;
- }
- else {
-
+ }
+ else
+ {
+
// tell daemonlet to die
- rc = kill( act->daemonlet_pid, SIGINT );
- if( rc < 0 ) {
-
- vdev_error("kill(PID=%d name=%s) rc = %d\n", act->daemonlet_pid, act->name, rc );
- }
-
+ rc = kill (act->daemonlet_pid, SIGINT);
+ if (rc < 0)
+ {
+
+ vdev_error ("kill(PID=%d name=%s) rc = %d\n",
+ act->daemonlet_pid, act->name, rc);
+ }
// will wait for the child to die
act->daemonlet_stdin = -1;
- }
-
- // join with it.
- while( 1 ) {
-
+ }
+
+ // join with it.
+ while (1)
+ {
+
// attempt to join
- child_pid = waitpid( act->daemonlet_pid, &rc, 0 );
-
- if( child_pid < 0 ) {
-
- rc = -errno;
- if( rc == -ECHILD ) {
-
- // already dead
- rc = 0;
- vdev_debug("Daemonlet %d (%s) dead\n", act->daemonlet_pid, act->name );
- vdev_action_daemonlet_clean( act );
- break;
- }
- else if( rc == -EINTR ) {
-
- // unhandled signal *or* SIGCHLD
- child_pid = waitpid( act->daemonlet_pid, &rc, WNOHANG );
- if( child_pid > 0 ) {
-
- // child died
- break;
- }
- else {
-
- // try waiting again
- continue;
- }
- }
- }
- else if( child_pid > 0 ) {
-
- // joined!
- break;
- }
- }
-
- // clean this child out (even if we had an error with waitpid)
- vdev_debug("Daemonlet %d (%s) dead\n", act->daemonlet_pid, act->name );
- vdev_action_daemonlet_clean( act );
-
- return rc;
+ child_pid = waitpid (act->daemonlet_pid, &rc, 0);
+
+ if (child_pid < 0)
+ {
+
+ rc = -errno;
+ if (rc == -ECHILD)
+ {
+
+ // already dead
+ rc = 0;
+ vdev_debug ("Daemonlet %d (%s) dead\n",
+ act->daemonlet_pid, act->name);
+ vdev_action_daemonlet_clean (act);
+ break;
+ }
+ else if (rc == -EINTR)
+ {
+
+ // unhandled signal *or* SIGCHLD
+ child_pid = waitpid (act->daemonlet_pid, &rc, WNOHANG);
+ if (child_pid > 0)
+ {
+
+ // child died
+ break;
+ }
+ else
+ {
+
+ // try waiting again
+ continue;
+ }
+ }
+ }
+ else if (child_pid > 0)
+ {
+
+ // joined!
+ break;
+ }
+ }
+
+ // clean this child out (even if we had an error with waitpid)
+ vdev_debug ("Daemonlet %d (%s) dead\n", act->daemonlet_pid, act->name);
+ vdev_action_daemonlet_clean (act);
+
+ return rc;
}
-
// stop all daemonlets
// always succeeds; mask all stop errors (i.e. only call this on shutdown)
-int vdev_action_daemonlet_stop_all( struct vdev_action* actions, size_t num_actions ) {
-
- int rc = 0;
-
- for( unsigned int i = 0; i < num_actions; i++ ) {
-
- if( !actions[i].is_daemonlet ) {
- continue;
- }
-
- rc = vdev_action_daemonlet_stop( &actions[i] );
- if( rc < 0 ) {
-
- vdev_error("vdev_action_daemonlet_stop('%s' PID=%d) rc = %d\n", actions[i].name, actions[i].daemonlet_pid, rc );
- }
- }
-
- return 0;
+int
+vdev_action_daemonlet_stop_all (struct vdev_action *actions,
+ size_t num_actions)
+{
+
+ int rc = 0;
+
+ for (unsigned int i = 0; i < num_actions; i++)
+ {
+
+ if (!actions[i].is_daemonlet)
+ {
+ continue;
+ }
+
+ rc = vdev_action_daemonlet_stop (&actions[i]);
+ if (rc < 0)
+ {
+
+ vdev_error
+ ("vdev_action_daemonlet_stop('%s' PID=%d) rc = %d\n",
+ actions[i].name, actions[i].daemonlet_pid, rc);
+ }
+ }
+
+ return 0;
}
// read a string-ified int64_t from a file descriptor, followed by a newline.
@@ -1153,52 +1355,59 @@ int vdev_action_daemonlet_stop_all( struct vdev_action* actions, size_t num_acti
// return 0 on success, and set *ret
// return -errno on I/O error (such as -EPIPE)
// return -EAGAIN if we got EOF
-static int vdev_action_daemonlet_read_int64( int fd, int64_t* ret ) {
-
- int64_t value = 0;
-
- int cnt = 0;
- int c = 0;
- int rc = 0;
- int s = 1;
-
- while( 1 ) {
-
+static int
+vdev_action_daemonlet_read_int64 (int fd, int64_t * ret)
+{
+
+ int64_t value = 0;
+
+ int cnt = 0;
+ int c = 0;
+ int rc = 0;
+ int s = 1;
+
+ while (1)
+ {
+
// next character
- rc = vdev_read_uninterrupted( fd, (char*)&c, 1 );
- if( rc < 0 ) {
-
- return rc;
- }
- if( rc == 0 ) {
-
- return -EAGAIN;
- }
-
- if( c == '\n' ) {
- break;
- }
-
- if( cnt == 0 && c == '-' ) {
- s = -1;
- }
- else if( c < '0' || c > '9' ) {
-
- // invalid
- rc = -EINVAL;
- break;
- }
-
+ rc = vdev_read_uninterrupted (fd, (char *) &c, 1);
+ if (rc < 0)
+ {
+
+ return rc;
+ }
+ if (rc == 0)
+ {
+
+ return -EAGAIN;
+ }
+
+ if (c == '\n')
+ {
+ break;
+ }
+
+ if (cnt == 0 && c == '-')
+ {
+ s = -1;
+ }
+ else if (c < '0' || c > '9')
+ {
+
+ // invalid
+ rc = -EINVAL;
+ break;
+ }
+
value *= 10;
value += (c - '0');
cnt++;
- }
-
- *ret = value * s;
- return 0;
-}
+ }
+ *ret = value * s;
+ return 0;
+}
// issue a command to a daemonlet, and get back its return code.
// the daemonlet should already be running (or thought to be running) before calling this method.
@@ -1207,99 +1416,123 @@ static int vdev_action_daemonlet_read_int64( int fd, int64_t* ret ) {
// return -ENOMEM on OOM
// return -EAGAIN if the daemonlet needs to be restarted and the request retried.
// return -EPERM on permanent daemonlet failure
-static int vdev_action_daemonlet_send_command( struct vdev_device_request* vreq, struct vdev_action* act, int64_t* daemonlet_rc ) {
-
- int rc = 0;
- char** req_env = NULL;
- size_t num_env = 0;
- char env_buf[ PATH_MAX+1 ];
-
- memset( env_buf, 0, PATH_MAX+1 );
-
- // generate the environment...
- rc = vdev_device_request_to_env( vreq, act->helper_vars, &req_env, &num_env, 1 );
- if( rc != 0 ) {
-
- vdev_error("vdev_device_request_to_env(%s) rc = %d\n", vreq->path, rc );
+static int
+vdev_action_daemonlet_send_command (struct vdev_device_request *vreq,
+ struct vdev_action *act,
+ int64_t * daemonlet_rc)
+{
+
+ int rc = 0;
+ char **req_env = NULL;
+ size_t num_env = 0;
+ char env_buf[PATH_MAX + 1];
+
+ memset (env_buf, 0, PATH_MAX + 1);
+
+ // generate the environment...
+ rc = vdev_device_request_to_env (vreq, act->helper_vars, &req_env,
+ &num_env, 1);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_device_request_to_env(%s) rc = %d\n", vreq->path, rc);
return rc;
- }
-
-
- vdev_debug("run daemonlet (async=%d): '%s'\n", act->async, act->name );
-
- for( unsigned int i = 0; i < num_env; i++ ) {
- vdev_debug("daemonlet env: '%s'\n", req_env[i] );
- }
-
- // feed environment variables
- for( unsigned int i = 0; i < num_env; i++ ) {
-
- snprintf( env_buf, PATH_MAX, "%s\n", req_env[i] );
-
- rc = vdev_write_uninterrupted( act->daemonlet_stdin, env_buf, strlen(env_buf) );
- if( rc < 0 ) {
-
- // failed to write!
- vdev_error("vdev_write_uninterrupted(%d) to daemonlet '%s' rc = %d\n", act->daemonlet_stdin, act->name, rc );
- break;
- }
- }
-
- if( rc > 0 ) {
-
+ }
+
+ vdev_debug ("run daemonlet (async=%d): '%s'\n", act->async, act->name);
+
+ for (unsigned int i = 0; i < num_env; i++)
+ {
+ vdev_debug ("daemonlet env: '%s'\n", req_env[i]);
+ }
+
+ // feed environment variables
+ for (unsigned int i = 0; i < num_env; i++)
+ {
+
+ snprintf (env_buf, PATH_MAX, "%s\n", req_env[i]);
+
+ rc = vdev_write_uninterrupted (act->daemonlet_stdin, env_buf,
+ strlen (env_buf));
+ if (rc < 0)
+ {
+
+ // failed to write!
+ vdev_error
+ ("vdev_write_uninterrupted(%d) to daemonlet '%s' rc = %d\n",
+ act->daemonlet_stdin, act->name, rc);
+ break;
+ }
+ }
+
+ if (rc > 0)
+ {
+
// feed end-of-environment flag
- rc = vdev_write_uninterrupted( act->daemonlet_stdin, "done\n", strlen("done\n") );
- if( rc < 0 ) {
-
- vdev_error("vdev_write_uninterrupted(%d) to daemonlet '%s' rc = %d\n", act->daemonlet_stdin, act->name, rc );
- }
- }
-
- VDEV_FREE_LIST( req_env );
-
- if( rc < 0 ) {
+ rc = vdev_write_uninterrupted (act->daemonlet_stdin, "done\n",
+ strlen ("done\n"));
+ if (rc < 0)
+ {
+
+ vdev_error
+ ("vdev_write_uninterrupted(%d) to daemonlet '%s' rc = %d\n",
+ act->daemonlet_stdin, act->name, rc);
+ }
+ }
+
+ VDEV_FREE_LIST (req_env);
+
+ if (rc < 0)
+ {
// -EPIPE means the daemonlet is dead, and the caller should restart it
- if( rc == -EPIPE ) {
- return -EAGAIN;
- }
- else {
- return -EPERM;
- }
- }
-
- // if we're running asynchronously, then we don't care about getting back the reply (stdout is routed to /dev/null anyway)
- if( act->async ) {
+ if (rc == -EPIPE)
+ {
+ return -EAGAIN;
+ }
+ else
+ {
+ return -EPERM;
+ }
+ }
+ // if we're running asynchronously, then we don't care about getting back the reply (stdout is routed to /dev/null anyway)
+ if (act->async)
+ {
*daemonlet_rc = 0;
return 0;
- }
-
- // wait for a status code reply
- rc = vdev_action_daemonlet_read_int64( act->daemonlet_stdout, daemonlet_rc );
- if( rc < 0 ) {
-
- vdev_error("vdev_action_daemonlet_read_int64('%s') rc = %d\n", act->name, rc );
+ }
+ // wait for a status code reply
+ rc = vdev_action_daemonlet_read_int64 (act->daemonlet_stdout, daemonlet_rc);
+ if (rc < 0)
+ {
+
+ vdev_error ("vdev_action_daemonlet_read_int64('%s') rc = %d\n",
+ act->name, rc);
// -EPIPE means the daemonlet is dead, and the caller should restart it
- if( rc == -EPIPE ) {
- return -EAGAIN;
- }
- else {
- return -EPERM;
- }
- }
-
- if( *daemonlet_rc < 0 || *daemonlet_rc > 255 ) {
-
+ if (rc == -EPIPE)
+ {
+ return -EAGAIN;
+ }
+ else
+ {
+ return -EPERM;
+ }
+ }
+
+ if (*daemonlet_rc < 0 || *daemonlet_rc > 255)
+ {
+
// invalid daemonlet return code
// caller should consider restarting the daemonlet and trying again
- vdev_error("vdev_daemonlet_read_int64('%s', PID=%d) exit status %d\n", act->name, act->daemonlet_pid, (int)*daemonlet_rc );
+ vdev_error
+ ("vdev_daemonlet_read_int64('%s', PID=%d) exit status %d\n",
+ act->name, act->daemonlet_pid, (int) *daemonlet_rc);
return -EAGAIN;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// carry out a command by sending it to a running daemonlet.
// restart the daemonlet if we need to (e.g. if it hasn't been started, or it died since the last device request).
@@ -1311,296 +1544,357 @@ static int vdev_action_daemonlet_send_command( struct vdev_device_request* vreq,
// return a positive exit code if the daemonlet failed to process the device request
// NOTE: if this method fails to communicate with the daemonlet, it will try to "reset" the daemonlet by stopping it, and allowing a subsequent call to start it.
// NOTE: not reload-safe; call while the reload lock is held
-int vdev_action_run_daemonlet( struct vdev_device_request* vreq, struct vdev_action* act ) {
-
- int rc = 0;
- int64_t daemonlet_rc = 0;
- int num_attempts = 0;
+int
+vdev_action_run_daemonlet (struct vdev_device_request *vreq,
+ struct vdev_action *act)
+{
+
+ int rc = 0;
+ int64_t daemonlet_rc = 0;
+ int num_attempts = 0;
- if( !act->is_daemonlet ) {
+ if (!act->is_daemonlet)
+ {
return -EINVAL;
- }
-
- // do we need to start it?
- if( act->daemonlet_pid <= 0 ) {
-
- rc = vdev_action_daemonlet_start( vreq->state, act );
- if( rc < 0 ) {
-
- vdev_error("vdev_action_daemonlet_start('%s') rc = %d\n", act->name, rc );
- return -EPERM;
- }
- }
-
- // try twice, in case we need to stop and start it.
- while( num_attempts < 2 ) {
-
- rc = vdev_action_daemonlet_send_command( vreq, act, &daemonlet_rc );
- if( rc != 0 ) {
-
- vdev_error("vdev_action_daemonlet_send_command('%s') rc = %d\n", act->name, rc );
-
- if( rc == -EAGAIN ) {
-
- // try restarting and re-dispatching the command
- rc = vdev_action_daemonlet_stop( act );
- if( rc < 0 ) {
-
- vdev_error("vdev_action_daemonlet_stop('%s', PID=%d) rc = %d\n", act->name, act->daemonlet_pid, rc );
- rc = -EPERM;
- break;
- }
- else {
-
- rc = vdev_action_daemonlet_start( vreq->state, act );
- if( rc < 0 ) {
-
- vdev_error("vdev_action_daemonlet_start('%s') rc = %d\n", act->name, rc );
- rc = -EPERM;
- break;
- }
- else {
-
- // try again
- num_attempts++;
- continue;
- }
- }
- }
- else {
-
- // permanent failure
- rc = -EPERM;
- break;
- }
- }
- else {
-
- // successfully dispatched the request, and (if not async) received an exit status via daemonlet_rc
- break;
- }
- }
-
- if( rc == 0 ) {
-
- vdev_debug("daemonlet '%s' returned %d\n", act->name, (int)daemonlet_rc );
- return (int)daemonlet_rc;
- }
- else {
-
- return rc;
- }
-}
+ }
+ // do we need to start it?
+ if (act->daemonlet_pid <= 0)
+ {
+
+ rc = vdev_action_daemonlet_start (vreq->state, act);
+ if (rc < 0)
+ {
+
+ vdev_error
+ ("vdev_action_daemonlet_start('%s') rc = %d\n", act->name, rc);
+ return -EPERM;
+ }
+ }
+ // try twice, in case we need to stop and start it.
+ while (num_attempts < 2)
+ {
+
+ rc = vdev_action_daemonlet_send_command (vreq, act, &daemonlet_rc);
+ if (rc != 0)
+ {
+
+ vdev_error
+ ("vdev_action_daemonlet_send_command('%s') rc = %d\n",
+ act->name, rc);
+
+ if (rc == -EAGAIN)
+ {
+
+ // try restarting and re-dispatching the command
+ rc = vdev_action_daemonlet_stop (act);
+ if (rc < 0)
+ {
+
+ vdev_error
+ ("vdev_action_daemonlet_stop('%s', PID=%d) rc = %d\n",
+ act->name, act->daemonlet_pid, rc);
+ rc = -EPERM;
+ break;
+ }
+ else
+ {
+
+ rc = vdev_action_daemonlet_start (vreq->state, act);
+ if (rc < 0)
+ {
+
+ vdev_error
+ ("vdev_action_daemonlet_start('%s') rc = %d\n",
+ act->name, rc);
+ rc = -EPERM;
+ break;
+ }
+ else
+ {
+
+ // try again
+ num_attempts++;
+ continue;
+ }
+ }
+ }
+ else
+ {
+
+ // permanent failure
+ rc = -EPERM;
+ break;
+ }
+ }
+ else
+ {
+
+ // successfully dispatched the request, and (if not async) received an exit status via daemonlet_rc
+ break;
+ }
+ }
+
+ if (rc == 0)
+ {
+
+ vdev_debug ("daemonlet '%s' returned %d\n", act->name,
+ (int) daemonlet_rc);
+ return (int) daemonlet_rc;
+ }
+ else
+ {
+ return rc;
+ }
+}
// match device request against action
// return 1 if match
// return 0 if not match
-int vdev_action_match( struct vdev_device_request* vreq, struct vdev_action* act ) {
-
- int rc = 0;
-
- // action match?
- if( act->trigger != vreq->type && act->trigger != VDEV_DEVICE_ANY ) {
+int
+vdev_action_match (struct vdev_device_request *vreq, struct vdev_action *act)
+{
+
+ int rc = 0;
+
+ // action match?
+ if (act->trigger != vreq->type && act->trigger != VDEV_DEVICE_ANY)
+ {
return 0;
- }
-
- // path match?
- if( act->path != NULL ) {
-
- rc = vdev_match_regex( vreq->path, &act->path_regex );
- if( rc == 0 ) {
-
- // no match
- return 0;
- }
- if( rc < 0 ) {
-
- // some error
- return rc;
- }
- }
-
- // type match?
- if( act->has_type ) {
-
- if( !S_ISBLK( vreq->mode ) && !S_ISCHR( vreq->mode ) ) {
- // device has no type
- return 0;
- }
-
- if( S_ISBLK( vreq->mode ) && strcasecmp( act->type, "block" ) != 0 ) {
-
- // not a block device
- return 0;
- }
- if( S_ISCHR( vreq->mode ) && strcasecmp( act->type, "char" ) != 0 ) {
-
- // not a char device
- return 0;
- }
- }
-
- // OS parameter match?
- if( act->dev_params != NULL ) {
-
+ }
+ // path match?
+ if (act->path != NULL)
+ {
+
+ rc = vdev_match_regex (vreq->path, &act->path_regex);
+ if (rc == 0)
+ {
+
+ // no match
+ return 0;
+ }
+ if (rc < 0)
+ {
+
+ // some error
+ return rc;
+ }
+ }
+ // type match?
+ if (act->has_type)
+ {
+
+ if (!S_ISBLK (vreq->mode) && !S_ISCHR (vreq->mode))
+ {
+ // device has no type
+ return 0;
+ }
+
+ if (S_ISBLK (vreq->mode) && strcasecmp (act->type, "block") != 0)
+ {
+
+ // not a block device
+ return 0;
+ }
+ if (S_ISCHR (vreq->mode) && strcasecmp (act->type, "char") != 0)
+ {
+
+ // not a char device
+ return 0;
+ }
+ }
+ // OS parameter match?
+ if (act->dev_params != NULL)
+ {
+
struct sglib_vdev_params_iterator itr;
- struct vdev_param_t* dp = NULL;
-
- for( dp = sglib_vdev_params_it_init_inorder( &itr, act->dev_params ); dp != NULL; dp = sglib_vdev_params_it_next( &itr ) ) {
-
- struct vdev_param_t* match = sglib_vdev_params_find_member( vreq->params, dp );
-
- if( match != NULL ) {
-
- // vreq has this parameter
- char const* vreq_param_value = match->value;
- char const* act_param_value = dp->value;
-
- // if the action has no value (value of length 0), then it matches any vreq value
- if( act_param_value == NULL || strlen( act_param_value ) == 0 ) {
-
- continue;
- }
-
- // otherwise, compare the values
- if( strcmp( vreq_param_value, act_param_value ) != 0 ) {
-
- // values don't match
- return 0;
- }
- }
- else {
-
- // vreq does not have this parameter, so no match
- return 0;
- }
- }
- }
-
- // match!
- return 1;
+ struct vdev_param_t *dp = NULL;
+
+ for (dp =
+ sglib_vdev_params_it_init_inorder (&itr, act->dev_params);
+ dp != NULL; dp = sglib_vdev_params_it_next (&itr))
+ {
+
+ struct vdev_param_t *match =
+ sglib_vdev_params_find_member (vreq->params, dp);
+
+ if (match != NULL)
+ {
+
+ // vreq has this parameter
+ char const *vreq_param_value = match->value;
+ char const *act_param_value = dp->value;
+
+ // if the action has no value (value of length 0), then it matches any vreq value
+ if (act_param_value == NULL || strlen (act_param_value) == 0)
+ {
+
+ continue;
+ }
+ // otherwise, compare the values
+ if (strcmp (vreq_param_value, act_param_value) != 0)
+ {
+
+ // values don't match
+ return 0;
+ }
+ }
+ else
+ {
+
+ // vreq does not have this parameter, so no match
+ return 0;
+ }
+ }
+ }
+ // match!
+ return 1;
}
-
// find the next action in a list of actions to run, given the path
// return the index into acts of the next match, if found
// return num_acts if not found
// return negative on error
-int vdev_action_find_next( struct vdev_device_request* vreq, struct vdev_action* acts, size_t num_acts ) {
-
- int rc = 0;
- int i = 0;
-
- for( i = 0; (unsigned)i < num_acts; i++ ) {
-
- rc = vdev_action_match( vreq, &acts[i] );
-
- if( rc > 0 ) {
- return i;
- }
- else if( rc < 0 ) {
- return rc;
- }
- }
-
- return num_acts;
+int
+vdev_action_find_next (struct vdev_device_request *vreq,
+ struct vdev_action *acts, size_t num_acts)
+{
+
+ int rc = 0;
+ int i = 0;
+
+ for (i = 0; (unsigned) i < num_acts; i++)
+ {
+
+ rc = vdev_action_match (vreq, &acts[i]);
+
+ if (rc > 0)
+ {
+ return i;
+ }
+ else if (rc < 0)
+ {
+ return rc;
+ }
+ }
+
+ return num_acts;
}
-
// find the path to create for the given device request, but in a fail-fast manner (i.e. return on first error)
// *path will be filled in with path to the device node, relative to the mountpoint. *path must be NULL on call.
// return 0 on success
// return -EINVAL if *path is not NULL, or if we failed to match the vreq against our actions due to a regex error
// return -ENODATA if *path has zero-length
-int vdev_action_create_path( struct vdev_device_request* vreq, struct vdev_action* acts, size_t num_acts, char** path ) {
-
- int rc = 0;
- int act_offset = 0;
- int i = 0;
- char* new_path = NULL;
-
- if( *path != NULL ) {
+int
+vdev_action_create_path (struct vdev_device_request *vreq,
+ struct vdev_action *acts, size_t num_acts,
+ char **path)
+{
+
+ int rc = 0;
+ int act_offset = 0;
+ int i = 0;
+ char *new_path = NULL;
+
+ if (*path != NULL)
+ {
return -EINVAL;
- }
-
- while( act_offset < (signed)num_acts ) {
-
+ }
+
+ while (act_offset < (signed) num_acts)
+ {
+
rc = 0;
-
+
// skip this action if there is no rename command
- if( acts[act_offset].rename_command == NULL ) {
- act_offset++;
- continue;
- }
-
+ if (acts[act_offset].rename_command == NULL)
+ {
+ act_offset++;
+ continue;
+ }
// find the next action that matches this path
- rc = vdev_action_find_next( vreq, acts + act_offset, num_acts - act_offset );
-
- if( rc == (signed)(num_acts - act_offset) ) {
-
- // not found
- rc = 0;
- break;
- }
- else if( rc < 0 ) {
-
- // error
- vdev_error("vdev_action_find_next(%s, offset = %d) rc = %d\n", vreq->path, act_offset, rc );
- break;
- }
- else {
-
- // matched! advance offset to next action
- i = act_offset + rc;
- act_offset += rc + 1;
- rc = 0;
-
- if( acts[i].rename_command == NULL ) {
- continue;
- }
-
- // generate the new name
- rc = vdev_action_run_sync( vreq, acts[i].rename_command, acts[i].helper_vars, true, &new_path, PATH_MAX + 1 );
- if( rc < 0 ) {
-
- vdev_error("vdev_action_run_sync('%s') rc = %d\n", acts[i].rename_command, rc );
- break;
- }
- else {
-
- if( *path != NULL ) {
- free( *path );
- }
-
- *path = new_path;
- new_path = NULL;
- }
- }
- }
-
- if( *path != NULL && strlen(*path) == 0 ) {
-
+ rc = vdev_action_find_next (vreq, acts + act_offset,
+ num_acts - act_offset);
+
+ if (rc == (signed) (num_acts - act_offset))
+ {
+
+ // not found
+ rc = 0;
+ break;
+ }
+ else if (rc < 0)
+ {
+
+ // error
+ vdev_error
+ ("vdev_action_find_next(%s, offset = %d) rc = %d\n",
+ vreq->path, act_offset, rc);
+ break;
+ }
+ else
+ {
+
+ // matched! advance offset to next action
+ i = act_offset + rc;
+ act_offset += rc + 1;
+ rc = 0;
+
+ if (acts[i].rename_command == NULL)
+ {
+ continue;
+ }
+ // generate the new name
+ rc = vdev_action_run_sync (vreq, acts[i].rename_command,
+ acts[i].helper_vars, true,
+ &new_path, PATH_MAX + 1);
+ if (rc < 0)
+ {
+
+ vdev_error
+ ("vdev_action_run_sync('%s') rc = %d\n",
+ acts[i].rename_command, rc);
+ break;
+ }
+ else
+ {
+
+ if (*path != NULL)
+ {
+ free (*path);
+ }
+
+ *path = new_path;
+ new_path = NULL;
+ }
+ }
+ }
+
+ if (*path != NULL && strlen (*path) == 0)
+ {
+
// if this is "UNKNOWN", then just reset to "UNKNOWN"
- if( strcmp(vreq->path, VDEV_DEVICE_PATH_UNKNOWN) == 0 ) {
-
- free( *path );
- *path = vdev_strdup_or_null( VDEV_DEVICE_PATH_UNKNOWN );
- }
- else {
-
- vdev_error("Zero-length path generated for '%s'\n", vreq->path );
-
- free( *path );
- *path = NULL;
-
- rc = -ENODATA;
- }
- }
-
- return rc;
-}
+ if (strcmp (vreq->path, VDEV_DEVICE_PATH_UNKNOWN) == 0)
+ {
+
+ free (*path);
+ *path = vdev_strdup_or_null (VDEV_DEVICE_PATH_UNKNOWN);
+ }
+ else
+ {
+
+ vdev_error ("Zero-length path generated for '%s'\n", vreq->path);
+
+ free (*path);
+ *path = NULL;
+
+ rc = -ENODATA;
+ }
+ }
+ return rc;
+}
// run all actions for a device, sequentially, in lexographic order.
// commands are executed optimistically--even if one fails, the other subsequent ones will be attempted, unless
@@ -1608,158 +1902,213 @@ int vdev_action_create_path( struct vdev_device_request* vreq, struct vdev_actio
// if the device already exists (given by the exists flag), then only run commands with if_exists set to "run"
// return 0 on success
// return negative on failure
-int vdev_action_run_commands( struct vdev_device_request* vreq, struct vdev_action* acts, size_t num_acts, bool exists ) {
-
- int rc = 0;
- int act_offset = 0;
- int i = 0;
- char const* method = NULL;
- struct timespec start;
- struct timespec end;
-
- while( act_offset < (signed)num_acts && rc == 0 ) {
-
+int
+vdev_action_run_commands (struct vdev_device_request *vreq,
+ struct vdev_action *acts, size_t num_acts,
+ bool exists)
+{
+
+ int rc = 0;
+ int act_offset = 0;
+ int i = 0;
+ char const *method = NULL;
+ struct timespec start;
+ struct timespec end;
+
+ while (act_offset < (signed) num_acts && rc == 0)
+ {
+
// skip this action if there is no command
- if( acts[act_offset].command == NULL ) {
- act_offset++;
- continue;
- }
-
+ if (acts[act_offset].command == NULL)
+ {
+ act_offset++;
+ continue;
+ }
// find the next action that matches this path
- rc = vdev_action_find_next( vreq, acts + act_offset, num_acts - act_offset );
-
- if( rc == (signed)(num_acts - act_offset) ) {
-
- // not found
- rc = 0;
- break;
- }
- else if( rc < 0 ) {
-
- vdev_error("vdev_action_find_next(%s, offset = %d) rc = %d\n", vreq->path, act_offset, rc );
- break;
- }
- else {
-
- // matched! advance offset to next action
- i = act_offset + rc;
- act_offset += rc + 1;
- rc = 0;
-
- if( acts[i].command == NULL ) {
- continue;
- }
-
- if( vreq->type == VDEV_DEVICE_ADD && exists && acts[i].if_exists != VDEV_IF_EXISTS_RUN ) {
-
- if( acts[i].if_exists == VDEV_IF_EXISTS_ERROR ) {
-
- vdev_error("Will stop processing %s, since it already exists\n", vreq->path );
- rc = 1;
- break;
- }
- else {
-
- // device already exists, but this is not considered by the .act file to be an error
- continue;
- }
- }
-
- // benchmark this...
- clock_gettime( CLOCK_MONOTONIC, &start );
-
- // what kind of action to take?
- if( !acts[i].is_daemonlet ) {
-
- if( acts[i].async ) {
-
- // fork a subprocess and handle asynchronously
- method = "vdev_action_run_async";
- rc = vdev_action_run_async( vreq, acts[i].command, acts[i].helper_vars, acts[i].use_shell );
- }
- else {
-
- // run as a subprocess, wait, and join with it
- method = "vdev_action_run_sync";
- rc = vdev_action_run_sync( vreq, acts[i].command, acts[i].helper_vars, acts[i].use_shell, NULL, 0 );
- }
- }
- else {
-
- if( acts[i].async ) {
-
- // run as a daemonlet, feed it the request, but don't wait for a reply
- method = "vdev_action_run_daemonlet_async";
- }
- else {
-
- // run as a daemonlet, feed the request, and wait for a reply
- method = "vdev_action_run_daemonlet";
- }
-
- rc = vdev_action_run_daemonlet( vreq, &acts[i] );
- }
-
- clock_gettime( CLOCK_MONOTONIC, &end );
-
- if( rc != 0 ) {
-
- vdev_error("%s('%s') rc = %d\n", method, acts[i].command, rc );
-
- if( rc < 0 ) {
- return rc;
- }
- else {
-
- // mask non-zero exit statuses
- uint64_t start_millis = 1000L * start.tv_sec + (start.tv_nsec / 1000000L);
- uint64_t end_millis = 1000L * end.tv_sec + (end.tv_nsec / 1000000L);
-
- vdev_debug("Benchmark: action %s failed (exit %d) in %lu millis\n", acts[i].name, rc, (unsigned long)(end_millis - start_millis) );
- rc = 0;
- }
- }
- else {
-
- // success! update benchmark
- acts[i].num_successful_calls++;
-
- uint64_t start_millis = 1000L * start.tv_sec + (start.tv_nsec / 1000000L);
- uint64_t end_millis = 1000L * end.tv_sec + (end.tv_nsec / 1000000L);
-
- acts[i].cumulative_time_millis += (end_millis - start_millis);
-
- // log timings directly, for finer granularity...
- vdev_debug("Benchmark: action %s succeeded in %lu millis\n", acts[i].name, (unsigned long)(end_millis - start_millis) );
- }
- }
- }
-
- if( rc > 0 ) {
-
+ rc = vdev_action_find_next (vreq, acts + act_offset,
+ num_acts - act_offset);
+
+ if (rc == (signed) (num_acts - act_offset))
+ {
+
+ // not found
+ rc = 0;
+ break;
+ }
+ else if (rc < 0)
+ {
+
+ vdev_error
+ ("vdev_action_find_next(%s, offset = %d) rc = %d\n",
+ vreq->path, act_offset, rc);
+ break;
+ }
+ else
+ {
+
+ // matched! advance offset to next action
+ i = act_offset + rc;
+ act_offset += rc + 1;
+ rc = 0;
+
+ if (acts[i].command == NULL)
+ {
+ continue;
+ }
+
+ if (vreq->type == VDEV_DEVICE_ADD && exists
+ && acts[i].if_exists != VDEV_IF_EXISTS_RUN)
+ {
+
+ if (acts[i].if_exists == VDEV_IF_EXISTS_ERROR)
+ {
+
+ vdev_error
+ ("Will stop processing %s, since it already exists\n",
+ vreq->path);
+ rc = 1;
+ break;
+ }
+ else
+ {
+
+ // device already exists, but this is not considered by the .act file to be an error
+ continue;
+ }
+ }
+ // benchmark this...
+ clock_gettime (CLOCK_MONOTONIC, &start);
+
+ // what kind of action to take?
+ if (!acts[i].is_daemonlet)
+ {
+
+ if (acts[i].async)
+ {
+
+ // fork a subprocess and handle asynchronously
+ method = "vdev_action_run_async";
+ rc = vdev_action_run_async (vreq,
+ acts
+ [i].command,
+ acts
+ [i].helper_vars,
+ acts[i].use_shell);
+ }
+ else
+ {
+
+ // run as a subprocess, wait, and join with it
+ method = "vdev_action_run_sync";
+ rc = vdev_action_run_sync (vreq,
+ acts
+ [i].command,
+ acts
+ [i].helper_vars,
+ acts[i].use_shell, NULL, 0);
+ }
+ }
+ else
+ {
+
+ if (acts[i].async)
+ {
+
+ // run as a daemonlet, feed it the request, but don't wait for a reply
+ method = "vdev_action_run_daemonlet_async";
+ }
+ else
+ {
+
+ // run as a daemonlet, feed the request, and wait for a reply
+ method = "vdev_action_run_daemonlet";
+ }
+
+ rc = vdev_action_run_daemonlet (vreq, &acts[i]);
+ }
+
+ clock_gettime (CLOCK_MONOTONIC, &end);
+
+ if (rc != 0)
+ {
+
+ vdev_error ("%s('%s') rc = %d\n", method, acts[i].command, rc);
+
+ if (rc < 0)
+ {
+ return rc;
+ }
+ else
+ {
+
+ // mask non-zero exit statuses
+ uint64_t start_millis =
+ 1000L * start.tv_sec + (start.tv_nsec / 1000000L);
+ uint64_t end_millis =
+ 1000L * end.tv_sec + (end.tv_nsec / 1000000L);
+
+ vdev_debug
+ ("Benchmark: action %s failed (exit %d) in %lu millis\n",
+ acts[i].name, rc,
+ (unsigned long) (end_millis - start_millis));
+ rc = 0;
+ }
+ }
+ else
+ {
+
+ // success! update benchmark
+ acts[i].num_successful_calls++;
+
+ uint64_t start_millis =
+ 1000L * start.tv_sec + (start.tv_nsec / 1000000L);
+ uint64_t end_millis =
+ 1000L * end.tv_sec + (end.tv_nsec / 1000000L);
+
+ acts[i].cumulative_time_millis += (end_millis - start_millis);
+
+ // log timings directly, for finer granularity...
+ vdev_debug
+ ("Benchmark: action %s succeeded in %lu millis\n",
+ acts[i].name, (unsigned long) (end_millis - start_millis));
+ }
+ }
+ }
+
+ if (rc > 0)
+ {
+
// not an error, but a cause to abort
rc = 0;
- }
-
- return rc;
-}
+ }
+ return rc;
+}
// print out all benchmark information for this action
// always succeeds
-int vdev_action_log_benchmarks( struct vdev_action* action ) {
-
- int rc = 0;
-
- if( action->num_successful_calls > 0 ) {
- vdev_debug("Action '%s' (daemon=%d, async=%d): %lu successful calls; %lu millis total; %lf avg.\n",
- action->name, action->is_daemonlet, action->async, action->num_successful_calls, action->cumulative_time_millis, (double)(action->cumulative_time_millis) / (double)(action->num_successful_calls));
- }
- else {
- vdev_debug("Action '%s' (daemon=%d, async=%d): 0 successful calls\n", action->name, action->is_daemonlet, action->async );
- }
-
- return 0;
+int
+vdev_action_log_benchmarks (struct vdev_action *action)
+{
+
+ // int rc = 0;
+
+ if (action->num_successful_calls > 0)
+ {
+ vdev_debug
+ ("Action '%s' (daemon=%d, async=%d): %lu successful calls; %lu millis total; %lf avg.\n",
+ action->name, action->is_daemonlet, action->async,
+ action->num_successful_calls,
+ action->cumulative_time_millis,
+ (double) (action->cumulative_time_millis) /
+ (double) (action->num_successful_calls));
+ }
+ else
+ {
+ vdev_debug
+ ("Action '%s' (daemon=%d, async=%d): 0 successful calls\n",
+ action->name, action->is_daemonlet, action->async);
+ }
+
+ return 0;
}
-
-
diff --git a/vdevd/action.h b/vdevd/action.h
index 16accb7..2f49f3b 100644
--- a/vdevd/action.h
+++ b/vdevd/action.h
@@ -28,7 +28,6 @@
#include "device.h"
-
// action fields
#define VDEV_ACTION_NAME "vdev-action"
@@ -54,85 +53,95 @@
#define VDEV_ACTION_DAEMONLET "daemonlet"
-enum vdev_action_if_exists {
- VDEV_IF_EXISTS_ERROR = 1,
- VDEV_IF_EXISTS_MASK,
- VDEV_IF_EXISTS_RUN
+enum vdev_action_if_exists
+{
+ VDEV_IF_EXISTS_ERROR = 1,
+ VDEV_IF_EXISTS_MASK,
+ VDEV_IF_EXISTS_RUN
};
// vdev action to take on an event
-struct vdev_action {
-
- // action name
- char* name;
-
- // what kind of request triggers this?
- vdev_device_request_t trigger;
-
- // device path to match on
- char* path;
- regex_t path_regex;
-
- // device type to match on (block, char)
- bool has_type;
- char* type;
-
- // command to run to rename the matched path, if needed
- char* rename_command;
-
- // command to run once the device state change is processed.
- // can be dynamically generated from helper, below.
- char* command;
-
- // name of a helper to run once the device state change is processed (conflicts with command)
- char* helper;
-
- // whether or not to run this action in the system shell, or directly
- bool use_shell;
-
- // OS-specific fields to match on
- vdev_params* dev_params;
-
- // helper-specific variables to export
- vdev_params* helper_vars;
-
- // synchronous or asynchronous
- bool async;
-
- // how to handle the case where the device already exists
- int if_exists;
-
- // is the action's command implemented as a daemonlet? If so, hold onto its runtime state
- bool is_daemonlet;
- int daemonlet_stdin;
- int daemonlet_stdout;
- pid_t daemonlet_pid;
-
- // action runtime statistics
- uint64_t num_successful_calls;
- uint64_t cumulative_time_millis;
+struct vdev_action
+{
+
+ // action name
+ char *name;
+
+ // what kind of request triggers this?
+ vdev_device_request_t trigger;
+
+ // device path to match on
+ char *path;
+ regex_t path_regex;
+
+ // device type to match on (block, char)
+ bool has_type;
+ char *type;
+
+ // command to run to rename the matched path, if needed
+ char *rename_command;
+
+ // command to run once the device state change is processed.
+ // can be dynamically generated from helper, below.
+ char *command;
+
+ // name of a helper to run once the device state change is processed (conflicts with command)
+ char *helper;
+
+ // whether or not to run this action in the system shell, or directly
+ bool use_shell;
+
+ // OS-specific fields to match on
+ vdev_params *dev_params;
+
+ // helper-specific variables to export
+ vdev_params *helper_vars;
+
+ // synchronous or asynchronous
+ bool async;
+
+ // how to handle the case where the device already exists
+ int if_exists;
+
+ // is the action's command implemented as a daemonlet? If so, hold onto its runtime state
+ bool is_daemonlet;
+ int daemonlet_stdin;
+ int daemonlet_stdout;
+ pid_t daemonlet_pid;
+
+ // action runtime statistics
+ uint64_t num_successful_calls;
+ uint64_t cumulative_time_millis;
};
typedef struct vdev_action vdev_action;
C_LINKAGE_BEGIN
+ int vdev_action_init (struct vdev_action *act,
+ vdev_device_request_t trigger, char *path,
+ char *command, char *helper, bool async);
+int vdev_action_add_param (struct vdev_action *act, char const *name,
+ char const *value);
+int vdev_action_free (struct vdev_action *act);
+int vdev_action_free_all (struct vdev_action *act_list, size_t num_acts);
-int vdev_action_init( struct vdev_action* act, vdev_device_request_t trigger, char* path, char* command, char* helper, bool async );
-int vdev_action_add_param( struct vdev_action* act, char const* name, char const* value );
-int vdev_action_free( struct vdev_action* act );
-int vdev_action_free_all( struct vdev_action* act_list, size_t num_acts );
+int vdev_action_load (struct vdev_config *config, char const *path,
+ struct vdev_action *act);
-int vdev_action_load( struct vdev_config* config, char const* path, struct vdev_action* act );
+int vdev_action_load_all (struct vdev_config *config,
+ struct vdev_action **acts, size_t * num_acts);
-int vdev_action_load_all( struct vdev_config* config, struct vdev_action** acts, size_t* num_acts );
+int vdev_action_create_path (struct vdev_device_request *vreq,
+ struct vdev_action *acts, size_t num_acts,
+ char **path);
+int vdev_action_run_commands (struct vdev_device_request *vreq,
+ struct vdev_action *acts, size_t num_acts,
+ bool exists);
-int vdev_action_create_path( struct vdev_device_request* vreq, struct vdev_action* acts, size_t num_acts, char** path );
-int vdev_action_run_commands( struct vdev_device_request* vreq, struct vdev_action* acts, size_t num_acts, bool exists );
+int vdev_action_daemonlet_stop_all (struct vdev_action *actions,
+ size_t num_actions);
-int vdev_action_daemonlet_stop_all( struct vdev_action* actions, size_t num_actions );
-
-int vdev_action_log_benchmarks( struct vdev_action* action );
+int vdev_action_log_benchmarks (struct vdev_action *action);
C_LINKAGE_END
-
-#endif
\ No newline at end of file
+#endif
diff --git a/vdevd/device.c b/vdevd/device.c
index 7d0369c..715c838 100644
--- a/vdevd/device.c
+++ b/vdevd/device.c
@@ -28,107 +28,132 @@
// create a request
// return 0 on success
// return -ENOMEM if we can't allocate device parameters
-int vdev_device_request_init( struct vdev_device_request* req, struct vdev_state* state, vdev_device_request_t req_type, char const* path ) {
-
- memset( req, 0, sizeof(struct vdev_device_request) );
-
- if( path != NULL ) {
- req->path = vdev_strdup_or_null( path );
- if( req->path == NULL ) {
- return -ENOMEM;
- }
- }
-
- req->state = state;
- req->type = req_type;
-
- return 0;
+int
+vdev_device_request_init (struct vdev_device_request *req,
+ struct vdev_state *state,
+ vdev_device_request_t req_type, char const *path)
+{
+
+ memset (req, 0, sizeof (struct vdev_device_request));
+
+ if (path != NULL)
+ {
+ req->path = vdev_strdup_or_null (path);
+ if (req->path == NULL)
+ {
+ return -ENOMEM;
+ }
+ }
+
+ req->state = state;
+ req->type = req_type;
+
+ return 0;
}
// free a request
-int vdev_device_request_free( struct vdev_device_request* req ) {
-
- if( req->params != NULL ) {
-
- vdev_params_free( req->params );
+int
+vdev_device_request_free (struct vdev_device_request *req)
+{
+
+ if (req->params != NULL)
+ {
+
+ vdev_params_free (req->params);
req->params = NULL;
- }
-
- if( req->path != NULL ) {
-
- free( req->path );
+ }
+
+ if (req->path != NULL)
+ {
+
+ free (req->path);
req->path = NULL;
- }
-
- if( req->renamed_path != NULL ) {
-
- free( req->renamed_path );
+ }
+
+ if (req->renamed_path != NULL)
+ {
+
+ free (req->renamed_path);
req->renamed_path = NULL;
- }
-
- memset( req, 0, sizeof(struct vdev_device_request) );
-
- return 0;
+ }
+
+ memset (req, 0, sizeof (struct vdev_device_request));
+
+ return 0;
}
// add a device parameter (must be unique)
// return 0 on success
// return -EEXIST if the parameter exists
// return -ENOMEM if OOM
-int vdev_device_request_add_param( struct vdev_device_request* req, char const* key, char const* value ) {
-
- return vdev_params_add( &req->params, key, value );
+int
+vdev_device_request_add_param (struct vdev_device_request *req,
+ char const *key, char const *value)
+{
+
+ return vdev_params_add (&req->params, key, value);
}
// create a KEY=VALUE string
-static int vdev_device_request_make_env_str( char const* key, char const* value, char** ret ) {
-
- char* e = VDEV_CALLOC( char, strlen(key) + 1 + strlen(value) + 1 );
-
- if( e == NULL ) {
+static int
+vdev_device_request_make_env_str (char const *key, char const *value,
+ char **ret)
+{
+
+ char *e = VDEV_CALLOC (char, strlen (key) + 1 + strlen (value) + 1);
+
+ if (e == NULL)
+ {
return -ENOMEM;
- }
-
- sprintf(e, "%s=%s", key, value );
- *ret = e;
-
- return 0;
-}
+ }
+ sprintf (e, "%s=%s", key, value);
+ *ret = e;
+
+ return 0;
+}
// action to const string
-static char const* vdev_device_request_type_to_string( vdev_device_request_t req ) {
-
- if( req == VDEV_DEVICE_ADD ) {
+static char const *
+vdev_device_request_type_to_string (vdev_device_request_t req)
+{
+
+ if (req == VDEV_DEVICE_ADD)
+ {
return "add";
- }
- if( req == VDEV_DEVICE_REMOVE ) {
+ }
+ if (req == VDEV_DEVICE_REMOVE)
+ {
return "remove";
- }
- if( req == VDEV_DEVICE_CHANGE ) {
+ }
+ if (req == VDEV_DEVICE_CHANGE)
+ {
return "change";
- }
+ }
- return "none";
+ return "none";
}
-
// mode to const string
-static char const* vdev_device_request_mode_to_string( mode_t mode ) {
-
- static char const* blk_str = "block";
- static char const* chr_str = "char";
- static char const* none_str = "none";
-
- if( S_ISBLK(mode) ) {
+static char const *
+vdev_device_request_mode_to_string (mode_t mode)
+{
+
+ static char const *blk_str = "block";
+ static char const *chr_str = "char";
+ static char const *none_str = "none";
+
+ if (S_ISBLK (mode))
+ {
return blk_str;
- }
-
- else if( S_ISCHR(mode) ) {
+ }
+
+ else if (S_ISCHR (mode))
+ {
return chr_str;
- }
-
- return none_str;
+ }
+
+ return none_str;
}
// convert a device request to a list of null-terminated KEY=VALUE environment variable strings
@@ -137,439 +162,535 @@ static char const* vdev_device_request_mode_to_string( mode_t mode ) {
// return 0 on success
// return negative on error
// NOTE: not reload-safe; call while the reload lock is held
-int vdev_device_request_to_env( struct vdev_device_request* req, vdev_params* helper_vars, char*** ret_env, size_t* num_env, int is_daemonlet ) {
-
- // type --> VDEV_ACTION
- // path --> VDEV_PATH (if non-null)
- // dev --> VDEV_MAJOR, VDEV_MINOR (if given)
- // mode --> VDEV_MODE (if given)
- // params --> VDEV_OS_*
- // helper vars --> VDEV_VAR_*
- // mountpoint --> VDEV_MOUNTPOINT
- // metadata --> VDEV_METADATA (if path is non-null)
- // global metadata --> VDEV_GLOBAL_METADATA
- // helpers --> VDEV_HELPERS
- // logfile --> VDEV_LOGFILE
- // vdev instance nonce --> VDEV_INSTANCE
- // config file --> VDEV_CONFIG_FILE
- // daemonlet --> VDEV_DAEMONLET (0 by default, 1 if is_daemonlet is non-zero)
-
- size_t num_vars = 15 + sglib_vdev_params_len( req->params ) + sglib_vdev_params_len( helper_vars );
- int i = 0;
- int rc = 0;
- char dev_buf[51];
- struct vdev_param_t* dp = NULL;
- struct sglib_vdev_params_iterator itr;
- char* vdev_path = req->renamed_path;
- char metadata_dir[ PATH_MAX + 1 ];
- char global_metadata_dir[ PATH_MAX + 1 ];
- char const* is_daemonlet_str = NULL;
- char const* loglevel = NULL;
-
- if( is_daemonlet != 0 ) {
+int
+vdev_device_request_to_env (struct vdev_device_request *req,
+ vdev_params * helper_vars, char ***ret_env,
+ size_t * num_env, int is_daemonlet)
+{
+
+ // type --> VDEV_ACTION
+ // path --> VDEV_PATH (if non-null)
+ // dev --> VDEV_MAJOR, VDEV_MINOR (if given)
+ // mode --> VDEV_MODE (if given)
+ // params --> VDEV_OS_*
+ // helper vars --> VDEV_VAR_*
+ // mountpoint --> VDEV_MOUNTPOINT
+ // metadata --> VDEV_METADATA (if path is non-null)
+ // global metadata --> VDEV_GLOBAL_METADATA
+ // helpers --> VDEV_HELPERS
+ // logfile --> VDEV_LOGFILE
+ // vdev instance nonce --> VDEV_INSTANCE
+ // config file --> VDEV_CONFIG_FILE
+ // daemonlet --> VDEV_DAEMONLET (0 by default, 1 if is_daemonlet is non-zero)
+
+ size_t num_vars =
+ 15 + sglib_vdev_params_len (req->params) +
+ sglib_vdev_params_len (helper_vars);
+ int i = 0;
+ int rc = 0;
+ char dev_buf[51];
+ struct vdev_param_t *dp = NULL;
+ struct sglib_vdev_params_iterator itr;
+ char *vdev_path = req->renamed_path;
+ char metadata_dir[PATH_MAX + 1];
+ char global_metadata_dir[PATH_MAX + 1];
+ char const *is_daemonlet_str = NULL;
+ char const *loglevel = NULL;
+
+ if (is_daemonlet != 0)
+ {
is_daemonlet_str = "1";
- }
- else {
+ }
+ else
+ {
is_daemonlet_str = "0";
- }
-
- memset( metadata_dir, 0, PATH_MAX+1 );
- memset( global_metadata_dir, 0, PATH_MAX+1 );
- memset( dev_buf, 0, 51 );
-
- if( vdev_path == NULL ) {
-
+ }
+
+ memset (metadata_dir, 0, PATH_MAX + 1);
+ memset (global_metadata_dir, 0, PATH_MAX + 1);
+ memset (dev_buf, 0, 51);
+
+ if (vdev_path == NULL)
+ {
+
vdev_path = req->path;
- }
-
- if( vdev_path != NULL ) {
- snprintf( metadata_dir, PATH_MAX, "%s/" VDEV_METADATA_PREFIX "/dev/%s", req->state->mountpoint, vdev_path );
- }
-
- char** env = VDEV_CALLOC( char*, num_vars + 1 );
-
- if( env == NULL ) {
+ }
+
+ if (vdev_path != NULL)
+ {
+ snprintf (metadata_dir, PATH_MAX,
+ "%s/" VDEV_METADATA_PREFIX "/dev/%s",
+ req->state->mountpoint, vdev_path);
+ }
+
+ char **env = VDEV_CALLOC (char *, num_vars + 1);
+
+ if (env == NULL)
+ {
return -ENOMEM;
- }
-
- snprintf( global_metadata_dir, PATH_MAX, "%s/" VDEV_METADATA_PREFIX, req->state->mountpoint );
-
- rc = vdev_device_request_make_env_str( "VDEV_MOUNTPOINT", req->state->mountpoint, &env[i] );
- if( rc != 0 ) {
-
- VDEV_FREE_LIST( env );
+ }
+
+ snprintf (global_metadata_dir, PATH_MAX, "%s/" VDEV_METADATA_PREFIX,
+ req->state->mountpoint);
+
+ rc = vdev_device_request_make_env_str ("VDEV_MOUNTPOINT",
+ req->state->mountpoint, &env[i]);
+ if (rc != 0)
+ {
+
+ VDEV_FREE_LIST (env);
return rc;
- }
-
- i++;
-
- rc = vdev_device_request_make_env_str( "VDEV_ACTION", vdev_device_request_type_to_string( req->type ), &env[i] );
- if( rc != 0 ) {
-
- VDEV_FREE_LIST( env );
+ }
+
+ i++;
+
+ rc = vdev_device_request_make_env_str ("VDEV_ACTION",
+ vdev_device_request_type_to_string
+ (req->type), &env[i]);
+ if (rc != 0)
+ {
+
+ VDEV_FREE_LIST (env);
return rc;
- }
-
- i++;
-
- if( vdev_path != NULL ) {
-
- rc = vdev_device_request_make_env_str( "VDEV_PATH", vdev_path, &env[i] );
- if( rc != 0 ) {
-
- VDEV_FREE_LIST( env );
- return rc;
- }
-
+ }
+
+ i++;
+
+ if (vdev_path != NULL)
+ {
+
+ rc = vdev_device_request_make_env_str ("VDEV_PATH", vdev_path, &env[i]);
+ if (rc != 0)
+ {
+
+ VDEV_FREE_LIST (env);
+ return rc;
+ }
+
i++;
-
- rc = vdev_device_request_make_env_str( "VDEV_METADATA", metadata_dir, &env[i] );
- if( rc != 0 ) {
-
- VDEV_FREE_LIST( env );
- return rc;
- }
-
+
+ rc = vdev_device_request_make_env_str ("VDEV_METADATA",
+ metadata_dir, &env[i]);
+ if (rc != 0)
+ {
+
+ VDEV_FREE_LIST (env);
+ return rc;
+ }
+
i++;
- }
-
- rc = vdev_device_request_make_env_str( "VDEV_GLOBAL_METADATA", global_metadata_dir, &env[i] );
- if( rc != 0 ) {
-
- VDEV_FREE_LIST( env );
+ }
+
+ rc = vdev_device_request_make_env_str ("VDEV_GLOBAL_METADATA",
+ global_metadata_dir, &env[i]);
+ if (rc != 0)
+ {
+
+ VDEV_FREE_LIST (env);
return rc;
- }
-
- i++;
-
- rc = vdev_device_request_make_env_str( "VDEV_CONFIG_FILE", req->state->config->config_path, &env[i] );
- if( rc != 0 ) {
-
- VDEV_FREE_LIST( env );
+ }
+
+ i++;
+
+ rc = vdev_device_request_make_env_str ("VDEV_CONFIG_FILE",
+ req->state->config->config_path,
+ &env[i]);
+ if (rc != 0)
+ {
+
+ VDEV_FREE_LIST (env);
return rc;
- }
-
- i++;
-
- if( req->dev != 0 ) {
-
- snprintf(dev_buf, 50, "%u", major(req->dev) );
-
- rc = vdev_device_request_make_env_str( "VDEV_MAJOR", dev_buf, &env[i] );
- if( rc != 0 ) {
-
- VDEV_FREE_LIST( env );
- return rc;
- }
-
+ }
+
+ i++;
+
+ if (req->dev != 0)
+ {
+
+ snprintf (dev_buf, 50, "%u", major (req->dev));
+
+ rc = vdev_device_request_make_env_str ("VDEV_MAJOR", dev_buf, &env[i]);
+ if (rc != 0)
+ {
+
+ VDEV_FREE_LIST (env);
+ return rc;
+ }
+
i++;
-
- snprintf(dev_buf, 50, "%u", minor(req->dev) );
-
- rc = vdev_device_request_make_env_str( "VDEV_MINOR", dev_buf, &env[i] );
- if( rc != 0 ) {
-
- VDEV_FREE_LIST( env );
- return rc;
- }
-
+
+ snprintf (dev_buf, 50, "%u", minor (req->dev));
+
+ rc = vdev_device_request_make_env_str ("VDEV_MINOR", dev_buf, &env[i]);
+ if (rc != 0)
+ {
+
+ VDEV_FREE_LIST (env);
+ return rc;
+ }
+
i++;
- }
-
- if( (req->mode & (S_IFBLK | S_IFCHR)) != 0 ) {
-
- rc = vdev_device_request_make_env_str( "VDEV_MODE", vdev_device_request_mode_to_string( req->mode ), &env[i] );
- if( rc != 0 ) {
-
- VDEV_FREE_LIST( env );
- return rc;
- }
-
+ }
+
+ if ((req->mode & (S_IFBLK | S_IFCHR)) != 0)
+ {
+
+ rc = vdev_device_request_make_env_str ("VDEV_MODE",
+ vdev_device_request_mode_to_string
+ (req->mode), &env[i]);
+ if (rc != 0)
+ {
+
+ VDEV_FREE_LIST (env);
+ return rc;
+ }
+
i++;
- }
-
- rc = vdev_device_request_make_env_str( "VDEV_HELPERS", req->state->config->helpers_dir, &env[i] );
- if( rc != 0 ) {
-
- VDEV_FREE_LIST( env );
+ }
+
+ rc = vdev_device_request_make_env_str ("VDEV_HELPERS",
+ req->state->config->helpers_dir,
+ &env[i]);
+ if (rc != 0)
+ {
+
+ VDEV_FREE_LIST (env);
return rc;
- }
-
- i++;
-
- if( req->state->config->logfile_path != NULL && strcasecmp( req->state->config->logfile_path, "syslog" ) != 0 ) {
-
- rc = vdev_device_request_make_env_str( "VDEV_LOGFILE", req->state->config->logfile_path, &env[i] );
- if( rc != 0 ) {
-
- VDEV_FREE_LIST( env );
- return rc;
- }
-
+ }
+
+ i++;
+
+ if (req->state->config->logfile_path != NULL
+ && strcasecmp (req->state->config->logfile_path, "syslog") != 0)
+ {
+
+ rc = vdev_device_request_make_env_str ("VDEV_LOGFILE",
+ req->state->config->logfile_path,
+ &env[i]);
+ if (rc != 0)
+ {
+
+ VDEV_FREE_LIST (env);
+ return rc;
+ }
+
i++;
- }
-
- rc = vdev_device_request_make_env_str( "VDEV_INSTANCE", req->state->config->instance_str, &env[i] );
- if( rc != 0 ) {
-
- VDEV_FREE_LIST( env );
- return rc;
- }
-
- i++;
-
- rc = vdev_device_request_make_env_str( "VDEV_DAEMONLET", is_daemonlet_str, &env[i] );
- if( rc != 0 ) {
-
- VDEV_FREE_LIST( env );
+ }
+
+ rc = vdev_device_request_make_env_str ("VDEV_INSTANCE",
+ req->state->config->instance_str,
+ &env[i]);
+ if (rc != 0)
+ {
+
+ VDEV_FREE_LIST (env);
return rc;
- }
-
- i++;
-
- if( vdev_get_debug_level() > 0 ) {
- if( vdev_get_debug_level() == 1 ) {
- loglevel = "info";
- }
- else {
- loglevel = "debug";
- }
- }
- else if( vdev_get_error_level() > 0 ) {
- if( vdev_get_error_level() == 1 ) {
- loglevel = "error";
- }
- else {
- loglevel = "warning";
- }
- }
+ }
+
+ i++;
- if( loglevel == NULL ) {
+ rc = vdev_device_request_make_env_str ("VDEV_DAEMONLET",
+ is_daemonlet_str, &env[i]);
+ if (rc != 0)
+ {
+
+ VDEV_FREE_LIST (env);
+ return rc;
+ }
+
+ i++;
+
+ if (vdev_get_debug_level () > 0)
+ {
+ if (vdev_get_debug_level () == 1)
+ {
+ loglevel = "info";
+ }
+ else
+ {
+ loglevel = "debug";
+ }
+ }
+ else if (vdev_get_error_level () > 0)
+ {
+ if (vdev_get_error_level () == 1)
+ {
+ loglevel = "error";
+ }
+ else
+ {
+ loglevel = "warning";
+ }
+ }
+
+ if (loglevel == NULL)
+ {
loglevel = "warning";
- }
+ }
- rc = vdev_device_request_make_env_str( "VDEV_LOGLEVEL", loglevel, &env[i] );
- if( rc != 0 ) {
+ rc = vdev_device_request_make_env_str ("VDEV_LOGLEVEL", loglevel, &env[i]);
+ if (rc != 0)
+ {
- VDEV_FREE_LIST( env );
+ VDEV_FREE_LIST (env);
return rc;
- }
-
- i++;
-
- // add all OS-specific parameters
- for( dp = sglib_vdev_params_it_init_inorder( &itr, req->params ); dp != NULL; dp = sglib_vdev_params_it_next( &itr ) ) {
-
- char const* param_key = dp->key;
- char const* param_value = dp->value;
-
+ }
+
+ i++;
+
+ // add all OS-specific parameters
+ for (dp = sglib_vdev_params_it_init_inorder (&itr, req->params);
+ dp != NULL; dp = sglib_vdev_params_it_next (&itr))
+ {
+
+ char const *param_key = dp->key;
+ char const *param_value = dp->value;
+
// prepend with "VDEV_OS_"
- char* varname = VDEV_CALLOC( char, strlen(param_key) + 1 + strlen("VDEV_OS_") );
-
- if( varname == NULL ) {
-
- VDEV_FREE_LIST( env );
- return -ENOMEM;
- }
-
- sprintf( varname, "VDEV_OS_%s", param_key );
-
- rc = vdev_device_request_make_env_str( varname, param_value, &env[i] );
-
- free( varname );
-
- if( rc != 0 ) {
-
- VDEV_FREE_LIST( env );
- return rc;
- }
-
+ char *varname = VDEV_CALLOC (char,
+ strlen (param_key) + 1 +
+ strlen ("VDEV_OS_"));
+
+ if (varname == NULL)
+ {
+
+ VDEV_FREE_LIST (env);
+ return -ENOMEM;
+ }
+
+ sprintf (varname, "VDEV_OS_%s", param_key);
+
+ rc = vdev_device_request_make_env_str (varname, param_value, &env[i]);
+
+ free (varname);
+
+ if (rc != 0)
+ {
+
+ VDEV_FREE_LIST (env);
+ return rc;
+ }
+
i++;
- }
-
- // add all helper-specific variables
- for( dp = sglib_vdev_params_it_init_inorder( &itr, helper_vars ); dp != NULL; dp = sglib_vdev_params_it_next( &itr ) ) {
-
- char const* param_key = dp->key;
- char const* param_value = dp->value;
-
+ }
+
+ // add all helper-specific variables
+ for (dp = sglib_vdev_params_it_init_inorder (&itr, helper_vars);
+ dp != NULL; dp = sglib_vdev_params_it_next (&itr))
+ {
+
+ char const *param_key = dp->key;
+ char const *param_value = dp->value;
+
// prepend with "VDEV_OS_"
- char* varname = VDEV_CALLOC( char, strlen(param_key) + 1 + strlen("VDEV_VAR_") );
-
- if( varname == NULL ) {
-
- VDEV_FREE_LIST( env );
- return -ENOMEM;
- }
-
- sprintf( varname, "VDEV_VAR_%s", param_key );
-
- rc = vdev_device_request_make_env_str( varname, param_value, &env[i] );
-
- free( varname );
-
- if( rc != 0 ) {
-
- VDEV_FREE_LIST( env );
- return rc;
- }
-
+ char *varname = VDEV_CALLOC (char,
+ strlen (param_key) + 1 +
+ strlen ("VDEV_VAR_"));
+
+ if (varname == NULL)
+ {
+
+ VDEV_FREE_LIST (env);
+ return -ENOMEM;
+ }
+
+ sprintf (varname, "VDEV_VAR_%s", param_key);
+
+ rc = vdev_device_request_make_env_str (varname, param_value, &env[i]);
+
+ free (varname);
+
+ if (rc != 0)
+ {
+
+ VDEV_FREE_LIST (env);
+ return rc;
+ }
+
i++;
- }
-
- *ret_env = env;
- *num_env = i;
-
- return 0;
-}
+ }
+ *ret_env = env;
+ *num_env = i;
+
+ return 0;
+}
// set the path
// return 0 on success
// return -ENOMEM on OOM
-int vdev_device_request_set_path( struct vdev_device_request* req, char const* path ) {
-
- if( req->path != NULL ) {
- free( req->path );
- }
-
- req->path = vdev_strdup_or_null( path );
-
- if( req->path == NULL && path != NULL ) {
+int
+vdev_device_request_set_path (struct vdev_device_request *req,
+ char const *path)
+{
+
+ if (req->path != NULL)
+ {
+ free (req->path);
+ }
+
+ req->path = vdev_strdup_or_null (path);
+
+ if (req->path == NULL && path != NULL)
+ {
return -ENOMEM;
- }
-
- return 0;
+ }
+
+ return 0;
}
// set the device
// always succeeds
-int vdev_device_request_set_dev( struct vdev_device_request* req, dev_t dev ) {
-
- req->dev = dev;
- return 0;
-}
+int
+vdev_device_request_set_dev (struct vdev_device_request *req, dev_t dev)
+{
+ req->dev = dev;
+ return 0;
+}
// mark this device as already existing
// always succeeds
-int vdev_device_request_set_exists( struct vdev_device_request* req, bool exists ) {
-
- req->exists = exists;
- return 0;
+int
+vdev_device_request_set_exists (struct vdev_device_request *req, bool exists)
+{
+
+ req->exists = exists;
+ return 0;
}
-
// device request sanity check
// return 0 if valid
// return -EINVAL if not valid
-int vdev_device_request_sanity_check( struct vdev_device_request* req ) {
-
- if( req->path == NULL ) {
-
- vdev_error("request %p missing path\n", req );
+int
+vdev_device_request_sanity_check (struct vdev_device_request *req)
+{
+
+ if (req->path == NULL)
+ {
+
+ vdev_error ("request %p missing path\n", req);
return -EINVAL;
- }
-
- if( req->type == VDEV_DEVICE_INVALID ) {
-
- vdev_error("request %p has no request type\n", req );
+ }
+
+ if (req->type == VDEV_DEVICE_INVALID)
+ {
+
+ vdev_error ("request %p has no request type\n", req);
return -EINVAL;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// set the request type
-int vdev_device_request_set_type( struct vdev_device_request* req, vdev_device_request_t req_type ) {
-
- req->type = req_type;
- return 0;
-}
+int
+vdev_device_request_set_type (struct vdev_device_request *req,
+ vdev_device_request_t req_type)
+{
+ req->type = req_type;
+ return 0;
+}
// set the request device mode
-int vdev_device_request_set_mode( struct vdev_device_request* req, mode_t mode ) {
-
- req->mode = mode;
- return 0;
-}
+int
+vdev_device_request_set_mode (struct vdev_device_request *req, mode_t mode)
+{
+ req->mode = mode;
+ return 0;
+}
// generate a path to a device's metadata
// return the malloc'ed path on success
// return NULL on error
-char* vdev_device_metadata_fullpath( char const* mountpoint, char const* device_path ) {
-
- char* base_dir = NULL;
- char* metadata_dir = VDEV_CALLOC( char, strlen( mountpoint ) + 1 + strlen(VDEV_METADATA_PREFIX) + 2 + strlen(device_path) + 1 );
- if( metadata_dir == NULL ) {
-
+char *
+vdev_device_metadata_fullpath (char const *mountpoint,
+ char const *device_path)
+{
+
+ char *base_dir = NULL;
+ char *metadata_dir = VDEV_CALLOC (char,
+ strlen (mountpoint) + 1 +
+ strlen (VDEV_METADATA_PREFIX) + 2 +
+ strlen (device_path) + 1);
+ if (metadata_dir == NULL)
+ {
+
return NULL;
- }
-
- sprintf( metadata_dir, VDEV_METADATA_PREFIX "/dev/%s", device_path );
-
- base_dir = vdev_fullpath( mountpoint, metadata_dir, NULL );
-
- free( metadata_dir );
-
- if( base_dir == NULL ) {
-
+ }
+
+ sprintf (metadata_dir, VDEV_METADATA_PREFIX "/dev/%s", device_path);
+
+ base_dir = vdev_fullpath (mountpoint, metadata_dir, NULL);
+
+ free (metadata_dir);
+
+ if (base_dir == NULL)
+ {
+
return NULL;
- }
-
- return base_dir;
-}
+ }
+ return base_dir;
+}
// create or update an item of metadata to $VDEV_MOUNTPOINT/$VDEV_METADATA_PREFIX/dev/$VDEV_PATH/$PARAM_KEY
// return 0 on success
// return negative on error
-static int vdev_device_put_metadata_item( char* base_dir, char const* param_name, char const* param_value, int flags, mode_t mode ) {
-
- int rc = 0;
- char* param_value_with_newline = NULL;
- char* key_value_path = NULL;
-
- key_value_path = vdev_fullpath( base_dir, param_name, NULL );
-
- if( key_value_path == NULL ) {
-
+static int
+vdev_device_put_metadata_item (char *base_dir, char const *param_name,
+ char const *param_value, int flags,
+ mode_t mode)
+{
+
+ int rc = 0;
+ char *param_value_with_newline = NULL;
+ char *key_value_path = NULL;
+
+ key_value_path = vdev_fullpath (base_dir, param_name, NULL);
+
+ if (key_value_path == NULL)
+ {
+
rc = -ENOMEM;
return rc;
- }
-
- param_value_with_newline = VDEV_CALLOC( char, strlen(param_value) + 2 );
- if( param_value_with_newline == NULL ) {
-
+ }
+
+ param_value_with_newline = VDEV_CALLOC (char, strlen (param_value) + 2);
+ if (param_value_with_newline == NULL)
+ {
+
rc = -ENOMEM;
- free( key_value_path );
+ free (key_value_path);
return rc;
- }
-
- strcpy( param_value_with_newline, param_value );
- strcat( param_value_with_newline, "\n");
-
- rc = vdev_write_file( key_value_path, param_value_with_newline, strlen(param_value_with_newline), flags, mode );
-
- free( param_value_with_newline );
-
- if( rc < 0 ) {
-
- vdev_error("vdev_write_file('%s', '%s') rc = %d\n", key_value_path, param_value, rc );
- }
- else {
-
+ }
+
+ strcpy (param_value_with_newline, param_value);
+ strcat (param_value_with_newline, "\n");
+
+ rc = vdev_write_file (key_value_path, param_value_with_newline,
+ strlen (param_value_with_newline), flags, mode);
+
+ free (param_value_with_newline);
+
+ if (rc < 0)
+ {
+
+ vdev_error ("vdev_write_file('%s', '%s') rc = %d\n",
+ key_value_path, param_value, rc);
+ }
+ else
+ {
+
rc = 0;
- }
-
- free( key_value_path );
-
- return rc;
-}
+ }
+ free (key_value_path);
+
+ return rc;
+}
// record extra metadata (i.e. vdev parameters) for a device node
// overwrite existing metadata if it already exists for this device.
@@ -579,241 +700,276 @@ static int vdev_device_put_metadata_item( char* base_dir, char const* param_name
// return negative on I/O error
// NOTE: the device metadata directory ($VDEV_MOUNTPOINT/$VDEV_METADATA_PREFIX/dev) must exist
// NOTE: not reload-safe; call while the reload lock is held
-static int vdev_device_put_metadata( struct vdev_device_request* req ) {
-
- int rc = 0;
- struct sglib_vdev_params_iterator itr;
- struct vdev_param_t* dp;
-
- char* base_dir = NULL;
- char* device_path = NULL;
-
- // only create device metadata if the device path is known.
- if( req->renamed_path != NULL ) {
-
+static int
+vdev_device_put_metadata (struct vdev_device_request *req)
+{
+
+ int rc = 0;
+ struct sglib_vdev_params_iterator itr;
+ struct vdev_param_t *dp;
+
+ char *base_dir = NULL;
+ char *device_path = NULL;
+
+ // only create device metadata if the device path is known.
+ if (req->renamed_path != NULL)
+ {
+
device_path = req->renamed_path;
- }
- else if( req->path != NULL ) {
-
+ }
+ else if (req->path != NULL)
+ {
+
device_path = req->path;
- }
- else {
-
+ }
+ else
+ {
+
return -EINVAL;
- }
-
- // unknown?
- if( strcmp( device_path, VDEV_DEVICE_PATH_UNKNOWN ) == 0 ) {
-
+ }
+
+ // unknown?
+ if (strcmp (device_path, VDEV_DEVICE_PATH_UNKNOWN) == 0)
+ {
+
return -EINVAL;
- }
-
- // path to device metadata
- base_dir = vdev_device_metadata_fullpath( req->state->mountpoint, req->renamed_path );
- if( base_dir == NULL ) {
-
+ }
+ // path to device metadata
+ base_dir =
+ vdev_device_metadata_fullpath (req->state->mountpoint, req->renamed_path);
+ if (base_dir == NULL)
+ {
+
return -ENOMEM;
- }
-
- // all directories must exist
- rc = vdev_mkdirs( base_dir, strlen( req->state->mountpoint ), 0755 );
- if( rc != 0 ) {
-
- vdev_error("vdev_mkdirs('%s') rc = %d\n", base_dir, rc );
-
- free( base_dir );
+ }
+ // all directories must exist
+ rc = vdev_mkdirs (base_dir, strlen (req->state->mountpoint), 0755);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_mkdirs('%s') rc = %d\n", base_dir, rc);
+
+ free (base_dir);
base_dir = NULL;
-
+
return rc;
- }
-
- // save instance nonce
- rc = vdev_device_put_metadata_item( base_dir, VDEV_METADATA_PARAM_INSTANCE, req->state->config->instance_str, O_CREAT | O_WRONLY | O_TRUNC, 0644 );
- if( rc != 0 ) {
-
- if( rc == -EEXIST ) {
-
- // try to update instead
- rc = vdev_device_put_metadata_item( base_dir, VDEV_METADATA_PARAM_INSTANCE, req->state->config->instance_str, O_WRONLY | O_TRUNC, 0644 );
- }
-
- if( rc != 0 ) {
- vdev_error("vdev_device_put_metadata_item('%s', '%s') rc = %d\n", VDEV_METADATA_PARAM_INSTANCE, req->state->config->instance_str, rc );
- }
- }
-
- free( base_dir );
-
- return rc;
+ }
+ // save instance nonce
+ rc = vdev_device_put_metadata_item (base_dir,
+ VDEV_METADATA_PARAM_INSTANCE,
+ req->state->config->instance_str,
+ O_CREAT | O_WRONLY | O_TRUNC, 0644);
+ if (rc != 0)
+ {
+
+ if (rc == -EEXIST)
+ {
+
+ // try to update instead
+ rc = vdev_device_put_metadata_item (base_dir,
+ VDEV_METADATA_PARAM_INSTANCE,
+ req->state->config->
+ instance_str,
+ O_WRONLY | O_TRUNC, 0644);
+ }
+
+ if (rc != 0)
+ {
+ vdev_error
+ ("vdev_device_put_metadata_item('%s', '%s') rc = %d\n",
+ VDEV_METADATA_PARAM_INSTANCE,
+ req->state->config->instance_str, rc);
+ }
+ }
+
+ free (base_dir);
+
+ return rc;
}
-
// remove helper for vdev_device_remove_metadata
// return 0 on success
// return -errno for unlink failure
-static int vdev_device_remove_metadata_file( char const* fp, void* cls ) {
-
- int rc = 0;
- struct stat sb;
-
- char name_buf[ VDEV_NAME_MAX + 1 ];
-
- vdev_basename( fp, name_buf );
-
- if( strcmp(name_buf, ".") == 0 || strcmp(name_buf, "..") == 0 ) {
+static int
+vdev_device_remove_metadata_file (char const *fp, void *cls)
+{
+
+ int rc = 0;
+ struct stat sb;
+
+ char name_buf[VDEV_NAME_MAX + 1];
+
+ vdev_basename (fp, name_buf);
+
+ if (strcmp (name_buf, ".") == 0 || strcmp (name_buf, "..") == 0)
+ {
// skip
return 0;
- }
-
- // is this a directory?
- rc = lstat( fp, &sb );
- if( rc != 0 ) {
-
+ }
+ // is this a directory?
+ rc = lstat (fp, &sb);
+ if (rc != 0)
+ {
+
rc = -errno;
- vdev_warn("stat('%s') rc = %d\n", fp, rc );
+ vdev_warn ("stat('%s') rc = %d\n", fp, rc);
return rc;
- }
-
- if( S_ISDIR( sb.st_mode ) ) {
-
+ }
+
+ if (S_ISDIR (sb.st_mode))
+ {
+
// blow away children too
- rc = vdev_load_all( fp, vdev_device_remove_metadata_file, NULL );
- if( rc != 0 ) {
-
- vdev_warn("removing '%s' rc = %d\n", fp, rc );
- return rc;
- }
-
+ rc = vdev_load_all (fp, vdev_device_remove_metadata_file, NULL);
+ if (rc != 0)
+ {
+
+ vdev_warn ("removing '%s' rc = %d\n", fp, rc);
+ return rc;
+ }
// blow away dir
- rc = rmdir( fp );
- }
- else {
-
+ rc = rmdir (fp);
+ }
+ else
+ {
+
// regular file
- rc = unlink( fp );
- }
-
- if( rc != 0 ) {
-
+ rc = unlink (fp);
+ }
+
+ if (rc != 0)
+ {
+
rc = -errno;
- vdev_warn("unlink('%s') rc = %d\n", fp, rc );
+ vdev_warn ("unlink('%s') rc = %d\n", fp, rc);
return rc;
- }
-
- return rc;
+ }
+
+ return rc;
}
// remove extra metadata (i.e. vdev and OS parameters) for a deivce node
// return 0 on success
// return negative on error
// NOTE: not reload-safe; call while the reload lock is held
-static int vdev_device_remove_metadata( struct vdev_device_request* req ) {
-
- int rc = 0;
-
- char* base_dir = NULL;
- char metadata_dir[ PATH_MAX + 1 ];
-
- // NOTE: req->path is guaranteed to be <= 256 characters
- sprintf( metadata_dir, VDEV_METADATA_PREFIX "/dev/%s", req->path );
-
- base_dir = vdev_fullpath( req->state->mountpoint, metadata_dir, NULL );
- if( base_dir == NULL ) {
-
+static int
+vdev_device_remove_metadata (struct vdev_device_request *req)
+{
+
+ int rc = 0;
+
+ char *base_dir = NULL;
+ char metadata_dir[PATH_MAX + 1];
+
+ // NOTE: req->path is guaranteed to be <= 256 characters
+ sprintf (metadata_dir, VDEV_METADATA_PREFIX "/dev/%s", req->path);
+
+ base_dir = vdev_fullpath (req->state->mountpoint, metadata_dir, NULL);
+ if (base_dir == NULL)
+ {
+
return -ENOMEM;
- }
-
- // remove everything in this directory
- rc = vdev_load_all( base_dir, vdev_device_remove_metadata_file, NULL );
-
- if( rc != 0 ) {
-
- vdev_error("vdev_load_all('%s') rc = %d\n", base_dir, rc );
- }
-
- // remove the directory itself
- rc = rmdir( base_dir );
- if( rc != 0 ) {
-
+ }
+ // remove everything in this directory
+ rc = vdev_load_all (base_dir, vdev_device_remove_metadata_file, NULL);
+
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_load_all('%s') rc = %d\n", base_dir, rc);
+ }
+ // remove the directory itself
+ rc = rmdir (base_dir);
+ if (rc != 0)
+ {
+
rc = -errno;
- vdev_warn("rmdir('%s') rc = %d\n", base_dir, rc );
- }
-
- free( base_dir );
- return rc;
-}
+ vdev_warn ("rmdir('%s') rc = %d\n", base_dir, rc);
+ }
+ free (base_dir);
+ return rc;
+}
// do we have metadata logged for a device?
// return 0 on success
// return negative on error
// NOTE: not reload-safe; call while the reload lock is held
-static int vdev_device_has_metadata( struct vdev_device_request* req ) {
-
- int rc = 0;
- struct stat sb;
- char* md_fp = vdev_device_metadata_fullpath( req->state->mountpoint, req->renamed_path );
- if( md_fp == NULL ) {
-
+static int
+vdev_device_has_metadata (struct vdev_device_request *req)
+{
+
+ int rc = 0;
+ struct stat sb;
+ char *md_fp = vdev_device_metadata_fullpath (req->state->mountpoint,
+ req->renamed_path);
+ if (md_fp == NULL)
+ {
+
rc = -ENOMEM;
- }
- else {
-
- rc = stat( md_fp, &sb );
+ }
+ else
+ {
- if( rc != 0 ) {
- rc = -errno;
- }
-
- free( md_fp );
- }
-
- return rc;
-}
+ rc = stat (md_fp, &sb);
+ if (rc != 0)
+ {
+ rc = -errno;
+ }
+
+ free (md_fp);
+ }
+
+ return rc;
+}
// create all directories leading up to a device
// return 0 on success
// return negative on error
// NOTE: not reload-safe; call while the reload lock is held
-static int vdev_device_mkdirs( struct vdev_device_request* req, char** dev_fullpath ) {
-
- int rc = 0;
- char* fp = NULL;
- char* fp_dir = NULL;
-
- fp = vdev_fullpath( req->state->mountpoint, req->renamed_path, NULL );
- if( fp == NULL ) {
-
+static int
+vdev_device_mkdirs (struct vdev_device_request *req, char **dev_fullpath)
+{
+
+ int rc = 0;
+ char *fp = NULL;
+ char *fp_dir = NULL;
+
+ fp = vdev_fullpath (req->state->mountpoint, req->renamed_path, NULL);
+ if (fp == NULL)
+ {
+
rc = -ENOMEM;
return rc;
- }
-
- if( strchr(req->renamed_path, '/') != NULL ) {
-
- fp_dir = vdev_dirname( fp, NULL );
- if( fp_dir == NULL ) {
-
- rc = -ENOMEM;
- free( fp );
- return rc;
- }
-
+ }
+
+ if (strchr (req->renamed_path, '/') != NULL)
+ {
+
+ fp_dir = vdev_dirname (fp, NULL);
+ if (fp_dir == NULL)
+ {
+
+ rc = -ENOMEM;
+ free (fp);
+ return rc;
+ }
// make sure the directories leading to this path exist
- rc = vdev_mkdirs( fp_dir, strlen(req->state->mountpoint), 0755 );
- if( rc != 0 ) {
-
- vdev_error("vdev_mkdirs('%s') rc = %d\n", fp_dir, rc );
- }
-
- free( fp_dir );
- }
-
- *dev_fullpath = fp;
-
- return rc;
-}
+ rc = vdev_mkdirs (fp_dir, strlen (req->state->mountpoint), 0755);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_mkdirs('%s') rc = %d\n", fp_dir, rc);
+ }
+ free (fp_dir);
+ }
+
+ *dev_fullpath = fp;
+
+ return rc;
+}
// handler to add a device
// rename the device, and if it succeeds, mknod the device (if it exists),
@@ -821,288 +977,349 @@ static int vdev_device_mkdirs( struct vdev_device_request* req, char** dev_fullp
// return -ENOMEM on OOM
// return -EACCES if we do not have enough privileges to create the device node
// return -EEXIST if the device node already exists
-int vdev_device_add( struct vdev_device_request* req ) {
-
- int rc = 0;
- int do_mknod = 1; // if 1, issue mknod. Otherwise, check to see if the device exists by checking for metadata.
- int device_exists = 0; // if 1, the device already exists. only run commands with the if_exists directive set to "run"
-
- // prevent reloads while processing
- vdev_reload_lock( req->state );
-
- // do the rename, possibly generating it
- rc = vdev_action_create_path( req, req->state->acts, req->state->num_acts, &req->renamed_path );
- if( rc != 0 ) {
-
- vdev_error("vdev_action_create_path('%s') rc = %d\n", req->path, rc);
-
+int
+vdev_device_add (struct vdev_device_request *req)
+{
+
+ int rc = 0;
+ int do_mknod = 1; // if 1, issue mknod. Otherwise, check to see if the device exists by checking for metadata.
+ int device_exists = 0; // if 1, the device already exists. only run commands with the if_exists directive set to "run"
+
+ // prevent reloads while processing
+ vdev_reload_lock (req->state);
+
+ // do the rename, possibly generating it
+ rc = vdev_action_create_path (req, req->state->acts,
+ req->state->num_acts, &req->renamed_path);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_action_create_path('%s') rc = %d\n", req->path, rc);
+
// done with this request
- vdev_reload_unlock( req->state );
- vdev_device_request_free( req );
- free( req );
-
+ vdev_reload_unlock (req->state);
+ vdev_device_request_free (req);
+ free (req);
+
return rc;
- }
-
- if( req->renamed_path == NULL ) {
-
+ }
+
+ if (req->renamed_path == NULL)
+ {
+
// base path becomes renamed path (trivial rename)
- req->renamed_path = vdev_strdup_or_null( req->path );
- if( req->renamed_path == NULL && req->path != NULL ) {
-
- // done with this request
- vdev_reload_unlock( req->state );
- vdev_device_request_free( req );
- free( req );
-
- return -ENOMEM;
- }
- }
-
- vdev_debug("ADD device: type '%s' at '%s' ('%s' %d:%d)\n", (S_ISBLK(req->mode) ? "block" : S_ISCHR(req->mode) ? "char" : "unknown"), req->renamed_path, req->path, major(req->dev), minor(req->dev) );
-
- if( req->renamed_path != NULL ) {
-
+ req->renamed_path = vdev_strdup_or_null (req->path);
+ if (req->renamed_path == NULL && req->path != NULL)
+ {
+
+ // done with this request
+ vdev_reload_unlock (req->state);
+ vdev_device_request_free (req);
+ free (req);
+
+ return -ENOMEM;
+ }
+ }
+
+ vdev_debug ("ADD device: type '%s' at '%s' ('%s' %d:%d)\n",
+ (S_ISBLK (req->mode) ? "block" : S_ISCHR (req->mode) ? "char" :
+ "unknown"), req->renamed_path, req->path, major (req->dev),
+ minor (req->dev));
+
+ if (req->renamed_path != NULL)
+ {
+
// device has a name (i.e. something for us to add)?
- if( strcmp( req->renamed_path, VDEV_DEVICE_PATH_UNKNOWN ) != 0 ) {
-
- // device has major/minor/mode?
- if( req->dev != 0 && req->mode != 0 ) {
-
- char* fp = NULL; // full path to the device
-
- rc = vdev_device_mkdirs( req, &fp );
- if( rc != 0 ) {
-
- vdev_error("vdev_device_mkdirs('%s/%s') rc = %d\n", req->state->mountpoint, req->renamed_path, rc );
-
- // done with this request
- vdev_reload_unlock( req->state );
- vdev_device_request_free( req );
- free( req );
-
- return rc;
- }
-
- // do we need to make the device?
- if( vdev_config_has_OS_quirk( req->state->config->OS_quirks, VDEV_OS_QUIRK_DEVICE_EXISTS ) ) {
-
- // nope, but did we process it already?
- if( vdev_device_has_metadata( req ) ) {
-
- // this device already exists, insofar as
- // we (or some other device manager)
- // have already processed it.
- device_exists = 1;
- }
- }
-
- else {
-
- if( !req->exists ) {
-
- // file is not expected to exist
- rc = mknod( fp, req->mode | req->state->config->default_mode, req->dev );
- }
- else {
-
- rc = 0;
- }
-
- if( rc != 0 ) {
-
- rc = -errno;
- if( rc == -EEXIST ) {
-
- // device already exists, insofar as
- // we (or some other device manager)
- // have already processed it.
- device_exists = 1;
- rc = 0;
- }
- }
- }
-
- free( fp );
- }
-
- // no major/minor/mode
- else {
-
- // not creating a device file, but a device-add event nevertheless.
- // creating or updating?
- rc = vdev_device_has_metadata( req );
- if( rc != 0 ) {
-
- if( rc == -ENOENT ) {
-
- // add metadata, since none exists!
- rc = 0;
- }
- }
- else {
-
- // metadata already present, meaning
- // that this device has been processed
- rc = 0;
- device_exists = 1;
- }
- }
-
- if( rc != 0 ) {
-
- // some mknod or metadata I/O error occurred
- vdev_error("Add device '%s/%s', rc = %d\n", req->state->mountpoint, req->renamed_path, rc );
- }
-
- else {
-
- // put/update metadata
- rc = vdev_device_put_metadata( req );
-
- if( rc != 0 ) {
-
- vdev_error("vdev_device_put_metadata('%s/%s') rc = %d\n", req->state->mountpoint, req->renamed_path, rc );
- }
- }
- }
-
- if( rc == 0 ) {
-
- // no problems yet. call all ADD actions
- rc = vdev_action_run_commands( req, req->state->acts, req->state->num_acts, device_exists );
- if( rc != 0 ) {
-
- vdev_error("vdev_action_run_commands(ADD %s, dev=(%u, %u)) rc = %d\n", req->renamed_path, major(req->dev), minor(req->dev), rc );
- }
- }
- }
-
- // done with this request
- vdev_reload_unlock( req->state );
- vdev_device_request_free( req );
- free( req );
-
- return 0;
+ if (strcmp (req->renamed_path, VDEV_DEVICE_PATH_UNKNOWN) != 0)
+ {
+
+ // device has major/minor/mode?
+ if (req->dev != 0 && req->mode != 0)
+ {
+
+ char *fp = NULL; // full path to the device
+
+ rc = vdev_device_mkdirs (req, &fp);
+ if (rc != 0)
+ {
+
+ vdev_error
+ ("vdev_device_mkdirs('%s/%s') rc = %d\n",
+ req->state->mountpoint, req->renamed_path, rc);
+
+ // done with this request
+ vdev_reload_unlock (req->state);
+ vdev_device_request_free (req);
+ free (req);
+
+ return rc;
+ }
+ // do we need to make the device?
+ if (vdev_config_has_OS_quirk
+ (req->state->config->OS_quirks,
+ VDEV_OS_QUIRK_DEVICE_EXISTS))
+ {
+
+ // nope, but did we process it already?
+ if (vdev_device_has_metadata (req))
+ {
+
+ // this device already exists, insofar as
+ // we (or some other device manager)
+ // have already processed it.
+ device_exists = 1;
+ }
+ }
+
+ else
+ {
+
+ if (!req->exists)
+ {
+
+ // file is not expected to exist
+ rc = mknod (fp,
+ req->mode | req->state->config->
+ default_mode, req->dev);
+ }
+ else
+ {
+
+ rc = 0;
+ }
+
+ if (rc != 0)
+ {
+
+ rc = -errno;
+ if (rc == -EEXIST)
+ {
+
+ // device already exists, insofar as
+ // we (or some other device manager)
+ // have already processed it.
+ device_exists = 1;
+ rc = 0;
+ }
+ }
+ }
+
+ free (fp);
+ }
+ // no major/minor/mode
+ else
+ {
+
+ // not creating a device file, but a device-add event nevertheless.
+ // creating or updating?
+ rc = vdev_device_has_metadata (req);
+ if (rc != 0)
+ {
+
+ if (rc == -ENOENT)
+ {
+
+ // add metadata, since none exists!
+ rc = 0;
+ }
+ }
+ else
+ {
+
+ // metadata already present, meaning
+ // that this device has been processed
+ rc = 0;
+ device_exists = 1;
+ }
+ }
+
+ if (rc != 0)
+ {
+
+ // some mknod or metadata I/O error occurred
+ vdev_error ("Add device '%s/%s', rc = %d\n",
+ req->state->mountpoint, req->renamed_path, rc);
+ }
+
+ else
+ {
+
+ // put/update metadata
+ rc = vdev_device_put_metadata (req);
+
+ if (rc != 0)
+ {
+
+ vdev_error
+ ("vdev_device_put_metadata('%s/%s') rc = %d\n",
+ req->state->mountpoint, req->renamed_path, rc);
+ }
+ }
+ }
+
+ if (rc == 0)
+ {
+
+ // no problems yet. call all ADD actions
+ rc = vdev_action_run_commands (req, req->state->acts,
+ req->state->num_acts, device_exists);
+ if (rc != 0)
+ {
+
+ vdev_error
+ ("vdev_action_run_commands(ADD %s, dev=(%u, %u)) rc = %d\n",
+ req->renamed_path, major (req->dev), minor (req->dev), rc);
+ }
+ }
+ }
+ // done with this request
+ vdev_reload_unlock (req->state);
+ vdev_device_request_free (req);
+ free (req);
+
+ return 0;
}
// workqueue call to vdev_device_add
-static int vdev_device_add_wq( struct vdev_wreq* wreq, void* cls ) {
-
- struct vdev_device_request* req = (struct vdev_device_request*)cls;
- return vdev_device_add( req );
-}
+static int
+vdev_device_add_wq (struct vdev_wreq *wreq, void *cls)
+{
+ struct vdev_device_request *req = (struct vdev_device_request *) cls;
+ return vdev_device_add (req);
+}
// handler to remove a device (unlink)
// return 0 on success. This masks failure to unlink or clean up metadata or a failed action.
// return -ENOMEM on OOM
-int vdev_device_remove( struct vdev_device_request* req ) {
-
- int rc = 0;
-
- vdev_reload_lock( req->state );
-
- // do the rename, possibly generating it
- rc = vdev_action_create_path( req, req->state->acts, req->state->num_acts, &req->renamed_path );
- if( rc != 0 ) {
-
- vdev_error("vdev_action_create_path('%s') rc = %d\n", req->path, rc);
-
+int
+vdev_device_remove (struct vdev_device_request *req)
+{
+
+ int rc = 0;
+
+ vdev_reload_lock (req->state);
+
+ // do the rename, possibly generating it
+ rc = vdev_action_create_path (req, req->state->acts,
+ req->state->num_acts, &req->renamed_path);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_action_create_path('%s') rc = %d\n", req->path, rc);
+
// done with this request
- vdev_reload_unlock( req->state );
- vdev_device_request_free( req );
- free( req );
-
+ vdev_reload_unlock (req->state);
+ vdev_device_request_free (req);
+ free (req);
+
return rc;
- }
-
- if( req->renamed_path == NULL ) {
-
- req->renamed_path = vdev_strdup_or_null( req->path );
- if( req->renamed_path == NULL && req->path == NULL ) {
-
- // done with this request
- vdev_reload_unlock( req->state );
- vdev_device_request_free( req );
- free( req );
-
- return -ENOMEM;
- }
- }
-
- vdev_info("REMOVE device: type '%s' at '%s' ('%s' %d:%d)\n", (S_ISBLK(req->mode) ? "block" : S_ISCHR(req->mode) ? "char" : "unknown"), req->renamed_path, req->path, major(req->dev), minor(req->dev) );
-
- if( req->renamed_path != NULL ) {
-
+ }
+
+ if (req->renamed_path == NULL)
+ {
+
+ req->renamed_path = vdev_strdup_or_null (req->path);
+ if (req->renamed_path == NULL && req->path == NULL)
+ {
+
+ // done with this request
+ vdev_reload_unlock (req->state);
+ vdev_device_request_free (req);
+ free (req);
+
+ return -ENOMEM;
+ }
+ }
+
+ vdev_info ("REMOVE device: type '%s' at '%s' ('%s' %d:%d)\n",
+ (S_ISBLK (req->mode) ? "block" : S_ISCHR (req->mode) ? "char" :
+ "unknown"), req->renamed_path, req->path, major (req->dev),
+ minor (req->dev));
+
+ if (req->renamed_path != NULL)
+ {
+
// call all REMOVE actions
- rc = vdev_action_run_commands( req, req->state->acts, req->state->num_acts, true );
- if( rc != 0 ) {
-
- vdev_error("vdev_action_run_all(REMOVE %s) rc = %d\n", req->renamed_path, rc );
- rc = 0;
- }
-
- if( strcmp( req->renamed_path, VDEV_DEVICE_PATH_UNKNOWN ) != 0 ) {
-
- // known path
- // only remove files from /dev if this is a device, and we created it
- if( req->dev != 0 && req->mode != 0 && !vdev_config_has_OS_quirk( req->state->config->OS_quirks, VDEV_OS_QUIRK_DEVICE_EXISTS ) ) {
-
- // remove the data itself, if there is data
- char* fp = vdev_fullpath( req->state->mountpoint, req->renamed_path, NULL );
-
- rc = unlink( fp );
- if( rc != 0 ) {
-
- rc = -errno;
-
- if( rc != -ENOENT ) {
- vdev_error("unlink(%s) rc = %d\n", fp, rc );
- }
-
- rc = 0;
- }
-
- // try to clean up directories
- rc = vdev_rmdirs( fp );
- if( rc != 0 && rc != -ENOTEMPTY && rc != -ENOENT ) {
-
- vdev_error("vdev_rmdirs('%s') rc = %d\n", fp, rc );
- rc = 0;
- }
-
- free( fp );
- }
-
- // remove metadata
- rc = vdev_device_remove_metadata( req );
-
- if( rc != 0 ) {
-
- vdev_warn("unable to clean up metadata for %s\n", req->renamed_path );
- rc = 0;
- }
- }
- }
-
- vdev_reload_unlock( req->state );
-
- // done with this request
- vdev_device_request_free( req );
- free( req );
-
- return rc;
+ rc = vdev_action_run_commands (req, req->state->acts,
+ req->state->num_acts, true);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_action_run_all(REMOVE %s) rc = %d\n",
+ req->renamed_path, rc);
+ rc = 0;
+ }
+
+ if (strcmp (req->renamed_path, VDEV_DEVICE_PATH_UNKNOWN) != 0)
+ {
+
+ // known path
+ // only remove files from /dev if this is a device, and we created it
+ if (req->dev != 0 && req->mode != 0
+ && !vdev_config_has_OS_quirk (req->state->config->OS_quirks,
+ VDEV_OS_QUIRK_DEVICE_EXISTS))
+ {
+
+ // remove the data itself, if there is data
+ char *fp = vdev_fullpath (req->state->mountpoint,
+ req->renamed_path,
+ NULL);
+
+ rc = unlink (fp);
+ if (rc != 0)
+ {
+
+ rc = -errno;
+
+ if (rc != -ENOENT)
+ {
+ vdev_error ("unlink(%s) rc = %d\n", fp, rc);
+ }
+
+ rc = 0;
+ }
+ // try to clean up directories
+ rc = vdev_rmdirs (fp);
+ if (rc != 0 && rc != -ENOTEMPTY && rc != -ENOENT)
+ {
+
+ vdev_error ("vdev_rmdirs('%s') rc = %d\n", fp, rc);
+ rc = 0;
+ }
+
+ free (fp);
+ }
+ // remove metadata
+ rc = vdev_device_remove_metadata (req);
+
+ if (rc != 0)
+ {
+
+ vdev_warn
+ ("unable to clean up metadata for %s\n", req->renamed_path);
+ rc = 0;
+ }
+ }
+ }
+
+ vdev_reload_unlock (req->state);
+
+ // done with this request
+ vdev_device_request_free (req);
+ free (req);
+
+ return rc;
}
-
// workqueue call to vdev_device_remove
-static int vdev_device_remove_wq( struct vdev_wreq* wreq, void* cls ) {
-
- struct vdev_device_request* req = (struct vdev_device_request*)cls;
- return vdev_device_remove( req );
-}
+static int
+vdev_device_remove_wq (struct vdev_wreq *wreq, void *cls)
+{
+ struct vdev_device_request *req = (struct vdev_device_request *) cls;
+ return vdev_device_remove (req);
+}
// handler to change a device
// Process any rename commands to get the final path, and then update that path's metadata
@@ -1111,123 +1328,146 @@ static int vdev_device_remove_wq( struct vdev_wreq* wreq, void* cls ) {
// return -ENOMEM on OOM
// return -EACCES if we do not have enough privileges to create the device node
// return -EEXIST if the device node already exists
-int vdev_device_change( struct vdev_device_request* req ) {
-
- int rc = 0;
-
- vdev_reload_lock( req->state );
-
- // do the rename, possibly generating it
- rc = vdev_action_create_path( req, req->state->acts, req->state->num_acts, &req->renamed_path );
- if( rc != 0 ) {
-
- vdev_error("vdev_action_create_path('%s') rc = %d\n", req->path, rc);
-
+int
+vdev_device_change (struct vdev_device_request *req)
+{
+
+ int rc = 0;
+
+ vdev_reload_lock (req->state);
+
+ // do the rename, possibly generating it
+ rc = vdev_action_create_path (req, req->state->acts,
+ req->state->num_acts, &req->renamed_path);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_action_create_path('%s') rc = %d\n", req->path, rc);
+
// done with this request
- vdev_reload_unlock( req->state );
- vdev_device_request_free( req );
- free( req );
-
+ vdev_reload_unlock (req->state);
+ vdev_device_request_free (req);
+ free (req);
+
return rc;
- }
-
- if( req->renamed_path == NULL ) {
-
+ }
+
+ if (req->renamed_path == NULL)
+ {
+
// base path becomes renamed path (trivial rename)
- req->renamed_path = vdev_strdup_or_null( req->path );
- if( req->renamed_path == NULL && req->path != NULL ) {
-
- // done with this request
- vdev_reload_unlock( req->state );
- vdev_device_request_free( req );
- free( req );
- return -ENOMEM;
- }
- }
-
- vdev_debug("CHANGE device: type '%s' at '%s' ('%s' %d:%d)\n", (S_ISBLK(req->mode) ? "block" : S_ISCHR(req->mode) ? "char" : "unknown"), req->renamed_path, req->path, major(req->dev), minor(req->dev) );
-
- if( req->renamed_path != NULL && vdev_device_has_metadata( req ) ) {
-
+ req->renamed_path = vdev_strdup_or_null (req->path);
+ if (req->renamed_path == NULL && req->path != NULL)
+ {
+
+ // done with this request
+ vdev_reload_unlock (req->state);
+ vdev_device_request_free (req);
+ free (req);
+ return -ENOMEM;
+ }
+ }
+
+ vdev_debug ("CHANGE device: type '%s' at '%s' ('%s' %d:%d)\n",
+ (S_ISBLK (req->mode) ? "block" : S_ISCHR (req->mode) ? "char" :
+ "unknown"), req->renamed_path, req->path, major (req->dev),
+ minor (req->dev));
+
+ if (req->renamed_path != NULL && vdev_device_has_metadata (req))
+ {
+
// call all CHANGE actions
- rc = vdev_action_run_commands( req, req->state->acts, req->state->num_acts, 1 );
- if( rc != 0 ) {
-
- vdev_error("vdev_action_run_commands(ADD %s, dev=(%u, %u)) rc = %d\n", req->renamed_path, major(req->dev), minor(req->dev), rc );
- }
- }
-
- vdev_reload_unlock( req->state );
-
- // done with this request
- vdev_device_request_free( req );
- free( req );
-
- return 0;
-}
+ rc = vdev_action_run_commands (req, req->state->acts,
+ req->state->num_acts, 1);
+ if (rc != 0)
+ {
+ vdev_error
+ ("vdev_action_run_commands(ADD %s, dev=(%u, %u)) rc = %d\n",
+ req->renamed_path, major (req->dev), minor (req->dev), rc);
+ }
+ }
-// workqueue call to vdev_device_change
-static int vdev_device_change_wq( struct vdev_wreq* wreq, void* cls ) {
-
- struct vdev_device_request* req = (struct vdev_device_request*)cls;
- return vdev_device_change( req );
+ vdev_reload_unlock (req->state);
+
+ // done with this request
+ vdev_device_request_free (req);
+ free (req);
+
+ return 0;
}
+// workqueue call to vdev_device_change
+static int
+vdev_device_change_wq (struct vdev_wreq *wreq, void *cls)
+{
+
+ struct vdev_device_request *req = (struct vdev_device_request *) cls;
+ return vdev_device_change (req);
+}
// enqueue a device request
// NOTE: the workqueue takes ownership of the request. The caller should not free it.
// return 0 on success
// return -EINVAL if the device request is missing required fields
// return -ENOMEM on OOM
-int vdev_device_request_enqueue( struct vdev_wq* wq, struct vdev_device_request* req ) {
-
- int rc = 0;
- struct vdev_wreq wreq;
-
- memset( &wreq, 0, sizeof(struct vdev_wreq) );
-
- // sanity check
- rc = vdev_device_request_sanity_check( req );
- if( rc != 0 ) {
-
- vdev_error("Invalid device request (type %d)\n", req->type );
+int
+vdev_device_request_enqueue (struct vdev_wq *wq,
+ struct vdev_device_request *req)
+{
+
+ int rc = 0;
+ struct vdev_wreq wreq;
+
+ memset (&wreq, 0, sizeof (struct vdev_wreq));
+
+ // sanity check
+ rc = vdev_device_request_sanity_check (req);
+ if (rc != 0)
+ {
+
+ vdev_error ("Invalid device request (type %d)\n", req->type);
return -EINVAL;
- }
-
- // which handler?
- switch( req->type ) {
-
- case VDEV_DEVICE_ADD: {
-
- vdev_wreq_init( &wreq, vdev_device_add_wq, req );
- break;
+ }
+ // which handler?
+ switch (req->type)
+ {
+
+ case VDEV_DEVICE_ADD:
+ {
+
+ vdev_wreq_init (&wreq, vdev_device_add_wq, req);
+ break;
}
-
- case VDEV_DEVICE_REMOVE: {
-
- vdev_wreq_init( &wreq, vdev_device_remove_wq, req );
- break;
+
+ case VDEV_DEVICE_REMOVE:
+ {
+
+ vdev_wreq_init (&wreq, vdev_device_remove_wq, req);
+ break;
}
-
- case VDEV_DEVICE_CHANGE: {
-
- vdev_wreq_init( &wreq, vdev_device_change_wq, req );
- break;
+
+ case VDEV_DEVICE_CHANGE:
+ {
+
+ vdev_wreq_init (&wreq, vdev_device_change_wq, req);
+ break;
+ }
+
+ default:
+ {
+
+ vdev_error ("Invalid device request type %d\n", req->type);
+ return -EINVAL;
}
-
- default: {
-
- vdev_error("Invalid device request type %d\n", req->type );
- return -EINVAL;
- }
- }
-
- rc = vdev_wq_add( wq, &wreq );
- if( rc != 0 ) {
-
- vdev_error("vdev_wq_add('%s') rc = %d\n", req->path, rc );
- }
-
- return rc;
+ }
+
+ rc = vdev_wq_add (wq, &wreq);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_wq_add('%s') rc = %d\n", req->path, rc);
+ }
+
+ return rc;
}
diff --git a/vdevd/device.h b/vdevd/device.h
index d0a6680..12f7a72 100644
--- a/vdevd/device.h
+++ b/vdevd/device.h
@@ -35,79 +35,89 @@
#define VDEV_METADATA_PARAM_INSTANCE "vdev_instance"
// device request type
-typedef enum {
- VDEV_DEVICE_INVALID = 0, // invalid request
- VDEV_DEVICE_ADD,
- VDEV_DEVICE_REMOVE,
- VDEV_DEVICE_CHANGE,
- VDEV_DEVICE_ANY // only useful for actions
+typedef enum
+{
+ VDEV_DEVICE_INVALID = 0, // invalid request
+ VDEV_DEVICE_ADD,
+ VDEV_DEVICE_REMOVE,
+ VDEV_DEVICE_CHANGE,
+ VDEV_DEVICE_ANY // only useful for actions
} vdev_device_request_t;
struct vdev_state;
// device request
-struct vdev_device_request {
-
- // type of request (always initialized)
- vdev_device_request_t type;
-
- // path to the device node to create (if we're making one at all)
- // If we're creating a network interface, this is the interface name.
- char* path;
-
- // renamed path (used internally)
- char* renamed_path;
-
- // device numbers, for mknod
- dev_t dev;
-
- // device mode: character or block device
- mode_t mode;
-
- // OS-specific driver parameters
- vdev_params* params;
-
- // reference to vdev state, so we can call other methods when working
- struct vdev_state* state;
-
- // does this device file already exist? for example, did the preseed script create it? this applies to files like /dev/null, which *need* to exist.
- bool exists;
-
- // reference to the next item, since this structure often gets used for linked lists
- struct vdev_device_request* next;
-};
+struct vdev_device_request
+{
+ // type of request (always initialized)
+ vdev_device_request_t type;
-C_LINKAGE_BEGIN
+ // path to the device node to create (if we're making one at all)
+ // If we're creating a network interface, this is the interface name.
+ char *path;
+
+ // renamed path (used internally)
+ char *renamed_path;
+
+ // device numbers, for mknod
+ dev_t dev;
+
+ // device mode: character or block device
+ mode_t mode;
+
+ // OS-specific driver parameters
+ vdev_params *params;
+ // reference to vdev state, so we can call other methods when working
+ struct vdev_state *state;
+
+ // does this device file already exist? for example, did the preseed script create it? this applies to files like /dev/null, which *need* to exist.
+ bool exists;
+
+ // reference to the next item, since this structure often gets used for linked lists
+ struct vdev_device_request *next;
+};
+
+C_LINKAGE_BEGIN
// memory management
-int vdev_device_request_init( struct vdev_device_request* req, struct vdev_state* state, vdev_device_request_t type, char const* path );
-int vdev_device_request_free( struct vdev_device_request* req );
+int vdev_device_request_init (struct vdev_device_request *req,
+ struct vdev_state *state,
+ vdev_device_request_t type, char const *path);
+int vdev_device_request_free (struct vdev_device_request *req);
// setters for device requests (so the OS can build one up)
-int vdev_device_request_set_type( struct vdev_device_request* req, vdev_device_request_t req_type );
-int vdev_device_request_set_dev( struct vdev_device_request* req, dev_t dev );
-int vdev_device_request_set_mode( struct vdev_device_request* req, mode_t mode );
-int vdev_device_request_set_path( struct vdev_device_request* req, char const* path );
-int vdev_device_request_add_param( struct vdev_device_request* req, char const* key, char const* value );
-int vdev_device_request_set_exists( struct vdev_device_request* req, bool exists );
+int vdev_device_request_set_type (struct vdev_device_request *req,
+ vdev_device_request_t req_type);
+int vdev_device_request_set_dev (struct vdev_device_request *req, dev_t dev);
+int vdev_device_request_set_mode (struct vdev_device_request *req,
+ mode_t mode);
+int vdev_device_request_set_path (struct vdev_device_request *req,
+ char const *path);
+int vdev_device_request_add_param (struct vdev_device_request *req,
+ char const *key, char const *value);
+int vdev_device_request_set_exists (struct vdev_device_request *req,
+ bool exists);
// environment variables
-int vdev_device_request_to_env( struct vdev_device_request* req, vdev_params* helper_vars, char*** env, size_t* num_env, int is_daemonlet );
+int vdev_device_request_to_env (struct vdev_device_request *req,
+ vdev_params * helper_vars, char ***env,
+ size_t * num_env, int is_daemonlet);
// add a device request to the work queue
-int vdev_device_request_enqueue( struct vdev_wq* wq, struct vdev_device_request* req );
+int vdev_device_request_enqueue (struct vdev_wq *wq,
+ struct vdev_device_request *req);
// sanity check structure
-int vdev_device_request_sanity_check( struct vdev_device_request* req );
+int vdev_device_request_sanity_check (struct vdev_device_request *req);
// device metadata
-char* vdev_device_metadata_fullpath( char const* mountpoint, char const* device_path );
+char *vdev_device_metadata_fullpath (char const *mountpoint,
+ char const *device_path);
// add/remove devices
-int vdev_device_add( struct vdev_device_request* req );
-int vdev_device_remove( struct vdev_device_request* req );
+int vdev_device_add (struct vdev_device_request *req);
+int vdev_device_remove (struct vdev_device_request *req);
C_LINKAGE_END
-
-#endif
\ No newline at end of file
+#endif
diff --git a/vdevd/helpers/LINUX/common.c b/vdevd/helpers/LINUX/common.c
index f4fec2b..5491ad6 100644
--- a/vdevd/helpers/LINUX/common.c
+++ b/vdevd/helpers/LINUX/common.c
@@ -53,240 +53,288 @@
#include "common.h"
-int vdev_util_replace_whitespace(const char *str, char *to, size_t len) {
- size_t i, j;
-
- /* strip trailing whitespace */
- len = strnlen(str, len);
- while (len && isspace(str[len-1])) {
+int
+vdev_util_replace_whitespace (const char *str, char *to, size_t len)
+{
+ size_t i, j;
+
+ /* strip trailing whitespace */
+ len = strnlen (str, len);
+ while (len && isspace (str[len - 1]))
+ {
len--;
- }
-
- /* strip leading whitespace */
- i = 0;
- while (isspace(str[i]) && (i < len)) {
+ }
+
+ /* strip leading whitespace */
+ i = 0;
+ while (isspace (str[i]) && (i < len))
+ {
i++;
- }
+ }
- j = 0;
- while (i < len) {
+ j = 0;
+ while (i < len)
+ {
/* substitute multiple whitespace with a single '_' */
- if (isspace(str[i])) {
- while (isspace(str[i])) {
- i++;
- }
- to[j++] = '_';
- }
+ if (isspace (str[i]))
+ {
+ while (isspace (str[i]))
+ {
+ i++;
+ }
+ to[j++] = '_';
+ }
to[j++] = str[i++];
- }
- to[j] = '\0';
- return 0;
+ }
+ to[j] = '\0';
+ return 0;
}
-
-int vdev_whitelisted_char_for_devnode(char c, const char *white) {
- if ((c >= '0' && c <= '9') ||
+int
+vdev_whitelisted_char_for_devnode (char c, const char *white)
+{
+ if ((c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
- strchr("#+-.:=@_", c) != NULL ||
- (white != NULL && strchr(white, c) != NULL)) {
- return 1;
- }
- return 0;
+ strchr ("#+-.:=@_", c) != NULL ||
+ (white != NULL && strchr (white, c) != NULL))
+ {
+ return 1;
+ }
+ return 0;
}
+static inline bool
+vdev_is_unicode_valid (uint32_t ch)
+{
-static inline bool vdev_is_unicode_valid(uint32_t ch) {
-
- if (ch >= 0x110000) {
+ if (ch >= 0x110000)
+ {
/* End of unicode space */
return false;
- }
-
- if ((ch & 0xFFFFF800) == 0xD800) {
+ }
+
+ if ((ch & 0xFFFFF800) == 0xD800)
+ {
/* Reserved area for UTF-16 */
return false;
- }
- if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) {
+ }
+ if ((ch >= 0xFDD0) && (ch <= 0xFDEF))
+ {
/* Reserved */
return false;
- }
-
- if ((ch & 0xFFFE) == 0xFFFE) {
+ }
+
+ if ((ch & 0xFFFE) == 0xFFFE)
+ {
/* BOM (Byte Order Mark) */
return false;
- }
- return true;
+ }
+ return true;
}
/* count of characters used to encode one unicode char */
-static int vdev_utf8_encoded_expected_len(const char *str) {
- unsigned char c;
-
- c = (unsigned char) str[0];
- if (c < 0x80) {
+static int
+vdev_utf8_encoded_expected_len (const char *str)
+{
+ unsigned char c;
+
+ c = (unsigned char) str[0];
+ if (c < 0x80)
+ {
return 1;
- }
-
- if ((c & 0xe0) == 0xc0) {
+ }
+
+ if ((c & 0xe0) == 0xc0)
+ {
return 2;
- }
- if ((c & 0xf0) == 0xe0) {
+ }
+ if ((c & 0xf0) == 0xe0)
+ {
return 3;
- }
- if ((c & 0xf8) == 0xf0) {
+ }
+ if ((c & 0xf8) == 0xf0)
+ {
return 4;
- }
- if ((c & 0xfc) == 0xf8) {
+ }
+ if ((c & 0xfc) == 0xf8)
+ {
return 5;
- }
- if ((c & 0xfe) == 0xfc) {
+ }
+ if ((c & 0xfe) == 0xfc)
+ {
return 6;
- }
+ }
- return 0;
+ return 0;
}
/* decode one unicode char */
-int vdev_utf8_encoded_to_unichar(const char *str) {
- int unichar, len, i;
-
- len = vdev_utf8_encoded_expected_len(str);
-
- switch (len) {
- case 1:
- return (int)str[0];
- case 2:
+int
+vdev_utf8_encoded_to_unichar (const char *str)
+{
+ int unichar, len, i;
+
+ len = vdev_utf8_encoded_expected_len (str);
+
+ switch (len)
+ {
+ case 1:
+ return (int) str[0];
+ case 2:
unichar = str[0] & 0x1f;
break;
- case 3:
- unichar = (int)str[0] & 0x0f;
+ case 3:
+ unichar = (int) str[0] & 0x0f;
break;
- case 4:
- unichar = (int)str[0] & 0x07;
+ case 4:
+ unichar = (int) str[0] & 0x07;
break;
- case 5:
- unichar = (int)str[0] & 0x03;
+ case 5:
+ unichar = (int) str[0] & 0x03;
break;
- case 6:
- unichar = (int)str[0] & 0x01;
+ case 6:
+ unichar = (int) str[0] & 0x01;
break;
- default:
+ default:
return -EINVAL;
- }
+ }
- for (i = 1; i < len; i++) {
- if (((int)str[i] & 0xc0) != 0x80) {
- return -EINVAL;
- }
+ for (i = 1; i < len; i++)
+ {
+ if (((int) str[i] & 0xc0) != 0x80)
+ {
+ return -EINVAL;
+ }
unichar <<= 6;
- unichar |= (int)str[i] & 0x3f;
- }
+ unichar |= (int) str[i] & 0x3f;
+ }
- return unichar;
+ return unichar;
}
/* expected size used to encode one unicode char */
-static int vdev_utf8_unichar_to_encoded_len(int unichar) {
+static int
+vdev_utf8_unichar_to_encoded_len (int unichar)
+{
- if (unichar < 0x80) {
+ if (unichar < 0x80)
+ {
return 1;
- }
- if (unichar < 0x800) {
+ }
+ if (unichar < 0x800)
+ {
return 2;
- }
- if (unichar < 0x10000) {
+ }
+ if (unichar < 0x10000)
+ {
return 3;
- }
- if (unichar < 0x200000) {
+ }
+ if (unichar < 0x200000)
+ {
return 4;
- }
- if (unichar < 0x4000000) {
+ }
+ if (unichar < 0x4000000)
+ {
return 5;
- }
+ }
- return 6;
+ return 6;
}
/* validate one encoded unicode char and return its length */
-int vdev_utf8_encoded_valid_unichar(const char *str) {
- int len, unichar, i;
-
- len = vdev_utf8_encoded_expected_len(str);
- if (len == 0) {
+int
+vdev_utf8_encoded_valid_unichar (const char *str)
+{
+ int len, unichar, i;
+
+ len = vdev_utf8_encoded_expected_len (str);
+ if (len == 0)
+ {
return -EINVAL;
- }
+ }
- /* ascii is valid */
- if (len == 1) {
+ /* ascii is valid */
+ if (len == 1)
+ {
return 1;
- }
+ }
- /* check if expected encoded chars are available */
- for (i = 0; i < len; i++) {
- if ((str[i] & 0x80) != 0x80) {
- return -EINVAL;
- }
- }
+ /* check if expected encoded chars are available */
+ for (i = 0; i < len; i++)
+ {
+ if ((str[i] & 0x80) != 0x80)
+ {
+ return -EINVAL;
+ }
+ }
- unichar = vdev_utf8_encoded_to_unichar(str);
+ unichar = vdev_utf8_encoded_to_unichar (str);
- /* check if encoded length matches encoded value */
- if (vdev_utf8_unichar_to_encoded_len(unichar) != len) {
+ /* check if encoded length matches encoded value */
+ if (vdev_utf8_unichar_to_encoded_len (unichar) != len)
+ {
return -EINVAL;
- }
+ }
- /* check if value has valid range */
- if (!vdev_is_unicode_valid(unichar)) {
+ /* check if value has valid range */
+ if (!vdev_is_unicode_valid (unichar))
+ {
return -EINVAL;
- }
+ }
- return len;
+ return len;
}
/* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */
-int vdev_util_replace_chars(char *str, const char *white) {
- size_t i = 0;
- int replaced = 0;
-
- while (str[i] != '\0') {
+int
+vdev_util_replace_chars (char *str, const char *white)
+{
+ size_t i = 0;
+ int replaced = 0;
+
+ while (str[i] != '\0')
+ {
int len;
- if (vdev_whitelisted_char_for_devnode(str[i], white)) {
- i++;
- continue;
- }
+ if (vdev_whitelisted_char_for_devnode (str[i], white))
+ {
+ i++;
+ continue;
+ }
/* accept hex encoding */
- if (str[i] == '\\' && str[i+1] == 'x') {
- i += 2;
- continue;
- }
+ if (str[i] == '\\' && str[i + 1] == 'x')
+ {
+ i += 2;
+ continue;
+ }
/* accept valid utf8 */
- len = vdev_utf8_encoded_valid_unichar(&str[i]);
- if (len > 1) {
- i += len;
- continue;
- }
+ len = vdev_utf8_encoded_valid_unichar (&str[i]);
+ if (len > 1)
+ {
+ i += len;
+ continue;
+ }
/* if space is allowed, replace whitespace with ordinary space */
- if (isspace(str[i]) && white != NULL && strchr(white, ' ') != NULL) {
- str[i] = ' ';
- i++;
- replaced++;
- continue;
- }
+ if (isspace (str[i]) && white != NULL && strchr (white, ' ') != NULL)
+ {
+ str[i] = ' ';
+ i++;
+ replaced++;
+ continue;
+ }
/* everything else is replaced with '_' */
str[i] = '_';
i++;
replaced++;
- }
- return replaced;
+ }
+ return replaced;
}
-
/**
* vdev_util_encode_string:
* @str: input string to be encoded
@@ -299,738 +347,855 @@ int vdev_util_replace_chars(char *str, const char *white) {
*
* Returns: 0 if the entire string was copied, non-zero otherwise.
**/
-int vdev_util_encode_string(const char *str, char *str_enc, size_t len) {
-
- size_t i, j;
+int
+vdev_util_encode_string (const char *str, char *str_enc, size_t len)
+{
- if (str == NULL || str_enc == NULL) {
+ size_t i, j;
+
+ if (str == NULL || str_enc == NULL)
+ {
return -EINVAL;
- }
+ }
- for (i = 0, j = 0; str[i] != '\0'; i++) {
+ for (i = 0, j = 0; str[i] != '\0'; i++)
+ {
int seqlen;
- seqlen = vdev_utf8_encoded_valid_unichar(&str[i]);
- if (seqlen > 1) {
-
- if (len-j < (size_t)seqlen) {
- goto err;
- }
- memcpy(&str_enc[j], &str[i], seqlen);
- j += seqlen;
- i += (seqlen-1);
- }
- else if (str[i] == '\\' || !vdev_whitelisted_char_for_devnode(str[i], NULL)) {
-
- if (len-j < 4) {
- goto err;
- }
- sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]);
- j += 4;
- }
- else {
-
- if (len-j < 1) {
- goto err;
- }
-
- str_enc[j] = str[i];
- j++;
- }
- }
- if (len-j < 1) {
+ seqlen = vdev_utf8_encoded_valid_unichar (&str[i]);
+ if (seqlen > 1)
+ {
+
+ if (len - j < (size_t) seqlen)
+ {
+ goto err;
+ }
+ memcpy (&str_enc[j], &str[i], seqlen);
+ j += seqlen;
+ i += (seqlen - 1);
+ }
+ else if (str[i] == '\\'
+ || !vdev_whitelisted_char_for_devnode (str[i], NULL))
+ {
+
+ if (len - j < 4)
+ {
+ goto err;
+ }
+ sprintf (&str_enc[j], "\\x%02x", (unsigned char) str[i]);
+ j += 4;
+ }
+ else
+ {
+
+ if (len - j < 1)
+ {
+ goto err;
+ }
+
+ str_enc[j] = str[i];
+ j++;
+ }
+ }
+ if (len - j < 1)
+ {
goto err;
- }
-
- str_enc[j] = '\0';
- return 0;
+ }
+
+ str_enc[j] = '\0';
+ return 0;
err:
- return -EINVAL;
+ return -EINVAL;
}
// remove trailing whitespace
-int vdev_util_rstrip( char* str ) {
-
- size_t i = strlen(str);
-
- if( i == 0 ) {
+int
+vdev_util_rstrip (char *str)
+{
+
+ size_t i = strlen (str);
+
+ if (i == 0)
+ {
return 0;
- }
-
- i--;
-
- while( i >= 0 ) {
-
- if( isspace(str[i]) ) {
- str[i] = 0;
- i--;
- continue;
- }
- else {
- // not space
- break;
- }
- }
-
- return 0;
+ }
+
+ i--;
+
+ while (i >= 0)
+ {
+
+ if (isspace (str[i]))
+ {
+ str[i] = 0;
+ i--;
+ continue;
+ }
+ else
+ {
+ // not space
+ break;
+ }
+ }
+
+ return 0;
}
// global list of properties discovered
-static struct vdev_property* vdev_property_head = NULL;
-static struct vdev_property* vdev_property_tail = NULL;
+static struct vdev_property *vdev_property_head = NULL;
+static struct vdev_property *vdev_property_tail = NULL;
// append to a linked list of properties discovered
// return 0 on success
// return -ENOMEM if we run out of memory
-int vdev_property_add( char const* name, char const* value ) {
-
- struct vdev_property* prop = (struct vdev_property*)calloc( sizeof(struct vdev_property), 1 );
-
- if( prop == NULL ) {
+int
+vdev_property_add (char const *name, char const *value)
+{
+
+ struct vdev_property *prop =
+ (struct vdev_property *) calloc (sizeof (struct vdev_property), 1);
+
+ if (prop == NULL)
+ {
return -ENOMEM;
- }
-
- prop->name = strdup( name );
- if( prop->name == NULL ) {
-
- free( prop );
+ }
+
+ prop->name = strdup (name);
+ if (prop->name == NULL)
+ {
+
+ free (prop);
return -ENOMEM;
- }
-
- prop->value = strdup( value );
- if( prop->value == NULL ) {
-
- free( prop->name );
- free( prop );
+ }
+
+ prop->value = strdup (value);
+ if (prop->value == NULL)
+ {
+
+ free (prop->name);
+ free (prop);
return -ENOMEM;
- }
-
- prop->next = NULL;
-
- if( vdev_property_head == NULL ) {
+ }
+
+ prop->next = NULL;
+
+ if (vdev_property_head == NULL)
+ {
vdev_property_head = prop;
vdev_property_tail = prop;
- }
-
- else {
+ }
+
+ else
+ {
vdev_property_tail->next = prop;
vdev_property_tail = prop;
- }
-
- return 0;
+ }
+
+ return 0;
}
// print all properties as sourceable environmet variables
// always succeeds
-int vdev_property_print( void ) {
-
- if( vdev_property_head != NULL ) {
-
- for( struct vdev_property* itr = vdev_property_head; itr != NULL; itr = itr->next ) {
- printf("%s='%s'\n", itr->name, itr->value );
- }
-
+int
+vdev_property_print (void)
+{
+
+ if (vdev_property_head != NULL)
+ {
+
+ for (struct vdev_property * itr = vdev_property_head;
+ itr != NULL; itr = itr->next)
+ {
+ printf ("%s='%s'\n", itr->name, itr->value);
+ }
+
// print the variable VDEV_PROPERTIES to include all property names
- printf("VDEV_PROPERTIES=\"");
- for( struct vdev_property* itr = vdev_property_head; itr != NULL; itr = itr->next ) {
- printf("%s ", itr->name );
- }
- printf("\"\n");
- }
-
- return 0;
-}
+ printf ("VDEV_PROPERTIES=\"");
+ for (struct vdev_property * itr = vdev_property_head;
+ itr != NULL; itr = itr->next)
+ {
+ printf ("%s ", itr->name);
+ }
+ printf ("\"\n");
+ }
+ return 0;
+}
// free all properties
// always succeeds
-int vdev_property_free_all( void ) {
-
- if( vdev_property_head != NULL ) {
-
- for( struct vdev_property* itr = vdev_property_head; itr != NULL; ) {
-
- struct vdev_property* itr_next = itr->next;
-
- free( itr->name );
- free( itr->value );
- free( itr );
-
- itr = itr_next;
- }
- }
-
- vdev_property_head = NULL;
- vdev_property_tail = NULL;
-
- return 0;
-}
+int
+vdev_property_free_all (void)
+{
+
+ if (vdev_property_head != NULL)
+ {
+
+ for (struct vdev_property * itr = vdev_property_head; itr != NULL;)
+ {
+ struct vdev_property *itr_next = itr->next;
+
+ free (itr->name);
+ free (itr->value);
+ free (itr);
+
+ itr = itr_next;
+ }
+ }
+
+ vdev_property_head = NULL;
+ vdev_property_tail = NULL;
+
+ return 0;
+}
// read a file, masking EINTR
// return the number of bytes read on success
// return -errno on failure
-ssize_t vdev_read_uninterrupted( int fd, char* buf, size_t len ) {
-
- ssize_t num_read = 0;
-
- if( buf == NULL ) {
+ssize_t
+vdev_read_uninterrupted (int fd, char *buf, size_t len)
+{
+
+ ssize_t num_read = 0;
+
+ if (buf == NULL)
+ {
return -EINVAL;
- }
-
- while( (unsigned)num_read < len ) {
- ssize_t nr = read( fd, buf + num_read, len - num_read );
- if( nr < 0 ) {
-
- int errsv = -errno;
- if( errsv == -EINTR ) {
- continue;
- }
-
- return errsv;
- }
- if( nr == 0 ) {
- break;
- }
-
+ }
+
+ while ((unsigned) num_read < len)
+ {
+ ssize_t nr = read (fd, buf + num_read, len - num_read);
+ if (nr < 0)
+ {
+
+ int errsv = -errno;
+ if (errsv == -EINTR)
+ {
+ continue;
+ }
+
+ return errsv;
+ }
+ if (nr == 0)
+ {
+ break;
+ }
+
num_read += nr;
- }
-
- return num_read;
+ }
+
+ return num_read;
}
+// read a sysfs attribute
+int
+vdev_sysfs_read_attr (char const *sysfs_device_path, char const *attr_name,
+ char **value, size_t * value_len)
+{
+
+ int rc = 0;
+ int fd = 0;
+ struct stat sb;
+ char attr_path[4097];
+ sprintf (attr_path, "%s/%s", sysfs_device_path, attr_name);
+
+ rc = stat (attr_path, &sb);
+ if (rc != 0)
+ {
-// read a sysfs attribute
-int vdev_sysfs_read_attr( char const* sysfs_device_path, char const* attr_name, char** value, size_t* value_len ) {
-
- int rc = 0;
- int fd = 0;
- struct stat sb;
- char attr_path[4097];
-
- sprintf(attr_path, "%s/%s", sysfs_device_path, attr_name );
-
- rc = stat( attr_path, &sb );
- if( rc != 0 ) {
-
rc = -errno;
return rc;
- }
-
- // regular file? return the contents
- if( S_ISREG( sb.st_mode ) ) {
-
- fd = open( attr_path, O_RDONLY );
- if( fd < 0 ) {
-
- rc = -errno;
-
- fprintf(stderr, "[WARN]: open('%s') errno = %d\n", attr_path, rc );
- return rc;
- }
-
- char* ret_value = (char*)calloc( sb.st_size + 1, 1 );
- if( ret_value == NULL ) {
-
- close( fd );
- return -ENOMEM;
- }
-
- rc = vdev_read_uninterrupted( fd, ret_value, sb.st_size );
- if( rc < 0 ) {
-
- free( ret_value );
- close( fd );
- return rc;
- }
-
- close( fd );
-
+ }
+ // regular file? return the contents
+ if (S_ISREG (sb.st_mode))
+ {
+
+ fd = open (attr_path, O_RDONLY);
+ if (fd < 0)
+ {
+
+ rc = -errno;
+
+ fprintf (stderr, "[WARN]: open('%s') errno = %d\n", attr_path, rc);
+ return rc;
+ }
+
+ char *ret_value = (char *) calloc (sb.st_size + 1, 1);
+ if (ret_value == NULL)
+ {
+
+ close (fd);
+ return -ENOMEM;
+ }
+
+ rc = vdev_read_uninterrupted (fd, ret_value, sb.st_size);
+ if (rc < 0)
+ {
+
+ free (ret_value);
+ close (fd);
+ return rc;
+ }
+
+ close (fd);
+
*value = ret_value;
*value_len = sb.st_size;
-
+
return 0;
- }
-
- // symlink? return the actual link
- else if( S_ISLNK( sb.st_mode ) ) {
-
- char* ret_value = (char*)calloc( sb.st_size + 1, 1 );
- if( ret_value == NULL ) {
-
- return -ENOMEM;
- }
-
- rc = readlink( attr_path, ret_value, sb.st_size );
- if( rc < 0 ) {
-
- rc = -errno;
- fprintf(stderr, "[WARN]: readlink('%s') errno = %d\n", attr_path, rc );
-
- free( ret_value );
- return rc;
- }
-
+ }
+ // symlink? return the actual link
+ else if (S_ISLNK (sb.st_mode))
+ {
+
+ char *ret_value = (char *) calloc (sb.st_size + 1, 1);
+ if (ret_value == NULL)
+ {
+
+ return -ENOMEM;
+ }
+
+ rc = readlink (attr_path, ret_value, sb.st_size);
+ if (rc < 0)
+ {
+
+ rc = -errno;
+ fprintf (stderr, "[WARN]: readlink('%s') errno = %d\n",
+ attr_path, rc);
+
+ free (ret_value);
+ return rc;
+ }
+
*value = ret_value;
*value_len = sb.st_size + 1;
-
+
return 0;
- }
-
- // not sure what to do here
- else {
-
+ }
+ // not sure what to do here
+ else
+ {
+
return -EINVAL;
- }
+ }
}
-
// find a field value from a uevent
// return 0 on success
// return -ENOENT if the key is not found
// return -ENOMEM if oom.
-int vdev_sysfs_uevent_get_key( char const* uevent_buf, size_t uevent_buflen, char const* key, char** value, size_t* value_len ) {
-
- char* tmp = NULL;
- char* tok = NULL;
- char* buf_ptr = NULL;
- char* delim = NULL;
- int rc = 0;
-
- // NOTE: zero-terminate
- char* buf_dup = (char*)calloc( uevent_buflen + 1, 1 );
- if( buf_dup == NULL ) {
+int
+vdev_sysfs_uevent_get_key (char const *uevent_buf, size_t uevent_buflen,
+ char const *key, char **value, size_t * value_len)
+{
+
+ char *tmp = NULL;
+ char *tok = NULL;
+ char *buf_ptr = NULL;
+ char *delim = NULL;
+ int rc = 0;
+
+ // NOTE: zero-terminate
+ char *buf_dup = (char *) calloc (uevent_buflen + 1, 1);
+ if (buf_dup == NULL)
+ {
return -ENOMEM;
- }
-
- memcpy( buf_dup, uevent_buf, uevent_buflen );
- buf_ptr = buf_dup;
-
- while( 1 ) {
-
+ }
+
+ memcpy (buf_dup, uevent_buf, uevent_buflen);
+ buf_ptr = buf_dup;
+
+ while (1)
+ {
+
// next line
- tok = strtok_r( buf_ptr, "\n", &tmp );
+ tok = strtok_r (buf_ptr, "\n", &tmp);
buf_ptr = NULL;
-
- if( tok == NULL ) {
- rc = -ENOENT;
- break;
- }
-
+
+ if (tok == NULL)
+ {
+ rc = -ENOENT;
+ break;
+ }
// read key
- delim = index( tok, '=' );
- if( delim == NULL ) {
- continue;
- }
-
+ delim = index (tok, '=');
+ if (delim == NULL)
+ {
+ continue;
+ }
+
*delim = '\0';
-
+
// match key?
- if( strcmp( tok, key ) == 0 ) {
-
- // get value
- *value_len = strlen( delim + 1 );
- *value = (char*)calloc( *value_len + 1, 1 );
-
- if( *value == NULL ) {
- rc = -ENOMEM;
- break;
- }
-
- strcpy( *value, delim + 1 );
- break;
- }
-
+ if (strcmp (tok, key) == 0)
+ {
+
+ // get value
+ *value_len = strlen (delim + 1);
+ *value = (char *) calloc (*value_len + 1, 1);
+
+ if (*value == NULL)
+ {
+ rc = -ENOMEM;
+ break;
+ }
+
+ strcpy (*value, delim + 1);
+ break;
+ }
+
*delim = '=';
- }
-
- free( buf_dup );
- return rc;
+ }
+
+ free (buf_dup);
+ return rc;
}
// read a whole file into RAM
// return 0 on success, and set *file_buf and *file_buf_len
// return negative on error
-int vdev_read_file( char const* path, char** file_buf, size_t* file_buf_len ) {
-
- int fd = 0;
- struct stat sb;
- char* buf = NULL;
- int rc = 0;
-
- // get size
- rc = stat( path, &sb );
- if( rc != 0 ) {
-
+int
+vdev_read_file (char const *path, char **file_buf, size_t * file_buf_len)
+{
+
+ int fd = 0;
+ struct stat sb;
+ char *buf = NULL;
+ int rc = 0;
+
+ // get size
+ rc = stat (path, &sb);
+ if (rc != 0)
+ {
+
rc = -errno;
return rc;
- }
-
- // read the uevent file itself
- buf = (char*)calloc( sb.st_size, 1 );
- if( buf == NULL ) {
-
+ }
+ // read the uevent file itself
+ buf = (char *) calloc (sb.st_size, 1);
+ if (buf == NULL)
+ {
+
return -ENOMEM;
- }
-
- fd = open( path, O_RDONLY );
- if( fd < 0 ) {
-
+ }
+
+ fd = open (path, O_RDONLY);
+ if (fd < 0)
+ {
+
rc = -errno;
- free( buf );
+ free (buf);
return rc;
- }
-
- rc = vdev_read_uninterrupted( fd, buf, sb.st_size );
- if( rc < 0 ) {
-
- close( fd );
- free( buf );
+ }
+
+ rc = vdev_read_uninterrupted (fd, buf, sb.st_size);
+ if (rc < 0)
+ {
+
+ close (fd);
+ free (buf);
return rc;
- }
-
- close( fd );
-
- *file_buf = buf;
- *file_buf_len = rc;
-
- return 0;
-}
+ }
+
+ close (fd);
+ *file_buf = buf;
+ *file_buf_len = rc;
+
+ return 0;
+}
// find a field in the uevent buffer, using vdev_read_file and vdev_sysfs_uevent_get_key
// return 0 on success, and set *value and *value_len
// return negative on error
-int vdev_sysfs_uevent_read_key( char const* sysfs_device_path, char const* uevent_key, char** uevent_value, size_t* uevent_value_len ) {
-
- int rc = 0;
-
- char* uevent_buf = NULL;
- size_t uevent_len = 0;
-
- char* uevent_path = (char*)calloc( strlen(sysfs_device_path) + strlen("/uevent") + 1, 1 );
- if( uevent_path == NULL ) {
-
+int
+vdev_sysfs_uevent_read_key (char const *sysfs_device_path,
+ char const *uevent_key, char **uevent_value,
+ size_t * uevent_value_len)
+{
+
+ int rc = 0;
+
+ char *uevent_buf = NULL;
+ size_t uevent_len = 0;
+
+ char *uevent_path =
+ (char *) calloc (strlen (sysfs_device_path) + strlen ("/uevent") + 1,
+ 1);
+ if (uevent_path == NULL)
+ {
+
return -ENOMEM;
- }
-
- sprintf( uevent_path, "%s/uevent", sysfs_device_path );
-
- // get uevent
- rc = vdev_read_file( uevent_path, &uevent_buf, &uevent_len );
- if( rc < 0 ) {
-
- if( DEBUG ) {
- fprintf(stderr, "[WARN]: vdev_read_file('%s') rc = %d\n", uevent_path, rc );
- }
+ }
+
+ sprintf (uevent_path, "%s/uevent", sysfs_device_path);
+
+ // get uevent
+ rc = vdev_read_file (uevent_path, &uevent_buf, &uevent_len);
+ if (rc < 0)
+ {
+
+ if (DEBUG)
+ {
+ fprintf (stderr,
+ "[WARN]: vdev_read_file('%s') rc = %d\n", uevent_path, rc);
+ }
return rc;
- }
-
- // get devtype
- rc = vdev_sysfs_uevent_get_key( uevent_buf, uevent_len, uevent_key, uevent_value, uevent_value_len );
-
- free( uevent_buf );
- free( uevent_path );
-
- return rc;
-}
+ }
+ // get devtype
+ rc = vdev_sysfs_uevent_get_key (uevent_buf, uevent_len, uevent_key,
+ uevent_value, uevent_value_len);
+ free (uevent_buf);
+ free (uevent_path);
+
+ return rc;
+}
// walk up a sysfs device path to find the ancestor device with the given subsystem and devtype
// if devtype_name is NULL, match any devtype (only match the subsystem)
// return 0 on success
// return -ENOMEM on OOM
// return -ENOENT if a subsystem or uevent was not found, when one was expected
-int vdev_sysfs_get_parent_with_subsystem_devtype( char const* sysfs_device_path, char const* subsystem_name, char const* devtype_name, char** devpath, size_t* devpath_len ) {
-
- char cur_dir[4097];
- char subsystem_path[4097];
- char subsystem_link[4097];
- char uevent_path[4097];
-
- memset( subsystem_path, 0, 4097 );
- memset( subsystem_link, 0, 4097 );
-
- char* tmp = NULL;
- int rc = 0;
- char* uevent_buf = NULL;
- size_t uevent_len = 0;
- char* devtype = NULL;
- size_t devtype_len = 0;
- char* parent_device = NULL;
- size_t parent_device_len = 0;
-
- strcpy( cur_dir, sysfs_device_path );
-
- while( 1 ) {
-
+int
+vdev_sysfs_get_parent_with_subsystem_devtype (char const *sysfs_device_path,
+ char const *subsystem_name,
+ char const *devtype_name,
+ char **devpath,
+ size_t * devpath_len)
+{
+
+ char cur_dir[4097];
+ char subsystem_path[4097];
+ char subsystem_link[4097];
+ char uevent_path[4097];
+
+ memset (subsystem_path, 0, 4097);
+ memset (subsystem_link, 0, 4097);
+
+ char *tmp = NULL;
+ int rc = 0;
+ char *uevent_buf = NULL;
+ size_t uevent_len = 0;
+ char *devtype = NULL;
+ size_t devtype_len = 0;
+ char *parent_device = NULL;
+ size_t parent_device_len = 0;
+
+ strcpy (cur_dir, sysfs_device_path);
+
+ while (1)
+ {
+
// get parent device
- rc = vdev_sysfs_get_parent_device( cur_dir, &parent_device, &parent_device_len );
- if( rc != 0 ) {
- break;
- }
-
+ rc = vdev_sysfs_get_parent_device (cur_dir, &parent_device,
+ &parent_device_len);
+ if (rc != 0)
+ {
+ break;
+ }
// subsystem?
- sprintf( subsystem_path, "%s/subsystem", parent_device );
-
- memset( subsystem_link, 0, 4096 );
-
- rc = readlink( subsystem_path, subsystem_link, 4096 );
- if( rc < 0 ) {
-
- rc = -errno;
- if( rc != -ENOENT ) {
- fprintf(stderr, "[WARN]: readlink('%s') errno = %d\n", subsystem_path, rc );
- }
-
- free( parent_device );
- parent_device = NULL;
- return rc;
- }
-
+ sprintf (subsystem_path, "%s/subsystem", parent_device);
+
+ memset (subsystem_link, 0, 4096);
+
+ rc = readlink (subsystem_path, subsystem_link, 4096);
+ if (rc < 0)
+ {
+
+ rc = -errno;
+ if (rc != -ENOENT)
+ {
+ fprintf (stderr,
+ "[WARN]: readlink('%s') errno = %d\n",
+ subsystem_path, rc);
+ }
+
+ free (parent_device);
+ parent_device = NULL;
+ return rc;
+ }
// get subsystem name...
- tmp = rindex( subsystem_link, '/' );
-
- if( tmp != NULL && strcmp( tmp + 1, subsystem_name ) != 0 ) {
-
- // subsystem does not match
- // crawl up to the parent
- strcpy( cur_dir, parent_device );
-
- free( parent_device );
- parent_device = NULL;
- continue;
- }
-
+ tmp = rindex (subsystem_link, '/');
+
+ if (tmp != NULL && strcmp (tmp + 1, subsystem_name) != 0)
+ {
+
+ // subsystem does not match
+ // crawl up to the parent
+ strcpy (cur_dir, parent_device);
+
+ free (parent_device);
+ parent_device = NULL;
+ continue;
+ }
// subsystem matches...
*tmp = 0;
-
- if( devtype_name != NULL ) {
-
- // get uevent
- // get DEVTYPE from uevent
- // make uevent path
- sprintf( uevent_path, "%s/uevent", parent_device );
-
- // get uevent
- rc = vdev_read_file( uevent_path, &uevent_buf, &uevent_len );
- if( rc < 0 ) {
-
- fprintf(stderr, "[WARN]: vdev_read_file('%s') rc = %d\n", uevent_path, rc );
-
- free( parent_device );
- parent_device = NULL;
- return rc;
- }
-
- // get devtype
- rc = vdev_sysfs_uevent_get_key( uevent_buf, uevent_len, "DEVTYPE", &devtype, &devtype_len );
- free( uevent_buf );
-
- if( rc != 0 ) {
-
- if( rc == -ENOENT ) {
-
- // not found
- // next parent
- strcpy( cur_dir, parent_device );
-
- free( parent_device );
- parent_device = NULL;
-
- continue;
- }
- else {
-
- free( parent_device );
- parent_device = NULL;
-
- return rc;
- }
- }
-
- // matches?
- if( strcmp( devtype, devtype_name ) == 0 ) {
-
- free( devtype );
-
- // this is the path to the device
- *devpath = parent_device;
- *devpath_len = strlen( parent_device );
-
- // found!
- rc = 0;
- break;
- }
- else {
- // no match.
- // next device
- free( devtype );
-
- strcpy( cur_dir, parent_device );
-
- free( parent_device );
- parent_device = NULL;
- continue;
- }
- }
- else {
-
- // match only on subsystem
- *devpath = parent_device;
- *devpath_len = strlen(parent_device);
-
- rc = 0;
- break;
- }
- }
-
- return rc;
-}
+ if (devtype_name != NULL)
+ {
+
+ // get uevent
+ // get DEVTYPE from uevent
+ // make uevent path
+ sprintf (uevent_path, "%s/uevent", parent_device);
+
+ // get uevent
+ rc = vdev_read_file (uevent_path, &uevent_buf, &uevent_len);
+ if (rc < 0)
+ {
+
+ fprintf (stderr,
+ "[WARN]: vdev_read_file('%s') rc = %d\n",
+ uevent_path, rc);
+
+ free (parent_device);
+ parent_device = NULL;
+ return rc;
+ }
+ // get devtype
+ rc = vdev_sysfs_uevent_get_key (uevent_buf, uevent_len,
+ "DEVTYPE", &devtype, &devtype_len);
+ free (uevent_buf);
+
+ if (rc != 0)
+ {
+
+ if (rc == -ENOENT)
+ {
+
+ // not found
+ // next parent
+ strcpy (cur_dir, parent_device);
+
+ free (parent_device);
+ parent_device = NULL;
+
+ continue;
+ }
+ else
+ {
+
+ free (parent_device);
+ parent_device = NULL;
+
+ return rc;
+ }
+ }
+ // matches?
+ if (strcmp (devtype, devtype_name) == 0)
+ {
+
+ free (devtype);
+
+ // this is the path to the device
+ *devpath = parent_device;
+ *devpath_len = strlen (parent_device);
+
+ // found!
+ rc = 0;
+ break;
+ }
+ else
+ {
+ // no match.
+ // next device
+ free (devtype);
+
+ strcpy (cur_dir, parent_device);
+
+ free (parent_device);
+ parent_device = NULL;
+ continue;
+ }
+ }
+ else
+ {
+
+ // match only on subsystem
+ *devpath = parent_device;
+ *devpath_len = strlen (parent_device);
+
+ rc = 0;
+ break;
+ }
+ }
+
+ return rc;
+}
// make a device path using the symlink in the contained 'device' entry
-int vdev_sysfs_read_device_path( char const* sysfs_dir, char** devpath, size_t* devpath_len ) {
-
- int rc = 0;
- struct stat sb;
-
- char path_buf[8193];
-
- sprintf( path_buf, "%s/device", sysfs_dir );
-
- // is there a link here?
- rc = stat( path_buf, &sb );
- if( rc != 0 ) {
-
+int
+vdev_sysfs_read_device_path (char const *sysfs_dir, char **devpath,
+ size_t * devpath_len)
+{
+
+ int rc = 0;
+ struct stat sb;
+
+ char path_buf[8193];
+
+ sprintf (path_buf, "%s/device", sysfs_dir);
+
+ // is there a link here?
+ rc = stat (path_buf, &sb);
+ if (rc != 0)
+ {
+
rc = -errno;
return rc;
- }
-
- // must be a link
- if( !S_ISLNK( sb.st_mode ) ) {
-
+ }
+ // must be a link
+ if (!S_ISLNK (sb.st_mode))
+ {
+
rc = -EINVAL;
return rc;
- }
-
- // follow that link!
- *devpath = realpath( path_buf, NULL );
- if( *devpath == NULL ) {
+ }
+ // follow that link!
+ *devpath = realpath (path_buf, NULL);
+ if (*devpath == NULL)
+ {
return -ENOMEM;
- }
-
- *devpath_len = strlen(*devpath);
-
- return 0;
-}
+ }
+
+ *devpath_len = strlen (*devpath);
+ return 0;
+}
// search sysfs for the device path corresponding to a given subsystem and sysname.
// fill in devpath if found.
// heavily inspired by udev_device_new_from_subsystem_sysname
-int vdev_sysfs_device_path_from_subsystem_sysname( char const* sysfs_mount, char const* subsystem, char const* sysname, char** devpath, size_t* devpath_len ) {
-
- int rc = 0;
- struct stat sb;
- char path_buf[8193];
-
- memset( path_buf, 0, 8193 );
-
- if( strcmp( subsystem, "subsystem" ) == 0 ) {
-
- sprintf( path_buf, "%s/subsystem/%s/", sysfs_mount, sysname );
- rc = stat( path_buf, &sb );
-
- if( rc == 0 ) {
- return vdev_sysfs_read_device_path( path_buf, devpath, devpath_len );
- }
-
- sprintf(path_buf, "%s/bus/%s/", sysfs_mount, sysname );
- rc = stat( path_buf, &sb );
-
- if( rc == 0 ) {
- return vdev_sysfs_read_device_path( path_buf, devpath, devpath_len );
- }
-
- sprintf(path_buf, "%s/class/%s/", sysfs_mount, sysname );
- rc = stat( path_buf, &sb );
-
- if( rc == 0 ) {
- return vdev_sysfs_read_device_path( path_buf, devpath, devpath_len );
- }
- }
-
- if( strcmp( subsystem, "module" ) == 0 ) {
-
- sprintf( path_buf, "%s/module/%s/", sysfs_mount, sysname );
- rc = stat( path_buf, &sb );
-
- if( rc == 0 ) {
- return vdev_sysfs_read_device_path( path_buf, devpath, devpath_len );
- }
- }
-
- if( strcmp( subsystem, "drivers" ) == 0 ) {
-
+int
+vdev_sysfs_device_path_from_subsystem_sysname (char const *sysfs_mount,
+ char const *subsystem,
+ char const *sysname,
+ char **devpath,
+ size_t * devpath_len)
+{
+
+ int rc = 0;
+ struct stat sb;
+ char path_buf[8193];
+
+ memset (path_buf, 0, 8193);
+
+ if (strcmp (subsystem, "subsystem") == 0)
+ {
+
+ sprintf (path_buf, "%s/subsystem/%s/", sysfs_mount, sysname);
+ rc = stat (path_buf, &sb);
+
+ if (rc == 0)
+ {
+ return vdev_sysfs_read_device_path (path_buf, devpath, devpath_len);
+ }
+
+ sprintf (path_buf, "%s/bus/%s/", sysfs_mount, sysname);
+ rc = stat (path_buf, &sb);
+
+ if (rc == 0)
+ {
+ return vdev_sysfs_read_device_path (path_buf, devpath, devpath_len);
+ }
+
+ sprintf (path_buf, "%s/class/%s/", sysfs_mount, sysname);
+ rc = stat (path_buf, &sb);
+
+ if (rc == 0)
+ {
+ return vdev_sysfs_read_device_path (path_buf, devpath, devpath_len);
+ }
+ }
+
+ if (strcmp (subsystem, "module") == 0)
+ {
+
+ sprintf (path_buf, "%s/module/%s/", sysfs_mount, sysname);
+ rc = stat (path_buf, &sb);
+
+ if (rc == 0)
+ {
+ return vdev_sysfs_read_device_path (path_buf, devpath, devpath_len);
+ }
+ }
+
+ if (strcmp (subsystem, "drivers") == 0)
+ {
+
char driver_prefix[4096];
- char* driver = NULL;
-
- sprintf( driver_prefix, sysname );
- driver = strchr( driver_prefix, ':' );
-
- if( driver != NULL ) {
-
- // trim header
- *driver = '\0';
- driver++;
-
- sprintf( path_buf, "%s/subsystem/%s/drivers/%s/", sysfs_mount, driver_prefix, driver );
- rc = stat( path_buf, &sb );
-
- if( rc == 0 ) {
- return vdev_sysfs_read_device_path( path_buf, devpath, devpath_len );
- }
-
- sprintf( path_buf, "%s/bus/%s/drivers/%s/", sysfs_mount, driver_prefix, driver );
- rc = stat( path_buf, &sb );
-
- if( rc == 0 ) {
- return vdev_sysfs_read_device_path( path_buf, devpath, devpath_len );
- }
- }
- else {
-
- return -EINVAL;
- }
- }
-
- sprintf( path_buf, "%s/subsystem/%s/devices/%s/", sysfs_mount, subsystem, sysname );
- rc = stat( path_buf, &sb );
-
- if( rc == 0 ) {
- return vdev_sysfs_read_device_path( path_buf, devpath, devpath_len );
- }
-
- sprintf( path_buf, "%s/bus/%s/devices/%s/", sysfs_mount, subsystem, sysname );
- rc = stat( path_buf, &sb );
-
- if( rc == 0 ) {
- return vdev_sysfs_read_device_path( path_buf, devpath, devpath_len );
- }
-
- sprintf( path_buf, "%s/class/%s/%s", sysfs_mount, subsystem, sysname );
- rc = stat( path_buf, &sb );
-
- if( rc == 0 ) {
-
- return vdev_sysfs_read_device_path( path_buf, devpath, devpath_len );
- }
-
- return -ENOENT;
-}
+ char *driver = NULL;
+
+ sprintf (driver_prefix, sysname);
+ driver = strchr (driver_prefix, ':');
+
+ if (driver != NULL)
+ {
+
+ // trim header
+ *driver = '\0';
+ driver++;
+
+ sprintf (path_buf, "%s/subsystem/%s/drivers/%s/",
+ sysfs_mount, driver_prefix, driver);
+ rc = stat (path_buf, &sb);
+
+ if (rc == 0)
+ {
+ return vdev_sysfs_read_device_path (path_buf,
+ devpath, devpath_len);
+ }
+
+ sprintf (path_buf, "%s/bus/%s/drivers/%s/", sysfs_mount,
+ driver_prefix, driver);
+ rc = stat (path_buf, &sb);
+
+ if (rc == 0)
+ {
+ return vdev_sysfs_read_device_path (path_buf,
+ devpath, devpath_len);
+ }
+ }
+ else
+ {
+
+ return -EINVAL;
+ }
+ }
+
+ sprintf (path_buf, "%s/subsystem/%s/devices/%s/", sysfs_mount, subsystem,
+ sysname);
+ rc = stat (path_buf, &sb);
+
+ if (rc == 0)
+ {
+ return vdev_sysfs_read_device_path (path_buf, devpath, devpath_len);
+ }
+
+ sprintf (path_buf, "%s/bus/%s/devices/%s/", sysfs_mount, subsystem,
+ sysname);
+ rc = stat (path_buf, &sb);
+ if (rc == 0)
+ {
+ return vdev_sysfs_read_device_path (path_buf, devpath, devpath_len);
+ }
+
+ sprintf (path_buf, "%s/class/%s/%s", sysfs_mount, subsystem, sysname);
+ rc = stat (path_buf, &sb);
+
+ if (rc == 0)
+ {
+
+ return vdev_sysfs_read_device_path (path_buf, devpath, devpath_len);
+ }
+
+ return -ENOENT;
+}
// get the parent device of a given device, using sysfs.
// not all devices have parents; those that do will have a uevent file.
@@ -1040,237 +1205,271 @@ int vdev_sysfs_device_path_from_subsystem_sysname( char const* sysfs_mount, char
// return -ENOENT if this dev has no parent
// return -errno if stat'ing the parent path fails
// return -ENOMEM if OOM
-int vdev_sysfs_get_parent_device( char const* dev_path, char** ret_parent_device, size_t* ret_parent_device_len ) {
-
- char* parent_path = NULL;
- size_t parent_path_len = 0;
- struct stat sb;
- int rc = 0;
-
- char* delim = NULL;
-
- parent_path = (char*)calloc( strlen(dev_path) + 1 + strlen("/uevent"), 1 );
- if( parent_path == NULL ) {
+int
+vdev_sysfs_get_parent_device (char const *dev_path, char **ret_parent_device,
+ size_t * ret_parent_device_len)
+{
+
+ char *parent_path = NULL;
+ size_t parent_path_len = 0;
+ struct stat sb;
+ int rc = 0;
+
+ char *delim = NULL;
+
+ parent_path =
+ (char *) calloc (strlen (dev_path) + 1 + strlen ("/uevent"), 1);
+ if (parent_path == NULL)
+ {
return -ENOMEM;
- }
-
- strcpy( parent_path, dev_path );
-
- while( strlen(parent_path) > 0 ) {
-
+ }
+
+ strcpy (parent_path, dev_path);
+
+ while (strlen (parent_path) > 0)
+ {
+
// lop off the child
- delim = rindex( parent_path, '/' );
- if( delim == NULL ) {
-
- // invalid
- free( parent_path );
- return -EINVAL;
- }
-
- if( delim == parent_path ) {
-
- // reached /
- free( parent_path );
- return -ENOENT;
- }
-
- while( *delim == '/' && delim != parent_path ) {
- *delim = '\0';
- delim--;
- }
-
- parent_path_len = strlen( parent_path );
-
+ delim = rindex (parent_path, '/');
+ if (delim == NULL)
+ {
+
+ // invalid
+ free (parent_path);
+ return -EINVAL;
+ }
+
+ if (delim == parent_path)
+ {
+
+ // reached /
+ free (parent_path);
+ return -ENOENT;
+ }
+
+ while (*delim == '/' && delim != parent_path)
+ {
+ *delim = '\0';
+ delim--;
+ }
+
+ parent_path_len = strlen (parent_path);
+
// verify that this is a device...
- strcat( parent_path, "/uevent" );
-
- rc = stat( parent_path, &sb );
- if( rc != 0 ) {
-
- // not a device
- // remove /uevent
- parent_path[ parent_path_len ] = '\0';
- continue;
- }
- else {
-
- // device!
- break;
- }
- }
-
- // lop off /uevent
- parent_path[ parent_path_len ] = '\0';
-
- *ret_parent_device = parent_path;
- *ret_parent_device_len = parent_path_len;
-
- return 0;
+ strcat (parent_path, "/uevent");
+
+ rc = stat (parent_path, &sb);
+ if (rc != 0)
+ {
+
+ // not a device
+ // remove /uevent
+ parent_path[parent_path_len] = '\0';
+ continue;
+ }
+ else
+ {
+
+ // device!
+ break;
+ }
+ }
+
+ // lop off /uevent
+ parent_path[parent_path_len] = '\0';
+
+ *ret_parent_device = parent_path;
+ *ret_parent_device_len = parent_path_len;
+
+ return 0;
}
// get the subsystem from a device path
-int vdev_sysfs_read_subsystem( char const* devpath, char** ret_subsystem, size_t* ret_subsystem_len ) {
-
- int rc = 0;
- char linkpath[ 4097 ];
- size_t linkpath_len = 4097;
- char* subsystem_path = NULL;
- char* subsystem = NULL;
-
- subsystem_path = (char*)calloc( strlen(devpath) + 1 + strlen("/subsystem") + 1, 1 );
- if( subsystem_path == NULL ) {
+int
+vdev_sysfs_read_subsystem (char const *devpath, char **ret_subsystem,
+ size_t * ret_subsystem_len)
+{
+
+ int rc = 0;
+ char linkpath[4097];
+ size_t linkpath_len = 4097;
+ char *subsystem_path = NULL;
+ char *subsystem = NULL;
+
+ subsystem_path =
+ (char *) calloc (strlen (devpath) + 1 + strlen ("/subsystem") + 1, 1);
+ if (subsystem_path == NULL)
+ {
return -ENOMEM;
- }
-
- sprintf( subsystem_path, "%s/subsystem", devpath );
-
- memset( linkpath, 0, 4097 );
-
- rc = readlink( subsystem_path, linkpath, linkpath_len );
- if( rc < 0 ) {
-
+ }
+
+ sprintf (subsystem_path, "%s/subsystem", devpath);
+
+ memset (linkpath, 0, 4097);
+
+ rc = readlink (subsystem_path, linkpath, linkpath_len);
+ if (rc < 0)
+ {
+
rc = -errno;
- log_error("readlink('%s') rc = %d\n", subsystem_path, rc );
- free( subsystem_path );
+ log_error ("readlink('%s') rc = %d\n", subsystem_path, rc);
+ free (subsystem_path);
return rc;
- }
-
- free( subsystem_path );
-
- subsystem = rindex( linkpath, '/' );
- if( subsystem == NULL ) {
+ }
+
+ free (subsystem_path);
+
+ subsystem = rindex (linkpath, '/');
+ if (subsystem == NULL)
+ {
return -EINVAL;
- }
-
- *ret_subsystem = strdup( subsystem + 1 );
- *ret_subsystem_len = strlen( subsystem + 1 );
-
- if( *ret_subsystem == NULL ) {
+ }
+
+ *ret_subsystem = strdup (subsystem + 1);
+ *ret_subsystem_len = strlen (subsystem + 1);
+
+ if (*ret_subsystem == NULL)
+ {
return -ENOMEM;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// get the sysname from the device path
-int vdev_sysfs_get_sysname( char const* devpath, char** ret_sysname, size_t* ret_sysname_len ) {
-
- char const* delim = NULL;
- char* sysname = NULL;
- size_t len = 0;
-
- delim = rindex( devpath, '/' );
- if( delim == NULL ) {
-
+int
+vdev_sysfs_get_sysname (char const *devpath, char **ret_sysname,
+ size_t * ret_sysname_len)
+{
+
+ char const *delim = NULL;
+ char *sysname = NULL;
+ size_t len = 0;
+
+ delim = rindex (devpath, '/');
+ if (delim == NULL)
+ {
+
return -EINVAL;
- }
-
- sysname = strdup( delim + 1 );
-
- if( sysname == NULL ) {
+ }
+
+ sysname = strdup (delim + 1);
+
+ if (sysname == NULL)
+ {
return -ENOMEM;
- }
-
- /* some devices have '!' in their name, change that to '/' */
- while( sysname[len] != '\0' ) {
-
- if( sysname[len] == '!' ) {
- sysname[len] = '/';
- }
-
- len++;
- }
-
- *ret_sysname = sysname;
- *ret_sysname_len = len;
-
- return 0;
-}
+ }
+
+ /* some devices have '!' in their name, change that to '/' */
+ while (sysname[len] != '\0')
+ {
+
+ if (sysname[len] == '!')
+ {
+ sysname[len] = '/';
+ }
+ len++;
+ }
+
+ *ret_sysname = sysname;
+ *ret_sysname_len = len;
+
+ return 0;
+}
// get the sysnum of a device from the device path
-int vdev_sysfs_get_sysnum( char const* devpath, int* sysnum ) {
-
- int rc = 0;
- char* sysname = NULL;
- size_t sysname_len = 0;
- int i = 0;
-
- // last digits at the end of the sysname
- rc = vdev_sysfs_get_sysname( devpath, &sysname, &sysname_len );
- if( rc != 0 ) {
+int
+vdev_sysfs_get_sysnum (char const *devpath, int *sysnum)
+{
+
+ int rc = 0;
+ char *sysname = NULL;
+ size_t sysname_len = 0;
+ int i = 0;
+
+ // last digits at the end of the sysname
+ rc = vdev_sysfs_get_sysname (devpath, &sysname, &sysname_len);
+ if (rc != 0)
+ {
return rc;
- }
-
- while( isdigit( sysname[ sysname_len - i ] ) ) {
+ }
+
+ while (isdigit (sysname[sysname_len - i]))
+ {
i++;
- }
- i++;
-
- *sysnum = strtol( sysname + sysname_len - i, NULL, 10 );
-
- free( sysname );
-
- return 0;
-}
+ }
+ i++;
+ *sysnum = strtol (sysname + sysname_len - i, NULL, 10);
+
+ free (sysname);
+
+ return 0;
+}
// get the absolute sysfs device path from a major/minor pair and device type
// return 0 on success, and set *syspath and *syspath_len
// return negative on error
-int vdev_sysfs_get_syspath_from_device( char const* sysfs_mountpoint, mode_t mode, unsigned int major, unsigned int minor, char** syspath, size_t* syspath_len ) {
-
- char* devpath = (char*)calloc( strlen(sysfs_mountpoint) + 4097, 1 );
- char linkbuf[4097];
-
- if( devpath == NULL ) {
+int
+vdev_sysfs_get_syspath_from_device (char const *sysfs_mountpoint,
+ mode_t mode, unsigned int major,
+ unsigned int minor, char **syspath,
+ size_t * syspath_len)
+{
+
+ char *devpath = (char *) calloc (strlen (sysfs_mountpoint) + 4097, 1);
+ char linkbuf[4097];
+
+ if (devpath == NULL)
+ {
return -ENOMEM;
- }
-
- int rc = 0;
-
- memset( linkbuf, 0, 4097 );
-
- if( S_ISCHR( mode ) ) {
-
+ }
+
+ int rc = 0;
+
+ memset (linkbuf, 0, 4097);
+
+ if (S_ISCHR (mode))
+ {
+
// character device
- sprintf(devpath, "%s/dev/char/%u:%u", sysfs_mountpoint, major, minor );
- }
- else if( S_ISBLK( mode ) ) {
-
+ sprintf (devpath, "%s/dev/char/%u:%u", sysfs_mountpoint, major, minor);
+ }
+ else if (S_ISBLK (mode))
+ {
+
// block device
- sprintf(devpath, "%s/dev/block/%u:%u", sysfs_mountpoint, major, minor );
- }
- else {
-
- free( devpath );
+ sprintf (devpath, "%s/dev/block/%u:%u", sysfs_mountpoint, major, minor);
+ }
+ else
+ {
+
+ free (devpath);
return -EINVAL;
- }
-
- rc = readlink( devpath, linkbuf, 4097 );
- if( rc < 0 ) {
-
+ }
+
+ rc = readlink (devpath, linkbuf, 4097);
+ if (rc < 0)
+ {
+
rc = -errno;
- free( devpath );
+ free (devpath);
return rc;
- }
-
- // link should start with "../devices"
- if( strncmp( linkbuf, "../../devices", strlen("../../devices") ) != 0 ) {
-
+ }
+ // link should start with "../devices"
+ if (strncmp (linkbuf, "../../devices", strlen ("../../devices")) != 0)
+ {
+
// sysfs structure changed???
- free( devpath );
+ free (devpath);
return -EIO;
- }
-
- sprintf( devpath, "%s/%s", sysfs_mountpoint, linkbuf + strlen("../../") );
-
- *syspath = devpath;
- *syspath_len = strlen(devpath);
-
- return 0;
-}
+ }
+ sprintf (devpath, "%s/%s", sysfs_mountpoint, linkbuf + strlen ("../../"));
+ *syspath = devpath;
+ *syspath_len = strlen (devpath);
+ return 0;
+}
diff --git a/vdevd/helpers/LINUX/common.h b/vdevd/helpers/LINUX/common.h
index f1c2f8a..bcc0763 100644
--- a/vdevd/helpers/LINUX/common.h
+++ b/vdevd/helpers/LINUX/common.h
@@ -19,7 +19,6 @@
.
*/
-
#ifndef _VDEV_LINUX_HELPERS_COMMON_H_
#define _VDEV_LINUX_HELPERS_COMMON_H_
@@ -66,7 +65,7 @@
// hold-overs from udev
-#ifndef memzero
+#ifndef memzero
#define memzero(b, z) memset( b, 0, z )
#endif
@@ -74,7 +73,7 @@
#define streq(a, b) (strcmp(a, b) == 0)
#endif
-#ifndef strneq
+#ifndef strneq
#define strneq(a, b, len) (strncmp(a, b, len) == 0)
#endif
@@ -86,50 +85,72 @@
#define strscpy(dest, destsize, src) strncpy(dest, src, destsize)
#endif
-#ifndef initialize_srand
+#ifndef initialize_srand
#define initialize_srand() do { struct timespec ts; clock_gettime( CLOCK_MONOTONIC, &ts ); srand( ts.tv_sec + ts.tv_nsec ); } while(0)
#endif
+// expanding list of properties
+struct vdev_property
+{
+ char *name;
+ char *value;
-// expanding list of properties
-struct vdev_property {
-
- char* name;
- char* value;
-
- struct vdev_property* next;
+ struct vdev_property *next;
};
// string methods (hold-overs from udev)
-int vdev_util_replace_whitespace(const char *str, char *to, size_t len);
-int vdev_whitelisted_char_for_devnode(char c, const char *white);
-int vdev_utf8_encoded_to_unichar(const char *str);
-int vdev_utf8_encoded_valid_unichar(const char *str);
-int vdev_util_replace_chars(char *str, const char *white);
-int vdev_util_encode_string(const char *str, char *str_enc, size_t len);
-int vdev_util_rstrip( char* str );
+int vdev_util_replace_whitespace (const char *str, char *to, size_t len);
+int vdev_whitelisted_char_for_devnode (char c, const char *white);
+int vdev_utf8_encoded_to_unichar (const char *str);
+int vdev_utf8_encoded_valid_unichar (const char *str);
+int vdev_util_replace_chars (char *str, const char *white);
+int vdev_util_encode_string (const char *str, char *str_enc, size_t len);
+int vdev_util_rstrip (char *str);
// device properties
-int vdev_property_add( char const* name, char const* value );
-int vdev_property_print( void );
-int vdev_property_free_all( void );
+int vdev_property_add (char const *name, char const *value);
+int vdev_property_print (void);
+int vdev_property_free_all (void);
// sysfs methods
-int vdev_sysfs_read_attr( char const* sysfs_device_path, char const* attr_name, char** value, size_t* value_len );
-int vdev_sysfs_uevent_read_key( char const* sysfs_device_path, char const* uevent_key, char** uevent_value, size_t* uevent_value_len );
-int vdev_sysfs_uevent_get_key( char const* uevent_buf, size_t uevent_buflen, char const* key, char** value, size_t* value_len );
-int vdev_sysfs_get_parent_with_subsystem_devtype( char const* sysfs_device_path, char const* subsystem_name, char const* devtype_name, char** devpath, size_t* devpath_len );
-int vdev_sysfs_read_device_path( char const* sysfs_dir, char** devpath, size_t* devpath_len );
-int vdev_sysfs_device_path_from_subsystem_sysname( char const* sysfs_mount, char const* subsystem, char const* sysname, char** devpath, size_t* devpath_len );
-int vdev_sysfs_get_parent_device( char const* dev_path, char** ret_parent_device, size_t* ret_parent_device_len );
-int vdev_sysfs_read_subsystem( char const* devpath, char** ret_subsystem, size_t* ret_subsystem_len );
-int vdev_sysfs_get_sysname( char const* devpath, char** sysname, size_t* sysname_len );
-int vdev_sysfs_get_sysnum( char const* devpath, int* sysnum );
-int vdev_sysfs_get_syspath_from_device( char const* sysfs_mountpoint, mode_t mode, unsigned int major, unsigned int minor, char** syspath, size_t* syspath_len );
+int vdev_sysfs_read_attr (char const *sysfs_device_path,
+ char const *attr_name, char **value,
+ size_t * value_len);
+int vdev_sysfs_uevent_read_key (char const *sysfs_device_path,
+ char const *uevent_key, char **uevent_value,
+ size_t * uevent_value_len);
+int vdev_sysfs_uevent_get_key (char const *uevent_buf, size_t uevent_buflen,
+ char const *key, char **value,
+ size_t * value_len);
+int vdev_sysfs_get_parent_with_subsystem_devtype (char const
+ *sysfs_device_path,
+ char const *subsystem_name,
+ char const *devtype_name,
+ char **devpath,
+ size_t * devpath_len);
+int vdev_sysfs_read_device_path (char const *sysfs_dir, char **devpath,
+ size_t * devpath_len);
+int vdev_sysfs_device_path_from_subsystem_sysname (char const *sysfs_mount,
+ char const *subsystem,
+ char const *sysname,
+ char **devpath,
+ size_t * devpath_len);
+int vdev_sysfs_get_parent_device (char const *dev_path,
+ char **ret_parent_device,
+ size_t * ret_parent_device_len);
+int vdev_sysfs_read_subsystem (char const *devpath, char **ret_subsystem,
+ size_t * ret_subsystem_len);
+int vdev_sysfs_get_sysname (char const *devpath, char **sysname,
+ size_t * sysname_len);
+int vdev_sysfs_get_sysnum (char const *devpath, int *sysnum);
+int vdev_sysfs_get_syspath_from_device (char const *sysfs_mountpoint,
+ mode_t mode, unsigned int major,
+ unsigned int minor, char **syspath,
+ size_t * syspath_len);
// file operations
-ssize_t vdev_read_uninterrupted( int fd, char* buf, size_t len );
-int vdev_read_file( char const* path, char** file_buf, size_t* file_buf_len );
+ssize_t vdev_read_uninterrupted (int fd, char *buf, size_t len);
+int vdev_read_file (char const *path, char **file_buf, size_t * file_buf_len);
#endif
diff --git a/vdevd/helpers/LINUX/echo_n.c b/vdevd/helpers/LINUX/echo_n.c
index d1263a9..f8deca9 100644
--- a/vdevd/helpers/LINUX/echo_n.c
+++ b/vdevd/helpers/LINUX/echo_n.c
@@ -1,13 +1,17 @@
#include
// echo -n implementation, where -n means "no newline"
-int main( int argc, char** argv ) {
- if( argc == 1 ) {
+int
+main (int argc, char **argv)
+{
+ if (argc == 1)
+ {
return 0;
- }
- for( int i = 1; i < argc-1; i++ ) {
- printf("%s ", argv[i]);
- }
- printf("%s", argv[argc-1]);
- return 0;
+ }
+ for (int i = 1; i < argc - 1; i++)
+ {
+ printf ("%s ", argv[i]);
+ }
+ printf ("%s", argv[argc - 1]);
+ return 0;
}
diff --git a/vdevd/helpers/LINUX/event-put.c b/vdevd/helpers/LINUX/event-put.c
index 7f77c57..0253bca 100644
--- a/vdevd/helpers/LINUX/event-put.c
+++ b/vdevd/helpers/LINUX/event-put.c
@@ -30,462 +30,532 @@
#define DEFAULT_DEV_EVENTS "/dev/events/global"
// path to device events directory (overrideable in command-line)
-static char g_dev_events[PATH_MAX+1];
+static char g_dev_events[PATH_MAX + 1];
// make a path to an event in the global queue
// event_path must have at least PATH_MAX+1 bytes
-int make_event_path( uint64_t seqnum, char* event_path ) {
-
- memset( event_path, 0, PATH_MAX+1 );
-
- return snprintf( event_path, PATH_MAX, "%s/%" PRIu64, g_dev_events, seqnum );
+int
+make_event_path (uint64_t seqnum, char *event_path)
+{
+
+ memset (event_path, 0, PATH_MAX + 1);
+
+ return snprintf (event_path, PATH_MAX, "%s/%" PRIu64, g_dev_events, seqnum);
}
// open the event file, exclusively, for writing.
// make sure that only the UID/GID of this process (i.e. root) can access it.
-int open_event( char* event_path ) {
-
- int fd = 0;
-
- fd = open( event_path, O_WRONLY | O_EXCL | O_CREAT, 0600 );
- if( fd < 0 ) {
-
+int
+open_event (char *event_path)
+{
+
+ int fd = 0;
+
+ fd = open (event_path, O_WRONLY | O_EXCL | O_CREAT, 0600);
+ if (fd < 0)
+ {
+
fd = -errno;
- log_error("open('%s') rc = %d\n", event_path, fd );
+ log_error ("open('%s') rc = %d\n", event_path, fd);
return fd;
- }
-
- return fd;
-}
+ }
+ return fd;
+}
// clear an event
// return 0 on success
// return -errno (from unlink(2)) on failure
-int clear_event( char* event_path ) {
-
- int rc = unlink( event_path );
- if( rc < 0 ) {
-
+int
+clear_event (char *event_path)
+{
+
+ int rc = unlink (event_path);
+ if (rc < 0)
+ {
+
rc = -errno;
- log_error("unlink('%s') rc = %d\n", event_path, rc );
- }
-
- return rc;
-}
+ log_error ("unlink('%s') rc = %d\n", event_path, rc);
+ }
+ return rc;
+}
// link all events to all directories that are siblings to the parent directory of the event path.
// try to do so even if we fail to link in some cases
// return 0 on success
// return -errno if at least one failed
-int multicast_event( uint64_t seqnum, char* event_path ) {
-
- int rc = 0;
- DIR* dirh = NULL;
- struct dirent entry;
- struct dirent* result = NULL;
- char pathbuf[ PATH_MAX+1 ];
-
- char event_queues_dir[ PATH_MAX+1 ];
- char global_queue_name[ NAME_MAX+1 ];
-
- memset( event_queues_dir, 0, PATH_MAX+1 );
- memset( global_queue_name, 0, NAME_MAX+1 );
-
- // parent nmae of event_path...
- ssize_t i = strlen(event_path) - 1;
- if( i < 0 ) {
+int
+multicast_event (uint64_t seqnum, char *event_path)
+{
+
+ int rc = 0;
+ DIR *dirh = NULL;
+ struct dirent entry;
+ struct dirent *result = NULL;
+ char pathbuf[PATH_MAX + 1];
+
+ char event_queues_dir[PATH_MAX + 1];
+ char global_queue_name[NAME_MAX + 1];
+
+ memset (event_queues_dir, 0, PATH_MAX + 1);
+ memset (global_queue_name, 0, NAME_MAX + 1);
+
+ // parent nmae of event_path...
+ ssize_t i = strlen (event_path) - 1;
+ if (i < 0)
+ {
return -EINVAL;
- }
-
- // shouldn't end in '/', but you never know...
- while( i > 0 && event_path[i] == '/' ) {
+ }
+ // shouldn't end in '/', but you never know...
+ while (i > 0 && event_path[i] == '/')
+ {
i--;
- }
-
- // skip event name
- while( i > 0 && event_path[i] != '/' ) {
+ }
+
+ // skip event name
+ while (i > 0 && event_path[i] != '/')
+ {
i--;
- }
-
- // skip '/' at the end of the parent name
- while( i > 0 && event_path[i] == '/' ) {
+ }
+
+ // skip '/' at the end of the parent name
+ while (i > 0 && event_path[i] == '/')
+ {
i--;
- }
-
- if( i == 0 ) {
-
+ }
+
+ if (i == 0)
+ {
+
// event_path's parent is /
- strcpy( global_queue_name, "." );
- strcpy( event_queues_dir, "/" );
- }
- else {
-
+ strcpy (global_queue_name, ".");
+ strcpy (event_queues_dir, "/");
+ }
+ else
+ {
+
ssize_t parent_end = i;
-
- while( i > 0 && event_path[i] != '/' ) {
- i--;
- }
-
- strncpy( global_queue_name, &event_path[i+1], parent_end - i );
- strncpy( event_queues_dir, event_path, i+1 );
- }
-
- dirh = opendir( event_queues_dir );
- if( dirh == NULL ) {
-
+
+ while (i > 0 && event_path[i] != '/')
+ {
+ i--;
+ }
+
+ strncpy (global_queue_name, &event_path[i + 1], parent_end - i);
+ strncpy (event_queues_dir, event_path, i + 1);
+ }
+
+ dirh = opendir (event_queues_dir);
+ if (dirh == NULL)
+ {
+
// OOM
rc = -errno;
return rc;
- }
-
- do {
-
+ }
+
+ do
+ {
+
// next entry
- rc = readdir_r( dirh, &entry, &result );
- if( rc != 0 ) {
-
- // I/O error
- log_error("readdir_r('%s') rc = %d", event_queues_dir, rc );
- break;
- }
-
+ rc = readdir_r (dirh, &entry, &result);
+ if (rc != 0)
+ {
+
+ // I/O error
+ log_error ("readdir_r('%s') rc = %d", event_queues_dir, rc);
+ break;
+ }
// skip . and ..
- if( strcmp( entry.d_name, "." ) == 0 || strcmp( entry.d_name, ".." ) == 0 ) {
- continue;
- }
-
+ if (strcmp (entry.d_name, ".") == 0 || strcmp (entry.d_name, "..") == 0)
+ {
+ continue;
+ }
// skip non-directories
- if( entry.d_type != DT_DIR ) {
- continue;
- }
-
+ if (entry.d_type != DT_DIR)
+ {
+ continue;
+ }
// skip global queue
- if( strcmp( global_queue_name, entry.d_name ) == 0 ) {
- continue;
- }
-
+ if (strcmp (global_queue_name, entry.d_name) == 0)
+ {
+ continue;
+ }
// link to this directory
- snprintf( pathbuf, PATH_MAX, "%s/%s/%" PRIu64, event_queues_dir, entry.d_name, seqnum );
-
- rc = link( event_path, pathbuf );
- if( rc != 0 ) {
-
- rc = errno;
- log_error("link('%s', '%s'): %s", event_path, pathbuf, strerror( -rc ) );
- rc = 0;
- }
-
- } while( result != NULL );
-
- closedir( dirh );
-
- return rc;
-}
+ snprintf (pathbuf, PATH_MAX, "%s/%s/%" PRIu64, event_queues_dir,
+ entry.d_name, seqnum);
+ rc = link (event_path, pathbuf);
+ if (rc != 0)
+ {
-// print usage statement
-int usage( char const* progname ) {
-
- int i = 0;
- char const* usage_text[] = {
- "Usage: ", progname, " [-v] [-n SEQNUM] [-s SOURCE-QUEUE] [-t TARGET-QUEUES]\n",
- "Options:\n",
- " -n SEQNUM\n",
- " Event sequence number. Must be\n",
- " unique across all pending events.\n",
- "\n",
- " -s SOURCE-QUEUE\n",
- " Path to the source event queue. An\n",
- " event will be added as a child of this\n",
- " directory, and linked into all directories\n",
- " in TARGET-QUEUES. The default is\n",
- " " DEFAULT_DEV_EVENTS, "\n",
- "\n",
- NULL
- };
-
- for( i = 0; usage_text[i] != NULL; i++ ) {
- fprintf(stderr, usage_text[i] );
- }
-
- return 0;
+ rc = errno;
+ log_error ("link('%s', '%s'): %s", event_path, pathbuf,
+ strerror (-rc));
+ rc = 0;
+ }
+
+ }
+ while (result != NULL);
+
+ closedir (dirh);
+
+ return rc;
}
+// print usage statement
+int
+usage (char const *progname)
+{
+
+ int i = 0;
+ char const *usage_text[] = {
+ "Usage: ", progname,
+ " [-v] [-n SEQNUM] [-s SOURCE-QUEUE] [-t TARGET-QUEUES]\n",
+ "Options:\n",
+ " -n SEQNUM\n",
+ " Event sequence number. Must be\n",
+ " unique across all pending events.\n",
+ "\n",
+ " -s SOURCE-QUEUE\n",
+ " Path to the source event queue. An\n",
+ " event will be added as a child of this\n",
+ " directory, and linked into all directories\n",
+ " in TARGET-QUEUES. The default is\n",
+ " " DEFAULT_DEV_EVENTS, "\n",
+ "\n",
+ NULL
+ };
+
+ for (i = 0; usage_text[i] != NULL; i++)
+ {
+ fprintf (stderr, usage_text[i]);
+ }
+
+ return 0;
+}
// print a verbose help statement
-int help( char const* progname ) {
-
- usage( progname );
-
- int i = 0;
- char const* help_text[] = {
- "This program reads a device event from standard input, such that\n",
- "each line takes the form of KEY=VALUE. Valid keys and values are:\n",
- "\n",
- " DEVPATH=(/devices path) [REQUIRED]\n",
- " SUBSYSTEM=(subsystem name) [REQUIRED]\n",
- " SEQNUM=(kernel uevent sequence number) [REQUIRED if -n is not given]\n",
- " DEVNAME=(/dev node path)\n",
- " DEVLINKS=(space-separated list of symlinks)\n",
- " TAGS=(colon-separated list of tags)\n",
- " USEC_INITIALIZED=(microseconds since device initialization)\n",
- " DRIVER=(name of device driver)\n",
- " ACTION=(add, remove, change, move, etc.)\n",
- " MAJOR=(major device number)\n",
- " MINOR=(minor device number)\n",
- " DEVPATH_OLD=(old device path (on move)\n",
- " IFINDEX=(device interface index, e.g. for USB and network interfaces)\n",
- " DEVMODE=(device node permission bits)\n",
- " DEVUID=(device node UID)\n",
- " DEVGID=(device node GID)\n",
- "\n",
- "Keys marked with [REQUIRED] must be present.\n",
- "NOTE: events are limited to 8192 bytes.\n",
- NULL
- };
-
- for( i = 0; help_text[i] != NULL; i++ ) {
- fprintf(stderr, help_text[i] );
- }
-
- return 0;
+int
+help (char const *progname)
+{
+
+ usage (progname);
+
+ int i = 0;
+ char const *help_text[] = {
+ "This program reads a device event from standard input, such that\n",
+ "each line takes the form of KEY=VALUE. Valid keys and values are:\n",
+ "\n",
+ " DEVPATH=(/devices path) [REQUIRED]\n",
+ " SUBSYSTEM=(subsystem name) [REQUIRED]\n",
+ " SEQNUM=(kernel uevent sequence number) [REQUIRED if -n is not given]\n",
+ " DEVNAME=(/dev node path)\n",
+ " DEVLINKS=(space-separated list of symlinks)\n",
+ " TAGS=(colon-separated list of tags)\n",
+ " USEC_INITIALIZED=(microseconds since device initialization)\n",
+ " DRIVER=(name of device driver)\n",
+ " ACTION=(add, remove, change, move, etc.)\n",
+ " MAJOR=(major device number)\n",
+ " MINOR=(minor device number)\n",
+ " DEVPATH_OLD=(old device path (on move)\n",
+ " IFINDEX=(device interface index, e.g. for USB and network interfaces)\n",
+ " DEVMODE=(device node permission bits)\n",
+ " DEVUID=(device node UID)\n",
+ " DEVGID=(device node GID)\n",
+ "\n",
+ "Keys marked with [REQUIRED] must be present.\n",
+ "NOTE: events are limited to 8192 bytes.\n",
+ NULL
+ };
+
+ for (i = 0; help_text[i] != NULL; i++)
+ {
+ fprintf (stderr, help_text[i]);
+ }
+
+ return 0;
}
// read, but mask EINTR
// return number of bytes read on success
// return -errno on I/O error
// NOTE: must be async-safe!
-ssize_t read_uninterrupted( int fd, char* buf, size_t len ) {
-
- ssize_t num_read = 0;
-
- if( buf == NULL ) {
+ssize_t
+read_uninterrupted (int fd, char *buf, size_t len)
+{
+
+ ssize_t num_read = 0;
+
+ if (buf == NULL)
+ {
return -EINVAL;
- }
-
- while( (unsigned)num_read < len ) {
- ssize_t nr = read( fd, buf + num_read, len - num_read );
- if( nr < 0 ) {
-
- int errsv = -errno;
- if( errsv == -EINTR ) {
- continue;
- }
-
- return errsv;
- }
- if( nr == 0 ) {
- break;
- }
-
+ }
+
+ while ((unsigned) num_read < len)
+ {
+ ssize_t nr = read (fd, buf + num_read, len - num_read);
+ if (nr < 0)
+ {
+
+ int errsv = -errno;
+ if (errsv == -EINTR)
+ {
+ continue;
+ }
+
+ return errsv;
+ }
+ if (nr == 0)
+ {
+ break;
+ }
+
num_read += nr;
- }
-
- return num_read;
-}
+ }
+ return num_read;
+}
// write, but mask EINTR
// return number of bytes written on success
// return -errno on I/O error
-ssize_t write_uninterrupted( int fd, char const* buf, size_t len ) {
-
- ssize_t num_written = 0;
-
- if( buf == NULL ) {
+ssize_t
+write_uninterrupted (int fd, char const *buf, size_t len)
+{
+
+ ssize_t num_written = 0;
+
+ if (buf == NULL)
+ {
return -EINVAL;
- }
-
- while( (unsigned)num_written < len ) {
- ssize_t nw = write( fd, buf + num_written, len - num_written );
- if( nw < 0 ) {
-
- int errsv = -errno;
- if( errsv == -EINTR ) {
- continue;
- }
-
- return errsv;
- }
- if( nw == 0 ) {
- break;
- }
-
+ }
+
+ while ((unsigned) num_written < len)
+ {
+ ssize_t nw = write (fd, buf + num_written, len - num_written);
+ if (nw < 0)
+ {
+
+ int errsv = -errno;
+ if (errsv == -EINTR)
+ {
+ continue;
+ }
+
+ return errsv;
+ }
+ if (nw == 0)
+ {
+ break;
+ }
+
num_written += nw;
- }
-
- return num_written;
-}
+ }
+ return num_written;
+}
// entry point
-int main( int argc, char** argv ) {
-
- int rc = 0;
- uint64_t seqnum = 0;
- int opt_index = 0;
- int c = 0;
- int fd = 0;
- char* tmp = NULL;
- char event_buf[8192];
- char event_buf_tmp[8292]; // has to hold event_buf plus an 8-byte sequence number
- char event_path[ PATH_MAX+1 ];
-
- bool have_seqnum = false;
- ssize_t nr = 0;
- char const* required_fields[] = {
- "\nSUBSYSTEM=",
- "\nDEVPATH=",
- NULL
- };
-
- char target_queues[PATH_MAX+1];
-
- // default event queue
- memset( g_dev_events, 0, PATH_MAX+1 );
- memset( target_queues, 0, PATH_MAX+1 );
- memset( event_path, 0, PATH_MAX+1 );
-
- strcpy( g_dev_events, DEFAULT_DEV_EVENTS );
-
- static struct option opts[] = {
- {"source-queue", required_argument, 0, 's'},
- {"seqnum", required_argument, 0, 'n'},
- {"help", no_argument, 0, 'h'},
- {0, 0, 0, 0}
- };
-
- char const* optstr = "n:s:h";
-
- while( rc == 0 && c != -1 ) {
-
- c = getopt_long( argc, argv, optstr, opts, &opt_index );
- if( c == -1 ) {
-
- break;
- }
-
- switch( c ) {
-
- case 's': {
-
- memset( g_dev_events, 0, PATH_MAX );
- strncpy( g_dev_events, optarg, PATH_MAX );
- break;
- }
-
- case 'n': {
-
- seqnum = (uint64_t)strtoull( optarg, &tmp, 10 );
- if( seqnum == 0 && (tmp == optarg || *tmp != '\0') ) {
-
- usage( argv[0] );
- exit(1);
- }
-
- have_seqnum = true;
- break;
- }
-
- case 'h': {
-
- help( argv[0] );
- exit(0);
- }
-
- default: {
-
- fprintf(stderr, "[ERROR] %s: Unrecognized option '%c'\n", argv[0], c );
- usage(argv[0]);
- exit(1);
- }
- }
- }
-
- // get the event
- memset( event_buf, 0, 8192 );
- nr = read_uninterrupted( STDIN_FILENO, event_buf, 8192 );
-
- if( nr <= 0 ) {
-
+int
+main (int argc, char **argv)
+{
+
+ int rc = 0;
+ uint64_t seqnum = 0;
+ int opt_index = 0;
+ int c = 0;
+ int fd = 0;
+ char *tmp = NULL;
+ char event_buf[8192];
+ char event_buf_tmp[8292]; // has to hold event_buf plus an 8-byte sequence number
+ char event_path[PATH_MAX + 1];
+
+ bool have_seqnum = false;
+ ssize_t nr = 0;
+ char const *required_fields[] = {
+ "\nSUBSYSTEM=",
+ "\nDEVPATH=",
+ NULL
+ };
+
+ char target_queues[PATH_MAX + 1];
+
+ // default event queue
+ memset (g_dev_events, 0, PATH_MAX + 1);
+ memset (target_queues, 0, PATH_MAX + 1);
+ memset (event_path, 0, PATH_MAX + 1);
+
+ strcpy (g_dev_events, DEFAULT_DEV_EVENTS);
+
+ static struct option opts[] = {
+ {"source-queue", required_argument, 0, 's'},
+ {"seqnum", required_argument, 0, 'n'},
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+
+ char const *optstr = "n:s:h";
+
+ while (rc == 0 && c != -1)
+ {
+
+ c = getopt_long (argc, argv, optstr, opts, &opt_index);
+ if (c == -1)
+ {
+
+ break;
+ }
+
+ switch (c)
+ {
+
+ case 's':
+ {
+
+ memset (g_dev_events, 0, PATH_MAX);
+ strncpy (g_dev_events, optarg, PATH_MAX);
+ break;
+ }
+
+ case 'n':
+ {
+
+ seqnum = (uint64_t) strtoull (optarg, &tmp, 10);
+ if (seqnum == 0 && (tmp == optarg || *tmp != '\0'))
+ {
+
+ usage (argv[0]);
+ exit (1);
+ }
+
+ have_seqnum = true;
+ break;
+ }
+
+ case 'h':
+ {
+
+ help (argv[0]);
+ exit (0);
+ }
+
+ default:
+ {
+
+ fprintf (stderr,
+ "[ERROR] %s: Unrecognized option '%c'\n", argv[0], c);
+ usage (argv[0]);
+ exit (1);
+ }
+ }
+ }
+
+ // get the event
+ memset (event_buf, 0, 8192);
+ nr = read_uninterrupted (STDIN_FILENO, event_buf, 8192);
+
+ if (nr <= 0)
+ {
+
rc = -errno;
- fprintf( stderr, "[ERROR] %s: Failed to read event from stdin: %s\n", argv[0], strerror( -rc ) );
- exit(1);
- }
-
- // simple sanity check for requirements
- for( int i = 0; required_fields[i] != NULL; i++ ) {
-
- if( strstr( event_buf, required_fields[i] ) == NULL ) {
-
- // head of line? with no leading '\n'?
- if( strncmp( event_buf, required_fields[i] + 1, strlen(required_fields[i]) - 1 ) != 0 ) {
-
- fprintf(stderr, "[ERROR] %s: Missing required field '%s'\n", argv[0], required_fields[i] + 1 );
- fprintf(stderr, "[ERROR] %s: Pass -h for a list of required fields\n", argv[0] );
- exit(1);
- }
- }
- }
-
- // do we have a seqnum?
- if( !have_seqnum ) {
-
- char* seqnum_str = strstr( event_buf, "SEQNUM=" );
-
+ fprintf (stderr,
+ "[ERROR] %s: Failed to read event from stdin: %s\n",
+ argv[0], strerror (-rc));
+ exit (1);
+ }
+ // simple sanity check for requirements
+ for (int i = 0; required_fields[i] != NULL; i++)
+ {
+
+ if (strstr (event_buf, required_fields[i]) == NULL)
+ {
+
+ // head of line? with no leading '\n'?
+ if (strncmp
+ (event_buf, required_fields[i] + 1,
+ strlen (required_fields[i]) - 1) != 0)
+ {
+
+ fprintf (stderr,
+ "[ERROR] %s: Missing required field '%s'\n",
+ argv[0], required_fields[i] + 1);
+ fprintf (stderr,
+ "[ERROR] %s: Pass -h for a list of required fields\n",
+ argv[0]);
+ exit (1);
+ }
+ }
+ }
+
+ // do we have a seqnum?
+ if (!have_seqnum)
+ {
+
+ char *seqnum_str = strstr (event_buf, "SEQNUM=");
+
// go find it in the device event
- if( seqnum_str == NULL ) {
-
- fprintf(stderr, "[ERROR] %s: Missing SEQNUM. Pass -n or include SEQNUM= in the input.\n", argv[0]);
- exit(1);
- }
-
+ if (seqnum_str == NULL)
+ {
+
+ fprintf (stderr,
+ "[ERROR] %s: Missing SEQNUM. Pass -n or include SEQNUM= in the input.\n",
+ argv[0]);
+ exit (1);
+ }
// is it a valid seqnum?
- seqnum = (uint64_t)strtoull( seqnum_str + strlen("SEQNUM="), &tmp, 10 );
- if( seqnum == 0 && (tmp == seqnum_str + strlen("SEQNUM=") || *tmp != '\n') ) {
-
- // invalid seqnum
- fprintf(stderr, "[ERROR] %s: Invalid SEQNUM. Pass -n or include a valid SEQNUM in the input.\n", argv[0]);
- exit(1);
- }
- }
-
- // send it off!
- make_event_path( seqnum, event_path );
-
- fd = open_event( event_path );
- if( fd < 0 ) {
-
- fprintf(stderr, "[ERROR] %s: Failed to open '%s': %s\n", argv[0], event_path, strerror( -fd ) );
- exit(1);
- }
-
- rc = write_uninterrupted( fd, event_buf, nr );
- if( rc < 0 ) {
-
- fprintf(stderr, "[ERROR] %s: Failed to write '%s': %s\n", argv[0], event_path, strerror( -fd ) );
-
- clear_event( event_buf );
- close( fd );
- exit(1);
- }
-
- // propagate....
- rc = multicast_event( seqnum, event_path );
- if( rc < 0 ) {
-
- fprintf(stderr, "[ERROR] %s: Failed to multicast '%s': %s\n", argv[0], event_path, strerror( -rc ) );
-
- clear_event( event_buf );
- close( fd );
- exit(1);
- }
-
- // done!
- clear_event( event_path );
- close( fd );
-
- return 0;
+ seqnum =
+ (uint64_t) strtoull (seqnum_str + strlen ("SEQNUM="), &tmp, 10);
+ if (seqnum == 0
+ && (tmp == seqnum_str + strlen ("SEQNUM=") || *tmp != '\n'))
+ {
+
+ // invalid seqnum
+ fprintf (stderr,
+ "[ERROR] %s: Invalid SEQNUM. Pass -n or include a valid SEQNUM in the input.\n",
+ argv[0]);
+ exit (1);
+ }
+ }
+ // send it off!
+ make_event_path (seqnum, event_path);
+
+ fd = open_event (event_path);
+ if (fd < 0)
+ {
+
+ fprintf (stderr, "[ERROR] %s: Failed to open '%s': %s\n",
+ argv[0], event_path, strerror (-fd));
+ exit (1);
+ }
+
+ rc = write_uninterrupted (fd, event_buf, nr);
+ if (rc < 0)
+ {
+
+ fprintf (stderr, "[ERROR] %s: Failed to write '%s': %s\n",
+ argv[0], event_path, strerror (-fd));
+
+ clear_event (event_buf);
+ close (fd);
+ exit (1);
+ }
+ // propagate....
+ rc = multicast_event (seqnum, event_path);
+ if (rc < 0)
+ {
+
+ fprintf (stderr, "[ERROR] %s: Failed to multicast '%s': %s\n",
+ argv[0], event_path, strerror (-rc));
+
+ clear_event (event_buf);
+ close (fd);
+ exit (1);
+ }
+ // done!
+ clear_event (event_path);
+ close (fd);
+
+ return 0;
}
diff --git a/vdevd/helpers/LINUX/stat_ata.c b/vdevd/helpers/LINUX/stat_ata.c
index 9500224..5797ff8 100644
--- a/vdevd/helpers/LINUX/stat_ata.c
+++ b/vdevd/helpers/LINUX/stat_ata.c
@@ -72,240 +72,258 @@
#define COMMAND_TIMEOUT_MSEC (30 * 1000)
-static int disk_scsi_inquiry_command(int fd, void *buf, size_t buf_len) {
-
- uint8_t cdb[6];
- uint8_t sense[32];
- struct sg_io_v4 io_v4;
- struct sg_io_hdr io_hdr;
- int ret = 0;
-
- memset( sense, 0, 32 * sizeof(uint8_t));
- memset( &io_v4, 0, sizeof(struct sg_io_v4) );
- memset( &io_hdr, 0, sizeof(struct sg_io_hdr) );
- memset( cdb, 0, 6 * sizeof(uint8_t) );
-
- /*
+static int
+disk_scsi_inquiry_command (int fd, void *buf, size_t buf_len)
+{
+
+ uint8_t cdb[6];
+ uint8_t sense[32];
+ struct sg_io_v4 io_v4;
+ struct sg_io_hdr io_hdr;
+ int ret = 0;
+
+ memset (sense, 0, 32 * sizeof (uint8_t));
+ memset (&io_v4, 0, sizeof (struct sg_io_v4));
+ memset (&io_hdr, 0, sizeof (struct sg_io_hdr));
+ memset (cdb, 0, 6 * sizeof (uint8_t));
+
+ /*
* INQUIRY, see SPC-4 section 6.4
*/
- cdb[0] = 0x12; /* OPERATION CODE: INQUIRY */
- cdb[3] = (buf_len >> 8); /* ALLOCATION LENGTH */
- cdb[4] = (buf_len & 0xff);
-
- io_v4.guard = 'Q',
- io_v4.protocol = BSG_PROTOCOL_SCSI;
- io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD;
- io_v4.request_len = sizeof(cdb);
- io_v4.request = (uintptr_t) cdb;
- io_v4.max_response_len = sizeof(sense);
- io_v4.response = (uintptr_t) sense;
- io_v4.din_xfer_len = buf_len;
- io_v4.din_xferp = (uintptr_t) buf;
- io_v4.timeout = COMMAND_TIMEOUT_MSEC;
-
- ret = ioctl(fd, SG_IO, &io_v4);
- if (ret != 0) {
+ cdb[0] = 0x12; /* OPERATION CODE: INQUIRY */
+ cdb[3] = (buf_len >> 8); /* ALLOCATION LENGTH */
+ cdb[4] = (buf_len & 0xff);
+
+ io_v4.guard = 'Q', io_v4.protocol = BSG_PROTOCOL_SCSI;
+ io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD;
+ io_v4.request_len = sizeof (cdb);
+ io_v4.request = (uintptr_t) cdb;
+ io_v4.max_response_len = sizeof (sense);
+ io_v4.response = (uintptr_t) sense;
+ io_v4.din_xfer_len = buf_len;
+ io_v4.din_xferp = (uintptr_t) buf;
+ io_v4.timeout = COMMAND_TIMEOUT_MSEC;
+
+ ret = ioctl (fd, SG_IO, &io_v4);
+ if (ret != 0)
+ {
/* could be that the driver doesn't do version 4, try version 3 */
- if (errno == EINVAL) {
-
- io_hdr.interface_id = 'S';
- io_hdr.cmdp = (unsigned char*) cdb;
- io_hdr.cmd_len = sizeof (cdb);
- io_hdr.dxferp = buf;
- io_hdr.dxfer_len = buf_len;
- io_hdr.sbp = sense;
- io_hdr.mx_sb_len = sizeof(sense);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.timeout = COMMAND_TIMEOUT_MSEC;
-
- ret = ioctl(fd, SG_IO, &io_hdr);
- if (ret != 0) {
-
- return ret;
- }
-
- /* even if the ioctl succeeds, we need to check the return value */
- if (!(io_hdr.status == 0 &&
- io_hdr.host_status == 0 &&
- io_hdr.driver_status == 0)) {
- errno = EIO;
-
- return -1;
- }
- } else {
-
- return ret;
- }
- }
-
- /* even if the ioctl succeeds, we need to check the return value */
- if (!(io_v4.device_status == 0 &&
- io_v4.transport_status == 0 &&
- io_v4.driver_status == 0)) {
- errno = EIO;
-
- return -1;
- }
-
- return 0;
+ if (errno == EINVAL)
+ {
+
+ io_hdr.interface_id = 'S';
+ io_hdr.cmdp = (unsigned char *) cdb;
+ io_hdr.cmd_len = sizeof (cdb);
+ io_hdr.dxferp = buf;
+ io_hdr.dxfer_len = buf_len;
+ io_hdr.sbp = sense;
+ io_hdr.mx_sb_len = sizeof (sense);
+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+ io_hdr.timeout = COMMAND_TIMEOUT_MSEC;
+
+ ret = ioctl (fd, SG_IO, &io_hdr);
+ if (ret != 0)
+ {
+
+ return ret;
+ }
+
+ /* even if the ioctl succeeds, we need to check the return value */
+ if (!(io_hdr.status == 0 &&
+ io_hdr.host_status == 0 && io_hdr.driver_status == 0))
+ {
+ errno = EIO;
+
+ return -1;
+ }
+ }
+ else
+ {
+
+ return ret;
+ }
+ }
+
+ /* even if the ioctl succeeds, we need to check the return value */
+ if (!(io_v4.device_status == 0 &&
+ io_v4.transport_status == 0 && io_v4.driver_status == 0))
+ {
+ errno = EIO;
+
+ return -1;
+ }
+
+ return 0;
}
-static int disk_identify_command(int fd, void *buf, size_t buf_len) {
-
- uint8_t cdb[12];
- uint8_t sense[32] = {};
- uint8_t *desc = sense + 8;
- struct sg_io_v4 io_v4;
- struct sg_io_hdr io_hdr;
- int ret = 0;
-
- memset( cdb, 0, sizeof(uint8_t) * 12 );
- memset( &io_v4, 0, sizeof(struct sg_io_v4) );
- memset( &io_hdr, 0, sizeof(struct sg_io_hdr) );
-
- /*
+static int
+disk_identify_command (int fd, void *buf, size_t buf_len)
+{
+
+ uint8_t cdb[12];
+ uint8_t sense[32] = { };
+ uint8_t *desc = sense + 8;
+ struct sg_io_v4 io_v4;
+ struct sg_io_hdr io_hdr;
+ int ret = 0;
+
+ memset (cdb, 0, sizeof (uint8_t) * 12);
+ memset (&io_v4, 0, sizeof (struct sg_io_v4));
+ memset (&io_hdr, 0, sizeof (struct sg_io_hdr));
+
+ /*
* ATA Pass-Through 12 byte command, as described in
*
* T10 04-262r8 ATA Command Pass-Through
*
* from http://www.t10.org/ftp/t10/document.04/04-262r8.pdf
*/
- cdb[0] = 0xa1; /* OPERATION CODE: 12 byte pass through */
- cdb[1] = 4 << 1; /* PROTOCOL: PIO Data-in */
- cdb[2] = 0x2e; /* OFF_LINE=0, CK_COND=1, T_DIR=1, BYT_BLOK=1, T_LENGTH=2 */
- cdb[3] = 0; /* FEATURES */
- cdb[4] = 1; /* SECTORS */
- cdb[5] = 0; /* LBA LOW */
- cdb[6] = 0; /* LBA MID */
- cdb[7] = 0; /* LBA HIGH */
- cdb[8] = 0 & 0x4F; /* SELECT */
- cdb[9] = 0xEC; /* Command: ATA IDENTIFY DEVICE */
-
- io_v4.guard = 'Q';
- io_v4.protocol = BSG_PROTOCOL_SCSI;
- io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD;
- io_v4.request_len = sizeof(cdb);
- io_v4.request = (uintptr_t) cdb;
- io_v4.max_response_len = sizeof(sense);
- io_v4.response = (uintptr_t) sense;
- io_v4.din_xfer_len = buf_len;
- io_v4.din_xferp = (uintptr_t) buf;
- io_v4.timeout = COMMAND_TIMEOUT_MSEC;
-
- ret = ioctl(fd, SG_IO, &io_v4);
- if (ret != 0) {
+ cdb[0] = 0xa1; /* OPERATION CODE: 12 byte pass through */
+ cdb[1] = 4 << 1; /* PROTOCOL: PIO Data-in */
+ cdb[2] = 0x2e; /* OFF_LINE=0, CK_COND=1, T_DIR=1, BYT_BLOK=1, T_LENGTH=2 */
+ cdb[3] = 0; /* FEATURES */
+ cdb[4] = 1; /* SECTORS */
+ cdb[5] = 0; /* LBA LOW */
+ cdb[6] = 0; /* LBA MID */
+ cdb[7] = 0; /* LBA HIGH */
+ cdb[8] = 0 & 0x4F; /* SELECT */
+ cdb[9] = 0xEC; /* Command: ATA IDENTIFY DEVICE */
+
+ io_v4.guard = 'Q';
+ io_v4.protocol = BSG_PROTOCOL_SCSI;
+ io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD;
+ io_v4.request_len = sizeof (cdb);
+ io_v4.request = (uintptr_t) cdb;
+ io_v4.max_response_len = sizeof (sense);
+ io_v4.response = (uintptr_t) sense;
+ io_v4.din_xfer_len = buf_len;
+ io_v4.din_xferp = (uintptr_t) buf;
+ io_v4.timeout = COMMAND_TIMEOUT_MSEC;
+
+ ret = ioctl (fd, SG_IO, &io_v4);
+ if (ret != 0)
+ {
/* could be that the driver doesn't do version 4, try version 3 */
- if (errno == EINVAL) {
-
- io_hdr.interface_id = 'S',
- io_hdr.cmdp = (unsigned char*) cdb;
- io_hdr.cmd_len = sizeof (cdb);
- io_hdr.dxferp = buf;
- io_hdr.dxfer_len = buf_len;
- io_hdr.sbp = sense;
- io_hdr.mx_sb_len = sizeof (sense);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.timeout = COMMAND_TIMEOUT_MSEC;
-
- ret = ioctl(fd, SG_IO, &io_hdr);
- if (ret != 0) {
- return ret;
- }
- }
- else {
- return ret;
- }
- }
-
- if (!(sense[0] == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c)) {
+ if (errno == EINVAL)
+ {
+
+ io_hdr.interface_id = 'S', io_hdr.cmdp = (unsigned char *) cdb;
+ io_hdr.cmd_len = sizeof (cdb);
+ io_hdr.dxferp = buf;
+ io_hdr.dxfer_len = buf_len;
+ io_hdr.sbp = sense;
+ io_hdr.mx_sb_len = sizeof (sense);
+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+ io_hdr.timeout = COMMAND_TIMEOUT_MSEC;
+
+ ret = ioctl (fd, SG_IO, &io_hdr);
+ if (ret != 0)
+ {
+ return ret;
+ }
+ }
+ else
+ {
+ return ret;
+ }
+ }
+
+ if (!(sense[0] == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c))
+ {
errno = EIO;
return -1;
- }
+ }
- return 0;
+ return 0;
}
+static int
+disk_identify_packet_device_command (int fd, void *buf, size_t buf_len)
+{
+
+ uint8_t cdb[16];
+ uint8_t sense[32];
+ struct sg_io_v4 io_v4;
+ struct sg_io_hdr io_hdr;
+ uint8_t *desc = sense + 8;
+ int ret = 0;
+
+ memset (sense, 0, 32 * sizeof (uint8_t));
+ memset (&io_v4, 0, sizeof (struct sg_io_v4));
+ memset (&io_hdr, 0, sizeof (struct sg_io_hdr));
-static int disk_identify_packet_device_command(int fd, void *buf, size_t buf_len) {
-
- uint8_t cdb[16];
- uint8_t sense[32];
- struct sg_io_v4 io_v4;
- struct sg_io_hdr io_hdr;
- uint8_t *desc = sense + 8;
- int ret = 0;
-
- memset( sense, 0, 32 * sizeof(uint8_t) );
- memset( &io_v4, 0, sizeof(struct sg_io_v4) );
- memset( &io_hdr, 0, sizeof(struct sg_io_hdr) );
-
- /*
+ /*
* ATA Pass-Through 16 byte command, as described in
*
* T10 04-262r8 ATA Command Pass-Through
*
* from http://www.t10.org/ftp/t10/document.04/04-262r8.pdf
*/
- cdb[0] = 0x85; /* OPERATION CODE: 16 byte pass through */
- cdb[1] = 4 << 1; /* PROTOCOL: PIO Data-in */
- cdb[2] = 0x2e; /* OFF_LINE=0, CK_COND=1, T_DIR=1, BYT_BLOK=1, T_LENGTH=2 */
- cdb[3] = 0; /* FEATURES */
- cdb[4] = 0; /* FEATURES */
- cdb[5] = 0; /* SECTORS */
- cdb[6] = 1; /* SECTORS */
- cdb[7] = 0; /* LBA LOW */
- cdb[8] = 0; /* LBA LOW */
- cdb[9] = 0; /* LBA MID */
- cdb[10] = 0; /* LBA MID */
- cdb[11] = 0; /* LBA HIGH */
- cdb[12] = 0; /* LBA HIGH */
- cdb[13] = 0; /* DEVICE */
- cdb[14] = 0xA1; /* Command: ATA IDENTIFY PACKET DEVICE */
- cdb[15] = 0; /* CONTROL */
-
- io_v4.guard = 'Q';
- io_v4.protocol = BSG_PROTOCOL_SCSI;
- io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD;
- io_v4.request_len = sizeof (cdb);
- io_v4.request = (uintptr_t) cdb;
- io_v4.max_response_len = sizeof (sense);
- io_v4.response = (uintptr_t) sense;
- io_v4.din_xfer_len = buf_len;
- io_v4.din_xferp = (uintptr_t) buf;
- io_v4.timeout = COMMAND_TIMEOUT_MSEC;
-
- ret = ioctl(fd, SG_IO, &io_v4);
- if (ret != 0) {
+ cdb[0] = 0x85; /* OPERATION CODE: 16 byte pass through */
+ cdb[1] = 4 << 1; /* PROTOCOL: PIO Data-in */
+ cdb[2] = 0x2e; /* OFF_LINE=0, CK_COND=1, T_DIR=1, BYT_BLOK=1, T_LENGTH=2 */
+ cdb[3] = 0; /* FEATURES */
+ cdb[4] = 0; /* FEATURES */
+ cdb[5] = 0; /* SECTORS */
+ cdb[6] = 1; /* SECTORS */
+ cdb[7] = 0; /* LBA LOW */
+ cdb[8] = 0; /* LBA LOW */
+ cdb[9] = 0; /* LBA MID */
+ cdb[10] = 0; /* LBA MID */
+ cdb[11] = 0; /* LBA HIGH */
+ cdb[12] = 0; /* LBA HIGH */
+ cdb[13] = 0; /* DEVICE */
+ cdb[14] = 0xA1; /* Command: ATA IDENTIFY PACKET DEVICE */
+ cdb[15] = 0; /* CONTROL */
+
+ io_v4.guard = 'Q';
+ io_v4.protocol = BSG_PROTOCOL_SCSI;
+ io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD;
+ io_v4.request_len = sizeof (cdb);
+ io_v4.request = (uintptr_t) cdb;
+ io_v4.max_response_len = sizeof (sense);
+ io_v4.response = (uintptr_t) sense;
+ io_v4.din_xfer_len = buf_len;
+ io_v4.din_xferp = (uintptr_t) buf;
+ io_v4.timeout = COMMAND_TIMEOUT_MSEC;
+
+ ret = ioctl (fd, SG_IO, &io_v4);
+ if (ret != 0)
+ {
/* could be that the driver doesn't do version 4, try version 3 */
- if (errno == EINVAL) {
-
- io_hdr.interface_id = 'S';
- io_hdr.cmdp = (unsigned char*) cdb;
- io_hdr.cmd_len = sizeof (cdb);
- io_hdr.dxferp = buf;
- io_hdr.dxfer_len = buf_len;
- io_hdr.sbp = sense;
- io_hdr.mx_sb_len = sizeof (sense);
- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
- io_hdr.timeout = COMMAND_TIMEOUT_MSEC;
-
- ret = ioctl(fd, SG_IO, &io_hdr);
- if (ret != 0) {
- return ret;
- }
-
- }
- else {
- return ret;
- }
- }
-
- if (!(sense[0] == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c)) {
+ if (errno == EINVAL)
+ {
+
+ io_hdr.interface_id = 'S';
+ io_hdr.cmdp = (unsigned char *) cdb;
+ io_hdr.cmd_len = sizeof (cdb);
+ io_hdr.dxferp = buf;
+ io_hdr.dxfer_len = buf_len;
+ io_hdr.sbp = sense;
+ io_hdr.mx_sb_len = sizeof (sense);
+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+ io_hdr.timeout = COMMAND_TIMEOUT_MSEC;
+
+ ret = ioctl (fd, SG_IO, &io_hdr);
+ if (ret != 0)
+ {
+ return ret;
+ }
+
+ }
+ else
+ {
+ return ret;
+ }
+ }
+
+ if (!(sense[0] == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c))
+ {
errno = EIO;
return -1;
- }
+ }
- return 0;
+ return 0;
}
/**
@@ -317,12 +335,17 @@ static int disk_identify_packet_device_command(int fd, void *buf, size_t buf_len
*
* Copies the ATA string from @identify located at @offset_words into @dest.
*/
-static void disk_identify_get_string(uint8_t identify[512], unsigned int offset_words, char *dest, size_t dest_len) {
-
- unsigned int c1;
- unsigned int c2;
+static void
+disk_identify_get_string (uint8_t identify[512],
+ unsigned int offset_words, char *dest,
+ size_t dest_len)
+{
- while (dest_len > 0) {
+ unsigned int c1;
+ unsigned int c2;
+
+ while (dest_len > 0)
+ {
c1 = identify[offset_words * 2 + 1];
c2 = identify[offset_words * 2];
*dest = c1;
@@ -331,19 +354,25 @@ static void disk_identify_get_string(uint8_t identify[512], unsigned int offset_
dest++;
offset_words++;
dest_len -= 2;
- }
+ }
}
-static void disk_identify_fixup_string(uint8_t identify[512], unsigned int offset_words, size_t len) {
-
- disk_identify_get_string(identify, offset_words, (char *) identify + offset_words * 2, len);
+static void
+disk_identify_fixup_string (uint8_t identify[512],
+ unsigned int offset_words, size_t len)
+{
+
+ disk_identify_get_string (identify, offset_words,
+ (char *) identify + offset_words * 2, len);
}
-static void disk_identify_fixup_uint16 (uint8_t identify[512], unsigned int offset_words) {
- uint16_t *p;
+static void
+disk_identify_fixup_uint16 (uint8_t identify[512], unsigned int offset_words)
+{
+ uint16_t *p;
- p = (uint16_t *) identify;
- p[offset_words] = le16toh (p[offset_words]);
+ p = (uint16_t *) identify;
+ p[offset_words] = le16toh (p[offset_words]);
}
/**
@@ -363,19 +392,21 @@ static void disk_identify_fixup_uint16 (uint8_t identify[512], unsigned int offs
* Returns: 0 if the data was successfully obtained, otherwise
* non-zero with errno set.
*/
-static int disk_identify(int fd, uint8_t out_identify[512], int *out_is_packet_device) {
+static int
+disk_identify (int fd, uint8_t out_identify[512], int *out_is_packet_device)
+{
- int ret;
- uint8_t inquiry_buf[36];
- int peripheral_device_type = 0;
- int all_nul_bytes = 1;
- int n = 0;
- int is_packet_device = 0;
+ int ret;
+ uint8_t inquiry_buf[36];
+ int peripheral_device_type = 0;
+ int all_nul_bytes = 1;
+ int n = 0;
+ int is_packet_device = 0;
- /* init results */
- memset(out_identify, 0, 512);
+ /* init results */
+ memset (out_identify, 0, 512);
- /* If we were to use ATA PASS_THROUGH (12) on an ATAPI device
+ /* If we were to use ATA PASS_THROUGH (12) on an ATAPI device
* we could accidentally blank media. This is because MMC's BLANK
* command has the same op-code (0x61).
*
@@ -396,380 +427,440 @@ static int disk_identify(int fd, uint8_t out_identify[512], int *out_is_packet_d
* the original bug-fix and see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=556635
* for the original bug-report.)
*/
- ret = disk_scsi_inquiry_command (fd, inquiry_buf, sizeof (inquiry_buf));
- if (ret != 0) {
-
+ ret = disk_scsi_inquiry_command (fd, inquiry_buf, sizeof (inquiry_buf));
+ if (ret != 0)
+ {
+
goto out;
- }
+ }
+
+ /* SPC-4, section 6.4.2: Standard INQUIRY data */
+ peripheral_device_type = inquiry_buf[0] & 0x1f;
+ if (peripheral_device_type == 0x05)
+ {
- /* SPC-4, section 6.4.2: Standard INQUIRY data */
- peripheral_device_type = inquiry_buf[0] & 0x1f;
- if (peripheral_device_type == 0x05) {
-
is_packet_device = 1;
- ret = disk_identify_packet_device_command(fd, out_identify, 512);
+ ret = disk_identify_packet_device_command (fd, out_identify, 512);
goto check_nul_bytes;
- }
- if (peripheral_device_type != 0x00) {
+ }
+ if (peripheral_device_type != 0x00)
+ {
ret = -1;
errno = EIO;
-
+
goto out;
- }
+ }
+
+ /* OK, now issue the IDENTIFY DEVICE command */
+ ret = disk_identify_command (fd, out_identify, 512);
+ if (ret != 0)
+ {
- /* OK, now issue the IDENTIFY DEVICE command */
- ret = disk_identify_command(fd, out_identify, 512);
- if (ret != 0) {
-
goto out;
- }
+ }
check_nul_bytes:
- /* Check if IDENTIFY data is all NUL bytes - if so, bail */
- all_nul_bytes = 1;
- for (n = 0; n < 512; n++) {
- if (out_identify[n] != '\0') {
- all_nul_bytes = 0;
- break;
- }
- }
-
- if (all_nul_bytes) {
-
+ /* Check if IDENTIFY data is all NUL bytes - if so, bail */
+ all_nul_bytes = 1;
+ for (n = 0; n < 512; n++)
+ {
+ if (out_identify[n] != '\0')
+ {
+ all_nul_bytes = 0;
+ break;
+ }
+ }
+
+ if (all_nul_bytes)
+ {
+
ret = -1;
errno = EIO;
goto out;
- }
+ }
out:
- if (out_is_packet_device != NULL) {
+ if (out_is_packet_device != NULL)
+ {
*out_is_packet_device = is_packet_device;
- }
- return ret;
+ }
+ return ret;
}
-
// entry point
-int main(int argc, char **argv ) {
-
- struct hd_driveid id;
- union {
- uint8_t byte[512];
- uint16_t wyde[256];
- uint64_t octa[64];
- } identify;
-
- int fd = 0;
- char model[41];
- char model_enc[256];
- char serial[21];
- char revision[9];
- const char *node = NULL;
- uint16_t word = 0;
- int is_packet_device = 0;
- int rc = 0;
-
- // check usage
- if( argc != 2 ) {
- fprintf(stderr, "[ERROR] %s: Usage: %s /path/to/device/file\n", argv[0], argv[0]);
- exit(1);
- }
-
- node = argv[1];
-
- fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC);
- if (fd < 0) {
- fprintf(stderr, "[ERROR] %s: unable to open '%s'\n", argv[0], node);
- exit(1);
- }
-
- rc = disk_identify(fd, identify.byte, &is_packet_device);
- if( rc == 0 ) {
+int
+main (int argc, char **argv)
+{
+
+ struct hd_driveid id;
+ union
+ {
+ uint8_t byte[512];
+ uint16_t wyde[256];
+ uint64_t octa[64];
+ } identify;
+
+ int fd = 0;
+ char model[41];
+ char model_enc[256];
+ char serial[21];
+ char revision[9];
+ const char *node = NULL;
+ uint16_t word = 0;
+ int is_packet_device = 0;
+ int rc = 0;
+
+ // check usage
+ if (argc != 2)
+ {
+ fprintf (stderr, "[ERROR] %s: Usage: %s /path/to/device/file\n",
+ argv[0], argv[0]);
+ exit (1);
+ }
+
+ node = argv[1];
+
+ fd = open (node, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ if (fd < 0)
+ {
+ fprintf (stderr, "[ERROR] %s: unable to open '%s'\n", argv[0], node);
+ exit (1);
+ }
+
+ rc = disk_identify (fd, identify.byte, &is_packet_device);
+ if (rc == 0)
+ {
/*
- * fix up only the fields from the IDENTIFY data that we are going to
- * use and copy it into the hd_driveid struct for convenience
- */
- disk_identify_fixup_string(identify.byte, 10, 20); /* serial */
- disk_identify_fixup_string(identify.byte, 23, 8); /* fwrev */
- disk_identify_fixup_string(identify.byte, 27, 40); /* model */
- disk_identify_fixup_uint16(identify.byte, 0); /* configuration */
- disk_identify_fixup_uint16(identify.byte, 75); /* queue depth */
- disk_identify_fixup_uint16(identify.byte, 75); /* SATA capabilities */
- disk_identify_fixup_uint16(identify.byte, 82); /* command set supported */
- disk_identify_fixup_uint16(identify.byte, 83); /* command set supported */
- disk_identify_fixup_uint16(identify.byte, 84); /* command set supported */
- disk_identify_fixup_uint16(identify.byte, 85); /* command set supported */
- disk_identify_fixup_uint16(identify.byte, 86); /* command set supported */
- disk_identify_fixup_uint16(identify.byte, 87); /* command set supported */
- disk_identify_fixup_uint16(identify.byte, 89); /* time required for SECURITY ERASE UNIT */
- disk_identify_fixup_uint16(identify.byte, 90); /* time required for enhanced SECURITY ERASE UNIT */
- disk_identify_fixup_uint16(identify.byte, 91); /* current APM values */
- disk_identify_fixup_uint16(identify.byte, 94); /* current AAM value */
- disk_identify_fixup_uint16(identify.byte, 128); /* device lock function */
- disk_identify_fixup_uint16(identify.byte, 217); /* nominal media rotation rate */
- memcpy(&id, identify.byte, sizeof id);
- }
- else {
-
+ * fix up only the fields from the IDENTIFY data that we are going to
+ * use and copy it into the hd_driveid struct for convenience
+ */
+ disk_identify_fixup_string (identify.byte, 10, 20); /* serial */
+ disk_identify_fixup_string (identify.byte, 23, 8); /* fwrev */
+ disk_identify_fixup_string (identify.byte, 27, 40); /* model */
+ disk_identify_fixup_uint16 (identify.byte, 0); /* configuration */
+ disk_identify_fixup_uint16 (identify.byte, 75); /* queue depth */
+ disk_identify_fixup_uint16 (identify.byte, 75); /* SATA capabilities */
+ disk_identify_fixup_uint16 (identify.byte, 82); /* command set supported */
+ disk_identify_fixup_uint16 (identify.byte, 83); /* command set supported */
+ disk_identify_fixup_uint16 (identify.byte, 84); /* command set supported */
+ disk_identify_fixup_uint16 (identify.byte, 85); /* command set supported */
+ disk_identify_fixup_uint16 (identify.byte, 86); /* command set supported */
+ disk_identify_fixup_uint16 (identify.byte, 87); /* command set supported */
+ disk_identify_fixup_uint16 (identify.byte, 89); /* time required for SECURITY ERASE UNIT */
+ disk_identify_fixup_uint16 (identify.byte, 90); /* time required for enhanced SECURITY ERASE UNIT */
+ disk_identify_fixup_uint16 (identify.byte, 91); /* current APM values */
+ disk_identify_fixup_uint16 (identify.byte, 94); /* current AAM value */
+ disk_identify_fixup_uint16 (identify.byte, 128); /* device lock function */
+ disk_identify_fixup_uint16 (identify.byte, 217); /* nominal media rotation rate */
+ memcpy (&id, identify.byte, sizeof id);
+ }
+ else
+ {
+
/* If this fails, then try HDIO_GET_IDENTITY */
- if (ioctl(fd, HDIO_GET_IDENTITY, &id) != 0) {
- int errsv = -errno;
- fprintf( stderr, "[ERROR] %s: HDIO_GET_IDENTITY failed for '%s': errno = %d\n", argv[0], node, errsv);
- close(fd);
- exit(2);
- }
- }
-
- memcpy (model, id.model, 40);
- model[40] = '\0';
-
- vdev_util_encode_string(model, model_enc, sizeof(model_enc));
- vdev_util_replace_whitespace((char *) id.model, model, 40);
- vdev_util_replace_chars(model, NULL);
- vdev_util_replace_whitespace((char *) id.serial_no, serial, 20);
- vdev_util_replace_chars(serial, NULL);
- vdev_util_replace_whitespace((char *) id.fw_rev, revision, 8);
- vdev_util_replace_chars(revision, NULL);
-
-
- /* Set this to convey the disk speaks the ATA protocol */
- vdev_property_add( "VDEV_ATA", "1" );
-
- if ((id.config >> 8) & 0x80) {
+ if (ioctl (fd, HDIO_GET_IDENTITY, &id) != 0)
+ {
+ int errsv = -errno;
+ fprintf (stderr,
+ "[ERROR] %s: HDIO_GET_IDENTITY failed for '%s': errno = %d\n",
+ argv[0], node, errsv);
+ close (fd);
+ exit (2);
+ }
+ }
+
+ memcpy (model, id.model, 40);
+ model[40] = '\0';
+
+ vdev_util_encode_string (model, model_enc, sizeof (model_enc));
+ vdev_util_replace_whitespace ((char *) id.model, model, 40);
+ vdev_util_replace_chars (model, NULL);
+ vdev_util_replace_whitespace ((char *) id.serial_no, serial, 20);
+ vdev_util_replace_chars (serial, NULL);
+ vdev_util_replace_whitespace ((char *) id.fw_rev, revision, 8);
+ vdev_util_replace_chars (revision, NULL);
+
+ /* Set this to convey the disk speaks the ATA protocol */
+ vdev_property_add ("VDEV_ATA", "1");
+
+ if ((id.config >> 8) & 0x80)
+ {
/* This is an ATAPI device */
- switch ((id.config >> 8) & 0x1f) {
- case 0:
-
- vdev_property_add( "VDEV_ATA_TYPE", "cd" );
- break;
-
- case 1:
-
- vdev_property_add("VDEV_ATA_TYPE", "tape" );
- break;
-
- case 5:
-
- vdev_property_add("VDEV_ATA_TYPE", "cd" );
- break;
-
- case 7:
-
- vdev_property_add("VDEV_ATA_TYPE", "optical" );
- break;
-
- default:
-
- vdev_property_add("VDEV_ATA_TYPE", "generic" );
- break;
- }
- }
- else {
-
- vdev_property_add("VDEV_ATA_TYPE", "disk" );
- }
-
- vdev_property_add("VDEV_ATA_MODEL", model );
- vdev_property_add("VDEV_ATA_MODEL_ENC", model_enc );
- vdev_property_add("VDEV_ATA_REVISION", revision );
-
- if (serial[0] != '\0') {
-
+ switch ((id.config >> 8) & 0x1f)
+ {
+ case 0:
+
+ vdev_property_add ("VDEV_ATA_TYPE", "cd");
+ break;
+
+ case 1:
+
+ vdev_property_add ("VDEV_ATA_TYPE", "tape");
+ break;
+
+ case 5:
+
+ vdev_property_add ("VDEV_ATA_TYPE", "cd");
+ break;
+
+ case 7:
+
+ vdev_property_add ("VDEV_ATA_TYPE", "optical");
+ break;
+
+ default:
+
+ vdev_property_add ("VDEV_ATA_TYPE", "generic");
+ break;
+ }
+ }
+ else
+ {
+
+ vdev_property_add ("VDEV_ATA_TYPE", "disk");
+ }
+
+ vdev_property_add ("VDEV_ATA_MODEL", model);
+ vdev_property_add ("VDEV_ATA_MODEL_ENC", model_enc);
+ vdev_property_add ("VDEV_ATA_REVISION", revision);
+
+ if (serial[0] != '\0')
+ {
+
char serial_buf[100];
- memset( serial_buf, 0, 100 );
-
- snprintf( serial_buf, 99, "%s_%s", model, serial );
-
- vdev_property_add("VDEV_ATA_SERIAL", serial_buf );
- vdev_property_add("VDEV_ATA_SERIAL_SHORT", serial );
-
- }
- else {
-
- vdev_property_add("VDEV_ATA_SERIAL", model );
- }
-
- if (id.command_set_1 & (1<<5)) {
-
- vdev_property_add("VDEV_ATA_WRITE_CACHE", "1" );
- vdev_property_add("VDEV_ATA_WRITE_CACHE_ENABLED", (id.cfs_enable_1 & (1<<5)) ? "1" : "0" );
- }
- if (id.command_set_1 & (1<<10)) {
-
- vdev_property_add("VDEV_ATA_FEATURE_SET_HPA", "1" );
- vdev_property_add("VDEV_ATA_FEATURE_SET_HPA_ENABLED", (id.cfs_enable_1 & (1<<10)) ? "1" : "0");
-
+ memset (serial_buf, 0, 100);
+
+ snprintf (serial_buf, 99, "%s_%s", model, serial);
+
+ vdev_property_add ("VDEV_ATA_SERIAL", serial_buf);
+ vdev_property_add ("VDEV_ATA_SERIAL_SHORT", serial);
+
+ }
+ else
+ {
+
+ vdev_property_add ("VDEV_ATA_SERIAL", model);
+ }
+
+ if (id.command_set_1 & (1 << 5))
+ {
+
+ vdev_property_add ("VDEV_ATA_WRITE_CACHE", "1");
+ vdev_property_add ("VDEV_ATA_WRITE_CACHE_ENABLED",
+ (id.cfs_enable_1 & (1 << 5)) ? "1" : "0");
+ }
+ if (id.command_set_1 & (1 << 10))
+ {
+
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_HPA", "1");
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_HPA_ENABLED",
+ (id.cfs_enable_1 & (1 << 10)) ? "1" : "0");
+
/*
- * TODO: use the READ NATIVE MAX ADDRESS command to get the native max address
- * so it is easy to check whether the protected area is in use.
- */
- }
- if (id.command_set_1 & (1<<3)) {
-
- vdev_property_add("VDEV_ATA_FEATURE_SET_PM", "1" );
- vdev_property_add("VDEV_ATA_FEATURE_SET_PM_ENABLED", (id.cfs_enable_1 & (1<<3)) ? "1" : "0");
- }
- if (id.command_set_1 & (1<<1)) {
-
+ * TODO: use the READ NATIVE MAX ADDRESS command to get the native max address
+ * so it is easy to check whether the protected area is in use.
+ */
+ }
+ if (id.command_set_1 & (1 << 3))
+ {
+
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_PM", "1");
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_PM_ENABLED",
+ (id.cfs_enable_1 & (1 << 3)) ? "1" : "0");
+ }
+ if (id.command_set_1 & (1 << 1))
+ {
+
char buf[100];
- memset( buf, 0, 100 );
- snprintf( buf, 99, "%d", id.trseuc * 2 );
-
- vdev_property_add("VDEV_ATA_FEATURE_SET_SECURITY", "1" );
- vdev_property_add("VDEV_ATA_FEATURE_SET_SECURITY_ENABLED", (id.cfs_enable_1 & (1<<1)) ? "1" : "0");
- vdev_property_add("VDEV_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN", buf );
-
- if ((id.cfs_enable_1 & (1<<1))) /* enabled */ {
-
- if (id.dlf & (1<<8)) {
-
- vdev_property_add( "VDEV_ATA_FEATURE_SET_SECURITY_LEVEL", "maximum" );
- }
- else {
-
- vdev_property_add("VDEV_ATA_FEATURE_SET_SECURITY_LEVEL", "high" );
- }
- }
- if (id.dlf & (1<<5)) {
-
- memset( buf, 0, 100 );
- snprintf( buf, 99, "%d", id.trsEuc * 2 );
-
- vdev_property_add("VDEV_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN", buf );
- }
- if (id.dlf & (1<<4)) {
-
- vdev_property_add("VDEV_ATA_FEATURE_SET_SECURITY_EXPIRE", "1" );
- }
- if (id.dlf & (1<<3)) {
-
- vdev_property_add("VDEV_ATA_FEATURE_SET_SECURITY_FROZEN", "1" );
- }
- if (id.dlf & (1<<2)) {
-
- vdev_property_add("VDEV_ATA_FEATURE_SET_SECURITY_LEVEL", "1" );
- }
- }
- if (id.command_set_1 & (1<<0)) {
-
- vdev_property_add("VDEV_ATA_FEATURE_SET_SMART", "1" );
- vdev_property_add("VDEV_ATA_FEATURE_SET_SMART_ENABLED", (id.cfs_enable_1 & (1<<0)) ? "1" : "0");
- }
- if (id.command_set_2 & (1<<9)) {
-
+ memset (buf, 0, 100);
+ snprintf (buf, 99, "%d", id.trseuc * 2);
+
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_SECURITY", "1");
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_SECURITY_ENABLED",
+ (id.cfs_enable_1 & (1 << 1)) ? "1" : "0");
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN", buf);
+
+ if ((id.cfs_enable_1 & (1 << 1)))
+ { /* enabled */
+
+ if (id.dlf & (1 << 8))
+ {
+
+ vdev_property_add
+ ("VDEV_ATA_FEATURE_SET_SECURITY_LEVEL", "maximum");
+ }
+ else
+ {
+
+ vdev_property_add
+ ("VDEV_ATA_FEATURE_SET_SECURITY_LEVEL", "high");
+ }
+ }
+ if (id.dlf & (1 << 5))
+ {
+
+ memset (buf, 0, 100);
+ snprintf (buf, 99, "%d", id.trsEuc * 2);
+
+ vdev_property_add
+ ("VDEV_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN", buf);
+ }
+ if (id.dlf & (1 << 4))
+ {
+
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_SECURITY_EXPIRE", "1");
+ }
+ if (id.dlf & (1 << 3))
+ {
+
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_SECURITY_FROZEN", "1");
+ }
+ if (id.dlf & (1 << 2))
+ {
+
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_SECURITY_LEVEL", "1");
+ }
+ }
+ if (id.command_set_1 & (1 << 0))
+ {
+
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_SMART", "1");
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_SMART_ENABLED",
+ (id.cfs_enable_1 & (1 << 0)) ? "1" : "0");
+ }
+ if (id.command_set_2 & (1 << 9))
+ {
+
char aam_buf[100];
char aam_cur_buf[100];
-
- memset( aam_buf, 0, 100 );
- memset( aam_cur_buf, 0, 100 );
-
- snprintf( aam_buf, 99, "%d", id.acoustic >> 8 );
- snprintf( aam_cur_buf, 99, "%d", id.acoustic & 0xff );
-
- vdev_property_add("VDEV_ATA_FEATURE_SET_AAM", "1" );
- vdev_property_add("VDEV_ATA_FEATURE_SET_AAM_ENABLED", (id.cfs_enable_2 & (1<<9)) ? "1" : "0");
- vdev_property_add("VDEV_ATA_FEATURE_SET_AAM_VENDOR_RECOMMENDED_VALUE", aam_buf );
- vdev_property_add("VDEV_ATA_FEATURE_SET_AAM_CURRENT_VALUE", aam_cur_buf );
- }
- if (id.command_set_2 & (1<<5)) {
-
- vdev_property_add("VDEV_ATA_FEATURE_SET_PUIS", "1" );
- vdev_property_add("VDEV_ATA_FEATURE_SET_PUIS_ENABLED", (id.cfs_enable_2 & (1<<5)) ? "1" : "0");
- }
- if (id.command_set_2 & (1<<3)) {
-
- vdev_property_add("VDEV_ATA_FEATURE_SET_APM", "1" );
- vdev_property_add("VDEV_ATA_FEATURE_SET_APM_ENABLED", (id.cfs_enable_2 & (1<<3)) ? "1" : "0");
-
- if ((id.cfs_enable_2 & (1<<3))) {
-
- char apm_cur_buf[100];
-
- memset( apm_cur_buf, 0, 100 );
-
- snprintf( apm_cur_buf, 99, "%d", id.CurAPMvalues & 0xff );
-
- vdev_property_add("VDEV_ATA_FEATURE_SET_APM_CURRENT_VALUE", apm_cur_buf );
- }
- }
- if (id.command_set_2 & (1<<0)) {
-
- vdev_property_add("VDEV_ATA_DOWNLOAD_MICROCODE", "1" );
- }
-
- /*
+
+ memset (aam_buf, 0, 100);
+ memset (aam_cur_buf, 0, 100);
+
+ snprintf (aam_buf, 99, "%d", id.acoustic >> 8);
+ snprintf (aam_cur_buf, 99, "%d", id.acoustic & 0xff);
+
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_AAM", "1");
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_AAM_ENABLED",
+ (id.cfs_enable_2 & (1 << 9)) ? "1" : "0");
+ vdev_property_add
+ ("VDEV_ATA_FEATURE_SET_AAM_VENDOR_RECOMMENDED_VALUE", aam_buf);
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_AAM_CURRENT_VALUE",
+ aam_cur_buf);
+ }
+ if (id.command_set_2 & (1 << 5))
+ {
+
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_PUIS", "1");
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_PUIS_ENABLED",
+ (id.cfs_enable_2 & (1 << 5)) ? "1" : "0");
+ }
+ if (id.command_set_2 & (1 << 3))
+ {
+
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_APM", "1");
+ vdev_property_add ("VDEV_ATA_FEATURE_SET_APM_ENABLED",
+ (id.cfs_enable_2 & (1 << 3)) ? "1" : "0");
+
+ if ((id.cfs_enable_2 & (1 << 3)))
+ {
+
+ char apm_cur_buf[100];
+
+ memset (apm_cur_buf, 0, 100);
+
+ snprintf (apm_cur_buf, 99, "%d", id.CurAPMvalues & 0xff);
+
+ vdev_property_add
+ ("VDEV_ATA_FEATURE_SET_APM_CURRENT_VALUE", apm_cur_buf);
+ }
+ }
+ if (id.command_set_2 & (1 << 0))
+ {
+
+ vdev_property_add ("VDEV_ATA_DOWNLOAD_MICROCODE", "1");
+ }
+
+ /*
* Word 76 indicates the capabilities of a SATA device. A PATA device shall set
* word 76 to 0000h or FFFFh. If word 76 is set to 0000h or FFFFh, then
* the device does not claim compliance with the Serial ATA specification and words
* 76 through 79 are not valid and shall be ignored.
*/
- word = identify.wyde[76];
- if (word != 0x0000 && word != 0xffff) {
-
- vdev_property_add("VDEV_ATA_SATA", "1" );
+ word = identify.wyde[76];
+ if (word != 0x0000 && word != 0xffff)
+ {
+
+ vdev_property_add ("VDEV_ATA_SATA", "1");
/*
- * If bit 2 of word 76 is set to one, then the device supports the Gen2
- * signaling rate of 3.0 Gb/s (see SATA 2.6).
- *
- * If bit 1 of word 76 is set to one, then the device supports the Gen1
- * signaling rate of 1.5 Gb/s (see SATA 2.6).
- */
- if (word & (1<<2)) {
-
- vdev_property_add("VDEV_ATA_SATA_SIGNAL_RATE_GEN2", "1" );
- }
- if (word & (1<<1)) {
-
- vdev_property_add("VDEV_ATA_SATA_SIGNAL_RATE_GEN1", "1" );
- }
- }
-
- /* Word 217 indicates the nominal media rotation rate of the device */
- word = identify.wyde[217];
- if (word == 0x0001) {
-
- vdev_property_add("VDEV_ATA_ROTATION_RATE_RPM", "0" );
- }
- else if (word >= 0x0401 && word <= 0xfffe) {
-
+ * If bit 2 of word 76 is set to one, then the device supports the Gen2
+ * signaling rate of 3.0 Gb/s (see SATA 2.6).
+ *
+ * If bit 1 of word 76 is set to one, then the device supports the Gen1
+ * signaling rate of 1.5 Gb/s (see SATA 2.6).
+ */
+ if (word & (1 << 2))
+ {
+
+ vdev_property_add ("VDEV_ATA_SATA_SIGNAL_RATE_GEN2", "1");
+ }
+ if (word & (1 << 1))
+ {
+
+ vdev_property_add ("VDEV_ATA_SATA_SIGNAL_RATE_GEN1", "1");
+ }
+ }
+
+ /* Word 217 indicates the nominal media rotation rate of the device */
+ word = identify.wyde[217];
+ if (word == 0x0001)
+ {
+
+ vdev_property_add ("VDEV_ATA_ROTATION_RATE_RPM", "0");
+ }
+ else if (word >= 0x0401 && word <= 0xfffe)
+ {
+
char rpm_buf[100];
-
- memset( rpm_buf, 0, 100 );
-
- snprintf( rpm_buf, 99, "%d", word );
-
- vdev_property_add("VDEV_ATA_ROTATION_RATE_RPM", rpm_buf );
- }
-
- /*
+
+ memset (rpm_buf, 0, 100);
+
+ snprintf (rpm_buf, 99, "%d", word);
+
+ vdev_property_add ("VDEV_ATA_ROTATION_RATE_RPM", rpm_buf);
+ }
+
+ /*
* Words 108-111 contain a mandatory World Wide Name (WWN) in the NAA IEEE Registered identifier
* format. Word 108 bits (15:12) shall contain 5h, indicating that the naming authority is IEEE.
* All other values are reserved.
*/
- word = identify.wyde[108];
- if ((word & 0xf000) == 0x5000) {
-
+ word = identify.wyde[108];
+ if ((word & 0xf000) == 0x5000)
+ {
+
char wwn_buf[100];
-
- memset( wwn_buf, 0, 100 );
-
- snprintf( wwn_buf, 99, "0x%04x%04x%04x%04x", identify.wyde[108], identify.wyde[109], identify.wyde[110], identify.wyde[111]);
-
- vdev_property_add("VDEV_ATA_WWN", wwn_buf );
- vdev_property_add("VDEV_ATA_WWN_WITH_EXTENSION", wwn_buf );
- }
-
- /* from Linux's include/linux/ata.h */
- if (identify.wyde[0] == 0x848a ||
- identify.wyde[0] == 0x844a ||
- (identify.wyde[83] & 0xc004) == 0x4004) {
-
- vdev_property_add("VDEV_ATA_CFA", "1" );
- }
-
- vdev_property_print();
- vdev_property_free_all();
-
- return 0;
+
+ memset (wwn_buf, 0, 100);
+
+ snprintf (wwn_buf, 99, "0x%04x%04x%04x%04x", identify.wyde[108],
+ identify.wyde[109], identify.wyde[110], identify.wyde[111]);
+
+ vdev_property_add ("VDEV_ATA_WWN", wwn_buf);
+ vdev_property_add ("VDEV_ATA_WWN_WITH_EXTENSION", wwn_buf);
+ }
+
+ /* from Linux's include/linux/ata.h */
+ if (identify.wyde[0] == 0x848a ||
+ identify.wyde[0] == 0x844a || (identify.wyde[83] & 0xc004) == 0x4004)
+ {
+
+ vdev_property_add ("VDEV_ATA_CFA", "1");
+ }
+
+ vdev_property_print ();
+ vdev_property_free_all ();
+
+ return 0;
}
diff --git a/vdevd/helpers/LINUX/stat_bus.c b/vdevd/helpers/LINUX/stat_bus.c
index ca7c12f..f4d7429 100644
--- a/vdevd/helpers/LINUX/stat_bus.c
+++ b/vdevd/helpers/LINUX/stat_bus.c
@@ -22,146 +22,178 @@
// determine what kind of busses we're on
#include "common.h"
-void usage( char const* progname ) {
-
- fprintf(stderr, "[ERROR] %s: Usage: %s /sysfs/path/to/device\n", progname, progname );
- exit(1);
+void
+usage (char const *progname)
+{
+
+ fprintf (stderr, "[ERROR] %s: Usage: %s /sysfs/path/to/device\n",
+ progname, progname);
+ exit (1);
}
// lop off the child of a directory
// return 0 on success
// return -ENOENT if there is no child to remove
-int remove_child( char* path ) {
+int
+remove_child (char *path)
+{
+
+ char *delim = NULL;
- char* delim = NULL;
-
- delim = strrchr( path, '/' );
- if( delim == NULL || delim == path ) {
+ delim = strrchr (path, '/');
+ if (delim == NULL || delim == path)
+ {
return -ENOENT;
- }
-
- while( *delim == '/' && delim != path ) {
+ }
+
+ while (*delim == '/' && delim != path)
+ {
*delim = '\0';
delim--;
- }
-
- return 0;
+ }
+
+ return 0;
}
-
-int main( int argc, char** argv ) {
-
- if( argc != 2 ) {
- usage( argv[0] );
- }
-
- char* next_bus = NULL;
- char subsystem_list[ 4097 ];
- char subsystem_list_uniq[ 4097 ];
- char* delim = NULL;
- char* subsystem_buf = (char*)calloc( strlen(argv[1]) + strlen("/subsystem") + 1, 1 );
- char readlink_buf[ 4097 ];
- int rc = 0;
- struct stat sb;
-
- if( subsystem_buf == NULL ) {
- exit(1);
- }
-
- next_bus = argv[1];
- memset( subsystem_list, 0, 4097 );
- memset( subsystem_list_uniq, 0, 4097 );
-
- // directory must exist
- rc = stat( next_bus, &sb );
- if( rc != 0 ) {
- exit(1);
- }
-
- while( 1 ) {
-
+
+int
+main (int argc, char **argv)
+{
+
+ if (argc != 2)
+ {
+ usage (argv[0]);
+ }
+
+ char *next_bus = NULL;
+ char subsystem_list[4097];
+ char subsystem_list_uniq[4097];
+ char *delim = NULL;
+ char *subsystem_buf =
+ (char *) calloc (strlen (argv[1]) + strlen ("/subsystem") + 1, 1);
+ char readlink_buf[4097];
+ int rc = 0;
+ struct stat sb;
+
+ if (subsystem_buf == NULL)
+ {
+ exit (1);
+ }
+
+ next_bus = argv[1];
+ memset (subsystem_list, 0, 4097);
+ memset (subsystem_list_uniq, 0, 4097);
+
+ // directory must exist
+ rc = stat (next_bus, &sb);
+ if (rc != 0)
+ {
+ exit (1);
+ }
+
+ while (1)
+ {
+
// what's the subsystem here?
- sprintf( subsystem_buf, "%s/subsystem", next_bus );
-
- rc = lstat( subsystem_buf, &sb );
- if( rc != 0 ) {
-
- rc = remove_child( next_bus );
- if( rc != 0 ) {
- break;
- }
- else {
- continue;
- }
- }
-
- if( !S_ISLNK( sb.st_mode ) ) {
-
- rc = remove_child( next_bus );
- if( rc != 0 ) {
- break;
- }
- else {
- continue;
- }
- }
-
- memset( readlink_buf, 0, 4097 );
-
- rc = readlink( subsystem_buf, readlink_buf, 4096 );
- if( rc < 0 ) {
-
- rc = remove_child( next_bus );
- if( rc != 0 ) {
- break;
- }
- else {
- continue;
- }
- }
-
- delim = strrchr( readlink_buf, '/' );
- if( delim == NULL ) {
-
- rc = remove_child( next_bus );
- if( rc != 0 ) {
- break;
- }
- else {
- continue;
- }
- }
-
+ sprintf (subsystem_buf, "%s/subsystem", next_bus);
+
+ rc = lstat (subsystem_buf, &sb);
+ if (rc != 0)
+ {
+
+ rc = remove_child (next_bus);
+ if (rc != 0)
+ {
+ break;
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ if (!S_ISLNK (sb.st_mode))
+ {
+
+ rc = remove_child (next_bus);
+ if (rc != 0)
+ {
+ break;
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ memset (readlink_buf, 0, 4097);
+
+ rc = readlink (subsystem_buf, readlink_buf, 4096);
+ if (rc < 0)
+ {
+
+ rc = remove_child (next_bus);
+ if (rc != 0)
+ {
+ break;
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ delim = strrchr (readlink_buf, '/');
+ if (delim == NULL)
+ {
+
+ rc = remove_child (next_bus);
+ if (rc != 0)
+ {
+ break;
+ }
+ else
+ {
+ continue;
+ }
+ }
// delim + 1 is the subsystem name
- if( subsystem_list[0] != 0 ) {
- strncat( subsystem_list, ",", 4096 - strlen(subsystem_list) - 1 );
- }
- strncat( subsystem_list, delim + 1, 4096 - strlen(subsystem_list) - 1 );
-
- if( strstr( subsystem_list_uniq, delim + 1 ) == NULL ) {
-
- // haven't seen this subsystem name before...
- if( subsystem_list_uniq[0] != 0 ) {
- strncat( subsystem_list_uniq, ",", 4096 - strlen(subsystem_list_uniq) - 1 );
- }
- strncat( subsystem_list_uniq, delim + 1, 4096 - strlen(subsystem_list_uniq) - 1 );
- }
-
- rc = remove_child( next_bus );
- if( rc != 0 ) {
- break;
- }
- else {
- continue;
- }
- }
-
- free( subsystem_buf );
-
- vdev_property_add( "VDEV_BUS_SUBSYSTEMS", subsystem_list );
- vdev_property_add( "VDEV_BUS_SUBSYSTEMS_UNIQ", subsystem_list_uniq );
-
- vdev_property_print();
- vdev_property_free_all();
-
- exit(0);
+ if (subsystem_list[0] != 0)
+ {
+ strncat (subsystem_list, ",", 4096 - strlen (subsystem_list) - 1);
+ }
+ strncat (subsystem_list, delim + 1, 4096 - strlen (subsystem_list) - 1);
+
+ if (strstr (subsystem_list_uniq, delim + 1) == NULL)
+ {
+
+ // haven't seen this subsystem name before...
+ if (subsystem_list_uniq[0] != 0)
+ {
+ strncat (subsystem_list_uniq, ",",
+ 4096 - strlen (subsystem_list_uniq) - 1);
+ }
+ strncat (subsystem_list_uniq, delim + 1,
+ 4096 - strlen (subsystem_list_uniq) - 1);
+ }
+
+ rc = remove_child (next_bus);
+ if (rc != 0)
+ {
+ break;
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ free (subsystem_buf);
+
+ vdev_property_add ("VDEV_BUS_SUBSYSTEMS", subsystem_list);
+ vdev_property_add ("VDEV_BUS_SUBSYSTEMS_UNIQ", subsystem_list_uniq);
+
+ vdev_property_print ();
+ vdev_property_free_all ();
+
+ exit (0);
}
diff --git a/vdevd/helpers/LINUX/stat_input.c b/vdevd/helpers/LINUX/stat_input.c
index 7b12dab..4c63e7f 100644
--- a/vdevd/helpers/LINUX/stat_input.c
+++ b/vdevd/helpers/LINUX/stat_input.c
@@ -32,7 +32,6 @@
* along with this program. If not, see .
*/
-
#include "common.h"
#include
#include
@@ -51,390 +50,459 @@
int g_input_class = 0;
-static inline int abs_size_mm(const struct input_absinfo *absinfo) {
- /* Resolution is defined to be in units/mm for ABS_X/Y */
- return (absinfo->maximum - absinfo->minimum) / absinfo->resolution;
+static inline int
+abs_size_mm (const struct input_absinfo *absinfo)
+{
+ /* Resolution is defined to be in units/mm for ABS_X/Y */
+ return (absinfo->maximum - absinfo->minimum) / absinfo->resolution;
}
-static void extract_input_resolution( const char *devpath ) {
-
- char width[50], height[50];
- struct input_absinfo xabsinfo = {}, yabsinfo = {};
-
- int rc = 0;
- int fd = -1;
+static void
+extract_input_resolution (const char *devpath)
+{
+
+ char width[50], height[50];
+ struct input_absinfo xabsinfo = { }, yabsinfo =
+ {
+ };
+
+ int rc = 0;
+ int fd = -1;
- fd = open(devpath, O_RDONLY|O_CLOEXEC);
- if (fd < 0) {
+ fd = open (devpath, O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
+ {
rc = -errno;
- log_debug("failed to open '%s', errno = %d", devpath, rc );
+ log_debug ("failed to open '%s', errno = %d", devpath, rc);
return;
- }
+ }
- if (ioctl(fd, EVIOCGABS(ABS_X), &xabsinfo) < 0 || ioctl(fd, EVIOCGABS(ABS_Y), &yabsinfo) < 0) {
-
- close( fd );
+ if (ioctl (fd, EVIOCGABS (ABS_X), &xabsinfo) < 0
+ || ioctl (fd, EVIOCGABS (ABS_Y), &yabsinfo) < 0)
+ {
+
+ close (fd);
return;
- }
+ }
+
+ if (xabsinfo.resolution <= 0 || yabsinfo.resolution <= 0)
+ {
- if (xabsinfo.resolution <= 0 || yabsinfo.resolution <= 0) {
-
- close( fd );
+ close (fd);
return;
- }
+ }
+
+ snprintf (width, sizeof (width), "%d", abs_size_mm (&xabsinfo));
+ snprintf (height, sizeof (height), "%d", abs_size_mm (&yabsinfo));
- snprintf(width, sizeof(width), "%d", abs_size_mm(&xabsinfo));
- snprintf(height, sizeof(height), "%d", abs_size_mm(&yabsinfo));
+ vdev_property_add ("VDEV_INPUT_WIDTH_MM", width);
+ vdev_property_add ("VDEV_INPUT_HEIGHT_MM", height);
- vdev_property_add( "VDEV_INPUT_WIDTH_MM", width );
- vdev_property_add( "VDEV_INPUT_HEIGHT_MM", height );
-
- close( fd );
+ close (fd);
}
/*
* Read a capability attribute and return bitmask.
* @param bitmask: Output array which has a length of bitmask_len
*/
-static void get_cap_mask( char const* sysfs_cap_path, unsigned long *bitmask, size_t bitmask_len) {
-
- char text[4096];
- unsigned i;
- char* word;
- unsigned long val;
- int rc = 0;
-
- memset( text, 0, 4096 );
-
- int fd = open( sysfs_cap_path, O_RDONLY );
- if( fd < 0 ) {
+static void
+get_cap_mask (char const *sysfs_cap_path, unsigned long *bitmask,
+ size_t bitmask_len)
+{
+
+ char text[4096];
+ unsigned i;
+ char *word;
+ unsigned long val;
+ int rc = 0;
+
+ memset (text, 0, 4096);
+
+ int fd = open (sysfs_cap_path, O_RDONLY);
+ if (fd < 0)
+ {
return;
- }
-
- rc = vdev_read_uninterrupted( fd, text, 4096 );
- close( fd );
-
- if( rc < 0 ) {
-
- log_debug("read('%s') errno = %d\n", sysfs_cap_path, rc );
+ }
+
+ rc = vdev_read_uninterrupted (fd, text, 4096);
+ close (fd);
+
+ if (rc < 0)
+ {
+
+ log_debug ("read('%s') errno = %d\n", sysfs_cap_path, rc);
return;
- }
-
- memset( bitmask, 0, bitmask_len * sizeof(unsigned long) );
-
- i = 0;
-
- while ((word = strrchr(text, ' ')) != NULL) {
-
- val = strtoul (word+1, NULL, 16);
- if (i < bitmask_len ) {
- bitmask[i] = val;
- }
- else {
- log_debug("ignoring %s block %lX which is larger than maximum length %zu", sysfs_cap_path, val, bitmask_len);
- }
+ }
+
+ memset (bitmask, 0, bitmask_len * sizeof (unsigned long));
+
+ i = 0;
+
+ while ((word = strrchr (text, ' ')) != NULL)
+ {
+
+ val = strtoul (word + 1, NULL, 16);
+ if (i < bitmask_len)
+ {
+ bitmask[i] = val;
+ }
+ else
+ {
+ log_debug
+ ("ignoring %s block %lX which is larger than maximum length %zu",
+ sysfs_cap_path, val, bitmask_len);
+ }
*word = '\0';
++i;
- }
- val = strtoul (text, NULL, 16);
- if (i < bitmask_len) {
+ }
+ val = strtoul (text, NULL, 16);
+ if (i < bitmask_len)
+ {
bitmask[i] = val;
- }
- else {
- log_debug("ignoring %s block %lX which is larger than maximum length %zu", sysfs_cap_path, val, bitmask_len);
- }
-
- log_debug("Bitmask path: %s, length: %zu, Text: '%s'", sysfs_cap_path, bitmask_len, text );
- for( unsigned int i = 0; i < bitmask_len; i++ ) {
- log_debug("Bitmask[%d] = %lX", i, bitmask[i]);
- }
+ }
+ else
+ {
+ log_debug
+ ("ignoring %s block %lX which is larger than maximum length %zu",
+ sysfs_cap_path, val, bitmask_len);
+ }
+
+ log_debug ("Bitmask path: %s, length: %zu, Text: '%s'", sysfs_cap_path,
+ bitmask_len, text);
+ for (unsigned int i = 0; i < bitmask_len; i++)
+ {
+ log_debug ("Bitmask[%d] = %lX", i, bitmask[i]);
+ }
}
/* pointer devices */
-static void test_pointers (const unsigned long* bitmask_ev,
- const unsigned long* bitmask_abs,
- const unsigned long* bitmask_key,
- const unsigned long* bitmask_rel ) {
- int is_mouse = 0;
- int is_touchpad = 0;
-
- if (!test_bit (EV_KEY, bitmask_ev)) {
+static void
+test_pointers (const unsigned long *bitmask_ev,
+ const unsigned long *bitmask_abs,
+ const unsigned long *bitmask_key,
+ const unsigned long *bitmask_rel)
+{
+ int is_mouse = 0;
+ int is_touchpad = 0;
+
+ if (!test_bit (EV_KEY, bitmask_ev))
+ {
if (test_bit (EV_ABS, bitmask_ev) &&
- test_bit (ABS_X, bitmask_abs) &&
- test_bit (ABS_Y, bitmask_abs) &&
- test_bit (ABS_Z, bitmask_abs)) {
-
- vdev_property_add( "VDEV_INPUT_ACCELEROMETER", "1" );
- }
+ test_bit (ABS_X, bitmask_abs) &&
+ test_bit (ABS_Y, bitmask_abs) && test_bit (ABS_Z, bitmask_abs))
+ {
+
+ vdev_property_add ("VDEV_INPUT_ACCELEROMETER", "1");
+ }
return;
- }
+ }
- if (test_bit (EV_ABS, bitmask_ev) && test_bit (ABS_X, bitmask_abs) && test_bit (ABS_Y, bitmask_abs)) {
+ if (test_bit (EV_ABS, bitmask_ev) && test_bit (ABS_X, bitmask_abs)
+ && test_bit (ABS_Y, bitmask_abs))
+ {
+
+ if (test_bit (BTN_STYLUS, bitmask_key)
+ || test_bit (BTN_TOOL_PEN, bitmask_key))
+ {
+
+ vdev_property_add ("VDEV_INPUT_TABLET", "1");
+
+ g_input_class = VDEV_INPUT_CLASS_MOUSE;
+ }
+
+ else if (test_bit (BTN_TOOL_FINGER, bitmask_key)
+ && !test_bit (BTN_TOOL_PEN, bitmask_key))
+ {
+
+ is_touchpad = 1;
+ }
+
+ else if (test_bit (BTN_MOUSE, bitmask_key))
+ {
+ /* This path is taken by VMware's USB mouse, which has
+ * absolute axes, but no touch/pressure button. */
+
+ is_mouse = 1;
+ }
+
+ else if (test_bit (BTN_TOUCH, bitmask_key))
+ {
+
+ vdev_property_add ("VDEV_INPUT_TOUCHSCREEN", "1");
+
+ g_input_class = VDEV_INPUT_CLASS_MOUSE;
+ }
- if (test_bit (BTN_STYLUS, bitmask_key) || test_bit (BTN_TOOL_PEN, bitmask_key)) {
-
- vdev_property_add( "VDEV_INPUT_TABLET", "1" );
-
- g_input_class = VDEV_INPUT_CLASS_MOUSE;
- }
-
- else if (test_bit (BTN_TOOL_FINGER, bitmask_key) && !test_bit (BTN_TOOL_PEN, bitmask_key)) {
-
- is_touchpad = 1;
- }
-
- else if (test_bit (BTN_MOUSE, bitmask_key)) {
- /* This path is taken by VMware's USB mouse, which has
- * absolute axes, but no touch/pressure button. */
-
- is_mouse = 1;
- }
-
- else if (test_bit (BTN_TOUCH, bitmask_key)) {
-
- vdev_property_add( "VDEV_INPUT_TOUCHSCREEN", "1" );
-
- g_input_class = VDEV_INPUT_CLASS_MOUSE;
- }
-
/* joysticks don't necessarily have to have buttons; e. g.
- * rudders/pedals are joystick-like, but buttonless; they have
- * other fancy axes */
+ * rudders/pedals are joystick-like, but buttonless; they have
+ * other fancy axes */
else if (test_bit (BTN_TRIGGER, bitmask_key) ||
- test_bit (BTN_A, bitmask_key) ||
- test_bit (BTN_1, bitmask_key) ||
- test_bit (ABS_RX, bitmask_abs) ||
- test_bit (ABS_RY, bitmask_abs) ||
- test_bit (ABS_RZ, bitmask_abs) ||
- test_bit (ABS_THROTTLE, bitmask_abs) ||
- test_bit (ABS_RUDDER, bitmask_abs) ||
- test_bit (ABS_WHEEL, bitmask_abs) ||
- test_bit (ABS_GAS, bitmask_abs) ||
- test_bit (ABS_BRAKE, bitmask_abs)) {
-
- vdev_property_add( "VDEV_INPUT_JOYSTICK", "1" );
-
- g_input_class = VDEV_INPUT_CLASS_JOYSTICK;
- }
- }
+ test_bit (BTN_A, bitmask_key) ||
+ test_bit (BTN_1, bitmask_key) ||
+ test_bit (ABS_RX, bitmask_abs) ||
+ test_bit (ABS_RY, bitmask_abs) ||
+ test_bit (ABS_RZ, bitmask_abs) ||
+ test_bit (ABS_THROTTLE, bitmask_abs) ||
+ test_bit (ABS_RUDDER, bitmask_abs) ||
+ test_bit (ABS_WHEEL, bitmask_abs) ||
+ test_bit (ABS_GAS, bitmask_abs) ||
+ test_bit (ABS_BRAKE, bitmask_abs))
+ {
+
+ vdev_property_add ("VDEV_INPUT_JOYSTICK", "1");
+
+ g_input_class = VDEV_INPUT_CLASS_JOYSTICK;
+ }
+ }
- if (test_bit (EV_REL, bitmask_ev) &&
+ if (test_bit (EV_REL, bitmask_ev) &&
test_bit (REL_X, bitmask_rel) && test_bit (REL_Y, bitmask_rel) &&
- test_bit (BTN_MOUSE, bitmask_key)) {
-
+ test_bit (BTN_MOUSE, bitmask_key))
+ {
+
is_mouse = 1;
- }
-
- if (is_mouse) {
-
- vdev_property_add( "VDEV_INPUT_MOUSE", "1" );
-
+ }
+
+ if (is_mouse)
+ {
+
+ vdev_property_add ("VDEV_INPUT_MOUSE", "1");
+
g_input_class = VDEV_INPUT_CLASS_MOUSE;
- }
-
- if( is_touchpad ) {
-
- vdev_property_add( "VDEV_INPUT_TOUCHPAD", "1" );
-
+ }
+
+ if (is_touchpad)
+ {
+
+ vdev_property_add ("VDEV_INPUT_TOUCHPAD", "1");
+
g_input_class = VDEV_INPUT_CLASS_MOUSE;
- }
+ }
}
/* key like devices */
-static void test_key (const unsigned long* bitmask_ev,
- const unsigned long* bitmask_key ) {
- unsigned i;
- unsigned long found;
- unsigned long mask;
-
- /* do we have any KEY_* capability? */
- if (!test_bit (EV_KEY, bitmask_ev)) {
- log_debug("%s", "test_key: no EV_KEY capability");
+static void
+test_key (const unsigned long *bitmask_ev, const unsigned long *bitmask_key)
+{
+ unsigned i;
+ unsigned long found;
+ unsigned long mask;
+
+ /* do we have any KEY_* capability? */
+ if (!test_bit (EV_KEY, bitmask_ev))
+ {
+ log_debug ("%s", "test_key: no EV_KEY capability");
return;
- }
+ }
- /* only consider KEY_* here, not BTN_* */
- found = 0;
- for (i = 0; i < BTN_MISC/BITS_PER_LONG; ++i) {
+ /* only consider KEY_* here, not BTN_* */
+ found = 0;
+ for (i = 0; i < BTN_MISC / BITS_PER_LONG; ++i)
+ {
found |= bitmask_key[i];
- log_debug("test_key: checking bit block %lu for any keys; found=%i", (unsigned long)i*BITS_PER_LONG, found > 0);
- }
-
- /* If there are no keys in the lower block, check the higher block */
- if (!found) {
- for (i = KEY_OK; i < BTN_TRIGGER_HAPPY; ++i) {
- if (test_bit (i, bitmask_key)) {
- log_debug("test_key: Found key %x in high block", i);
- found = 1;
- break;
- }
- }
- }
-
- if (found > 0) {
-
- vdev_property_add( "VDEV_INPUT_KEY", "1" );
- }
-
- /* the first 32 bits are ESC, numbers, and Q to D; if we have all of
+ log_debug
+ ("test_key: checking bit block %lu for any keys; found=%i",
+ (unsigned long) i * BITS_PER_LONG, found > 0);
+ }
+
+ /* If there are no keys in the lower block, check the higher block */
+ if (!found)
+ {
+ for (i = KEY_OK; i < BTN_TRIGGER_HAPPY; ++i)
+ {
+ if (test_bit (i, bitmask_key))
+ {
+ log_debug ("test_key: Found key %x in high block", i);
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if (found > 0)
+ {
+
+ vdev_property_add ("VDEV_INPUT_KEY", "1");
+ }
+
+ /* the first 32 bits are ESC, numbers, and Q to D; if we have all of
* those, consider it a full keyboard; do not test KEY_RESERVED, though */
- mask = 0xFFFFFFFE;
- if ((bitmask_key[0] & mask) == mask) {
-
- vdev_property_add( "VDEV_INPUT_KEYBOARD", "1" );
-
+ mask = 0xFFFFFFFE;
+ if ((bitmask_key[0] & mask) == mask)
+ {
+
+ vdev_property_add ("VDEV_INPUT_KEYBOARD", "1");
+
g_input_class = VDEV_INPUT_CLASS_KBD;
- }
+ }
}
+void
+usage (char const *program_name)
+{
+
+ fprintf (stderr, "[ERROR] %s: Usage: %s /path/to/input/device/file\n",
+ program_name, program_name);
-void usage(char const* program_name ) {
-
- fprintf(stderr, "[ERROR] %s: Usage: %s /path/to/input/device/file\n", program_name, program_name);
-
}
// entry point
// TODO: support using a sysfs device path directly
-int main( int argc, char** argv ) {
-
- // look for the character device with VDEV_MAJOR and VDEV_MINOR
- char capabilities_path[4096];
- char full_sysfs_path[4096];
- char subsystem[4096];
- char sysdev_path[4096];
-
- unsigned long bitmask_ev[NBITS(EV_MAX)];
- unsigned long bitmask_abs[NBITS(ABS_MAX)];
- unsigned long bitmask_key[NBITS(KEY_MAX)];
- unsigned long bitmask_rel[NBITS(REL_MAX)];
-
- struct stat sb;
- int rc = 0;
- char major[20];
- char minor[20];
- char* basename = NULL;
-
- if( argc != 2 ) {
- usage( argv[0] );
- exit(1);
- }
-
- rc = stat( argv[1], &sb );
- if( rc != 0 ) {
-
+int
+main (int argc, char **argv)
+{
+
+ // look for the character device with VDEV_MAJOR and VDEV_MINOR
+ char capabilities_path[4096];
+ char full_sysfs_path[4096];
+ char subsystem[4096];
+ char sysdev_path[4096];
+
+ unsigned long bitmask_ev[NBITS (EV_MAX)];
+ unsigned long bitmask_abs[NBITS (ABS_MAX)];
+ unsigned long bitmask_key[NBITS (KEY_MAX)];
+ unsigned long bitmask_rel[NBITS (REL_MAX)];
+
+ struct stat sb;
+ int rc = 0;
+ char major[20];
+ char minor[20];
+ char *basename = NULL;
+
+ if (argc != 2)
+ {
+ usage (argv[0]);
+ exit (1);
+ }
+
+ rc = stat (argv[1], &sb);
+ if (rc != 0)
+ {
+
rc = -errno;
- fprintf(stderr, "[ERROR] %s: stat('%s') errno = %d\n", argv[0], argv[1], rc );
- exit(2);
- }
-
- if( !S_ISCHR( sb.st_mode ) ) {
-
- fprintf(stderr, "[ERROR] %s: '%s' is not a character device file\n", argv[0], argv[1] );
- usage(argv[0]);
- exit(2);
- }
-
- sprintf( major, "%u", major(sb.st_rdev) );
- sprintf( minor, "%u", minor(sb.st_rdev) );
-
- static char const* caps[] = {
- "ev",
- "abs",
- "key",
- "rel",
- NULL
- };
-
- unsigned long *bitmasks[] = {
- bitmask_ev,
- bitmask_abs,
- bitmask_key,
- bitmask_rel,
- NULL
- };
-
- size_t bitmask_lens[] = {
- NBITS(EV_MAX),
- NBITS(ABS_MAX),
- NBITS(KEY_MAX),
- NBITS(REL_MAX),
- 0
- };
-
- if( major == NULL || minor == NULL ) {
+ fprintf (stderr, "[ERROR] %s: stat('%s') errno = %d\n", argv[0],
+ argv[1], rc);
+ exit (2);
+ }
+
+ if (!S_ISCHR (sb.st_mode))
+ {
+
+ fprintf (stderr,
+ "[ERROR] %s: '%s' is not a character device file\n",
+ argv[0], argv[1]);
+ usage (argv[0]);
+ exit (2);
+ }
+
+ sprintf (major, "%u", major (sb.st_rdev));
+ sprintf (minor, "%u", minor (sb.st_rdev));
+
+ static char const *caps[] = {
+ "ev",
+ "abs",
+ "key",
+ "rel",
+ NULL
+ };
+
+ unsigned long *bitmasks[] = {
+ bitmask_ev,
+ bitmask_abs,
+ bitmask_key,
+ bitmask_rel,
+ NULL
+ };
+
+ size_t bitmask_lens[] = {
+ NBITS (EV_MAX),
+ NBITS (ABS_MAX),
+ NBITS (KEY_MAX),
+ NBITS (REL_MAX),
+ 0
+ };
+
+ if (major == NULL || minor == NULL)
+ {
// nothing to do here
- exit(1);
- }
-
- // is this an input device?
- memset( sysdev_path, 0, 4096 );
- memset( subsystem, 0, 4096 );
-
- snprintf( sysdev_path, 4096, "/sys/dev/char/%s:%s/subsystem", major, minor );
- rc = readlink( sysdev_path, subsystem, 4096 );
- if( rc < 0 ) {
- fprintf(stderr, "[ERROR] %s: readlink('%s'): %s\n", argv[0], sysdev_path, strerror( rc ) );
- exit(1);
- }
-
- if( strcmp( subsystem + strlen(subsystem) - 5, "input" ) != 0 ) {
-
+ exit (1);
+ }
+ // is this an input device?
+ memset (sysdev_path, 0, 4096);
+ memset (subsystem, 0, 4096);
+
+ snprintf (sysdev_path, 4096, "/sys/dev/char/%s:%s/subsystem", major, minor);
+ rc = readlink (sysdev_path, subsystem, 4096);
+ if (rc < 0)
+ {
+ fprintf (stderr, "[ERROR] %s: readlink('%s'): %s\n", argv[0],
+ sysdev_path, strerror (rc));
+ exit (1);
+ }
+
+ if (strcmp (subsystem + strlen (subsystem) - 5, "input") != 0)
+ {
+
// not an input device
- exit(1);
- }
-
- // replaces ID_INPUT
- vdev_property_add( "VDEV_INPUT", "1" );
-
- memset( capabilities_path, 0, 4096 );
-
- snprintf(capabilities_path, 4095, "/sys/dev/char/%s:%s/device/capabilities", major, minor );
-
- // read each capability
- for( int i = 0; caps[i] != NULL; i++ ) {
-
- memset( full_sysfs_path, 0, 4096 );
- snprintf( full_sysfs_path, 4096, "%s/%s", capabilities_path, caps[i] );
-
- get_cap_mask( full_sysfs_path, bitmasks[i], bitmask_lens[i] );
- }
-
- // build up properties
- test_pointers( bitmask_ev, bitmask_abs, bitmask_key, bitmask_rel );
- test_key( bitmask_ev, bitmask_key );
-
- basename = rindex( argv[1], '/' ) + 1;
-
- if( strncmp( basename, "event", 5) == 0 ) {
-
- extract_input_resolution( argv[1] );
- }
-
- // state the input class too
- switch( g_input_class ) {
-
- case VDEV_INPUT_CLASS_JOYSTICK: {
-
- vdev_property_add( "VDEV_INPUT_CLASS", "joystick" );
- break;
+ exit (1);
+ }
+ // replaces ID_INPUT
+ vdev_property_add ("VDEV_INPUT", "1");
+
+ memset (capabilities_path, 0, 4096);
+
+ snprintf (capabilities_path, 4095,
+ "/sys/dev/char/%s:%s/device/capabilities", major, minor);
+
+ // read each capability
+ for (int i = 0; caps[i] != NULL; i++)
+ {
+
+ memset (full_sysfs_path, 0, 4096);
+ snprintf (full_sysfs_path, 4096, "%s/%s", capabilities_path, caps[i]);
+
+ get_cap_mask (full_sysfs_path, bitmasks[i], bitmask_lens[i]);
+ }
+
+ // build up properties
+ test_pointers (bitmask_ev, bitmask_abs, bitmask_key, bitmask_rel);
+ test_key (bitmask_ev, bitmask_key);
+
+ basename = rindex (argv[1], '/') + 1;
+
+ if (strncmp (basename, "event", 5) == 0)
+ {
+
+ extract_input_resolution (argv[1]);
+ }
+ // state the input class too
+ switch (g_input_class)
+ {
+
+ case VDEV_INPUT_CLASS_JOYSTICK:
+ {
+
+ vdev_property_add ("VDEV_INPUT_CLASS", "joystick");
+ break;
}
-
- case VDEV_INPUT_CLASS_MOUSE: {
-
- vdev_property_add( "VDEV_INPUT_CLASS", "mouse" );
- break;
+
+ case VDEV_INPUT_CLASS_MOUSE:
+ {
+
+ vdev_property_add ("VDEV_INPUT_CLASS", "mouse");
+ break;
}
-
- case VDEV_INPUT_CLASS_KBD: {
-
- vdev_property_add( "VDEV_INPUT_CLASS", "kbd" );
- break;
+
+ case VDEV_INPUT_CLASS_KBD:
+ {
+
+ vdev_property_add ("VDEV_INPUT_CLASS", "kbd");
+ break;
}
- }
-
- vdev_property_print();
- vdev_property_free_all();
-
- return 0;
+ }
+
+ vdev_property_print ();
+ vdev_property_free_all ();
+
+ return 0;
}
diff --git a/vdevd/helpers/LINUX/stat_net.c b/vdevd/helpers/LINUX/stat_net.c
index 21f1ed7..1c43f4d 100644
--- a/vdevd/helpers/LINUX/stat_net.c
+++ b/vdevd/helpers/LINUX/stat_net.c
@@ -102,899 +102,1080 @@
#include
#include
-enum netname_type{
- NET_UNDEF,
- NET_PCI,
- NET_USB,
- NET_BCMA,
- NET_VIRTIO,
- NET_CCWGROUP,
+enum netname_type
+{
+ NET_UNDEF,
+ NET_PCI,
+ NET_USB,
+ NET_BCMA,
+ NET_VIRTIO,
+ NET_CCWGROUP,
};
-struct netnames {
- enum netname_type type;
-
- uint8_t mac[6];
- bool mac_valid;
-
- char* pcidev; // sysfs device path
- char pci_slot[IFNAMSIZ+1];
- char pci_path[IFNAMSIZ+1];
- char pci_onboard[IFNAMSIZ+1];
- char *pci_onboard_label;
-
- char usb_ports[IFNAMSIZ+1];
- char bcma_core[IFNAMSIZ+1];
- char ccw_group[IFNAMSIZ+1];
+struct netnames
+{
+ enum netname_type type;
+
+ uint8_t mac[6];
+ bool mac_valid;
+
+ char *pcidev; // sysfs device path
+ char pci_slot[IFNAMSIZ + 1];
+ char pci_path[IFNAMSIZ + 1];
+ char pci_onboard[IFNAMSIZ + 1];
+ char *pci_onboard_label;
+
+ char usb_ports[IFNAMSIZ + 1];
+ char bcma_core[IFNAMSIZ + 1];
+ char ccw_group[IFNAMSIZ + 1];
};
/* retrieve on-board index number and label from firmware */
-static int dev_pci_onboard( struct netnames *names) {
-
- char *index;
- size_t index_len;
-
- int idx;
- int rc = 0;
-
- /* ACPI _DSM -- device specific method for naming a PCI or PCI Express device */
- rc = vdev_sysfs_read_attr(names->pcidev, "acpi_index", &index, &index_len );
-
- /* SMBIOS type 41 -- Onboard Devices Extended Information */
- if ( rc < 0 ) {
- rc = vdev_sysfs_read_attr(names->pcidev, "index", &index, &index_len );
- }
-
- if( rc < 0 ) {
+static int
+dev_pci_onboard (struct netnames *names)
+{
+
+ char *index;
+ size_t index_len;
+
+ int idx;
+ int rc = 0;
+
+ /* ACPI _DSM -- device specific method for naming a PCI or PCI Express device */
+ rc = vdev_sysfs_read_attr (names->pcidev, "acpi_index", &index, &index_len);
+
+ /* SMBIOS type 41 -- Onboard Devices Extended Information */
+ if (rc < 0)
+ {
+ rc = vdev_sysfs_read_attr (names->pcidev, "index", &index, &index_len);
+ }
+
+ if (rc < 0)
+ {
return -ENOENT;
- }
-
- idx = strtoul(index, NULL, 0);
- if (idx <= 0) {
-
- free( index );
+ }
+
+ idx = strtoul (index, NULL, 0);
+ if (idx <= 0)
+ {
+
+ free (index);
return -EINVAL;
- }
-
- snprintf(names->pci_onboard, sizeof(names->pci_onboard), "o%d", idx);
-
- vdev_sysfs_read_attr( names->pcidev, "label", &names->pci_onboard_label, &index_len );
- free( index );
-
- return 0;
+ }
+
+ snprintf (names->pci_onboard, sizeof (names->pci_onboard), "o%d", idx);
+
+ vdev_sysfs_read_attr (names->pcidev, "label", &names->pci_onboard_label,
+ &index_len);
+ free (index);
+
+ return 0;
}
/* read the 256 bytes PCI configuration space to check the multi-function bit */
-static bool is_pci_multifunction( char const* sysfs_path ) {
-
- FILE *f = NULL;
- char *filename;
- uint8_t config[64];
-
- filename = (char*)calloc( strlen(sysfs_path) + 1 + strlen("/config") + 1, 1 );
- if( filename == NULL ) {
+static bool
+is_pci_multifunction (char const *sysfs_path)
+{
+
+ FILE *f = NULL;
+ char *filename;
+ uint8_t config[64];
+
+ filename =
+ (char *) calloc (strlen (sysfs_path) + 1 + strlen ("/config") + 1, 1);
+ if (filename == NULL)
+ {
return -ENOMEM;
- }
-
- sprintf( filename, "%s/config", sysfs_path );
-
- f = fopen(filename, "re");
- if (!f) {
-
- free( filename );
+ }
+
+ sprintf (filename, "%s/config", sysfs_path);
+
+ f = fopen (filename, "re");
+ if (!f)
+ {
+
+ free (filename);
return false;
- }
-
- if (fread(&config, sizeof(config), 1, f) != 1) {
-
- free( filename );
- fclose( f );
+ }
+
+ if (fread (&config, sizeof (config), 1, f) != 1)
+ {
+
+ free (filename);
+ fclose (f);
return false;
- }
+ }
+
+ fclose (f);
- fclose( f );
-
- /* bit 0-6 header type, bit 7 multi/single function device */
- if ((config[PCI_HEADER_TYPE] & 0x80) != 0) {
- free( filename );
+ /* bit 0-6 header type, bit 7 multi/single function device */
+ if ((config[PCI_HEADER_TYPE] & 0x80) != 0)
+ {
+ free (filename);
return true;
- }
-
- free( filename );
+ }
- return false;
-}
+ free (filename);
+ return false;
+}
// calculate the pci path and slot of the device
-static int dev_pci_slot( char const* dev_path, struct netnames *names) {
-
- unsigned domain, bus, slot, func, dev_port = 0;
-
- char *attr;
- size_t attr_len;
-
- char* pci_sysfs_path = NULL;
- size_t pci_sysfs_path_len = 0;
-
- char* slots = NULL;
- char* address_path = NULL;
-
- DIR *dir = NULL;
- struct dirent *dent;
- int hotplug_slot = 0, err = 0;
- char* pcidev_sysname = NULL;
- size_t pcidev_sysname_len = 0;
- int rc = 0;
-
- rc = vdev_sysfs_get_sysname( names->pcidev, &pcidev_sysname, &pcidev_sysname_len );
- if( rc != 0 ) {
+static int
+dev_pci_slot (char const *dev_path, struct netnames *names)
+{
+
+ unsigned domain, bus, slot, func, dev_port = 0;
+
+ char *attr;
+ size_t attr_len;
+
+ char *pci_sysfs_path = NULL;
+ size_t pci_sysfs_path_len = 0;
+
+ char *slots = NULL;
+ char *address_path = NULL;
+
+ DIR *dir = NULL;
+ struct dirent *dent;
+ int hotplug_slot = 0, err = 0;
+ char *pcidev_sysname = NULL;
+ size_t pcidev_sysname_len = 0;
+ int rc = 0;
+
+ rc = vdev_sysfs_get_sysname (names->pcidev, &pcidev_sysname,
+ &pcidev_sysname_len);
+ if (rc != 0)
+ {
return rc;
- }
+ }
- if (sscanf( pcidev_sysname, "%x:%x:%x.%u", &domain, &bus, &slot, &func) != 4) {
-
- free( pcidev_sysname );
+ if (sscanf (pcidev_sysname, "%x:%x:%x.%u", &domain, &bus, &slot, &func)
+ != 4)
+ {
+
+ free (pcidev_sysname);
return -ENOENT;
- }
-
- free( pcidev_sysname );
-
- /* kernel provided multi-device index */
- rc = vdev_sysfs_read_attr(dev_path, "dev_port", &attr, &attr_len );
- if ( rc == 0 ) {
- dev_port = strtol(attr, NULL, 10);
- free( attr );
- }
-
- /* compose a name based on the raw kernel's PCI bus, slot numbers */
- memset( names->pci_path, 0, IFNAMSIZ+1 );
-
- if (domain > 0) {
-
- sprintf( names->pci_path + strlen(names->pci_path), "P%u", domain );
- }
-
- sprintf( names->pci_path + strlen(names->pci_path), "p%us%u", bus, slot );
-
- if (func > 0 || is_pci_multifunction(names->pcidev)) {
-
- sprintf( names->pci_path + strlen(names->pci_path), "f%u", func );
- }
-
- if (dev_port > 0) {
-
- sprintf( names->pci_path + strlen(names->pci_path), "d%u", dev_port );
- }
-
- if (strlen(names->pci_path) == 0) {
- names->pci_path[0] = '\0';
- }
+ }
+
+ free (pcidev_sysname);
+
+ /* kernel provided multi-device index */
+ rc = vdev_sysfs_read_attr (dev_path, "dev_port", &attr, &attr_len);
+ if (rc == 0)
+ {
+ dev_port = strtol (attr, NULL, 10);
+ free (attr);
+ }
+
+ /* compose a name based on the raw kernel's PCI bus, slot numbers */
+ memset (names->pci_path, 0, IFNAMSIZ + 1);
+
+ if (domain > 0)
+ {
+
+ sprintf (names->pci_path + strlen (names->pci_path), "P%u", domain);
+ }
+
+ sprintf (names->pci_path + strlen (names->pci_path), "p%us%u", bus, slot);
+
+ if (func > 0 || is_pci_multifunction (names->pcidev))
+ {
+
+ sprintf (names->pci_path + strlen (names->pci_path), "f%u", func);
+ }
+
+ if (dev_port > 0)
+ {
- /* ACPI _SUN -- slot user number */
- rc = vdev_sysfs_device_path_from_subsystem_sysname("/sys", "subsystem", "pci", &pci_sysfs_path, &pci_sysfs_path_len);
- if ( rc != 0 ) {
+ sprintf (names->pci_path + strlen (names->pci_path), "d%u", dev_port);
+ }
+
+ if (strlen (names->pci_path) == 0)
+ {
+ names->pci_path[0] = '\0';
+ }
+
+ /* ACPI _SUN -- slot user number */
+ rc = vdev_sysfs_device_path_from_subsystem_sysname ("/sys", "subsystem",
+ "pci",
+ &pci_sysfs_path,
+ &pci_sysfs_path_len);
+ if (rc != 0)
+ {
err = -ENOENT;
goto out;
- }
-
- slots = (char*)calloc( strlen(pci_sysfs_path) + strlen("/slots") + 1, 1 );
- if( slots == NULL ) {
+ }
+
+ slots =
+ (char *) calloc (strlen (pci_sysfs_path) + strlen ("/slots") + 1, 1);
+ if (slots == NULL)
+ {
err = -ENOMEM;
-
- free( pci_sysfs_path );
+
+ free (pci_sysfs_path);
goto out;
- }
-
- sprintf( slots, "%s/slots", pci_sysfs_path );
-
- free( pci_sysfs_path );
-
- dir = opendir(slots);
- if (!dir) {
+ }
+
+ sprintf (slots, "%s/slots", pci_sysfs_path);
+
+ free (pci_sysfs_path);
+
+ dir = opendir (slots);
+ if (!dir)
+ {
err = -errno;
goto out;
- }
+ }
- for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+ for (dent = readdir (dir); dent != NULL; dent = readdir (dir))
+ {
int i;
char *rest;
char *address;
size_t address_len = 0;
- if (dent->d_name[0] == '.') {
- continue;
- }
-
- i = strtol(dent->d_name, &rest, 10);
-
- if (rest[0] != '\0') {
- continue;
- }
-
- if (i < 1) {
- continue;
- }
-
- address_path = (char*)calloc( strlen(slots) + strlen(dent->d_name) + 3 + strlen("address"), 1 );
- if( address_path == NULL ) {
- err = -ENOMEM;
- goto out;
- }
-
- sprintf( address_path, "%s/%s/address", slots, dent->d_name );
-
- rc = vdev_read_file( address_path, &address, &address_len );
- if( rc != 0 ) {
-
- free( address_path );
- continue;
- }
-
- free( address_path );
-
+ if (dent->d_name[0] == '.')
+ {
+ continue;
+ }
+
+ i = strtol (dent->d_name, &rest, 10);
+
+ if (rest[0] != '\0')
+ {
+ continue;
+ }
+
+ if (i < 1)
+ {
+ continue;
+ }
+
+ address_path =
+ (char *) calloc (strlen (slots) + strlen (dent->d_name) + 3 +
+ strlen ("address"), 1);
+ if (address_path == NULL)
+ {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ sprintf (address_path, "%s/%s/address", slots, dent->d_name);
+
+ rc = vdev_read_file (address_path, &address, &address_len);
+ if (rc != 0)
+ {
+
+ free (address_path);
+ continue;
+ }
+
+ free (address_path);
+
// take the first line only
- if( index( address, '\n' ) != NULL ) {
-
- *(index(address, '\n')) = '\0';
- }
-
+ if (index (address, '\n') != NULL)
+ {
+
+ *(index (address, '\n')) = '\0';
+ }
+
/* match slot address with device by stripping the function */
- if (strneq(address, names->pcidev, strlen(address))) {
- hotplug_slot = i;
- }
-
- free(address);
-
- if (hotplug_slot > 0) {
- break;
- }
- }
-
- closedir( dir );
-
- if (hotplug_slot > 0) {
-
- memset( names->pci_slot, 0, IFNAMSIZ+1 );
-
- if (domain > 0) {
-
- sprintf( names->pci_slot + strlen( names->pci_slot ), "P%d", domain );
- }
-
- sprintf( names->pci_slot + strlen( names->pci_slot ), "s%d", hotplug_slot );
-
- if (func > 0 || is_pci_multifunction(names->pcidev)) {
-
- sprintf( names->pci_slot + strlen( names->pci_slot ), "f%d", func );
- }
-
- if (dev_port > 0) {
-
- sprintf( names->pci_slot + strlen( names->pci_slot ), "d%d", dev_port );
- }
-
- if (strlen(names->pci_slot) == 0) {
- names->pci_slot[0] = '\0';
- }
- }
+ if (strneq (address, names->pcidev, strlen (address)))
+ {
+ hotplug_slot = i;
+ }
+
+ free (address);
+
+ if (hotplug_slot > 0)
+ {
+ break;
+ }
+ }
+
+ closedir (dir);
+
+ if (hotplug_slot > 0)
+ {
+
+ memset (names->pci_slot, 0, IFNAMSIZ + 1);
+
+ if (domain > 0)
+ {
+
+ sprintf (names->pci_slot + strlen (names->pci_slot), "P%d", domain);
+ }
+
+ sprintf (names->pci_slot + strlen (names->pci_slot), "s%d",
+ hotplug_slot);
+
+ if (func > 0 || is_pci_multifunction (names->pcidev))
+ {
+
+ sprintf (names->pci_slot + strlen (names->pci_slot), "f%d", func);
+ }
+
+ if (dev_port > 0)
+ {
+
+ sprintf (names->pci_slot + strlen (names->pci_slot),
+ "d%d", dev_port);
+ }
+
+ if (strlen (names->pci_slot) == 0)
+ {
+ names->pci_slot[0] = '\0';
+ }
+ }
out:
- return err;
+ return err;
}
-static int names_pci( char const* dev_path, struct netnames *names ) {
-
- char* parent_device_path = NULL;
- size_t parent_device_path_len = 0;
-
- char* parent_device_subsystem = NULL;
- size_t parent_device_subsystem_len = 0;
-
- int rc = 0;
-
- // get parent device
- rc = vdev_sysfs_get_parent_device( dev_path, &parent_device_path, &parent_device_path_len );
- if( rc != 0 ) {
-
- if( rc != -ENOENT ) {
- // some other fatal error
- log_error("WARN: vdev_sysfs_get_parent_device('%s') rc = %d\n", dev_path, rc );
- }
-
+static int
+names_pci (char const *dev_path, struct netnames *names)
+{
+
+ char *parent_device_path = NULL;
+ size_t parent_device_path_len = 0;
+
+ char *parent_device_subsystem = NULL;
+ size_t parent_device_subsystem_len = 0;
+
+ int rc = 0;
+
+ // get parent device
+ rc = vdev_sysfs_get_parent_device (dev_path, &parent_device_path,
+ &parent_device_path_len);
+ if (rc != 0)
+ {
+
+ if (rc != -ENOENT)
+ {
+ // some other fatal error
+ log_error
+ ("WARN: vdev_sysfs_get_parent_device('%s') rc = %d\n",
+ dev_path, rc);
+ }
+
return rc;
- }
-
- // get parent subsystem
- rc = vdev_sysfs_read_subsystem( parent_device_path, &parent_device_subsystem, &parent_device_subsystem_len );
- if( rc != 0 ) {
-
- free( parent_device_path );
-
- log_error("WARN: vdev_sysfs_read_subsystem('%s') rc = %d\n", parent_device_path, rc );
+ }
+ // get parent subsystem
+ rc = vdev_sysfs_read_subsystem (parent_device_path,
+ &parent_device_subsystem,
+ &parent_device_subsystem_len);
+ if (rc != 0)
+ {
+
+ free (parent_device_path);
+
+ log_error ("WARN: vdev_sysfs_read_subsystem('%s') rc = %d\n",
+ parent_device_path, rc);
return rc;
- }
-
- /* check if our direct parent is a PCI device with no other bus in-between */
- if ( strcmp("pci", parent_device_subsystem) == 0 ) {
-
+ }
+
+ /* check if our direct parent is a PCI device with no other bus in-between */
+ if (strcmp ("pci", parent_device_subsystem) == 0)
+ {
+
names->type = NET_PCI;
- names->pcidev = strdup( parent_device_path );
-
- if( names->pcidev == NULL ) {
- free( parent_device_path );
- free( parent_device_subsystem );
- return -ENOMEM;
- }
- }
- else {
-
+ names->pcidev = strdup (parent_device_path);
+
+ if (names->pcidev == NULL)
+ {
+ free (parent_device_path);
+ free (parent_device_subsystem);
+ return -ENOMEM;
+ }
+ }
+ else
+ {
+
size_t pcidev_len = 0;
- rc = vdev_sysfs_get_parent_with_subsystem_devtype( dev_path, "pci", NULL, &names->pcidev, &pcidev_len );
-
- if( rc != 0 ) {
-
- if( rc != -ENOENT ) {
- log_error("WARN: vdev_sysfs_get_parent_with_subsystem_devtype('%s', 'pci', NULL) rc = %d\n", dev_path, rc );
- }
-
- return rc;
- }
- }
-
- free( parent_device_subsystem );
- free( parent_device_path );
-
- dev_pci_onboard( names );
- dev_pci_slot(dev_path, names);
- return 0;
+ rc = vdev_sysfs_get_parent_with_subsystem_devtype (dev_path,
+ "pci", NULL,
+ &names->pcidev,
+ &pcidev_len);
+
+ if (rc != 0)
+ {
+
+ if (rc != -ENOENT)
+ {
+ log_error
+ ("WARN: vdev_sysfs_get_parent_with_subsystem_devtype('%s', 'pci', NULL) rc = %d\n",
+ dev_path, rc);
+ }
+
+ return rc;
+ }
+ }
+
+ free (parent_device_subsystem);
+ free (parent_device_path);
+
+ dev_pci_onboard (names);
+ dev_pci_slot (dev_path, names);
+ return 0;
}
-static int names_usb( char const* dev_path, struct netnames *names) {
-
- char *ports;
- char *config;
- char *interf;
- char *s;
- char* usbdev_path = NULL;
- char* usbdev_sysname = NULL;
- size_t usbdev_path_len = 0;
- size_t usbdev_sysname_len =0;
- int rc = 0;
-
- rc = vdev_sysfs_get_parent_with_subsystem_devtype( dev_path, "usb", "usb_interface", &usbdev_path, &usbdev_path_len );
- if( rc != 0 ) {
-
- if( rc != -ENOENT ) {
- log_error("WARN: vdev_sysfs_get_parent_with_subsystem_devtype('%s', 'usb', 'usb_interface') rc = %d\n", dev_path, rc );
- }
-
+static int
+names_usb (char const *dev_path, struct netnames *names)
+{
+
+ char *ports;
+ char *config;
+ char *interf;
+ char *s;
+ char *usbdev_path = NULL;
+ char *usbdev_sysname = NULL;
+ size_t usbdev_path_len = 0;
+ size_t usbdev_sysname_len = 0;
+ int rc = 0;
+
+ rc = vdev_sysfs_get_parent_with_subsystem_devtype (dev_path, "usb",
+ "usb_interface",
+ &usbdev_path,
+ &usbdev_path_len);
+ if (rc != 0)
+ {
+
+ if (rc != -ENOENT)
+ {
+ log_error
+ ("WARN: vdev_sysfs_get_parent_with_subsystem_devtype('%s', 'usb', 'usb_interface') rc = %d\n",
+ dev_path, rc);
+ }
+
return rc;
- }
-
- rc = vdev_sysfs_get_sysname( usbdev_path, &usbdev_sysname, &usbdev_sysname_len );
- if( rc != 0 ) {
-
- free( usbdev_path );
+ }
+
+ rc = vdev_sysfs_get_sysname (usbdev_path, &usbdev_sysname,
+ &usbdev_sysname_len);
+ if (rc != 0)
+ {
+
+ free (usbdev_path);
return rc;
- }
-
- free( usbdev_path );
-
- /* get USB port number chain, configuration, interface */
- s = strchr(usbdev_sysname, '-');
- if (!s) {
-
- free( usbdev_sysname );
+ }
+
+ free (usbdev_path);
+
+ /* get USB port number chain, configuration, interface */
+ s = strchr (usbdev_sysname, '-');
+ if (!s)
+ {
+
+ free (usbdev_sysname);
return -EINVAL;
- }
-
- ports = s+1;
-
- s = strchr(ports, ':');
- if (!s) {
-
- free( usbdev_sysname );
+ }
+
+ ports = s + 1;
+
+ s = strchr (ports, ':');
+ if (!s)
+ {
+
+ free (usbdev_sysname);
return -EINVAL;
- }
-
- s[0] = '\0';
- config = s+1;
-
- s = strchr(config, '.');
- if (!s) {
-
- free( usbdev_sysname );
+ }
+
+ s[0] = '\0';
+ config = s + 1;
+
+ s = strchr (config, '.');
+ if (!s)
+ {
+
+ free (usbdev_sysname);
return -EINVAL;
- }
-
- s[0] = '\0';
- interf = s+1;
-
- /* prefix every port number in the chain with "u" */
- s = ports;
- while ((s = strchr(s, '.'))) {
+ }
+
+ s[0] = '\0';
+ interf = s + 1;
+
+ /* prefix every port number in the chain with "u" */
+ s = ports;
+ while ((s = strchr (s, '.')))
+ {
s[0] = 'u';
- }
-
- // set up usb_ports
- s = names->usb_ports;
- memset( s, 0, IFNAMSIZ+1 );
-
- strncat( s, "u", IFNAMSIZ );
- strncat( s, ports, IFNAMSIZ );
-
- /* append USB config number, suppress the common config == 1 */
- if( strcmp(config, "1") != 0 ) {
- strncat( s, "c", IFNAMSIZ );
- strncat( s, ports, IFNAMSIZ );
- }
-
- /* append USB interface number, suppress the interface == 0 */
- if( strcmp(interf, "0") != 0 ) {
- strncat( s, "i", IFNAMSIZ );
- strncat( s, interf, IFNAMSIZ );
- }
-
- if( strlen(s) == 0 ) {
-
- free( usbdev_sysname );
+ }
+
+ // set up usb_ports
+ s = names->usb_ports;
+ memset (s, 0, IFNAMSIZ + 1);
+
+ strncat (s, "u", IFNAMSIZ);
+ strncat (s, ports, IFNAMSIZ);
+
+ /* append USB config number, suppress the common config == 1 */
+ if (strcmp (config, "1") != 0)
+ {
+ strncat (s, "c", IFNAMSIZ);
+ strncat (s, ports, IFNAMSIZ);
+ }
+
+ /* append USB interface number, suppress the interface == 0 */
+ if (strcmp (interf, "0") != 0)
+ {
+ strncat (s, "i", IFNAMSIZ);
+ strncat (s, interf, IFNAMSIZ);
+ }
+
+ if (strlen (s) == 0)
+ {
+
+ free (usbdev_sysname);
return -ENAMETOOLONG;
- }
-
- free( usbdev_sysname );
- names->type = NET_USB;
- return 0;
+ }
+
+ free (usbdev_sysname);
+ names->type = NET_USB;
+ return 0;
}
-static int names_bcma( char const* devpath, struct netnames *names) {
-
- char* bcmadev_path = NULL;
- size_t bcmadev_path_len = 0;
- char* bcmadev_sysname = NULL;
- size_t bcmadev_sysname_len = 0;
- unsigned int core;
- int rc = 0;
-
- rc = vdev_sysfs_get_parent_with_subsystem_devtype( devpath, "bcma", NULL, &bcmadev_path, &bcmadev_path_len );
- if( rc != 0 ) {
-
- if( rc != -ENOENT ) {
- log_error("vdev_sysfs_get_parent_with_subsystem_devtype('%s', 'bcma', NULL) rc = %d\n", devpath, rc );
- }
-
+static int
+names_bcma (char const *devpath, struct netnames *names)
+{
+
+ char *bcmadev_path = NULL;
+ size_t bcmadev_path_len = 0;
+ char *bcmadev_sysname = NULL;
+ size_t bcmadev_sysname_len = 0;
+ unsigned int core;
+ int rc = 0;
+
+ rc = vdev_sysfs_get_parent_with_subsystem_devtype (devpath, "bcma", NULL,
+ &bcmadev_path,
+ &bcmadev_path_len);
+ if (rc != 0)
+ {
+
+ if (rc != -ENOENT)
+ {
+ log_error
+ ("vdev_sysfs_get_parent_with_subsystem_devtype('%s', 'bcma', NULL) rc = %d\n",
+ devpath, rc);
+ }
+
return rc;
- }
-
- rc = vdev_sysfs_get_sysname( devpath, &bcmadev_sysname, &bcmadev_sysname_len );
- if( rc != 0 ) {
-
- free( bcmadev_path );
+ }
+
+ rc = vdev_sysfs_get_sysname (devpath, &bcmadev_sysname,
+ &bcmadev_sysname_len);
+ if (rc != 0)
+ {
+
+ free (bcmadev_path);
return rc;
- }
-
- /* bus num:core num */
- if (sscanf( bcmadev_sysname, "bcma%*u:%u", &core) != 1) {
-
- free( bcmadev_path );
- free( bcmadev_sysname );
+ }
+
+ /* bus num:core num */
+ if (sscanf (bcmadev_sysname, "bcma%*u:%u", &core) != 1)
+ {
+
+ free (bcmadev_path);
+ free (bcmadev_sysname);
return -EINVAL;
- }
-
- /* suppress the common core == 0 */
- if (core > 0) {
- snprintf(names->bcma_core, sizeof(names->bcma_core), "b%u", core);
- }
-
- names->type = NET_BCMA;
-
- free( bcmadev_path );
- free( bcmadev_sysname );
- return 0;
+ }
+
+ /* suppress the common core == 0 */
+ if (core > 0)
+ {
+ snprintf (names->bcma_core, sizeof (names->bcma_core), "b%u", core);
+ }
+
+ names->type = NET_BCMA;
+
+ free (bcmadev_path);
+ free (bcmadev_sysname);
+ return 0;
}
+static int
+names_ccw (char const *devpath, struct netnames *names)
+{
+
+ char *bus_id = NULL;
+ size_t bus_id_len = 0;
+ int rc;
+
+ char *parent_devpath = NULL;
+ size_t parent_devpath_len = 0;
-static int names_ccw( char const* devpath, struct netnames *names) {
-
- char *bus_id = NULL;
- size_t bus_id_len = 0;
- int rc;
-
- char* parent_devpath = NULL;
- size_t parent_devpath_len = 0;
-
- char* parent_subsystem = NULL;
- size_t parent_subsystem_len = 0;
-
- /* Retrieve the associated CCW device */
- rc = vdev_sysfs_get_parent_device( devpath, &parent_devpath, &parent_devpath_len );
- if( rc != 0 ) {
+ char *parent_subsystem = NULL;
+ size_t parent_subsystem_len = 0;
+
+ /* Retrieve the associated CCW device */
+ rc = vdev_sysfs_get_parent_device (devpath, &parent_devpath,
+ &parent_devpath_len);
+ if (rc != 0)
+ {
return -ENOENT;
- }
-
- // get parent subsystem
- rc = vdev_sysfs_read_subsystem( parent_devpath, &parent_subsystem, &parent_subsystem_len );
- if( rc != 0 ) {
-
- free( parent_devpath );
+ }
+ // get parent subsystem
+ rc = vdev_sysfs_read_subsystem (parent_devpath, &parent_subsystem,
+ &parent_subsystem_len);
+ if (rc != 0)
+ {
+
+ free (parent_devpath);
return rc;
- }
-
- /* Network devices are always grouped CCW devices */
- if( strcmp("ccwgroup", parent_subsystem) != 0 ) {
-
- free( parent_devpath );
- free( parent_subsystem );
+ }
+
+ /* Network devices are always grouped CCW devices */
+ if (strcmp ("ccwgroup", parent_subsystem) != 0)
+ {
+
+ free (parent_devpath);
+ free (parent_subsystem);
return -ENOENT;
- }
+ }
- /* Retrieve bus-ID of the grouped CCW device. The bus-ID uniquely
+ /* Retrieve bus-ID of the grouped CCW device. The bus-ID uniquely
* identifies the network device on the Linux on System z channel
* subsystem. Note that the bus-ID contains lowercase characters.
*/
- rc = vdev_sysfs_get_sysname( parent_devpath, &bus_id, &bus_id_len );
- if( rc != 0 ) {
-
- free( parent_devpath );
- free( parent_subsystem );
+ rc = vdev_sysfs_get_sysname (parent_devpath, &bus_id, &bus_id_len);
+ if (rc != 0)
+ {
+
+ free (parent_devpath);
+ free (parent_subsystem);
return -ENOENT;
- }
-
- /* Check the length of the bus-ID. Rely on that the kernel provides
+ }
+
+ /* Check the length of the bus-ID. Rely on that the kernel provides
* a correct bus-ID; alternatively, improve this check and parse and
* verify each bus-ID part...
*/
- if (bus_id_len == 0 || bus_id_len < 8 || bus_id_len > 9) {
-
- free( parent_devpath );
- free( parent_subsystem );
- free( bus_id );
-
+ if (bus_id_len == 0 || bus_id_len < 8 || bus_id_len > 9)
+ {
+
+ free (parent_devpath);
+ free (parent_subsystem);
+ free (bus_id);
+
return -EINVAL;
- }
+ }
- /* Store the CCW bus-ID for use as network device name */
- rc = snprintf(names->ccw_group, sizeof(names->ccw_group), "ccw%s", bus_id);
- if (rc >= 0 && rc < (int)sizeof(names->ccw_group)) {
+ /* Store the CCW bus-ID for use as network device name */
+ rc = snprintf (names->ccw_group, sizeof (names->ccw_group), "ccw%s",
+ bus_id);
+ if (rc >= 0 && rc < (int) sizeof (names->ccw_group))
+ {
names->type = NET_CCWGROUP;
- }
-
- free( parent_devpath );
- free( parent_subsystem );
- free( bus_id );
-
- return 0;
+ }
+
+ free (parent_devpath);
+ free (parent_subsystem);
+ free (bus_id);
+
+ return 0;
}
-static int names_mac( char const* devpath, struct netnames *names) {
-
- unsigned int i;
- unsigned int a1, a2, a3, a4, a5, a6;
- int rc = 0;
-
- char* addr_assign_type = NULL;
- size_t addr_assign_type_len = 0;
-
- char* address = NULL;
- size_t address_len = 0;
-
- rc = vdev_sysfs_read_attr( devpath, "addr_assign_type", &addr_assign_type, &addr_assign_type_len );
- if( rc != 0 ) {
+static int
+names_mac (char const *devpath, struct netnames *names)
+{
+
+ unsigned int i;
+ unsigned int a1, a2, a3, a4, a5, a6;
+ int rc = 0;
+
+ char *addr_assign_type = NULL;
+ size_t addr_assign_type_len = 0;
+
+ char *address = NULL;
+ size_t address_len = 0;
+
+ rc = vdev_sysfs_read_attr (devpath, "addr_assign_type",
+ &addr_assign_type, &addr_assign_type_len);
+ if (rc != 0)
+ {
return rc;
- }
-
- i = strtoul( addr_assign_type, NULL, 0);
- if (i != 0) {
-
- free( addr_assign_type );
+ }
+
+ i = strtoul (addr_assign_type, NULL, 0);
+ if (i != 0)
+ {
+
+ free (addr_assign_type);
return 0;
- }
-
- rc = vdev_sysfs_read_attr( devpath, "address", &address, &address_len );
- if( rc != 0 ) {
-
- free( addr_assign_type );
+ }
+
+ rc = vdev_sysfs_read_attr (devpath, "address", &address, &address_len);
+ if (rc != 0)
+ {
+
+ free (addr_assign_type);
return rc;
- }
-
- rc = sscanf(address, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6);
- if( rc != 6 ) {
-
- free( addr_assign_type );
- free( address );
+ }
+
+ rc = sscanf (address, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6);
+ if (rc != 6)
+ {
+
+ free (addr_assign_type);
+ free (address);
return -EINVAL;
- }
+ }
- free( addr_assign_type );
- free( address );
-
- /* skip empty MAC addresses */
- if( a1 == 0 && a2 == 0 && a3 == 0 && a4 == 0 && a5 == 0 && a6 == 0 ) {
+ free (addr_assign_type);
+ free (address);
+
+ /* skip empty MAC addresses */
+ if (a1 == 0 && a2 == 0 && a3 == 0 && a4 == 0 && a5 == 0 && a6 == 0)
+ {
return -EINVAL;
- }
-
- names->mac[0] = a1;
- names->mac[1] = a2;
- names->mac[2] = a3;
- names->mac[3] = a4;
- names->mac[4] = a5;
- names->mac[5] = a6;
- names->mac_valid = true;
- return 0;
+ }
+
+ names->mac[0] = a1;
+ names->mac[1] = a2;
+ names->mac[2] = a3;
+ names->mac[3] = a4;
+ names->mac[4] = a5;
+ names->mac[5] = a6;
+ names->mac_valid = true;
+ return 0;
}
/* IEEE Organizationally Unique Identifier vendor string */
-static int ieee_oui( char const* devpath, struct netnames *names ) {
- char str[32];
+static int
+ieee_oui (char const *devpath, struct netnames *names)
+{
+ char str[32];
- if (!names->mac_valid) {
+ if (!names->mac_valid)
+ {
return -ENOENT;
- }
-
- /* skip commonly misused 00:00:00 (Xerox) prefix */
- if (memcmp(names->mac, "\0\0\0", 3) == 0) {
+ }
+
+ /* skip commonly misused 00:00:00 (Xerox) prefix */
+ if (memcmp (names->mac, "\0\0\0", 3) == 0)
+ {
return -EINVAL;
- }
-
- snprintf(str, sizeof(str), "OUI:%02X%02X%02X%02X%02X%02X",
- names->mac[0], names->mac[1], names->mac[2],
- names->mac[3], names->mac[4], names->mac[5]);
-
- // TODO: find out how to replace this
- // udev_builtin_hwdb_lookup(dev, NULL, str, NULL, test);
-
- return 0;
-}
+ }
+
+ snprintf (str, sizeof (str), "OUI:%02X%02X%02X%02X%02X%02X",
+ names->mac[0], names->mac[1], names->mac[2],
+ names->mac[3], names->mac[4], names->mac[5]);
+ // TODO: find out how to replace this
+ // udev_builtin_hwdb_lookup(dev, NULL, str, NULL, test);
-void usage( char const* progname ) {
- fprintf(stderr, "[ERROR] %s: Usage: %s INTERFACE\n", progname, progname );
+ return 0;
}
-int main( int argc, char **argv ) {
-
- unsigned int i;
- const char *prefix = "en";
- struct netnames names;
- int err = 0;
- int rc = 0;
- char* tmp = NULL; // for realpath success check
- bool is_net_device = false;
-
- char devpath_class[4097];
- char devpath[4097];
- char devpath_uevent[4097];
-
- char* devtype = NULL;
- size_t devtype_len = 0;
-
- // sysfs attr buf
- char* attr = NULL;
- char* attr_iflink = NULL;
- char* attr_ifindex = NULL;
- size_t attr_len = 0;
-
- char* uevent_buf = NULL;
- size_t uevent_buf_len = 0;
-
- memset( &names, 0, sizeof(struct netnames) );
-
- if( argc != 2 ) {
- usage( argv[0] );
- }
-
- // get the device from the interface
- sprintf( devpath_class, "/sys/class/net/%s", argv[1] );
-
- tmp = realpath( devpath_class, devpath );
- if( tmp == NULL ) {
+void
+usage (char const *progname)
+{
+ fprintf (stderr, "[ERROR] %s: Usage: %s INTERFACE\n", progname, progname);
+}
+
+int
+main (int argc, char **argv)
+{
+
+ unsigned int i;
+ const char *prefix = "en";
+ struct netnames names;
+ int err = 0;
+ int rc = 0;
+ char *tmp = NULL; // for realpath success check
+ bool is_net_device = false;
+
+ char devpath_class[4097];
+ char devpath[4097];
+ char devpath_uevent[4097];
+
+ char *devtype = NULL;
+ size_t devtype_len = 0;
+
+ // sysfs attr buf
+ char *attr = NULL;
+ char *attr_iflink = NULL;
+ char *attr_ifindex = NULL;
+ size_t attr_len = 0;
+
+ char *uevent_buf = NULL;
+ size_t uevent_buf_len = 0;
+
+ memset (&names, 0, sizeof (struct netnames));
+
+ if (argc != 2)
+ {
+ usage (argv[0]);
+ }
+ // get the device from the interface
+ sprintf (devpath_class, "/sys/class/net/%s", argv[1]);
+
+ tmp = realpath (devpath_class, devpath);
+ if (tmp == NULL)
+ {
rc = -errno;
- fprintf(stderr, "[ERROR] %s: Failed to locate sysfs entry for %s\n", argv[0], argv[1] );
- exit(1);
- }
-
- // only care about ethernet and SLIP devices
- rc = vdev_sysfs_read_attr( devpath, "type", &attr, &attr_len );
- if( rc != 0 ) {
-
+ fprintf (stderr,
+ "[ERROR] %s: Failed to locate sysfs entry for %s\n",
+ argv[0], argv[1]);
+ exit (1);
+ }
+ // only care about ethernet and SLIP devices
+ rc = vdev_sysfs_read_attr (devpath, "type", &attr, &attr_len);
+ if (rc != 0)
+ {
+
// not found
- fprintf(stderr, "[ERROR] %s: Failed to find interface type for %s (sysfs path '%s'), rc = %d\n", argv[0], argv[1], devpath, rc );
- exit(1);
- }
-
- i = strtoul(attr, NULL, 0);
-
- free( attr );
-
- switch (i) {
- case ARPHRD_ETHER:
+ fprintf (stderr,
+ "[ERROR] %s: Failed to find interface type for %s (sysfs path '%s'), rc = %d\n",
+ argv[0], argv[1], devpath, rc);
+ exit (1);
+ }
+
+ i = strtoul (attr, NULL, 0);
+
+ free (attr);
+
+ switch (i)
+ {
+ case ARPHRD_ETHER:
prefix = "en";
break;
- case ARPHRD_SLIP:
+ case ARPHRD_SLIP:
prefix = "sl";
break;
- default:
+ default:
return 0;
- }
-
- // sanity check (i.e. no stacked devices)
- rc = vdev_sysfs_read_attr( devpath, "ifindex", &attr_ifindex, &attr_len );
- if( rc != 0 ) {
-
- log_error("vdev_sysfs_read_attr('%s', 'ifindex') rc = %d\n", devpath, rc );
- exit(1);
- }
-
- rc = vdev_sysfs_read_attr( devpath, "iflink", &attr_iflink, &attr_len );
- if( rc != 0 ) {
-
- log_error("vdev_sysfs_read_attr('%s', 'iflink') rc = %d\n", devpath, rc );
-
- free( attr_ifindex );
- exit(1);
- }
-
- if( strcmp( attr_ifindex, attr_iflink ) != 0 ) {
- exit(0);
- }
-
- free( attr_ifindex );
- free( attr_iflink );
-
- // get device type
- sprintf( devpath_uevent, "%s/uevent", devpath );
-
- rc = vdev_read_file( devpath_uevent, &uevent_buf, &uevent_buf_len );
- if( rc != 0 ) {
-
- log_error("vdev_read_file('%s') rc = %d\n", devpath_uevent, rc );
- exit(2);
- }
-
- rc = vdev_sysfs_uevent_get_key( uevent_buf, uevent_buf_len, "DEVTYPE", &devtype, &devtype_len );
- if( rc == 0 ) {
-
- if( strcmp("wlan", devtype) == 0 ) {
- prefix = "wl";
- }
- else if( strcmp("wwan", devtype) == 0 ) {
- prefix = "ww";
- }
- }
-
- free( uevent_buf );
- free( devtype );
-
- err = names_mac( devpath, &names);
- if (err >= 0 && names.mac_valid) {
-
+ }
+
+ // sanity check (i.e. no stacked devices)
+ rc = vdev_sysfs_read_attr (devpath, "ifindex", &attr_ifindex, &attr_len);
+ if (rc != 0)
+ {
+
+ log_error ("vdev_sysfs_read_attr('%s', 'ifindex') rc = %d\n",
+ devpath, rc);
+ exit (1);
+ }
+
+ rc = vdev_sysfs_read_attr (devpath, "iflink", &attr_iflink, &attr_len);
+ if (rc != 0)
+ {
+
+ log_error ("vdev_sysfs_read_attr('%s', 'iflink') rc = %d\n",
+ devpath, rc);
+
+ free (attr_ifindex);
+ exit (1);
+ }
+
+ if (strcmp (attr_ifindex, attr_iflink) != 0)
+ {
+ exit (0);
+ }
+
+ free (attr_ifindex);
+ free (attr_iflink);
+
+ // get device type
+ sprintf (devpath_uevent, "%s/uevent", devpath);
+
+ rc = vdev_read_file (devpath_uevent, &uevent_buf, &uevent_buf_len);
+ if (rc != 0)
+ {
+
+ log_error ("vdev_read_file('%s') rc = %d\n", devpath_uevent, rc);
+ exit (2);
+ }
+
+ rc = vdev_sysfs_uevent_get_key (uevent_buf, uevent_buf_len, "DEVTYPE",
+ &devtype, &devtype_len);
+ if (rc == 0)
+ {
+
+ if (strcmp ("wlan", devtype) == 0)
+ {
+ prefix = "wl";
+ }
+ else if (strcmp ("wwan", devtype) == 0)
+ {
+ prefix = "ww";
+ }
+ }
+
+ free (uevent_buf);
+ free (devtype);
+
+ err = names_mac (devpath, &names);
+ if (err >= 0 && names.mac_valid)
+ {
+
char str[IFNAMSIZ];
- snprintf(str, sizeof(str), "%sx%02x%02x%02x%02x%02x%02x", prefix,
- names.mac[0], names.mac[1], names.mac[2],
- names.mac[3], names.mac[4], names.mac[5]);
-
- vdev_property_add( "VDEV_NET_NAME_MAC", str );
-
+ snprintf (str, sizeof (str), "%sx%02x%02x%02x%02x%02x%02x",
+ prefix, names.mac[0], names.mac[1], names.mac[2],
+ names.mac[3], names.mac[4], names.mac[5]);
+
+ vdev_property_add ("VDEV_NET_NAME_MAC", str);
+
is_net_device = true;
- ieee_oui(devpath, &names);
- }
+ ieee_oui (devpath, &names);
+ }
+
+ /* get path names for Linux on System z network devices */
+ err = names_ccw (devpath, &names);
+ if (err >= 0 && names.type == NET_CCWGROUP)
+ {
- /* get path names for Linux on System z network devices */
- err = names_ccw(devpath, &names);
- if (err >= 0 && names.type == NET_CCWGROUP) {
-
char str[IFNAMSIZ];
- if (snprintf(str, sizeof(str), "%s%s", prefix, names.ccw_group) < (int)sizeof(str)) {
-
- vdev_property_add( "VDEV_NET_NAME_PATH", str );
- is_net_device = true;
- }
-
+ if (snprintf (str, sizeof (str), "%s%s", prefix, names.ccw_group)
+ < (int) sizeof (str))
+ {
+
+ vdev_property_add ("VDEV_NET_NAME_PATH", str);
+ is_net_device = true;
+ }
+
goto out;
- }
+ }
- /* get PCI based path names, we compose only PCI based paths */
- err = names_pci(devpath, &names);
- if (err < 0) {
+ /* get PCI based path names, we compose only PCI based paths */
+ err = names_pci (devpath, &names);
+ if (err < 0)
+ {
goto out;
- }
+ }
+
+ /* plain PCI device */
+ if (names.type == NET_PCI)
+ {
- /* plain PCI device */
- if (names.type == NET_PCI) {
-
char str[IFNAMSIZ];
- if (names.pci_onboard[0]) {
- if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_onboard) < (int)sizeof(str)) {
-
- vdev_property_add( "VDEV_NET_NAME_ONBOARD", str );
- is_net_device = true;
- }
- }
-
- if (names.pci_onboard_label) {
- if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_onboard_label) < (int)sizeof(str)) {
-
- vdev_property_add( "VDEV_NET_LABEL_ONBOARD", str );
- is_net_device = true;
- }
- }
-
- if (names.pci_path[0]) {
- if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_path) < (int)sizeof(str)) {
-
- vdev_property_add( "VDEV_NET_NAME_PATH", str );
- is_net_device = true;
- }
- }
-
- if (names.pci_slot[0]) {
- if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_slot) < (int)sizeof(str)) {
-
- vdev_property_add( "VDEV_NET_NAME_SLOT", str );
- is_net_device = true;
- }
- }
+ if (names.pci_onboard[0])
+ {
+ if (snprintf
+ (str, sizeof (str), "%s%s", prefix,
+ names.pci_onboard) < (int) sizeof (str))
+ {
+
+ vdev_property_add ("VDEV_NET_NAME_ONBOARD", str);
+ is_net_device = true;
+ }
+ }
+
+ if (names.pci_onboard_label)
+ {
+ if (snprintf
+ (str, sizeof (str), "%s%s", prefix,
+ names.pci_onboard_label) < (int) sizeof (str))
+ {
+
+ vdev_property_add ("VDEV_NET_LABEL_ONBOARD", str);
+ is_net_device = true;
+ }
+ }
+
+ if (names.pci_path[0])
+ {
+ if (snprintf
+ (str, sizeof (str), "%s%s", prefix,
+ names.pci_path) < (int) sizeof (str))
+ {
+
+ vdev_property_add ("VDEV_NET_NAME_PATH", str);
+ is_net_device = true;
+ }
+ }
+
+ if (names.pci_slot[0])
+ {
+ if (snprintf
+ (str, sizeof (str), "%s%s", prefix,
+ names.pci_slot) < (int) sizeof (str))
+ {
+
+ vdev_property_add ("VDEV_NET_NAME_SLOT", str);
+ is_net_device = true;
+ }
+ }
goto out;
- }
+ }
+
+ /* USB device */
+ err = names_usb (devpath, &names);
+ if (err >= 0 && names.type == NET_USB)
+ {
- /* USB device */
- err = names_usb(devpath, &names);
- if (err >= 0 && names.type == NET_USB) {
-
char str[IFNAMSIZ];
- if (names.pci_path[0]) {
- if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_path, names.usb_ports) < (int)sizeof(str)) {
-
- vdev_property_add( "VDEV_NET_NAME_PATH", str );
- is_net_device = true;
- }
- }
-
- if (names.pci_slot[0]) {
- if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_slot, names.usb_ports) < (int)sizeof(str)) {
-
- vdev_property_add( "VDEV_NET_NAME_SLOT", str );
- is_net_device = true;
- }
- }
-
+ if (names.pci_path[0])
+ {
+ if (snprintf
+ (str, sizeof (str), "%s%s%s", prefix, names.pci_path,
+ names.usb_ports) < (int) sizeof (str))
+ {
+
+ vdev_property_add ("VDEV_NET_NAME_PATH", str);
+ is_net_device = true;
+ }
+ }
+
+ if (names.pci_slot[0])
+ {
+ if (snprintf
+ (str, sizeof (str), "%s%s%s", prefix, names.pci_slot,
+ names.usb_ports) < (int) sizeof (str))
+ {
+
+ vdev_property_add ("VDEV_NET_NAME_SLOT", str);
+ is_net_device = true;
+ }
+ }
+
goto out;
- }
+ }
+
+ /* Broadcom bus */
+ err = names_bcma (devpath, &names);
+ if (err >= 0 && names.type == NET_BCMA)
+ {
- /* Broadcom bus */
- err = names_bcma(devpath, &names);
- if (err >= 0 && names.type == NET_BCMA) {
-
char str[IFNAMSIZ];
- if (names.pci_path[0]) {
- if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_path, names.bcma_core) < (int)sizeof(str)) {
-
- vdev_property_add( "VDEV_NET_NAME_PATH", str );
- is_net_device = true;
- }
- }
-
- if (names.pci_slot[0]) {
- if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_slot, names.bcma_core) < (int)sizeof(str)) {
-
- vdev_property_add( "VDEV_NET_NAME_SLOT", str );
- is_net_device = true;
- }
- }
+ if (names.pci_path[0])
+ {
+ if (snprintf
+ (str, sizeof (str), "%s%s%s", prefix, names.pci_path,
+ names.bcma_core) < (int) sizeof (str))
+ {
+
+ vdev_property_add ("VDEV_NET_NAME_PATH", str);
+ is_net_device = true;
+ }
+ }
+
+ if (names.pci_slot[0])
+ {
+ if (snprintf
+ (str, sizeof (str), "%s%s%s", prefix, names.pci_slot,
+ names.bcma_core) < (int) sizeof (str))
+ {
+
+ vdev_property_add ("VDEV_NET_NAME_SLOT", str);
+ is_net_device = true;
+ }
+ }
goto out;
- }
+ }
out:
- if( is_net_device ) {
- vdev_property_add( "VDEV_NET", "1" );
- }
-
- vdev_property_print();
- vdev_property_free_all();
-
- return EXIT_SUCCESS;
+ if (is_net_device)
+ {
+ vdev_property_add ("VDEV_NET", "1");
+ }
+
+ vdev_property_print ();
+ vdev_property_free_all ();
+
+ return EXIT_SUCCESS;
}
diff --git a/vdevd/helpers/LINUX/stat_optical.c b/vdevd/helpers/LINUX/stat_optical.c
index ef66be3..0790e45 100644
--- a/vdevd/helpers/LINUX/stat_optical.c
+++ b/vdevd/helpers/LINUX/stat_optical.c
@@ -41,78 +41,99 @@
// get drive capabilities from an open device node, using the Linux-specific CDROM_GET_CAPABILITY ioctl.
// return 0 on success
// return negative errno on error
-static int stat_optical_get_caps( int fd ) {
-
- int caps = 0;
- int rc = 0;
-
- // get the cpability
- caps = ioctl( fd, CDROM_GET_CAPABILITY, NULL );
- if( caps < 0 ) {
-
+static int
+stat_optical_get_caps (int fd)
+{
+
+ int caps = 0;
+ int rc = 0;
+
+ // get the cpability
+ caps = ioctl (fd, CDROM_GET_CAPABILITY, NULL);
+ if (caps < 0)
+ {
+
rc = -errno;
- fprintf(stderr, "[ERROR] optical: CDROM_GET_CAPABILITY ioctl failed, rc = %d\n", rc );
+ fprintf (stderr,
+ "[ERROR] optical: CDROM_GET_CAPABILITY ioctl failed, rc = %d\n",
+ rc);
return rc;
- }
-
- return caps;
-}
+ }
+ return caps;
+}
// print out optical capabilities as environment variables
-static int stat_optical_print_caps( int capabilities ) {
-
- vdev_property_add( "VDEV_OPTICAL_CD_R", (capabilities & CDC_CD_R) == 0 ? "0" : "1" );
- vdev_property_add( "VDEV_OPTICAL_CD_RW", (capabilities & CDC_CD_R) == 0 ? "0" : "1" );
- vdev_property_add( "VDEV_OPTICAL_DVD", (capabilities & CDC_DVD) == 0 ? "0" : "1" );
- vdev_property_add( "VDEV_OPTICAL_DVD_R", (capabilities & CDC_DVD_R) == 0 ? "0" : "1" );
- vdev_property_add( "VDEV_OPTICAL_DVD_RAM", (capabilities & CDC_DVD_RAM) == 0 ? "0" : "1" );
-
- vdev_property_print();
- vdev_property_free_all();
-
- return 0;
+static int
+stat_optical_print_caps (int capabilities)
+{
+
+ vdev_property_add ("VDEV_OPTICAL_CD_R",
+ (capabilities & CDC_CD_R) == 0 ? "0" : "1");
+ vdev_property_add ("VDEV_OPTICAL_CD_RW",
+ (capabilities & CDC_CD_R) == 0 ? "0" : "1");
+ vdev_property_add ("VDEV_OPTICAL_DVD",
+ (capabilities & CDC_DVD) == 0 ? "0" : "1");
+ vdev_property_add ("VDEV_OPTICAL_DVD_R",
+ (capabilities & CDC_DVD_R) == 0 ? "0" : "1");
+ vdev_property_add ("VDEV_OPTICAL_DVD_RAM",
+ (capabilities & CDC_DVD_RAM) == 0 ? "0" : "1");
+
+ vdev_property_print ();
+ vdev_property_free_all ();
+
+ return 0;
}
// usage statement
-static int usage( char const* prog_name ) {
-
- fprintf(stderr, "[ERROR] %s: Usage: %s /path/to/optical/device\n", prog_name, prog_name );
- return 0;
+static int
+usage (char const *prog_name)
+{
+
+ fprintf (stderr, "[ERROR] %s: Usage: %s /path/to/optical/device\n",
+ prog_name, prog_name);
+ return 0;
}
// entry point
-int main( int argc, char** argv ) {
-
- int rc = 0;
- int fd = 0;
- int capabilities = 0;
-
- if( argc != 2 ) {
-
- usage( argv[0] );
- exit(1);
- }
-
- // get the device node
- fd = open( argv[1], O_RDONLY | O_NONBLOCK );
- if( fd < 0 ) {
-
+int
+main (int argc, char **argv)
+{
+
+ int rc = 0;
+ int fd = 0;
+ int capabilities = 0;
+
+ if (argc != 2)
+ {
+
+ usage (argv[0]);
+ exit (1);
+ }
+ // get the device node
+ fd = open (argv[1], O_RDONLY | O_NONBLOCK);
+ if (fd < 0)
+ {
+
rc = -errno;
- fprintf(stderr, "[ERROR] %s: open('%s') rc = %d\n", argv[0], argv[1], rc );
- exit(2);
- }
-
- capabilities = stat_optical_get_caps( fd );
-
- close( fd );
-
- if( capabilities < 0 ) {
-
- fprintf(stderr, "[ERROR] %s: stat_optical_get_caps('%s') rc = %d\n", argv[0], argv[1], rc );
- exit(4);
- }
-
- stat_optical_print_caps( capabilities );
- return 0;
+ fprintf (stderr, "[ERROR] %s: open('%s') rc = %d\n", argv[0],
+ argv[1], rc);
+ exit (2);
+ }
+
+ capabilities = stat_optical_get_caps (fd);
+
+ close (fd);
+
+ if (capabilities < 0)
+ {
+
+ fprintf (stderr,
+ "[ERROR] %s: stat_optical_get_caps('%s') rc = %d\n",
+ argv[0], argv[1], rc);
+ exit (4);
+ }
+
+ stat_optical_print_caps (capabilities);
+ return 0;
}
diff --git a/vdevd/helpers/LINUX/stat_path.c b/vdevd/helpers/LINUX/stat_path.c
index e3b8d57..f6ae6b7 100644
--- a/vdevd/helpers/LINUX/stat_path.c
+++ b/vdevd/helpers/LINUX/stat_path.c
@@ -43,681 +43,777 @@
#include
#include
-static int path_prepend(char **path, const char *fmt, ...) {
- va_list va;
- char *pre;
- int err = 0;
-
- va_start(va, fmt);
- err = vasprintf(&pre, fmt, va);
- va_end(va);
- if (err < 0) {
+static int
+path_prepend (char **path, const char *fmt, ...)
+{
+ va_list va;
+ char *pre;
+ int err = 0;
+
+ va_start (va, fmt);
+ err = vasprintf (&pre, fmt, va);
+ va_end (va);
+ if (err < 0)
+ {
goto out;
- }
-
- if (*path != NULL) {
+ }
+
+ if (*path != NULL)
+ {
char *new;
- err = asprintf(&new, "%s-%s", pre, *path);
- free(pre);
- if (err < 0) {
- goto out;
- }
- free(*path);
+ err = asprintf (&new, "%s-%s", pre, *path);
+ free (pre);
+ if (err < 0)
+ {
+ goto out;
+ }
+ free (*path);
*path = new;
- } else {
+ }
+ else
+ {
*path = pre;
- }
+ }
out:
- return err;
+ return err;
}
/*
** Linux only supports 32 bit luns.
** See drivers/scsi/scsi_scan.c::scsilun_to_int() for more details.
*/
-static int format_lun_number( char const* devpath, char **path) {
-
- int lun = 0;
- int rc = vdev_sysfs_get_sysnum( devpath, &lun );
- if( rc != 0 ) {
+static int
+format_lun_number (char const *devpath, char **path)
+{
+
+ int lun = 0;
+ int rc = vdev_sysfs_get_sysnum (devpath, &lun);
+ if (rc != 0)
+ {
return rc;
- }
-
- /* address method 0, peripheral device addressing with bus id of zero */
- if (lun < 256) {
- return path_prepend(path, "lun-%lu", lun);
- }
-
- /* handle all other lun addressing methods by using a variant of the original lun format */
- return path_prepend(path, "lun-0x%04lx%04lx00000000", lun & 0xffff, (lun >> 16) & 0xffff);
-}
+ }
+ /* address method 0, peripheral device addressing with bus id of zero */
+ if (lun < 256)
+ {
+ return path_prepend (path, "lun-%lu", lun);
+ }
+
+ /* handle all other lun addressing methods by using a variant of the original lun format */
+ return path_prepend (path, "lun-0x%04lx%04lx00000000", lun & 0xffff,
+ (lun >> 16) & 0xffff);
+}
// walk up the sysfs path and skip all ancestor devices with the given subsystem.
// stop once the parent device has a different subsystem from subsys.
// return 0 on success, and set *next to the path to the deepest ancestor device that either does not have a subsystem, or has one that is different from subsys.
-static int skip_subsystem( char const* devpath, char const* subsys, char** next ) {
-
- char* cur_dev = strdup( devpath );
- char* parent = cur_dev;
-
- size_t parent_len = 0;
- int rc = 0;
-
- while( true ) {
-
- char* subsystem = NULL;
+static int
+skip_subsystem (char const *devpath, char const *subsys, char **next)
+{
+
+ char *cur_dev = strdup (devpath);
+ char *parent = cur_dev;
+
+ size_t parent_len = 0;
+ int rc = 0;
+
+ while (true)
+ {
+
+ char *subsystem = NULL;
size_t subsystem_len = 0;
-
+
int rc = 0;
-
- rc = vdev_sysfs_read_subsystem( parent, &subsystem, &subsystem_len );
-
+
+ rc = vdev_sysfs_read_subsystem (parent, &subsystem, &subsystem_len);
+
// break if not matched
- if( (rc == -ENOENT || subsystem == NULL) || strcmp( subsystem, subsys ) != 0 ) {
-
- if( subsystem != NULL ) {
- free( subsystem );
- }
- break;
- }
-
- log_debug("skip %s", parent );
-
- free( subsystem );
-
- if( cur_dev != parent ) {
- free( cur_dev );
- }
-
+ if ((rc == -ENOENT || subsystem == NULL)
+ || strcmp (subsystem, subsys) != 0)
+ {
+
+ if (subsystem != NULL)
+ {
+ free (subsystem);
+ }
+ break;
+ }
+
+ log_debug ("skip %s", parent);
+
+ free (subsystem);
+
+ if (cur_dev != parent)
+ {
+ free (cur_dev);
+ }
+
cur_dev = parent;
-
+
// matched; walk up
- rc = vdev_sysfs_get_parent_device( cur_dev, &parent, &parent_len );
- if( rc != 0 ) {
-
- break;
- }
- }
-
- *next = cur_dev;
-
- if( cur_dev != parent ) {
- free( parent );
- }
-
- log_debug("Skip from '%s' to '%s'\n", devpath, *next );
-
- return rc;
+ rc = vdev_sysfs_get_parent_device (cur_dev, &parent, &parent_len);
+ if (rc != 0)
+ {
+
+ break;
+ }
+ }
+
+ *next = cur_dev;
+
+ if (cur_dev != parent)
+ {
+ free (parent);
+ }
+
+ log_debug ("Skip from '%s' to '%s'\n", devpath, *next);
+
+ return rc;
}
// persistent name for scsi fibre channel (named by parent)
// return 0 on success, and set *new_parent to the parent device and update *path
// return negative on failure
-static int handle_scsi_fibre_channel( char const* parent, char **path, char** new_parent ) {
-
- char* port = NULL;
- size_t port_len = 0;
-
- char* lun = NULL;
-
- char* targetdev = NULL;
- size_t targetdev_len = 0;
-
- char* targetdev_sysname = NULL;
- size_t targetdev_sysname_len = 0;
-
- char* fcdev = NULL;
- size_t fcdev_len = 0;
-
- int rc = 0;
-
- // look up SCSI parent target
- rc = vdev_sysfs_get_parent_with_subsystem_devtype( parent, "scsi", "scsi_target", &targetdev, &targetdev_len );
- if( rc != 0 ) {
-
+static int
+handle_scsi_fibre_channel (char const *parent, char **path, char **new_parent)
+{
+
+ char *port = NULL;
+ size_t port_len = 0;
+
+ char *lun = NULL;
+
+ char *targetdev = NULL;
+ size_t targetdev_len = 0;
+
+ char *targetdev_sysname = NULL;
+ size_t targetdev_sysname_len = 0;
+
+ char *fcdev = NULL;
+ size_t fcdev_len = 0;
+
+ int rc = 0;
+
+ // look up SCSI parent target
+ rc = vdev_sysfs_get_parent_with_subsystem_devtype (parent, "scsi",
+ "scsi_target",
+ &targetdev,
+ &targetdev_len);
+ if (rc != 0)
+ {
+
return rc;
- }
-
- // get target device name
- rc = vdev_sysfs_get_sysname( targetdev, &targetdev_sysname, &targetdev_sysname_len );
- if( rc != 0 ) {
-
- free( targetdev );
+ }
+ // get target device name
+ rc = vdev_sysfs_get_sysname (targetdev, &targetdev_sysname,
+ &targetdev_sysname_len);
+ if (rc != 0)
+ {
+
+ free (targetdev);
return rc;
- }
-
- // find the corresponding fibrechannel sysfs path
- rc = vdev_sysfs_device_path_from_subsystem_sysname( "/sys", "fc_transport", targetdev_sysname, &fcdev, &fcdev_len );
- if( rc != 0 ) {
-
- free( targetdev );
- free( targetdev_sysname );
+ }
+ // find the corresponding fibrechannel sysfs path
+ rc = vdev_sysfs_device_path_from_subsystem_sysname ("/sys",
+ "fc_transport",
+ targetdev_sysname,
+ &fcdev, &fcdev_len);
+ if (rc != 0)
+ {
+
+ free (targetdev);
+ free (targetdev_sysname);
return rc;
- }
-
- free( targetdev_sysname );
-
- // look up the port name
- rc = vdev_sysfs_read_attr( fcdev, "port_name", &port, &port_len );
- if( rc != 0 ) {
-
- free( targetdev );
+ }
+
+ free (targetdev_sysname);
+
+ // look up the port name
+ rc = vdev_sysfs_read_attr (fcdev, "port_name", &port, &port_len);
+ if (rc != 0)
+ {
+
+ free (targetdev);
return rc;
- }
-
- free( fcdev );
-
- // parse port name
- rc = format_lun_number( parent, &lun );
-
- path_prepend( path, "fc-%s-%s", port, lun );
-
- if( lun != NULL ) {
- free( lun );
- }
-
- // parent stays the same
- *new_parent = strdup( parent );
- if( *new_parent == NULL ) {
-
+ }
+
+ free (fcdev);
+
+ // parse port name
+ rc = format_lun_number (parent, &lun);
+
+ path_prepend (path, "fc-%s-%s", port, lun);
+
+ if (lun != NULL)
+ {
+ free (lun);
+ }
+ // parent stays the same
+ *new_parent = strdup (parent);
+ if (*new_parent == NULL)
+ {
+
return -ENOMEM;
- }
-
- return 0;
+ }
+
+ return 0;
}
// persistent name for SCSI SAS wide port
// return 0 on success, and update *path with the new persistent name information and set *new_parent to the next parent to parse
// return negative on error
-static int handle_scsi_sas_wide_port( char const *parent, char **path, char** new_parent ) {
-
- char* targetdev = NULL;
- size_t targetdev_len = 0;
-
- char* targetparent = NULL;
- size_t targetparent_len = 0;
-
- char* targetparent_sysname = NULL;
- size_t targetparent_sysname_len = 0;
-
- char* sasdev = NULL;
- size_t sasdev_len = 0;
-
- char* sas_address = NULL;
- size_t sas_address_len = 0;
-
- char* lun = NULL;
-
- int rc = 0;
-
- rc = vdev_sysfs_get_parent_with_subsystem_devtype( parent, "scsi", "scsi_target", &targetdev, &targetdev_len );
- if( rc != 0 ) {
+static int
+handle_scsi_sas_wide_port (char const *parent, char **path, char **new_parent)
+{
+
+ char *targetdev = NULL;
+ size_t targetdev_len = 0;
+
+ char *targetparent = NULL;
+ size_t targetparent_len = 0;
+
+ char *targetparent_sysname = NULL;
+ size_t targetparent_sysname_len = 0;
+
+ char *sasdev = NULL;
+ size_t sasdev_len = 0;
+
+ char *sas_address = NULL;
+ size_t sas_address_len = 0;
+
+ char *lun = NULL;
+
+ int rc = 0;
+
+ rc = vdev_sysfs_get_parent_with_subsystem_devtype (parent, "scsi",
+ "scsi_target",
+ &targetdev,
+ &targetdev_len);
+ if (rc != 0)
+ {
return rc;
- }
-
- rc = vdev_sysfs_get_parent_device( parent, &targetparent, &targetparent_len );
- if( rc != 0 ) {
-
- free( targetdev );
+ }
+
+ rc = vdev_sysfs_get_parent_device (parent, &targetparent,
+ &targetparent_len);
+ if (rc != 0)
+ {
+
+ free (targetdev);
return rc;
- }
-
- rc = vdev_sysfs_get_sysname( targetparent, &targetparent_sysname, &targetparent_sysname_len );
- if( rc != 0 ) {
-
- free( targetdev );
- free( targetparent );
+ }
+
+ rc = vdev_sysfs_get_sysname (targetparent, &targetparent_sysname,
+ &targetparent_sysname_len);
+ if (rc != 0)
+ {
+
+ free (targetdev);
+ free (targetparent);
return rc;
- }
-
- // find the sas device
- rc = vdev_sysfs_device_path_from_subsystem_sysname( "/sys", "sas_device", targetparent_sysname, &sasdev, &sasdev_len );
-
- free( targetparent );
- free( targetparent_sysname );
-
- if( rc != 0 ) {
-
- free( targetdev );
+ }
+ // find the sas device
+ rc = vdev_sysfs_device_path_from_subsystem_sysname ("/sys", "sas_device",
+ targetparent_sysname,
+ &sasdev, &sasdev_len);
+
+ free (targetparent);
+ free (targetparent_sysname);
+
+ if (rc != 0)
+ {
+
+ free (targetdev);
return rc;
- }
-
- // find the address
- rc = vdev_sysfs_read_attr( sasdev, "sas_address", &sas_address, &sas_address_len );
- if( rc != 0 ) {
-
- free( targetdev );
+ }
+ // find the address
+ rc = vdev_sysfs_read_attr (sasdev, "sas_address", &sas_address,
+ &sas_address_len);
+ if (rc != 0)
+ {
+
+ free (targetdev);
return rc;
- }
-
- format_lun_number( parent, &lun );
- path_prepend( path, "sas-%s-%s", sas_address, lun );
-
- if( lun != NULL ) {
- free( lun );
- }
-
- free( targetdev );
-
- *new_parent = strdup( parent );
- if( *new_parent == NULL ) {
-
+ }
+
+ format_lun_number (parent, &lun);
+ path_prepend (path, "sas-%s-%s", sas_address, lun);
+
+ if (lun != NULL)
+ {
+ free (lun);
+ }
+
+ free (targetdev);
+
+ *new_parent = strdup (parent);
+ if (*new_parent == NULL)
+ {
+
return -ENOMEM;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// get the persistent path for a SCSI SAS
// return 0 on success, and update *path with the persistent path information for this device, and set *parent to the next parent to process
// return negative on error
-static int handle_scsi_sas( char const* parent, char **path, char** new_parent ) {
-
- char* targetdev = NULL;
- size_t targetdev_len = 0;
-
- char* target_parent = NULL;
- size_t target_parent_len = 0;
-
- char* target_parent_sysname = NULL;
- size_t target_parent_sysname_len = 0;
-
- char* port = NULL;
- size_t port_len = 0;
-
- char* port_sysname = NULL;
- size_t port_sysname_len = 0;
-
- char* expander = NULL;
- size_t expander_len = 0;
-
- char* expander_sysname = NULL;
- size_t expander_sysname_len = 0;
-
- char* target_sasdev = NULL;
- size_t target_sasdev_len = 0;
-
- char* expander_sasdev = NULL;
- size_t expander_sasdev_len = 0;
-
- char* port_sasdev = NULL;
- size_t port_sasdev_len = 0;
-
- char* sas_address = NULL;
- size_t sas_address_len = 0;
-
- char* phy_id = NULL;
- size_t phy_id_len = 0;
-
- char* phy_count = NULL;
- size_t phy_count_len = 0;
-
- char* lun = NULL;
-
- int rc = 0;
-
- // find scsi target parent device
- rc = vdev_sysfs_get_parent_with_subsystem_devtype( parent, "scsi", "scsi_target", &targetdev, &targetdev_len );
- if( rc != 0 ) {
-
+static int
+handle_scsi_sas (char const *parent, char **path, char **new_parent)
+{
+
+ char *targetdev = NULL;
+ size_t targetdev_len = 0;
+
+ char *target_parent = NULL;
+ size_t target_parent_len = 0;
+
+ char *target_parent_sysname = NULL;
+ size_t target_parent_sysname_len = 0;
+
+ char *port = NULL;
+ size_t port_len = 0;
+
+ char *port_sysname = NULL;
+ size_t port_sysname_len = 0;
+
+ char *expander = NULL;
+ size_t expander_len = 0;
+
+ char *expander_sysname = NULL;
+ size_t expander_sysname_len = 0;
+
+ char *target_sasdev = NULL;
+ size_t target_sasdev_len = 0;
+
+ char *expander_sasdev = NULL;
+ size_t expander_sasdev_len = 0;
+
+ char *port_sasdev = NULL;
+ size_t port_sasdev_len = 0;
+
+ char *sas_address = NULL;
+ size_t sas_address_len = 0;
+
+ char *phy_id = NULL;
+ size_t phy_id_len = 0;
+
+ char *phy_count = NULL;
+ size_t phy_count_len = 0;
+
+ char *lun = NULL;
+
+ int rc = 0;
+
+ // find scsi target parent device
+ rc = vdev_sysfs_get_parent_with_subsystem_devtype (parent, "scsi",
+ "scsi_target",
+ &targetdev,
+ &targetdev_len);
+ if (rc != 0)
+ {
+
return rc;
- }
-
- // find parent of the scsi target
- rc = vdev_sysfs_get_parent_device( targetdev, &target_parent, &target_parent_len );
-
- free( targetdev );
-
- if( rc != 0 ) {
-
+ }
+ // find parent of the scsi target
+ rc = vdev_sysfs_get_parent_device (targetdev, &target_parent,
+ &target_parent_len);
+
+ free (targetdev);
+
+ if (rc != 0)
+ {
+
return rc;
- }
-
- // get parent sysname
- rc = vdev_sysfs_get_sysname( target_parent, &target_parent_sysname, &target_parent_sysname_len );
- if( rc != 0 ) {
-
- free( target_parent );
+ }
+ // get parent sysname
+ rc = vdev_sysfs_get_sysname (target_parent, &target_parent_sysname,
+ &target_parent_sysname_len);
+ if (rc != 0)
+ {
+
+ free (target_parent);
return rc;
- }
-
- // get sas device
- rc = vdev_sysfs_device_path_from_subsystem_sysname( "/sys", "sas_device", target_parent_sysname, &target_sasdev, &target_sasdev_len );
-
- free( target_parent );
-
- if( rc != 0 ) {
-
+ }
+ // get sas device
+ rc = vdev_sysfs_device_path_from_subsystem_sysname ("/sys", "sas_device",
+ target_parent_sysname,
+ &target_sasdev,
+ &target_sasdev_len);
+
+ free (target_parent);
+
+ if (rc != 0)
+ {
+
return rc;
- }
-
- // get the sas port (parent of the sas device)
- rc = vdev_sysfs_get_parent_device( target_parent, &port, &port_len );
- if( rc != 0 ) {
-
- free( target_sasdev );
+ }
+ // get the sas port (parent of the sas device)
+ rc = vdev_sysfs_get_parent_device (target_parent, &port, &port_len);
+ if (rc != 0)
+ {
+
+ free (target_sasdev);
return rc;
- }
-
- // get sas port sysname
- rc = vdev_sysfs_get_sysname( port, &port_sysname, &port_sysname_len );
- if( rc != 0 ) {
-
- free( target_sasdev );
- free( port );
+ }
+ // get sas port sysname
+ rc = vdev_sysfs_get_sysname (port, &port_sysname, &port_sysname_len);
+ if (rc != 0)
+ {
+
+ free (target_sasdev);
+ free (port);
return rc;
- }
-
- // get the port device
- rc = vdev_sysfs_device_path_from_subsystem_sysname( "/sys", "sas_port", port_sysname, &port_sasdev, &port_sasdev_len );
-
- free( port_sysname );
-
- if( rc != 0 ) {
-
- free( target_sasdev );
- free( port );
+ }
+ // get the port device
+ rc = vdev_sysfs_device_path_from_subsystem_sysname ("/sys", "sas_port",
+ port_sysname,
+ &port_sasdev,
+ &port_sasdev_len);
+
+ free (port_sysname);
+
+ if (rc != 0)
+ {
+
+ free (target_sasdev);
+ free (port);
return rc;
- }
-
- // get phy count for this sas device
- rc = vdev_sysfs_read_attr( port_sasdev, "num_phys", &phy_count, &phy_count_len );
- if( rc != 0 ) {
-
- free( target_sasdev );
- free( port_sasdev );
- free( port );
+ }
+ // get phy count for this sas device
+ rc = vdev_sysfs_read_attr (port_sasdev, "num_phys", &phy_count,
+ &phy_count_len);
+ if (rc != 0)
+ {
+
+ free (target_sasdev);
+ free (port_sasdev);
+ free (port);
return rc;
- }
-
- // one disk?
- if( strncmp( phy_count, "1", 2 ) != 0 ) {
-
+ }
+ // one disk?
+ if (strncmp (phy_count, "1", 2) != 0)
+ {
+
// wide port
- rc = handle_scsi_sas_wide_port( parent, path, new_parent );
-
- free( target_sasdev );
- free( port_sasdev );
-
+ rc = handle_scsi_sas_wide_port (parent, path, new_parent);
+
+ free (target_sasdev);
+ free (port_sasdev);
+
return rc;
- }
-
- free( phy_count );
-
- // multiple disks...
- // which one is this?
- rc = vdev_sysfs_read_attr( target_sasdev, "phy_identifier", &phy_id, &phy_id_len );
-
- free( target_sasdev );
-
- if( rc != 0 ) {
-
- free( port );
+ }
+
+ free (phy_count);
+
+ // multiple disks...
+ // which one is this?
+ rc = vdev_sysfs_read_attr (target_sasdev, "phy_identifier", &phy_id,
+ &phy_id_len);
+
+ free (target_sasdev);
+
+ if (rc != 0)
+ {
+
+ free (port);
return rc;
- }
-
- // parent is either an HBA or expander device...
- rc = vdev_sysfs_get_parent_device( port, &expander, &expander_len );
-
- free( port );
-
- if( rc != 0 ) {
-
- free( phy_id );
+ }
+ // parent is either an HBA or expander device...
+ rc = vdev_sysfs_get_parent_device (port, &expander, &expander_len);
+
+ free (port);
+
+ if (rc != 0)
+ {
+
+ free (phy_id);
return rc;
- }
-
- // get the expander sysname
- rc = vdev_sysfs_get_sysname( expander, &expander_sysname, &expander_sysname_len );
- if( rc != 0 ) {
-
- free( phy_id );
- free( expander );
+ }
+ // get the expander sysname
+ rc = vdev_sysfs_get_sysname (expander, &expander_sysname,
+ &expander_sysname_len);
+ if (rc != 0)
+ {
+
+ free (phy_id);
+ free (expander);
return rc;
- }
-
- free( expander );
-
- // get the expander sas device
- rc = vdev_sysfs_device_path_from_subsystem_sysname( "/sys", "sas_device", expander_sysname, &expander_sasdev, &expander_sasdev_len );
-
- free( expander_sysname );
-
- if( rc == 0 ) {
-
+ }
+
+ free (expander);
+
+ // get the expander sas device
+ rc = vdev_sysfs_device_path_from_subsystem_sysname ("/sys", "sas_device",
+ expander_sysname,
+ &expander_sasdev,
+ &expander_sasdev_len);
+
+ free (expander_sysname);
+
+ if (rc == 0)
+ {
+
// has expander device
// get its address
- rc = vdev_sysfs_read_attr( expander_sasdev, "sas_address", &sas_address, &sas_address_len );
- free( expander_sasdev );
-
- if( rc != 0 ) {
-
- free( phy_id );
- return rc;
- }
- }
-
- format_lun_number( parent, &lun );
-
- if( sas_address != NULL ) {
-
- path_prepend(path, "sas-exp%s-phy%s-%s", sas_address, phy_id, lun);
- free( sas_address );
- }
- else {
-
- path_prepend(path, "sas-phy%s-%s", phy_id, lun);
- }
-
- if( lun != NULL ) {
- free( lun );
- }
-
- free( phy_id );
-
- *new_parent = strdup( parent );
- if( *new_parent == NULL ) {
-
+ rc = vdev_sysfs_read_attr (expander_sasdev, "sas_address",
+ &sas_address, &sas_address_len);
+ free (expander_sasdev);
+
+ if (rc != 0)
+ {
+
+ free (phy_id);
+ return rc;
+ }
+ }
+
+ format_lun_number (parent, &lun);
+
+ if (sas_address != NULL)
+ {
+
+ path_prepend (path, "sas-exp%s-phy%s-%s", sas_address, phy_id, lun);
+ free (sas_address);
+ }
+ else
+ {
+
+ path_prepend (path, "sas-phy%s-%s", phy_id, lun);
+ }
+
+ if (lun != NULL)
+ {
+ free (lun);
+ }
+
+ free (phy_id);
+
+ *new_parent = strdup (parent);
+ if (*new_parent == NULL)
+ {
+
return -ENOMEM;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// generate persistent path for iscsi devices
// return 0 on success, and update *path with this device's persistent path information, and set *parent to the next parent device to explore
// return negative on errror
-static int handle_scsi_iscsi( char const* parent, char **path, char** new_parent ) {
-
- char* transportdev = NULL;
-
- char* transportdev_sysname = NULL;
- size_t transportdev_sysname_len = 0;
-
- char* sessiondev = NULL;
- size_t sessiondev_len = 0;
-
- char* target = NULL;
- size_t target_len = 0;
-
- char* connname = NULL;
-
- char* conndev = NULL;
- size_t conndev_len = 0;
-
- char* addr = NULL;
- size_t addr_len = 0;
-
- char* port = NULL;
- size_t port_len = 0;
-
- char* lun = NULL;
-
- int rc = 0;
-
- // find iscsi session
- transportdev = (char*)parent;
-
- while( 1 ) {
-
- char* transport_parent = NULL;
+static int
+handle_scsi_iscsi (char const *parent, char **path, char **new_parent)
+{
+
+ char *transportdev = NULL;
+
+ char *transportdev_sysname = NULL;
+ size_t transportdev_sysname_len = 0;
+
+ char *sessiondev = NULL;
+ size_t sessiondev_len = 0;
+
+ char *target = NULL;
+ size_t target_len = 0;
+
+ char *connname = NULL;
+
+ char *conndev = NULL;
+ size_t conndev_len = 0;
+
+ char *addr = NULL;
+ size_t addr_len = 0;
+
+ char *port = NULL;
+ size_t port_len = 0;
+
+ char *lun = NULL;
+
+ int rc = 0;
+
+ // find iscsi session
+ transportdev = (char *) parent;
+
+ while (1)
+ {
+
+ char *transport_parent = NULL;
size_t transport_parent_len = 0;
-
- rc = vdev_sysfs_get_parent_device( transportdev, &transport_parent, &transport_parent_len );
- if( rc != 0 ) {
-
- return rc;
- }
-
+
+ rc = vdev_sysfs_get_parent_device (transportdev,
+ &transport_parent,
+ &transport_parent_len);
+ if (rc != 0)
+ {
+
+ return rc;
+ }
+
transportdev = transport_parent;
- if( strncmp( transportdev, "session", strlen("session") ) == 0 ) {
-
- break;
- }
-
- free( transportdev );
- }
-
- // find tranport dev sysname
- rc = vdev_sysfs_get_sysname( transportdev, &transportdev_sysname, &transportdev_sysname_len );
- if( rc != 0 ) {
-
- free( transportdev );
+ if (strncmp (transportdev, "session", strlen ("session")) == 0)
+ {
+
+ break;
+ }
+
+ free (transportdev);
+ }
+
+ // find tranport dev sysname
+ rc = vdev_sysfs_get_sysname (transportdev, &transportdev_sysname,
+ &transportdev_sysname_len);
+ if (rc != 0)
+ {
+
+ free (transportdev);
return rc;
- }
-
- free( transportdev );
-
- // find iscsi session device
- rc = vdev_sysfs_device_path_from_subsystem_sysname( "/sys", "iscsi_session", transportdev_sysname, &sessiondev, &sessiondev_len );
- if( rc != 0 ) {
-
- free( transportdev_sysname );
+ }
+
+ free (transportdev);
+
+ // find iscsi session device
+ rc = vdev_sysfs_device_path_from_subsystem_sysname ("/sys",
+ "iscsi_session",
+ transportdev_sysname,
+ &sessiondev,
+ &sessiondev_len);
+ if (rc != 0)
+ {
+
+ free (transportdev_sysname);
return rc;
- }
-
- // read the target
- rc = vdev_sysfs_read_attr( sessiondev, "targetname", &target, &target_len );
-
- free( sessiondev );
-
- if( rc != 0 ) {
-
- free( transportdev_sysname );
+ }
+ // read the target
+ rc = vdev_sysfs_read_attr (sessiondev, "targetname", &target, &target_len);
+
+ free (sessiondev);
+
+ if (rc != 0)
+ {
+
+ free (transportdev_sysname);
return rc;
- }
-
- rc = asprintf( &connname, "connection%s:0", transportdev_sysname );
-
- free( transportdev_sysname );
-
- if( rc < 0 ) {
-
- free( target );
- free( connname );
+ }
+
+ rc = asprintf (&connname, "connection%s:0", transportdev_sysname);
+
+ free (transportdev_sysname);
+
+ if (rc < 0)
+ {
+
+ free (target);
+ free (connname);
return rc;
- }
-
- // find connection device
- rc = vdev_sysfs_device_path_from_subsystem_sysname( "/sys", "iscsi_connection", connname, &conndev, &conndev_len );
-
- free( connname );
-
- if( rc != 0 ) {
-
- free( target );
+ }
+ // find connection device
+ rc = vdev_sysfs_device_path_from_subsystem_sysname ("/sys",
+ "iscsi_connection",
+ connname, &conndev,
+ &conndev_len);
+
+ free (connname);
+
+ if (rc != 0)
+ {
+
+ free (target);
return rc;
- }
-
- // look up address
- rc = vdev_sysfs_read_attr( conndev, "persistent_address", &addr, &addr_len );
- if( rc != 0 ) {
-
- free( target );
+ }
+ // look up address
+ rc = vdev_sysfs_read_attr (conndev, "persistent_address", &addr, &addr_len);
+ if (rc != 0)
+ {
+
+ free (target);
return rc;
- }
-
- // look up port
- rc = vdev_sysfs_read_attr( conndev, "persistent_port", &port, &port_len );
- if( rc != 0 ) {
-
- free( addr );
- free( target );
+ }
+ // look up port
+ rc = vdev_sysfs_read_attr (conndev, "persistent_port", &port, &port_len);
+ if (rc != 0)
+ {
+
+ free (addr);
+ free (target);
return rc;
- }
-
- // make the name!
- format_lun_number( parent, &lun );
- path_prepend( path, "ip-%s:%s-iscsi-%s-%s", addr, port, target, lun );
-
- if( lun != NULL ) {
-
- free( lun );
- }
-
- free( port );
- free( target );
- free( addr );
-
- *new_parent = strdup( parent );
- if( *new_parent == NULL ) {
-
- return -ENOMEM;
- }
-
- return 0;
-}
+ }
+ // make the name!
+ format_lun_number (parent, &lun);
+ path_prepend (path, "ip-%s:%s-iscsi-%s-%s", addr, port, target, lun);
+
+ if (lun != NULL)
+ {
+
+ free (lun);
+ }
+ free (port);
+ free (target);
+ free (addr);
+ *new_parent = strdup (parent);
+ if (*new_parent == NULL)
+ {
+
+ return -ENOMEM;
+ }
+
+ return 0;
+}
// get scsi host information
// return 0 on success
// return negative on failure
-static int scsi_read_host_info( char const* parent, char** hostdev, int* host, int* bus, int* target, int* lun ) {
-
- int rc = 0;
-
- size_t hostdev_len = 0;
-
- char* name = NULL;
- size_t name_len = 0;
-
- // find scsi host parent device
- rc = vdev_sysfs_device_path_from_subsystem_sysname( parent, "scsi", "scsi_host", hostdev, &hostdev_len );
- if( rc != 0 ) {
-
+static int
+scsi_read_host_info (char const *parent, char **hostdev, int *host,
+ int *bus, int *target, int *lun)
+{
+
+ int rc = 0;
+
+ size_t hostdev_len = 0;
+
+ char *name = NULL;
+ size_t name_len = 0;
+
+ // find scsi host parent device
+ rc = vdev_sysfs_device_path_from_subsystem_sysname (parent, "scsi",
+ "scsi_host", hostdev,
+ &hostdev_len);
+ if (rc != 0)
+ {
+
return rc;
- }
-
- // get sysname of scsi host
- rc = vdev_sysfs_get_sysname( parent, &name, &name_len );
- if( rc != 0 ) {
-
- free( *hostdev );
+ }
+ // get sysname of scsi host
+ rc = vdev_sysfs_get_sysname (parent, &name, &name_len);
+ if (rc != 0)
+ {
+
+ free (*hostdev);
*hostdev = NULL;
-
+
return rc;
- }
-
- // read host, bus, target, and lun
- rc = sscanf( name, "%d:%d:%d:%d", host, bus, target, lun );
- if( rc != 4 ) {
-
+ }
+ // read host, bus, target, and lun
+ rc = sscanf (name, "%d:%d:%d:%d", host, bus, target, lun);
+ if (rc != 4)
+ {
+
// invalid name
- free( *hostdev );
+ free (*hostdev);
*hostdev = NULL;
-
- free( name );
+
+ free (name);
return -EINVAL;
- }
-
- free( name );
-
- return 0;
+ }
+
+ free (name);
+
+ return 0;
}
/*
@@ -737,359 +833,390 @@ static int scsi_read_host_info( char const* parent, char** hostdev, int* host, i
* this. Manual driver unbind/bind, parallel hotplug/unplug will
* get into the way of this "I hope it works" logic.
*/
-static int scsi_host_offset( char const* hostdev_sysname ) {
-
- DIR* dir = NULL;
- struct dirent* dent = NULL;
- char* base = NULL;
- char* pos = NULL;
- int basenum = -1;
- int rc = 0;
-
- base = strdup( hostdev_sysname );
- if( base == NULL ) {
+static int
+scsi_host_offset (char const *hostdev_sysname)
+{
+
+ DIR *dir = NULL;
+ struct dirent *dent = NULL;
+ char *base = NULL;
+ char *pos = NULL;
+ int basenum = -1;
+ int rc = 0;
+
+ base = strdup (hostdev_sysname);
+ if (base == NULL)
+ {
return -ENOMEM;
- }
-
- // sanity check
- pos = strrchr(base, '/');
- if (pos == NULL) {
-
- free( base );
+ }
+ // sanity check
+ pos = strrchr (base, '/');
+ if (pos == NULL)
+ {
+
+ free (base);
return -EINVAL;
- }
-
- // make base its dirname
- pos[0] = '\0';
-
- dir = opendir(base);
-
- if (dir == NULL) {
-
+ }
+ // make base its dirname
+ pos[0] = '\0';
+
+ dir = opendir (base);
+
+ if (dir == NULL)
+ {
+
rc = -errno;
- free( base );
+ free (base);
return rc;
- }
-
- for( dent = readdir( dir ); dent != NULL; dent = readdir( dir ) ) {
-
- char* rest = NULL;
+ }
+
+ for (dent = readdir (dir); dent != NULL; dent = readdir (dir))
+ {
+
+ char *rest = NULL;
int i = 0;
-
+
// skip . and ..
- if( dent->d_name[0] == '.' ) {
- continue;
- }
-
+ if (dent->d_name[0] == '.')
+ {
+ continue;
+ }
// only regular files
- if( dent->d_type != DT_DIR && dent->d_type != DT_LNK ) {
- continue;
- }
-
+ if (dent->d_type != DT_DIR && dent->d_type != DT_LNK)
+ {
+ continue;
+ }
// only files that start with "host"
- if( strncmp( dent->d_name, "host", strlen("host") ) != 0 ) {
- continue;
- }
-
+ if (strncmp (dent->d_name, "host", strlen ("host")) != 0)
+ {
+ continue;
+ }
// get base number
- i = strtoul( &dent->d_name[4], &rest, 10 );
- if( rest[0] != '\0' ) {
- continue;
- }
-
+ i = strtoul (&dent->d_name[4], &rest, 10);
+ if (rest[0] != '\0')
+ {
+ continue;
+ }
+
/*
* find the smallest number; the host really needs to export its
* own instance number per parent device; relying on the global host
* enumeration and plainly rebasing the numbers sounds unreliable
*/
- if( basenum == -1 || i < basenum ) {
- basenum = i;
- }
- }
-
- closedir( dir );
-
- if( basenum == -1 ) {
-
+ if (basenum == -1 || i < basenum)
+ {
+ basenum = i;
+ }
+ }
+
+ closedir (dir);
+
+ if (basenum == -1)
+ {
+
// not found
return -ENOENT;
- }
-
- return basenum;
-}
+ }
+ return basenum;
+}
// persistent default scsi path
// return 0 on success, and update *path with the scsi path information, and set *parent to the next parent device to explore
// return negative on error.
-static int handle_scsi_default( char const* parent, char **path, char** new_parent ) {
-
- int rc = 0;
- int attempts = 5; // arbitrary
-
- while( 1 ) {
-
+static int
+handle_scsi_default (char const *parent, char **path, char **new_parent)
+{
+
+ int rc = 0;
+ int attempts = 5; // arbitrary
+
+ while (1)
+ {
+
int host = 0, bus = 0, target = 0, lun = 0;
int host2 = 0, bus2 = 0, target2 = 0, lun2 = 0;
int host_offset = 0;
- char* hostdev = NULL;
- char* hostdev2 = NULL;
-
- char* hostdev_sysname = NULL;
+ char *hostdev = NULL;
+ char *hostdev2 = NULL;
+
+ char *hostdev_sysname = NULL;
size_t hostdev_sysname_len = 0;
-
+
// get host info
- rc = scsi_read_host_info( parent, &hostdev, &host, &bus, &target, &lun );
-
- if( rc != 0 ) {
-
- return rc;
- }
-
+ rc = scsi_read_host_info (parent, &hostdev, &host, &bus, &target, &lun);
+
+ if (rc != 0)
+ {
+
+ return rc;
+ }
// get host sysname
- rc = vdev_sysfs_get_sysname( hostdev, &hostdev_sysname, &hostdev_sysname_len );
- if( rc != 0 ) {
-
- free( hostdev );
- return rc;
- }
-
+ rc = vdev_sysfs_get_sysname (hostdev, &hostdev_sysname,
+ &hostdev_sysname_len);
+ if (rc != 0)
+ {
+
+ free (hostdev);
+ return rc;
+ }
// get host offset
- host_offset = scsi_host_offset( hostdev_sysname );
-
- free( hostdev_sysname );
-
- if( host_offset < 0 ) {
-
- return -ENODATA;
- }
-
+ host_offset = scsi_host_offset (hostdev_sysname);
+
+ free (hostdev_sysname);
+
+ if (host_offset < 0)
+ {
+
+ return -ENODATA;
+ }
// get the host info, again, and verify that the kernel didn't race us
- rc = scsi_read_host_info( parent, &hostdev2, &host2, &bus2, &target2, &lun2 );
-
- if( rc != 0 ) {
-
- free( hostdev );
- return rc;
- }
-
+ rc = scsi_read_host_info (parent, &hostdev2, &host2, &bus2,
+ &target2, &lun2);
+
+ if (rc != 0)
+ {
+
+ free (hostdev);
+ return rc;
+ }
// verify that nothing changed
- if( strcmp(hostdev, hostdev2) != 0 || host != host2 || bus != bus2 || target != target2 || lun != lun2 ) {
-
- free( hostdev );
- free( hostdev2 );
-
- // let the driver settle
- sleep(1);
-
- attempts--;
- if( attempts <= 0 ) {
-
- return -ETIMEDOUT;
- }
-
- continue;
- }
-
+ if (strcmp (hostdev, hostdev2) != 0 || host != host2
+ || bus != bus2 || target != target2 || lun != lun2)
+ {
+
+ free (hostdev);
+ free (hostdev2);
+
+ // let the driver settle
+ sleep (1);
+
+ attempts--;
+ if (attempts <= 0)
+ {
+
+ return -ETIMEDOUT;
+ }
+
+ continue;
+ }
// success
- free( hostdev2 );
-
+ free (hostdev2);
+
// success!
host -= host_offset;
-
- path_prepend(path, "scsi-%u:%u:%u:%u", host, bus, target, lun);
-
+
+ path_prepend (path, "scsi-%u:%u:%u:%u", host, bus, target, lun);
+
*new_parent = hostdev;
break;
- }
-
- return 0;
-}
-
+ }
+ return 0;
+}
// create persistent path for a hyperv scsi device
// return 0 on success, and append persistent path info to *path and set *new_parent to the next parent device to explore
// return negative on error
-static int handle_scsi_hyperv( char const* parent, char **path, char** new_parent ) {
-
- char* hostdev = NULL;
- size_t hostdev_len = 0;
-
- char* vmbusdev = NULL;
- size_t vmbusdev_len = 0;
-
- char* guid_str = NULL;
- size_t guid_str_len = 0;
-
- char* lun = NULL;
-
- char guid[38];
- memset( guid, 0, 38 );
-
- size_t i = 0;
- size_t k = 0;
-
- int rc = 0;
-
- // get scsi host parent device
- rc = vdev_sysfs_get_parent_with_subsystem_devtype( parent, "scsi", "scsi_host", &hostdev, &hostdev_len );
- if( rc != 0 ) {
-
+static int
+handle_scsi_hyperv (char const *parent, char **path, char **new_parent)
+{
+
+ char *hostdev = NULL;
+ size_t hostdev_len = 0;
+
+ char *vmbusdev = NULL;
+ size_t vmbusdev_len = 0;
+
+ char *guid_str = NULL;
+ size_t guid_str_len = 0;
+
+ char *lun = NULL;
+
+ char guid[38];
+ memset (guid, 0, 38);
+
+ size_t i = 0;
+ size_t k = 0;
+
+ int rc = 0;
+
+ // get scsi host parent device
+ rc = vdev_sysfs_get_parent_with_subsystem_devtype (parent, "scsi",
+ "scsi_host", &hostdev,
+ &hostdev_len);
+ if (rc != 0)
+ {
+
return rc;
- }
-
- // get vmbus device--parent of scsi host
- rc = vdev_sysfs_get_parent_device( hostdev, &vmbusdev, &vmbusdev_len );
- if( rc != 0 ) {
-
- free( hostdev );
+ }
+ // get vmbus device--parent of scsi host
+ rc = vdev_sysfs_get_parent_device (hostdev, &vmbusdev, &vmbusdev_len);
+ if (rc != 0)
+ {
+
+ free (hostdev);
return rc;
- }
-
- // get the guid
- rc = vdev_sysfs_read_attr( vmbusdev, "device_id", &guid_str, &guid_str_len );
-
- free( hostdev );
- free( vmbusdev );
-
- if( rc != 0 ) {
-
+ }
+ // get the guid
+ rc = vdev_sysfs_read_attr (vmbusdev, "device_id", &guid_str, &guid_str_len);
+
+ free (hostdev);
+ free (vmbusdev);
+
+ if (rc != 0)
+ {
+
return rc;
- }
-
- // sanity check
- if( strlen(guid_str) < 37 || guid_str[0] != '{' || guid_str[36] != '}' ) {
-
+ }
+ // sanity check
+ if (strlen (guid_str) < 37 || guid_str[0] != '{' || guid_str[36] != '}')
+ {
+
return -EINVAL;
- }
-
- // remove '-'
- for( i = 0, k = 0; i < 36; i++ ) {
-
- if( guid_str[i] == '-' ) {
- continue;
- }
-
+ }
+ // remove '-'
+ for (i = 0, k = 0; i < 36; i++)
+ {
+
+ if (guid_str[i] == '-')
+ {
+ continue;
+ }
+
guid[k] = guid_str[i];
k++;
- }
- guid[k] = '\0';
-
- format_lun_number( parent, &lun );
- path_prepend(path, "vmbus-%s-%s", guid, lun);
-
- if( lun != NULL ) {
- free( lun );
- }
-
- *new_parent = strdup( parent );
- if( *new_parent == NULL ) {
-
+ }
+ guid[k] = '\0';
+
+ format_lun_number (parent, &lun);
+ path_prepend (path, "vmbus-%s-%s", guid, lun);
+
+ if (lun != NULL)
+ {
+ free (lun);
+ }
+
+ *new_parent = strdup (parent);
+ if (*new_parent == NULL)
+ {
+
return -ENOMEM;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// generate persistent device name for a scsi device. dispatch to implementation-specific handlers.
// return 0 on success, and prepend *path with the persistent name for this device. Set *new_parent to the next parent to explore, and set
// *supported_parent to true if this device has a parent we support for persistent names.
// return negative on failure.
-static int handle_scsi( char const* parent, char **path, char** new_parent, bool *supported_parent ) {
-
- char* devtype = NULL;
- size_t devtype_len = 0;
-
- char* id = NULL;
- size_t id_len = 0;
-
- int rc = 0;
-
- // verify that this is a scsi_device
- rc = vdev_sysfs_uevent_read_key( parent, "DEVTYPE", &devtype, &devtype_len );
- if( rc != 0 ) {
-
+static int
+handle_scsi (char const *parent, char **path, char **new_parent,
+ bool * supported_parent)
+{
+
+ char *devtype = NULL;
+ size_t devtype_len = 0;
+
+ char *id = NULL;
+ size_t id_len = 0;
+
+ int rc = 0;
+
+ // verify that this is a scsi_device
+ rc = vdev_sysfs_uevent_read_key (parent, "DEVTYPE", &devtype, &devtype_len);
+ if (rc != 0)
+ {
+
return rc;
- }
-
- if( devtype == NULL || strcmp( devtype, "scsi_device" ) != 0 ) {
-
+ }
+
+ if (devtype == NULL || strcmp (devtype, "scsi_device") != 0)
+ {
+
// not a scsi device
- *new_parent = strdup( parent );
- if( *new_parent == NULL ) {
-
- return -ENOMEM;
- }
-
+ *new_parent = strdup (parent);
+ if (*new_parent == NULL)
+ {
+
+ return -ENOMEM;
+ }
+
return 0;
- }
-
- // firewrire?
- rc = vdev_sysfs_read_attr( parent, "ieee1394_id", &id, &id_len );
- free( devtype );
-
- if( rc == 0 ) {
-
+ }
+ // firewrire?
+ rc = vdev_sysfs_read_attr (parent, "ieee1394_id", &id, &id_len);
+ free (devtype);
+
+ if (rc == 0)
+ {
+
// yup!
- rc = skip_subsystem( parent, "scsi", new_parent );
- if( rc != 0 ) {
-
- free( id );
- return rc;
- }
-
- path_prepend(path, "ieee1394-0x%s", id);
-
- free( id );
-
+ rc = skip_subsystem (parent, "scsi", new_parent);
+ if (rc != 0)
+ {
+
+ free (id);
+ return rc;
+ }
+
+ path_prepend (path, "ieee1394-0x%s", id);
+
+ free (id);
+
*supported_parent = true;
return 0;
- }
-
- free( id );
-
- if( strstr( parent, "/rport-" ) != NULL ) {
-
+ }
+
+ free (id);
+
+ if (strstr (parent, "/rport-") != NULL)
+ {
+
// fibrechannel
- rc = handle_scsi_fibre_channel( parent, path, new_parent );
- if( rc != 0 ) {
-
- return rc;
- }
-
+ rc = handle_scsi_fibre_channel (parent, path, new_parent);
+ if (rc != 0)
+ {
+
+ return rc;
+ }
+
*supported_parent = true;
return 0;
- }
-
- if( strstr( parent, "/end_device-" ) != NULL ) {
-
+ }
+
+ if (strstr (parent, "/end_device-") != NULL)
+ {
+
// SCSI SAS
- rc = handle_scsi_sas( parent, path, new_parent );
- if( rc != 0 ) {
-
- return rc;
- }
-
+ rc = handle_scsi_sas (parent, path, new_parent);
+ if (rc != 0)
+ {
+
+ return rc;
+ }
+
*supported_parent = true;
return 0;
- }
-
- if( strstr( parent, "/session" ) != NULL ) {
-
+ }
+
+ if (strstr (parent, "/session") != NULL)
+ {
+
// iSCSI
- rc = handle_scsi_iscsi( parent, path, new_parent );
- if( rc != 0 ) {
-
- return rc;
- }
-
+ rc = handle_scsi_iscsi (parent, path, new_parent);
+ if (rc != 0)
+ {
+
+ return rc;
+ }
+
*supported_parent = true;
return 0;
- }
-
- /*
+ }
+
+ /*
* We do not support the ATA transport class, it uses global counters
* to name the ata devices which numbers spread across multiple
* controllers.
@@ -1100,626 +1227,715 @@ static int handle_scsi( char const* parent, char **path, char** new_parent, bool
* Until all that is solved at the kernel level, there are no by-path/
* links for ATA devices.
*/
-
- if( strstr( parent, "/ata" ) != NULL ) {
-
+
+ if (strstr (parent, "/ata") != NULL)
+ {
+
// not supported
*new_parent = NULL;
-
+
return 0;
- }
-
- if( strstr( parent, "/vmbus_" ) != NULL ) {
-
- rc = handle_scsi_hyperv( parent, path, new_parent );
- if( rc != 0 ) {
-
- return rc;
- }
-
+ }
+
+ if (strstr (parent, "/vmbus_") != NULL)
+ {
+
+ rc = handle_scsi_hyperv (parent, path, new_parent);
+ if (rc != 0)
+ {
+
+ return rc;
+ }
+
return 0;
- }
-
- // default
- rc = handle_scsi_default( parent, path, new_parent );
-
- return rc;
+ }
+ // default
+ rc = handle_scsi_default (parent, path, new_parent);
+
+ return rc;
}
// add persistent path name information for a cciss device
// return 0 on success, update *path, and set *new_parent to the next parent device to explore
// return negative on failure
-static int handle_cciss( char const* parent, char **path, char** new_parent ) {
-
- unsigned int controller = 0, disk = 0;
-
- char* parent_sysname = NULL;
- size_t parent_sysname_len = 0;
-
- int rc = 0;
-
- rc = vdev_sysfs_get_sysname( parent, &parent_sysname, &parent_sysname_len );
- if( rc != 0 ) {
+static int
+handle_cciss (char const *parent, char **path, char **new_parent)
+{
+
+ unsigned int controller = 0, disk = 0;
+
+ char *parent_sysname = NULL;
+ size_t parent_sysname_len = 0;
+
+ int rc = 0;
+
+ rc = vdev_sysfs_get_sysname (parent, &parent_sysname, &parent_sysname_len);
+ if (rc != 0)
+ {
return rc;
- }
-
- rc = sscanf( parent_sysname, "c%ud%u%*s", &controller, &disk );
-
- free( parent_sysname );
-
- if( rc != 2 ) {
-
+ }
+
+ rc = sscanf (parent_sysname, "c%ud%u%*s", &controller, &disk);
+
+ free (parent_sysname);
+
+ if (rc != 2)
+ {
+
return -ENOENT;
- }
-
- path_prepend(path, "cciss-disk%u", disk);
-
- rc = skip_subsystem( parent, "cciss", new_parent );
-
- return rc;
-}
+ }
+
+ path_prepend (path, "cciss-disk%u", disk);
+
+ rc = skip_subsystem (parent, "cciss", new_parent);
+ return rc;
+}
// add persistent path name information for a scsi tape device
// always succeeds
-static void handle_scsi_tape( char const* dev, char **path ) {
-
- // must be the last device in the syspath
- if( *path != NULL ) {
+static void
+handle_scsi_tape (char const *dev, char **path)
+{
+
+ // must be the last device in the syspath
+ if (*path != NULL)
+ {
return;
- }
-
- char* sysname = NULL;
- size_t sysname_len = 0;
-
- int rc = 0;
-
- rc = vdev_sysfs_get_sysname( dev, &sysname, &sysname_len );
- if( rc != 0 ) {
-
+ }
+
+ char *sysname = NULL;
+ size_t sysname_len = 0;
+
+ int rc = 0;
+
+ rc = vdev_sysfs_get_sysname (dev, &sysname, &sysname_len);
+ if (rc != 0)
+ {
+
return;
- }
-
- if( strncmp( sysname, "nst", 3 ) == 0 && strchr( "lma", sysname[3] ) != NULL ) {
-
- path_prepend( path, "nst%c", sysname[3] );
- }
- else if( strncmp( sysname, "st", 2 ) == 0 && strchr( "lma", sysname[2] ) != NULL ) {
-
- path_prepend( path, "st%c", sysname[2] );
- }
-
- free( sysname );
- return;
-}
+ }
+
+ if (strncmp (sysname, "nst", 3) == 0 && strchr ("lma", sysname[3]) != NULL)
+ {
+ path_prepend (path, "nst%c", sysname[3]);
+ }
+ else if (strncmp (sysname, "st", 2) == 0
+ && strchr ("lma", sysname[2]) != NULL)
+ {
+
+ path_prepend (path, "st%c", sysname[2]);
+ }
+
+ free (sysname);
+ return;
+}
// add persistent path name information for a usb device
// return 0 on success, update *path with the information, and set *new_parent to the next device to explore
// return negative on failure
-static int handle_usb( char const *parent, char **path, char** new_parent ) {
-
- int rc = 0;
-
- char* devtype = NULL;
- size_t devtype_len = 0;
-
- char* sysname = NULL;
- size_t sysname_len = 0;
-
- char* port = NULL;
-
- rc = vdev_sysfs_uevent_read_key( parent, "DEVTYPE", &devtype, &devtype_len );
- if( rc != 0 ) {
-
- *new_parent = strdup( parent );
- if( *new_parent == NULL ) {
-
- return -ENOMEM;
- }
-
+static int
+handle_usb (char const *parent, char **path, char **new_parent)
+{
+
+ int rc = 0;
+
+ char *devtype = NULL;
+ size_t devtype_len = 0;
+
+ char *sysname = NULL;
+ size_t sysname_len = 0;
+
+ char *port = NULL;
+
+ rc = vdev_sysfs_uevent_read_key (parent, "DEVTYPE", &devtype, &devtype_len);
+ if (rc != 0)
+ {
+
+ *new_parent = strdup (parent);
+ if (*new_parent == NULL)
+ {
+
+ return -ENOMEM;
+ }
+
return 0;
- }
-
- if( strcmp( devtype, "usb_interface" ) != 0 && strcmp( devtype, "usb_device" ) != 0 ) {
-
- free( devtype );
-
- *new_parent = strdup( parent );
- if( *new_parent == NULL ) {
-
- return -ENOMEM;
- }
-
+ }
+
+ if (strcmp (devtype, "usb_interface") != 0
+ && strcmp (devtype, "usb_device") != 0)
+ {
+
+ free (devtype);
+
+ *new_parent = strdup (parent);
+ if (*new_parent == NULL)
+ {
+
+ return -ENOMEM;
+ }
+
return 0;
- }
-
- free( devtype );
-
- rc = vdev_sysfs_get_sysname( parent, &sysname, &sysname_len );
- if( rc != 0 ) {
-
+ }
+
+ free (devtype);
+
+ rc = vdev_sysfs_get_sysname (parent, &sysname, &sysname_len);
+ if (rc != 0)
+ {
+
return rc;
- }
-
- port = strchr( sysname, '-' );
-
- if( port == NULL ) {
-
- *new_parent = strdup( parent );
- if( *new_parent == NULL ) {
-
- return -ENOMEM;
- }
-
- free( sysname );
-
+ }
+
+ port = strchr (sysname, '-');
+
+ if (port == NULL)
+ {
+
+ *new_parent = strdup (parent);
+ if (*new_parent == NULL)
+ {
+
+ return -ENOMEM;
+ }
+
+ free (sysname);
+
return 0;
- }
-
- port++;
-
- rc = skip_subsystem( parent, "usb", new_parent );
- if( rc != 0 ) {
-
- free( sysname );
+ }
+
+ port++;
+
+ rc = skip_subsystem (parent, "usb", new_parent);
+ if (rc != 0)
+ {
+
+ free (sysname);
return rc;
- }
-
- path_prepend( path, "usb-0:%s", port );
-
- free( sysname );
-
- return 0;
+ }
+
+ path_prepend (path, "usb-0:%s", port);
+
+ free (sysname);
+
+ return 0;
}
-static int handle_bcma( char const* parent, char **path, char** new_parent ) {
-
- unsigned int core = 0;
- int rc = 0;
-
- char* sysname = NULL;
- size_t sysname_len = 0;
-
- rc = vdev_sysfs_get_sysname( parent, &sysname, &sysname_len );
- if( rc != 0 ) {
-
+static int
+handle_bcma (char const *parent, char **path, char **new_parent)
+{
+
+ unsigned int core = 0;
+ int rc = 0;
+
+ char *sysname = NULL;
+ size_t sysname_len = 0;
+
+ rc = vdev_sysfs_get_sysname (parent, &sysname, &sysname_len);
+ if (rc != 0)
+ {
+
return rc;
- }
-
- rc = sscanf( sysname, "bcma%*u:%u", &core );
-
- free( sysname );
-
- if( rc != 1 ) {
-
+ }
+
+ rc = sscanf (sysname, "bcma%*u:%u", &core);
+
+ free (sysname);
+
+ if (rc != 1)
+ {
+
return -ENOENT;
- }
-
- path_prepend( path, "bcma-%u", core );
-
- *new_parent = strdup( parent );
- if( *new_parent == NULL ) {
+ }
+
+ path_prepend (path, "bcma-%u", core);
+
+ *new_parent = strdup (parent);
+ if (*new_parent == NULL)
+ {
return -ENOMEM;
- }
-
- return 0;
+ }
+
+ return 0;
}
+static int
+handle_ccw (char const *parent, char const *dev, char **path,
+ char **new_parent)
+{
+
+ char *scsi_dev = NULL;
+ size_t scsi_dev_len = 0;
+
+ bool handled = false;
+
+ int rc = 0;
-static int handle_ccw( char const* parent, char const* dev, char **path, char** new_parent ) {
-
- char* scsi_dev = NULL;
- size_t scsi_dev_len = 0;
-
- bool handled = false;
-
- int rc = 0;
-
- rc = vdev_sysfs_get_parent_with_subsystem_devtype( dev, "scsi", "scsi_device", &scsi_dev, &scsi_dev_len );
- if( rc == 0 ) {
-
- char* wwpn = NULL;
+ rc = vdev_sysfs_get_parent_with_subsystem_devtype (dev, "scsi",
+ "scsi_device",
+ &scsi_dev,
+ &scsi_dev_len);
+ if (rc == 0)
+ {
+
+ char *wwpn = NULL;
size_t wwpn_len = 0;
-
- char* lun = NULL;
+
+ char *lun = NULL;
size_t lun_len = 0;
-
- char* hba_id = NULL;
+
+ char *hba_id = NULL;
size_t hba_id_len = 0;
-
- vdev_sysfs_read_attr( scsi_dev, "hba_id", &hba_id, &hba_id_len );
- vdev_sysfs_read_attr( scsi_dev, "wwpn", &wwpn, &wwpn_len );
- vdev_sysfs_read_attr( scsi_dev, "fcp_lun", &lun, &lun_len );
-
- if( hba_id != NULL && lun != NULL && wwpn != NULL ) {
-
- path_prepend(path, "ccw-%s-zfcp-%s:%s", hba_id, wwpn, lun);
- handled = true;
- }
-
- if( hba_id != NULL ) {
- free( hba_id );
- }
- if( lun != NULL ) {
- free( lun );
- }
- if( wwpn != NULL ) {
- free( wwpn );
- }
- }
-
- if( !handled ) {
-
- char* sysname = NULL;
+
+ vdev_sysfs_read_attr (scsi_dev, "hba_id", &hba_id, &hba_id_len);
+ vdev_sysfs_read_attr (scsi_dev, "wwpn", &wwpn, &wwpn_len);
+ vdev_sysfs_read_attr (scsi_dev, "fcp_lun", &lun, &lun_len);
+
+ if (hba_id != NULL && lun != NULL && wwpn != NULL)
+ {
+
+ path_prepend (path, "ccw-%s-zfcp-%s:%s", hba_id, wwpn, lun);
+ handled = true;
+ }
+
+ if (hba_id != NULL)
+ {
+ free (hba_id);
+ }
+ if (lun != NULL)
+ {
+ free (lun);
+ }
+ if (wwpn != NULL)
+ {
+ free (wwpn);
+ }
+ }
+
+ if (!handled)
+ {
+
+ char *sysname = NULL;
size_t sysname_len = 0;
-
- rc = vdev_sysfs_get_sysname( parent, &sysname, &sysname_len );
-
- if( rc != 0 ) {
-
- free( scsi_dev );
- return rc;
- }
-
- path_prepend( path, "ccw-%s", sysname );
-
- free( sysname );
- }
-
- free( scsi_dev );
-
- rc = skip_subsystem( parent, "ccw", new_parent );
- if( rc != 0 ) {
+
+ rc = vdev_sysfs_get_sysname (parent, &sysname, &sysname_len);
+
+ if (rc != 0)
+ {
+
+ free (scsi_dev);
+ return rc;
+ }
+
+ path_prepend (path, "ccw-%s", sysname);
+
+ free (sysname);
+ }
+
+ free (scsi_dev);
+
+ rc = skip_subsystem (parent, "ccw", new_parent);
+ if (rc != 0)
+ {
return rc;
- }
-
- return 0;
+ }
+
+ return 0;
}
+void
+usage (char const *progname)
+{
-void usage( char const* progname ) {
-
- fprintf(stderr, "[ERROR] %s: Usage: %s /sysfs/path/to/device | /path/to/device/node\n", progname, progname );
+ fprintf (stderr,
+ "[ERROR] %s: Usage: %s /sysfs/path/to/device | /path/to/device/node\n",
+ progname, progname);
}
-
// entry point
-int main( int argc, char** argv ) {
-
- char* parent = NULL;
- size_t parent_len = 0;
-
- char* new_parent = NULL;
-
- char* sysname = NULL;
- size_t sysname_len = 0;
-
- char* path = NULL;
-
- char* subsys = NULL;
- size_t subsys_len = 0;
-
- bool supported_transport = false;
- bool supported_parent = false;
-
- struct stat sb;
-
- int rc = 0;
-
- if( argc != 2 ) {
- usage( argv[0] );
- exit(1);
- }
-
- char* dev = NULL;
-
- // if this is a character device, then look up the device path
- rc = stat( argv[1], &sb );
- if( rc != 0 ) {
-
- usage( argv[0] );
- exit(1);
- }
-
- if( S_ISCHR( sb.st_mode ) ) {
-
+int
+main (int argc, char **argv)
+{
+
+ char *parent = NULL;
+ size_t parent_len = 0;
+
+ char *new_parent = NULL;
+
+ char *sysname = NULL;
+ size_t sysname_len = 0;
+
+ char *path = NULL;
+
+ char *subsys = NULL;
+ size_t subsys_len = 0;
+
+ bool supported_transport = false;
+ bool supported_parent = false;
+
+ struct stat sb;
+
+ int rc = 0;
+
+ if (argc != 2)
+ {
+ usage (argv[0]);
+ exit (1);
+ }
+
+ char *dev = NULL;
+
+ // if this is a character device, then look up the device path
+ rc = stat (argv[1], &sb);
+ if (rc != 0)
+ {
+
+ usage (argv[0]);
+ exit (1);
+ }
+
+ if (S_ISCHR (sb.st_mode))
+ {
+
size_t dev_len = 0;
- rc = vdev_sysfs_get_syspath_from_device( "/sys", sb.st_mode, major( sb.st_rdev ), minor( sb.st_rdev ), &dev, &dev_len );
- if( rc != 0 ) {
-
- fprintf(stderr, "[ERROR] %s: vdev_sysfs_get_syspath_from_device rc = %d\n", argv[0], rc );
- usage(argv[0]);
- exit(1);
- }
- }
- else {
-
- dev = strdup( argv[1] );
- }
-
- // s390 ccw bus?
- rc = vdev_sysfs_get_parent_with_subsystem_devtype( dev, "ccw", NULL, &parent, &parent_len );
- if( rc == 0 ) {
-
- rc = handle_ccw( parent, dev, &path, &new_parent );
- if( rc != 0 ) {
- exit(2);
- }
-
+ rc = vdev_sysfs_get_syspath_from_device ("/sys", sb.st_mode,
+ major (sb.st_rdev),
+ minor (sb.st_rdev), &dev,
+ &dev_len);
+ if (rc != 0)
+ {
+
+ fprintf (stderr,
+ "[ERROR] %s: vdev_sysfs_get_syspath_from_device rc = %d\n",
+ argv[0], rc);
+ usage (argv[0]);
+ exit (1);
+ }
+ }
+ else
+ {
+
+ dev = strdup (argv[1]);
+ }
+
+ // s390 ccw bus?
+ rc = vdev_sysfs_get_parent_with_subsystem_devtype (dev, "ccw", NULL,
+ &parent, &parent_len);
+ if (rc == 0)
+ {
+
+ rc = handle_ccw (parent, dev, &path, &new_parent);
+ if (rc != 0)
+ {
+ exit (2);
+ }
+
goto main_finish;
- }
-
- // walk up the device sysfs path and make the persistent path
- parent = strdup( dev );
- if( parent == NULL ) {
-
- exit(3);
- }
-
- rc = 0;
-
- while( parent != NULL ) {
-
- vdev_sysfs_read_subsystem( parent, &subsys, &subsys_len );
-
- log_debug("'%s': subsystem '%s'", parent, subsys );
-
- if( subsys != NULL ) {
-
- if( strcmp( subsys, "scsi_tape" ) == 0 ) {
-
- handle_scsi_tape( parent, &path );
- }
- else if( strcmp( subsys, "scsi" ) == 0 ) {
-
- rc = handle_scsi( parent, &path, &new_parent, &supported_parent );
- supported_transport = true;
- }
- else if( strcmp( subsys, "cciss" ) == 0 ) {
-
- rc = handle_cciss( parent, &path, &new_parent );
- supported_transport = true;
- }
- else if( strcmp( subsys, "usb" ) == 0 ) {
-
- rc = handle_usb( parent, &path, &new_parent );
- supported_transport = true;
- }
- else if( strcmp( subsys, "bcma" ) == 0 ) {
-
- rc = handle_bcma( parent, &path, &new_parent );
- supported_transport = true;
- }
- else if( strcmp( subsys, "serio" ) == 0 ) {
-
- int sysnum = 0;
- rc = vdev_sysfs_get_sysnum( parent, &sysnum );
- if( rc == 0 ) {
-
- path_prepend( &path, "serio-%d", sysnum );
-
- rc = skip_subsystem( parent, "serio", &new_parent );
- }
- }
- else if( strcmp( subsys, "pci" ) == 0 ) {
-
- rc = vdev_sysfs_get_sysname( parent, &sysname, &sysname_len );
- if( rc == 0 ) {
-
- path_prepend( &path, "pci-%s", sysname );
- free( sysname );
-
- rc = skip_subsystem( parent, "pci", &new_parent );
- }
-
- supported_parent = true;
- }
- else if( strcmp( subsys, "platform" ) == 0 ) {
-
- rc = vdev_sysfs_get_sysname( parent, &sysname, &sysname_len );
- if( rc == 0 ) {
-
- path_prepend( &path, "platform-%s", sysname );
- free( sysname );
-
- rc = skip_subsystem( parent, "platform", &new_parent );
- }
-
- supported_parent = true;
- supported_transport = true;
- }
- else if( strcmp( subsys, "acpi" ) == 0 ) {
-
- rc = vdev_sysfs_get_sysname( parent, &sysname, &sysname_len );
- if( rc == 0 ) {
-
- path_prepend( &path, "acpi-%s", sysname );
- free( sysname );
-
- rc = skip_subsystem( parent, "acpi", &new_parent );
- }
-
- supported_parent = true;
- }
- else if( strcmp( subsys, "xen" ) == 0 ) {
-
- rc = vdev_sysfs_get_sysname( parent, &sysname, &sysname_len );
- if( rc == 0 ) {
-
- path_prepend( &path, "xen-%s", sysname );
- free( sysname );
-
- rc = skip_subsystem( parent, "xen", &new_parent );
- }
-
- supported_parent = true;
- }
- else if( strcmp( subsys, "scm" ) == 0 ) {
-
- rc = vdev_sysfs_get_sysname( parent, &sysname, &sysname_len );
- if( rc == 0 ) {
-
- path_prepend( &path, "scm-%s", sysname );
- free( sysname );
-
- rc = skip_subsystem( parent, "scm", &new_parent );
- }
-
- supported_transport = true;
- supported_parent = true;
- }
- }
-
- if( rc != 0 ) {
-
- exit(4);
- }
-
- if( new_parent != NULL ) {
-
- log_debug("new parent is '%s' (original = '%s')", new_parent, parent );
-
- free( parent );
- parent = new_parent;
-
- new_parent = NULL;
- }
-
- char* next = NULL;
+ }
+ // walk up the device sysfs path and make the persistent path
+ parent = strdup (dev);
+ if (parent == NULL)
+ {
+
+ exit (3);
+ }
+
+ rc = 0;
+
+ while (parent != NULL)
+ {
+
+ vdev_sysfs_read_subsystem (parent, &subsys, &subsys_len);
+
+ log_debug ("'%s': subsystem '%s'", parent, subsys);
+
+ if (subsys != NULL)
+ {
+
+ if (strcmp (subsys, "scsi_tape") == 0)
+ {
+
+ handle_scsi_tape (parent, &path);
+ }
+ else if (strcmp (subsys, "scsi") == 0)
+ {
+
+ rc = handle_scsi (parent, &path, &new_parent,
+ &supported_parent);
+ supported_transport = true;
+ }
+ else if (strcmp (subsys, "cciss") == 0)
+ {
+
+ rc = handle_cciss (parent, &path, &new_parent);
+ supported_transport = true;
+ }
+ else if (strcmp (subsys, "usb") == 0)
+ {
+
+ rc = handle_usb (parent, &path, &new_parent);
+ supported_transport = true;
+ }
+ else if (strcmp (subsys, "bcma") == 0)
+ {
+
+ rc = handle_bcma (parent, &path, &new_parent);
+ supported_transport = true;
+ }
+ else if (strcmp (subsys, "serio") == 0)
+ {
+
+ int sysnum = 0;
+ rc = vdev_sysfs_get_sysnum (parent, &sysnum);
+ if (rc == 0)
+ {
+
+ path_prepend (&path, "serio-%d", sysnum);
+
+ rc = skip_subsystem (parent, "serio", &new_parent);
+ }
+ }
+ else if (strcmp (subsys, "pci") == 0)
+ {
+
+ rc = vdev_sysfs_get_sysname (parent, &sysname, &sysname_len);
+ if (rc == 0)
+ {
+
+ path_prepend (&path, "pci-%s", sysname);
+ free (sysname);
+
+ rc = skip_subsystem (parent, "pci", &new_parent);
+ }
+
+ supported_parent = true;
+ }
+ else if (strcmp (subsys, "platform") == 0)
+ {
+
+ rc = vdev_sysfs_get_sysname (parent, &sysname, &sysname_len);
+ if (rc == 0)
+ {
+
+ path_prepend (&path, "platform-%s", sysname);
+ free (sysname);
+
+ rc = skip_subsystem (parent, "platform", &new_parent);
+ }
+
+ supported_parent = true;
+ supported_transport = true;
+ }
+ else if (strcmp (subsys, "acpi") == 0)
+ {
+
+ rc = vdev_sysfs_get_sysname (parent, &sysname, &sysname_len);
+ if (rc == 0)
+ {
+
+ path_prepend (&path, "acpi-%s", sysname);
+ free (sysname);
+
+ rc = skip_subsystem (parent, "acpi", &new_parent);
+ }
+
+ supported_parent = true;
+ }
+ else if (strcmp (subsys, "xen") == 0)
+ {
+
+ rc = vdev_sysfs_get_sysname (parent, &sysname, &sysname_len);
+ if (rc == 0)
+ {
+
+ path_prepend (&path, "xen-%s", sysname);
+ free (sysname);
+
+ rc = skip_subsystem (parent, "xen", &new_parent);
+ }
+
+ supported_parent = true;
+ }
+ else if (strcmp (subsys, "scm") == 0)
+ {
+
+ rc = vdev_sysfs_get_sysname (parent, &sysname, &sysname_len);
+ if (rc == 0)
+ {
+
+ path_prepend (&path, "scm-%s", sysname);
+ free (sysname);
+
+ rc = skip_subsystem (parent, "scm", &new_parent);
+ }
+
+ supported_transport = true;
+ supported_parent = true;
+ }
+ }
+
+ if (rc != 0)
+ {
+
+ exit (4);
+ }
+
+ if (new_parent != NULL)
+ {
+
+ log_debug ("new parent is '%s' (original = '%s')",
+ new_parent, parent);
+
+ free (parent);
+ parent = new_parent;
+
+ new_parent = NULL;
+ }
+
+ char *next = NULL;
size_t next_len = 0;
-
+
// next device
- rc = vdev_sysfs_get_parent_device( parent, &next, &next_len );
- if( rc != 0 ) {
-
- if( rc == -ENOENT ) {
-
- break;
- }
-
- // terminal error
- exit(15);
- }
-
-
- log_debug("Parent of '%s' is '%s'\n", parent, next );
-
- free( parent );
+ rc = vdev_sysfs_get_parent_device (parent, &next, &next_len);
+ if (rc != 0)
+ {
+
+ if (rc == -ENOENT)
+ {
+
+ break;
+ }
+ // terminal error
+ exit (15);
+ }
+
+ log_debug ("Parent of '%s' is '%s'\n", parent, next);
+
+ free (parent);
parent = next;
-
- free( subsys );
+
+ free (subsys);
subsys = NULL;
- }
-
- /*
- * Do not return devices with an unknown parent device type. They
- * might produce conflicting IDs if the parent does not provide a
- * unique and predictable name.
- */
- if( !supported_parent ) {
-
- log_debug("%s", "Unsupported parent");
-
- if( path != NULL ) {
- free( path );
- }
+ }
+
+ /*
+ * Do not return devices with an unknown parent device type. They
+ * might produce conflicting IDs if the parent does not provide a
+ * unique and predictable name.
+ */
+ if (!supported_parent)
+ {
+
+ log_debug ("%s", "Unsupported parent");
+
+ if (path != NULL)
+ {
+ free (path);
+ }
path = NULL;
- }
-
- /*
- * Do not return block devices without a well-known transport. Some
- * devices do not expose their buses and do not provide a unique
- * and predictable name that way.
- */
- rc = vdev_sysfs_read_subsystem( dev, &subsys, &subsys_len );
- if( rc != 0 ) {
-
- if( path != NULL ) {
- free( path );
- }
-
- exit(16);
- }
-
- if( strcmp( subsys, "block" ) == 0 && !supported_transport ) {
-
- log_debug("'%s': Unsupported transport", dev);
-
- if( path != NULL ) {
- free( path );
- }
- exit(17);
- }
-
+ }
+
+ /*
+ * Do not return block devices without a well-known transport. Some
+ * devices do not expose their buses and do not provide a unique
+ * and predictable name that way.
+ */
+ rc = vdev_sysfs_read_subsystem (dev, &subsys, &subsys_len);
+ if (rc != 0)
+ {
+
+ if (path != NULL)
+ {
+ free (path);
+ }
+
+ exit (16);
+ }
+
+ if (strcmp (subsys, "block") == 0 && !supported_transport)
+ {
+
+ log_debug ("'%s': Unsupported transport", dev);
+
+ if (path != NULL)
+ {
+ free (path);
+ }
+ exit (17);
+ }
+
main_finish:
-
- free( dev );
- free( subsys );
-
- if( path != NULL ) {
-
+
+ free (dev);
+ free (subsys);
+
+ if (path != NULL)
+ {
+
char tag[4097];
- memset( tag, 0, 4097 );
-
+ memset (tag, 0, 4097);
+
size_t i = 0;
- char const* p = NULL;
-
-
+ char const *p = NULL;
+
/* compose valid udev tag name */
- for (p = path, i = 0; *p != '\0'; p++ ) {
-
- // alphanumeric?
- if ((*p >= '0' && *p <= '9') ||
- (*p >= 'A' && *p <= 'Z') ||
- (*p >= 'a' && *p <= 'z') ||
- *p == '-') {
-
- tag[i++] = *p;
- continue;
- }
-
- // skip leading '_'
- if( i == 0 ) {
- continue;
- }
-
- // avoid second '_'
- if( tag[i-1] == '_' ) {
- continue;
- }
-
- tag[i++] = '_';
- }
-
+ for (p = path, i = 0; *p != '\0'; p++)
+ {
+
+ // alphanumeric?
+ if ((*p >= '0' && *p <= '9') ||
+ (*p >= 'A' && *p <= 'Z') ||
+ (*p >= 'a' && *p <= 'z') || *p == '-')
+ {
+
+ tag[i++] = *p;
+ continue;
+ }
+ // skip leading '_'
+ if (i == 0)
+ {
+ continue;
+ }
+ // avoid second '_'
+ if (tag[i - 1] == '_')
+ {
+ continue;
+ }
+
+ tag[i++] = '_';
+ }
+
/* strip trailing '_' */
- while( i > 0 && tag[i-1] == '_' ) {
- i--;
- }
-
+ while (i > 0 && tag[i - 1] == '_')
+ {
+ i--;
+ }
+
tag[i] = '\0';
// replaces ID_PATH and ID_PATH_TAG
- vdev_property_add( "VDEV_PERSISTENT_PATH", path );
- vdev_property_add( "VDEV_PERSISTENT_PATH_TAG", tag );
-
- free( path );
-
- vdev_property_print();
- vdev_property_free_all();
-
- exit(0);
- }
- else {
-
+ vdev_property_add ("VDEV_PERSISTENT_PATH", path);
+ vdev_property_add ("VDEV_PERSISTENT_PATH_TAG", tag);
+
+ free (path);
+
+ vdev_property_print ();
+ vdev_property_free_all ();
+
+ exit (0);
+ }
+ else
+ {
+
// no path
- vdev_property_add( "VDEV_PERSISTENT_PATH", "" );
- vdev_property_add( "VDEV_PERSISTENT_PATH_TAG", "" );
-
- vdev_property_print();
- vdev_property_free_all();
-
- exit(0);
- }
+ vdev_property_add ("VDEV_PERSISTENT_PATH", "");
+ vdev_property_add ("VDEV_PERSISTENT_PATH_TAG", "");
+
+ vdev_property_print ();
+ vdev_property_free_all ();
+
+ exit (0);
+ }
}
diff --git a/vdevd/helpers/LINUX/stat_scsi.c b/vdevd/helpers/LINUX/stat_scsi.c
index 74796dd..086a643 100644
--- a/vdevd/helpers/LINUX/stat_scsi.c
+++ b/vdevd/helpers/LINUX/stat_scsi.c
@@ -40,11 +40,12 @@
#include
-struct scsi_ioctl_command {
- unsigned int inlen; /* excluding scsi command length */
- unsigned int outlen;
- unsigned char data[1];
- /* on input, scsi command starts here then opt. data */
+struct scsi_ioctl_command
+{
+ unsigned int inlen; /* excluding scsi command length */
+ unsigned int outlen;
+ unsigned char data[1];
+ /* on input, scsi command starts here then opt. data */
};
/*
@@ -102,10 +103,11 @@ struct scsi_ioctl_command {
#define SCSI_ID_BINARY 1
#define SCSI_ID_ASCII 2
-struct scsi_id_search_values {
- u_char id_type;
- u_char naa_type;
- u_char code_set;
+struct scsi_id_search_values
+{
+ u_char id_type;
+ u_char naa_type;
+ u_char code_set;
};
/*
@@ -144,40 +146,43 @@ struct scsi_id_search_values {
*/
#define MAX_BUFFER_LEN 256
-struct scsi_id_device {
- char vendor[9];
- char model[17];
- char revision[5];
- char type[33];
- char kernel[64];
- char serial[MAX_SERIAL_LEN];
- char serial_short[MAX_SERIAL_LEN];
- int use_sg;
-
- /* Always from page 0x80 e.g. 'B3G1P8500RWT' - may not be unique */
- char unit_serial_number[MAX_SERIAL_LEN];
-
- /* NULs if not set - otherwise hex encoding using lower-case e.g. '50014ee0016eb572' */
- char wwn[17];
-
- /* NULs if not set - otherwise hex encoding using lower-case e.g. '0xe00000d80000' */
- char wwn_vendor_extension[17];
-
- /* NULs if not set - otherwise decimal number */
- char tgpt_group[8];
+struct scsi_id_device
+{
+ char vendor[9];
+ char model[17];
+ char revision[5];
+ char type[33];
+ char kernel[64];
+ char serial[MAX_SERIAL_LEN];
+ char serial_short[MAX_SERIAL_LEN];
+ int use_sg;
+
+ /* Always from page 0x80 e.g. 'B3G1P8500RWT' - may not be unique */
+ char unit_serial_number[MAX_SERIAL_LEN];
+
+ /* NULs if not set - otherwise hex encoding using lower-case e.g. '50014ee0016eb572' */
+ char wwn[17];
+
+ /* NULs if not set - otherwise hex encoding using lower-case e.g. '0xe00000d80000' */
+ char wwn_vendor_extension[17];
+
+ /* NULs if not set - otherwise decimal number */
+ char tgpt_group[8];
};
-int scsi_std_inquiry( struct scsi_id_device *dev_scsi, const char *devname);
-int scsi_get_serial( struct scsi_id_device *dev_scsi, const char *devname, int page_code, int len);
+int scsi_std_inquiry (struct scsi_id_device *dev_scsi, const char *devname);
+int scsi_get_serial (struct scsi_id_device *dev_scsi, const char *devname,
+ int page_code, int len);
/*
* Page code values.
*/
-enum page_code {
- PAGE_83_PRE_SPC3 = -0x83,
- PAGE_UNSPECIFIED = 0x00,
- PAGE_80 = 0x80,
- PAGE_83 = 0x83,
+enum page_code
+{
+ PAGE_83_PRE_SPC3 = -0x83,
+ PAGE_UNSPECIFIED = 0x00,
+ PAGE_80 = 0x80,
+ PAGE_83 = 0x83,
};
/*
@@ -189,12 +194,12 @@ enum page_code {
* is normally one or some small number of descriptors.
*/
static const struct scsi_id_search_values id_search_list[] = {
- { SCSI_ID_TGTGROUP, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY },
- { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG_EXTENDED, SCSI_ID_BINARY },
- { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG_EXTENDED, SCSI_ID_ASCII },
- { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG, SCSI_ID_BINARY },
- { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG, SCSI_ID_ASCII },
- /*
+ {SCSI_ID_TGTGROUP, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY},
+ {SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG_EXTENDED, SCSI_ID_BINARY},
+ {SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG_EXTENDED, SCSI_ID_ASCII},
+ {SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG, SCSI_ID_BINARY},
+ {SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG, SCSI_ID_ASCII},
+ /*
* Devices already exist using NAA values that are now marked
* reserved. These should not conflict with other values, or it is
* a bug in the device. As long as we find the IEEE extended one
@@ -203,50 +208,49 @@ static const struct scsi_id_search_values id_search_list[] = {
* non-IEEE descriptors in a random order will get different
* names.
*/
- { SCSI_ID_NAA, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY },
- { SCSI_ID_NAA, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII },
- { SCSI_ID_EUI_64, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY },
- { SCSI_ID_EUI_64, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII },
- { SCSI_ID_T10_VENDOR, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY },
- { SCSI_ID_T10_VENDOR, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII },
- { SCSI_ID_VENDOR_SPECIFIC, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY },
- { SCSI_ID_VENDOR_SPECIFIC, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII },
+ {SCSI_ID_NAA, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY},
+ {SCSI_ID_NAA, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII},
+ {SCSI_ID_EUI_64, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY},
+ {SCSI_ID_EUI_64, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII},
+ {SCSI_ID_T10_VENDOR, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY},
+ {SCSI_ID_T10_VENDOR, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII},
+ {SCSI_ID_VENDOR_SPECIFIC, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY},
+ {SCSI_ID_VENDOR_SPECIFIC, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII},
};
-static const char hex_str[]="0123456789abcdef";
+static const char hex_str[] = "0123456789abcdef";
/*
* Values returned in the result/status, only the ones used by the code
* are used here.
*/
-#define DID_NO_CONNECT 0x01 /* Unable to connect before timeout */
-#define DID_BUS_BUSY 0x02 /* Bus remain busy until timeout */
-#define DID_TIME_OUT 0x03 /* Timed out for some other reason */
+#define DID_NO_CONNECT 0x01 /* Unable to connect before timeout */
+#define DID_BUS_BUSY 0x02 /* Bus remain busy until timeout */
+#define DID_TIME_OUT 0x03 /* Timed out for some other reason */
#define DRIVER_TIMEOUT 0x06
-#define DRIVER_SENSE 0x08 /* Sense_buffer has been set */
+#define DRIVER_SENSE 0x08 /* Sense_buffer has been set */
/* The following "category" function returns one of the following */
-#define SG_ERR_CAT_CLEAN 0 /* No errors or other information */
-#define SG_ERR_CAT_MEDIA_CHANGED 1 /* interpreted from sense buffer */
-#define SG_ERR_CAT_RESET 2 /* interpreted from sense buffer */
+#define SG_ERR_CAT_CLEAN 0 /* No errors or other information */
+#define SG_ERR_CAT_MEDIA_CHANGED 1 /* interpreted from sense buffer */
+#define SG_ERR_CAT_RESET 2 /* interpreted from sense buffer */
#define SG_ERR_CAT_TIMEOUT 3
-#define SG_ERR_CAT_RECOVERED 4 /* Successful command after recovered err */
-#define SG_ERR_CAT_NOTSUPPORTED 5 /* Illegal / unsupported command */
-#define SG_ERR_CAT_SENSE 98 /* Something else in the sense buffer */
-#define SG_ERR_CAT_OTHER 99 /* Some other error/warning */
-
+#define SG_ERR_CAT_RECOVERED 4 /* Successful command after recovered err */
+#define SG_ERR_CAT_NOTSUPPORTED 5 /* Illegal / unsupported command */
+#define SG_ERR_CAT_SENSE 98 /* Something else in the sense buffer */
+#define SG_ERR_CAT_OTHER 99 /* Some other error/warning */
static const struct option options[] = {
- { "device", required_argument, NULL, 'd' },
- { "config", required_argument, NULL, 'f' },
- { "page", required_argument, NULL, 'p' },
- { "replace-whitespace", no_argument, NULL, 'u' },
- { "sg-version", required_argument, NULL, 's' },
- { "verbose", no_argument, NULL, 'v' },
- { "version", no_argument, NULL, 'V' }, /* don't advertise -V */
- { "help", no_argument, NULL, 'h' },
- {}
+ {"device", required_argument, NULL, 'd'},
+ {"config", required_argument, NULL, 'f'},
+ {"page", required_argument, NULL, 'p'},
+ {"replace-whitespace", no_argument, NULL, 'u'},
+ {"sg-version", required_argument, NULL, 's'},
+ {"verbose", no_argument, NULL, 'v'},
+ {"version", no_argument, NULL, 'V'}, /* don't advertise -V */
+ {"help", no_argument, NULL, 'h'},
+ {}
};
static bool all_good = true;
@@ -262,88 +266,120 @@ static char model_enc_str[256];
static char revision_str[16];
static char type_str[16];
-static int do_scsi_page80_inquiry(struct scsi_id_device *dev_scsi, int fd, char *serial, char *serial_short, int max_len);
+static int do_scsi_page80_inquiry (struct scsi_id_device *dev_scsi, int fd,
+ char *serial, char *serial_short,
+ int max_len);
-static int sg_err_category_new(int scsi_status, int msg_status, int host_status, int driver_status, const unsigned char *sense_buffer, int sb_len) {
+static int
+sg_err_category_new (int scsi_status, int msg_status, int host_status,
+ int driver_status,
+ const unsigned char *sense_buffer, int sb_len)
+{
- scsi_status &= 0x7e;
+ scsi_status &= 0x7e;
- /*
+ /*
* XXX change to return only two values - failed or OK.
*/
- if (!scsi_status && !host_status && !driver_status) {
+ if (!scsi_status && !host_status && !driver_status)
+ {
return SG_ERR_CAT_CLEAN;
- }
+ }
- if ((scsi_status == SCSI_CHECK_CONDITION) ||
+ if ((scsi_status == SCSI_CHECK_CONDITION) ||
(scsi_status == SCSI_COMMAND_TERMINATED) ||
- ((driver_status & 0xf) == DRIVER_SENSE)) {
-
- if (sense_buffer && (sb_len > 2)) {
- int sense_key;
- unsigned char asc;
-
- if (sense_buffer[0] & 0x2) {
- sense_key = sense_buffer[1] & 0xf;
- asc = sense_buffer[2];
- } else {
- sense_key = sense_buffer[2] & 0xf;
- asc = (sb_len > 12) ? sense_buffer[12] : 0;
- }
-
- if (sense_key == RECOVERED_ERROR) {
- return SG_ERR_CAT_RECOVERED;
- }
- else if (sense_key == UNIT_ATTENTION) {
- if (0x28 == asc) {
- return SG_ERR_CAT_MEDIA_CHANGED;
- }
- if (0x29 == asc) {
- return SG_ERR_CAT_RESET;
- }
- } else if (sense_key == ILLEGAL_REQUEST) {
- return SG_ERR_CAT_NOTSUPPORTED;
- }
- }
+ ((driver_status & 0xf) == DRIVER_SENSE))
+ {
+
+ if (sense_buffer && (sb_len > 2))
+ {
+ int sense_key;
+ unsigned char asc;
+
+ if (sense_buffer[0] & 0x2)
+ {
+ sense_key = sense_buffer[1] & 0xf;
+ asc = sense_buffer[2];
+ }
+ else
+ {
+ sense_key = sense_buffer[2] & 0xf;
+ asc = (sb_len > 12) ? sense_buffer[12] : 0;
+ }
+
+ if (sense_key == RECOVERED_ERROR)
+ {
+ return SG_ERR_CAT_RECOVERED;
+ }
+ else if (sense_key == UNIT_ATTENTION)
+ {
+ if (0x28 == asc)
+ {
+ return SG_ERR_CAT_MEDIA_CHANGED;
+ }
+ if (0x29 == asc)
+ {
+ return SG_ERR_CAT_RESET;
+ }
+ }
+ else if (sense_key == ILLEGAL_REQUEST)
+ {
+ return SG_ERR_CAT_NOTSUPPORTED;
+ }
+ }
return SG_ERR_CAT_SENSE;
- }
- if (host_status) {
+ }
+ if (host_status)
+ {
if ((host_status == DID_NO_CONNECT) ||
- (host_status == DID_BUS_BUSY) ||
- (host_status == DID_TIME_OUT)) {
- return SG_ERR_CAT_TIMEOUT;
- }
- }
- if (driver_status) {
- if (driver_status == DRIVER_TIMEOUT) {
- return SG_ERR_CAT_TIMEOUT;
- }
- }
- return SG_ERR_CAT_OTHER;
+ (host_status == DID_BUS_BUSY) || (host_status == DID_TIME_OUT))
+ {
+ return SG_ERR_CAT_TIMEOUT;
+ }
+ }
+ if (driver_status)
+ {
+ if (driver_status == DRIVER_TIMEOUT)
+ {
+ return SG_ERR_CAT_TIMEOUT;
+ }
+ }
+ return SG_ERR_CAT_OTHER;
}
-static int sg_err_category3( struct sg_io_hdr *hp) {
- return sg_err_category_new(hp->status, hp->msg_status, hp->host_status, hp->driver_status, hp->sbp, hp->sb_len_wr);
+static int
+sg_err_category3 (struct sg_io_hdr *hp)
+{
+ return sg_err_category_new (hp->status, hp->msg_status, hp->host_status,
+ hp->driver_status, hp->sbp, hp->sb_len_wr);
}
-static int sg_err_category4( struct sg_io_v4 *hp) {
- return sg_err_category_new( hp->device_status, 0, hp->transport_status, hp->driver_status, (unsigned char *)(uintptr_t)hp->response, hp->response_len);
+static int
+sg_err_category4 (struct sg_io_v4 *hp)
+{
+ return sg_err_category_new (hp->device_status, 0, hp->transport_status,
+ hp->driver_status,
+ (unsigned char *) (uintptr_t) hp->response,
+ hp->response_len);
}
-static int scsi_dump_sense( struct scsi_id_device *dev_scsi, unsigned char *sense_buffer, int sb_len) {
+static int
+scsi_dump_sense (struct scsi_id_device *dev_scsi,
+ unsigned char *sense_buffer, int sb_len)
+{
- int s;
- int code;
- int sense_class;
- int sense_key;
- int asc, ascq;
+ int s;
+ int code;
+ int sense_class;
+ int sense_key;
+ int asc, ascq;
#ifdef DUMP_SENSE
- char out_buffer[256];
- int i, j;
+ char out_buffer[256];
+ int i, j;
#endif
- /*
+ /*
* Figure out and print the sense key, asc and ascq.
*
* If you want to suppress these for a particular drive model, add
@@ -355,449 +391,555 @@ static int scsi_dump_sense( struct scsi_id_device *dev_scsi, unsigned char *sens
* we'll retry the command.
*/
- if (sb_len < 1) {
- log_debug("%s: sense buffer empty", dev_scsi->kernel);
+ if (sb_len < 1)
+ {
+ log_debug ("%s: sense buffer empty", dev_scsi->kernel);
return -1;
- }
+ }
- sense_class = (sense_buffer[0] >> 4) & 0x07;
- code = sense_buffer[0] & 0xf;
+ sense_class = (sense_buffer[0] >> 4) & 0x07;
+ code = sense_buffer[0] & 0xf;
- if (sense_class == 7) {
+ if (sense_class == 7)
+ {
/*
- * extended sense data.
- */
+ * extended sense data.
+ */
s = sense_buffer[7] + 8;
- if (sb_len < s) {
- log_debug("%s: sense buffer too small %d bytes, %d bytes too short", dev_scsi->kernel, sb_len, s - sb_len);
- return -1;
- }
- if ((code == 0x0) || (code == 0x1)) {
- sense_key = sense_buffer[2] & 0xf;
- if (s < 14) {
- /*
- * Possible?
- */
- log_debug("%s: sense result too" " small %d bytes", dev_scsi->kernel, s);
- return -1;
- }
- asc = sense_buffer[12];
- ascq = sense_buffer[13];
- } else if ((code == 0x2) || (code == 0x3)) {
- sense_key = sense_buffer[1] & 0xf;
- asc = sense_buffer[2];
- ascq = sense_buffer[3];
- } else {
- log_debug("%s: invalid sense code 0x%x", dev_scsi->kernel, code);
- return -1;
- }
- log_debug("%s: sense key 0x%x ASC 0x%x ASCQ 0x%x", dev_scsi->kernel, sense_key, asc, ascq);
- }
- else {
- if (sb_len < 4) {
- log_debug("%s: sense buffer too small %d bytes, %d bytes too short", dev_scsi->kernel, sb_len, 4 - sb_len);
- return -1;
- }
-
- if (sense_buffer[0] < 15) {
- log_debug("%s: old sense key: 0x%x", dev_scsi->kernel, sense_buffer[0] & 0x0f);
- }
-
- else {
- log_debug("%s: sense = %2x %2x", dev_scsi->kernel, sense_buffer[0], sense_buffer[2]);
- }
- log_debug("%s: non-extended sense class %d code 0x%0x", dev_scsi->kernel, sense_class, code);
-
- }
+ if (sb_len < s)
+ {
+ log_debug
+ ("%s: sense buffer too small %d bytes, %d bytes too short",
+ dev_scsi->kernel, sb_len, s - sb_len);
+ return -1;
+ }
+ if ((code == 0x0) || (code == 0x1))
+ {
+ sense_key = sense_buffer[2] & 0xf;
+ if (s < 14)
+ {
+ /*
+ * Possible?
+ */
+ log_debug ("%s: sense result too"
+ " small %d bytes", dev_scsi->kernel, s);
+ return -1;
+ }
+ asc = sense_buffer[12];
+ ascq = sense_buffer[13];
+ }
+ else if ((code == 0x2) || (code == 0x3))
+ {
+ sense_key = sense_buffer[1] & 0xf;
+ asc = sense_buffer[2];
+ ascq = sense_buffer[3];
+ }
+ else
+ {
+ log_debug ("%s: invalid sense code 0x%x", dev_scsi->kernel, code);
+ return -1;
+ }
+ log_debug ("%s: sense key 0x%x ASC 0x%x ASCQ 0x%x",
+ dev_scsi->kernel, sense_key, asc, ascq);
+ }
+ else
+ {
+ if (sb_len < 4)
+ {
+ log_debug
+ ("%s: sense buffer too small %d bytes, %d bytes too short",
+ dev_scsi->kernel, sb_len, 4 - sb_len);
+ return -1;
+ }
+
+ if (sense_buffer[0] < 15)
+ {
+ log_debug ("%s: old sense key: 0x%x", dev_scsi->kernel,
+ sense_buffer[0] & 0x0f);
+ }
+
+ else
+ {
+ log_debug ("%s: sense = %2x %2x", dev_scsi->kernel,
+ sense_buffer[0], sense_buffer[2]);
+ }
+ log_debug ("%s: non-extended sense class %d code 0x%0x",
+ dev_scsi->kernel, sense_class, code);
+
+ }
#ifdef DUMP_SENSE
- for (i = 0, j = 0; (i < s) && (j < 254); i++) {
+ for (i = 0, j = 0; (i < s) && (j < 254); i++)
+ {
out_buffer[j++] = hex_str[(sense_buffer[i] & 0xf0) >> 4];
out_buffer[j++] = hex_str[sense_buffer[i] & 0x0f];
out_buffer[j++] = ' ';
- }
- out_buffer[j] = '\0';
- log_debug("%s: sense dump:", dev_scsi->kernel);
- log_debug("%s: %s", dev_scsi->kernel, out_buffer);
+ }
+ out_buffer[j] = '\0';
+ log_debug ("%s: sense dump:", dev_scsi->kernel);
+ log_debug ("%s: %s", dev_scsi->kernel, out_buffer);
#endif
- return -1;
+ return -1;
}
-static int scsi_dump( struct scsi_id_device *dev_scsi, struct sg_io_hdr *io) {
+static int
+scsi_dump (struct scsi_id_device *dev_scsi, struct sg_io_hdr *io)
+{
- if (!io->status && !io->host_status && !io->msg_status && !io->driver_status) {
+ if (!io->status && !io->host_status && !io->msg_status
+ && !io->driver_status)
+ {
/*
- * Impossible, should not be called.
- */
- log_debug("%s: called with no error", __FUNCTION__);
+ * Impossible, should not be called.
+ */
+ log_debug ("%s: called with no error", __FUNCTION__);
return -1;
- }
-
- log_debug("%s: sg_io failed status 0x%x 0x%x 0x%x 0x%x", dev_scsi->kernel, io->driver_status, io->host_status, io->msg_status, io->status);
- if (io->status == SCSI_CHECK_CONDITION) {
- return scsi_dump_sense( dev_scsi, io->sbp, io->sb_len_wr);
- }
- else {
+ }
+
+ log_debug ("%s: sg_io failed status 0x%x 0x%x 0x%x 0x%x",
+ dev_scsi->kernel, io->driver_status, io->host_status,
+ io->msg_status, io->status);
+ if (io->status == SCSI_CHECK_CONDITION)
+ {
+ return scsi_dump_sense (dev_scsi, io->sbp, io->sb_len_wr);
+ }
+ else
+ {
return -1;
- }
+ }
}
-static int scsi_dump_v4( struct scsi_id_device *dev_scsi, struct sg_io_v4 *io) {
-
- if (!io->device_status && !io->transport_status && !io->driver_status) {
+static int
+scsi_dump_v4 (struct scsi_id_device *dev_scsi, struct sg_io_v4 *io)
+{
+
+ if (!io->device_status && !io->transport_status && !io->driver_status)
+ {
/*
- * Impossible, should not be called.
- */
- log_debug("%s: called with no error", __FUNCTION__);
+ * Impossible, should not be called.
+ */
+ log_debug ("%s: called with no error", __FUNCTION__);
return -1;
- }
-
- log_debug("%s: sg_io failed status 0x%x 0x%x 0x%x", dev_scsi->kernel, io->driver_status, io->transport_status, io->device_status);
-
- if (io->device_status == SCSI_CHECK_CONDITION) {
- return scsi_dump_sense( dev_scsi, (unsigned char *)(uintptr_t)io->response, io->response_len);
- }
- else {
+ }
+
+ log_debug ("%s: sg_io failed status 0x%x 0x%x 0x%x", dev_scsi->kernel,
+ io->driver_status, io->transport_status, io->device_status);
+
+ if (io->device_status == SCSI_CHECK_CONDITION)
+ {
+ return scsi_dump_sense (dev_scsi,
+ (unsigned char *) (uintptr_t) io->response,
+ io->response_len);
+ }
+ else
+ {
return -1;
- }
+ }
}
-static int scsi_inquiry(struct scsi_id_device *dev_scsi, int fd, unsigned char evpd, unsigned char page, unsigned char *buf, unsigned int buflen) {
-
- unsigned char inq_cmd[INQUIRY_CMDLEN] = { INQUIRY_CMD, evpd, page, 0, buflen, 0 };
- unsigned char sense[SENSE_BUFF_LEN];
- void *io_buf;
- struct sg_io_v4 io_v4;
- struct sg_io_hdr io_hdr;
- int retry = 3; /* rather random */
- int retval;
- int rc = 0;
+static int
+scsi_inquiry (struct scsi_id_device *dev_scsi, int fd,
+ unsigned char evpd, unsigned char page,
+ unsigned char *buf, unsigned int buflen)
+{
- if (buflen > SCSI_INQ_BUFF_LEN) {
- log_debug("buflen %d too long", buflen);
+ unsigned char inq_cmd[INQUIRY_CMDLEN] =
+ { INQUIRY_CMD, evpd, page, 0, buflen, 0 };
+ unsigned char sense[SENSE_BUFF_LEN];
+ void *io_buf;
+ struct sg_io_v4 io_v4;
+ struct sg_io_hdr io_hdr;
+ int retry = 3; /* rather random */
+ int retval;
+ int rc = 0;
+
+ if (buflen > SCSI_INQ_BUFF_LEN)
+ {
+ log_debug ("buflen %d too long", buflen);
return -1;
- }
+ }
resend:
- if (dev_scsi->use_sg == 4) {
- memzero(&io_v4, sizeof(struct sg_io_v4));
+ if (dev_scsi->use_sg == 4)
+ {
+ memzero (&io_v4, sizeof (struct sg_io_v4));
io_v4.guard = 'Q';
io_v4.protocol = BSG_PROTOCOL_SCSI;
io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD;
- io_v4.request_len = sizeof(inq_cmd);
- io_v4.request = (uintptr_t)inq_cmd;
- io_v4.max_response_len = sizeof(sense);
- io_v4.response = (uintptr_t)sense;
+ io_v4.request_len = sizeof (inq_cmd);
+ io_v4.request = (uintptr_t) inq_cmd;
+ io_v4.max_response_len = sizeof (sense);
+ io_v4.response = (uintptr_t) sense;
io_v4.din_xfer_len = buflen;
- io_v4.din_xferp = (uintptr_t)buf;
- io_buf = (void *)&io_v4;
- }
- else {
- memzero(&io_hdr, sizeof(struct sg_io_hdr));
+ io_v4.din_xferp = (uintptr_t) buf;
+ io_buf = (void *) &io_v4;
+ }
+ else
+ {
+ memzero (&io_hdr, sizeof (struct sg_io_hdr));
io_hdr.interface_id = 'S';
- io_hdr.cmd_len = sizeof(inq_cmd);
- io_hdr.mx_sb_len = sizeof(sense);
+ io_hdr.cmd_len = sizeof (inq_cmd);
+ io_hdr.mx_sb_len = sizeof (sense);
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
io_hdr.dxfer_len = buflen;
io_hdr.dxferp = buf;
io_hdr.cmdp = inq_cmd;
io_hdr.sbp = sense;
io_hdr.timeout = DEF_TIMEOUT;
- io_buf = (void *)&io_hdr;
- }
-
- retval = ioctl(fd, SG_IO, io_buf);
- if (retval < 0) {
- if ((errno == EINVAL || errno == ENOSYS) && dev_scsi->use_sg == 4) {
- dev_scsi->use_sg = 3;
- goto resend;
- }
-
+ io_buf = (void *) &io_hdr;
+ }
+
+ retval = ioctl (fd, SG_IO, io_buf);
+ if (retval < 0)
+ {
+ if ((errno == EINVAL || errno == ENOSYS) && dev_scsi->use_sg == 4)
+ {
+ dev_scsi->use_sg = 3;
+ goto resend;
+ }
+
rc = -errno;
- log_debug( "%s: ioctl failed: errno = %d", dev_scsi->kernel, rc);
+ log_debug ("%s: ioctl failed: errno = %d", dev_scsi->kernel, rc);
goto error;
- }
-
- if (dev_scsi->use_sg == 4) {
- retval = sg_err_category4(io_buf);
- }
- else {
- retval = sg_err_category3(io_buf);
- }
-
- switch (retval) {
- case SG_ERR_CAT_NOTSUPPORTED:
+ }
+
+ if (dev_scsi->use_sg == 4)
+ {
+ retval = sg_err_category4 (io_buf);
+ }
+ else
+ {
+ retval = sg_err_category3 (io_buf);
+ }
+
+ switch (retval)
+ {
+ case SG_ERR_CAT_NOTSUPPORTED:
buf[1] = 0;
- /* Fallthrough */
- case SG_ERR_CAT_CLEAN:
- case SG_ERR_CAT_RECOVERED:
+ /* Fallthrough */
+ case SG_ERR_CAT_CLEAN:
+ case SG_ERR_CAT_RECOVERED:
retval = 0;
break;
- default:
- if (dev_scsi->use_sg == 4) {
- retval = scsi_dump_v4(dev_scsi, io_buf);
- }
- else {
- retval = scsi_dump(dev_scsi, io_buf);
- }
- }
-
- if (!retval) {
+ default:
+ if (dev_scsi->use_sg == 4)
+ {
+ retval = scsi_dump_v4 (dev_scsi, io_buf);
+ }
+ else
+ {
+ retval = scsi_dump (dev_scsi, io_buf);
+ }
+ }
+
+ if (!retval)
+ {
retval = buflen;
- } else if (retval > 0) {
- if (--retry > 0) {
- goto resend;
- }
+ }
+ else if (retval > 0)
+ {
+ if (--retry > 0)
+ {
+ goto resend;
+ }
retval = -1;
- }
+ }
error:
- if (retval < 0) {
- log_debug("%s: Unable to get INQUIRY vpd %d page 0x%x.", dev_scsi->kernel, evpd, page);
- }
-
- return retval;
+ if (retval < 0)
+ {
+ log_debug ("%s: Unable to get INQUIRY vpd %d page 0x%x.",
+ dev_scsi->kernel, evpd, page);
+ }
+
+ return retval;
}
/* Get list of supported EVPD pages */
-static int do_scsi_page0_inquiry( struct scsi_id_device *dev_scsi, int fd, unsigned char *buffer, unsigned int len) {
+static int
+do_scsi_page0_inquiry (struct scsi_id_device *dev_scsi, int fd,
+ unsigned char *buffer, unsigned int len)
+{
- int retval;
+ int retval;
- memzero(buffer, len);
- retval = scsi_inquiry( dev_scsi, fd, 1, 0x0, buffer, len);
- if (retval < 0) {
+ memzero (buffer, len);
+ retval = scsi_inquiry (dev_scsi, fd, 1, 0x0, buffer, len);
+ if (retval < 0)
+ {
return 1;
- }
+ }
- if (buffer[1] != 0) {
- log_debug("%s: page 0 not available.", dev_scsi->kernel);
+ if (buffer[1] != 0)
+ {
+ log_debug ("%s: page 0 not available.", dev_scsi->kernel);
return 1;
- }
- if (buffer[3] > len) {
- log_debug("%s: page 0 buffer too long %d", dev_scsi->kernel, buffer[3]);
+ }
+ if (buffer[3] > len)
+ {
+ log_debug ("%s: page 0 buffer too long %d", dev_scsi->kernel,
+ buffer[3]);
return 1;
- }
+ }
- /*
+ /*
* Following check is based on code once included in the 2.5.x
* kernel.
*
* Some ill behaved devices return the standard inquiry here
* rather than the evpd data, snoop the data to verify.
*/
- if (buffer[3] > MODEL_LENGTH) {
+ if (buffer[3] > MODEL_LENGTH)
+ {
/*
- * If the vendor id appears in the page assume the page is
- * invalid.
- */
- if (strneq((char *)&buffer[VENDOR_LENGTH], dev_scsi->vendor, VENDOR_LENGTH)) {
- log_debug("%s: invalid page0 data", dev_scsi->kernel);
- return 1;
- }
- }
- return 0;
+ * If the vendor id appears in the page assume the page is
+ * invalid.
+ */
+ if (strneq
+ ((char *) &buffer[VENDOR_LENGTH], dev_scsi->vendor, VENDOR_LENGTH))
+ {
+ log_debug ("%s: invalid page0 data", dev_scsi->kernel);
+ return 1;
+ }
+ }
+ return 0;
}
/*
* The caller checks that serial is long enough to include the vendor +
* model.
*/
-static int prepend_vendor_model(struct scsi_id_device *dev_scsi, char *serial) {
+static int
+prepend_vendor_model (struct scsi_id_device *dev_scsi, char *serial)
+{
- int ind;
+ int ind;
- strncpy(serial, dev_scsi->vendor, VENDOR_LENGTH);
- strncat(serial, dev_scsi->model, MODEL_LENGTH);
- ind = strlen(serial);
+ strncpy (serial, dev_scsi->vendor, VENDOR_LENGTH);
+ strncat (serial, dev_scsi->model, MODEL_LENGTH);
+ ind = strlen (serial);
- /*
+ /*
* This is not a complete check, since we are using strncat/cpy
* above, ind will never be too large.
*/
- if (ind != (VENDOR_LENGTH + MODEL_LENGTH)) {
- log_debug("%s: expected length %d, got length %d", dev_scsi->kernel, (VENDOR_LENGTH + MODEL_LENGTH), ind);
+ if (ind != (VENDOR_LENGTH + MODEL_LENGTH))
+ {
+ log_debug ("%s: expected length %d, got length %d",
+ dev_scsi->kernel, (VENDOR_LENGTH + MODEL_LENGTH), ind);
return -1;
- }
- return ind;
+ }
+ return ind;
}
/*
* check_fill_0x83_id - check the page 0x83 id, if OK allocate and fill
* serial number.
*/
-static int check_fill_0x83_id(struct scsi_id_device *dev_scsi,
- unsigned char *page_83,
- const struct scsi_id_search_values
- *id_search, char *serial, char *serial_short,
- int max_len, char *wwn,
- char *wwn_vendor_extension, char *tgpt_group) {
+static int
+check_fill_0x83_id (struct scsi_id_device *dev_scsi,
+ unsigned char *page_83,
+ const struct scsi_id_search_values
+ *id_search, char *serial, char *serial_short,
+ int max_len, char *wwn,
+ char *wwn_vendor_extension, char *tgpt_group)
+{
- int i, j, s, len;
+ int i, j, s, len;
- /*
+ /*
* ASSOCIATION must be with the device (value 0)
* or with the target port for SCSI_ID_TGTPORT
*/
- if ((page_83[1] & 0x30) == 0x10) {
- if (id_search->id_type != SCSI_ID_TGTGROUP) {
- return 1;
- }
- }
- else if ((page_83[1] & 0x30) != 0) {
+ if ((page_83[1] & 0x30) == 0x10)
+ {
+ if (id_search->id_type != SCSI_ID_TGTGROUP)
+ {
+ return 1;
+ }
+ }
+ else if ((page_83[1] & 0x30) != 0)
+ {
return 1;
- }
+ }
- if ((page_83[1] & 0x0f) != id_search->id_type) {
+ if ((page_83[1] & 0x0f) != id_search->id_type)
+ {
return 1;
- }
+ }
- /*
+ /*
* Possibly check NAA sub-type.
*/
- if ((id_search->naa_type != SCSI_ID_NAA_DONT_CARE) && (id_search->naa_type != (page_83[4] & 0xf0) >> 4)) {
+ if ((id_search->naa_type != SCSI_ID_NAA_DONT_CARE)
+ && (id_search->naa_type != (page_83[4] & 0xf0) >> 4))
+ {
return 1;
- }
+ }
- /*
+ /*
* Check for matching code set - ASCII or BINARY.
*/
- if ((page_83[0] & 0x0f) != id_search->code_set) {
+ if ((page_83[0] & 0x0f) != id_search->code_set)
+ {
return 1;
- }
+ }
- /*
+ /*
* page_83[3]: identifier length
*/
- len = page_83[3];
- if ((page_83[0] & 0x0f) != SCSI_ID_ASCII) {
+ len = page_83[3];
+ if ((page_83[0] & 0x0f) != SCSI_ID_ASCII)
+ {
/*
- * If not ASCII, use two bytes for each binary value.
- */
+ * If not ASCII, use two bytes for each binary value.
+ */
len *= 2;
- }
+ }
- /*
+ /*
* Add one byte for the NUL termination, and one for the id_type.
*/
- len += 2;
- if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) {
+ len += 2;
+ if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC)
+ {
len += VENDOR_LENGTH + MODEL_LENGTH;
- }
+ }
- if (max_len < len) {
- log_debug("%s: length %d too short - need %d", dev_scsi->kernel, max_len, len);
+ if (max_len < len)
+ {
+ log_debug ("%s: length %d too short - need %d", dev_scsi->kernel,
+ max_len, len);
return 1;
- }
+ }
- if (id_search->id_type == SCSI_ID_TGTGROUP && tgpt_group != NULL) {
+ if (id_search->id_type == SCSI_ID_TGTGROUP && tgpt_group != NULL)
+ {
unsigned int group;
- group = ((unsigned int)page_83[6] << 8) | page_83[7];
- sprintf(tgpt_group,"%x", group);
+ group = ((unsigned int) page_83[6] << 8) | page_83[7];
+ sprintf (tgpt_group, "%x", group);
return 1;
- }
+ }
- serial[0] = hex_str[id_search->id_type];
+ serial[0] = hex_str[id_search->id_type];
- /*
+ /*
* For SCSI_ID_VENDOR_SPECIFIC prepend the vendor and model before
* the id since it is not unique across all vendors and models,
* this differs from SCSI_ID_T10_VENDOR, where the vendor is
* included in the identifier.
*/
- if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) {
- if (prepend_vendor_model( dev_scsi, &serial[1]) < 0) {
- return 1;
- }
- }
-
- i = 4; /* offset to the start of the identifier */
- s = j = strlen(serial);
- if ((page_83[0] & 0x0f) == SCSI_ID_ASCII) {
+ if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC)
+ {
+ if (prepend_vendor_model (dev_scsi, &serial[1]) < 0)
+ {
+ return 1;
+ }
+ }
+
+ i = 4; /* offset to the start of the identifier */
+ s = j = strlen (serial);
+ if ((page_83[0] & 0x0f) == SCSI_ID_ASCII)
+ {
/*
- * ASCII descriptor.
- */
- while (i < (4 + page_83[3])) {
- serial[j++] = page_83[i++];
- }
- } else {
+ * ASCII descriptor.
+ */
+ while (i < (4 + page_83[3]))
+ {
+ serial[j++] = page_83[i++];
+ }
+ }
+ else
+ {
/*
- * Binary descriptor, convert to ASCII, using two bytes of
- * ASCII for each byte in the page_83.
- */
- while (i < (4 + page_83[3])) {
- serial[j++] = hex_str[(page_83[i] & 0xf0) >> 4];
- serial[j++] = hex_str[page_83[i] & 0x0f];
- i++;
- }
- }
-
- strcpy(serial_short, &serial[s]);
-
- if (id_search->id_type == SCSI_ID_NAA && wwn != NULL) {
- strncpy(wwn, &serial[s], 16);
- if (wwn_vendor_extension != NULL) {
- strncpy(wwn_vendor_extension, &serial[s + 16], 16);
- }
- }
-
- return 0;
+ * Binary descriptor, convert to ASCII, using two bytes of
+ * ASCII for each byte in the page_83.
+ */
+ while (i < (4 + page_83[3]))
+ {
+ serial[j++] = hex_str[(page_83[i] & 0xf0) >> 4];
+ serial[j++] = hex_str[page_83[i] & 0x0f];
+ i++;
+ }
+ }
+
+ strcpy (serial_short, &serial[s]);
+
+ if (id_search->id_type == SCSI_ID_NAA && wwn != NULL)
+ {
+ strncpy (wwn, &serial[s], 16);
+ if (wwn_vendor_extension != NULL)
+ {
+ strncpy (wwn_vendor_extension, &serial[s + 16], 16);
+ }
+ }
+
+ return 0;
}
/* Extract the raw binary from VPD 0x83 pre-SPC devices */
-static int check_fill_0x83_prespc3(struct scsi_id_device *dev_scsi,
- unsigned char *page_83,
- const struct scsi_id_search_values
- *id_search, char *serial, char *serial_short, int max_len) {
- int i, j;
-
- serial[0] = hex_str[id_search->id_type];
- /* serial has been memset to zero before */
- j = strlen(serial); /* j = 1; */
-
- for (i = 0; (i < page_83[3]) && (j < max_len-3); ++i) {
- serial[j++] = hex_str[(page_83[4+i] & 0xf0) >> 4];
- serial[j++] = hex_str[ page_83[4+i] & 0x0f];
- }
- serial[max_len-1] = 0;
- strncpy(serial_short, serial, max_len-1);
- return 0;
+static int
+check_fill_0x83_prespc3 (struct scsi_id_device *dev_scsi,
+ unsigned char *page_83,
+ const struct scsi_id_search_values
+ *id_search, char *serial, char *serial_short,
+ int max_len)
+{
+ int i, j;
+
+ serial[0] = hex_str[id_search->id_type];
+ /* serial has been memset to zero before */
+ j = strlen (serial); /* j = 1; */
+
+ for (i = 0; (i < page_83[3]) && (j < max_len - 3); ++i)
+ {
+ serial[j++] = hex_str[(page_83[4 + i] & 0xf0) >> 4];
+ serial[j++] = hex_str[page_83[4 + i] & 0x0f];
+ }
+ serial[max_len - 1] = 0;
+ strncpy (serial_short, serial, max_len - 1);
+ return 0;
}
-
/* Get device identification VPD page */
-static int do_scsi_page83_inquiry(struct scsi_id_device *dev_scsi, int fd,
- char *serial, char *serial_short, int len,
- char *unit_serial_number, char *wwn,
- char *wwn_vendor_extension, char *tgpt_group) {
- int retval;
- unsigned int id_ind, j;
- unsigned char page_83[SCSI_INQ_BUFF_LEN];
-
- /* also pick up the page 80 serial number */
- do_scsi_page80_inquiry( dev_scsi, fd, NULL, unit_serial_number, MAX_SERIAL_LEN);
-
- memzero(page_83, SCSI_INQ_BUFF_LEN);
- retval = scsi_inquiry( dev_scsi, fd, 1, PAGE_83, page_83, SCSI_INQ_BUFF_LEN);
- if (retval < 0) {
+static int
+do_scsi_page83_inquiry (struct scsi_id_device *dev_scsi, int fd,
+ char *serial, char *serial_short, int len,
+ char *unit_serial_number, char *wwn,
+ char *wwn_vendor_extension, char *tgpt_group)
+{
+ int retval;
+ unsigned int id_ind, j;
+ unsigned char page_83[SCSI_INQ_BUFF_LEN];
+
+ /* also pick up the page 80 serial number */
+ do_scsi_page80_inquiry (dev_scsi, fd, NULL, unit_serial_number,
+ MAX_SERIAL_LEN);
+
+ memzero (page_83, SCSI_INQ_BUFF_LEN);
+ retval =
+ scsi_inquiry (dev_scsi, fd, 1, PAGE_83, page_83, SCSI_INQ_BUFF_LEN);
+ if (retval < 0)
+ {
return 1;
- }
+ }
- if (page_83[1] != PAGE_83) {
- log_debug("%s: Invalid page 0x83", dev_scsi->kernel);
+ if (page_83[1] != PAGE_83)
+ {
+ log_debug ("%s: Invalid page 0x83", dev_scsi->kernel);
return 1;
- }
+ }
- /*
+ /*
* XXX Some devices (IBM 3542) return all spaces for an identifier if
* the LUN is not actually configured. This leads to identifiers of
* the form: "1 ".
*/
- /*
+ /*
* Model 4, 5, and (some) model 6 EMC Symmetrix devices return
* a page 83 reply according to SCSI-2 format instead of SPC-2/3.
*
@@ -820,35 +962,43 @@ static int do_scsi_page83_inquiry(struct scsi_id_device *dev_scsi, int fd,
* 0x006048.
*/
- if (page_83[6] != 0) {
- return check_fill_0x83_prespc3(dev_scsi, page_83, id_search_list, serial, serial_short, len);
- }
-
- /*
+ if (page_83[6] != 0)
+ {
+ return check_fill_0x83_prespc3 (dev_scsi, page_83,
+ id_search_list, serial,
+ serial_short, len);
+ }
+
+ /*
* Search for a match in the prioritized id_search_list - since WWN ids
* come first we can pick up the WWN in check_fill_0x83_id().
*/
- for (id_ind = 0; id_ind < sizeof(id_search_list)/sizeof(id_search_list[0]); id_ind++) {
+ for (id_ind = 0;
+ id_ind < sizeof (id_search_list) / sizeof (id_search_list[0]);
+ id_ind++)
+ {
/*
- * Examine each descriptor returned. There is normally only
- * one or a small number of descriptors.
- */
- for (j = 4; j <= (unsigned int)page_83[3] + 3; j += page_83[j + 3] + 4) {
-
- retval = check_fill_0x83_id( dev_scsi, &page_83[j],
- &id_search_list[id_ind],
- serial, serial_short, len,
- wwn, wwn_vendor_extension,
- tgpt_group);
- if (!retval) {
- return retval;
- }
- else if (retval < 0) {
- return retval;
- }
- }
- }
- return 1;
+ * Examine each descriptor returned. There is normally only
+ * one or a small number of descriptors.
+ */
+ for (j = 4; j <= (unsigned int) page_83[3] + 3; j += page_83[j + 3] + 4)
+ {
+
+ retval = check_fill_0x83_id (dev_scsi, &page_83[j],
+ &id_search_list[id_ind],
+ serial, serial_short, len,
+ wwn, wwn_vendor_extension, tgpt_group);
+ if (!retval)
+ {
+ return retval;
+ }
+ else if (retval < 0)
+ {
+ return retval;
+ }
+ }
+ }
+ return 1;
}
/*
@@ -858,22 +1008,29 @@ static int do_scsi_page83_inquiry(struct scsi_id_device *dev_scsi, int fd,
* Return the hard coded error code value 2 if the page 83 reply is not
* conformant to the SCSI-2 format.
*/
-static int do_scsi_page83_prespc3_inquiry(struct scsi_id_device *dev_scsi, int fd, char *serial, char *serial_short, int len) {
- int retval;
- int i, j;
- unsigned char page_83[SCSI_INQ_BUFF_LEN];
-
- memzero(page_83, SCSI_INQ_BUFF_LEN);
- retval = scsi_inquiry(dev_scsi, fd, 1, PAGE_83, page_83, SCSI_INQ_BUFF_LEN);
- if (retval < 0) {
+static int
+do_scsi_page83_prespc3_inquiry (struct scsi_id_device *dev_scsi,
+ int fd, char *serial,
+ char *serial_short, int len)
+{
+ int retval;
+ int i, j;
+ unsigned char page_83[SCSI_INQ_BUFF_LEN];
+
+ memzero (page_83, SCSI_INQ_BUFF_LEN);
+ retval =
+ scsi_inquiry (dev_scsi, fd, 1, PAGE_83, page_83, SCSI_INQ_BUFF_LEN);
+ if (retval < 0)
+ {
return 1;
- }
+ }
- if (page_83[1] != PAGE_83) {
- log_debug("%s: Invalid page 0x83", dev_scsi->kernel);
+ if (page_83[1] != PAGE_83)
+ {
+ log_debug ("%s: Invalid page 0x83", dev_scsi->kernel);
return 1;
- }
- /*
+ }
+ /*
* Model 4, 5, and (some) model 6 EMC Symmetrix devices return
* a page 83 reply according to SCSI-2 format instead of SPC-2/3.
*
@@ -895,279 +1052,348 @@ static int do_scsi_page83_prespc3_inquiry(struct scsi_id_device *dev_scsi, int f
* to the 4th and 5th nibbles of the 6-byte OUI for EMC, that is,
* 0x006048.
*/
- if (page_83[6] == 0) {
+ if (page_83[6] == 0)
+ {
return 2;
- }
+ }
- serial[0] = hex_str[id_search_list[0].id_type];
- /*
+ serial[0] = hex_str[id_search_list[0].id_type];
+ /*
* The first four bytes contain data, not a descriptor.
*/
- i = 4;
- j = strlen(serial);
- /*
+ i = 4;
+ j = strlen (serial);
+ /*
* Binary descriptor, convert to ASCII,
* using two bytes of ASCII for each byte
* in the page_83.
*/
- while (i < (page_83[3]+4)) {
+ while (i < (page_83[3] + 4))
+ {
serial[j++] = hex_str[(page_83[i] & 0xf0) >> 4];
serial[j++] = hex_str[page_83[i] & 0x0f];
i++;
- }
- return 0;
+ }
+ return 0;
}
/* Get unit serial number VPD page */
-static int do_scsi_page80_inquiry(struct scsi_id_device *dev_scsi, int fd,
- char *serial, char *serial_short, int max_len) {
-
- int retval;
- int ser_ind;
- int i;
- int len;
- unsigned char buf[SCSI_INQ_BUFF_LEN];
-
- memzero(buf, SCSI_INQ_BUFF_LEN);
- retval = scsi_inquiry( dev_scsi, fd, 1, PAGE_80, buf, SCSI_INQ_BUFF_LEN);
- if (retval < 0) {
+static int
+do_scsi_page80_inquiry (struct scsi_id_device *dev_scsi, int fd,
+ char *serial, char *serial_short, int max_len)
+{
+
+ int retval;
+ int ser_ind;
+ int i;
+ int len;
+ unsigned char buf[SCSI_INQ_BUFF_LEN];
+
+ memzero (buf, SCSI_INQ_BUFF_LEN);
+ retval = scsi_inquiry (dev_scsi, fd, 1, PAGE_80, buf, SCSI_INQ_BUFF_LEN);
+ if (retval < 0)
+ {
return retval;
- }
+ }
- if (buf[1] != PAGE_80) {
- log_debug("%s: Invalid page 0x80", dev_scsi->kernel);
+ if (buf[1] != PAGE_80)
+ {
+ log_debug ("%s: Invalid page 0x80", dev_scsi->kernel);
return 1;
- }
+ }
- len = 1 + VENDOR_LENGTH + MODEL_LENGTH + buf[3];
- if (max_len < len) {
- log_debug("%s: length %d too short - need %d", dev_scsi->kernel, max_len, len);
+ len = 1 + VENDOR_LENGTH + MODEL_LENGTH + buf[3];
+ if (max_len < len)
+ {
+ log_debug ("%s: length %d too short - need %d", dev_scsi->kernel,
+ max_len, len);
return 1;
- }
- /*
+ }
+ /*
* Prepend 'S' to avoid unlikely collision with page 0x83 vendor
* specific type where we prepend '0' + vendor + model.
*/
- len = buf[3];
- if (serial != NULL) {
+ len = buf[3];
+ if (serial != NULL)
+ {
serial[0] = 'S';
- ser_ind = prepend_vendor_model( dev_scsi, &serial[1]);
- if (ser_ind < 0) {
- return 1;
- }
- ser_ind++; /* for the leading 'S' */
- for (i = 4; i < len + 4; i++, ser_ind++) {
- serial[ser_ind] = buf[i];
- }
- }
- if (serial_short != NULL) {
- memcpy(serial_short, &buf[4], len);
+ ser_ind = prepend_vendor_model (dev_scsi, &serial[1]);
+ if (ser_ind < 0)
+ {
+ return 1;
+ }
+ ser_ind++; /* for the leading 'S' */
+ for (i = 4; i < len + 4; i++, ser_ind++)
+ {
+ serial[ser_ind] = buf[i];
+ }
+ }
+ if (serial_short != NULL)
+ {
+ memcpy (serial_short, &buf[4], len);
serial_short[len] = '\0';
- }
- return 0;
+ }
+ return 0;
}
-int scsi_std_inquiry(struct scsi_id_device *dev_scsi, const char *devname) {
-
- int fd;
- unsigned char buf[SCSI_INQ_BUFF_LEN];
- struct stat statbuf;
- int err = 0;
+int
+scsi_std_inquiry (struct scsi_id_device *dev_scsi, const char *devname)
+{
+
+ int fd;
+ unsigned char buf[SCSI_INQ_BUFF_LEN];
+ struct stat statbuf;
+ int err = 0;
- fd = open(devname, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
- if (fd < 0) {
+ fd = open (devname, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ if (fd < 0)
+ {
err = -errno;
- log_debug( "scsi_id: cannot open %s: errno = %d", devname, err);
+ log_debug ("scsi_id: cannot open %s: errno = %d", devname, err);
return 1;
- }
+ }
+
+ if (fstat (fd, &statbuf) < 0)
+ {
- if (fstat(fd, &statbuf) < 0) {
-
err = -errno;
- log_debug( "scsi_id: cannot stat %s: errno = %d", devname, err);
+ log_debug ("scsi_id: cannot stat %s: errno = %d", devname, err);
err = 2;
goto out;
- }
-
- sprintf(dev_scsi->kernel,"%d:%d", major(statbuf.st_rdev), minor(statbuf.st_rdev));
+ }
+
+ sprintf (dev_scsi->kernel, "%d:%d", major (statbuf.st_rdev),
+ minor (statbuf.st_rdev));
- memzero(buf, SCSI_INQ_BUFF_LEN);
- err = scsi_inquiry( dev_scsi, fd, 0, 0, buf, SCSI_INQ_BUFF_LEN);
- if (err < 0) {
+ memzero (buf, SCSI_INQ_BUFF_LEN);
+ err = scsi_inquiry (dev_scsi, fd, 0, 0, buf, SCSI_INQ_BUFF_LEN);
+ if (err < 0)
+ {
goto out;
- }
+ }
- err = 0;
- memcpy(dev_scsi->vendor, buf + 8, 8);
- dev_scsi->vendor[8] = '\0';
- memcpy(dev_scsi->model, buf + 16, 16);
- dev_scsi->model[16] = '\0';
- memcpy(dev_scsi->revision, buf + 32, 4);
- dev_scsi->revision[4] = '\0';
- sprintf(dev_scsi->type,"%x", buf[0] & 0x1f);
+ err = 0;
+ memcpy (dev_scsi->vendor, buf + 8, 8);
+ dev_scsi->vendor[8] = '\0';
+ memcpy (dev_scsi->model, buf + 16, 16);
+ dev_scsi->model[16] = '\0';
+ memcpy (dev_scsi->revision, buf + 32, 4);
+ dev_scsi->revision[4] = '\0';
+ sprintf (dev_scsi->type, "%x", buf[0] & 0x1f);
out:
- close(fd);
- return err;
+ close (fd);
+ return err;
}
-int scsi_get_serial(struct scsi_id_device *dev_scsi, const char *devname, int page_code, int len) {
+int
+scsi_get_serial (struct scsi_id_device *dev_scsi, const char *devname,
+ int page_code, int len)
+{
+
+ unsigned char page0[SCSI_INQ_BUFF_LEN];
+ int fd = -1;
+ int cnt;
+ int ind;
+ int retval;
- unsigned char page0[SCSI_INQ_BUFF_LEN];
- int fd = -1;
- int cnt;
- int ind;
- int retval;
+ memzero (dev_scsi->serial, len);
+ initialize_srand ();
- memzero(dev_scsi->serial, len);
- initialize_srand();
-
- for (cnt = 20; cnt > 0; cnt--) {
+ for (cnt = 20; cnt > 0; cnt--)
+ {
struct timespec duration;
- fd = open(devname, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
- if (fd >= 0 || errno != EBUSY) {
- break;
- }
-
+ fd = open (devname, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ if (fd >= 0 || errno != EBUSY)
+ {
+ break;
+ }
+
duration.tv_sec = 0;
- duration.tv_nsec = (200 * 1000 * 1000) + (rand() % 100 * 1000 * 1000);
- nanosleep(&duration, NULL);
- }
- if (fd < 0) {
+ duration.tv_nsec = (200 * 1000 * 1000) + (rand () % 100 * 1000 * 1000);
+ nanosleep (&duration, NULL);
+ }
+ if (fd < 0)
+ {
return 1;
- }
-
- if (page_code == PAGE_80) {
- if (do_scsi_page80_inquiry( dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len)) {
- retval = 1;
- goto completed;
- } else {
- retval = 0;
- goto completed;
- }
- }
- else if (page_code == PAGE_83) {
- if (do_scsi_page83_inquiry( dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) {
- retval = 1;
- goto completed;
- } else {
- retval = 0;
- goto completed;
- }
- }
- else if (page_code == PAGE_83_PRE_SPC3) {
- retval = do_scsi_page83_prespc3_inquiry( dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len);
- if (retval) {
- /*
- * Fallback to servicing a SPC-2/3 compliant page 83
- * inquiry if the page 83 reply format does not
- * conform to pre-SPC3 expectations.
- */
- if (retval == 2) {
- if (do_scsi_page83_inquiry( dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) {
- retval = 1;
- goto completed;
- } else {
- retval = 0;
- goto completed;
- }
- }
- else {
- retval = 1;
- goto completed;
- }
- } else {
- retval = 0;
- goto completed;
- }
- } else if (page_code != 0x00) {
- log_debug("%s: unsupported page code 0x%d", dev_scsi->kernel, page_code);
+ }
+
+ if (page_code == PAGE_80)
+ {
+ if (do_scsi_page80_inquiry
+ (dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len))
+ {
+ retval = 1;
+ goto completed;
+ }
+ else
+ {
+ retval = 0;
+ goto completed;
+ }
+ }
+ else if (page_code == PAGE_83)
+ {
+ if (do_scsi_page83_inquiry
+ (dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short,
+ len, dev_scsi->unit_serial_number, dev_scsi->wwn,
+ dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group))
+ {
+ retval = 1;
+ goto completed;
+ }
+ else
+ {
+ retval = 0;
+ goto completed;
+ }
+ }
+ else if (page_code == PAGE_83_PRE_SPC3)
+ {
+ retval =
+ do_scsi_page83_prespc3_inquiry (dev_scsi, fd,
+ dev_scsi->serial,
+ dev_scsi->serial_short, len);
+ if (retval)
+ {
+ /*
+ * Fallback to servicing a SPC-2/3 compliant page 83
+ * inquiry if the page 83 reply format does not
+ * conform to pre-SPC3 expectations.
+ */
+ if (retval == 2)
+ {
+ if (do_scsi_page83_inquiry
+ (dev_scsi, fd, dev_scsi->serial,
+ dev_scsi->serial_short, len,
+ dev_scsi->unit_serial_number,
+ dev_scsi->wwn,
+ dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group))
+ {
+ retval = 1;
+ goto completed;
+ }
+ else
+ {
+ retval = 0;
+ goto completed;
+ }
+ }
+ else
+ {
+ retval = 1;
+ goto completed;
+ }
+ }
+ else
+ {
+ retval = 0;
+ goto completed;
+ }
+ }
+ else if (page_code != 0x00)
+ {
+ log_debug ("%s: unsupported page code 0x%d", dev_scsi->kernel,
+ page_code);
retval = 1;
goto completed;
- }
+ }
- /*
+ /*
* Get page 0, the page of the pages. By default, try from best to
* worst of supported pages: 0x83 then 0x80.
*/
- if (do_scsi_page0_inquiry( dev_scsi, fd, page0, SCSI_INQ_BUFF_LEN)) {
+ if (do_scsi_page0_inquiry (dev_scsi, fd, page0, SCSI_INQ_BUFF_LEN))
+ {
/*
- * Don't try anything else. Black list if a specific page
- * should be used for this vendor+model, or maybe have an
- * optional fall-back to page 0x80 or page 0x83.
- */
+ * Don't try anything else. Black list if a specific page
+ * should be used for this vendor+model, or maybe have an
+ * optional fall-back to page 0x80 or page 0x83.
+ */
retval = 1;
goto completed;
- }
-
- for (ind = 4; ind <= page0[3] + 3; ind++) {
- if (page0[ind] == PAGE_83) {
- if (!do_scsi_page83_inquiry( dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) {
- /*
- * Success
- */
- retval = 0;
- goto completed;
- }
- }
- }
-
- for (ind = 4; ind <= page0[3] + 3; ind++) {
- if (page0[ind] == PAGE_80) {
- if (!do_scsi_page80_inquiry( dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len)) {
- /*
- * Success
- */
- retval = 0;
- goto completed;
- }
- }
- }
- retval = 1;
+ }
+
+ for (ind = 4; ind <= page0[3] + 3; ind++)
+ {
+ if (page0[ind] == PAGE_83)
+ {
+ if (!do_scsi_page83_inquiry
+ (dev_scsi, fd, dev_scsi->serial,
+ dev_scsi->serial_short, len,
+ dev_scsi->unit_serial_number, dev_scsi->wwn,
+ dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group))
+ {
+ /*
+ * Success
+ */
+ retval = 0;
+ goto completed;
+ }
+ }
+ }
+
+ for (ind = 4; ind <= page0[3] + 3; ind++)
+ {
+ if (page0[ind] == PAGE_80)
+ {
+ if (!do_scsi_page80_inquiry
+ (dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len))
+ {
+ /*
+ * Success
+ */
+ retval = 0;
+ goto completed;
+ }
+ }
+ }
+ retval = 1;
completed:
- close(fd);
- return retval;
+ close (fd);
+ return retval;
}
-
-
-static void set_type(const char *from, char *to, size_t len)
+static void
+set_type (const char *from, char *to, size_t len)
{
- int type_num;
- char *eptr;
- const char *type = "generic";
-
- type_num = strtoul(from, &eptr, 0);
- if (eptr != from) {
- switch (type_num) {
- case 0:
- type = "disk";
- break;
- case 1:
- type = "tape";
- break;
- case 4:
- type = "optical";
- break;
- case 5:
- type = "cd";
- break;
- case 7:
- type = "optical";
- break;
- case 0xe:
- type = "disk";
- break;
- case 0xf:
- type = "optical";
- break;
- default:
- break;
- }
- }
- strscpy(to, len, type);
+ int type_num;
+ char *eptr;
+ const char *type = "generic";
+
+ type_num = strtoul (from, &eptr, 0);
+ if (eptr != from)
+ {
+ switch (type_num)
+ {
+ case 0:
+ type = "disk";
+ break;
+ case 1:
+ type = "tape";
+ break;
+ case 4:
+ type = "optical";
+ break;
+ case 5:
+ type = "cd";
+ break;
+ case 7:
+ type = "optical";
+ break;
+ case 0xe:
+ type = "disk";
+ break;
+ case 0xf:
+ type = "optical";
+ break;
+ default:
+ break;
+ }
+ }
+ strscpy (to, len, type);
}
/*
@@ -1179,45 +1405,56 @@ static void set_type(const char *from, char *to, size_t len)
* Return a pointer to the NUL terminated string, returns NULL if no
* matches.
*/
-static char *get_value(char **buffer) {
-
- static const char *quote_string = "\"\n";
- static const char *comma_string = ",\n";
- char *val;
- const char *end;
-
- if (**buffer == '"') {
+static char *
+get_value (char **buffer)
+{
+
+ static const char *quote_string = "\"\n";
+ static const char *comma_string = ",\n";
+ char *val;
+ const char *end;
+
+ if (**buffer == '"')
+ {
/*
- * skip leading quote, terminate when quote seen
- */
+ * skip leading quote, terminate when quote seen
+ */
(*buffer)++;
end = quote_string;
- } else {
+ }
+ else
+ {
end = comma_string;
- }
- val = strsep(buffer, end);
- if (val && end == quote_string) {
+ }
+ val = strsep (buffer, end);
+ if (val && end == quote_string)
+ {
/*
- * skip trailing quote
- */
+ * skip trailing quote
+ */
(*buffer)++;
- }
-
- while (isspace(**buffer)) {
+ }
+
+ while (isspace (**buffer))
+ {
(*buffer)++;
- }
- return val;
+ }
+ return val;
}
-static int argc_count(char *opts) {
+static int
+argc_count (char *opts)
+{
- int i = 0;
- while (*opts != '\0') {
- if (*opts++ == ' ') {
- i++;
- }
- }
- return i;
+ int i = 0;
+ while (*opts != '\0')
+ {
+ if (*opts++ == ' ')
+ {
+ i++;
+ }
+ }
+ return i;
}
/*
@@ -1229,472 +1466,562 @@ static int argc_count(char *opts) {
*
* vendor and model can end in '\n'.
*/
-static int get_file_options(const char *vendor, const char *model, int *argc, char ***newargv) {
-
- char *buffer;
- FILE *f = NULL;
- char *buf;
- char *str1;
- char *vendor_in, *model_in, *options_in; /* read in from file */
- int lineno;
- int c;
- int retval = 0;
- int rc = 0;
-
- f = fopen(config_file, "re");
- if (f == NULL) {
- if (errno == ENOENT) {
- return 1;
- }
- else {
-
- rc = -errno;
- log_error( "can't open %s: errno = %d", config_file, rc);
- return -1;
- }
- }
+static int
+get_file_options (const char *vendor, const char *model, int *argc,
+ char ***newargv)
+{
- /*
+ char *buffer;
+ FILE *f = NULL;
+ char *buf;
+ char *str1;
+ char *vendor_in, *model_in, *options_in; /* read in from file */
+ int lineno;
+ int c;
+ int retval = 0;
+ int rc = 0;
+
+ f = fopen (config_file, "re");
+ if (f == NULL)
+ {
+ if (errno == ENOENT)
+ {
+ return 1;
+ }
+ else
+ {
+
+ rc = -errno;
+ log_error ("can't open %s: errno = %d", config_file, rc);
+ return -1;
+ }
+ }
+
+ /*
* Allocate a buffer rather than put it on the stack so we can
* keep it around to parse any options (any allocated newargv
* points into this buffer for its strings).
*/
- buffer = (char*)malloc(MAX_BUFFER_LEN);
- if (!buffer) {
-
- fclose(f);
+ buffer = (char *) malloc (MAX_BUFFER_LEN);
+ if (!buffer)
+ {
+
+ fclose (f);
return -ENOMEM;
- }
+ }
- *newargv = NULL;
- lineno = 0;
- while (1) {
+ *newargv = NULL;
+ lineno = 0;
+ while (1)
+ {
vendor_in = model_in = options_in = NULL;
- buf = fgets(buffer, MAX_BUFFER_LEN, f);
-
- if (buf == NULL) {
- break;
- }
-
+ buf = fgets (buffer, MAX_BUFFER_LEN, f);
+
+ if (buf == NULL)
+ {
+ break;
+ }
+
lineno++;
- if (buf[strlen(buffer) - 1] != '\n') {
- log_error("Config file line %d too long", lineno);
- break;
- }
+ if (buf[strlen (buffer) - 1] != '\n')
+ {
+ log_error ("Config file line %d too long", lineno);
+ break;
+ }
- while (isspace(*buf)) {
- buf++;
- }
+ while (isspace (*buf))
+ {
+ buf++;
+ }
/* blank or all whitespace line */
- if (*buf == '\0') {
- continue;
- }
+ if (*buf == '\0')
+ {
+ continue;
+ }
/* comment line */
- if (*buf == '#') {
- continue;
- }
- str1 = strsep(&buf, "=");
- if (str1 && strcaseeq(str1, "VENDOR")) {
- str1 = get_value(&buf);
- if (!str1) {
- retval = -ENOMEM;
- break;
- }
- vendor_in = str1;
-
- str1 = strsep(&buf, "=");
- if (str1 && strcaseeq(str1, "MODEL")) {
- str1 = get_value(&buf);
- if (!str1) {
- retval = -ENOMEM;
- break;
- }
- model_in = str1;
- str1 = strsep(&buf, "=");
- }
- }
-
- if (str1 && strcaseeq(str1, "OPTIONS")) {
- str1 = get_value(&buf);
- if (!str1) {
- retval = -ENOMEM;
- break;
- }
- options_in = str1;
- }
+ if (*buf == '#')
+ {
+ continue;
+ }
+ str1 = strsep (&buf, "=");
+ if (str1 && strcaseeq (str1, "VENDOR"))
+ {
+ str1 = get_value (&buf);
+ if (!str1)
+ {
+ retval = -ENOMEM;
+ break;
+ }
+ vendor_in = str1;
+
+ str1 = strsep (&buf, "=");
+ if (str1 && strcaseeq (str1, "MODEL"))
+ {
+ str1 = get_value (&buf);
+ if (!str1)
+ {
+ retval = -ENOMEM;
+ break;
+ }
+ model_in = str1;
+ str1 = strsep (&buf, "=");
+ }
+ }
+
+ if (str1 && strcaseeq (str1, "OPTIONS"))
+ {
+ str1 = get_value (&buf);
+ if (!str1)
+ {
+ retval = -ENOMEM;
+ break;
+ }
+ options_in = str1;
+ }
/*
- * Only allow: [vendor=foo[,model=bar]]options=stuff
- */
- if (!options_in || (!vendor_in && model_in)) {
- log_error("Error parsing config file line %d '%s'", lineno, buffer);
- retval = -1;
- break;
- }
- if (vendor == NULL) {
- if (vendor_in == NULL) {
- break;
- }
- }
- else if (vendor_in && strneq(vendor, vendor_in, strlen(vendor_in)) && (!model_in || (strneq(model, model_in, strlen(model_in))))) {
- /*
- * Matched vendor and optionally model.
- *
- * Note: a short vendor_in or model_in can
- * give a partial match (that is FOO
- * matches FOOBAR).
- */
- break;
- }
- }
-
- fclose( f );
-
- if (retval == 0) {
- if (vendor_in != NULL || model_in != NULL || options_in != NULL) {
- /*
- * Something matched. Allocate newargv, and store
- * values found in options_in.
- */
- strcpy(buffer, options_in);
- c = argc_count(buffer) + 2;
- *newargv = calloc(c, sizeof(**newargv));
- if (!*newargv) {
-
- retval = -ENOMEM;
- }
- else {
- *argc = c;
- c = 0;
- /*
- * argv[0] at 0 is skipped by getopt, but
- * store the buffer address there for
- * later freeing
- */
- (*newargv)[c] = buffer;
- for (c = 1; c < *argc; c++) {
- (*newargv)[c] = strsep(&buffer, " \t");
- }
- }
- } else {
- /* No matches */
- retval = 1;
- }
- }
- if (retval != 0) {
- free(buffer);
- }
-
- return retval;
+ * Only allow: [vendor=foo[,model=bar]]options=stuff
+ */
+ if (!options_in || (!vendor_in && model_in))
+ {
+ log_error ("Error parsing config file line %d '%s'",
+ lineno, buffer);
+ retval = -1;
+ break;
+ }
+ if (vendor == NULL)
+ {
+ if (vendor_in == NULL)
+ {
+ break;
+ }
+ }
+ else if (vendor_in
+ && strneq (vendor, vendor_in, strlen (vendor_in))
+ && (!model_in
+ || (strneq (model, model_in, strlen (model_in)))))
+ {
+ /*
+ * Matched vendor and optionally model.
+ *
+ * Note: a short vendor_in or model_in can
+ * give a partial match (that is FOO
+ * matches FOOBAR).
+ */
+ break;
+ }
+ }
+
+ fclose (f);
+
+ if (retval == 0)
+ {
+ if (vendor_in != NULL || model_in != NULL || options_in != NULL)
+ {
+ /*
+ * Something matched. Allocate newargv, and store
+ * values found in options_in.
+ */
+ strcpy (buffer, options_in);
+ c = argc_count (buffer) + 2;
+ *newargv = calloc (c, sizeof (**newargv));
+ if (!*newargv)
+ {
+
+ retval = -ENOMEM;
+ }
+ else
+ {
+ *argc = c;
+ c = 0;
+ /*
+ * argv[0] at 0 is skipped by getopt, but
+ * store the buffer address there for
+ * later freeing
+ */
+ (*newargv)[c] = buffer;
+ for (c = 1; c < *argc; c++)
+ {
+ (*newargv)[c] = strsep (&buffer, " \t");
+ }
+ }
+ }
+ else
+ {
+ /* No matches */
+ retval = 1;
+ }
+ }
+ if (retval != 0)
+ {
+ free (buffer);
+ }
+
+ return retval;
}
-static void help( char const* progname ) {
- printf("Usage: %s [OPTION...] /path/to/device/file\n\n"
- "SCSI device identification.\n\n"
- " -h --help Print this message\n"
- " --version Print version of the program\n\n"
- " -d --device= Device node for SG_IO commands\n"
- " -f --config= Location of config file\n"
- " -p --page=0x80|0x83|pre-spc3-83 SCSI page (0x80, 0x83, pre-spc3-83)\n"
- " -s --sg-version=3|4 Use SGv3 or SGv4\n"
- " -u --replace-whitespace Replace all whitespace by underscores\n"
- " -v --verbose Verbose logging\n"
- , progname);
+static void
+help (char const *progname)
+{
+ printf ("Usage: %s [OPTION...] /path/to/device/file\n\n"
+ "SCSI device identification.\n\n"
+ " -h --help Print this message\n"
+ " --version Print version of the program\n\n"
+ " -d --device= Device node for SG_IO commands\n"
+ " -f --config= Location of config file\n"
+ " -p --page=0x80|0x83|pre-spc3-83 SCSI page (0x80, 0x83, pre-spc3-83)\n"
+ " -s --sg-version=3|4 Use SGv3 or SGv4\n"
+ " -u --replace-whitespace Replace all whitespace by underscores\n"
+ " -v --verbose Verbose logging\n", progname);
}
-static int set_options( int argc, char **argv, char *maj_min_dev) {
+static int
+set_options (int argc, char **argv, char *maj_min_dev)
+{
- int option;
+ int option;
- /*
+ /*
* optind is a global extern used by getopt. Since we can call
* set_options twice (once for command line, and once for config
* file) we have to reset this back to 1.
*/
- optind = 1;
- while ((option = getopt_long(argc, argv, "d:f:gp:uvVh", options, NULL)) >= 0)
- switch (option) {
+ optind = 1;
+ while ((option =
+ getopt_long (argc, argv, "d:f:gp:uvVh", options, NULL)) >= 0)
+ switch (option)
+ {
case 'd':
- dev_specified = true;
- strscpy(maj_min_dev, MAX_PATH_LEN, optarg);
- break;
+ dev_specified = true;
+ strscpy (maj_min_dev, MAX_PATH_LEN, optarg);
+ break;
case 'f':
- strscpy(config_file, MAX_PATH_LEN, optarg);
- break;
+ strscpy (config_file, MAX_PATH_LEN, optarg);
+ break;
case 'h':
- help( argv[0] );
- exit(0);
+ help (argv[0]);
+ exit (0);
case 'p':
- if (streq(optarg, "0x80"))
- default_page_code = PAGE_80;
- else if (streq(optarg, "0x83"))
- default_page_code = PAGE_83;
- else if (streq(optarg, "pre-spc3-83"))
- default_page_code = PAGE_83_PRE_SPC3;
- else {
- fprintf(stderr, "[ERROR] %s: Unknown page code '%s'\n", argv[0], optarg);
- return -1;
- }
- break;
+ if (streq (optarg, "0x80"))
+ default_page_code = PAGE_80;
+ else if (streq (optarg, "0x83"))
+ default_page_code = PAGE_83;
+ else if (streq (optarg, "pre-spc3-83"))
+ default_page_code = PAGE_83_PRE_SPC3;
+ else
+ {
+ fprintf (stderr,
+ "[ERROR] %s: Unknown page code '%s'\n", argv[0], optarg);
+ return -1;
+ }
+ break;
case 's':
- sg_version = atoi(optarg);
- if (sg_version < 3 || sg_version > 4) {
- fprintf(stderr, "[ERROR] %s: Unknown SG version '%s'\n", argv[0], optarg);
- return -1;
- }
- break;
+ sg_version = atoi (optarg);
+ if (sg_version < 3 || sg_version > 4)
+ {
+ fprintf (stderr,
+ "[ERROR] %s: Unknown SG version '%s'\n",
+ argv[0], optarg);
+ return -1;
+ }
+ break;
case 'u':
- reformat_serial = true;
- break;
+ reformat_serial = true;
+ break;
case 'v':
- break;
+ break;
case 'V':
- printf("%s\n", "1.0");
- exit(0);
+ printf ("%s\n", "1.0");
+ exit (0);
case '?':
- return -1;
+ return -1;
default:
- fprintf(stderr, "[ERROR] %s: Unknown option -%c\n", argv[0], option);
- return -1;
- }
+ fprintf (stderr, "[ERROR] %s: Unknown option -%c\n", argv[0], option);
+ return -1;
+ }
- if (optind < argc && !dev_specified) {
+ if (optind < argc && !dev_specified)
+ {
dev_specified = true;
- strscpy(maj_min_dev, MAX_PATH_LEN, argv[optind]);
- }
+ strscpy (maj_min_dev, MAX_PATH_LEN, argv[optind]);
+ }
- return 0;
+ return 0;
}
-static int per_dev_options(struct scsi_id_device *dev_scsi, int *good_bad, int *page_code) {
+static int
+per_dev_options (struct scsi_id_device *dev_scsi, int *good_bad,
+ int *page_code)
+{
- int retval;
- int newargc;
- char **newargv = NULL;
- int option;
+ int retval;
+ int newargc;
+ char **newargv = NULL;
+ int option;
- *good_bad = all_good;
- *page_code = default_page_code;
+ *good_bad = all_good;
+ *page_code = default_page_code;
- retval = get_file_options( vendor_str, model_str, &newargc, &newargv);
+ retval = get_file_options (vendor_str, model_str, &newargc, &newargv);
- optind = 1; /* reset this global extern */
- while (retval == 0) {
- option = getopt_long(newargc, newargv, "p:", options, NULL);
+ optind = 1; /* reset this global extern */
+ while (retval == 0)
+ {
+ option = getopt_long (newargc, newargv, "p:", options, NULL);
if (option == -1)
- break;
-
- switch (option) {
-
- case 'p':
- if (streq(optarg, "0x80")) {
- *page_code = PAGE_80;
- } else if (streq(optarg, "0x83")) {
- *page_code = PAGE_83;
- } else if (streq(optarg, "pre-spc3-83")) {
- *page_code = PAGE_83_PRE_SPC3;
- } else {
- log_error("Unknown page code '%s'", optarg);
- retval = -1;
- }
- break;
-
- default:
- log_error("Unknown or bad option '%c' (0x%x)", option, option);
- retval = -1;
- break;
- }
- }
-
- if (newargv) {
- free(newargv[0]);
- free(newargv);
- }
- return retval;
+ break;
+
+ switch (option)
+ {
+
+ case 'p':
+ if (streq (optarg, "0x80"))
+ {
+ *page_code = PAGE_80;
+ }
+ else if (streq (optarg, "0x83"))
+ {
+ *page_code = PAGE_83;
+ }
+ else if (streq (optarg, "pre-spc3-83"))
+ {
+ *page_code = PAGE_83_PRE_SPC3;
+ }
+ else
+ {
+ log_error ("Unknown page code '%s'", optarg);
+ retval = -1;
+ }
+ break;
+
+ default:
+ log_error ("Unknown or bad option '%c' (0x%x)", option, option);
+ retval = -1;
+ break;
+ }
+ }
+
+ if (newargv)
+ {
+ free (newargv[0]);
+ free (newargv);
+ }
+ return retval;
}
+static int
+set_inq_values (struct scsi_id_device *dev_scsi, const char *path)
+{
+
+ int retval;
-static int set_inq_values( struct scsi_id_device *dev_scsi, const char *path) {
-
- int retval;
+ dev_scsi->use_sg = sg_version;
- dev_scsi->use_sg = sg_version;
+ retval = scsi_std_inquiry (dev_scsi, path);
+ if (retval)
+ {
- retval = scsi_std_inquiry(dev_scsi, path);
- if (retval) {
-
- log_error("scsi_std_inquiry('%s') rc = %d\n", path, retval);
+ log_error ("scsi_std_inquiry('%s') rc = %d\n", path, retval);
return retval;
- }
-
- vdev_util_encode_string(dev_scsi->vendor, vendor_enc_str, sizeof(vendor_enc_str));
- vdev_util_encode_string(dev_scsi->model, model_enc_str, sizeof(model_enc_str));
-
- vdev_util_replace_whitespace(dev_scsi->vendor, vendor_str, sizeof(vendor_str));
- vdev_util_replace_chars(vendor_str, NULL);
- vdev_util_replace_whitespace(dev_scsi->model, model_str, sizeof(model_str));
- vdev_util_replace_chars(model_str, NULL);
- set_type(dev_scsi->type, type_str, sizeof(type_str));
- vdev_util_replace_whitespace(dev_scsi->revision, revision_str, sizeof(revision_str));
- vdev_util_replace_chars(revision_str, NULL);
- return 0;
+ }
+
+ vdev_util_encode_string (dev_scsi->vendor, vendor_enc_str,
+ sizeof (vendor_enc_str));
+ vdev_util_encode_string (dev_scsi->model, model_enc_str,
+ sizeof (model_enc_str));
+
+ vdev_util_replace_whitespace (dev_scsi->vendor, vendor_str,
+ sizeof (vendor_str));
+ vdev_util_replace_chars (vendor_str, NULL);
+ vdev_util_replace_whitespace (dev_scsi->model, model_str,
+ sizeof (model_str));
+ vdev_util_replace_chars (model_str, NULL);
+ set_type (dev_scsi->type, type_str, sizeof (type_str));
+ vdev_util_replace_whitespace (dev_scsi->revision, revision_str,
+ sizeof (revision_str));
+ vdev_util_replace_chars (revision_str, NULL);
+ return 0;
}
/*
* scsi_id: try to get an id, if one is found, printf it to stdout.
* returns a value passed to exit() - 0 if printed an id, else 1.
*/
-static int scsi_id( char *maj_min_dev) {
+static int
+scsi_id (char *maj_min_dev)
+{
- struct scsi_id_device dev_scsi = {};
- int good_dev = 1;
- int page_code = 0;
- int retval = 0;
+ struct scsi_id_device dev_scsi = { };
+ int good_dev = 1;
+ int page_code = 0;
+ int retval = 0;
- if (set_inq_values( &dev_scsi, maj_min_dev) < 0) {
+ if (set_inq_values (&dev_scsi, maj_min_dev) < 0)
+ {
retval = 1;
return retval;
- }
+ }
- /* get per device (vendor + model) options from the config file */
- per_dev_options( &dev_scsi, &good_dev, &page_code);
- if (!good_dev) {
-
- log_error("per_dev_options: good_dev = %d", good_dev );
+ /* get per device (vendor + model) options from the config file */
+ per_dev_options (&dev_scsi, &good_dev, &page_code);
+ if (!good_dev)
+ {
+
+ log_error ("per_dev_options: good_dev = %d", good_dev);
retval = 1;
return retval;
- }
-
- /* read serial number from mode pages (no values for optical drives) */
- scsi_get_serial( &dev_scsi, maj_min_dev, page_code, MAX_SERIAL_LEN);
-
- char serial_str[MAX_SERIAL_LEN];
-
- vdev_property_add("VDEV_SCSI", "1" );
- vdev_property_add("VDEV_SCSI_VENDOR", vendor_str );
- vdev_property_add("VDEV_SCSI_VENDOR_ENC", vendor_enc_str );
- vdev_property_add("VDEV_SCSI_MODEL", model_str );
- vdev_property_add("VDEV_SCSI_MODEL_ENC", model_enc_str );
- vdev_property_add("VDEV_SCSI_REVISION", revision_str );
- vdev_property_add("VDEV_SCSI_TYPE", type_str );
-
- if (dev_scsi.serial[0] != '\0') {
-
- vdev_util_replace_whitespace(dev_scsi.serial, serial_str, sizeof(serial_str));
- vdev_util_replace_chars(serial_str, NULL);
-
- vdev_property_add("VDEV_SCSI_SERIAL", serial_str );
-
- vdev_util_replace_whitespace(dev_scsi.serial_short, serial_str, sizeof(serial_str));
- vdev_util_replace_chars(serial_str, NULL);
-
- vdev_property_add("VDEV_SCSI_SERIAL_SHORT", serial_str );
- }
- if (dev_scsi.wwn[0] != '\0') {
-
+ }
+
+ /* read serial number from mode pages (no values for optical drives) */
+ scsi_get_serial (&dev_scsi, maj_min_dev, page_code, MAX_SERIAL_LEN);
+
+ char serial_str[MAX_SERIAL_LEN];
+
+ vdev_property_add ("VDEV_SCSI", "1");
+ vdev_property_add ("VDEV_SCSI_VENDOR", vendor_str);
+ vdev_property_add ("VDEV_SCSI_VENDOR_ENC", vendor_enc_str);
+ vdev_property_add ("VDEV_SCSI_MODEL", model_str);
+ vdev_property_add ("VDEV_SCSI_MODEL_ENC", model_enc_str);
+ vdev_property_add ("VDEV_SCSI_REVISION", revision_str);
+ vdev_property_add ("VDEV_SCSI_TYPE", type_str);
+
+ if (dev_scsi.serial[0] != '\0')
+ {
+
+ vdev_util_replace_whitespace (dev_scsi.serial, serial_str,
+ sizeof (serial_str));
+ vdev_util_replace_chars (serial_str, NULL);
+
+ vdev_property_add ("VDEV_SCSI_SERIAL", serial_str);
+
+ vdev_util_replace_whitespace (dev_scsi.serial_short, serial_str,
+ sizeof (serial_str));
+ vdev_util_replace_chars (serial_str, NULL);
+
+ vdev_property_add ("VDEV_SCSI_SERIAL_SHORT", serial_str);
+ }
+ if (dev_scsi.wwn[0] != '\0')
+ {
+
char wwn_buf[100];
char wwn_vendor_buf[100];
-
- memset( wwn_buf, 0, 100 );
- memset( wwn_vendor_buf, 0, 100 );
-
- vdev_property_add("VDEV_SCSI_WWN", dev_scsi.wwn );
-
- if (dev_scsi.wwn_vendor_extension[0] != '\0') {
-
- snprintf( wwn_buf, 99, "0x%s%s", dev_scsi.wwn, dev_scsi.wwn_vendor_extension );
- snprintf( wwn_vendor_buf, 99, "0x%s", dev_scsi.wwn_vendor_extension );
-
- vdev_property_add("VDEV_SCSI_WWN_VENDOR_EXTENSION", wwn_vendor_buf );
- vdev_property_add("VDEV_SCSI_WWN_WITH_EXTENSION", wwn_buf );
- }
-
- else {
-
- snprintf( wwn_buf, 99, "0x%s", dev_scsi.wwn );
-
- vdev_property_add("VDEV_SCSI_WWN_WITH_EXTENSION", wwn_buf );
- }
- }
- if (dev_scsi.tgpt_group[0] != '\0') {
-
- vdev_property_add("VDEV_SCSI_TARGET_PORT", dev_scsi.tgpt_group );
- }
- if (dev_scsi.unit_serial_number[0] != '\0') {
-
- vdev_property_add("VDEV_SCSI_UNIT_SERIAL", dev_scsi.unit_serial_number );
- }
-
- return retval;
-}
+ memset (wwn_buf, 0, 100);
+ memset (wwn_vendor_buf, 0, 100);
+
+ vdev_property_add ("VDEV_SCSI_WWN", dev_scsi.wwn);
+
+ if (dev_scsi.wwn_vendor_extension[0] != '\0')
+ {
+
+ snprintf (wwn_buf, 99, "0x%s%s", dev_scsi.wwn,
+ dev_scsi.wwn_vendor_extension);
+ snprintf (wwn_vendor_buf, 99, "0x%s",
+ dev_scsi.wwn_vendor_extension);
+
+ vdev_property_add ("VDEV_SCSI_WWN_VENDOR_EXTENSION",
+ wwn_vendor_buf);
+ vdev_property_add ("VDEV_SCSI_WWN_WITH_EXTENSION", wwn_buf);
+ }
+
+ else
+ {
+
+ snprintf (wwn_buf, 99, "0x%s", dev_scsi.wwn);
+
+ vdev_property_add ("VDEV_SCSI_WWN_WITH_EXTENSION", wwn_buf);
+ }
+ }
+ if (dev_scsi.tgpt_group[0] != '\0')
+ {
+
+ vdev_property_add ("VDEV_SCSI_TARGET_PORT", dev_scsi.tgpt_group);
+ }
+ if (dev_scsi.unit_serial_number[0] != '\0')
+ {
+
+ vdev_property_add ("VDEV_SCSI_UNIT_SERIAL",
+ dev_scsi.unit_serial_number);
+ }
+
+ return retval;
+}
// entry point
-int main(int argc, char **argv) {
-
- int retval = 0;
- char maj_min_dev[MAX_PATH_LEN];
- int newargc;
- char **newargv = NULL;
-
- /*
+int
+main (int argc, char **argv)
+{
+
+ int retval = 0;
+ char maj_min_dev[MAX_PATH_LEN];
+ int newargc;
+ char **newargv = NULL;
+
+ /*
* Get config file options.
*/
- retval = get_file_options( NULL, NULL, &newargc, &newargv);
- if (retval < 0) {
+ retval = get_file_options (NULL, NULL, &newargc, &newargv);
+ if (retval < 0)
+ {
retval = 1;
goto exit;
- }
- if (retval == 0) {
-
- if( newargv == NULL ) {
- retval = 4;
- goto exit;
- }
-
- if (set_options( newargc, newargv, maj_min_dev) < 0) {
- retval = 2;
- goto exit;
- }
- }
-
- /*
+ }
+ if (retval == 0)
+ {
+
+ if (newargv == NULL)
+ {
+ retval = 4;
+ goto exit;
+ }
+
+ if (set_options (newargc, newargv, maj_min_dev) < 0)
+ {
+ retval = 2;
+ goto exit;
+ }
+ }
+
+ /*
* Get command line options (overriding any config file settings).
*/
- if (set_options( argc, argv, maj_min_dev) < 0) {
- exit(1);
- }
-
- if (!dev_specified) {
- log_error("%s", "No device specified.");
+ if (set_options (argc, argv, maj_min_dev) < 0)
+ {
+ exit (1);
+ }
+
+ if (!dev_specified)
+ {
+ log_error ("%s", "No device specified.");
retval = 1;
goto exit;
- }
+ }
- retval = scsi_id( maj_min_dev);
+ retval = scsi_id (maj_min_dev);
exit:
- if (newargv) {
- free(newargv[0]);
- free(newargv);
- }
-
- vdev_property_print();
- vdev_property_free_all();
-
- return retval;
+ if (newargv)
+ {
+ free (newargv[0]);
+ free (newargv);
+ }
+
+ vdev_property_print ();
+ vdev_property_free_all ();
+
+ return retval;
}
diff --git a/vdevd/helpers/LINUX/stat_usb.c b/vdevd/helpers/LINUX/stat_usb.c
index cc433a0..9eaaa83 100644
--- a/vdevd/helpers/LINUX/stat_usb.c
+++ b/vdevd/helpers/LINUX/stat_usb.c
@@ -47,250 +47,280 @@
#define USB_DT_DEVICE 0x01
#define USB_DT_INTERFACE 0x04
+static void
+set_usb_iftype (char *to, int if_class_num, size_t len)
+{
+ const char *type = "generic";
-static void set_usb_iftype(char *to, int if_class_num, size_t len) {
- const char *type = "generic";
-
- switch (if_class_num) {
- case 1:
- type = "audio";
- break;
- case 2: /* CDC-Control */
- break;
- case 3:
- type = "hid";
- break;
- case 5: /* Physical */
- break;
- case 6:
- type = "media";
- break;
- case 7:
- type = "printer";
- break;
- case 8:
- type = "storage";
- break;
- case 9:
- type = "hub";
- break;
- case 0x0a: /* CDC-Data */
- break;
- case 0x0b: /* Chip/Smart Card */
- break;
- case 0x0d: /* Content Security */
- break;
- case 0x0e:
- type = "video";
- break;
- case 0xdc: /* Diagnostic Device */
- break;
- case 0xe0: /* Wireless Controller */
- break;
- case 0xfe: /* Application-specific */
- break;
- case 0xff: /* Vendor-specific */
- break;
- default:
- break;
- }
-
- strncpy(to, type, len);
- to[len-1] = '\0';
+ switch (if_class_num)
+ {
+ case 1:
+ type = "audio";
+ break;
+ case 2: /* CDC-Control */
+ break;
+ case 3:
+ type = "hid";
+ break;
+ case 5: /* Physical */
+ break;
+ case 6:
+ type = "media";
+ break;
+ case 7:
+ type = "printer";
+ break;
+ case 8:
+ type = "storage";
+ break;
+ case 9:
+ type = "hub";
+ break;
+ case 0x0a: /* CDC-Data */
+ break;
+ case 0x0b: /* Chip/Smart Card */
+ break;
+ case 0x0d: /* Content Security */
+ break;
+ case 0x0e:
+ type = "video";
+ break;
+ case 0xdc: /* Diagnostic Device */
+ break;
+ case 0xe0: /* Wireless Controller */
+ break;
+ case 0xfe: /* Application-specific */
+ break;
+ case 0xff: /* Vendor-specific */
+ break;
+ default:
+ break;
+ }
+
+ strncpy (to, type, len);
+ to[len - 1] = '\0';
}
-static int set_usb_mass_storage_ifsubtype(char *to, const char *from, size_t len) {
-
- int type_num = 0;
- char *eptr;
- const char *type = "generic";
-
- type_num = strtoul(from, &eptr, 0);
- if (eptr != from) {
- switch (type_num) {
- case 1: /* RBC devices */
- type = "rbc";
- break;
- case 2:
- type = "atapi";
- break;
- case 3:
- type = "tape";
- break;
- case 4: /* UFI */
- type = "floppy";
- break;
- case 6: /* Transparent SPC-2 devices */
- type = "scsi";
- break;
- default:
- break;
- }
- }
-
- strncpy( to, type, (strlen(type) < len ? strlen(type) : len) );
-
- return type_num;
+static int
+set_usb_mass_storage_ifsubtype (char *to, const char *from, size_t len)
+{
+
+ int type_num = 0;
+ char *eptr;
+ const char *type = "generic";
+
+ type_num = strtoul (from, &eptr, 0);
+ if (eptr != from)
+ {
+ switch (type_num)
+ {
+ case 1: /* RBC devices */
+ type = "rbc";
+ break;
+ case 2:
+ type = "atapi";
+ break;
+ case 3:
+ type = "tape";
+ break;
+ case 4: /* UFI */
+ type = "floppy";
+ break;
+ case 6: /* Transparent SPC-2 devices */
+ type = "scsi";
+ break;
+ default:
+ break;
+ }
+ }
+
+ strncpy (to, type, (strlen (type) < len ? strlen (type) : len));
+
+ return type_num;
}
-static void set_scsi_type(char *to, const char *from, size_t len) {
-
- int type_num;
- char *eptr;
- const char *type = "generic";
-
- type_num = strtoul(from, &eptr, 0);
- if (eptr != from) {
- switch (type_num) {
- case 0:
- case 0xe:
- type = "disk";
- break;
- case 1:
- type = "tape";
- break;
- case 4:
- case 7:
- case 0xf:
- type = "optical";
- break;
- case 5:
- type = "cd";
- break;
- default:
- break;
- }
- }
-
- strncpy( to, type, (strlen(type) < len ? strlen(type) : len) );
+static void
+set_scsi_type (char *to, const char *from, size_t len)
+{
+
+ int type_num;
+ char *eptr;
+ const char *type = "generic";
+
+ type_num = strtoul (from, &eptr, 0);
+ if (eptr != from)
+ {
+ switch (type_num)
+ {
+ case 0:
+ case 0xe:
+ type = "disk";
+ break;
+ case 1:
+ type = "tape";
+ break;
+ case 4:
+ case 7:
+ case 0xf:
+ type = "optical";
+ break;
+ case 5:
+ type = "cd";
+ break;
+ default:
+ break;
+ }
+ }
+
+ strncpy (to, type, (strlen (type) < len ? strlen (type) : len));
}
// read packed descriptors information from sysfs
-static int dev_if_packed_info( char const* sysfs_path, char *ifs_str, size_t len) {
-
- char sysfs_descriptors[4096];
- int fd = -1;
- ssize_t size;
- unsigned char buf[18 + 65535];
- int pos = 0;
- unsigned strpos = 0;
- int rc = 0;
- struct usb_interface_descriptor {
- u_int8_t bLength;
- u_int8_t bDescriptorType;
- u_int8_t bInterfaceNumber;
- u_int8_t bAlternateSetting;
- u_int8_t bNumEndpoints;
- u_int8_t bInterfaceClass;
- u_int8_t bInterfaceSubClass;
- u_int8_t bInterfaceProtocol;
- u_int8_t iInterface;
- } __attribute__((packed));
-
- memset( sysfs_descriptors, 0, 4096 );
- snprintf( sysfs_descriptors, 4095, "%s/descriptors", sysfs_path );
-
- fd = open(sysfs_descriptors, O_RDONLY|O_CLOEXEC);
- if (fd < 0) {
-
+static int
+dev_if_packed_info (char const *sysfs_path, char *ifs_str, size_t len)
+{
+
+ char sysfs_descriptors[4096];
+ int fd = -1;
+ ssize_t size;
+ unsigned char buf[18 + 65535];
+ int pos = 0;
+ unsigned strpos = 0;
+ int rc = 0;
+ struct usb_interface_descriptor
+ {
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+ u_int8_t bInterfaceNumber;
+ u_int8_t bAlternateSetting;
+ u_int8_t bNumEndpoints;
+ u_int8_t bInterfaceClass;
+ u_int8_t bInterfaceSubClass;
+ u_int8_t bInterfaceProtocol;
+ u_int8_t iInterface;
+ } __attribute__ ((packed));
+
+ memset (sysfs_descriptors, 0, 4096);
+ snprintf (sysfs_descriptors, 4095, "%s/descriptors", sysfs_path);
+
+ fd = open (sysfs_descriptors, O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
+ {
+
rc = -errno;
- log_debug("open('%s') errno = %d\n", sysfs_descriptors, rc );
-
+ log_debug ("open('%s') errno = %d\n", sysfs_descriptors, rc);
+
return rc;
- }
+ }
+
+ size = read (fd, buf, sizeof (buf));
+ if (size < 18 || size == sizeof (buf))
+ {
- size = read(fd, buf, sizeof(buf));
- if (size < 18 || size == sizeof(buf)) {
-
rc = -errno;
-
- close( fd );
- log_debug("read('%s') rc = %zd, errno = %d\n", sysfs_path, size, rc );
+
+ close (fd);
+ log_debug ("read('%s') rc = %zd, errno = %d\n", sysfs_path, size, rc);
return -EIO;
- }
+ }
+
+ close (fd);
+
+ ifs_str[0] = '\0';
+ while (pos < size && strpos + 7 < len - 2)
+ {
- close( fd );
-
- ifs_str[0] = '\0';
- while (pos < size && strpos+7 < len-2) {
-
struct usb_interface_descriptor *desc;
char if_str[8];
desc = (struct usb_interface_descriptor *) &buf[pos];
- if (desc->bLength < 3) {
- break;
- }
-
+ if (desc->bLength < 3)
+ {
+ break;
+ }
+
pos += desc->bLength;
- if (desc->bDescriptorType != USB_DT_INTERFACE) {
- continue;
- }
+ if (desc->bDescriptorType != USB_DT_INTERFACE)
+ {
+ continue;
+ }
- if (snprintf(if_str, 8, ":%02x%02x%02x", desc->bInterfaceClass, desc->bInterfaceSubClass, desc->bInterfaceProtocol) != 7) {
- continue;
- }
+ if (snprintf
+ (if_str, 8, ":%02x%02x%02x", desc->bInterfaceClass,
+ desc->bInterfaceSubClass, desc->bInterfaceProtocol) != 7)
+ {
+ continue;
+ }
- if (strstr(ifs_str, if_str) != NULL) {
- continue;
- }
+ if (strstr (ifs_str, if_str) != NULL)
+ {
+ continue;
+ }
- memcpy(&ifs_str[strpos], if_str, 8),
- strpos += 7;
- }
+ memcpy (&ifs_str[strpos], if_str, 8), strpos += 7;
+ }
- if (strpos > 0) {
+ if (strpos > 0)
+ {
ifs_str[strpos++] = ':';
ifs_str[strpos++] = '\0';
- }
+ }
- return 0;
+ return 0;
}
-
-void usage(char const* progname) {
- fprintf(stderr, "[ERROR] %s: Usage: %s /path/to/sysfs/device/directory\n", progname, progname);
- exit(2);
+void
+usage (char const *progname)
+{
+ fprintf (stderr,
+ "[ERROR] %s: Usage: %s /path/to/sysfs/device/directory\n",
+ progname, progname);
+ exit (2);
}
-
// find out what kind of device this is from the sysfs device tree
// fill in the caller-supplied pointer with a malloc'ed string that encodes the DEVTYPE
-int get_device_type( char const* sysfs_path, char** device_type, size_t* device_type_len ) {
-
- char uevent_path[4097];
- memset( uevent_path, 0, 4097 );
-
- char* uevent_buf = NULL;
- size_t uevent_len = 0;
-
- char* device_type_buf = NULL;
- size_t device_type_buf_len = 0;
-
- int rc = 0;
-
- snprintf(uevent_path, 4096, "%s/uevent", sysfs_path );
-
- rc = vdev_read_file( uevent_path, &uevent_buf, &uevent_len );
- if( rc != 0 ) {
-
+int
+get_device_type (char const *sysfs_path, char **device_type,
+ size_t * device_type_len)
+{
+
+ char uevent_path[4097];
+ memset (uevent_path, 0, 4097);
+
+ char *uevent_buf = NULL;
+ size_t uevent_len = 0;
+
+ char *device_type_buf = NULL;
+ size_t device_type_buf_len = 0;
+
+ int rc = 0;
+
+ snprintf (uevent_path, 4096, "%s/uevent", sysfs_path);
+
+ rc = vdev_read_file (uevent_path, &uevent_buf, &uevent_len);
+ if (rc != 0)
+ {
+
return rc;
- }
-
- rc = vdev_sysfs_uevent_get_key( uevent_buf, uevent_len, "DEVTYPE", &device_type_buf, &device_type_buf_len );
- if( rc != 0 ) {
-
- free( uevent_buf );
+ }
+
+ rc = vdev_sysfs_uevent_get_key (uevent_buf, uevent_len, "DEVTYPE",
+ &device_type_buf, &device_type_buf_len);
+ if (rc != 0)
+ {
+
+ free (uevent_buf);
return rc;
- }
-
- *device_type = device_type_buf;
- *device_type_len = device_type_buf_len;
-
- free( uevent_buf );
-
- return 0;
+ }
+
+ *device_type = device_type_buf;
+ *device_type_len = device_type_buf_len;
+
+ free (uevent_buf);
+
+ return 0;
}
/*
@@ -310,558 +340,681 @@ int get_device_type( char const* sysfs_path, char** device_type, size_t* device_
* 6.) If the device supplies a serial number, this number
* is concatenated with the identification with an underscore '_'.
*/
-int main( int argc, char **argv) {
-
- int rc = 0;
- char vendor_str[256];
- char vendor_str_enc[256];
- char vendor_id[256];
- char model_str[256];
- char model_str_enc[256];
- char product_id[256];
- char serial_str[256];
- char packed_if_str[256];
- char revision_str[256];
- char type_str[256];
- char instance_str[256];
- char driver[256];
- char ifnum[256];
- char serial[4096];
- char sysfs_base[8193]; // /sys/devices entry for this device
- char path_tmp[8193];
-
- bool confirm_usb = false;
-
- char* attr = NULL; // temporary buffer for pulling attrs out of sysfs
- size_t attr_len = 0;
-
- int if_class_num;
- int protocol = 0;
- size_t l;
- char *s;
- char* devtype_str = NULL;
- size_t devtype_strlen = 0;
-
- // interface information
- char* if_device_path = NULL;
- size_t if_device_path_len= 0;
-
- char* usb_device_path = NULL;
- size_t usb_device_path_len = 0;
-
- char* ifnum_str = NULL;
- size_t ifnum_strlen = 0;
-
- char* driver_str = NULL;
- size_t driver_strlen = 0;
-
- char* if_class_str = NULL;
- size_t if_class_strlen = 0;
-
- char* if_subclass_str = NULL;
- size_t if_subclass_strlen = 0;
-
- memset( sysfs_base, 0, 8193 );
- memset( path_tmp, 0, 8193 );
-
- memset( vendor_str, 0, 256 );
- memset( vendor_str_enc, 0, 256 );
- memset( vendor_id, 0, 256 );
- memset( model_str, 0, 256 );
- memset( model_str_enc, 0, 256 );
- memset( product_id, 0, 256 );
- memset( serial_str, 0, 256 );
- memset( packed_if_str, 0, 256 );
- memset( revision_str, 0, 256 );
- memset( type_str, 0, 256 );
- memset( instance_str, 0, 256 );
- memset( driver, 0, 256 );
- memset( ifnum, 0, 256 );
- memset( serial, 0, 4096 );
-
- if( argc != 2 ) {
- usage(argv[0] );
- }
-
- if( strlen(argv[1]) >= 4096 ) {
- fprintf(stderr, "[ERROR] %s: Invalid /sys/devices path\n", argv[0]);
- exit(3);
- }
-
- strcpy( sysfs_base, argv[1] );
-
- // find out what kind of device we are...
- get_device_type( sysfs_base, &devtype_str, &devtype_strlen );
-
- if( devtype_str != NULL && strcmp(devtype_str, "usb_device") == 0 ) {
-
+int
+main (int argc, char **argv)
+{
+
+ int rc = 0;
+ char vendor_str[256];
+ char vendor_str_enc[256];
+ char vendor_id[256];
+ char model_str[256];
+ char model_str_enc[256];
+ char product_id[256];
+ char serial_str[256];
+ char packed_if_str[256];
+ char revision_str[256];
+ char type_str[256];
+ char instance_str[256];
+ char driver[256];
+ char ifnum[256];
+ char serial[4096];
+ char sysfs_base[8193]; // /sys/devices entry for this device
+ char path_tmp[8193];
+
+ bool confirm_usb = false;
+
+ char *attr = NULL; // temporary buffer for pulling attrs out of sysfs
+ size_t attr_len = 0;
+
+ int if_class_num;
+ int protocol = 0;
+ size_t l;
+ char *s;
+ char *devtype_str = NULL;
+ size_t devtype_strlen = 0;
+
+ // interface information
+ char *if_device_path = NULL;
+ size_t if_device_path_len = 0;
+
+ char *usb_device_path = NULL;
+ size_t usb_device_path_len = 0;
+
+ char *ifnum_str = NULL;
+ size_t ifnum_strlen = 0;
+
+ char *driver_str = NULL;
+ size_t driver_strlen = 0;
+
+ char *if_class_str = NULL;
+ size_t if_class_strlen = 0;
+
+ char *if_subclass_str = NULL;
+ size_t if_subclass_strlen = 0;
+
+ memset (sysfs_base, 0, 8193);
+ memset (path_tmp, 0, 8193);
+
+ memset (vendor_str, 0, 256);
+ memset (vendor_str_enc, 0, 256);
+ memset (vendor_id, 0, 256);
+ memset (model_str, 0, 256);
+ memset (model_str_enc, 0, 256);
+ memset (product_id, 0, 256);
+ memset (serial_str, 0, 256);
+ memset (packed_if_str, 0, 256);
+ memset (revision_str, 0, 256);
+ memset (type_str, 0, 256);
+ memset (instance_str, 0, 256);
+ memset (driver, 0, 256);
+ memset (ifnum, 0, 256);
+ memset (serial, 0, 4096);
+
+ if (argc != 2)
+ {
+ usage (argv[0]);
+ }
+
+ if (strlen (argv[1]) >= 4096)
+ {
+ fprintf (stderr, "[ERROR] %s: Invalid /sys/devices path\n", argv[0]);
+ exit (3);
+ }
+
+ strcpy (sysfs_base, argv[1]);
+
+ // find out what kind of device we are...
+ get_device_type (sysfs_base, &devtype_str, &devtype_strlen);
+
+ if (devtype_str != NULL && strcmp (devtype_str, "usb_device") == 0)
+ {
+
// we're a device, and can get the packed info right now
- dev_if_packed_info( sysfs_base, packed_if_str, sizeof(packed_if_str) );
-
- usb_device_path = strdup( sysfs_base );
- if( usb_device_path == NULL ) {
- exit(4);
- }
-
- usb_device_path_len = strlen(usb_device_path);
-
+ dev_if_packed_info (sysfs_base, packed_if_str, sizeof (packed_if_str));
+
+ usb_device_path = strdup (sysfs_base);
+ if (usb_device_path == NULL)
+ {
+ exit (4);
+ }
+
+ usb_device_path_len = strlen (usb_device_path);
+
goto fallback;
- }
-
- // find USB parent
- rc = vdev_sysfs_get_parent_with_subsystem_devtype( sysfs_base, "usb", "usb_interface", &if_device_path, &if_device_path_len );
- if( rc != 0 ) {
-
- fprintf(stderr, "[ERROR] %s: unable to access usb_interface device of '%s'\n", argv[0], sysfs_base );
- exit(1);
- }
-
- // search *this* device instead
- // get interface information
- rc = vdev_sysfs_read_attr( if_device_path, "bInterfaceNumber", &ifnum_str, &ifnum_strlen );
- if( rc == 0 ) {
-
- vdev_util_rstrip( ifnum_str );
-
- strncpy( ifnum, ifnum_str, (sizeof(ifnum) - 1 < ifnum_strlen ? sizeof(ifnum) - 1 : ifnum_strlen) );
-
- free( ifnum_str );
- }
-
- rc = vdev_sysfs_read_attr( if_device_path, "driver", &driver_str, &driver_strlen );
- if( rc == 0 ) {
-
- vdev_util_rstrip( driver_str );
-
- strncpy( driver, driver_str, (sizeof(driver) - 1 < driver_strlen ? sizeof(driver) - 1 : driver_strlen) );
-
- free( driver_str );
- }
-
- rc = vdev_sysfs_read_attr( if_device_path, "bInterfaceClass", &if_class_str, &if_class_strlen );
- if( rc != 0 ) {
-
- if( devtype_str != NULL ) {
- free( devtype_str );
- }
-
- fprintf(stderr, "[ERROR] %s: vdev_sysfs_read_attr('%s/%s') rc = %d\n", if_device_path, "bInterfaceClass", argv[0], rc );
- exit(1);
- }
-
- // parse fields
- if_class_num = strtoul( if_class_str, NULL, 16 );
-
- free( if_class_str );
-
- if( if_class_num == 8 ) {
+ }
+ // find USB parent
+ rc = vdev_sysfs_get_parent_with_subsystem_devtype (sysfs_base, "usb",
+ "usb_interface",
+ &if_device_path,
+ &if_device_path_len);
+ if (rc != 0)
+ {
+
+ fprintf (stderr,
+ "[ERROR] %s: unable to access usb_interface device of '%s'\n",
+ argv[0], sysfs_base);
+ exit (1);
+ }
+ // search *this* device instead
+ // get interface information
+ rc = vdev_sysfs_read_attr (if_device_path, "bInterfaceNumber",
+ &ifnum_str, &ifnum_strlen);
+ if (rc == 0)
+ {
+
+ vdev_util_rstrip (ifnum_str);
+
+ strncpy (ifnum, ifnum_str,
+ (sizeof (ifnum) - 1 <
+ ifnum_strlen ? sizeof (ifnum) - 1 : ifnum_strlen));
+
+ free (ifnum_str);
+ }
+
+ rc = vdev_sysfs_read_attr (if_device_path, "driver", &driver_str,
+ &driver_strlen);
+ if (rc == 0)
+ {
+
+ vdev_util_rstrip (driver_str);
+
+ strncpy (driver, driver_str,
+ (sizeof (driver) - 1 <
+ driver_strlen ? sizeof (driver) - 1 : driver_strlen));
+
+ free (driver_str);
+ }
+
+ rc = vdev_sysfs_read_attr (if_device_path, "bInterfaceClass",
+ &if_class_str, &if_class_strlen);
+ if (rc != 0)
+ {
+
+ if (devtype_str != NULL)
+ {
+ free (devtype_str);
+ }
+
+ fprintf (stderr,
+ "[ERROR] %s: vdev_sysfs_read_attr('%s/%s') rc = %d\n",
+ if_device_path, "bInterfaceClass", argv[0], rc);
+ exit (1);
+ }
+ // parse fields
+ if_class_num = strtoul (if_class_str, NULL, 16);
+
+ free (if_class_str);
+
+ if (if_class_num == 8)
+ {
// indicates mass storage device.
// check subclass
- rc = vdev_sysfs_read_attr( if_device_path, "bInterfaceSubClass", &if_subclass_str, &if_subclass_strlen );
- if( rc == 0 ) {
-
- // got ourselves a type of storage device
- protocol = set_usb_mass_storage_ifsubtype( type_str, if_subclass_str, sizeof(type_str) - 1 );
- }
- else {
-
- // set type from interface instead
- set_usb_iftype( type_str, if_class_num, sizeof(type_str) - 1 );
- }
-
- free( if_subclass_str );
- }
-
- // find the usb_device that is this interface's parent
- rc = vdev_sysfs_get_parent_with_subsystem_devtype( if_device_path, "usb", "usb_device", &usb_device_path, &usb_device_path_len );
- if( rc != 0 ) {
-
+ rc = vdev_sysfs_read_attr (if_device_path, "bInterfaceSubClass",
+ &if_subclass_str, &if_subclass_strlen);
+ if (rc == 0)
+ {
+
+ // got ourselves a type of storage device
+ protocol =
+ set_usb_mass_storage_ifsubtype (type_str,
+ if_subclass_str,
+ sizeof (type_str) - 1);
+ }
+ else
+ {
+
+ // set type from interface instead
+ set_usb_iftype (type_str, if_class_num, sizeof (type_str) - 1);
+ }
+
+ free (if_subclass_str);
+ }
+ // find the usb_device that is this interface's parent
+ rc = vdev_sysfs_get_parent_with_subsystem_devtype (if_device_path, "usb",
+ "usb_device",
+ &usb_device_path,
+ &usb_device_path_len);
+ if (rc != 0)
+ {
+
// couldn't find
- if( devtype_str != NULL ) {
- free( devtype_str );
- }
-
- fprintf( stderr, "[ERROR] %s: vdev_sysfs_get_parent_with_subsystem_devtype('%s', 'usb', 'usb_device') rc = %d\n", argv[0], sysfs_base, rc );
-
- exit(1);
- }
-
- // got the device path!
- // get the device info
- dev_if_packed_info( usb_device_path, packed_if_str, sizeof(packed_if_str) );
-
- // is this a SCSI or ATAPI device?
- if ((protocol == 6 || protocol == 2)) {
-
- char* dev_scsi_path = NULL;
+ if (devtype_str != NULL)
+ {
+ free (devtype_str);
+ }
+
+ fprintf (stderr,
+ "[ERROR] %s: vdev_sysfs_get_parent_with_subsystem_devtype('%s', 'usb', 'usb_device') rc = %d\n",
+ argv[0], sysfs_base, rc);
+
+ exit (1);
+ }
+ // got the device path!
+ // get the device info
+ dev_if_packed_info (usb_device_path, packed_if_str, sizeof (packed_if_str));
+
+ // is this a SCSI or ATAPI device?
+ if ((protocol == 6 || protocol == 2))
+ {
+
+ char *dev_scsi_path = NULL;
size_t dev_scsi_path_len = 0;
-
- char* scsi_vendor_str = NULL;
+
+ char *scsi_vendor_str = NULL;
size_t scsi_vendor_str_len = 0;
-
- char* scsi_model_str = NULL;
+
+ char *scsi_model_str = NULL;
size_t scsi_model_str_len = 0;
-
- char* scsi_type_str = NULL;
+
+ char *scsi_type_str = NULL;
size_t scsi_type_str_len = 0;
-
- char* scsi_rev_str = NULL;
+
+ char *scsi_rev_str = NULL;
size_t scsi_rev_str_len = 0;
-
- char* dev_scsi_sysname = NULL;
+
+ char *dev_scsi_sysname = NULL;
size_t dev_scsi_sysname_len = 0;
-
+
int host = 0;
int bus = 0;
int target = 0;
int lun = 0;
-
+
// scsi device?
- rc = vdev_sysfs_get_parent_with_subsystem_devtype( sysfs_base, "scsi", "scsi_device", &dev_scsi_path, &dev_scsi_path_len );
- if( rc != 0 ) {
-
- // nope
- log_error( "WARN: unable to find parent 'scsi' of '%s'", sysfs_base );
- goto fallback;
- }
-
- rc = vdev_sysfs_get_sysname( dev_scsi_path, &dev_scsi_sysname, &dev_scsi_sysname_len );
- if( rc != 0 ) {
-
- // nope
- free( dev_scsi_path );
-
- log_error("WARN: vdev_sysfs_get_sysname('%s') rc = %d\n", dev_scsi_path, rc );
- goto fallback;
- }
-
+ rc = vdev_sysfs_get_parent_with_subsystem_devtype (sysfs_base,
+ "scsi",
+ "scsi_device",
+ &dev_scsi_path,
+ &dev_scsi_path_len);
+ if (rc != 0)
+ {
+
+ // nope
+ log_error ("WARN: unable to find parent 'scsi' of '%s'",
+ sysfs_base);
+ goto fallback;
+ }
+
+ rc = vdev_sysfs_get_sysname (dev_scsi_path, &dev_scsi_sysname,
+ &dev_scsi_sysname_len);
+ if (rc != 0)
+ {
+
+ // nope
+ free (dev_scsi_path);
+
+ log_error
+ ("WARN: vdev_sysfs_get_sysname('%s') rc = %d\n",
+ dev_scsi_path, rc);
+ goto fallback;
+ }
// find host, bus, target, lun
- rc = sscanf( dev_scsi_sysname, "%d:%d:%d:%d", &host, &bus, &target, &lun );
- if( rc != 4 ) {
-
- // nope
- log_error( "WARN: unable to read host, bus, target, and/or lun from '%s'", dev_scsi_path );
- free( dev_scsi_path );
- free( dev_scsi_sysname );
- goto fallback;
- }
-
+ rc = sscanf (dev_scsi_sysname, "%d:%d:%d:%d", &host, &bus,
+ &target, &lun);
+ if (rc != 4)
+ {
+
+ // nope
+ log_error
+ ("WARN: unable to read host, bus, target, and/or lun from '%s'",
+ dev_scsi_path);
+ free (dev_scsi_path);
+ free (dev_scsi_sysname);
+ goto fallback;
+ }
// see about vendor?
- rc = vdev_sysfs_read_attr( dev_scsi_path, "vendor", &scsi_vendor_str, &scsi_vendor_str_len );
- if( rc != 0 ) {
-
- // nope
- log_error("WARN: unable to read vendor string from '%s'", dev_scsi_path );
- free( dev_scsi_path );
- free( dev_scsi_sysname );
- goto fallback;
- }
-
- vdev_util_rstrip( scsi_vendor_str );
-
- vdev_util_encode_string( scsi_vendor_str, vendor_str_enc, sizeof(vendor_str_enc) );
- vdev_util_replace_whitespace( scsi_vendor_str, vendor_str, sizeof(vendor_str) - 1 );
- vdev_util_replace_chars( vendor_str, NULL );
-
- free( scsi_vendor_str );
-
+ rc = vdev_sysfs_read_attr (dev_scsi_path, "vendor",
+ &scsi_vendor_str, &scsi_vendor_str_len);
+ if (rc != 0)
+ {
+
+ // nope
+ log_error
+ ("WARN: unable to read vendor string from '%s'", dev_scsi_path);
+ free (dev_scsi_path);
+ free (dev_scsi_sysname);
+ goto fallback;
+ }
+
+ vdev_util_rstrip (scsi_vendor_str);
+
+ vdev_util_encode_string (scsi_vendor_str, vendor_str_enc,
+ sizeof (vendor_str_enc));
+ vdev_util_replace_whitespace (scsi_vendor_str, vendor_str,
+ sizeof (vendor_str) - 1);
+ vdev_util_replace_chars (vendor_str, NULL);
+
+ free (scsi_vendor_str);
+
// see about model?
- rc = vdev_sysfs_read_attr( dev_scsi_path, "model", &scsi_model_str, &scsi_model_str_len );
- if( rc != 0 ) {
-
- // nope
- log_error("WARN: unable to read model from '%s'", dev_scsi_path );
- free( dev_scsi_path );
- free( dev_scsi_sysname );
-
- goto fallback;
- }
-
- vdev_util_rstrip( scsi_model_str );
-
- vdev_util_encode_string( scsi_model_str, model_str_enc, sizeof(model_str_enc) );
- vdev_util_replace_whitespace( scsi_model_str, model_str, sizeof(model_str) - 1 );
- vdev_util_replace_chars( model_str, NULL );
-
- free( scsi_model_str );
-
+ rc = vdev_sysfs_read_attr (dev_scsi_path, "model",
+ &scsi_model_str, &scsi_model_str_len);
+ if (rc != 0)
+ {
+
+ // nope
+ log_error ("WARN: unable to read model from '%s'", dev_scsi_path);
+ free (dev_scsi_path);
+ free (dev_scsi_sysname);
+
+ goto fallback;
+ }
+
+ vdev_util_rstrip (scsi_model_str);
+
+ vdev_util_encode_string (scsi_model_str, model_str_enc,
+ sizeof (model_str_enc));
+ vdev_util_replace_whitespace (scsi_model_str, model_str,
+ sizeof (model_str) - 1);
+ vdev_util_replace_chars (model_str, NULL);
+
+ free (scsi_model_str);
+
// see about type?
- rc = vdev_sysfs_read_attr( dev_scsi_path, "type", &scsi_type_str, &scsi_type_str_len );
- if( rc != 0 ) {
-
- // nope
- log_error("WARN: unable to read type from '%s'", dev_scsi_path );
- free( dev_scsi_path );
- free( dev_scsi_sysname );
-
- goto fallback;
- }
-
- set_scsi_type( type_str, scsi_type_str, sizeof(type_str) - 1 );
-
- free( scsi_type_str );
-
+ rc = vdev_sysfs_read_attr (dev_scsi_path, "type", &scsi_type_str,
+ &scsi_type_str_len);
+ if (rc != 0)
+ {
+
+ // nope
+ log_error ("WARN: unable to read type from '%s'", dev_scsi_path);
+ free (dev_scsi_path);
+ free (dev_scsi_sysname);
+
+ goto fallback;
+ }
+
+ set_scsi_type (type_str, scsi_type_str, sizeof (type_str) - 1);
+
+ free (scsi_type_str);
+
// see about revision?
- rc = vdev_sysfs_read_attr( dev_scsi_path, "rev", &scsi_rev_str, &scsi_rev_str_len );
- if( rc != 0 ) {
-
- // nope
- log_error("WARN: unable to read revision from '%s'", dev_scsi_path );
- free( dev_scsi_path );
- free( dev_scsi_sysname );
-
- goto fallback;
- }
-
- vdev_util_replace_whitespace( scsi_rev_str, revision_str, sizeof(revision_str) - 1 );
- vdev_util_replace_chars( revision_str, NULL );
-
- free( scsi_rev_str );
-
- sprintf(instance_str, "%d:%d", target, lun );
-
- free( dev_scsi_path );
- free( dev_scsi_sysname );
- }
+ rc = vdev_sysfs_read_attr (dev_scsi_path, "rev", &scsi_rev_str,
+ &scsi_rev_str_len);
+ if (rc != 0)
+ {
+
+ // nope
+ log_error ("WARN: unable to read revision from '%s'",
+ dev_scsi_path);
+ free (dev_scsi_path);
+ free (dev_scsi_sysname);
+
+ goto fallback;
+ }
+
+ vdev_util_replace_whitespace (scsi_rev_str, revision_str,
+ sizeof (revision_str) - 1);
+ vdev_util_replace_chars (revision_str, NULL);
+
+ free (scsi_rev_str);
+
+ sprintf (instance_str, "%d:%d", target, lun);
+
+ free (dev_scsi_path);
+ free (dev_scsi_sysname);
+ }
fallback:
- // not a device, and not an interface.
- // fall back to querying vendor and model information
- rc = vdev_sysfs_read_attr( usb_device_path, "idVendor", &attr, &attr_len );
- if( rc == 0 ) {
-
- strncpy( vendor_id, attr, (attr_len < sizeof(vendor_id)-1 ? attr_len : sizeof(vendor_id)-1) );
- vdev_util_rstrip( vendor_id );
-
- free( attr );
+ // not a device, and not an interface.
+ // fall back to querying vendor and model information
+ rc = vdev_sysfs_read_attr (usb_device_path, "idVendor", &attr, &attr_len);
+ if (rc == 0)
+ {
+
+ strncpy (vendor_id, attr,
+ (attr_len <
+ sizeof (vendor_id) - 1 ? attr_len : sizeof (vendor_id) - 1));
+ vdev_util_rstrip (vendor_id);
+
+ free (attr);
attr = NULL;
- }
-
- rc = vdev_sysfs_read_attr( usb_device_path, "idProduct", &attr, &attr_len );
- if( rc == 0 ) {
-
- strncpy( product_id, attr, (attr_len < sizeof(product_id)-1 ? attr_len : sizeof(product_id)-1) );
- vdev_util_rstrip( product_id );
-
- free( attr );
+ }
+
+ rc = vdev_sysfs_read_attr (usb_device_path, "idProduct", &attr, &attr_len);
+ if (rc == 0)
+ {
+
+ strncpy (product_id, attr,
+ (attr_len <
+ sizeof (product_id) -
+ 1 ? attr_len : sizeof (product_id) - 1));
+ vdev_util_rstrip (product_id);
+
+ free (attr);
attr = NULL;
- }
-
- if( vendor_str[0] == 0 ) {
-
+ }
+
+ if (vendor_str[0] == 0)
+ {
+
// vendor not known yet. Try manufaturer, and fall back to idVendor if need be
- char* manufacturer_str = NULL;
+ char *manufacturer_str = NULL;
size_t manufacturer_strlen = 0;
-
- rc = vdev_sysfs_read_attr( usb_device_path, "manufacturer", &manufacturer_str, &manufacturer_strlen );
- if( rc != 0 ) {
-
- if( rc == -ENOENT ) {
-
- // fall back to idVendor
- vdev_util_encode_string( vendor_id, vendor_str_enc, sizeof(vendor_str_enc) );
- vdev_util_replace_whitespace( vendor_id, vendor_str, sizeof(vendor_str)-1 );
- vdev_util_replace_chars( vendor_str, NULL );
- }
- else {
-
- log_error("FATAL: vdev_sysfs_read_attr('%s/manufacturer') rc = %d\n", usb_device_path, rc );
- exit(1);
- }
- }
- else {
-
- // success!
- vdev_util_rstrip( manufacturer_str );
-
- vdev_util_encode_string( manufacturer_str, vendor_str_enc, sizeof(vendor_str_enc) );
- vdev_util_replace_whitespace( manufacturer_str, vendor_str, sizeof(vendor_str)-1 );
- vdev_util_replace_chars( vendor_str, NULL );
-
- free( manufacturer_str );
- manufacturer_str = NULL;
- }
- }
-
- if( model_str[0] == 0 ) {
-
+
+ rc = vdev_sysfs_read_attr (usb_device_path, "manufacturer",
+ &manufacturer_str, &manufacturer_strlen);
+ if (rc != 0)
+ {
+
+ if (rc == -ENOENT)
+ {
+
+ // fall back to idVendor
+ vdev_util_encode_string (vendor_id,
+ vendor_str_enc,
+ sizeof (vendor_str_enc));
+ vdev_util_replace_whitespace (vendor_id,
+ vendor_str,
+ sizeof (vendor_str) - 1);
+ vdev_util_replace_chars (vendor_str, NULL);
+ }
+ else
+ {
+
+ log_error
+ ("FATAL: vdev_sysfs_read_attr('%s/manufacturer') rc = %d\n",
+ usb_device_path, rc);
+ exit (1);
+ }
+ }
+ else
+ {
+
+ // success!
+ vdev_util_rstrip (manufacturer_str);
+
+ vdev_util_encode_string (manufacturer_str,
+ vendor_str_enc, sizeof (vendor_str_enc));
+ vdev_util_replace_whitespace (manufacturer_str,
+ vendor_str, sizeof (vendor_str) - 1);
+ vdev_util_replace_chars (vendor_str, NULL);
+
+ free (manufacturer_str);
+ manufacturer_str = NULL;
+ }
+ }
+
+ if (model_str[0] == 0)
+ {
+
// model not known yet. Try product, and fall back to idProduct if we fail
- char* product_str = NULL;
+ char *product_str = NULL;
size_t product_strlen = 0;
-
- rc = vdev_sysfs_read_attr( usb_device_path, "product", &product_str, &product_strlen );
- if( rc != 0 ) {
-
- if( rc == -ENOENT ) {
-
- // fall back to idProduct
- vdev_util_encode_string( product_id, model_str_enc, sizeof(model_str_enc) );
- vdev_util_replace_whitespace( product_id, vendor_str, sizeof(vendor_str) - 1 );
- vdev_util_replace_chars( vendor_str, NULL );
- }
- else {
-
- log_error("FATAL: vdev_sysfs_read_attr('%s/product') rc = %d\n", usb_device_path, rc );
- exit(1);
- }
- }
- else {
-
- // success!
- vdev_util_rstrip( product_str );
-
- vdev_util_encode_string( product_str, model_str_enc, sizeof(model_str_enc) );
- vdev_util_replace_whitespace( product_str, model_str, sizeof(model_str) - 1 );
- vdev_util_replace_chars( model_str, NULL );
-
- free( product_str );
- product_str = NULL;
- }
- }
-
- if( revision_str[0] == 0 ) {
-
+
+ rc = vdev_sysfs_read_attr (usb_device_path, "product",
+ &product_str, &product_strlen);
+ if (rc != 0)
+ {
+
+ if (rc == -ENOENT)
+ {
+
+ // fall back to idProduct
+ vdev_util_encode_string (product_id,
+ model_str_enc, sizeof (model_str_enc));
+ vdev_util_replace_whitespace (product_id,
+ vendor_str,
+ sizeof (vendor_str) - 1);
+ vdev_util_replace_chars (vendor_str, NULL);
+ }
+ else
+ {
+
+ log_error
+ ("FATAL: vdev_sysfs_read_attr('%s/product') rc = %d\n",
+ usb_device_path, rc);
+ exit (1);
+ }
+ }
+ else
+ {
+
+ // success!
+ vdev_util_rstrip (product_str);
+
+ vdev_util_encode_string (product_str, model_str_enc,
+ sizeof (model_str_enc));
+ vdev_util_replace_whitespace (product_str, model_str,
+ sizeof (model_str) - 1);
+ vdev_util_replace_chars (model_str, NULL);
+
+ free (product_str);
+ product_str = NULL;
+ }
+ }
+
+ if (revision_str[0] == 0)
+ {
+
// revision not known yet. maybe it's in bcdDevice?
- rc = vdev_sysfs_read_attr( usb_device_path, "bcdDevice", &attr, &attr_len );
- if( rc == 0 ) {
-
- vdev_util_rstrip( attr );
-
- vdev_util_replace_whitespace( attr, revision_str, sizeof(revision_str) - 1 );
- vdev_util_replace_chars( revision_str, NULL );
-
- free( attr );
- attr = NULL;
- }
- }
-
- if( serial_str[0] == 0 ) {
-
+ rc = vdev_sysfs_read_attr (usb_device_path, "bcdDevice", &attr,
+ &attr_len);
+ if (rc == 0)
+ {
+
+ vdev_util_rstrip (attr);
+
+ vdev_util_replace_whitespace (attr, revision_str,
+ sizeof (revision_str) - 1);
+ vdev_util_replace_chars (revision_str, NULL);
+
+ free (attr);
+ attr = NULL;
+ }
+ }
+
+ if (serial_str[0] == 0)
+ {
+
// serial number not known. Try 'serial'
- rc = vdev_sysfs_read_attr( usb_device_path, "serial", &attr, &attr_len );
- if( rc == 0 ) {
-
- vdev_util_rstrip( attr );
-
- const unsigned char *p = NULL;
- bool valid = true;
-
- /* http://msdn.microsoft.com/en-us/library/windows/hardware/gg487321.aspx */
- for (p = (unsigned char *)attr; *p != '\0'; p++) {
- if (*p < 0x20 || *p > 0x7f || *p == ',') {
- valid = false;
- break;
- }
- }
-
- if( valid ) {
- vdev_util_replace_whitespace( attr, serial_str, sizeof(serial_str) - 1 );
- vdev_util_replace_chars( serial_str, NULL );
- }
-
- free( attr );
- attr = NULL;
- }
- }
-
- // serialize everything
- s = serial;
- sprintf( s, "%s_%s", vendor_str, model_str );
- l = strlen(s);
-
- if( serial_str[0] != 0 ) {
- sprintf( s + l, "_%s", serial_str );
- l = strlen(s);
- }
-
- if( instance_str[0] != 0 ) {
- sprintf( s + l, "-%s", instance_str );
- l = strlen(s);
- }
-
- if( vendor_str[0] != 0 ) {
- vdev_property_add( "VDEV_USB_VENDOR", vendor_str );
+ rc = vdev_sysfs_read_attr (usb_device_path, "serial", &attr, &attr_len);
+ if (rc == 0)
+ {
+
+ vdev_util_rstrip (attr);
+
+ const unsigned char *p = NULL;
+ bool valid = true;
+
+ /* http://msdn.microsoft.com/en-us/library/windows/hardware/gg487321.aspx */
+ for (p = (unsigned char *) attr; *p != '\0'; p++)
+ {
+ if (*p < 0x20 || *p > 0x7f || *p == ',')
+ {
+ valid = false;
+ break;
+ }
+ }
+
+ if (valid)
+ {
+ vdev_util_replace_whitespace (attr, serial_str,
+ sizeof (serial_str) - 1);
+ vdev_util_replace_chars (serial_str, NULL);
+ }
+
+ free (attr);
+ attr = NULL;
+ }
+ }
+ // serialize everything
+ s = serial;
+ sprintf (s, "%s_%s", vendor_str, model_str);
+ l = strlen (s);
+
+ if (serial_str[0] != 0)
+ {
+ sprintf (s + l, "_%s", serial_str);
+ l = strlen (s);
+ }
+
+ if (instance_str[0] != 0)
+ {
+ sprintf (s + l, "-%s", instance_str);
+ l = strlen (s);
+ }
+
+ if (vendor_str[0] != 0)
+ {
+ vdev_property_add ("VDEV_USB_VENDOR", vendor_str);
confirm_usb = true;
- }
-
- if( vendor_str_enc[0] != 0 ) {
- vdev_property_add( "VDEV_USB_VENDOR_ENC", vendor_str_enc );
+ }
+
+ if (vendor_str_enc[0] != 0)
+ {
+ vdev_property_add ("VDEV_USB_VENDOR_ENC", vendor_str_enc);
confirm_usb = true;
- }
-
- if( vendor_id[0] != 0 ) {
- vdev_property_add( "VDEV_USB_VENDOR_ID", vendor_id );
+ }
+
+ if (vendor_id[0] != 0)
+ {
+ vdev_property_add ("VDEV_USB_VENDOR_ID", vendor_id);
confirm_usb = true;
- }
-
- if( model_str[0] != 0 ) {
- vdev_property_add( "VDEV_USB_MODEL", model_str );
+ }
+
+ if (model_str[0] != 0)
+ {
+ vdev_property_add ("VDEV_USB_MODEL", model_str);
confirm_usb = true;
- }
-
- if( model_str_enc[0] != 0 ) {
- vdev_property_add( "VDEV_USB_MODEL_ENC", model_str_enc );
+ }
+
+ if (model_str_enc[0] != 0)
+ {
+ vdev_property_add ("VDEV_USB_MODEL_ENC", model_str_enc);
confirm_usb = true;
- }
-
- if( product_id[0] != 0 ) {
- vdev_property_add( "VDEV_USB_MODEL_ID", product_id );
+ }
+
+ if (product_id[0] != 0)
+ {
+ vdev_property_add ("VDEV_USB_MODEL_ID", product_id);
confirm_usb = true;
- }
-
- if( revision_str[0] != 0 ) {
- vdev_property_add( "VDEV_USB_REVISION", revision_str );
+ }
+
+ if (revision_str[0] != 0)
+ {
+ vdev_property_add ("VDEV_USB_REVISION", revision_str);
confirm_usb = true;
- }
-
- if( strcmp(serial, "_") != 0 ) {
-
+ }
+
+ if (strcmp (serial, "_") != 0)
+ {
+
// nonempty serial number
- vdev_property_add( "VDEV_USB_SERIAL", serial );
+ vdev_property_add ("VDEV_USB_SERIAL", serial);
confirm_usb = true;
- }
-
- if( serial_str[0] != 0 ) {
- vdev_property_add( "VDEV_USB_SERIAL_SHORT", serial_str );
+ }
+
+ if (serial_str[0] != 0)
+ {
+ vdev_property_add ("VDEV_USB_SERIAL_SHORT", serial_str);
confirm_usb = true;
- }
-
- if( type_str[0] != 0 ) {
- vdev_property_add( "VDEV_USB_TYPE", type_str );
+ }
+
+ if (type_str[0] != 0)
+ {
+ vdev_property_add ("VDEV_USB_TYPE", type_str);
confirm_usb = true;
- }
-
- if( instance_str[0] != 0 ) {
- vdev_property_add( "VDEV_USB_INSTANCE", instance_str );
+ }
+
+ if (instance_str[0] != 0)
+ {
+ vdev_property_add ("VDEV_USB_INSTANCE", instance_str);
confirm_usb = true;
- }
-
- if( packed_if_str[0] != 0 ) {
- vdev_property_add( "VDEV_USB_INTERFACES", packed_if_str );
+ }
+
+ if (packed_if_str[0] != 0)
+ {
+ vdev_property_add ("VDEV_USB_INTERFACES", packed_if_str);
confirm_usb = true;
- }
-
- if( ifnum[0] != 0 ) {
- vdev_property_add( "VDEV_USB_INTERFACE_NUM", ifnum );
+ }
+
+ if (ifnum[0] != 0)
+ {
+ vdev_property_add ("VDEV_USB_INTERFACE_NUM", ifnum);
confirm_usb = true;
- }
-
- if( driver[0] != 0 ) {
- vdev_property_add( "VDEV_USB_DRIVER", driver );
+ }
+
+ if (driver[0] != 0)
+ {
+ vdev_property_add ("VDEV_USB_DRIVER", driver);
confirm_usb = true;
- }
-
- if( confirm_usb ) {
- vdev_property_add( "VDEV_USB", "1" );
- }
-
- vdev_property_print();
- vdev_property_free_all();
-
- if( devtype_str != NULL ) {
- free( devtype_str );
- }
-
- return 0;
+ }
+
+ if (confirm_usb)
+ {
+ vdev_property_add ("VDEV_USB", "1");
+ }
+
+ vdev_property_print ();
+ vdev_property_free_all ();
+
+ if (devtype_str != NULL)
+ {
+ free (devtype_str);
+ }
+
+ return 0;
}
diff --git a/vdevd/helpers/LINUX/stat_v4l.c b/vdevd/helpers/LINUX/stat_v4l.c
index 607c201..b4c0afc 100644
--- a/vdevd/helpers/LINUX/stat_v4l.c
+++ b/vdevd/helpers/LINUX/stat_v4l.c
@@ -39,89 +39,102 @@
#include "common.h"
-int main(int argc, char *argv[]) {
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- {}
- };
-
- int fd = 0;
- char *device;
- struct v4l2_capability v2cap;
- char cap_str[4097];
-
- memset( cap_str, 0, 4097 );
-
- for (;;) {
+int
+main (int argc, char *argv[])
+{
+ static const struct option options[] = {
+ {"help", no_argument, NULL, 'h'},
+ {}
+ };
+
+ int fd = 0;
+ char *device;
+ struct v4l2_capability v2cap;
+ char cap_str[4097];
+
+ memset (cap_str, 0, 4097);
+
+ for (;;)
+ {
int option;
- option = getopt_long(argc, argv, "h", options, NULL);
- if (option == -1) {
- break;
- }
-
- switch (option) {
- case 'h':
- printf("%s [-h,--help] \n\n"
- "Video4Linux device identification.\n\n"
- " -h Print this message\n"
- , argv[0]);
- return 0;
- default:
- return 1;
- }
- }
-
- device = argv[optind];
-
- if (device == NULL) {
+ option = getopt_long (argc, argv, "h", options, NULL);
+ if (option == -1)
+ {
+ break;
+ }
+
+ switch (option)
+ {
+ case 'h':
+ printf ("%s [-h,--help] \n\n"
+ "Video4Linux device identification.\n\n"
+ " -h Print this message\n", argv[0]);
+ return 0;
+ default:
+ return 1;
+ }
+ }
+
+ device = argv[optind];
+
+ if (device == NULL)
+ {
return 2;
- }
-
- fd = open(device, O_RDONLY);
- if (fd < 0) {
+ }
+
+ fd = open (device, O_RDONLY);
+ if (fd < 0)
+ {
return 3;
- }
-
- if (ioctl(fd, VIDIOC_QUERYCAP, &v2cap) == 0) {
-
- vdev_property_add("VDEV_V4L_VERSION", "2");
- vdev_property_add("VDEV_V4L_PRODUCT", (char*)v2cap.card );
-
- strcat( cap_str, ":" );
-
- if ((v2cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) > 0) {
-
- strcat( cap_str, "capture:" );
- }
- if ((v2cap.capabilities & V4L2_CAP_VIDEO_OUTPUT) > 0) {
-
- strcat( cap_str, "video_output:" );
- }
- if ((v2cap.capabilities & V4L2_CAP_VIDEO_OVERLAY) > 0) {
-
- strcat( cap_str, "video_overlay:" );
- }
- if ((v2cap.capabilities & V4L2_CAP_AUDIO) > 0) {
-
- strcat( cap_str, "audio:" );
- }
- if ((v2cap.capabilities & V4L2_CAP_TUNER) > 0) {
-
- strcat( cap_str, "tuner:" );
- }
- if ((v2cap.capabilities & V4L2_CAP_RADIO) > 0) {
-
- strcat( cap_str, "radio:" );
- }
-
- vdev_property_add( "VDEV_V4L_CAPABILITIES", cap_str );
- }
-
- close( fd );
-
- vdev_property_print();
- vdev_property_free_all();
-
- return 0;
+ }
+
+ if (ioctl (fd, VIDIOC_QUERYCAP, &v2cap) == 0)
+ {
+
+ vdev_property_add ("VDEV_V4L_VERSION", "2");
+ vdev_property_add ("VDEV_V4L_PRODUCT", (char *) v2cap.card);
+
+ strcat (cap_str, ":");
+
+ if ((v2cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) > 0)
+ {
+
+ strcat (cap_str, "capture:");
+ }
+ if ((v2cap.capabilities & V4L2_CAP_VIDEO_OUTPUT) > 0)
+ {
+
+ strcat (cap_str, "video_output:");
+ }
+ if ((v2cap.capabilities & V4L2_CAP_VIDEO_OVERLAY) > 0)
+ {
+
+ strcat (cap_str, "video_overlay:");
+ }
+ if ((v2cap.capabilities & V4L2_CAP_AUDIO) > 0)
+ {
+
+ strcat (cap_str, "audio:");
+ }
+ if ((v2cap.capabilities & V4L2_CAP_TUNER) > 0)
+ {
+
+ strcat (cap_str, "tuner:");
+ }
+ if ((v2cap.capabilities & V4L2_CAP_RADIO) > 0)
+ {
+
+ strcat (cap_str, "radio:");
+ }
+
+ vdev_property_add ("VDEV_V4L_CAPABILITIES", cap_str);
+ }
+
+ close (fd);
+
+ vdev_property_print ();
+ vdev_property_free_all ();
+
+ return 0;
}
diff --git a/vdevd/main.c b/vdevd/main.c
index 84d49ca..3517abd 100644
--- a/vdevd/main.c
+++ b/vdevd/main.c
@@ -25,218 +25,255 @@
static struct vdev_state vdev;
// reload handler
-void vdev_reload_sighup( int ignored ) {
-
- vdev_reload( &vdev );
+void
+vdev_reload_sighup (int ignored)
+{
+
+ vdev_reload (&vdev);
}
// run!
-int main( int argc, char** argv ) {
-
- int rc = 0;
- int coldplug_quiesce_pipe[2];
- bool is_child = false;
- bool is_parent = false;
- ssize_t nr = 0;
-
- int coldplug_finished_fd = -1; // FD to write to once we finish flushing the initial device requests
-
- memset( &vdev, 0, sizeof(struct vdev_state) );
-
- // ignore SIGPIPE from daemonlets
- signal( SIGPIPE, SIG_IGN );
-
- // set up global vdev state
- rc = vdev_init( &vdev, argc, argv );
- if( rc != 0 ) {
-
- vdev_error("vdev_init rc = %d\n", rc );
-
- vdev_shutdown( &vdev, false );
- exit(1);
- }
-
- // run the preseed command
- rc = vdev_preseed_run( &vdev );
- if( rc != 0 ) {
-
- vdev_error("vdev_preseed_run rc = %d\n", rc );
-
- vdev_shutdown( &vdev, false );
- exit(1);
- }
-
- // if we're going to daemonize, then redirect logging to the logfile
- if( !vdev.config->foreground ) {
-
+int
+main (int argc, char **argv)
+{
+
+ int rc = 0;
+ int coldplug_quiesce_pipe[2];
+ bool is_child = false;
+ bool is_parent = false;
+ ssize_t nr = 0;
+
+ int coldplug_finished_fd = -1; // FD to write to once we finish flushing the initial device requests
+
+ memset (&vdev, 0, sizeof (struct vdev_state));
+
+ // ignore SIGPIPE from daemonlets
+ signal (SIGPIPE, SIG_IGN);
+
+ // set up global vdev state
+ rc = vdev_init (&vdev, argc, argv);
+ // help called from command line -h or --help (-2)
+ // short circuit with log/debug support
+ if (vdev.config->help)
+ {
+ if (rc == -2)
+ {
+
+ vdev_debug ("%s", "exiting: help called at command line\n");
+ // the shutdown and clean up should be redundant ?
+ exit (0);
+ }
+ }
+
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_init rc = %d\n", rc);
+
+ vdev_shutdown (&vdev, false);
+ exit (1);
+ }
+ // run the preseed command
+ rc = vdev_preseed_run (&vdev);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_preseed_run rc = %d\n", rc);
+
+ vdev_shutdown (&vdev, false);
+ exit (1);
+ }
+ // if we're going to daemonize, then redirect logging to the logfile
+ if (!vdev.config->foreground)
+ {
+
// sanity check
- if( vdev.config->logfile_path == NULL ) {
-
- fprintf(stderr, "No logfile specified\n");
-
- vdev_shutdown( &vdev, false );
- exit(2);
- }
-
+ if (vdev.config->logfile_path == NULL)
+ {
+
+ fprintf (stderr, "No logfile specified\n");
+
+ vdev_shutdown (&vdev, false);
+ exit (2);
+ }
// do we need to connect to syslog?
- if( strcmp( vdev.config->logfile_path, "syslog" ) == 0 ) {
-
- vdev_debug("%s", "Switching to syslog for messages\n");
- vdev_enable_syslog();
- }
-
- else {
-
- // send to a specific logfile
- rc = vdev_log_redirect( vdev.config->logfile_path );
- if( rc != 0 ) {
-
- vdev_error("vdev_log_redirect('%s') rc = %d\n", vdev.config->logfile_path, rc );
-
- vdev_shutdown( &vdev, false );
- exit(2);
- }
- }
-
- if( !vdev.config->coldplug_only ) {
-
- // will become a daemon after handling coldplug.
- // set up a pipe between parent and child, so the child can
- // signal the parent when it's device queue has been emptied
- // (meaning the parent can safely exit).
-
- rc = pipe( coldplug_quiesce_pipe );
- if( rc != 0 ) {
-
- vdev_error("pipe rc = %d\n", rc );
- vdev_shutdown( &vdev, false );
-
- exit(3);
- }
-
- // become a daemon
- rc = vdev_daemonize();
- if( rc < 0 ) {
-
- vdev_error("vdev_daemonize rc = %d\n", rc );
- vdev_shutdown( &vdev, false );
-
- exit(3);
- }
-
- if( rc == 0 ) {
-
- // child
- close( coldplug_quiesce_pipe[0] );
- coldplug_finished_fd = coldplug_quiesce_pipe[1];
-
- // write a pidfile
- if( vdev.config->pidfile_path != NULL ) {
-
- rc = vdev_pidfile_write( vdev.config->pidfile_path );
- if( rc != 0 ) {
-
- vdev_error("vdev_pidfile_write('%s') rc = %d\n", vdev.config->pidfile_path, rc );
-
- vdev_shutdown( &vdev, false );
- exit(4);
- }
- }
-
- // set reload handler
- signal( SIGHUP, vdev_reload_sighup );
-
- is_child = true;
- }
- else {
-
- // parent
- is_parent = true;
- close( coldplug_quiesce_pipe[1] );
- }
- }
- }
-
- if( !is_parent || vdev.config->foreground || vdev.config->coldplug_only ) {
-
+ if (strcmp (vdev.config->logfile_path, "syslog") == 0)
+ {
+
+ vdev_debug ("%s", "Switching to syslog for messages\n");
+ vdev_enable_syslog ();
+ }
+
+ else
+ {
+
+ // send to a specific logfile
+ rc = vdev_log_redirect (vdev.config->logfile_path);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_log_redirect('%s') rc = %d\n",
+ vdev.config->logfile_path, rc);
+
+ vdev_shutdown (&vdev, false);
+ exit (2);
+ }
+ }
+
+ if (!vdev.config->coldplug_only)
+ {
+
+ // will become a daemon after handling coldplug.
+ // set up a pipe between parent and child, so the child can
+ // signal the parent when it's device queue has been emptied
+ // (meaning the parent can safely exit).
+
+ rc = pipe (coldplug_quiesce_pipe);
+ if (rc != 0)
+ {
+
+ vdev_error ("pipe rc = %d\n", rc);
+ vdev_shutdown (&vdev, false);
+
+ exit (3);
+ }
+ // become a daemon
+ rc = vdev_daemonize ();
+ if (rc < 0)
+ {
+
+ vdev_error ("vdev_daemonize rc = %d\n", rc);
+ vdev_shutdown (&vdev, false);
+
+ exit (3);
+ }
+
+ if (rc == 0)
+ {
+
+ // child
+ close (coldplug_quiesce_pipe[0]);
+ coldplug_finished_fd = coldplug_quiesce_pipe[1];
+
+ // write a pidfile
+ if (vdev.config->pidfile_path != NULL)
+ {
+
+ rc = vdev_pidfile_write (vdev.config->pidfile_path);
+ if (rc != 0)
+ {
+
+ vdev_error
+ ("vdev_pidfile_write('%s') rc = %d\n",
+ vdev.config->pidfile_path, rc);
+
+ vdev_shutdown (&vdev, false);
+ exit (4);
+ }
+ }
+ // set reload handler
+ signal (SIGHUP, vdev_reload_sighup);
+
+ is_child = true;
+ }
+ else
+ {
+
+ // parent
+ is_parent = true;
+ close (coldplug_quiesce_pipe[1]);
+ }
+ }
+ }
+
+ if (!is_parent || vdev.config->foreground || vdev.config->coldplug_only)
+ {
+
// child, or foreground, or coldplug only. start handling (coldplug) device events
- rc = vdev_start( &vdev );
- if( rc != 0 ) {
-
- vdev_error("vdev_backend_init rc = %d\n", rc );
-
- vdev_stop( &vdev );
- vdev_shutdown( &vdev, false );
-
- // if child, and we're connected to the parent, then tell the parent to exit failure
- if( is_child && !vdev.config->foreground && !vdev.config->coldplug_only ) {
-
- write( coldplug_quiesce_pipe[1], &rc, sizeof(rc) );
- close( coldplug_quiesce_pipe[1] );
- }
-
- exit(5);
- }
-
+ rc = vdev_start (&vdev);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_backend_init rc = %d\n", rc);
+
+ vdev_stop (&vdev);
+ vdev_shutdown (&vdev, false);
+
+ // if child, and we're connected to the parent, then tell the parent to exit failure
+ if (is_child && !vdev.config->foreground
+ && !vdev.config->coldplug_only)
+ {
+
+ write (coldplug_quiesce_pipe[1], &rc, sizeof (rc));
+ close (coldplug_quiesce_pipe[1]);
+ }
+
+ exit (5);
+ }
// main loop: get events from the OS and process them.
// wake up the parent once we finish the coldplugged devices
- rc = vdev_main( &vdev, coldplug_finished_fd );
- if( rc != 0 ) {
-
- vdev_error("vdev_main rc = %d\n", rc );
- }
-
+ rc = vdev_main (&vdev, coldplug_finished_fd);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_main rc = %d\n", rc);
+ }
// if only doing coldplug, find and remove all stale coldplug devices.
// use the metadata directory to figure this out
- if( vdev.config->coldplug_only ) {
-
- rc = vdev_remove_unplugged_devices( &vdev );
- if( rc != 0 ) {
-
- vdev_error("vdev_remove_unplugged_devices() rc = %d\n", rc );
- }
- }
-
+ if (vdev.config->coldplug_only)
+ {
+
+ rc = vdev_remove_unplugged_devices (&vdev);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_remove_unplugged_devices() rc = %d\n", rc);
+ }
+ }
// quiesce requests
- vdev_stop( &vdev );
-
+ vdev_stop (&vdev);
+
// print benchmarks...
- vdev_debug("%s", "Action benchmarks:\n");
- for( unsigned int i = 0; i < vdev.num_acts; i++ ) {
-
- vdev_action_log_benchmarks( &vdev.acts[i] );
- }
-
+ vdev_debug ("%s", "Action benchmarks:\n");
+ for (unsigned int i = 0; i < vdev.num_acts; i++)
+ {
+
+ vdev_action_log_benchmarks (&vdev.acts[i]);
+ }
+
// clean up
// keep the pidfile unless we're doing coldplug only (in which case don't touch it)
- vdev_shutdown( &vdev, !vdev.config->coldplug_only );
-
+ vdev_shutdown (&vdev, !vdev.config->coldplug_only);
+
return rc;
- }
- else {
-
+ }
+ else
+ {
+
// parent process--wait for the child to finish processing the coldplugged devices, and exit.
- nr = read( coldplug_quiesce_pipe[0], &rc, sizeof(rc) );
-
- if( nr < 0 || rc != 0 ) {
-
- if( nr < 0 ) {
-
- vdev_error("read(%d) rc = %zd\n", coldplug_quiesce_pipe[0], nr );
- }
-
- vdev_error("device quiesce failure, child rc = %d\n", rc );
- exit(6);
- }
-
- printf("parent: all initial devices processed\n");
-
+ nr = read (coldplug_quiesce_pipe[0], &rc, sizeof (rc));
+
+ if (nr < 0 || rc != 0)
+ {
+
+ if (nr < 0)
+ {
+
+ vdev_error ("read(%d) rc = %zd\n",
+ coldplug_quiesce_pipe[0], nr);
+ }
+
+ vdev_error ("device quiesce failure, child rc = %d\n", rc);
+ exit (6);
+ }
+
+ printf ("parent: all initial devices processed\n");
+
// clean up, but keep the pidfile
- vdev_shutdown( &vdev, false );
-
- close( coldplug_quiesce_pipe[0] );
-
+ vdev_shutdown (&vdev, false);
+
+ close (coldplug_quiesce_pipe[0]);
+
return 0;
- }
+ }
}
-
diff --git a/vdevd/os/common.c b/vdevd/os/common.c
index 0e19722..901b8c6 100644
--- a/vdevd/os/common.c
+++ b/vdevd/os/common.c
@@ -25,142 +25,165 @@
#include "methods.h"
// yield new devices
-int vdev_os_main( struct vdev_os_context* vos ) {
-
- int rc = 0;
-
- while( vos->running ) {
-
+int
+vdev_os_main (struct vdev_os_context *vos)
+{
+
+ int rc = 0;
+
+ while (vos->running)
+ {
+
// make a device request
- struct vdev_device_request* vreq = VDEV_CALLOC( struct vdev_device_request, 1 );
-
- if( vreq == NULL ) {
- // OOM
- break;
- }
+ struct vdev_device_request *vreq =
+ VDEV_CALLOC (struct vdev_device_request, 1);
+ if (vreq == NULL)
+ {
+ // OOM
+ break;
+ }
// next device request
- rc = vdev_device_request_init( vreq, vos->state, VDEV_DEVICE_INVALID, NULL );
- if( rc != 0 ) {
-
- if( rc == -EAGAIN ) {
- continue;
- }
-
- free( vreq );
-
- vdev_error("vdev_device_request_init rc = %d\n", rc );
- break;
- }
-
+ rc = vdev_device_request_init (vreq, vos->state,
+ VDEV_DEVICE_INVALID, NULL);
+ if (rc != 0)
+ {
+
+ if (rc == -EAGAIN)
+ {
+ continue;
+ }
+
+ free (vreq);
+
+ vdev_error ("vdev_device_request_init rc = %d\n", rc);
+ break;
+ }
// yield the next device
- rc = vdev_os_next_device( vreq, vos->os_cls );
- if( rc != 0 ) {
-
- vdev_device_request_free( vreq );
- free( vreq );
-
- if( rc < 0 ) {
- vdev_error("vdev_os_next_device rc = %d\n", rc );
-
- if( rc == -EAGAIN ) {
-
- // OS backend says try again
- continue;
- }
- else {
-
- // fatal error
- break;
- }
- }
- else {
-
- // exit on success
- rc = 0;
- break;
- }
- }
-
- vdev_debug("Next device: %p, type=%d path=%s major=%u minor=%u mode=%o\n", vreq, vreq->type, vreq->path, major(vreq->dev), minor(vreq->dev), vreq->mode );
-
+ rc = vdev_os_next_device (vreq, vos->os_cls);
+ if (rc != 0)
+ {
+
+ vdev_device_request_free (vreq);
+ free (vreq);
+
+ if (rc < 0)
+ {
+ vdev_error ("vdev_os_next_device rc = %d\n", rc);
+
+ if (rc == -EAGAIN)
+ {
+
+ // OS backend says try again
+ continue;
+ }
+ else
+ {
+
+ // fatal error
+ break;
+ }
+ }
+ else
+ {
+
+ // exit on success
+ rc = 0;
+ break;
+ }
+ }
+
+ vdev_debug
+ ("Next device: %p, type=%d path=%s major=%u minor=%u mode=%o\n",
+ vreq, vreq->type, vreq->path, major (vreq->dev),
+ minor (vreq->dev), vreq->mode);
+
/*
- struct sglib_vdev_params_iterator itr2;
- struct vdev_param_t* dp2 = NULL;
-
- printf("vreq %p: params:\n", vreq);
- for( dp2 = sglib_vdev_params_it_init_inorder( &itr2, vreq->params ); dp2 != NULL; dp2 = sglib_vdev_params_it_next( &itr2 ) ) {
-
+ struct sglib_vdev_params_iterator itr2;
+ struct vdev_param_t* dp2 = NULL;
+
+ printf("vreq %p: params:\n", vreq);
+ for( dp2 = sglib_vdev_params_it_init_inorder( &itr2, vreq->params ); dp2 != NULL; dp2 = sglib_vdev_params_it_next( &itr2 ) ) {
+
printf(" '%s' == '%s'\n", dp2->key, dp2->value );
- }
- */
-
+ }
+ */
+
// post the event to the device work queue
- rc = vdev_device_request_enqueue( &vos->state->device_wq, vreq );
-
- if( rc != 0 ) {
-
- vdev_device_request_free( vreq );
- free( vreq );
-
- vdev_error("vdev_device_request_add rc = %d\n", rc );
-
- continue;
- }
- }
-
- return rc;
+ rc = vdev_device_request_enqueue (&vos->state->device_wq, vreq);
+
+ if (rc != 0)
+ {
+
+ vdev_device_request_free (vreq);
+ free (vreq);
+
+ vdev_error ("vdev_device_request_add rc = %d\n", rc);
+
+ continue;
+ }
+ }
+
+ return rc;
}
// set up a vdev os context
// NOTE: not reload-safe
-int vdev_os_context_init( struct vdev_os_context* vos, struct vdev_state* state ) {
-
- int rc = 0;
-
- memset( vos, 0, sizeof(struct vdev_os_context) );
-
- vos->state = state;
- vos->coldplug_only = state->coldplug_only;
-
- // set up OS state
- rc = vdev_os_init( vos, &vos->os_cls );
- if( rc != 0 ) {
-
- vdev_error("vdev_os_init rc = %d\n", rc );
- memset( vos, 0, sizeof(struct vdev_os_context) );
+int
+vdev_os_context_init (struct vdev_os_context *vos, struct vdev_state *state)
+{
+
+ int rc = 0;
+
+ memset (vos, 0, sizeof (struct vdev_os_context));
+
+ vos->state = state;
+ vos->coldplug_only = state->coldplug_only;
+
+ // set up OS state
+ rc = vdev_os_init (vos, &vos->os_cls);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_os_init rc = %d\n", rc);
+ memset (vos, 0, sizeof (struct vdev_os_context));
return rc;
- }
-
- vos->running = true;
-
- return 0;
-}
+ }
+ vos->running = true;
+
+ return 0;
+}
// free memory
-int vdev_os_context_free( struct vdev_os_context* vos ) {
+int
+vdev_os_context_free (struct vdev_os_context *vos)
+{
- if( vos != NULL ) {
- vdev_os_shutdown( vos->os_cls );
+ if (vos != NULL)
+ {
+ vdev_os_shutdown (vos->os_cls);
vos->os_cls = NULL;
-
- memset( vos, 0, sizeof(struct vdev_os_context) );
- }
-
- return 0;
-}
+ memset (vos, 0, sizeof (struct vdev_os_context));
+ }
+
+ return 0;
+}
// backend signal to vdevd that it has processed all coldplugged devices
-int vdev_os_context_signal_coldplug_finished( struct vdev_os_context* vos ) {
-
- vos->coldplug_finished = true;
- return 0;
+int
+vdev_os_context_signal_coldplug_finished (struct vdev_os_context *vos)
+{
+
+ vos->coldplug_finished = true;
+ return 0;
}
// wait for coldplug to finish
-bool vdev_os_context_is_coldplug_finished( struct vdev_os_context* vos ) {
-
- return vos->coldplug_finished;
+bool
+vdev_os_context_is_coldplug_finished (struct vdev_os_context * vos)
+{
+
+ return vos->coldplug_finished;
}
diff --git a/vdevd/os/common.h b/vdevd/os/common.h
index 59a3587..88d2998 100644
--- a/vdevd/os/common.h
+++ b/vdevd/os/common.h
@@ -25,32 +25,32 @@
#include "libvdev/util.h"
// connection to the OS's device notification system
-struct vdev_os_context {
-
- void* os_cls; // OS-specific data
-
- bool running;
-
- bool coldplug_only;
- bool coldplug_finished;
-
- // reference to global state
- // ACCESS WITH CAUTION--ENSURE RELOAD SAFETY
- struct vdev_state* state;
+struct vdev_os_context
+{
+
+ void *os_cls; // OS-specific data
+
+ bool running;
+
+ bool coldplug_only;
+ bool coldplug_finished;
+
+ // reference to global state
+ // ACCESS WITH CAUTION--ENSURE RELOAD SAFETY
+ struct vdev_state *state;
};
C_LINKAGE_BEGIN
-
// context management
-int vdev_os_context_init( struct vdev_os_context* vos, struct vdev_state* state );
-int vdev_os_context_free( struct vdev_os_context* vos );
+int vdev_os_context_init (struct vdev_os_context *vos,
+ struct vdev_state *state);
+int vdev_os_context_free (struct vdev_os_context *vos);
// signaling from the back-end to vdevd
-int vdev_os_context_signal_coldplug_finished( struct vdev_os_context* vos );
-bool vdev_os_context_is_coldplug_finished( struct vdev_os_context* vos );
+int vdev_os_context_signal_coldplug_finished (struct vdev_os_context *vos);
+bool vdev_os_context_is_coldplug_finished (struct vdev_os_context *vos);
-int vdev_os_main( struct vdev_os_context* vos );
+int vdev_os_main (struct vdev_os_context *vos);
C_LINKAGE_END
-
-#endif
+#endif
diff --git a/vdevd/os/linux.c b/vdevd/os/linux.c
index 2446e0b..dc4a216 100644
--- a/vdevd/os/linux.c
+++ b/vdevd/os/linux.c
@@ -26,175 +26,208 @@
#include "libvdev/sglib.h"
// parse a uevent action
-static vdev_device_request_t vdev_linux_parse_device_request_type( char const* type ) {
-
- if( strcmp(type, "add") == 0 ) {
+static vdev_device_request_t
+vdev_linux_parse_device_request_type (char const *type)
+{
+
+ if (strcmp (type, "add") == 0)
+ {
return VDEV_DEVICE_ADD;
- }
- else if( strcmp(type, "remove") == 0 ) {
+ }
+ else if (strcmp (type, "remove") == 0)
+ {
return VDEV_DEVICE_REMOVE;
- }
- else if( strcmp(type, "change") == 0 ) {
+ }
+ else if (strcmp (type, "change") == 0)
+ {
return VDEV_DEVICE_CHANGE;
- }
-
- return VDEV_DEVICE_INVALID;
-}
+ }
+ return VDEV_DEVICE_INVALID;
+}
// make the full sysfs path from the dev path, plus an additional path
// return NULL on OOM
-static char* vdev_linux_sysfs_fullpath( char const* sysfs_mountpoint, char const* devpath, char const* attr_path ) {
-
- char* tmp = NULL;
- char* ret = NULL;
-
- tmp = vdev_fullpath( sysfs_mountpoint, devpath, NULL );
- if( tmp == NULL ) {
+static char *
+vdev_linux_sysfs_fullpath (char const *sysfs_mountpoint,
+ char const *devpath, char const *attr_path)
+{
+
+ char *tmp = NULL;
+ char *ret = NULL;
+
+ tmp = vdev_fullpath (sysfs_mountpoint, devpath, NULL);
+ if (tmp == NULL)
+ {
return NULL;
- }
-
- ret = vdev_fullpath( tmp, attr_path, NULL );
- free( tmp );
-
- return ret;
-}
+ }
+ ret = vdev_fullpath (tmp, attr_path, NULL);
+ free (tmp);
+
+ return ret;
+}
// parse a device number pair
// return 0 on success, and set *major and *minor
// return -EINVAL if we failed to parse
-static int vdev_linux_sysfs_parse_device_nums( char const* devbuf, unsigned int* major, unsigned int* minor ) {
-
- int rc = 0;
-
- // parse devpath
- rc = sscanf( devbuf, "%u:%u", major, minor );
-
- if( rc != 2 ) {
-
- vdev_error("sscanf('%s') for major:minor rc = %d\n", devbuf, rc );
+static int
+vdev_linux_sysfs_parse_device_nums (char const *devbuf,
+ unsigned int *major, unsigned int *minor)
+{
+
+ int rc = 0;
+
+ // parse devpath
+ rc = sscanf (devbuf, "%u:%u", major, minor);
+
+ if (rc != 2)
+ {
+
+ vdev_error ("sscanf('%s') for major:minor rc = %d\n", devbuf, rc);
rc = -EINVAL;
- }
- else {
+ }
+ else
+ {
rc = 0;
- }
+ }
- return rc;
+ return rc;
}
// read the device major and minor number, using the devpath
// return 0 on success, and set *major and *minor
// return -ENOMEM on OOM
// return -errno on failure to open or read
-static int vdev_linux_sysfs_read_dev_nums( struct vdev_linux_context* ctx, char const* devpath, unsigned int* major, unsigned int* minor ) {
-
- int rc = 0;
- int fd = 0;
- ssize_t nr = 0;
- char devbuf[101];
-
- memset( devbuf, 0, 101 );
-
- char* full_devpath = vdev_linux_sysfs_fullpath( ctx->sysfs_mountpoint, devpath, "dev" );
- if( full_devpath == NULL ) {
+static int
+vdev_linux_sysfs_read_dev_nums (struct vdev_linux_context *ctx,
+ char const *devpath,
+ unsigned int *major, unsigned int *minor)
+{
+
+ int rc = 0;
+ int fd = 0;
+ ssize_t nr = 0;
+ char devbuf[101];
+
+ memset (devbuf, 0, 101);
+
+ char *full_devpath =
+ vdev_linux_sysfs_fullpath (ctx->sysfs_mountpoint, devpath, "dev");
+ if (full_devpath == NULL)
+ {
return -ENOMEM;
- }
-
- // open device path
- fd = open( full_devpath, O_RDONLY );
- if( fd < 0 ) {
-
+ }
+ // open device path
+ fd = open (full_devpath, O_RDONLY);
+ if (fd < 0)
+ {
+
rc = -errno;
-
- if( rc != -ENOENT ) {
- vdev_error("open('%s') rc = %d\n", full_devpath, rc );
- }
-
- free( full_devpath );
+
+ if (rc != -ENOENT)
+ {
+ vdev_error ("open('%s') rc = %d\n", full_devpath, rc);
+ }
+
+ free (full_devpath);
return rc;
- }
-
- nr = vdev_read_uninterrupted( fd, devbuf, 100 );
- if( nr < 0 ) {
-
+ }
+
+ nr = vdev_read_uninterrupted (fd, devbuf, 100);
+ if (nr < 0)
+ {
+
rc = nr;
- vdev_error("read('%s') rc = %d\n", full_devpath, rc );
-
- free( full_devpath );
- close( fd );
+ vdev_error ("read('%s') rc = %d\n", full_devpath, rc);
+
+ free (full_devpath);
+ close (fd);
return rc;
- }
-
- close( fd );
- free( full_devpath );
-
- rc = vdev_linux_sysfs_parse_device_nums( devbuf, major, minor );
-
- if( rc != 0 ) {
-
- vdev_error("Failed to parse '%s'\n", devbuf );
+ }
+
+ close (fd);
+ free (full_devpath);
+
+ rc = vdev_linux_sysfs_parse_device_nums (devbuf, major, minor);
+
+ if (rc != 0)
+ {
+
+ vdev_error ("Failed to parse '%s'\n", devbuf);
rc = -EIO;
- }
-
- return rc;
+ }
+
+ return rc;
}
// read the kernel-given device subsystem from sysfs
// return 0 on success, and set *subsystem
// return -ENOMEM on OOM
// return negative on readlink failure
-static int vdev_linux_sysfs_read_subsystem( struct vdev_linux_context* ctx, char const* devpath, char** subsystem ) {
-
- int rc = 0;
- char linkpath[PATH_MAX+1];
- size_t linkpath_len = PATH_MAX;
- char* subsystem_path = NULL;
-
- memset( linkpath, 0, PATH_MAX+1 );
-
- subsystem_path = vdev_linux_sysfs_fullpath( ctx->sysfs_mountpoint, devpath, "subsystem" );
- if( subsystem_path == NULL ) {
+static int
+vdev_linux_sysfs_read_subsystem (struct vdev_linux_context *ctx,
+ char const *devpath, char **subsystem)
+{
+
+ int rc = 0;
+ char linkpath[PATH_MAX + 1];
+ size_t linkpath_len = PATH_MAX;
+ char *subsystem_path = NULL;
+
+ memset (linkpath, 0, PATH_MAX + 1);
+
+ subsystem_path =
+ vdev_linux_sysfs_fullpath (ctx->sysfs_mountpoint, devpath, "subsystem");
+ if (subsystem_path == NULL)
+ {
return -ENOMEM;
- }
-
- rc = readlink( subsystem_path, linkpath, linkpath_len );
- if( rc < 0 ) {
-
+ }
+
+ rc = readlink (subsystem_path, linkpath, linkpath_len);
+ if (rc < 0)
+ {
+
rc = -errno;
- vdev_error("readlink('%s') rc = %d\n", subsystem_path, rc );
- free( subsystem_path );
+ vdev_error ("readlink('%s') rc = %d\n", subsystem_path, rc);
+ free (subsystem_path);
return rc;
- }
-
- free( subsystem_path );
-
- *subsystem = vdev_basename( linkpath, NULL );
- if( *subsystem == NULL ) {
-
+ }
+
+ free (subsystem_path);
+
+ *subsystem = vdev_basename (linkpath, NULL);
+ if (*subsystem == NULL)
+ {
+
return -ENOMEM;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// print a uevent, either with debugging or error loglevels
-static int vdev_linux_log_uevent( char const* uevent_buf, size_t uevent_buf_len, bool debug ) {
-
- for( unsigned int i = 0; i < uevent_buf_len; ) {
-
- if( debug ) {
- vdev_debug("uevent '%s'\n", uevent_buf + i );
- }
- else {
- vdev_error("uevent '%s'\n", uevent_buf + i );
- }
-
- i += strlen(uevent_buf + i) + 1;
- }
-
- return 0;
+static int
+vdev_linux_log_uevent (char const *uevent_buf, size_t uevent_buf_len,
+ bool debug)
+{
+
+ for (unsigned int i = 0; i < uevent_buf_len;)
+ {
+
+ if (debug)
+ {
+ vdev_debug ("uevent '%s'\n", uevent_buf + i);
+ }
+ else
+ {
+ vdev_error ("uevent '%s'\n", uevent_buf + i);
+ }
+
+ i += strlen (uevent_buf + i) + 1;
+ }
+
+ return 0;
}
#define vdev_linux_debug_uevent( uevent_buf, uevent_buf_len ) vdev_linux_log_uevent( uevent_buf, uevent_buf_len, true )
@@ -203,420 +236,464 @@ static int vdev_linux_log_uevent( char const* uevent_buf, size_t uevent_buf_len,
// parse a uevent, and use the information to fill in a device request.
// nlbuf must be a contiguous concatenation of null-terminated KEY=VALUE strings.
// return 0 on success
-static int vdev_linux_parse_request( struct vdev_linux_context* ctx, struct vdev_device_request* vreq, char* nlbuf, ssize_t buflen ) {
-
- char* buf = nlbuf;
- char* key = NULL;
- char* value = NULL;
- int offset = 0;
- int rc = 0;
- unsigned int major = 0;
- unsigned int minor = 0;
- bool have_major = false;
- bool have_minor = false;
- mode_t dev_mode = 0;
- int line_count = 0;
- bool not_param = false; // if set to true, add as an OS-specific parameter to the vreq
-
- char* devpath = NULL; // sysfs devpath
- char* subsystem = NULL; // sysfs subsystem
- char* devname = (char*)VDEV_DEVICE_PATH_UNKNOWN; // DEVNAME from uevent
-
- vdev_device_request_t reqtype = VDEV_DEVICE_INVALID;
-
- vdev_debug("%p: uevent buffer\n", vreq );
- vdev_linux_debug_uevent( nlbuf, buflen );
-
- // sanity check: if the first line is $action@$devpath, then skip it (since the information
- // contained in the uevent will encode the very same bits of information)
- if( strchr(buf, '@') != NULL ) {
-
+static int
+vdev_linux_parse_request (struct vdev_linux_context *ctx,
+ struct vdev_device_request *vreq,
+ char *nlbuf, ssize_t buflen)
+{
+
+ char *buf = nlbuf;
+ char *key = NULL;
+ char *value = NULL;
+ int offset = 0;
+ int rc = 0;
+ unsigned int major = 0;
+ unsigned int minor = 0;
+ bool have_major = false;
+ bool have_minor = false;
+ mode_t dev_mode = 0;
+ int line_count = 0;
+ bool not_param = false; // if set to true, add as an OS-specific parameter to the vreq
+
+ char *devpath = NULL; // sysfs devpath
+ char *subsystem = NULL; // sysfs subsystem
+ char *devname = (char *) VDEV_DEVICE_PATH_UNKNOWN; // DEVNAME from uevent
+
+ vdev_device_request_t reqtype = VDEV_DEVICE_INVALID;
+
+ vdev_debug ("%p: uevent buffer\n", vreq);
+ vdev_linux_debug_uevent (nlbuf, buflen);
+
+ // sanity check: if the first line is $action@$devpath, then skip it (since the information
+ // contained in the uevent will encode the very same bits of information)
+ if (strchr (buf, '@') != NULL)
+ {
+
// advance to the next line
- offset += strlen(buf) + 1;
- }
-
- // get key/value pairs
- while( offset < buflen ) {
-
+ offset += strlen (buf) + 1;
+ }
+ // get key/value pairs
+ while (offset < buflen)
+ {
+
line_count++;
not_param = false;
-
- rc = vdev_keyvalue_next( buf + offset, &key, &value );
-
- if( rc < 0 ) {
-
- vdev_error("Invalid line %d (byte %d): '%s'\n", line_count, offset, buf + offset );
- vdev_linux_error_uevent( nlbuf, buflen );
-
- return -EINVAL;
- }
-
- offset += rc + 1; // count the \0 at the end
+
+ rc = vdev_keyvalue_next (buf + offset, &key, &value);
+
+ if (rc < 0)
+ {
+
+ vdev_error ("Invalid line %d (byte %d): '%s'\n",
+ line_count, offset, buf + offset);
+ vdev_linux_error_uevent (nlbuf, buflen);
+
+ return -EINVAL;
+ }
+
+ offset += rc + 1; // count the \0 at the end
rc = 0;
-
+
// is this the action to take?
- if( strcmp(key, "ACTION") == 0 ) {
-
- reqtype = vdev_linux_parse_device_request_type( value );
-
- if( reqtype == VDEV_DEVICE_INVALID ) {
-
- vdev_error("Invalid ACTION '%s'\n", value );
- vdev_linux_error_uevent( nlbuf, buflen );
-
- return -EINVAL;
- }
-
- vdev_device_request_set_type( vreq, reqtype );
-
- not_param = true;
- }
-
+ if (strcmp (key, "ACTION") == 0)
+ {
+
+ reqtype = vdev_linux_parse_device_request_type (value);
+
+ if (reqtype == VDEV_DEVICE_INVALID)
+ {
+
+ vdev_error ("Invalid ACTION '%s'\n", value);
+ vdev_linux_error_uevent (nlbuf, buflen);
+
+ return -EINVAL;
+ }
+
+ vdev_device_request_set_type (vreq, reqtype);
+
+ not_param = true;
+ }
// is this the sysfs device path?
- else if( strcmp(key, "DEVPATH") == 0 ) {
-
- devpath = value;
- }
-
+ else if (strcmp (key, "DEVPATH") == 0)
+ {
+
+ devpath = value;
+ }
// is this the devname?
- else if( strcmp(key, "DEVNAME") == 0 ) {
-
- devname = value;
- }
-
+ else if (strcmp (key, "DEVNAME") == 0)
+ {
+
+ devname = value;
+ }
// subsystem given?
- else if( strcmp(key, "SUBSYSTEM") == 0 ) {
-
- subsystem = vdev_strdup_or_null( value );
- }
-
+ else if (strcmp (key, "SUBSYSTEM") == 0)
+ {
+
+ subsystem = vdev_strdup_or_null (value);
+ }
// is this the major device number?
- else if( strcmp(key, "MAJOR") == 0 && !have_major ) {
-
- char* tmp = NULL;
- major = (int)strtol( value, &tmp, 10 );
-
- if( *tmp != '\0' ) {
-
- vdev_error("Invalid 'MAJOR' value '%s'\n", value);
- vdev_linux_error_uevent( nlbuf, buflen );
-
- return -EINVAL;
- }
-
- have_major = true;
- not_param = true;
- }
-
+ else if (strcmp (key, "MAJOR") == 0 && !have_major)
+ {
+
+ char *tmp = NULL;
+ major = (int) strtol (value, &tmp, 10);
+
+ if (*tmp != '\0')
+ {
+
+ vdev_error ("Invalid 'MAJOR' value '%s'\n", value);
+ vdev_linux_error_uevent (nlbuf, buflen);
+
+ return -EINVAL;
+ }
+
+ have_major = true;
+ not_param = true;
+ }
// is this the minor device number?
- else if( strcmp(key, "MINOR") == 0 && !have_minor ) {
-
- char* tmp = NULL;
- minor = (int)strtol( value, &tmp, 10 ) ;
-
- if( *tmp != '\0' ) {
-
- vdev_error("Invalid 'MINOR' value '%s'\n", value );
- vdev_linux_error_uevent( nlbuf, buflen );
-
- return -EINVAL;
- }
-
- have_minor = true;
- not_param = true;
- }
-
- if( !not_param ) {
-
- // add to OS params
- rc = vdev_device_request_add_param( vreq, key, value );
- if( rc != 0 ) {
-
- // could be OOM
- if( subsystem != NULL ) {
- free( subsystem );
- }
-
- return rc;
- }
- }
- }
-
- if( reqtype == VDEV_DEVICE_INVALID ) {
-
- vdev_error("%s", "No ACTION given\n");
- vdev_linux_error_uevent( nlbuf, buflen );
-
- if( subsystem != NULL ) {
- free( subsystem );
- }
-
+ else if (strcmp (key, "MINOR") == 0 && !have_minor)
+ {
+
+ char *tmp = NULL;
+ minor = (int) strtol (value, &tmp, 10);
+
+ if (*tmp != '\0')
+ {
+
+ vdev_error ("Invalid 'MINOR' value '%s'\n", value);
+ vdev_linux_error_uevent (nlbuf, buflen);
+
+ return -EINVAL;
+ }
+
+ have_minor = true;
+ not_param = true;
+ }
+
+ if (!not_param)
+ {
+
+ // add to OS params
+ rc = vdev_device_request_add_param (vreq, key, value);
+ if (rc != 0)
+ {
+
+ // could be OOM
+ if (subsystem != NULL)
+ {
+ free (subsystem);
+ }
+
+ return rc;
+ }
+ }
+ }
+
+ if (reqtype == VDEV_DEVICE_INVALID)
+ {
+
+ vdev_error ("%s", "No ACTION given\n");
+ vdev_linux_error_uevent (nlbuf, buflen);
+
+ if (subsystem != NULL)
+ {
+ free (subsystem);
+ }
+
return -EINVAL;
- }
-
- if( (!have_major && have_minor) || (have_major && !have_minor) ) {
-
- vdev_error("Missing device information: major=%d, minor=%d\n", have_major, have_minor );
- vdev_linux_error_uevent( nlbuf, buflen );
-
- if( subsystem != NULL ) {
- free( subsystem );
- }
-
+ }
+
+ if ((!have_major && have_minor) || (have_major && !have_minor))
+ {
+
+ vdev_error ("Missing device information: major=%d, minor=%d\n",
+ have_major, have_minor);
+ vdev_linux_error_uevent (nlbuf, buflen);
+
+ if (subsystem != NULL)
+ {
+ free (subsystem);
+ }
+
return -EINVAL;
- }
-
- if( have_major && have_minor ) {
-
+ }
+
+ if (have_major && have_minor)
+ {
+
// explicit major and minor device numbers given
- vdev_device_request_set_dev( vreq, makedev(major, minor) );
- }
-
- if( devname != NULL ) {
-
+ vdev_device_request_set_dev (vreq, makedev (major, minor));
+ }
+
+ if (devname != NULL)
+ {
+
// use this as the device's path
- vdev_device_request_set_path( vreq, devname );
- }
-
- if( devpath != NULL ) {
-
+ vdev_device_request_set_path (vreq, devname);
+ }
+
+ if (devpath != NULL)
+ {
+
// get any remaining information from sysfs
// check major/minor?
- if( !have_major || !have_minor ) {
-
- // see if we have major/minor device numbers for this device...
- rc = vdev_linux_sysfs_read_dev_nums( ctx, devpath, &major, &minor );
-
- if( rc == 0 ) {
-
- // yup!
- vdev_device_request_set_dev( vreq, makedev(major, minor) );
-
- have_major = true;
- have_minor = true;
- }
- else {
-
- // it's okay to not have dev numbers
- rc = 0;
- }
- }
-
+ if (!have_major || !have_minor)
+ {
+
+ // see if we have major/minor device numbers for this device...
+ rc = vdev_linux_sysfs_read_dev_nums (ctx, devpath, &major, &minor);
+
+ if (rc == 0)
+ {
+
+ // yup!
+ vdev_device_request_set_dev (vreq, makedev (major, minor));
+
+ have_major = true;
+ have_minor = true;
+ }
+ else
+ {
+
+ // it's okay to not have dev numbers
+ rc = 0;
+ }
+ }
// subsystem?
- if( subsystem == NULL ) {
-
- // see if we have a subsystem
- rc = vdev_linux_sysfs_read_subsystem( ctx, devpath, &subsystem );
-
- if( rc == 0 ) {
-
- // yup!
- rc = vdev_device_request_add_param( vreq, "SUBSYSTEM", subsystem );
- if( rc != 0 ) {
-
- // OOM
- free( subsystem );
- return rc;
- }
- }
- else if( rc != -ENOMEM ) {
-
- // this is weird...
- vdev_warn("no subsystem found for '%s'\n", devpath );
- rc = 0;
- }
- }
- }
-
- if( have_major && have_minor ) {
-
- if( subsystem != NULL && strcasecmp(subsystem, "block") == 0 ) {
-
- // this is a block
- dev_mode = S_IFBLK;
- }
-
- else {
-
- // this is a character device--we have major/minor numbers
- dev_mode = S_IFCHR;
- }
-
- vdev_device_request_set_mode( vreq, dev_mode );
- }
-
- vdev_debug("subsystem = '%s', have_major=%d, major = %u, have_minor=%d, minor = %u, mode = %o\n", subsystem, have_major, major, have_minor, minor, dev_mode );
-
- if( subsystem != NULL ) {
- free( subsystem );
- }
-
- // tell helpers where /sys is mounted
- rc = vdev_device_request_add_param( vreq, "SYSFS_MOUNTPOINT", ctx->sysfs_mountpoint );
- if( rc != 0 ) {
-
+ if (subsystem == NULL)
+ {
+
+ // see if we have a subsystem
+ rc = vdev_linux_sysfs_read_subsystem (ctx, devpath, &subsystem);
+
+ if (rc == 0)
+ {
+
+ // yup!
+ rc = vdev_device_request_add_param (vreq,
+ "SUBSYSTEM", subsystem);
+ if (rc != 0)
+ {
+
+ // OOM
+ free (subsystem);
+ return rc;
+ }
+ }
+ else if (rc != -ENOMEM)
+ {
+
+ // this is weird...
+ vdev_warn ("no subsystem found for '%s'\n", devpath);
+ rc = 0;
+ }
+ }
+ }
+
+ if (have_major && have_minor)
+ {
+
+ if (subsystem != NULL && strcasecmp (subsystem, "block") == 0)
+ {
+
+ // this is a block
+ dev_mode = S_IFBLK;
+ }
+
+ else
+ {
+
+ // this is a character device--we have major/minor numbers
+ dev_mode = S_IFCHR;
+ }
+
+ vdev_device_request_set_mode (vreq, dev_mode);
+ }
+
+ vdev_debug
+ ("subsystem = '%s', have_major=%d, major = %u, have_minor=%d, minor = %u, mode = %o\n",
+ subsystem, have_major, major, have_minor, minor, dev_mode);
+
+ if (subsystem != NULL)
+ {
+ free (subsystem);
+ }
+ // tell helpers where /sys is mounted
+ rc = vdev_device_request_add_param (vreq, "SYSFS_MOUNTPOINT",
+ ctx->sysfs_mountpoint);
+ if (rc != 0)
+ {
+
// OOM
return rc;
- }
-
- return rc;
-}
+ }
+ return rc;
+}
// yield the next device event
// return 0 on success
// return 1 if there are no more devices
// return -EAGAIN if vdev should try to get this device again
// return -errno on failure to poll for devices or read the next device packet.
-int vdev_os_next_device( struct vdev_device_request* vreq, void* cls ) {
-
- int rc = 0;
- struct vdev_linux_context* ctx = (struct vdev_linux_context*)cls;
- char buf[VDEV_LINUX_NETLINK_BUF_MAX];
- ssize_t len = 0;
-
- char cbuf[CMSG_SPACE(sizeof(struct ucred))];
- struct cmsghdr *chdr = NULL;
- struct ucred *cred = NULL;
- struct msghdr hdr;
- struct iovec iov;
- struct sockaddr_nl cnls;
-
- pthread_mutex_lock( &ctx->initial_requests_lock );
-
- // do we have initial requests?
- if( ctx->initial_requests != NULL ) {
-
+int
+vdev_os_next_device (struct vdev_device_request *vreq, void *cls)
+{
+
+ int rc = 0;
+ struct vdev_linux_context *ctx = (struct vdev_linux_context *) cls;
+ char buf[VDEV_LINUX_NETLINK_BUF_MAX];
+ ssize_t len = 0;
+
+ char cbuf[CMSG_SPACE (sizeof (struct ucred))];
+ struct cmsghdr *chdr = NULL;
+ struct ucred *cred = NULL;
+ struct msghdr hdr;
+ struct iovec iov;
+ struct sockaddr_nl cnls;
+
+ pthread_mutex_lock (&ctx->initial_requests_lock);
+
+ // do we have initial requests?
+ if (ctx->initial_requests != NULL)
+ {
+
// next request
- struct vdev_device_request* req = ctx->initial_requests;
-
+ struct vdev_device_request *req = ctx->initial_requests;
+
// consume
ctx->initial_requests = ctx->initial_requests->next;
-
- memcpy( vreq, req, sizeof(struct vdev_device_request) );
- free( req );
-
- pthread_mutex_unlock( &ctx->initial_requests_lock );
-
+
+ memcpy (vreq, req, sizeof (struct vdev_device_request));
+ free (req);
+
+ pthread_mutex_unlock (&ctx->initial_requests_lock);
+
// was that the last of them?
- if( ctx->initial_requests == NULL ) {
-
- // tell vdevd that we've finished coldplug processing
- vdev_os_context_signal_coldplug_finished( ctx->os_ctx );
- }
-
+ if (ctx->initial_requests == NULL)
+ {
+
+ // tell vdevd that we've finished coldplug processing
+ vdev_os_context_signal_coldplug_finished (ctx->os_ctx);
+ }
+
return 0;
- }
- else if( ctx->os_ctx->coldplug_only ) {
-
+ }
+ else if (ctx->os_ctx->coldplug_only)
+ {
+
// out of coldplug requests; die
- pthread_mutex_unlock( &ctx->initial_requests_lock );
+ pthread_mutex_unlock (&ctx->initial_requests_lock);
return 1;
- }
- else {
-
- pthread_mutex_unlock( &ctx->initial_requests_lock );
- }
-
- memset(&hdr, 0, sizeof(struct msghdr));
-
- // next event (wait forever)
- // NOTE: this is a cancellation point!
- rc = poll( &ctx->pfd, 1, -1 );
-
- if( rc < 0 ) {
-
+ }
+ else
+ {
+
+ pthread_mutex_unlock (&ctx->initial_requests_lock);
+ }
+
+ memset (&hdr, 0, sizeof (struct msghdr));
+
+ // next event (wait forever)
+ // NOTE: this is a cancellation point!
+ rc = poll (&ctx->pfd, 1, -1);
+
+ if (rc < 0)
+ {
+
rc = -errno;
-
- if( rc == -EINTR ) {
- // try again
- return -EAGAIN;
- }
-
- vdev_error("FATAL: poll(%d) rc = %d\n", ctx->pfd.fd, rc );
-
+
+ if (rc == -EINTR)
+ {
+ // try again
+ return -EAGAIN;
+ }
+
+ vdev_error ("FATAL: poll(%d) rc = %d\n", ctx->pfd.fd, rc);
+
return rc;
- }
-
- // get the event
- iov.iov_base = buf;
- iov.iov_len = VDEV_LINUX_NETLINK_BUF_MAX;
-
- hdr.msg_iov = &iov;
- hdr.msg_iovlen = 1;
-
- // get control-plane messages
- hdr.msg_control = cbuf;
- hdr.msg_controllen = sizeof(cbuf);
-
- hdr.msg_name = &cnls;
- hdr.msg_namelen = sizeof(cnls);
-
- // get the event
- len = recvmsg( ctx->pfd.fd, &hdr, 0 );
- if( len < 0 ) {
-
+ }
+ // get the event
+ iov.iov_base = buf;
+ iov.iov_len = VDEV_LINUX_NETLINK_BUF_MAX;
+
+ hdr.msg_iov = &iov;
+ hdr.msg_iovlen = 1;
+
+ // get control-plane messages
+ hdr.msg_control = cbuf;
+ hdr.msg_controllen = sizeof (cbuf);
+
+ hdr.msg_name = &cnls;
+ hdr.msg_namelen = sizeof (cnls);
+
+ // get the event
+ len = recvmsg (ctx->pfd.fd, &hdr, 0);
+ if (len < 0)
+ {
+
rc = -errno;
- vdev_error("FATAL: recvmsg(%d) rc = %d\n", ctx->pfd.fd, rc );
-
+ vdev_error ("FATAL: recvmsg(%d) rc = %d\n", ctx->pfd.fd, rc);
+
return rc;
- }
-
- // big enough?
- if( len < 32 || len >= VDEV_LINUX_NETLINK_BUF_MAX ) {
-
- vdev_error("Netlink message is %zd bytes; ignoring...\n", len );
+ }
+ // big enough?
+ if (len < 32 || len >= VDEV_LINUX_NETLINK_BUF_MAX)
+ {
+
+ vdev_error ("Netlink message is %zd bytes; ignoring...\n", len);
return -EAGAIN;
- }
-
- // control message, for credentials
- chdr = CMSG_FIRSTHDR( &hdr );
- if( chdr == NULL || chdr->cmsg_type != SCM_CREDENTIALS ) {
-
- vdev_error("%s", "Netlink message has no credentials\n");
+ }
+ // control message, for credentials
+ chdr = CMSG_FIRSTHDR (&hdr);
+ if (chdr == NULL || chdr->cmsg_type != SCM_CREDENTIALS)
+ {
+
+ vdev_error ("%s", "Netlink message has no credentials\n");
return -EAGAIN;
- }
-
- // get the credentials
- cred = (struct ucred *)CMSG_DATA(chdr);
-
- // if not root, ignore
- if( cred->uid != 0 ) {
-
- vdev_error("Ignoring message from non-root ID %d\n", cred->uid );
+ }
+ // get the credentials
+ cred = (struct ucred *) CMSG_DATA (chdr);
+
+ // if not root, ignore
+ if (cred->uid != 0)
+ {
+
+ vdev_error ("Ignoring message from non-root ID %d\n", cred->uid);
return -EAGAIN;
- }
-
- // if udev, ignore
- if( memcmp( buf, VDEV_LINUX_NETLINK_UDEV_HEADER, VDEV_LINUX_NETLINK_UDEV_HEADER_LEN ) == 0 ) {
-
+ }
+ // if udev, ignore
+ if (memcmp
+ (buf, VDEV_LINUX_NETLINK_UDEV_HEADER,
+ VDEV_LINUX_NETLINK_UDEV_HEADER_LEN) == 0)
+ {
+
// message from udev; ignore
- vdev_warn("%s", "Ignoring libudev message\n");
+ vdev_warn ("%s", "Ignoring libudev message\n");
return -EAGAIN;
- }
-
- // kernel messages don't come from userspace
- if( cnls.nl_pid > 0 ) {
-
+ }
+ // kernel messages don't come from userspace
+ if (cnls.nl_pid > 0)
+ {
+
// from userspace???
- vdev_warn("Ignoring message from PID %d\n", (int)cnls.nl_pid );
+ vdev_warn ("Ignoring message from PID %d\n", (int) cnls.nl_pid);
return -EAGAIN;
- }
-
- // parse the event buffer
- vdev_debug("%p from netlink\n", vreq );
- rc = vdev_linux_parse_request( ctx, vreq, buf, len );
-
- if( rc != 0 ) {
-
- vdev_error("vdev_linux_parse_request rc = %d\n", rc );
-
+ }
+ // parse the event buffer
+ vdev_debug ("%p from netlink\n", vreq);
+ rc = vdev_linux_parse_request (ctx, vreq, buf, len);
+
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_linux_parse_request rc = %d\n", rc);
+
return -EAGAIN;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// find sysfs mountpoint in /proc/mounts
// this is apparently superfluous (it *should* be mounted at /sys), but you never know.
@@ -626,56 +703,63 @@ int vdev_os_next_device( struct vdev_device_request* vreq, void* cls ) {
// return -ENOMEM if the buffer isn't big enough
// return -EINVAL if somehow we failed to parse a mount entry
// return negative for some other errors (like access permission failures, or /proc not mounted)
-static int vdev_linux_find_sysfs_mountpoint( char* mountpoint, size_t mountpoint_len ) {
-
- FILE* f = NULL;
- int rc = 0;
-
- char mntbuf[4096];
- struct mntent ment_buf;
- struct mntent* ment_ptr = NULL;
- int ent_count = 1;
- bool found = false;
-
- f = fopen( "/proc/mounts", "r" );
- if( f == NULL ) {
-
+static int
+vdev_linux_find_sysfs_mountpoint (char *mountpoint, size_t mountpoint_len)
+{
+
+ FILE *f = NULL;
+ int rc = 0;
+
+ char mntbuf[4096];
+ struct mntent ment_buf;
+ struct mntent *ment_ptr = NULL;
+ int ent_count = 1;
+ bool found = false;
+
+ f = fopen ("/proc/mounts", "r");
+ if (f == NULL)
+ {
+
rc = -errno;
- fprintf(stderr, "Failed to open /proc/mounts, rc = %d\n", rc );
+ fprintf (stderr, "Failed to open /proc/mounts, rc = %d\n", rc);
return rc;
- }
-
- // scan for sysfs mount type
- while( 1 ) {
-
- ment_ptr = getmntent_r( f, &ment_buf, mntbuf, 4096 );
- if( ment_ptr == NULL ) {
-
- vdev_error("Failed on processing entry #%d of /proc/mounts\n", ent_count );
- rc = -EINVAL;
- break;
- }
-
- if( strcmp( ment_ptr->mnt_type, "sysfs" ) == 0 ) {
-
- // found!
- strncpy( mountpoint, ment_ptr->mnt_dir, mountpoint_len - 1 );
- found = true;
- rc = 0;
- break;
- }
-
+ }
+ // scan for sysfs mount type
+ while (1)
+ {
+
+ ment_ptr = getmntent_r (f, &ment_buf, mntbuf, 4096);
+ if (ment_ptr == NULL)
+ {
+
+ vdev_error
+ ("Failed on processing entry #%d of /proc/mounts\n", ent_count);
+ rc = -EINVAL;
+ break;
+ }
+
+ if (strcmp (ment_ptr->mnt_type, "sysfs") == 0)
+ {
+
+ // found!
+ strncpy (mountpoint, ment_ptr->mnt_dir, mountpoint_len - 1);
+ found = true;
+ rc = 0;
+ break;
+ }
+
ent_count++;
- }
-
- fclose( f );
-
- if( rc == 0 && !found ) {
- fprintf(stderr, "Failed to find mounted sysfs filesystem\n");
+ }
+
+ fclose (f);
+
+ if (rc == 0 && !found)
+ {
+ fprintf (stderr, "Failed to find mounted sysfs filesystem\n");
return -ENOSYS;
- }
-
- return rc;
+ }
+
+ return rc;
}
// get a uevent from a uevent file
@@ -684,114 +768,133 @@ static int vdev_linux_find_sysfs_mountpoint( char* mountpoint, size_t mountpoint
// return 0 on success
// return -ENOMEM on OOM
// return -errno on failure to stat or read
-static int vdev_linux_sysfs_read_uevent( char const* fp_uevent, char** ret_uevent_buf, size_t* ret_uevent_len ) {
-
- int rc = 0;
- struct stat sb;
- char* uevent_buf = NULL;
- size_t uevent_buf_len = 0;
- size_t uevent_len = 0;
-
- // get uevent size
- rc = stat( fp_uevent, &sb );
- if( rc != 0 ) {
-
+static int
+vdev_linux_sysfs_read_uevent (char const *fp_uevent,
+ char **ret_uevent_buf, size_t * ret_uevent_len)
+{
+
+ int rc = 0;
+ struct stat sb;
+ char *uevent_buf = NULL;
+ size_t uevent_buf_len = 0;
+ size_t uevent_len = 0;
+
+ // get uevent size
+ rc = stat (fp_uevent, &sb);
+ if (rc != 0)
+ {
+
rc = -errno;
-
- vdev_error("stat('%s') rc = %d\n", fp_uevent, rc );
-
+
+ vdev_error ("stat('%s') rc = %d\n", fp_uevent, rc);
+
return rc;
- }
- else {
-
+ }
+ else
+ {
+
uevent_buf_len = sb.st_size;
- }
-
- // read the uevent
- if( fp_uevent != NULL ) {
-
- uevent_buf = VDEV_CALLOC( char, uevent_buf_len );
- if( uevent_buf == NULL ) {
-
- return -ENOMEM;
- }
-
- rc = vdev_read_file( fp_uevent, uevent_buf, uevent_buf_len );
- if( rc != 0 ) {
-
- // failed in this
- vdev_error("vdev_read_file('%s') rc = %d\n", fp_uevent, rc );
- free( uevent_buf );
- }
- else {
-
- for( unsigned int i = 0; i < uevent_buf_len; i++ ) {
-
- if( uevent_buf[i] == '\n' ) {
-
- uevent_buf[i] = '\0';
- }
- }
-
- // NOTE: the stat size is an upper-bound. Find the exact number of bytes.
- for( uevent_len = 0; uevent_len < uevent_buf_len; ) {
-
- if( *(uevent_buf + uevent_len) == '\0' ) {
- break;
- }
-
- uevent_len += strlen( uevent_buf + uevent_len ) + 1;
- }
-
- *ret_uevent_buf = uevent_buf;
- *ret_uevent_len = uevent_len;
- }
- }
-
- return rc;
-}
+ }
+
+ // read the uevent
+ if (fp_uevent != NULL)
+ {
+
+ uevent_buf = VDEV_CALLOC (char, uevent_buf_len);
+ if (uevent_buf == NULL)
+ {
+
+ return -ENOMEM;
+ }
+
+ rc = vdev_read_file (fp_uevent, uevent_buf, uevent_buf_len);
+ if (rc != 0)
+ {
+
+ // failed in this
+ vdev_error ("vdev_read_file('%s') rc = %d\n", fp_uevent, rc);
+ free (uevent_buf);
+ }
+ else
+ {
+
+ for (unsigned int i = 0; i < uevent_buf_len; i++)
+ {
+
+ if (uevent_buf[i] == '\n')
+ {
+
+ uevent_buf[i] = '\0';
+ }
+ }
+
+ // NOTE: the stat size is an upper-bound. Find the exact number of bytes.
+ for (uevent_len = 0; uevent_len < uevent_buf_len;)
+ {
+
+ if (*(uevent_buf + uevent_len) == '\0')
+ {
+ break;
+ }
+ uevent_len += strlen (uevent_buf + uevent_len) + 1;
+ }
+
+ *ret_uevent_buf = uevent_buf;
+ *ret_uevent_len = uevent_len;
+ }
+ }
+
+ return rc;
+}
// append a key/value pair to a uevent buffer
// return 0 on success
// return -ENOMEM on OOM
-static int vdev_linux_uevent_append( char** ret_uevent_buf, size_t* ret_uevent_buf_len, char const* key, char const* value ) {
-
- char* tmp = NULL;
- char* uevent_buf = *ret_uevent_buf;
- size_t uevent_buf_len = *ret_uevent_buf_len;
-
- // add it to the uevent buffer, so we can parse it like a normal uevent
- tmp = (char*)realloc( uevent_buf, uevent_buf_len + 1 + strlen(key) + 1 + strlen(value) + 1 );
- if( tmp == NULL ) {
-
+static int
+vdev_linux_uevent_append (char **ret_uevent_buf,
+ size_t * ret_uevent_buf_len,
+ char const *key, char const *value)
+{
+
+ char *tmp = NULL;
+ char *uevent_buf = *ret_uevent_buf;
+ size_t uevent_buf_len = *ret_uevent_buf_len;
+
+ // add it to the uevent buffer, so we can parse it like a normal uevent
+ tmp =
+ (char *) realloc (uevent_buf,
+ uevent_buf_len + 1 + strlen (key) + 1 +
+ strlen (value) + 1);
+ if (tmp == NULL)
+ {
+
return -ENOMEM;
- }
-
- uevent_buf = tmp;
-
- // add key
- memcpy( uevent_buf + uevent_buf_len, key, strlen(key) );
- uevent_buf_len += strlen(key);
-
- // add '='
- *(uevent_buf + uevent_buf_len) = '=';
- uevent_buf_len ++;
-
- // add value
- memcpy( uevent_buf + uevent_buf_len, value, strlen(value) );
- uevent_buf_len += strlen(value);
-
- // NULL-terminate
- *(uevent_buf + uevent_buf_len) = '\0';
- uevent_buf_len ++;
-
- *ret_uevent_buf = uevent_buf;
- *ret_uevent_buf_len = uevent_buf_len;
-
- return 0;
-}
+ }
+
+ uevent_buf = tmp;
+
+ // add key
+ memcpy (uevent_buf + uevent_buf_len, key, strlen (key));
+ uevent_buf_len += strlen (key);
+
+ // add '='
+ *(uevent_buf + uevent_buf_len) = '=';
+ uevent_buf_len++;
+
+ // add value
+ memcpy (uevent_buf + uevent_buf_len, value, strlen (value));
+ uevent_buf_len += strlen (value);
+ // NULL-terminate
+ *(uevent_buf + uevent_buf_len) = '\0';
+ uevent_buf_len++;
+
+ *ret_uevent_buf = uevent_buf;
+ *ret_uevent_buf_len = uevent_buf_len;
+
+ return 0;
+}
// register a device from sysfs, given the path to its uevent file.
// that is, read the uevent file, generate a device request, and add it to the initial_requests list in the ctx.
@@ -799,682 +902,771 @@ static int vdev_linux_uevent_append( char** ret_uevent_buf, size_t* ret_uevent_b
// return 0 on success
// return -ENOMEM on OOM
// return negative on error.
-static int vdev_linux_sysfs_register_device( struct vdev_linux_context* ctx, char const* fp_uevent ) {
-
- int rc = 0;
- struct stat sb;
- char* uevent_buf = NULL;
- size_t uevent_buf_len = 0;
- char* full_devpath = NULL;
- char* devpath = NULL;
- char* devname = NULL;
- char* delim = NULL;
-
- // extract the devpath from the uevent path
- full_devpath = vdev_dirname( fp_uevent, NULL );
- if( full_devpath == NULL ) {
+static int
+vdev_linux_sysfs_register_device (struct vdev_linux_context *ctx,
+ char const *fp_uevent)
+{
+
+ int rc = 0;
+ struct stat sb;
+ char *uevent_buf = NULL;
+ size_t uevent_buf_len = 0;
+ char *full_devpath = NULL;
+ char *devpath = NULL;
+ char *devname = NULL;
+ char *delim = NULL;
+
+ // extract the devpath from the uevent path
+ full_devpath = vdev_dirname (fp_uevent, NULL);
+ if (full_devpath == NULL)
+ {
return -ENOMEM;
- }
-
- // get uevent
- rc = vdev_linux_sysfs_read_uevent( fp_uevent, &uevent_buf, &uevent_buf_len );
- if( rc != 0 ) {
-
- vdev_error("vdev_linux_sysfs_read_uevent('%s') rc = %d\n", fp_uevent, rc );
-
- free( full_devpath );
+ }
+ // get uevent
+ rc = vdev_linux_sysfs_read_uevent (fp_uevent, &uevent_buf, &uevent_buf_len);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_linux_sysfs_read_uevent('%s') rc = %d\n",
+ fp_uevent, rc);
+
+ free (full_devpath);
return rc;
- }
-
- if( uevent_buf_len == 0 ) {
-
+ }
+
+ if (uevent_buf_len == 0)
+ {
+
// no messages to be had
- vdev_debug("Empty uevent file at '%s'\n", fp_uevent );
-
- free( full_devpath );
- free( uevent_buf );
+ vdev_debug ("Empty uevent file at '%s'\n", fp_uevent);
+
+ free (full_devpath);
+ free (uevent_buf);
return 0;
- }
-
- // truncate to /devices
- devpath = full_devpath + strlen( ctx->sysfs_mountpoint );
-
- // we're adding this, so make ACTION=add
- rc = vdev_linux_uevent_append( &uevent_buf, &uevent_buf_len, "ACTION", "add" );
- if( rc != 0 ) {
-
- vdev_error("vdev_linux_uevent_append('%s=%s') rc = %d\n", "ACTION", "add", rc );
-
- free( uevent_buf );
- free( full_devpath );
-
+ }
+ // truncate to /devices
+ devpath = full_devpath + strlen (ctx->sysfs_mountpoint);
+
+ // we're adding this, so make ACTION=add
+ rc = vdev_linux_uevent_append (&uevent_buf, &uevent_buf_len, "ACTION",
+ "add");
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_linux_uevent_append('%s=%s') rc = %d\n",
+ "ACTION", "add", rc);
+
+ free (uevent_buf);
+ free (full_devpath);
+
return rc;
- }
-
-
- // see if the uevent has a devname. Use that over our devname, if need be
- devname = strstr( uevent_buf, "DEVNAME=" );
- if( devname != NULL ) {
-
+ }
+
+ // see if the uevent has a devname. Use that over our devname, if need be
+ devname = strstr (uevent_buf, "DEVNAME=");
+ if (devname != NULL)
+ {
+
// have a devname!
- devname += strlen("DEVNAME=") + 1;
-
- size_t devname_len = strcspn( devname, "\n\0" );
- if( devname_len > 0 ) {
-
- char* tmp = VDEV_CALLOC( char, devname_len + 1 );
- if( tmp == NULL ) {
-
- free( uevent_buf );
- free( full_devpath );
-
- return -ENOMEM;
- }
-
- strncpy( tmp, devname, devname_len );
-
- devname = tmp;
- }
- }
-
- // include the device path
- rc = vdev_linux_uevent_append( &uevent_buf, &uevent_buf_len, "DEVPATH", devpath );
- if( rc != 0 ) {
-
- vdev_error("vdev_linux_uevent_append('%s=%s') rc = %d\n", "DEVPATH", devpath, rc );
-
- free( uevent_buf );
- free( full_devpath );
- free( devname );
+ devname += strlen ("DEVNAME=") + 1;
+
+ size_t devname_len = strcspn (devname, "\n\0");
+ if (devname_len > 0)
+ {
+
+ char *tmp = VDEV_CALLOC (char, devname_len + 1);
+ if (tmp == NULL)
+ {
+
+ free (uevent_buf);
+ free (full_devpath);
+
+ return -ENOMEM;
+ }
+
+ strncpy (tmp, devname, devname_len);
+
+ devname = tmp;
+ }
+ }
+ // include the device path
+ rc = vdev_linux_uevent_append (&uevent_buf, &uevent_buf_len, "DEVPATH",
+ devpath);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_linux_uevent_append('%s=%s') rc = %d\n",
+ "DEVPATH", devpath, rc);
+
+ free (uevent_buf);
+ free (full_devpath);
+ free (devname);
return rc;
- }
-
-
- // make the device request
- struct vdev_device_request* vreq = VDEV_CALLOC( struct vdev_device_request, 1 );
- if( vreq == NULL ) {
-
- free( full_devpath );
- free( uevent_buf );
-
+ }
+
+ // make the device request
+ struct vdev_device_request *vreq =
+ VDEV_CALLOC (struct vdev_device_request, 1);
+ if (vreq == NULL)
+ {
+
+ free (full_devpath);
+ free (uevent_buf);
+
return -ENOMEM;
- }
-
- // build up the request
- vdev_device_request_init( vreq, ctx->os_ctx->state, VDEV_DEVICE_INVALID, devname );
-
- // parse from our uevent
- rc = vdev_linux_parse_request( ctx, vreq, uevent_buf, uevent_buf_len );
-
- free( uevent_buf );
- uevent_buf = NULL;
-
- if( rc != 0 ) {
-
- vdev_error("vdev_linux_parse_request('%s') rc = %d\n", fp_uevent, rc );
-
- free( full_devpath );
- free( devname );
-
+ }
+ // build up the request
+ vdev_device_request_init (vreq, ctx->os_ctx->state, VDEV_DEVICE_INVALID,
+ devname);
+
+ // parse from our uevent
+ rc = vdev_linux_parse_request (ctx, vreq, uevent_buf, uevent_buf_len);
+
+ free (uevent_buf);
+ uevent_buf = NULL;
+
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_linux_parse_request('%s') rc = %d\n", fp_uevent, rc);
+
+ free (full_devpath);
+ free (devname);
+
return rc;
- }
-
- free( full_devpath );
- free( devname );
-
- pthread_mutex_lock( &ctx->initial_requests_lock );
-
- // append
- if( ctx->initial_requests == NULL ) {
-
+ }
+
+ free (full_devpath);
+ free (devname);
+
+ pthread_mutex_lock (&ctx->initial_requests_lock);
+
+ // append
+ if (ctx->initial_requests == NULL)
+ {
+
ctx->initial_requests = vreq;
ctx->initial_requests_tail = vreq;
- }
- else {
-
+ }
+ else
+ {
+
ctx->initial_requests_tail->next = vreq;
ctx->initial_requests_tail = vreq;
- }
-
- vreq->next = NULL;
-
- pthread_mutex_unlock( &ctx->initial_requests_lock );
-
- return rc;
-}
+ }
+ vreq->next = NULL;
+
+ pthread_mutex_unlock (&ctx->initial_requests_lock);
+
+ return rc;
+}
// scan structure for finding new device directories, and signalling whether or not
// the given directory has a uevent.
-struct vdev_linux_sysfs_scan_context {
-
- char* uevent_path;
- struct sglib_cstr_vector* device_frontier;
+struct vdev_linux_sysfs_scan_context
+{
+
+ char *uevent_path;
+ struct sglib_cstr_vector *device_frontier;
};
// scan a directory in /sys/devices directory, to find its child directories
// return 0 on success
// return -ENOMEM on OOM
// return -errno on failure to stat
-static int vdev_linux_sysfs_scan_device_directory( char const* fp, void* cls ) {
-
- struct vdev_linux_sysfs_scan_context* scan_ctx = (struct vdev_linux_sysfs_scan_context*)cls;
-
- struct sglib_cstr_vector* device_frontier = scan_ctx->device_frontier;
-
- struct stat sb;
- int rc = 0;
- char* fp_base = NULL;
- char* fp_dup = NULL;
-
- fp_base = rindex( fp, '/' );
-
- if( fp_base == NULL ) {
+static int
+vdev_linux_sysfs_scan_device_directory (char const *fp, void *cls)
+{
+
+ struct vdev_linux_sysfs_scan_context *scan_ctx =
+ (struct vdev_linux_sysfs_scan_context *) cls;
+
+ struct sglib_cstr_vector *device_frontier = scan_ctx->device_frontier;
+
+ struct stat sb;
+ int rc = 0;
+ char *fp_base = NULL;
+ char *fp_dup = NULL;
+
+ fp_base = rindex (fp, '/');
+
+ if (fp_base == NULL)
+ {
return 0;
- }
-
- // skip . and ..
- if( strcmp( fp_base, "/." ) == 0 || strcmp( fp_base, "/.." ) == 0 ) {
+ }
+ // skip . and ..
+ if (strcmp (fp_base, "/.") == 0 || strcmp (fp_base, "/..") == 0)
+ {
return 0;
- }
-
- // add directories
- rc = lstat( fp, &sb );
- if( rc != 0 ) {
-
+ }
+ // add directories
+ rc = lstat (fp, &sb);
+ if (rc != 0)
+ {
+
rc = -errno;
- vdev_error("lstat('%s') rc = %d\n", fp, rc );
+ vdev_error ("lstat('%s') rc = %d\n", fp, rc);
return rc;
- }
-
- if( !S_ISDIR( sb.st_mode ) && strcmp( fp_base, "/uevent" ) != 0 ) {
-
+ }
+
+ if (!S_ISDIR (sb.st_mode) && strcmp (fp_base, "/uevent") != 0)
+ {
+
// not a directory, and not a uevent
return 0;
- }
-
- fp_dup = vdev_strdup_or_null( fp );
- if( fp_dup == NULL ) {
-
+ }
+
+ fp_dup = vdev_strdup_or_null (fp);
+ if (fp_dup == NULL)
+ {
+
return -ENOMEM;
- }
-
- if( S_ISDIR( sb.st_mode ) ) {
-
- vdev_debug("Search '%s'\n", fp_dup );
-
- rc = sglib_cstr_vector_push_back( device_frontier, fp_dup );
- if( rc != 0 ) {
-
- free( fp_dup );
- return rc;
- }
- }
- else {
-
+ }
+
+ if (S_ISDIR (sb.st_mode))
+ {
+
+ vdev_debug ("Search '%s'\n", fp_dup);
+
+ rc = sglib_cstr_vector_push_back (device_frontier, fp_dup);
+ if (rc != 0)
+ {
+
+ free (fp_dup);
+ return rc;
+ }
+ }
+ else
+ {
+
// this is a uevent; this directory is a device
- vdev_debug("Uevent '%s'\n", fp_dup );
+ vdev_debug ("Uevent '%s'\n", fp_dup);
scan_ctx->uevent_path = fp_dup;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// read all devices from sysfs, and put their uevent paths into the given uevent_paths.
// scan in breadth-first order, so we find and process parent devices before their child devices.
// return 0 on success
// return negative on error
-static int vdev_linux_sysfs_find_devices( struct vdev_linux_context* ctx, struct sglib_cstr_vector* uevent_paths ) {
-
- int rc = 0;
-
- // find all directories that have a 'uevent' file in them
- struct sglib_cstr_vector device_frontier;
- sglib_cstr_vector_init( &device_frontier );
-
- struct vdev_linux_sysfs_scan_context scan_context;
- memset( &scan_context, 0, sizeof(struct vdev_linux_sysfs_scan_context) );
-
- scan_context.device_frontier = &device_frontier;
-
- char* device_root = NULL;
-
- // scan /sys/devices
- device_root = vdev_fullpath( ctx->sysfs_mountpoint, "/devices", NULL );
- if( device_root == NULL ) {
-
+static int
+vdev_linux_sysfs_find_devices (struct vdev_linux_context *ctx,
+ struct sglib_cstr_vector *uevent_paths)
+{
+
+ int rc = 0;
+
+ // find all directories that have a 'uevent' file in them
+ struct sglib_cstr_vector device_frontier;
+ sglib_cstr_vector_init (&device_frontier);
+
+ struct vdev_linux_sysfs_scan_context scan_context;
+ memset (&scan_context, 0, sizeof (struct vdev_linux_sysfs_scan_context));
+
+ scan_context.device_frontier = &device_frontier;
+
+ char *device_root = NULL;
+
+ // scan /sys/devices
+ device_root = vdev_fullpath (ctx->sysfs_mountpoint, "/devices", NULL);
+ if (device_root == NULL)
+ {
+
return -ENOMEM;
- }
-
- rc = vdev_load_all( device_root, vdev_linux_sysfs_scan_device_directory, &scan_context );
- if( rc != 0 ) {
-
- vdev_error("vdev_load_all('%s') rc = %d\n", device_root, rc );
-
- free( device_root );
-
- sglib_cstr_vector_free( &device_frontier );
-
+ }
+
+ rc = vdev_load_all (device_root, vdev_linux_sysfs_scan_device_directory,
+ &scan_context);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_load_all('%s') rc = %d\n", device_root, rc);
+
+ free (device_root);
+
+ sglib_cstr_vector_free (&device_frontier);
+
return rc;
- }
-
- free( device_root );
-
- while( 1 ) {
-
- unsigned long len = sglib_cstr_vector_size( &device_frontier );
-
- if( len == 0 ) {
- break;
- }
-
- device_root = sglib_cstr_vector_at( &device_frontier, len - 1 );
- sglib_cstr_vector_set( &device_frontier, NULL, len - 1 );
-
- sglib_cstr_vector_pop_back( &device_frontier );
-
+ }
+
+ free (device_root);
+
+ while (1)
+ {
+
+ unsigned long len = sglib_cstr_vector_size (&device_frontier);
+
+ if (len == 0)
+ {
+ break;
+ }
+
+ device_root = sglib_cstr_vector_at (&device_frontier, len - 1);
+ sglib_cstr_vector_set (&device_frontier, NULL, len - 1);
+
+ sglib_cstr_vector_pop_back (&device_frontier);
+
// scan for more devices
- rc = vdev_load_all( device_root, vdev_linux_sysfs_scan_device_directory, &scan_context );
- if( rc != 0 ) {
-
- vdev_error("vdev_load_all('%s') rc = %d\n", device_root, rc );
- free( device_root );
- break;
- }
-
+ rc = vdev_load_all (device_root,
+ vdev_linux_sysfs_scan_device_directory,
+ &scan_context);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_load_all('%s') rc = %d\n", device_root, rc);
+ free (device_root);
+ break;
+ }
// is one of them a uevent?
- if( scan_context.uevent_path != NULL ) {
-
- // yup--remember it
- char* uevent_path = vdev_strdup_or_null( scan_context.uevent_path );
-
- if( uevent_path == NULL ) {
-
- free( device_root );
- free( scan_context.uevent_path );
- scan_context.uevent_path = NULL;
-
- rc = -ENOMEM;
- break;
- }
-
- rc = sglib_cstr_vector_push_back( uevent_paths, uevent_path );
- if( rc < 0 ) {
-
- free( uevent_path );
- free( device_root );
- free( scan_context.uevent_path );
- scan_context.uevent_path = NULL;
-
- break;
- }
-
- free( scan_context.uevent_path );
- scan_context.uevent_path = NULL;
- }
-
- free( device_root );
- }
-
- sglib_cstr_vector_free( &device_frontier );
-
- return rc;
-}
+ if (scan_context.uevent_path != NULL)
+ {
+
+ // yup--remember it
+ char *uevent_path = vdev_strdup_or_null (scan_context.uevent_path);
+
+ if (uevent_path == NULL)
+ {
+ free (device_root);
+ free (scan_context.uevent_path);
+ scan_context.uevent_path = NULL;
+
+ rc = -ENOMEM;
+ break;
+ }
+
+ rc = sglib_cstr_vector_push_back (uevent_paths, uevent_path);
+ if (rc < 0)
+ {
+
+ free (uevent_path);
+ free (device_root);
+ free (scan_context.uevent_path);
+ scan_context.uevent_path = NULL;
+
+ break;
+ }
+
+ free (scan_context.uevent_path);
+ scan_context.uevent_path = NULL;
+ }
+
+ free (device_root);
+ }
+
+ sglib_cstr_vector_free (&device_frontier);
+
+ return rc;
+}
// free a list of cstr vectors
// always succeeds
-static int vdev_cstr_vector_free_all( struct sglib_cstr_vector* vec ) {
-
- // free all strings
- for( unsigned long i = 0; i < sglib_cstr_vector_size( vec ); i++ ) {
-
- if( sglib_cstr_vector_at( vec, i ) != NULL ) {
-
- free( sglib_cstr_vector_at( vec, i ) );
- sglib_cstr_vector_set( vec, NULL, i );
- }
- }
-
- return 0;
+static int
+vdev_cstr_vector_free_all (struct sglib_cstr_vector *vec)
+{
+
+ // free all strings
+ for (unsigned long i = 0; i < sglib_cstr_vector_size (vec); i++)
+ {
+
+ if (sglib_cstr_vector_at (vec, i) != NULL)
+ {
+
+ free (sglib_cstr_vector_at (vec, i));
+ sglib_cstr_vector_set (vec, NULL, i);
+ }
+ }
+
+ return 0;
}
-
+
// register all devices, given a vector to their uevent files
// return 0 on success
// return negative on error
-static int vdev_linux_sysfs_register_devices( struct vdev_linux_context* ctx ) {
-
- int rc = 0;
- struct sglib_cstr_vector uevent_paths;
-
- sglib_cstr_vector_init( &uevent_paths );
-
- // scan devices
- rc = vdev_linux_sysfs_find_devices( ctx, &uevent_paths );
- if( rc != 0 ) {
-
- vdev_error("vdev_linux_sysfs_find_devices() rc = %d\n", rc );
-
- vdev_cstr_vector_free_all( &uevent_paths );
- sglib_cstr_vector_free( &uevent_paths );
+static int
+vdev_linux_sysfs_register_devices (struct vdev_linux_context *ctx)
+{
+
+ int rc = 0;
+ struct sglib_cstr_vector uevent_paths;
+
+ sglib_cstr_vector_init (&uevent_paths);
+
+ // scan devices
+ rc = vdev_linux_sysfs_find_devices (ctx, &uevent_paths);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_linux_sysfs_find_devices() rc = %d\n", rc);
+
+ vdev_cstr_vector_free_all (&uevent_paths);
+ sglib_cstr_vector_free (&uevent_paths);
return rc;
- }
-
- // process all devices
- for( unsigned long i = 0; i < sglib_cstr_vector_size( &uevent_paths ); i++ ) {
-
- char* uevent_path = sglib_cstr_vector_at( &uevent_paths, i );
-
+ }
+ // process all devices
+ for (unsigned long i = 0; i < sglib_cstr_vector_size (&uevent_paths); i++)
+ {
+
+ char *uevent_path = sglib_cstr_vector_at (&uevent_paths, i);
+
// skip filtered entries
- if( uevent_path == NULL ) {
- continue;
- }
-
- vdev_debug("Register device '%s'\n", uevent_path );
- rc = vdev_linux_sysfs_register_device( ctx, uevent_path );
- if( rc != 0 ) {
-
- vdev_error("vdev_linux_sysfs_register_device('%s') rc = %d\n", uevent_path, rc );
- continue;
- }
- }
-
- // free all paths
- vdev_cstr_vector_free_all( &uevent_paths );
- sglib_cstr_vector_free( &uevent_paths );
-
- return rc;
+ if (uevent_path == NULL)
+ {
+ continue;
+ }
+
+ vdev_debug ("Register device '%s'\n", uevent_path);
+ rc = vdev_linux_sysfs_register_device (ctx, uevent_path);
+ if (rc != 0)
+ {
+
+ vdev_error
+ ("vdev_linux_sysfs_register_device('%s') rc = %d\n",
+ uevent_path, rc);
+ continue;
+ }
+ }
+
+ // free all paths
+ vdev_cstr_vector_free_all (&uevent_paths);
+ sglib_cstr_vector_free (&uevent_paths);
+
+ return rc;
}
// start listening for kernel events via netlink
// only do so if we're *NOT* going to run once (check the config)
// return 0 on success
// return -errno on error (failure to socket(2), setsockopt(2), bind(2), or walk sysfs)
-static int vdev_linux_context_init( struct vdev_os_context* os_ctx, struct vdev_linux_context* ctx ) {
-
- int rc = 0;
- size_t slen = VDEV_LINUX_NETLINK_RECV_BUF_MAX;
- int so_passcred_enable = 1;
-
- memset( ctx, 0, sizeof(struct vdev_linux_context) );
-
- ctx->os_ctx = os_ctx;
-
- // if we're just handling coldplug, don't set up the netlink socket
- if( !os_ctx->coldplug_only ) {
-
+static int
+vdev_linux_context_init (struct vdev_os_context *os_ctx,
+ struct vdev_linux_context *ctx)
+{
+
+ int rc = 0;
+ size_t slen = VDEV_LINUX_NETLINK_RECV_BUF_MAX;
+ int so_passcred_enable = 1;
+
+ memset (ctx, 0, sizeof (struct vdev_linux_context));
+
+ ctx->os_ctx = os_ctx;
+
+ // if we're just handling coldplug, don't set up the netlink socket
+ if (!os_ctx->coldplug_only)
+ {
+
ctx->nl_addr.nl_family = AF_NETLINK;
- ctx->nl_addr.nl_pid = getpid();
+ ctx->nl_addr.nl_pid = getpid ();
ctx->nl_addr.nl_groups = NETLINK_KOBJECT_UEVENT;
-
- ctx->pfd.fd = socket( PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT );
- if( ctx->pfd.fd < 0 ) {
-
- rc = -errno;
- vdev_error("socket(PF_NETLINK) rc = %d\n", rc);
- return rc;
- }
-
+
+ ctx->pfd.fd = socket (PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+ if (ctx->pfd.fd < 0)
+ {
+
+ rc = -errno;
+ vdev_error ("socket(PF_NETLINK) rc = %d\n", rc);
+ return rc;
+ }
+
ctx->pfd.events = POLLIN;
-
+
// big receive buffer, if running as root
- if( geteuid() == 0 ) {
- rc = setsockopt( ctx->pfd.fd, SOL_SOCKET, SO_RCVBUFFORCE, &slen, sizeof(slen) );
- if( rc < 0 ) {
-
- rc = -errno;
- vdev_error("setsockopt(SO_RCVBUFFORCE) rc = %d\n", rc);
-
- close( ctx->pfd.fd );
- return rc;
- }
- }
-
+ if (geteuid () == 0)
+ {
+ rc = setsockopt (ctx->pfd.fd, SOL_SOCKET, SO_RCVBUFFORCE,
+ &slen, sizeof (slen));
+ if (rc < 0)
+ {
+
+ rc = -errno;
+ vdev_error ("setsockopt(SO_RCVBUFFORCE) rc = %d\n", rc);
+
+ close (ctx->pfd.fd);
+ return rc;
+ }
+ }
// check credentials of message--only root should be able talk to us
- rc = setsockopt( ctx->pfd.fd, SOL_SOCKET, SO_PASSCRED, &so_passcred_enable, sizeof(so_passcred_enable) );
- if( rc < 0 ) {
-
- rc = -errno;
- vdev_error("setsockopt(SO_PASSCRED) rc = %d\n", rc );
-
- close( ctx->pfd.fd );
- return rc;
-
- }
-
+ rc = setsockopt (ctx->pfd.fd, SOL_SOCKET, SO_PASSCRED,
+ &so_passcred_enable, sizeof (so_passcred_enable));
+ if (rc < 0)
+ {
+
+ rc = -errno;
+ vdev_error ("setsockopt(SO_PASSCRED) rc = %d\n", rc);
+
+ close (ctx->pfd.fd);
+ return rc;
+
+ }
// bind to the address
- rc = bind( ctx->pfd.fd, (struct sockaddr*)&ctx->nl_addr, sizeof(struct sockaddr_nl) );
- if( rc != 0 ) {
-
- rc = -errno;
- vdev_error("bind(%d) rc = %d\n", ctx->pfd.fd, rc );
-
- close( ctx->pfd.fd );
- return rc;
- }
- }
- else {
-
+ rc = bind (ctx->pfd.fd, (struct sockaddr *) &ctx->nl_addr,
+ sizeof (struct sockaddr_nl));
+ if (rc != 0)
+ {
+
+ rc = -errno;
+ vdev_error ("bind(%d) rc = %d\n", ctx->pfd.fd, rc);
+
+ close (ctx->pfd.fd);
+ return rc;
+ }
+ }
+ else
+ {
+
ctx->pfd.fd = -1;
- }
-
- // lookup sysfs mountpoint
- rc = vdev_linux_find_sysfs_mountpoint( ctx->sysfs_mountpoint, PATH_MAX );
- if( rc != 0 ) {
-
- vdev_error("vdev_linux_find_sysfs_mountpoint rc = %d\n", rc );
-
- close( ctx->pfd.fd );
+ }
+
+ // lookup sysfs mountpoint
+ rc = vdev_linux_find_sysfs_mountpoint (ctx->sysfs_mountpoint, PATH_MAX);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_linux_find_sysfs_mountpoint rc = %d\n", rc);
+
+ close (ctx->pfd.fd);
return rc;
- }
-
- pthread_mutex_init( &ctx->initial_requests_lock, NULL );
-
- // seed devices from sysfs
- rc = vdev_linux_sysfs_register_devices( ctx );
- if( rc != 0 ) {
-
- vdev_error("vdev_linux_sysfs_walk_devs rc = %d\n", rc );
+ }
+
+ pthread_mutex_init (&ctx->initial_requests_lock, NULL);
+
+ // seed devices from sysfs
+ rc = vdev_linux_sysfs_register_devices (ctx);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_linux_sysfs_walk_devs rc = %d\n", rc);
return rc;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// stop listening
-static int vdev_linux_context_shutdown( struct vdev_linux_context* ctx ) {
-
- // shut down
- if( ctx != NULL ) {
-
- if( ctx->pfd.fd >= 0 ) {
- close( ctx->pfd.fd );
- ctx->pfd.fd = -1;
- }
-
- if( ctx->initial_requests != NULL ) {
-
- struct vdev_device_request* itr = ctx->initial_requests;
- struct vdev_device_request* next = NULL;
-
- while( itr != NULL ) {
-
- next = itr->next;
-
- vdev_device_request_free( itr );
- free( itr );
-
- itr = next;
- }
-
- ctx->initial_requests = NULL;
- ctx->initial_requests_tail = NULL;
- }
- }
-
- return 0;
-}
+static int
+vdev_linux_context_shutdown (struct vdev_linux_context *ctx)
+{
+
+ // shut down
+ if (ctx != NULL)
+ {
+
+ if (ctx->pfd.fd >= 0)
+ {
+ close (ctx->pfd.fd);
+ ctx->pfd.fd = -1;
+ }
+
+ if (ctx->initial_requests != NULL)
+ {
+
+ struct vdev_device_request *itr = ctx->initial_requests;
+ struct vdev_device_request *next = NULL;
+
+ while (itr != NULL)
+ {
+
+ next = itr->next;
+
+ vdev_device_request_free (itr);
+ free (itr);
+ itr = next;
+ }
+
+ ctx->initial_requests = NULL;
+ ctx->initial_requests_tail = NULL;
+ }
+ }
+
+ return 0;
+}
// are we using devtmpfs on this mountpoint?
// return 1 if so
// return 0 if not
// return negative on error
-static int vdev_linux_mountpoint_on_devtmpfs( char const* mountpoint ) {
-
- // NOTE: You would think that we can just statfs(2) the
- // mountpoint and get the underlying filesystem type.
- // However, devtmpfs and tmpfs have the same f_type value.
- // This makes this strategy a no-go, since vdevd will need
- // to behave differently on devtmpfs but not tmpfs.
- // So, we have to parse /proc/mounts instead.
-
- int rc = 0;
-
- FILE* f = NULL;
- int ent_count = 1;
-
- bool found = false;
- char devtmpfs_mountpoint[PATH_MAX+1];
-
- char realpath_mountpoint[PATH_MAX+1];
- char devtmpfs_realpath_mountpoint[PATH_MAX+1];
-
- size_t devtmpfs_realpath_mountpoint_len = 0;
- size_t realpath_mountpoint_len = 0;
-
- char mntbuf[4096];
- struct mntent ment_buf;
- struct mntent* ment_ptr = NULL;
-
- f = fopen( "/proc/mounts", "r" );
- if( f == NULL ) {
-
+static int
+vdev_linux_mountpoint_on_devtmpfs (char const *mountpoint)
+{
+
+ // NOTE: You would think that we can just statfs(2) the
+ // mountpoint and get the underlying filesystem type.
+ // However, devtmpfs and tmpfs have the same f_type value.
+ // This makes this strategy a no-go, since vdevd will need
+ // to behave differently on devtmpfs but not tmpfs.
+ // So, we have to parse /proc/mounts instead.
+
+ int rc = 0;
+
+ FILE *f = NULL;
+ int ent_count = 1;
+
+ bool found = false;
+ char devtmpfs_mountpoint[PATH_MAX + 1];
+
+ char realpath_mountpoint[PATH_MAX + 1];
+ char devtmpfs_realpath_mountpoint[PATH_MAX + 1];
+
+ size_t devtmpfs_realpath_mountpoint_len = 0;
+ size_t realpath_mountpoint_len = 0;
+
+ char mntbuf[4096];
+ struct mntent ment_buf;
+ struct mntent *ment_ptr = NULL;
+
+ f = fopen ("/proc/mounts", "r");
+ if (f == NULL)
+ {
+
rc = -errno;
- fprintf(stderr, "Failed to open /proc/mounts, rc = %d\n", rc );
+ fprintf (stderr, "Failed to open /proc/mounts, rc = %d\n", rc);
return rc;
- }
-
- // scan for sysfs mount type
- while( 1 ) {
-
- ment_ptr = getmntent_r( f, &ment_buf, mntbuf, 4096 );
- if( ment_ptr == NULL ) {
-
- break;
- }
-
- if( strcmp( ment_ptr->mnt_type, "devtmpfs" ) == 0 ) {
-
- // found!
- strncpy( devtmpfs_mountpoint, ment_ptr->mnt_dir, PATH_MAX );
-
- // is the mountpoint contained in devtmpfs_mountpoint?
- char* tmp = NULL;
-
- memset( realpath_mountpoint, 0, PATH_MAX+1 );
- memset( devtmpfs_realpath_mountpoint, 0, PATH_MAX+1 );
-
- tmp = realpath( mountpoint, realpath_mountpoint );
- if( tmp == NULL ) {
-
- rc = -errno;
- fprintf(stderr, "Failed to get the real path of '%s', rc = %d\n", mountpoint, rc );
- break;
- }
-
- tmp = realpath( devtmpfs_mountpoint, devtmpfs_realpath_mountpoint );
- if( tmp == NULL ) {
-
- rc = -errno;
- fprintf(stderr, "Failed to get the real path of '%s', rc = %d\n", devtmpfs_mountpoint, rc );
- break;
- }
-
- vdev_debug("devtmpfs realpath is '%s'\n", devtmpfs_realpath_mountpoint );
- vdev_debug("mountpoint realpath is '%s'\n", realpath_mountpoint );
-
- devtmpfs_realpath_mountpoint_len = strlen(devtmpfs_realpath_mountpoint);
- realpath_mountpoint_len = strlen(realpath_mountpoint);
-
- size_t min_len = MIN( devtmpfs_realpath_mountpoint_len, realpath_mountpoint_len );
-
- // is our mountpoint within the devtmpfs mountpoint?
- if( strncmp( devtmpfs_realpath_mountpoint, realpath_mountpoint, min_len ) == 0 && // devtmpfs mountpoint path is a substring of the mountpoint path and
- (strchr( realpath_mountpoint + min_len, '/' ) != NULL || // either the mountpoint path continues at least one directory into devtmpfs path, or
- strcmp( devtmpfs_realpath_mountpoint, realpath_mountpoint ) == 0 ) ) { // the devtmpfs mountpoint path *is* the mountpoint path
-
- // contained!
- rc = 1;
- found = true;
- break;
- }
- }
-
+ }
+ // scan for sysfs mount type
+ while (1)
+ {
+
+ ment_ptr = getmntent_r (f, &ment_buf, mntbuf, 4096);
+ if (ment_ptr == NULL)
+ {
+
+ break;
+ }
+
+ if (strcmp (ment_ptr->mnt_type, "devtmpfs") == 0)
+ {
+
+ // found!
+ strncpy (devtmpfs_mountpoint, ment_ptr->mnt_dir, PATH_MAX);
+
+ // is the mountpoint contained in devtmpfs_mountpoint?
+ char *tmp = NULL;
+
+ memset (realpath_mountpoint, 0, PATH_MAX + 1);
+ memset (devtmpfs_realpath_mountpoint, 0, PATH_MAX + 1);
+
+ tmp = realpath (mountpoint, realpath_mountpoint);
+ if (tmp == NULL)
+ {
+
+ rc = -errno;
+ fprintf (stderr,
+ "Failed to get the real path of '%s', rc = %d\n",
+ mountpoint, rc);
+ break;
+ }
+
+ tmp = realpath (devtmpfs_mountpoint, devtmpfs_realpath_mountpoint);
+ if (tmp == NULL)
+ {
+
+ rc = -errno;
+ fprintf (stderr,
+ "Failed to get the real path of '%s', rc = %d\n",
+ devtmpfs_mountpoint, rc);
+ break;
+ }
+
+ vdev_debug ("devtmpfs realpath is '%s'\n",
+ devtmpfs_realpath_mountpoint);
+ vdev_debug ("mountpoint realpath is '%s'\n", realpath_mountpoint);
+
+ devtmpfs_realpath_mountpoint_len =
+ strlen (devtmpfs_realpath_mountpoint);
+ realpath_mountpoint_len = strlen (realpath_mountpoint);
+
+ size_t min_len = MIN (devtmpfs_realpath_mountpoint_len,
+ realpath_mountpoint_len);
+
+ // is our mountpoint within the devtmpfs mountpoint?
+ if (strncmp (devtmpfs_realpath_mountpoint, realpath_mountpoint, min_len) == 0 && // devtmpfs mountpoint path is a substring of the mountpoint path and
+ (strchr (realpath_mountpoint + min_len, '/') != NULL || // either the mountpoint path continues at least one directory into devtmpfs path, or
+ strcmp (devtmpfs_realpath_mountpoint,
+ realpath_mountpoint) == 0))
+ { // the devtmpfs mountpoint path *is* the mountpoint path
+
+ // contained!
+ rc = 1;
+ found = true;
+ break;
+ }
+ }
+
ent_count++;
- }
-
- fclose( f );
-
- return rc;
+ }
+
+ fclose (f);
+
+ return rc;
}
// set up Linux-specific vdev state.
// this is early initialization, so don't start anything yet
// NOTE: this should only be called from reload-safe code--i.e. a reload can't occur while this method runs
-int vdev_os_init( struct vdev_os_context* os_ctx, void** cls ) {
-
- int rc = 0;
- struct vdev_linux_context* ctx = NULL;
-
- rc = vdev_linux_mountpoint_on_devtmpfs( os_ctx->state->mountpoint );
- if( rc < 0 ) {
-
- vdev_error("vdev_linux_mountpoint_on_devtmpfs('%s') rc = %d\n", os_ctx->state->mountpoint, rc );
+int
+vdev_os_init (struct vdev_os_context *os_ctx, void **cls)
+{
+
+ int rc = 0;
+ struct vdev_linux_context *ctx = NULL;
+
+ rc = vdev_linux_mountpoint_on_devtmpfs (os_ctx->state->mountpoint);
+ if (rc < 0)
+ {
+
+ vdev_error ("vdev_linux_mountpoint_on_devtmpfs('%s') rc = %d\n",
+ os_ctx->state->mountpoint, rc);
return rc;
- }
-
- if( rc > 0 ) {
-
+ }
+
+ if (rc > 0)
+ {
+
// using devtmpfs
- vdev_info("'%s' is on devtmpfs\n", os_ctx->state->mountpoint );
-
- vdev_config_set_OS_quirk( os_ctx->state->config->OS_quirks, VDEV_OS_QUIRK_DEVICE_EXISTS );
- }
- else {
-
- vdev_info("'%s' is not on devtmpfs\n", os_ctx->state->mountpoint );
- }
-
- ctx = VDEV_CALLOC( struct vdev_linux_context, 1 );
- if( ctx == NULL ) {
+ vdev_info ("'%s' is on devtmpfs\n", os_ctx->state->mountpoint);
+
+ vdev_config_set_OS_quirk (os_ctx->state->config->OS_quirks,
+ VDEV_OS_QUIRK_DEVICE_EXISTS);
+ }
+ else
+ {
+
+ vdev_info ("'%s' is not on devtmpfs\n", os_ctx->state->mountpoint);
+ }
+
+ ctx = VDEV_CALLOC (struct vdev_linux_context, 1);
+ if (ctx == NULL)
+ {
return -ENOMEM;
- }
-
- rc = vdev_linux_context_init( os_ctx, ctx );
- if( rc != 0 ) {
-
- free( ctx );
+ }
+
+ rc = vdev_linux_context_init (os_ctx, ctx);
+ if (rc != 0)
+ {
+
+ free (ctx);
return rc;
- }
-
- *cls = ctx;
- return 0;
-}
+ }
+ *cls = ctx;
+ return 0;
+}
// shut down Linux-specific vdev state
-int vdev_os_shutdown( void* cls ) {
-
- struct vdev_linux_context* ctx = (struct vdev_linux_context*)cls;
-
- vdev_linux_context_shutdown( ctx );
- free( ctx );
-
- return 0;
-}
+int
+vdev_os_shutdown (void *cls)
+{
+
+ struct vdev_linux_context *ctx = (struct vdev_linux_context *) cls;
+ vdev_linux_context_shutdown (ctx);
+ free (ctx);
+
+ return 0;
+}
#endif
diff --git a/vdevd/os/linux.h b/vdevd/os/linux.h
index 68b7ae5..a43e825 100644
--- a/vdevd/os/linux.h
+++ b/vdevd/os/linux.h
@@ -25,7 +25,7 @@
// build Linux-specific method implementations
#ifdef _VDEV_OS_LINUX
-#define _GNU_SOURCE
+#define _GNU_SOURCE
#include "vdev.h"
@@ -47,34 +47,32 @@
#define VDEV_LINUX_NETLINK_UDEV_HEADER_LEN 8
// connection to the linux kernel for hotplug
-struct vdev_linux_context {
-
- // netlink address
- struct sockaddr_nl nl_addr;
-
- // poll on the netlink socket
- struct pollfd pfd;
-
- // path to mounted sysfs
- char sysfs_mountpoint[ PATH_MAX+1 ];
-
- // ref to OS context
- struct vdev_os_context* os_ctx;
-
- // initial device requests
- pthread_mutex_t initial_requests_lock;
- struct vdev_device_request* initial_requests;
- struct vdev_device_request* initial_requests_tail;
-};
+struct vdev_linux_context
+{
-C_LINKAGE_BEGIN
+ // netlink address
+ struct sockaddr_nl nl_addr;
-int vdev_os_init( struct vdev_os_context* ctx, void** cls );
-int vdev_os_shutdown( void* cls );
+ // poll on the netlink socket
+ struct pollfd pfd;
-int vdev_os_next_device( struct vdev_device_request* request, void* cls );
+ // path to mounted sysfs
+ char sysfs_mountpoint[PATH_MAX + 1];
-C_LINKAGE_END
+ // ref to OS context
+ struct vdev_os_context *os_ctx;
+
+ // initial device requests
+ pthread_mutex_t initial_requests_lock;
+ struct vdev_device_request *initial_requests;
+ struct vdev_device_request *initial_requests_tail;
+};
+C_LINKAGE_BEGIN int vdev_os_init (struct vdev_os_context *ctx, void **cls);
+int vdev_os_shutdown (void *cls);
+
+int vdev_os_next_device (struct vdev_device_request *request, void *cls);
+
+C_LINKAGE_END
+#endif
#endif
-#endif
\ No newline at end of file
diff --git a/vdevd/os/methods.h b/vdevd/os/methods.h
index 938f594..537c699 100644
--- a/vdevd/os/methods.h
+++ b/vdevd/os/methods.h
@@ -34,18 +34,15 @@
#include "test.h"
#endif
-C_LINKAGE_BEGIN
-
-int vdev_os_init( struct vdev_os_context* ctx, void** cls );
-int vdev_os_shutdown( void* cls );
+C_LINKAGE_BEGIN int vdev_os_init (struct vdev_os_context *ctx, void **cls);
+int vdev_os_shutdown (void *cls);
// yield the next device
// return 0 on success
// return positive to exit successfully
// return -EAGAIN if vdevd should try again
// return negative on fatal error (causes vdevd to exit).
-int vdev_os_next_device( struct vdev_device_request* request, void* cls );
+int vdev_os_next_device (struct vdev_device_request *request, void *cls);
C_LINKAGE_END
-
-#endif
+#endif
diff --git a/vdevd/os/test.h b/vdevd/os/test.h
index ffbdb78..fbd781f 100644
--- a/vdevd/os/test.h
+++ b/vdevd/os/test.h
@@ -34,30 +34,29 @@
#define VDEV_TEST_NAME_MAJOR "MAJOR"
#define VDEV_TEST_NAME_MINOR "MINOR"
+typedef vector < struct vdev_device_request *>vdev_test_device_list_t;
-typedef vector vdev_test_device_list_t;
+struct vdev_test_context
+{
-struct vdev_test_context {
-
- vdev_test_device_list_t* devlist;
-
- pthread_mutex_t devlist_lock;
- sem_t devlist_sem;
-
- char* events_dir;
+ vdev_test_device_list_t *devlist;
+
+ pthread_mutex_t devlist_lock;
+ sem_t devlist_sem;
+
+ char *events_dir;
};
-extern "C" {
+extern "C"
+{
-int vdev_os_init( struct vdev_os_context* ctx, void** cls );
-int vdev_os_start( void* cls );
-int vdev_os_stop( void* cls );
-int vdev_os_shutdown( void* cls );
+ int vdev_os_init (struct vdev_os_context *ctx, void **cls);
+ int vdev_os_start (void *cls);
+ int vdev_os_stop (void *cls);
+ int vdev_os_shutdown (void *cls);
-int vdev_os_next_device( struct vdev_device_request* request, void* cls );
+ int vdev_os_next_device (struct vdev_device_request *request, void *cls);
}
-
#endif
-
-#endif
\ No newline at end of file
+#endif
diff --git a/vdevd/vdev.c b/vdevd/vdev.c
index 306d674..fdb820f 100644
--- a/vdevd/vdev.c
+++ b/vdevd/vdev.c
@@ -1,5 +1,5 @@
/*
- vdev: a virtual device manager for *nix
+ Vdev: A virtual device manager for *nix
Copyright (C) 2014 Jude Nelson
This program is dual-licensed: you can redistribute it and/or modify
@@ -23,521 +23,582 @@
#include "action.h"
#include "libvdev/config.h"
-SGLIB_DEFINE_VECTOR_FUNCTIONS( cstr );
-
-
+SGLIB_DEFINE_VECTOR_FUNCTIONS (cstr)
// context for removing unplugged device
-struct vdev_device_unplug_context {
-
- struct sglib_cstr_vector* device_paths; // queue of device paths to search
- struct vdev_state* state; // vdev state
-};
+ struct vdev_device_unplug_context
+ {
+
+ struct sglib_cstr_vector *device_paths; // queue of device paths to search
+ struct vdev_state *state; // vdev state
+ };
// get the instance of the vdevd program that made this device, given its device path
// instance_str must be at least VDEV_CONFIG_INSTANCE_NONCE_STRLEN bytes
// return 0 on success
// return -errno on failure to stat, open, or read
-static int vdev_device_read_vdevd_instance( char const* mountpoint, char const* dev_fullpath, char* instance_str ) {
-
- int rc = 0;
- char const* devpath = dev_fullpath + strlen(mountpoint);
-
- char* instance_attr_relpath = vdev_fullpath( VDEV_METADATA_PREFIX "/dev", devpath, NULL );
- if( instance_attr_relpath == NULL ) {
-
+ static int vdev_device_read_vdevd_instance (char const *mountpoint,
+ char const *dev_fullpath,
+ char *instance_str)
+{
+
+ int rc = 0;
+ char const *devpath = dev_fullpath + strlen (mountpoint);
+
+ char *instance_attr_relpath =
+ vdev_fullpath (VDEV_METADATA_PREFIX "/dev", devpath, NULL);
+ if (instance_attr_relpath == NULL)
+ {
+
return -ENOMEM;
- }
-
- char* instance_attr_path = vdev_fullpath( mountpoint, instance_attr_relpath, NULL );
-
- free( instance_attr_relpath );
- instance_attr_relpath = NULL;
-
- if( instance_attr_path == NULL ) {
-
+ }
+
+ char *instance_attr_path =
+ vdev_fullpath (mountpoint, instance_attr_relpath, NULL);
+
+ free (instance_attr_relpath);
+ instance_attr_relpath = NULL;
+
+ if (instance_attr_path == NULL)
+ {
+
return -ENOMEM;
- }
-
- char* instance_path = vdev_fullpath( instance_attr_path, VDEV_METADATA_PARAM_INSTANCE, NULL );
-
- free( instance_attr_path );
- instance_attr_path = NULL;
-
- if( instance_path == NULL ) {
-
+ }
+
+ char *instance_path =
+ vdev_fullpath (instance_attr_path, VDEV_METADATA_PARAM_INSTANCE,
+ NULL);
+
+ free (instance_attr_path);
+ instance_attr_path = NULL;
+
+ if (instance_path == NULL)
+ {
+
return -ENOMEM;
- }
-
- // read the instance string
- rc = vdev_read_file( instance_path, instance_str, VDEV_CONFIG_INSTANCE_NONCE_STRLEN - 1 );
- if( rc < 0 ) {
-
- vdev_error("vdev_read_file('%s') rc = %d\n", instance_path, rc );
- }
-
- free( instance_path );
- instance_path = NULL;
-
- return rc;
-}
+ }
+ // read the instance string
+ rc = vdev_read_file (instance_path, instance_str,
+ VDEV_CONFIG_INSTANCE_NONCE_STRLEN - 1);
+ if (rc < 0)
+ {
+
+ vdev_error ("vdev_read_file('%s') rc = %d\n", instance_path, rc);
+ }
+ free (instance_path);
+ instance_path = NULL;
+
+ return rc;
+}
// scan callback for a directory.
// queue directories, and unlink device files that are no longer plugged in.
// return 0 on success
// return -ENOMEM on OOM
// NOTE: mask unlink() failures, but log them.
-static int vdev_remove_unplugged_device( char const* path, void* cls ) {
-
- int rc = 0;
- struct stat sb;
- char instance_str[ VDEV_CONFIG_INSTANCE_NONCE_STRLEN + 1 ];
- char basename[ NAME_MAX+1 ];
-
- memset( instance_str, 0, VDEV_CONFIG_INSTANCE_NONCE_STRLEN + 1 );
-
- // extract cls
- struct vdev_device_unplug_context* ctx = (struct vdev_device_unplug_context*)cls;
-
- struct sglib_cstr_vector* device_paths = ctx->device_paths;
- struct vdev_state* state = ctx->state;
-
- if( strlen(path) == 0 ) {
-
+static int
+vdev_remove_unplugged_device (char const *path, void *cls)
+{
+
+ int rc = 0;
+ struct stat sb;
+ char instance_str[VDEV_CONFIG_INSTANCE_NONCE_STRLEN + 1];
+ char basename[NAME_MAX + 1];
+
+ memset (instance_str, 0, VDEV_CONFIG_INSTANCE_NONCE_STRLEN + 1);
+
+ // extract cls
+ struct vdev_device_unplug_context *ctx =
+ (struct vdev_device_unplug_context *) cls;
+
+ struct sglib_cstr_vector *device_paths = ctx->device_paths;
+ struct vdev_state *state = ctx->state;
+
+ if (strlen (path) == 0)
+ {
+
// nothing to do
return 0;
- }
-
- vdev_basename( path, basename );
-
- // is this . or ..?
- if( strcmp(basename, ".") == 0 || strcmp(basename, "..") == 0 ) {
+ }
+
+ vdev_basename (path, basename);
+
+ // is this . or ..?
+ if (strcmp (basename, ".") == 0 || strcmp (basename, "..") == 0)
+ {
return 0;
- }
-
- // what is this?
- rc = lstat( path, &sb );
- if( rc != 0 ) {
-
- vdev_error("stat('%s') rc = %d\n", path, rc );
-
+ }
+ // what is this?
+ rc = lstat (path, &sb);
+ if (rc != 0)
+ {
+
+ vdev_error ("stat('%s') rc = %d\n", path, rc);
+
// mask
return 0;
- }
-
- // is this a directory?
- if( S_ISDIR( sb.st_mode ) ) {
-
- // skip the metadata dir
- if( strcmp( basename, "metadata" ) == 0 ) {
- return 0;
- }
+ }
+ // is this a directory?
+ if (S_ISDIR (sb.st_mode))
+ {
+ // skip the metadata dir
+ if (strcmp (basename, "metadata") == 0)
+ {
+ return 0;
+ }
// search this later
- char* path_dup = vdev_strdup_or_null( path );
- if( path_dup == NULL ) {
-
- // really can't continue
- return -ENOMEM;
- }
-
- sglib_cstr_vector_push_back( device_paths, path_dup );
-
+ char *path_dup = vdev_strdup_or_null (path);
+ if (path_dup == NULL)
+ {
+
+ // really can't continue
+ return -ENOMEM;
+ }
+
+ sglib_cstr_vector_push_back (device_paths, path_dup);
+
return 0;
- }
-
- // is this a device file?
- if( S_ISBLK( sb.st_mode ) || S_ISCHR( sb.st_mode ) ) {
-
+ }
+ // is this a device file?
+ if (S_ISBLK (sb.st_mode) || S_ISCHR (sb.st_mode))
+ {
+
// what's the instance value?
- rc = vdev_device_read_vdevd_instance( state->config->mountpoint, path, instance_str );
- if( rc != 0 ) {
-
- vdev_error("vdev_device_read_vdevd_instance('%s') rc = %d\n", path, rc );
-
- // mask
- return 0;
- }
-
+ rc = vdev_device_read_vdevd_instance (state->config->mountpoint,
+ path, instance_str);
+ if (rc != 0)
+ {
+
+ vdev_error
+ ("vdev_device_read_vdevd_instance('%s') rc = %d\n", path, rc);
+
+ // mask
+ return 0;
+ }
// does it match ours?
- if( strcmp( state->config->instance_str, instance_str ) != 0 ) {
-
- struct vdev_device_request* to_delete = NULL;
- char const* device_path = NULL;
-
- vdev_debug("Remove unplugged device '%s'\n", path );
-
- device_path = path + strlen( state->config->mountpoint );
-
- to_delete = VDEV_CALLOC( struct vdev_device_request, 1 );
- if( to_delete == NULL ) {
-
- // OOM
- return -ENOMEM;
- }
-
- rc = vdev_device_request_init( to_delete, state, VDEV_DEVICE_REMOVE, device_path );
- if( rc != 0 ) {
-
- // OOM
- return rc;
- }
-
- // populate
- vdev_device_request_set_dev( to_delete, sb.st_rdev );
- vdev_device_request_set_mode( to_delete, S_ISBLK( sb.st_mode ) ? S_IFBLK : S_IFCHR );
-
- // remove it
- rc = vdev_device_remove( to_delete );
- if( rc != 0 ) {
-
- vdev_warn("vdev_device_remove('%s') rc = %d\n", device_path, rc );
- rc = 0;
- }
- }
- }
-
- return 0;
+ if (strcmp (state->config->instance_str, instance_str) != 0)
+ {
+
+ struct vdev_device_request *to_delete = NULL;
+ char const *device_path = NULL;
+
+ vdev_debug ("Remove unplugged device '%s'\n", path);
+
+ device_path = path + strlen (state->config->mountpoint);
+
+ to_delete = VDEV_CALLOC (struct vdev_device_request, 1);
+ if (to_delete == NULL)
+ {
+
+ // OOM
+ return -ENOMEM;
+ }
+
+ rc = vdev_device_request_init (to_delete, state,
+ VDEV_DEVICE_REMOVE, device_path);
+ if (rc != 0)
+ {
+
+ // OOM
+ return rc;
+ }
+ // populate
+ vdev_device_request_set_dev (to_delete, sb.st_rdev);
+ vdev_device_request_set_mode (to_delete,
+ S_ISBLK (sb.st_mode) ?
+ S_IFBLK : S_IFCHR);
+
+ // remove it
+ rc = vdev_device_remove (to_delete);
+ if (rc != 0)
+ {
+
+ vdev_warn ("vdev_device_remove('%s') rc = %d\n",
+ device_path, rc);
+ rc = 0;
+ }
+ }
+ }
+
+ return 0;
}
-
// remove all devices that no longer exist--that is, the contents of the /dev/metadata/$DEVICE_PATH/dev_instance file
// does not match this vdev's instance nonce.
// this is used when running with --once.
-int vdev_remove_unplugged_devices( struct vdev_state* state ) {
-
- int rc = 0;
- struct sglib_cstr_vector device_paths;
- char* devroot = vdev_strdup_or_null( state->config->mountpoint );
- char* next_dir = NULL;
- size_t next_dir_index = 0;
- struct stat sb;
-
- struct vdev_device_unplug_context unplug_ctx;
-
- unplug_ctx.state = state;
- unplug_ctx.device_paths = &device_paths;
-
- if( devroot == NULL ) {
+int
+vdev_remove_unplugged_devices (struct vdev_state *state)
+{
+
+ int rc = 0;
+ struct sglib_cstr_vector device_paths;
+ char *devroot = vdev_strdup_or_null (state->config->mountpoint);
+ char *next_dir = NULL;
+ size_t next_dir_index = 0;
+ // sb ?
+ struct stat sb;
+
+ struct vdev_device_unplug_context unplug_ctx;
+
+ unplug_ctx.state = state;
+ unplug_ctx.device_paths = &device_paths;
+
+ if (devroot == NULL)
+ {
return -ENOMEM;
- }
-
- sglib_cstr_vector_init( &device_paths );
-
- // walk /dev breadth-first
- rc = sglib_cstr_vector_push_back( &device_paths, devroot );
- if( rc != 0 ) {
-
- sglib_cstr_vector_free( &device_paths );
- free( devroot );
-
+ }
+
+ sglib_cstr_vector_init (&device_paths);
+
+ // walk /dev breadth-first
+ rc = sglib_cstr_vector_push_back (&device_paths, devroot);
+ if (rc != 0)
+ {
+
+ sglib_cstr_vector_free (&device_paths);
+ free (devroot);
+
return rc;
- }
-
- while( next_dir_index < sglib_cstr_vector_size( &device_paths ) ) {
-
+ }
+
+ while (next_dir_index < sglib_cstr_vector_size (&device_paths))
+ {
+
// next path
- next_dir = sglib_cstr_vector_at( &device_paths, next_dir_index );
- sglib_cstr_vector_set( &device_paths, NULL, next_dir_index );
-
+ next_dir = sglib_cstr_vector_at (&device_paths, next_dir_index);
+ sglib_cstr_vector_set (&device_paths, NULL, next_dir_index);
+
next_dir_index++;
-
+
// scan this directory, and remove unplugged device files and remember the directories to search
- rc = vdev_load_all( next_dir, vdev_remove_unplugged_device, &unplug_ctx );
- if( rc != 0 ) {
-
- vdev_error("vdev_load_all('%s') rc = %d\n", next_dir, rc );
-
- free( next_dir );
- break;
- }
-
- free( next_dir );
- }
-
- // free any unused vector space
- while( next_dir_index < sglib_cstr_vector_size( &device_paths ) ) {
-
- next_dir = sglib_cstr_vector_at( &device_paths, next_dir_index );
- sglib_cstr_vector_set( &device_paths, NULL, next_dir_index );
-
+ rc = vdev_load_all (next_dir, vdev_remove_unplugged_device,
+ &unplug_ctx);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_load_all('%s') rc = %d\n", next_dir, rc);
+
+ free (next_dir);
+ break;
+ }
+
+ free (next_dir);
+ }
+
+ // free any unused vector space
+ while (next_dir_index < sglib_cstr_vector_size (&device_paths))
+ {
+
+ next_dir = sglib_cstr_vector_at (&device_paths, next_dir_index);
+ sglib_cstr_vector_set (&device_paths, NULL, next_dir_index);
+
next_dir_index++;
-
- free( next_dir );
- }
-
- sglib_cstr_vector_free( &device_paths );
-
- return rc;
-}
+ free (next_dir);
+ }
+
+ sglib_cstr_vector_free (&device_paths);
+
+ return rc;
+}
// create the path to the error FIFO
// that helpers use to write error messages.
// return 0 on success
// return -EPERM on overflow
-int vdev_error_fifo_path( char const* mountpoint, char* path, size_t path_len ) {
-
- int rc = 0;
- rc = snprintf( path, path_len, "%s/%s/err.pipe", mountpoint, VDEV_METADATA_PREFIX );
- if( rc >= path_len ) {
+int
+vdev_error_fifo_path (char const *mountpoint, char *path, size_t path_len)
+{
+
+ int rc = 0;
+ rc = snprintf (path, path_len, "%s/%s/err.pipe", mountpoint,
+ VDEV_METADATA_PREFIX);
+ if (rc >= path_len)
+ {
return -EPERM;
- }
+ }
- return 0;
+ return 0;
}
-
// get a handle to the error FIFO, creating the FIFO if it doesn't yet exist.
// the handle will be in read/write mode
// return 0 on success, and set *fd
// return -errno on failure to create the FIFO
-int vdev_error_fifo_get_or_create( char const* mountpoint, int* fd ) {
-
- int rc = 0;
- char fifo_path[PATH_MAX+1];
- struct stat sb;
- memset( fifo_path, 0, PATH_MAX+1 );
-
- rc = vdev_error_fifo_path( mountpoint, fifo_path, PATH_MAX );
- if( rc < 0 ) {
+int
+vdev_error_fifo_get_or_create (char const *mountpoint, int *fd)
+{
+
+ int rc = 0;
+ char fifo_path[PATH_MAX + 1];
+ struct stat sb;
+ memset (fifo_path, 0, PATH_MAX + 1);
+
+ rc = vdev_error_fifo_path (mountpoint, fifo_path, PATH_MAX);
+ if (rc < 0)
+ {
return rc;
- }
+ }
- rc = stat( fifo_path, &sb );
- if( rc != 0 ) {
-
- rc = -errno;
- if( rc != -ENOENT ) {
+ rc = stat (fifo_path, &sb);
+ if (rc != 0)
+ {
- vdev_error("failed to create FIFO '%s': %s\n", fifo_path, strerror( -rc ) );
- return rc;
- }
+ rc = -errno;
+ if (rc != -ENOENT)
+ {
+ vdev_error ("failed to create FIFO '%s': %s\n",
+ fifo_path, strerror (-rc));
+ return rc;
+ }
// create
- rc = mkfifo( fifo_path, 0600 );
- if( rc != 0 ) {
+ rc = mkfifo (fifo_path, 0600);
+ if (rc != 0)
+ {
- rc = -errno;
- vdev_error("mkfifo('%s'): %s\n", fifo_path, strerror( -rc ) );
- return rc;
- }
- }
+ rc = -errno;
+ vdev_error ("mkfifo('%s'): %s\n", fifo_path, strerror (-rc));
+ return rc;
+ }
+ }
- *fd = open( fifo_path, O_RDWR );
- if( *fd < 0 ) {
+ *fd = open (fifo_path, O_RDWR);
+ if (*fd < 0)
+ {
rc = -errno;
- vdev_error("open('%s'): %s\n", fifo_path, strerror( -rc ) );
+ vdev_error ("open('%s'): %s\n", fifo_path, strerror (-rc));
return rc;
- }
+ }
- return 0;
+ return 0;
}
-
-
// thread for gathering error messages from the helpers and forwarding
// them to our logging system.
// *arg is an int, which is the error pipe to read from
-void* vdev_error_thread_main( void* arg ) {
-
- int rc = 0;
- int fd = *((int*)arg);
- char buf[4096];
- ssize_t nr = 0;
- int flags = 0;
- fd_set read_fds;
-
- // put into non-blocking mode
- flags = fcntl( fd, F_GETFL, 0 );
- if( flags < 0 ) {
+void *
+vdev_error_thread_main (void *arg)
+{
+
+ int rc = 0;
+ int fd = *((int *) arg);
+ char buf[4096];
+ ssize_t nr = 0;
+ int flags = 0;
+ fd_set read_fds;
+
+ // put into non-blocking mode
+ flags = fcntl (fd, F_GETFL, 0);
+ if (flags < 0)
+ {
rc = -errno;
- vdev_error("fcntl(%d, F_GETFL): %s\n", fd, strerror(-rc) );
+ vdev_error ("fcntl(%d, F_GETFL): %s\n", fd, strerror (-rc));
return NULL;
- }
+ }
- rc = fcntl( fd, F_SETFL, flags | O_NONBLOCK );
- if( rc < 0 ) {
+ rc = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
+ if (rc < 0)
+ {
rc = -errno;
- vdev_error("fctnl(%d, F_SETFL): %s\n", fd, strerror(-rc) );
+ vdev_error ("fctnl(%d, F_SETFL): %s\n", fd, strerror (-rc));
return NULL;
- }
+ }
- while( 1 ) {
+ while (1)
+ {
- FD_ZERO( &read_fds );
- FD_SET( fd, &read_fds );
+ FD_ZERO (&read_fds);
+ FD_SET (fd, &read_fds);
- rc = select( fd + 1, &read_fds, NULL, NULL, NULL );
- if( rc == 0 ) {
+ rc = select (fd + 1, &read_fds, NULL, NULL, NULL);
+ if (rc == 0)
+ {
- // not ready
- continue;
- }
+ // not ready
+ continue;
+ }
- if( rc < 0 ) {
+ if (rc < 0)
+ {
- // pipe closed
- break;
- }
+ // pipe closed
+ break;
+ }
- nr = read( fd, buf, 4095 );
- if( nr <= 0 ) {
-
- // closed, invalidated, etc.
- break;
- }
+ nr = read (fd, buf, 4095);
+ if (nr <= 0)
+ {
+ // closed, invalidated, etc.
+ break;
+ }
// truncate and log
buf[nr] = 0;
-
- vdev_error( "%s", buf );
- }
- return NULL;
-}
+ vdev_error ("%s", buf);
+ }
+ return NULL;
+}
// start the error-listining thread
// return 0 on success, and set state->error_thread
// return -errno on failure
-int vdev_error_thread_start( struct vdev_state* vdev ) {
+int
+vdev_error_thread_start (struct vdev_state *vdev)
+{
- int rc = 0;
- pthread_attr_t attrs;
+ int rc = 0;
+ pthread_attr_t attrs;
- rc = vdev_error_fifo_get_or_create( vdev->config->mountpoint, &vdev->error_fd );
- if( rc < 0 ) {
+ rc = vdev_error_fifo_get_or_create (vdev->config->mountpoint,
+ &vdev->error_fd);
+ if (rc < 0)
+ {
- vdev_error("vdev_error_fifo_get_or_create: %s\n", strerror(-rc) );
+ vdev_error ("vdev_error_fifo_get_or_create: %s\n", strerror (-rc));
return rc;
- }
+ }
- rc = pthread_attr_init( &attrs );
- if( rc != 0 ) {
+ rc = pthread_attr_init (&attrs);
+ if (rc != 0)
+ {
- vdev_error("pthread_attr_init: %s\n", strerror(rc) );
+ vdev_error ("pthread_attr_init: %s\n", strerror (rc));
return -rc;
- }
+ }
- vdev->error_thread_running = true;
+ vdev->error_thread_running = true;
- rc = pthread_create( &vdev->error_thread, &attrs, vdev_error_thread_main, &vdev->error_fd );
- if( rc != 0 ) {
+ rc = pthread_create (&vdev->error_thread, &attrs, vdev_error_thread_main,
+ &vdev->error_fd);
+ if (rc != 0)
+ {
vdev->error_thread_running = false;
- vdev_error("pthread_crate: %s\n", strerror(rc) );
+ vdev_error ("pthread_crate: %s\n", strerror (rc));
return -rc;
- }
+ }
- return 0;
+ return 0;
}
-
// stop the error-listening thread
// return 0 on success
-int vdev_error_thread_stop( struct vdev_state* vdev ) {
+int
+vdev_error_thread_stop (struct vdev_state *vdev)
+{
- int rc = 0;
- if( !vdev->error_thread_running ) {
+ int rc = 0;
+ if (!vdev->error_thread_running)
+ {
// already stopped
return 0;
- }
+ }
+
+ if (vdev->error_fd >= 0)
+ {
- if( vdev->error_fd >= 0 ) {
-
int fd = vdev->error_fd;
vdev->error_fd = -1;
- close( fd );
- }
+ close (fd);
+ }
- rc = pthread_cancel( vdev->error_thread );
- if( rc != 0 ) {
+ rc = pthread_cancel (vdev->error_thread);
+ if (rc != 0)
+ {
- vdev_error("pthread_cancel: %s\n", strerror(rc) );
- }
+ vdev_error ("pthread_cancel: %s\n", strerror (rc));
+ }
- rc = pthread_join( vdev->error_thread, NULL );
- if( rc != 0 ) {
+ rc = pthread_join (vdev->error_thread, NULL);
+ if (rc != 0)
+ {
- vdev_error("pthread_join: %s\n", strerror(rc) );
- }
+ vdev_error ("pthread_join: %s\n", strerror (rc));
+ }
- vdev->error_thread_running = false;
+ vdev->error_thread_running = false;
- return 0;
+ return 0;
}
-
// start up the back-end
// return 0 on success
// return -ENOMEM on OOM
// return negative if the OS-specific back-end fails to initialize
-int vdev_start( struct vdev_state* vdev ) {
-
- int rc = 0;
-
- // otherwise, it's already given
- vdev->running = true;
-
- // initialize OS-specific state, and start feeding requests
- vdev->os = VDEV_CALLOC( struct vdev_os_context, 1 );
-
- if( vdev->os == NULL ) {
-
+int
+vdev_start (struct vdev_state *vdev)
+{
+
+ int rc = 0;
+
+ // otherwise, it's already given
+ vdev->running = true;
+
+ // initialize OS-specific state, and start feeding requests
+ vdev->os = VDEV_CALLOC (struct vdev_os_context, 1);
+
+ if (vdev->os == NULL)
+ {
+
return -ENOMEM;
- }
-
- // set up error capture
- rc = vdev_error_thread_start( vdev );
- if( rc != 0 ) {
-
- vdev_error("vdev_error_thread_start: %s\n", strerror(-rc) );
- free( vdev->os );
+ }
+ // set up error capture
+ rc = vdev_error_thread_start (vdev);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_error_thread_start: %s\n", strerror (-rc));
+ free (vdev->os);
vdev->os = NULL;
return rc;
- }
+ }
+ // start processing requests
+ rc = vdev_wq_start (&vdev->device_wq);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_wq_start: %s\n", strerror (-rc));
- // start processing requests
- rc = vdev_wq_start( &vdev->device_wq );
- if( rc != 0 ) {
-
- vdev_error("vdev_wq_start: %s\n", strerror(-rc) );
-
- int erc = vdev_error_thread_stop( vdev );
- if( erc != 0 ) {
+ int erc = vdev_error_thread_stop (vdev);
+ if (erc != 0)
+ {
- vdev_error("vdev_error_thread_stop: %s\n", strerror(-erc) );
- }
+ vdev_error ("vdev_error_thread_stop: %s\n", strerror (-erc));
+ }
- free( vdev->os );
+ free (vdev->os);
vdev->os = NULL;
return rc;
- }
-
- rc = vdev_os_context_init( vdev->os, vdev );
-
- if( rc != 0 ) {
-
- vdev_error("vdev_os_context_init rc = %d\n", rc );
-
- int wqrc = vdev_wq_stop( &vdev->device_wq, false );
- if( wqrc != 0 ) {
-
- vdev_error("vdev_wq_stop rc = %d\n", wqrc);
- }
-
- vdev_error_thread_stop( vdev );
- free( vdev->os );
+ }
+
+ rc = vdev_os_context_init (vdev->os, vdev);
+
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_os_context_init rc = %d\n", rc);
+
+ int wqrc = vdev_wq_stop (&vdev->device_wq, false);
+ if (wqrc != 0)
+ {
+
+ vdev_error ("vdev_wq_stop rc = %d\n", wqrc);
+ }
+
+ vdev_error_thread_stop (vdev);
+ free (vdev->os);
vdev->os = NULL;
return rc;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// process a single line of text into a device request
//
@@ -555,166 +616,185 @@ int vdev_start( struct vdev_state* vdev ) {
// return -ENOENT if we're missing a parameter
// return -EINVAL if the parameter is malformed
// return -ENOMEM on OOM
-int vdev_parse_device_request( struct vdev_state* state, struct vdev_device_request* vreq, char* line ) {
-
- int rc = 0;
- int stat_rc;
- char* tok = NULL;
- char* tokstr = line;
- char* tok_ctx = NULL;
- char* tmp = NULL;
-
- mode_t mode = 0;
- dev_t major = 0;
- dev_t minor = 0;
- char name[4097];
- char fullpath[ PATH_MAX+1 ];
- char keyvalue_buf[4097];
- char* key = NULL;
- char* value = NULL;
-
- struct stat sb;
-
- // type
- tok = strtok_r( tokstr, " \t", &tok_ctx );
- tokstr = NULL;
-
- if( tok == NULL ) {
-
+int
+vdev_parse_device_request (struct vdev_state *state,
+ struct vdev_device_request *vreq, char *line)
+{
+
+ int rc = 0;
+ int stat_rc;
+ char *tok = NULL;
+ char *tokstr = line;
+ char *tok_ctx = NULL;
+ char *tmp = NULL;
+
+ mode_t mode = 0;
+ dev_t major = 0;
+ dev_t minor = 0;
+ char name[4097];
+ char fullpath[PATH_MAX + 1];
+ char keyvalue_buf[4097];
+ char *key = NULL;
+ char *value = NULL;
+
+ struct stat sb;
+
+ // type
+ tok = strtok_r (tokstr, " \t", &tok_ctx);
+ tokstr = NULL;
+
+ if (tok == NULL)
+ {
+
// no type
- fprintf(stderr, "Missing type\n");
+ fprintf (stderr, "Missing type\n");
return -ENOENT;
- }
-
- if( strlen(tok) != 1 ) {
-
+ }
+
+ if (strlen (tok) != 1)
+ {
+
// invalid type
- fprintf(stderr, "Unrecognized type '%s'. Expected 'c', 'b', or 'u'\n", tok );
+ fprintf (stderr,
+ "Unrecognized type '%s'. Expected 'c', 'b', or 'u'\n", tok);
return -EINVAL;
- }
-
- if( tok[0] != 'c' && tok[0] != 'b' && tok[0] != 'u' ) {
-
+ }
+
+ if (tok[0] != 'c' && tok[0] != 'b' && tok[0] != 'u')
+ {
+
// invalid type
- fprintf(stderr, "Unrecognized type '%s'. Expected 'c', 'b', or 'u'\n", tok );
+ fprintf (stderr,
+ "Unrecognized type '%s'. Expected 'c', 'b', or 'u'\n", tok);
return -EINVAL;
- }
-
- if( tok[0] == 'c' ) {
+ }
+
+ if (tok[0] == 'c')
+ {
mode = S_IFCHR;
- }
- else if( tok[0] == 'b' ) {
+ }
+ else if (tok[0] == 'b')
+ {
mode = S_IFBLK;
- }
-
- // name
- tok = strtok_r( tokstr, " \t", &tok_ctx );
- if( tok == NULL ) {
-
+ }
+ // name
+ tok = strtok_r (tokstr, " \t", &tok_ctx);
+ if (tok == NULL)
+ {
+
// no name
- fprintf(stderr, "Missing name\n");
+ fprintf (stderr, "Missing name\n");
return -ENOENT;
- }
-
- strcpy( name, tok );
-
- // major
- tok = strtok_r( tokstr, " \t", &tok_ctx );
- if( tok == NULL ) {
-
+ }
+
+ strcpy (name, tok);
+
+ // major
+ tok = strtok_r (tokstr, " \t", &tok_ctx);
+ if (tok == NULL)
+ {
+
// no major
- fprintf(stderr, "Missing major device number\n");
+ fprintf (stderr, "Missing major device number\n");
return -ENOENT;
- }
-
- major = (dev_t)strtoul( tok, &tmp, 10 );
- if( tmp == tok || *tmp != '\0' ) {
-
+ }
+
+ major = (dev_t) strtoul (tok, &tmp, 10);
+ if (tmp == tok || *tmp != '\0')
+ {
+
// invalid major
- fprintf(stderr, "Invalid major device number '%s'\n", tok );
+ fprintf (stderr, "Invalid major device number '%s'\n", tok);
return -EINVAL;
- }
-
- // minor
- tok = strtok_r( tokstr, " \t", &tok_ctx );
- if( tok == NULL ) {
-
+ }
+ // minor
+ tok = strtok_r (tokstr, " \t", &tok_ctx);
+ if (tok == NULL)
+ {
+
// no minor
- fprintf(stderr, "Missing minor device number\n");
+ fprintf (stderr, "Missing minor device number\n");
return -ENOENT;
- }
-
- minor = (dev_t)strtoul( tok, &tmp, 10 );
- if( tmp == tok || *tmp != '\0' ) {
-
+ }
+
+ minor = (dev_t) strtoul (tok, &tmp, 10);
+ if (tmp == tok || *tmp != '\0')
+ {
+
// invalid minor
- fprintf(stderr, "Invalid minor device number '%s'\n", tok );
+ fprintf (stderr, "Invalid minor device number '%s'\n", tok);
return -EINVAL;
- }
-
- // set up the device...
- rc = vdev_device_request_init( vreq, state, VDEV_DEVICE_ADD, name );
- if( rc != 0 ) {
-
- vdev_error("vdev_device_request_init('%s') rc = %d\n", name, rc );
+ }
+ // set up the device...
+ rc = vdev_device_request_init (vreq, state, VDEV_DEVICE_ADD, name);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_device_request_init('%s') rc = %d\n", name, rc);
return rc;
- }
-
- vdev_device_request_set_type( vreq, VDEV_DEVICE_ADD );
- vdev_device_request_set_mode( vreq, mode );
- vdev_device_request_set_dev( vreq, makedev( major, minor ) );
-
- // parameters
- while( tok != NULL ) {
-
- tok = strtok_r( tokstr, " \t", &tok_ctx );
- if( tok == NULL ) {
- break;
- }
-
- if( strlen(tok) > 4096 ) {
-
- // too big
- fprintf(stderr, "OS parameter too long: '%s'\n", tok );
- vdev_device_request_free( vreq );
- return -EINVAL;
- }
-
- strcpy( keyvalue_buf, tok );
-
- rc = vdev_keyvalue_next( keyvalue_buf, &key, &value );
- if( rc < 0 ) {
-
- // could not parse
- fprintf(stderr, "Unparsible OS parameter: '%s'\n", tok );
- vdev_device_request_free( vreq );
- return -EINVAL;
- }
-
- rc = vdev_device_request_add_param( vreq, key, value );
- if( rc != 0 ) {
-
- vdev_device_request_free( vreq );
- return rc;
- }
- }
-
- // finally, does this device exist already?
- snprintf( fullpath, PATH_MAX, "%s/%s", state->config->mountpoint, name );
- stat_rc = lstat( fullpath, &sb );
-
- if( stat_rc == 0 ) {
-
- vdev_device_request_set_exists( vreq, true );
- }
- else {
-
- vdev_device_request_set_exists( vreq, false );
- }
-
- return rc;
-}
+ }
+
+ vdev_device_request_set_type (vreq, VDEV_DEVICE_ADD);
+ vdev_device_request_set_mode (vreq, mode);
+ vdev_device_request_set_dev (vreq, makedev (major, minor));
+
+ // parameters
+ while (tok != NULL)
+ {
+ tok = strtok_r (tokstr, " \t", &tok_ctx);
+ if (tok == NULL)
+ {
+ break;
+ }
+
+ if (strlen (tok) > 4096)
+ {
+
+ // too big
+ fprintf (stderr, "OS parameter too long: '%s'\n", tok);
+ vdev_device_request_free (vreq);
+ return -EINVAL;
+ }
+
+ strcpy (keyvalue_buf, tok);
+
+ rc = vdev_keyvalue_next (keyvalue_buf, &key, &value);
+ if (rc < 0)
+ {
+
+ // could not parse
+ fprintf (stderr, "Unparsible OS parameter: '%s'\n", tok);
+ vdev_device_request_free (vreq);
+ return -EINVAL;
+ }
+
+ rc = vdev_device_request_add_param (vreq, key, value);
+ if (rc != 0)
+ {
+
+ vdev_device_request_free (vreq);
+ return rc;
+ }
+ }
+
+ // finally, does this device exist already?
+ snprintf (fullpath, PATH_MAX, "%s/%s", state->config->mountpoint, name);
+ stat_rc = lstat (fullpath, &sb);
+
+ if (stat_rc == 0)
+ {
+
+ vdev_device_request_set_exists (vreq, true);
+ }
+ else
+ {
+
+ vdev_device_request_set_exists (vreq, false);
+ }
+
+ return rc;
+}
// process a newline-delimited textual list of device events.
//
@@ -731,523 +811,600 @@ int vdev_parse_device_request( struct vdev_state* state, struct vdev_device_requ
// NOTE: currently, we do not tolerate spaces in any of these fields. Sorry.
// return 0 on success
// return -ERANGE if a line exceeded 4096 characters
-int vdev_load_device_requests( struct vdev_state* state, char* text_buf, size_t text_buflen ) {
-
- int rc = 0;
- char* cur_line = NULL;
- char* next_line = NULL;
-
- struct vdev_device_request* vreq = NULL;
-
- size_t consumed = 0;
- size_t line_len = 0;
- char line_buf[4097];
- char line_buf_dbg[4097]; // for debugging
-
- dev_t major = 0;
- dev_t minor = 0;
-
- cur_line = text_buf;
- while( consumed < text_buflen && cur_line != NULL ) {
-
- next_line = strchr( cur_line, '\n' );
- if( next_line == NULL ) {
-
- line_len = strlen( cur_line );
-
- if( line_len == 0 ) {
- // done
- break;
- }
-
- // last line
- if( line_len < 4096 ) {
-
- strcpy( line_buf, cur_line );
- }
- else {
-
- // too big
- return -ERANGE;
- }
- }
- else {
-
- // copy until '\n'
- line_len = (size_t)(next_line - cur_line) / sizeof(char);
- memcpy( line_buf, cur_line, line_len );
-
- line_buf[ line_len ] = '\0';
- }
-
- vdev_debug("Preseed device: '%s'\n", line_buf );
-
- strcpy( line_buf_dbg, line_buf );
-
- vreq = VDEV_CALLOC( struct vdev_device_request, 1 );
- if( vreq == NULL ) {
-
- // OOM
- return -ENOMEM;
- }
-
+int
+vdev_load_device_requests (struct vdev_state *state, char *text_buf,
+ size_t text_buflen)
+{
+
+ int rc = 0;
+ char *cur_line = NULL;
+ char *next_line = NULL;
+
+ struct vdev_device_request *vreq = NULL;
+
+ size_t consumed = 0;
+ size_t line_len = 0;
+ char line_buf[4097];
+ char line_buf_dbg[4097]; // for debugging
+
+ dev_t major = 0;
+ dev_t minor = 0;
+
+ cur_line = text_buf;
+ while (consumed < text_buflen && cur_line != NULL)
+ {
+
+ next_line = strchr (cur_line, '\n');
+ if (next_line == NULL)
+ {
+
+ line_len = strlen (cur_line);
+
+ if (line_len == 0)
+ {
+ // done
+ break;
+ }
+ // last line
+ if (line_len < 4096)
+ {
+
+ strcpy (line_buf, cur_line);
+ }
+ else
+ {
+
+ // too big
+ return -ERANGE;
+ }
+ }
+ else
+ {
+
+ // copy until '\n'
+ line_len = (size_t) (next_line - cur_line) / sizeof (char);
+ memcpy (line_buf, cur_line, line_len);
+
+ line_buf[line_len] = '\0';
+ }
+
+ vdev_debug ("Preseed device: '%s'\n", line_buf);
+
+ strcpy (line_buf_dbg, line_buf);
+
+ vreq = VDEV_CALLOC (struct vdev_device_request, 1);
+ if (vreq == NULL)
+ {
+
+ // OOM
+ return -ENOMEM;
+ }
// consume the line
- rc = vdev_parse_device_request( state, vreq, line_buf );
- if( rc != 0 ) {
-
- fprintf(stderr, "Could not parse line '%s' (rc = %d)\n", line_buf_dbg, rc );
- vdev_error("vdev_parse_device_request('%s') rc = %d\n", line_buf_dbg, rc );
-
- free( vreq );
- return rc;
- }
-
+ rc = vdev_parse_device_request (state, vreq, line_buf);
+ if (rc != 0)
+ {
+
+ fprintf (stderr, "Could not parse line '%s' (rc = %d)\n",
+ line_buf_dbg, rc);
+ vdev_error ("vdev_parse_device_request('%s') rc = %d\n",
+ line_buf_dbg, rc);
+
+ free (vreq);
+ return rc;
+ }
// enqueue the device!
- rc = vdev_device_request_enqueue( &state->device_wq, vreq );
- if( rc != 0 ) {
-
- vdev_error("vdev_device_request_enqueue('%s') rc = %d\n", line_buf_dbg, rc );
-
- free( vreq );
- return rc;
- }
-
+ rc = vdev_device_request_enqueue (&state->device_wq, vreq);
+ if (rc != 0)
+ {
+
+ vdev_error
+ ("vdev_device_request_enqueue('%s') rc = %d\n", line_buf_dbg, rc);
+
+ free (vreq);
+ return rc;
+ }
// next line
cur_line = next_line;
- consumed += strlen(next_line);
-
- while( consumed < text_buflen && *cur_line == '\n' ) {
-
- cur_line++;
- consumed++;
- }
- }
-
- return rc;
-}
+ consumed += strlen (next_line);
+ while (consumed < text_buflen && *cur_line == '\n')
+ {
+
+ cur_line++;
+ consumed++;
+ }
+ }
+
+ return rc;
+}
// run the pre-seed command, if given
// return 0 on success
// return -ENOMEM on OOM
// return non-zero on non-zero exit status
// TODO: "unlimited" output buffer space--like a pipe
-int vdev_preseed_run( struct vdev_state* vdev ) {
-
- int rc = 0;
- int exit_status = 0;
- char* command = NULL;
-
- size_t output_len = 1024 * 1024; // 1MB buffer for initial devices, just in case
- char* output = NULL;
-
- if( vdev->config->preseed_path == NULL ) {
+int
+vdev_preseed_run (struct vdev_state *vdev)
+{
+
+ int rc = 0;
+ int exit_status = 0;
+ char *command = NULL;
+
+ size_t output_len = 1024 * 1024; // 1MB buffer for initial devices, just in case
+ char *output = NULL;
+
+ if (vdev->config->preseed_path == NULL)
+ {
// nothing to do
return 0;
- }
-
- output = VDEV_CALLOC( char, output_len );
- if( output == NULL ) {
-
+ }
+
+ output = VDEV_CALLOC (char, output_len);
+ if (output == NULL)
+ {
+
// OOM
return -ENOMEM;
- }
-
- command = VDEV_CALLOC( char, strlen( vdev->config->preseed_path ) + 2 + strlen( vdev->config->mountpoint ) + 2 + strlen( vdev->config->config_path ) + 1 );
- if( command == NULL ) {
-
+ }
+
+ command =
+ VDEV_CALLOC (char,
+ strlen (vdev->config->preseed_path) + 2 +
+ strlen (vdev->config->mountpoint) + 2 +
+ strlen (vdev->config->config_path) + 1);
+ if (command == NULL)
+ {
+
// OOM
- free( output );
+ free (output);
return -ENOMEM;
- }
-
- sprintf(command, "%s %s %s", vdev->config->preseed_path, vdev->config->mountpoint, vdev->config->config_path );
-
- rc = vdev_subprocess( command, NULL, &output, output_len, -1, &exit_status, true );
- if( rc != 0 ) {
-
- vdev_error("vdev_subprocess('%s') rc = %d\n", command, rc );
- }
- else if( exit_status != 0 ) {
-
- vdev_error("vdev_subprocess('%s') exit status %d\n", command, exit_status );
+ }
+
+ sprintf (command, "%s %s %s", vdev->config->preseed_path,
+ vdev->config->mountpoint, vdev->config->config_path);
+
+ rc = vdev_subprocess (command, NULL, &output, output_len, -1,
+ &exit_status, true);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_subprocess('%s') rc = %d\n", command, rc);
+ }
+ else if (exit_status != 0)
+ {
+
+ vdev_error ("vdev_subprocess('%s') exit status %d\n", command,
+ exit_status);
rc = exit_status;
- }
-
- free( command );
- command = NULL;
-
- if( rc != 0 ) {
-
- free( output );
+ }
+
+ free (command);
+ command = NULL;
+
+ if (rc != 0)
+ {
+
+ free (output);
return rc;
- }
-
- // process the preseed devices...
- rc = vdev_load_device_requests( vdev, output, output_len );
- if( rc != 0 ) {
-
- vdev_error("vdev_load_device_requests rc = %d\n", rc);
- }
-
- free( output );
- output = NULL;
-
- return rc;
-}
+ }
+ // process the preseed devices...
+ rc = vdev_load_device_requests (vdev, output, output_len);
+ if (rc != 0)
+ {
+ vdev_error ("vdev_load_device_requests rc = %d\n", rc);
+ }
+
+ free (output);
+ output = NULL;
+
+ return rc;
+}
// global vdev initialization
-int vdev_init( struct vdev_state* vdev, int argc, char** argv ) {
-
- int rc = 0;
-
- // global setup
- vdev_setup_global();
-
- pthread_mutex_init( &vdev->reload_lock, NULL );
- vdev->error_fd = -1;
- vdev->coldplug_finished_fd = -1;
-
- // config...
- vdev->config = VDEV_CALLOC( struct vdev_config, 1 );
- if( vdev->config == NULL ) {
-
+int
+vdev_init (struct vdev_state *vdev, int argc, char **argv)
+{
+
+ int rc = 0;
+
+ // global setup
+ vdev_setup_global ();
+
+ pthread_mutex_init (&vdev->reload_lock, NULL);
+ vdev->error_fd = -1;
+ vdev->coldplug_finished_fd = -1;
+
+ // config...
+ vdev->config = VDEV_CALLOC (struct vdev_config, 1);
+ if (vdev->config == NULL)
+ {
+
return -ENOMEM;
- }
-
- // config init
- rc = vdev_config_init( vdev->config );
- if( rc != 0 ) {
-
- vdev_error("vdev_config_init rc = %d\n", rc );
+ }
+ // config init
+ rc = vdev_config_init (vdev->config);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_config_init rc = %d\n", rc);
return rc;
- }
-
- // parse config options from command-line
- rc = vdev_config_load_from_args( vdev->config, argc, argv, NULL, NULL );
-
- if( rc != 0 ) {
-
- vdev_error("vdev_config_load_from_argv rc = %d\n", rc );
-
- vdev_config_usage( argv[0] );
-
+ }
+ // parse config options from command-line
+ rc = vdev_config_load_from_args (vdev->config, argc, argv, NULL, NULL);
+ // help is not an error
+ if (rc == -2)
+ {
+
+ vdev_config_usage (argv[0]);
+
+ return 0;
+
+ }
+
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_config_load_from_argv rc = %d\n", rc);
+
+ vdev_config_usage (argv[0]);
+
return rc;
- }
-
- // if we didn't get a config file, use the default one
- if( vdev->config->config_path == NULL ) {
-
- vdev->config->config_path = vdev_strdup_or_null( VDEV_CONFIG_FILE );
- if( vdev->config->config_path == NULL ) {
-
- // OOM
- return -ENOMEM;
- }
- }
-
- vdev_set_debug_level( vdev->config->debug_level );
- vdev_set_error_level( vdev->config->error_level );
-
- vdev_info("Config file: '%s'\n", vdev->config->config_path );
- vdev_info("Log debug level: '%s'\n", (vdev->config->debug_level == VDEV_LOGLEVEL_DEBUG ? "debug" : (vdev->config->debug_level == VDEV_LOGLEVEL_INFO ? "info" : "none")) );
- vdev_info("Log error level: '%s'\n", (vdev->config->error_level == VDEV_LOGLEVEL_WARN ? "warning" : (vdev->config->error_level == VDEV_LOGLEVEL_ERROR ? "error" : "none")) );
-
- // load from file...
- rc = vdev_config_load( vdev->config->config_path, vdev->config );
- if( rc != 0 ) {
-
- vdev_error("vdev_config_load('%s') rc = %d\n", vdev->config->config_path, rc );
-
+ }
+ // if we didn't get a config file, use the default one
+ if (vdev->config->config_path == NULL)
+ {
+
+ vdev->config->config_path = vdev_strdup_or_null (VDEV_CONFIG_FILE);
+ if (vdev->config->config_path == NULL)
+ {
+
+ // OOM
+ return -ENOMEM;
+ }
+ }
+
+ vdev_set_debug_level (vdev->config->debug_level);
+ vdev_set_error_level (vdev->config->error_level);
+
+ vdev_info ("Config file: '%s'\n", vdev->config->config_path);
+ vdev_info ("Log debug level: '%s'\n",
+ (vdev->config->debug_level ==
+ VDEV_LOGLEVEL_DEBUG ? "debug" : (vdev->config->debug_level ==
+ VDEV_LOGLEVEL_INFO ? "info"
+ : "none")));
+ vdev_info ("Log error level: '%s'\n",
+ (vdev->config->error_level ==
+ VDEV_LOGLEVEL_WARN ? "warning" : (vdev->config->error_level ==
+ VDEV_LOGLEVEL_ERROR ?
+ "error" : "none")));
+
+ // load from file...
+ rc = vdev_config_load (vdev->config->config_path, vdev->config);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_config_load('%s') rc = %d\n",
+ vdev->config->config_path, rc);
+
return rc;
- }
-
- // if no command-line loglevel is given, then take it from the config file (if given)
- if( vdev->config->debug_level != VDEV_LOGLEVEL_NONE ) {
-
- vdev_set_debug_level( vdev->config->debug_level );
- }
-
- if( vdev->config->error_level != VDEV_LOGLEVEL_NONE ) {
-
- vdev_set_error_level( vdev->config->error_level );
- }
-
- vdev_info("vdev actions dir: '%s'\n", vdev->config->acts_dir );
- vdev_info("helpers dir: '%s'\n", vdev->config->helpers_dir );
- vdev_info("logfile path: '%s'\n", vdev->config->logfile_path );
- vdev_info("pidfile path: '%s'\n", vdev->config->pidfile_path );
- vdev_info("default mode: 0%o\n", vdev->config->default_mode );
- vdev_info("preseed script: '%s'\n", vdev->config->preseed_path );
-
- vdev->mountpoint = vdev_strdup_or_null( vdev->config->mountpoint );
- vdev->coldplug_only = vdev->config->coldplug_only;
-
- if( vdev->mountpoint == NULL ) {
-
- vdev_error("Failed to set mountpoint, config->mountpount = '%s'\n", vdev->config->mountpoint );
-
+ }
+ // if no command-line loglevel is given, then take it from the config file (if given)
+ if (vdev->config->debug_level != VDEV_LOGLEVEL_NONE)
+ {
+
+ vdev_set_debug_level (vdev->config->debug_level);
+ }
+
+ if (vdev->config->error_level != VDEV_LOGLEVEL_NONE)
+ {
+
+ vdev_set_error_level (vdev->config->error_level);
+ }
+
+ vdev_info ("vdev actions dir: '%s'\n", vdev->config->acts_dir);
+ vdev_info ("helpers dir: '%s'\n", vdev->config->helpers_dir);
+ vdev_info ("logfile path: '%s'\n", vdev->config->logfile_path);
+ vdev_info ("pidfile path: '%s'\n", vdev->config->pidfile_path);
+ vdev_info ("default mode: 0%o\n", vdev->config->default_mode);
+ vdev_info ("preseed script: '%s'\n", vdev->config->preseed_path);
+
+ vdev->mountpoint = vdev_strdup_or_null (vdev->config->mountpoint);
+ vdev->coldplug_only = vdev->config->coldplug_only;
+
+ if (vdev->mountpoint == NULL)
+ {
+
+ vdev_error
+ ("Failed to set mountpoint, config->mountpount = '%s'\n",
+ vdev->config->mountpoint);
+
return -EINVAL;
- }
- else {
-
- vdev_info("mountpoint: '%s'\n", vdev->mountpoint );
- }
-
- vdev->argc = argc;
- vdev->argv = argv;
-
- // load actions
- rc = vdev_action_load_all( vdev->config, &vdev->acts, &vdev->num_acts );
- if( rc != 0) {
-
- vdev_error("vdev_action_load_all('%s') rc = %d\n", vdev->config->acts_dir, rc );
-
+ }
+ else
+ {
+
+ vdev_info ("mountpoint: '%s'\n", vdev->mountpoint);
+ }
+
+ vdev->argc = argc;
+ vdev->argv = argv;
+
+ // load actions
+ rc = vdev_action_load_all (vdev->config, &vdev->acts, &vdev->num_acts);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_action_load_all('%s') rc = %d\n",
+ vdev->config->acts_dir, rc);
+
return rc;
- }
-
- // initialize request work queue
- rc = vdev_wq_init( &vdev->device_wq, vdev );
- if( rc != 0 ) {
-
- vdev_error("vdev_wq_init rc = %d\n", rc );
-
+ }
+ // initialize request work queue
+ rc = vdev_wq_init (&vdev->device_wq, vdev);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_wq_init rc = %d\n", rc);
+
return rc;
- }
+ }
- return 0;
+ return 0;
}
-
// main loop for the back-end
// takes a file descriptor to be written to once coldplug processing has finished.
// return 0 on success
// return -errno on failure to daemonize, or abnormal OS-specific back-end failure
-int vdev_main( struct vdev_state* vdev, int coldplug_finished_fd ) {
-
- int rc = 0;
-
- vdev->coldplug_finished_fd = coldplug_finished_fd;
-
- char* metadata_dir = vdev_device_metadata_fullpath( vdev->mountpoint, "" );
- if( metadata_dir == NULL ) {
-
+int
+vdev_main (struct vdev_state *vdev, int coldplug_finished_fd)
+{
+
+ int rc = 0;
+
+ vdev->coldplug_finished_fd = coldplug_finished_fd;
+
+ char *metadata_dir = vdev_device_metadata_fullpath (vdev->mountpoint, "");
+ if (metadata_dir == NULL)
+ {
+
return -ENOMEM;
- }
-
- // create metadata directory
- rc = vdev_mkdirs( metadata_dir, 0, 0755 );
-
- if( rc != 0 ) {
-
- vdev_error("vdev_mkdirs('%s') rc = %d\n", metadata_dir, rc );
-
- free( metadata_dir );
+ }
+ // create metadata directory
+ rc = vdev_mkdirs (metadata_dir, 0, 0755);
+
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_mkdirs('%s') rc = %d\n", metadata_dir, rc);
+
+ free (metadata_dir);
return rc;
- }
-
- free( metadata_dir );
-
- rc = vdev_os_main( vdev->os );
-
- return rc;
-}
+ }
+
+ free (metadata_dir);
+ rc = vdev_os_main (vdev->os);
+
+ return rc;
+}
// signal that we've processed all coldplug devices
-int vdev_signal_coldplug_finished( struct vdev_state* vdev, int status ) {
-
- if( vdev->coldplug_finished_fd > 0 ) {
- write( vdev->coldplug_finished_fd, &status, sizeof(status));
- close( vdev->coldplug_finished_fd );
+int
+vdev_signal_coldplug_finished (struct vdev_state *vdev, int status)
+{
+
+ if (vdev->coldplug_finished_fd > 0)
+ {
+ write (vdev->coldplug_finished_fd, &status, sizeof (status));
+ close (vdev->coldplug_finished_fd);
vdev->coldplug_finished_fd = -1;
- }
-
- return 0;
-}
+ }
+ return 0;
+}
// prevent reload
-int vdev_reload_lock( struct vdev_state* vdev ) {
- return pthread_mutex_lock( &vdev->reload_lock );
+int
+vdev_reload_lock (struct vdev_state *vdev)
+{
+ return pthread_mutex_lock (&vdev->reload_lock);
}
-
// allow reload
-int vdev_reload_unlock( struct vdev_state* vdev ) {
- return pthread_mutex_unlock( &vdev->reload_lock );
+int
+vdev_reload_unlock (struct vdev_state *vdev)
+{
+ return pthread_mutex_unlock (&vdev->reload_lock);
}
-
// do a reload
// return 0 on success, and replace the config and actions, atomically
// return -errno on failure, and do nothing to vdev
-int vdev_reload( struct vdev_state* vdev ) {
-
- int rc = 0;
- struct vdev_config* config = NULL;
- struct vdev_action* acts = NULL;
- size_t num_acts = 0;
-
- struct vdev_config* old_config = NULL;
- struct vdev_action* old_acts = NULL;
- size_t old_num_acts = 0;
-
- config = VDEV_CALLOC( struct vdev_config, 1 );
- if( config == NULL ) {
+int
+vdev_reload (struct vdev_state *vdev)
+{
+
+ int rc = 0;
+ struct vdev_config *config = NULL;
+ struct vdev_action *acts = NULL;
+ size_t num_acts = 0;
+
+ struct vdev_config *old_config = NULL;
+ struct vdev_action *old_acts = NULL;
+ size_t old_num_acts = 0;
+
+ config = VDEV_CALLOC (struct vdev_config, 1);
+ if (config == NULL)
+ {
return -ENOMEM;
- }
+ }
+ // config init
+ rc = vdev_config_init (config);
+ if (rc != 0)
+ {
- // config init
- rc = vdev_config_init( config );
- if( rc != 0 ) {
-
- vdev_error("vdev_config_init rc = %d\n", rc );
+ vdev_error ("vdev_config_init rc = %d\n", rc);
return rc;
- }
+ }
- if( config->config_path == NULL ) {
+ if (config->config_path == NULL)
+ {
// default
- config->config_path = vdev_strdup_or_null( VDEV_CONFIG_FILE );
- if( config->config_path == NULL ) {
-
- vdev_config_free( config );
- free( config );
- return -ENOMEM;
- }
- }
-
- // parse config options from command-line
- rc = vdev_config_load_from_args( config, vdev->argc, vdev->argv, NULL, NULL );
- if( rc != 0 ) {
-
- vdev_error("vdev_config_load_from_argv rc = %d\n", rc );
+ config->config_path = vdev_strdup_or_null (VDEV_CONFIG_FILE);
+ if (config->config_path == NULL)
+ {
+
+ vdev_config_free (config);
+ free (config);
+ return -ENOMEM;
+ }
+ }
+ // parse config options from command-line
+ rc = vdev_config_load_from_args (config, vdev->argc, vdev->argv, NULL,
+ NULL);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_config_load_from_argv rc = %d\n", rc);
return rc;
- }
-
- // load from file...
- rc = vdev_config_load( config->config_path, config );
- if( rc != 0 ) {
-
- vdev_error("vdev_config_load('%s') rc = %d\n", config->config_path, rc );
-
- vdev_config_free( config );
- free( config );
+ }
+ // load from file...
+ rc = vdev_config_load (config->config_path, config);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_config_load('%s') rc = %d\n",
+ config->config_path, rc);
+
+ vdev_config_free (config);
+ free (config);
return rc;
- }
-
- // load actions
- rc = vdev_action_load_all( config, &acts, &num_acts );
- if( rc != 0) {
-
- vdev_error("vdev_action_load_all('%s') rc = %d\n", config->acts_dir, rc );
-
- vdev_config_free( config );
- free( config );
+ }
+ // load actions
+ rc = vdev_action_load_all (config, &acts, &num_acts);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_action_load_all('%s') rc = %d\n",
+ config->acts_dir, rc);
+
+ vdev_config_free (config);
+ free (config);
return rc;
- }
+ }
+ // install them
+ vdev_reload_lock (vdev);
- // install them
- vdev_reload_lock( vdev );
+ old_config = vdev->config;
+ vdev->config = config;
- old_config = vdev->config;
- vdev->config = config;
+ old_acts = vdev->acts;
+ old_num_acts = vdev->num_acts;
+ vdev->acts = acts;
+ vdev->num_acts = num_acts;
- old_acts = vdev->acts;
- old_num_acts = vdev->num_acts;
- vdev->acts = acts;
- vdev->num_acts = num_acts;
-
- vdev_reload_unlock( vdev );
+ vdev_reload_unlock (vdev);
- // free old state
- vdev_config_free( old_config );
- free( old_config );
+ // free old state
+ vdev_config_free (old_config);
+ free (old_config);
- vdev_action_free_all( old_acts, old_num_acts );
+ vdev_action_free_all (old_acts, old_num_acts);
- return rc;
+ return rc;
}
// stop vdev
// NOTE: if this fails, there's not really a way to recover
// return 0 on success
// return non-zero if we failed to stop the work queue
-int vdev_stop( struct vdev_state* vdev ) {
-
- int rc = 0;
- bool wait_for_empty = false;
-
- if( !vdev->running ) {
+int
+vdev_stop (struct vdev_state *vdev)
+{
+
+ int rc = 0;
+ bool wait_for_empty = false;
+
+ if (!vdev->running)
+ {
return -EINVAL;
- }
-
- vdev->running = false;
- wait_for_empty = vdev->coldplug_only; // wait for the queue to drain if running coldplug only
-
- // stop processing requests
- rc = vdev_wq_stop( &vdev->device_wq, wait_for_empty );
- if( rc != 0 ) {
-
- vdev_error("vdev_wq_stop: %s\n", strerror(-rc) );
+ }
+
+ vdev->running = false;
+ wait_for_empty = vdev->coldplug_only; // wait for the queue to drain if running coldplug only
+
+ // stop processing requests
+ rc = vdev_wq_stop (&vdev->device_wq, wait_for_empty);
+ if (rc != 0)
+ {
+
+ vdev_error ("vdev_wq_stop: %s\n", strerror (-rc));
return rc;
- }
-
- // stop all actions' daemonlets
- vdev_action_daemonlet_stop_all( vdev->acts, vdev->num_acts );
- return rc;
+ }
+ // stop all actions' daemonlets
+ vdev_action_daemonlet_stop_all (vdev->acts, vdev->num_acts);
+ return rc;
}
// free up vdev.
// only call after vdev_stop().
// return 0 on success, and print out benchmarks
// return -EINVAL if we're still running.
-int vdev_shutdown( struct vdev_state* vdev, bool unlink_pidfile ) {
-
- if( vdev->running ) {
+int
+vdev_shutdown (struct vdev_state *vdev, bool unlink_pidfile)
+{
+
+ if (vdev->running)
+ {
return -EINVAL;
- }
-
- vdev_debug("%s", "vdev shutdown\n" );
-
- // stop error thread--all daemonlets should be dead anyway
- int erc = vdev_error_thread_stop( vdev );
- if( erc != 0 ) {
-
- vdev_error("vdev_error_thread_stop: %s\n", strerror(-erc) );
- }
-
- // remove the PID file, if we have one
- if( vdev->config->pidfile_path != NULL && unlink_pidfile ) {
- unlink( vdev->config->pidfile_path );
- }
-
- vdev_action_free_all( vdev->acts, vdev->num_acts );
-
- vdev->acts = NULL;
- vdev->num_acts = 0;
-
- if( vdev->os != NULL ) {
- vdev_os_context_free( vdev->os );
- free( vdev->os );
+ }
+
+ vdev_debug ("%s", "vdev shutdown\n");
+
+ // stop error thread--all daemonlets should be dead anyway
+ int erc = vdev_error_thread_stop (vdev);
+ if (erc != 0)
+ {
+
+ vdev_error ("vdev_error_thread_stop: %s\n", strerror (-erc));
+ }
+ // remove the PID file, if we have one
+ if (vdev->config->pidfile_path != NULL && unlink_pidfile)
+ {
+ unlink (vdev->config->pidfile_path);
+ }
+
+ vdev_action_free_all (vdev->acts, vdev->num_acts);
+
+ vdev->acts = NULL;
+ vdev->num_acts = 0;
+
+ if (vdev->os != NULL)
+ {
+ vdev_os_context_free (vdev->os);
+ free (vdev->os);
vdev->os = NULL;
- }
-
- if( vdev->config != NULL ) {
- vdev_config_free( vdev->config );
- free( vdev->config );
+ }
+
+ if (vdev->config != NULL)
+ {
+ vdev_config_free (vdev->config);
+ free (vdev->config);
vdev->config = NULL;
- }
-
- vdev_wq_free( &vdev->device_wq );
-
- if( vdev->mountpoint != NULL ) {
- free( vdev->mountpoint );
+ }
+
+ vdev_wq_free (&vdev->device_wq);
+
+ if (vdev->mountpoint != NULL)
+ {
+ free (vdev->mountpoint);
vdev->mountpoint = NULL;
- }
+ }
+
+ pthread_mutex_destroy (&vdev->reload_lock);
- pthread_mutex_destroy( &vdev->reload_lock );
-
- return 0;
+ return 0;
}
diff --git a/vdevd/vdev.h b/vdevd/vdev.h
index 32c1c65..b7aa73e 100644
--- a/vdevd/vdev.h
+++ b/vdevd/vdev.h
@@ -33,76 +33,74 @@
#endif
// global vdev state
-struct vdev_state {
-
- // configuration (covered by reload_lock)
- struct vdev_config* config;
-
- // arguments
- int argc;
- char** argv;
-
- // mountpoint; where /dev is
- char* mountpoint;
-
- // OS context
- struct vdev_os_context* os;
-
- // actions (covered by reload_lock)
- struct vdev_action* acts;
- size_t num_acts;
-
- // pending requests
- struct vdev_pending_context* pending;
-
- // device processing workqueue (back-end)
- struct vdev_wq device_wq;
-
- // are we taking events from the OS? (back-end)
- bool running;
-
- // coldplug only?
- bool coldplug_only;
-
- // fd to signal the end of coldplug
- int coldplug_finished_fd;
-
- // error thread that listens to an error FIFO
- // that helper processes use to send error
- // messages to vdev's log
- bool error_thread_running;
- pthread_t error_thread;
-
- // fd to the error pipe, to be passed to subprocesses
- // in place of stderr
- int error_fd;
-
- // reload lock--held when reloading the config
- pthread_mutex_t reload_lock;
-};
+struct vdev_state
+{
+
+ // configuration (covered by reload_lock)
+ struct vdev_config *config;
+
+ // arguments
+ int argc;
+ char **argv;
+
+ // mountpoint; where /dev is
+ char *mountpoint;
+
+ // OS context
+ struct vdev_os_context *os;
+
+ // actions (covered by reload_lock)
+ struct vdev_action *acts;
+ size_t num_acts;
-typedef char* cstr;
+ // pending requests
+ struct vdev_pending_context *pending;
-C_LINKAGE_BEGIN
+ // device processing workqueue (back-end)
+ struct vdev_wq device_wq;
-int vdev_init( struct vdev_state* vdev, int argc, char** argv );
-int vdev_start( struct vdev_state* vdev );
-int vdev_main( struct vdev_state* vdev, int flush_fd );
-int vdev_reload( struct vdev_state* vdev );
-int vdev_stop( struct vdev_state* vdev );
-int vdev_shutdown( struct vdev_state* vdev, bool unlink_pidfile );
+ // are we taking events from the OS? (back-end)
+ bool running;
+
+ // coldplug only?
+ bool coldplug_only;
+
+ // fd to signal the end of coldplug
+ int coldplug_finished_fd;
+
+ // error thread that listens to an error FIFO
+ // that helper processes use to send error
+ // messages to vdev's log
+ bool error_thread_running;
+ pthread_t error_thread;
+
+ // fd to the error pipe, to be passed to subprocesses
+ // in place of stderr
+ int error_fd;
+
+ // reload lock--held when reloading the config
+ pthread_mutex_t reload_lock;
+};
-int vdev_reload_lock( struct vdev_state* vdev );
-int vdev_reload_unlock( struct vdev_state* vdev );
+typedef char *cstr;
-int vdev_error_fifo_path( char const* mountpoint, char* path, size_t path_len );
-int vdev_signal_coldplug_finished( struct vdev_state* state, int status );
+C_LINKAGE_BEGIN int vdev_init (struct vdev_state *vdev, int argc,
+ char **argv);
+int vdev_start (struct vdev_state *vdev);
+int vdev_main (struct vdev_state *vdev, int flush_fd);
+int vdev_reload (struct vdev_state *vdev);
+int vdev_stop (struct vdev_state *vdev);
+int vdev_shutdown (struct vdev_state *vdev, bool unlink_pidfile);
-int vdev_preseed_run( struct vdev_state* state );
-int vdev_remove_unplugged_devices( struct vdev_state* state );
+int vdev_reload_lock (struct vdev_state *vdev);
+int vdev_reload_unlock (struct vdev_state *vdev);
-SGLIB_DEFINE_VECTOR_PROTOTYPES( cstr );
+int vdev_error_fifo_path (char const *mountpoint, char *path,
+ size_t path_len);
+int vdev_signal_coldplug_finished (struct vdev_state *state, int status);
-C_LINKAGE_END
+int vdev_preseed_run (struct vdev_state *state);
+int vdev_remove_unplugged_devices (struct vdev_state *state);
+SGLIB_DEFINE_VECTOR_PROTOTYPES (cstr) C_LINKAGE_END
#endif
diff --git a/vdevd/workqueue.c b/vdevd/workqueue.c
index e18c365..0cb2e39 100644
--- a/vdevd/workqueue.c
+++ b/vdevd/workqueue.c
@@ -25,318 +25,356 @@
#include "vdev.h"
// wait for the queue to be drained of coldplug events
-static void vdev_wq_wait_for_empty( struct vdev_wq* wq ) {
-
- pthread_mutex_lock( &wq->waiter_lock );
-
- wq->num_waiters++;
-
- pthread_mutex_unlock( &wq->waiter_lock );
-
- sem_wait( &wq->end_sem );
-}
+static void
+vdev_wq_wait_for_empty (struct vdev_wq *wq)
+{
+ pthread_mutex_lock (&wq->waiter_lock);
-// signal any waiting threads that the queue has been drained of coldplug events
-static void vdev_wq_signal_empty( struct vdev_wq* wq ) {
-
- volatile int num_waiters = 0;
-
- pthread_mutex_lock( &wq->waiter_lock );
-
- num_waiters = wq->num_waiters;
- wq->num_waiters = 0;
-
- pthread_mutex_unlock( &wq->waiter_lock );
-
- for( int i = 0; i < num_waiters; i++ ) {
-
- sem_post( &wq->end_sem );
- }
+ wq->num_waiters++;
+
+ pthread_mutex_unlock (&wq->waiter_lock);
+
+ sem_wait (&wq->end_sem);
}
+// signal any waiting threads that the queue has been drained of coldplug events
+static void
+vdev_wq_signal_empty (struct vdev_wq *wq)
+{
+
+ volatile int num_waiters = 0;
+
+ pthread_mutex_lock (&wq->waiter_lock);
+
+ num_waiters = wq->num_waiters;
+ wq->num_waiters = 0;
+
+ pthread_mutex_unlock (&wq->waiter_lock);
+
+ for (int i = 0; i < num_waiters; i++)
+ {
+
+ sem_post (&wq->end_sem);
+ }
+}
// work queue main method
// always succeeds
-static void* vdev_wq_main( void* cls ) {
+static void *
+vdev_wq_main (void *cls)
+{
+
+ struct vdev_wq *wq = (struct vdev_wq *) cls;
+
+ struct vdev_wreq *work_itr = NULL;
+ struct vdev_wreq *next = NULL;
- struct vdev_wq* wq = (struct vdev_wq*)cls;
-
- struct vdev_wreq* work_itr = NULL;
- struct vdev_wreq* next = NULL;
-
- struct vdev_state* state = wq->state;
-
- bool coldplug_finished = false;
-
- int rc = 0;
+ struct vdev_state *state = wq->state;
- while( wq->running ) {
+ bool coldplug_finished = false;
+
+ int rc = 0;
+
+ while (wq->running)
+ {
// is there work?
- rc = sem_trywait( &wq->work_sem );
- if( rc != 0 ) {
-
- rc = -errno;
- if( rc == -EAGAIN ) {
-
- // wait for work
- sem_wait( &wq->work_sem );
- }
- else {
-
- // some other fatal error
- vdev_error("FATAL: sem_trywait rc = %d\n", rc );
- break;
- }
- }
-
+ rc = sem_trywait (&wq->work_sem);
+ if (rc != 0)
+ {
+
+ rc = -errno;
+ if (rc == -EAGAIN)
+ {
+
+ // wait for work
+ sem_wait (&wq->work_sem);
+ }
+ else
+ {
+
+ // some other fatal error
+ vdev_error ("FATAL: sem_trywait rc = %d\n", rc);
+ break;
+ }
+ }
// cancelled?
- if( !wq->running ) {
- break;
- }
-
+ if (!wq->running)
+ {
+ break;
+ }
// we have work to do
- pthread_mutex_lock( &wq->work_lock );
+ pthread_mutex_lock (&wq->work_lock);
work_itr = wq->work;
wq->work = NULL;
wq->tail = NULL;
-
- pthread_mutex_unlock( &wq->work_lock );
-
- if( !coldplug_finished ) {
- coldplug_finished = vdev_os_context_is_coldplug_finished( state->os );
- }
-
- if( work_itr == NULL ) {
-
- vdev_wq_signal_empty( wq );
-
- if( coldplug_finished ) {
-
- // coldplug has finished! signal the parent to exit.
- vdev_signal_coldplug_finished( state, 0 );
- }
-
- continue;
- }
+ pthread_mutex_unlock (&wq->work_lock);
+
+ if (!coldplug_finished)
+ {
+ coldplug_finished =
+ vdev_os_context_is_coldplug_finished (state->os);
+ }
+
+ if (work_itr == NULL)
+ {
+
+ vdev_wq_signal_empty (wq);
+
+ if (coldplug_finished)
+ {
+
+ // coldplug has finished! signal the parent to exit.
+ vdev_signal_coldplug_finished (state, 0);
+ }
+
+ continue;
+ }
// safe to use work buffer (we'll clear it out in the process)
- while( work_itr != NULL ) {
-
- // carry out work
- rc = (*work_itr->work)( work_itr, work_itr->work_data );
-
- if( rc != 0 ) {
-
- vdev_warn("work %p rc = %d\n", work_itr->work, rc );
- }
-
- next = work_itr->next;
-
- vdev_wreq_free( work_itr );
- free( work_itr );
-
- work_itr = next;
- }
- }
-
- return NULL;
+ while (work_itr != NULL)
+ {
+
+ // carry out work
+ rc = (*work_itr->work) (work_itr, work_itr->work_data);
+
+ if (rc != 0)
+ {
+
+ vdev_warn ("work %p rc = %d\n", work_itr->work, rc);
+ }
+
+ next = work_itr->next;
+
+ vdev_wreq_free (work_itr);
+ free (work_itr);
+
+ work_itr = next;
+ }
+ }
+
+ return NULL;
}
// set up a work queue, but don't start it.
// return 0 on success
// return negative on failure:
// * -ENOMEM if OOM
-int vdev_wq_init( struct vdev_wq* wq, struct vdev_state* state ) {
-
- int rc = 0;
-
- memset( wq, 0, sizeof(struct vdev_wq) );
-
- rc = pthread_mutex_init( &wq->work_lock, NULL );
- if( rc != 0 ) {
-
- return -abs(rc);
- }
-
- rc = pthread_mutex_init( &wq->waiter_lock, NULL );
- if( rc != 0 ) {
-
- pthread_mutex_destroy( &wq->work_lock );
- return -abs(rc);
- }
-
- sem_init( &wq->work_sem, 0, 0 );
- sem_init( &wq->end_sem, 0, 0 );
-
- wq->state = state;
-
- return rc;
-}
+int
+vdev_wq_init (struct vdev_wq *wq, struct vdev_state *state)
+{
+
+ int rc = 0;
+
+ memset (wq, 0, sizeof (struct vdev_wq));
+
+ rc = pthread_mutex_init (&wq->work_lock, NULL);
+ if (rc != 0)
+ {
+ return -abs (rc);
+ }
+
+ rc = pthread_mutex_init (&wq->waiter_lock, NULL);
+ if (rc != 0)
+ {
+
+ pthread_mutex_destroy (&wq->work_lock);
+ return -abs (rc);
+ }
+
+ sem_init (&wq->work_sem, 0, 0);
+ sem_init (&wq->end_sem, 0, 0);
+
+ wq->state = state;
+
+ return rc;
+}
// start a work queue
// return 0 on success
// return negative on error:
// * -EINVAL if already started
// * whatever pthread_create errors on
-int vdev_wq_start( struct vdev_wq* wq ) {
+int
+vdev_wq_start (struct vdev_wq *wq)
+{
- if( wq->running ) {
+ if (wq->running)
+ {
return -EINVAL;
- }
+ }
- int rc = 0;
- pthread_attr_t attrs;
+ int rc = 0;
+ pthread_attr_t attrs;
- memset( &attrs, 0, sizeof(pthread_attr_t) );
+ memset (&attrs, 0, sizeof (pthread_attr_t));
- wq->running = true;
+ wq->running = true;
- rc = pthread_create( &wq->thread, &attrs, vdev_wq_main, wq );
- if( rc != 0 ) {
+ rc = pthread_create (&wq->thread, &attrs, vdev_wq_main, wq);
+ if (rc != 0)
+ {
wq->running = false;
rc = -errno;
- vdev_error("pthread_create errno = %d\n", rc );
+ vdev_error ("pthread_create errno = %d\n", rc);
return rc;
- }
+ }
- return 0;
+ return 0;
}
// stop a work queue
// return 0 on success
// return negative on error:
// * -EINVAL if not running
-int vdev_wq_stop( struct vdev_wq* wq, bool wait ) {
+int
+vdev_wq_stop (struct vdev_wq *wq, bool wait)
+{
- if( !wq->running ) {
+ if (!wq->running)
+ {
return -EINVAL;
- }
-
- if( wait ) {
-
+ }
+
+ if (wait)
+ {
+
// wait for the queue to be empty
- vdev_wq_wait_for_empty( wq );
- }
+ vdev_wq_wait_for_empty (wq);
+ }
- wq->running = false;
+ wq->running = false;
- // wake up the work queue so it cancels
- sem_post( &wq->work_sem );
- pthread_cancel( wq->thread );
+ // wake up the work queue so it cancels
+ sem_post (&wq->work_sem);
+ pthread_cancel (wq->thread);
- pthread_join( wq->thread, NULL );
+ pthread_join (wq->thread, NULL);
- return 0;
+ return 0;
}
-
// free a work request queue
// always succeeds
-static int vdev_wq_queue_free( struct vdev_wreq* wqueue ) {
+static int
+vdev_wq_queue_free (struct vdev_wreq *wqueue)
+{
+
+ struct vdev_wreq *next = NULL;
+
+ while (wqueue != NULL)
+ {
- struct vdev_wreq* next = NULL;
-
- while( wqueue != NULL ) {
-
next = wqueue->next;
-
- vdev_wreq_free( wqueue );
- free( wqueue );
-
+
+ vdev_wreq_free (wqueue);
+ free (wqueue);
+
wqueue = next;
- }
-
- return 0;
+ }
+
+ return 0;
}
// free up a work queue
// return 0 on success
// return negative on error:
// * -EINVAL if running
-int vdev_wq_free( struct vdev_wq* wq ) {
+int
+vdev_wq_free (struct vdev_wq *wq)
+{
- if( wq->running ) {
+ if (wq->running)
+ {
return -EINVAL;
- }
+ }
+ // free all
+ vdev_wq_queue_free (wq->work);
+
+ pthread_mutex_destroy (&wq->work_lock);
+ pthread_mutex_destroy (&wq->waiter_lock);
- // free all
- vdev_wq_queue_free( wq->work );
-
- pthread_mutex_destroy( &wq->work_lock );
- pthread_mutex_destroy( &wq->waiter_lock );
-
- sem_destroy( &wq->work_sem );
- sem_destroy( &wq->end_sem );
+ sem_destroy (&wq->work_sem);
+ sem_destroy (&wq->end_sem);
- memset( wq, 0, sizeof(struct vdev_wq) );
+ memset (wq, 0, sizeof (struct vdev_wq));
- return 0;
+ return 0;
}
// create a work request
// always succeeds
-int vdev_wreq_init( struct vdev_wreq* wreq, vdev_wq_func_t work, void* work_data ) {
+int
+vdev_wreq_init (struct vdev_wreq *wreq, vdev_wq_func_t work, void *work_data)
+{
- memset( wreq, 0, sizeof(struct vdev_wreq) );
+ memset (wreq, 0, sizeof (struct vdev_wreq));
- wreq->work = work;
- wreq->work_data = work_data;
+ wreq->work = work;
+ wreq->work_data = work_data;
- return 0;
+ return 0;
}
// free a work request
// always succeeds
-int vdev_wreq_free( struct vdev_wreq* wreq ) {
+int
+vdev_wreq_free (struct vdev_wreq *wreq)
+{
- memset( wreq, 0, sizeof(struct vdev_wreq) );
- return 0;
+ memset (wreq, 0, sizeof (struct vdev_wreq));
+ return 0;
}
// enqueue work
// return 0 on success
// return -ENOMEM if OOM
-int vdev_wq_add( struct vdev_wq* wq, struct vdev_wreq* wreq ) {
+int
+vdev_wq_add (struct vdev_wq *wq, struct vdev_wreq *wreq)
+{
- int rc = 0;
- struct vdev_wreq* next = NULL;
+ int rc = 0;
+ struct vdev_wreq *next = NULL;
- // duplicate this work item
- next = VDEV_CALLOC( struct vdev_wreq, 1 );
- if( next == NULL ) {
+ // duplicate this work item
+ next = VDEV_CALLOC (struct vdev_wreq, 1);
+ if (next == NULL)
+ {
return -ENOMEM;
- }
-
- next->work = wreq->work;
- next->work_data = wreq->work_data;
- next->next = NULL;
-
- pthread_mutex_lock( &wq->work_lock );
-
- if( wq->work == NULL ) {
+ }
+
+ next->work = wreq->work;
+ next->work_data = wreq->work_data;
+ next->next = NULL;
+
+ pthread_mutex_lock (&wq->work_lock);
+
+ if (wq->work == NULL)
+ {
// head
wq->work = next;
wq->tail = next;
- }
- else {
+ }
+ else
+ {
// append
wq->tail->next = next;
wq->tail = next;
- }
-
- pthread_mutex_unlock( &wq->work_lock );
+ }
+
+ pthread_mutex_unlock (&wq->work_lock);
- if( rc == 0 ) {
+ if (rc == 0)
+ {
// have work
- sem_post( &wq->work_sem );
- }
+ sem_post (&wq->work_sem);
+ }
- return rc;
+ return rc;
}
diff --git a/vdevd/workqueue.h b/vdevd/workqueue.h
index afd3673..1ada2e3 100644
--- a/vdevd/workqueue.h
+++ b/vdevd/workqueue.h
@@ -28,63 +28,64 @@ struct vdev_wreq;
struct vdev_state;
// vdev workqueue callback type
-typedef int (*vdev_wq_func_t)( struct vdev_wreq* wreq, void* cls );
+typedef int (*vdev_wq_func_t) (struct vdev_wreq * wreq, void *cls);
// vdev workqueue request
-struct vdev_wreq {
+struct vdev_wreq
+{
- // callback to do work
- vdev_wq_func_t work;
+ // callback to do work
+ vdev_wq_func_t work;
- // user-supplied arguments
- void* work_data;
+ // user-supplied arguments
+ void *work_data;
- // next item
- struct vdev_wreq* next;
+ // next item
+ struct vdev_wreq *next;
};
// vdev workqueue
-struct vdev_wq {
-
- // worker thread
- pthread_t thread;
-
- // is the thread running?
- volatile bool running;
-
- // things to do
- struct vdev_wreq* work;
- struct vdev_wreq* tail;
-
- // lock governing access to work
- pthread_mutex_t work_lock;
-
- // semaphore to signal the availability of work
- sem_t work_sem;
-
- // semaphore to signal the end of coldplug processing
- sem_t end_sem;
-
- // pointer to vdev global state
- struct vdev_state* state;
-
- // number of threads waiting for the queue to be empty
- volatile int num_waiters;
- pthread_mutex_t waiter_lock;
-};
+struct vdev_wq
+{
-C_LINKAGE_BEGIN
+ // worker thread
+ pthread_t thread;
-int vdev_wq_init( struct vdev_wq* wq, struct vdev_state* state );
-int vdev_wq_start( struct vdev_wq* wq );
-int vdev_wq_stop( struct vdev_wq* wq, bool wait );
-int vdev_wq_free( struct vdev_wq* wq );
+ // is the thread running?
+ volatile bool running;
-int vdev_wreq_init( struct vdev_wreq* wreq, vdev_wq_func_t work, void* work_data );
-int vdev_wreq_free( struct vdev_wreq* wreq );
+ // things to do
+ struct vdev_wreq *work;
+ struct vdev_wreq *tail;
-int vdev_wq_add( struct vdev_wq* wq, struct vdev_wreq* wreq );
+ // lock governing access to work
+ pthread_mutex_t work_lock;
-C_LINKAGE_END
+ // semaphore to signal the availability of work
+ sem_t work_sem;
+
+ // semaphore to signal the end of coldplug processing
+ sem_t end_sem;
+
+ // pointer to vdev global state
+ struct vdev_state *state;
+
+ // number of threads waiting for the queue to be empty
+ volatile int num_waiters;
+ pthread_mutex_t waiter_lock;
+};
+
+C_LINKAGE_BEGIN int vdev_wq_init (struct vdev_wq *wq,
+ struct vdev_state *state);
+int vdev_wq_start (struct vdev_wq *wq);
+int vdev_wq_stop (struct vdev_wq *wq, bool wait);
+int vdev_wq_free (struct vdev_wq *wq);
+
+int vdev_wreq_init (struct vdev_wreq *wreq, vdev_wq_func_t work,
+ void *work_data);
+int vdev_wreq_free (struct vdev_wreq *wreq);
+int vdev_wq_add (struct vdev_wq *wq, struct vdev_wreq *wreq);
+
+C_LINKAGE_END
#endif