aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Hjelm <hjelmn@me.com>2013-08-07 21:01:43 -0600
committerNathan Hjelm <hjelmn@me.com>2013-08-07 21:01:43 -0600
commitb50a433c164996761344efb6c90594de7906fe56 (patch)
treefa44e559b337b54ed6282eedae0b9d753651cef0
parentc848e5b72a1670a33eb84f210b951177a3de19e9 (diff)
downloadandroid_external_libusbx-b50a433c164996761344efb6c90594de7906fe56.tar.gz
android_external_libusbx-b50a433c164996761344efb6c90594de7906fe56.tar.bz2
android_external_libusbx-b50a433c164996761344efb6c90594de7906fe56.zip
linux: ensure the netlink socket is correctly opened with older Linux kernels
It is possible for the extra socket flags (available from 2.6.27 on) to be defined but not available. Check for this case and set the flags correctly on the netlink socket.
-rw-r--r--libusb/os/linux_netlink.c36
-rw-r--r--libusb/version_nano.h2
2 files changed, 31 insertions, 7 deletions
diff --git a/libusb/os/linux_netlink.c b/libusb/os/linux_netlink.c
index 758974f..20f1d02 100644
--- a/libusb/os/linux_netlink.c
+++ b/libusb/os/linux_netlink.c
@@ -63,6 +63,26 @@ static void *linux_netlink_event_thread_main(void *arg);
struct sockaddr_nl snl = { .nl_family=AF_NETLINK, .nl_groups=KERNEL };
+static int set_fd_cloexec_nb (int fd)
+{
+ int flags;
+
+#if defined(FD_CLOEXEC)
+ fcntl (linux_netlink_socket, F_GETFD, &flags);
+
+ if (!(flags & FD_CLOEXEC)) {
+ fcntl (linux_netlink_socket, F_SETFD, flags | FD_CLOEXEC);
+ }
+#endif
+
+ fcntl (linux_netlink_socket, F_GETFL, &flags);
+ if (!(flags & O_NONBLOCK)) {
+ fcntl (linux_netlink_socket, F_SETFL, flags | O_NONBLOCK);
+ }
+
+ return 0;
+}
+
int linux_netlink_start_event_monitor(void)
{
int socktype = SOCK_RAW;
@@ -78,16 +98,20 @@ int linux_netlink_start_event_monitor(void)
#endif
linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT);
+ if (-1 == linux_netlink_socket && EINVAL == errno) {
+ linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
+ }
+
if (-1 == linux_netlink_socket) {
return LIBUSB_ERROR_OTHER;
}
-#if !defined(SOCK_CLOEXEC) && defined(FD_CLOEXEC)
- fcntl (linux_netlink_socket, F_SETFD, FD_CLOEXEC);
-#endif
-#if !defined(SOCK_NONBLOCK)
- fcntl (linux_netlink_socket, F_SETFL, O_NONBLOCK);
-#endif
+ ret = set_fd_cloexec_nb (linux_netlink_socket);
+ if (0 != ret) {
+ close (linux_netlink_socket);
+ linux_netlink_socket = -1;
+ return LIBUSB_ERROR_OTHER;
+ }
ret = bind(linux_netlink_socket, (struct sockaddr *) &snl, sizeof(snl));
if (0 != ret) {
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index b8325ac..7ee3d41 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 10803
+#define LIBUSB_NANO 10805