linux: Apply v2 version of patch for CLOEXEC changes

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>
This commit is contained in:
Chris Dickens
2017-03-26 20:19:40 -07:00
parent 871eb299b9
commit beb0d61b92
2 changed files with 37 additions and 7 deletions
+36 -6
View 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) {
+1 -1
View File
@@ -1 +1 @@
#define LIBUSB_NANO 11194
#define LIBUSB_NANO 11195