Skip to content

Commit

Permalink
linux: Apply v2 version of patch for CLOEXEC changes
Browse files Browse the repository at this point in the history
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 aa73b2e and provides this backwards compatibility.

Closes libusb#286

Signed-off-by: Chris Dickens <[email protected]>
  • Loading branch information
dickens committed Mar 27, 2017
1 parent 871eb29 commit beb0d61
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 7 deletions.
42 changes: 36 additions & 6 deletions libusb/os/linux_usbfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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 */

Expand All @@ -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 */
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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). */
Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion libusb/version_nano.h
Original file line number Diff line number Diff line change
@@ -1 +1 @@
#define LIBUSB_NANO 11194
#define LIBUSB_NANO 11195

0 comments on commit beb0d61

Please sign in to comment.