diff --git a/libgphoto2_port/usbscsi/linux.c b/libgphoto2_port/usbscsi/linux.c index e9635880a..c964e6d1f 100644 --- a/libgphoto2_port/usbscsi/linux.c +++ b/libgphoto2_port/usbscsi/linux.c @@ -1,6 +1,6 @@ /* SCSI commands to USB Mass storage devices port library for Linux * - * Copyright (c) 2010 Hans de Goede + * Copyright (c) 2010-2012 Hans de Goede * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -19,6 +19,7 @@ #include "config.h" #include +#include #include #include #include @@ -29,6 +30,7 @@ #ifdef HAVE_LIMITS_H # include #endif +#include #include #include #ifdef HAVE_SYS_PARAM_H @@ -40,9 +42,6 @@ #ifdef HAVE_SCSI_SG_H # include #endif -#ifdef HAVE_LOCKDEV -# include -#endif #include #include @@ -80,62 +79,37 @@ gp_port_library_type () } static int -gp_port_usbscsi_lock (GPPort *port, const char *path) +gp_port_usbscsi_lock (GPPort *port) { -#ifdef HAVE_LOCKDEV - int pid; - gp_log (GP_LOG_DEBUG, "gphoto2-port-usbscsi", - "Trying to lock '%s'...", path); + "Trying to lock '%s'...", port->settings.usbscsi.path); - pid = dev_lock (path); - if (pid) { - if (port) { - if (pid > 0) - gp_port_set_error (port, _("Device '%s' is " - "locked by pid %d"), path, pid); - else - gp_port_set_error (port, _("Device '%s' could " - "not be locked (dev_lock returned " - "%d)"), path, pid); + if (flock(port->pl->fd, LOCK_EX | LOCK_NB) != 0) { + switch (errno) { + case EWOULDBLOCK: + gp_port_set_error (port, + _("Device '%s' is locked by another app."), + port->settings.usbscsi.path); + return GP_ERROR_IO_LOCK; + default: + gp_port_set_error (port, + _("Failed to lock '%s' (%m)."), + port->settings.usbscsi.path); + return GP_ERROR_IO; } - return GP_ERROR_IO_LOCK; } -#else -# ifdef __GCC__ -# warning No locking library found. -# warning You will run into problems if you use -# warning gphoto2 with a usbscsi picframe in -# warning combination with Konqueror (KDE) or Nautilus (GNOME). -# warning This will *not* concern USB cameras. -# endif -#endif return GP_OK; } static int -gp_port_usbscsi_unlock (GPPort *port, const char *path) +gp_port_usbscsi_unlock (GPPort *port) { -#ifdef HAVE_LOCKDEV - int pid; - - pid = dev_unlock (path, 0); - if (pid) { - if (port) { - if (pid > 0) - gp_port_set_error (port, _("Device '%s' could " - "not be unlocked as it is locked by " - "pid %d."), path, pid); - else - gp_port_set_error (port, _("Device '%s' could " - "not be unlocked (dev_unlock " - "returned %d)"), path, pid); - } - return GP_ERROR_IO_LOCK; + if (flock(port->pl->fd, LOCK_UN) != 0) { + gp_port_set_error (port, _("Failed to unlock '%s' (%m)."), + port->settings.usbscsi.path); + return GP_ERROR_IO; } -#endif /* !HAVE_LOCKDEV */ - return GP_OK; } @@ -271,34 +245,36 @@ gp_port_usbscsi_open (GPPort *port) const int max_tries = 5; const char *path = port->settings.usbscsi.path; - result = gp_port_usbscsi_lock (port, path); - if (result != GP_OK) { - for (i = 0; i < max_tries; i++) { - result = gp_port_usbscsi_lock (port, path); - if (result == GP_OK) - break; - gp_log (GP_LOG_DEBUG, "gphoto2-port-usbscsi", - "Failed to get a lock, trying again..."); - sleep (1); - } - CHECK (result) - } port->pl->fd = open (path, O_RDWR); if (port->pl->fd == -1) { - gp_port_usbscsi_unlock (port, path); gp_port_set_error (port, _("Failed to open '%s' (%m)."), path); return GP_ERROR_IO; } - return GP_OK; + result = gp_port_usbscsi_lock (port); + for (i = 0; i < max_tries && result == GP_ERROR_IO_LOCK; i++) { + gp_log (GP_LOG_DEBUG, "gphoto2-port-usbscsi", + "Failed to get a lock, trying again..."); + sleep (1); + result = gp_port_usbscsi_lock (port); + } + if (result != GP_OK) { + close (port->pl->fd); + port->pl->fd = -1; + } + return result; } static int gp_port_usbscsi_close (GPPort *port) { + int result; + if (!port || port->pl->fd == -1) return GP_OK; + result = gp_port_usbscsi_unlock (port); + if (close (port->pl->fd) == -1) { gp_port_set_error (port, _("Could not close " "'%s' (%m)."), port->settings.usbscsi.path); @@ -306,10 +282,7 @@ gp_port_usbscsi_close (GPPort *port) } port->pl->fd = -1; - CHECK (gp_port_usbscsi_unlock (port, - port->settings.usbscsi.path)) - - return GP_OK; + return result; } static int gp_port_usbscsi_send_scsi_cmd (GPPort *port, int to_dev, char *cmd,