linux: Apply v2 version of patch for CLOEXEC changes
authorChris Dickens <christopher.a.dickens@gmail.com>
Mon, 27 Mar 2017 03:19:40 +0000 (20:19 -0700)
committerChris Dickens <christopher.a.dickens@gmail.com>
Mon, 27 Mar 2017 03:25:27 +0000 (20:25 -0700)
Somehow I managed to push v1 of the patch, which didn't handle older
versions of the kernel or C library that don't support the O_CLOEXEC
flag (suggested by Tim Roberts). This commit amends the original
changes in aa73b2ec and provides this backwards compatibility.

Closes #286

Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
libusb/os/linux_usbfs.c
libusb/version_nano.h

index 442ee6a..ae5b8e2 100644 (file)
@@ -81,6 +81,10 @@ static const char *usbfs_path = NULL;
 /* use usbdev*.* device names in /dev instead of the usbfs bus directories */
 static int usbdev_names = 0;
 
+/* Linux 2.6.23 adds support for O_CLOEXEC when opening files, which marks the
+ * close-on-exec flag in the underlying file descriptor. */
+static int supports_flag_cloexec = -1;
+
 /* Linux 2.6.32 adds support for a bulk continuation URB flag. this basically
  * allows us to mark URBs as being part of a specific logical transfer when
  * we submit them to the kernel. then, on any error except a cancellation, all
@@ -180,6 +184,16 @@ struct linux_transfer_priv {
        int iso_packet_offset;
 };
 
+static int _open(const char *path, int flags)
+{
+#if defined(O_CLOEXEC)
+       if (supports_flag_cloexec)
+               return open(path, flags | O_CLOEXEC);
+       else
+#endif
+               return open(path, flags);
+}
+
 static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
 {
        struct libusb_context *ctx = DEVICE_CTX(dev);
@@ -194,7 +208,7 @@ static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
                snprintf(path, PATH_MAX, "%s/%03d/%03d",
                        usbfs_path, dev->bus_number, dev->device_address);
 
-       fd = open(path, mode | O_CLOEXEC);
+       fd = _open(path, mode);
        if (fd != -1)
                return fd; /* Success */
 
@@ -205,7 +219,7 @@ static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
                /* Wait 10ms for USB device path creation.*/
                nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL);
 
-               fd = open(path, mode | O_CLOEXEC);
+               fd = _open(path, mode);
                if (fd != -1)
                        return fd; /* Success */
        }
@@ -387,6 +401,15 @@ static int op_init(struct libusb_context *ctx)
        if (monotonic_clkid == -1)
                monotonic_clkid = find_monotonic_clock();
 
+       if (supports_flag_cloexec == -1) {
+               /* O_CLOEXEC flag available from Linux 2.6.23 */
+               supports_flag_cloexec = kernel_version_ge(2,6,23);
+               if (supports_flag_cloexec == -1) {
+                       usbi_err(ctx, "error checking for O_CLOEXEC support");
+                       return LIBUSB_ERROR_OTHER;
+               }
+       }
+
        if (supports_flag_bulk_continuation == -1) {
                /* bulk continuation URB flag available from Linux 2.6.32 */
                supports_flag_bulk_continuation = kernel_version_ge(2,6,32);
@@ -526,7 +549,7 @@ static int _open_sysfs_attr(struct libusb_device *dev, const char *attr)
 
        snprintf(filename, PATH_MAX, "%s/%s/%s",
                SYSFS_DEVICE_PATH, priv->sysfs_dir, attr);
-       fd = open(filename, O_RDONLY | O_CLOEXEC);
+       fd = _open(filename, O_RDONLY);
        if (fd < 0) {
                usbi_err(DEVICE_CTX(dev),
                        "open %s failed ret=%d errno=%d", filename, fd, errno);
@@ -542,12 +565,12 @@ static int __read_sysfs_attr(struct libusb_context *ctx,
 {
        char filename[PATH_MAX];
        FILE *f;
-       int r, value;
+       int fd, r, value;
 
        snprintf(filename, PATH_MAX, "%s/%s/%s", SYSFS_DEVICE_PATH,
                 devname, attr);
-       f = fopen(filename, "re");
-       if (f == NULL) {
+       fd = _open(filename, O_RDONLY);
+       if (fd == -1) {
                if (errno == ENOENT) {
                        /* File doesn't exist. Assume the device has been
                           disconnected (see trac ticket #70). */
@@ -557,6 +580,13 @@ static int __read_sysfs_attr(struct libusb_context *ctx,
                return LIBUSB_ERROR_IO;
        }
 
+       f = fdopen(fd, "r");
+       if (f == NULL) {
+               usbi_err(ctx, "fdopen %s failed errno=%d", filename, errno);
+               close(fd);
+               return LIBUSB_ERROR_OTHER;
+       }
+
        r = fscanf(f, "%d", &value);
        fclose(f);
        if (r != 1) {
index 723c6c5..f75412b 100644 (file)
@@ -1 +1 @@
-#define LIBUSB_NANO 11194
+#define LIBUSB_NANO 11195