Fixed FTBFS in Debian/Ubuntu due to missing liblockdev1-dev package. Device locking is now done through 'flock()'

Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
(cherry picked from commit 3ed5f6bda5)
r14.0.x
Michele Calgaro 9 years ago
parent b80f9a2251
commit 3811fc1773

@ -54,17 +54,6 @@ if( BUILD_KMOBILE )
endif( ) endif( )
if( BUILD_KANDY OR (BUILD_KMOBILE AND NOT HAVE_BAUDBOY_H) )
check_include_file( "lockdev.h" HAVE_LOCKDEV_H )
if( HAVE_LOCKDEV_H )
check_library_exists( lockdev dev_unlock "" HAVE_LOCKDEV )
if( HAVE_LOCKDEV )
set( LOCKDEV_LIBRARY lockdev CACHE INTERNAL "" FORCE )
endif( )
endif( )
endif( )
if( WITH_GNOKII AND (BUILD_KADDRESSBOOK OR BUILD_KMOBILE) ) if( WITH_GNOKII AND (BUILD_KADDRESSBOOK OR BUILD_KMOBILE) )
pkg_search_module( GNOKII gnokii ) pkg_search_module( GNOKII gnokii )
if( NOT GNOKII_FOUND ) if( NOT GNOKII_FOUND )

@ -39,9 +39,6 @@
// kaddressbook // kaddressbook
#cmakedefine TDEPIM_NEW_DISTRLISTS 1 #cmakedefine TDEPIM_NEW_DISTRLISTS 1
// kandy
#cmakedefine HAVE_LOCKDEV 1
// karm // karm
#cmakedefine HAVE_LIBXSS 1 #cmakedefine HAVE_LIBXSS 1

@ -1,12 +0,0 @@
# check for lockdev, optionally used to lock serial device
AH_TEMPLATE(HAVE_LOCKDEV)
AC_CHECK_HEADERS(lockdev.h, HAVE_LOCKDEV_H=1, HAVE_LOCKDEV_H=)
AC_SUBST(HAVE_LOCKDEV_H)
# we check for dev_unlock since kmobile checks dev_lock, caches it
# and the variables are messed up then... *sigh*
if test -n "$HAVE_LOCKDEV_H"; then
AC_CHECK_LIB(lockdev, dev_unlock,
[KANDY_LIBLOCKDEV="-llockdev $KANDY_LIBLOCKDEV"
AC_DEFINE(HAVE_LOCKDEV)], , $KANDY_LIBLOCKDEV)
fi
AC_SUBST(KANDY_LIBLOCKDEV)

@ -47,7 +47,7 @@ tde_add_executable( kandy AUTOMOC
atcommand.cpp commanditem.cpp mobilegui_base.ui mobilegui.cpp atcommand.cpp commanditem.cpp mobilegui_base.ui mobilegui.cpp
commandscheduler.cpp commandset.cpp kandyprefs.kcfgc commandscheduler.cpp commandset.cpp kandyprefs.kcfgc
kandyprefsdialog.cpp mobilemain.cpp kandyprefsdialog.cpp mobilemain.cpp
LINK tdepim-shared ${LOCKDEV_LIBRARY} LINK tdepim-shared
DESTINATION ${BIN_INSTALL_DIR} DESTINATION ${BIN_INSTALL_DIR}
) )

@ -3,7 +3,7 @@ bin_PROGRAMS = kandy kandy_client
INCLUDES = -I$(top_srcdir) $(all_includes) INCLUDES = -I$(top_srcdir) $(all_includes)
kandy_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor kandy_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor
kandy_LDADD = $(KANDY_LIBLOCKDEV) $(LIB_TDEFILE) -ltdeabc $(top_builddir)/libtdepim/libtdepim.la kandy_LDADD = $(LIB_TDEFILE) -ltdeabc $(top_builddir)/libtdepim/libtdepim.la
kandy_SOURCES = main.cpp kandy.cpp \ kandy_SOURCES = main.cpp kandy.cpp \
cmdpropertiesdialog_base.ui cmdpropertiesdialog.cpp \ cmdpropertiesdialog_base.ui cmdpropertiesdialog.cpp \
kandyview.cpp \ kandyview.cpp \

@ -30,6 +30,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/file.h>
#include <fcntl.h> #include <fcntl.h>
#include <termios.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
@ -75,10 +76,10 @@
Modem::Modem( KandyPrefs *kprefs, TQObject *parent, const char *name ) : Modem::Modem( KandyPrefs *kprefs, TQObject *parent, const char *name ) :
TQObject(parent, name) TQObject(parent, name), fd(-1)
{ {
mOpen = false; mOpen = false;
prefs = kprefs; prefs = kprefs;
timer = new TQTimer( this, "modemtimer" ); timer = new TQTimer( this, "modemtimer" );
@ -185,28 +186,31 @@ bool Modem::open()
{ {
struct termios tty; struct termios tty;
close(); close();
if ( !lockDevice() ) if (fd == -1)
return false; {
TQCString dev = TQFile::encodeName( (*prefs).serialDevice() );
const char *fdev = dev.data();
if ( ( fd = ::open( fdev, O_RDWR | O_NOCTTY | O_NONBLOCK ) ) == -1 ) {
emit errorMessage( i18n( "Unable to open device '%1'. "
"Please check that you have sufficient permissions." )
.arg( fdev ) );
return false;
}
}
TQCString dev = TQFile::encodeName( (*prefs).serialDevice() ); if ( !lockDevice() )
const char *fdev = dev.data();
if ( ( fd = ::open( fdev, O_RDWR | O_NOCTTY | O_NONBLOCK ) ) == -1 ) {
emit errorMessage( i18n( "Unable to open device '%1'. "
"Please check that you have sufficient permissions." )
.arg( fdev ) );
return false; return false;
}
tcflush( fd, TCIOFLUSH ); tcflush( fd, TCIOFLUSH );
if ( tcgetattr( fd, &init_tty ) == -1 ) { if ( tcgetattr( fd, &init_tty ) == -1 ) {
int errnumber = errno; int errnumber = errno;
emit errorMessage( i18n( "Communication setup failed (tcgetattr code: %1)" ) emit errorMessage( i18n( "Communication setup failed (tcgetattr code: %1)" )
.arg(strerror(errnumber)) ); .arg(strerror(errnumber)) );
unlockDevice();
::close( fd ); ::close( fd );
fd = 0; fd = -1;
return false; return false;
} }
@ -221,8 +225,9 @@ bool Modem::open()
if ( tcsetattr( fd, TCSANOW, &tty ) == -1 ) { if ( tcsetattr( fd, TCSANOW, &tty ) == -1 ) {
emit errorMessage( i18n( "tcsetattr() failed." ) ); emit errorMessage( i18n( "tcsetattr() failed." ) );
unlockDevice();
::close( fd ); ::close( fd );
fd = 0; fd = -1;
return false; return false;
} }
@ -244,127 +249,56 @@ void Modem::close()
delete sn; delete sn;
sn = 0; sn = 0;
unlockDevice();
if ( fd ) { if ( fd ) {
tcflush( fd, TCIOFLUSH ); tcflush( fd, TCIOFLUSH );
tcsetattr( fd, TCSANOW, &init_tty ); tcsetattr( fd, TCSANOW, &init_tty );
::close( fd ); ::close( fd );
fd = 0; fd = -1;
} }
xreset(); xreset();
unlockDevice();
mOpen = false; mOpen = false;
} }
void Modem::flush() void Modem::flush()
{ {
if ( fd ) { if ( fd != -1) {
tcflush( fd, TCIOFLUSH ); tcflush( fd, TCIOFLUSH );
bufpos = 0; bufpos = 0;
} }
} }
#ifdef HAVE_LOCKDEV
#include <lockdev.h>
#endif
bool Modem::lockDevice() bool Modem::lockDevice()
{ {
if ( is_locked ) if (is_locked)
return true; return true;
#ifdef HAVE_LOCKDEV if (flock(fd, LOCK_EX))
is_locked = !dev_lock( (*prefs).serialDevice().local8Bit() ); {
if (!is_locked) // Locking failed
emit errorMessage( i18n( "Unable to lock device '%1'." ).arg( is_locked = false;
(*prefs).serialDevice() )); emit errorMessage(i18n("Unable to lock device '%1'.").arg((*prefs).serialDevice()));
return is_locked; }
#else else
ssize_t count; {
pid_t pid; is_locked = true;
int lfd;
struct passwd *pw;
TQStringList pathList;
TQString fileName, content;
pathList = TQStringList::split( "/", (*prefs).serialDevice() );
fileName = (*prefs).lockDirectory() + "/LCK.." + pathList.last();
if ( !access( TQFile::encodeName( fileName ).data(), F_OK ) ) {
char buf[256];
if ( ( lfd = ::open( TQFile::encodeName( fileName ), O_RDONLY ) ) < 0 ) {
emit errorMessage( i18n( "Unable to open lock file '%1'.")
.arg( fileName ) );
return false;
}
count = read( lfd, buf, 79 );
if ( count < 0 ) {
emit errorMessage( i18n( "Unable to read lock file '%1'.")
.arg( fileName ) );
::close( lfd );
return false;
}
buf[ count ] = 0;
::close( lfd );
count = sscanf( buf, "%d", &pid );
if ( ( count != 1 ) || ( pid <= 0 ) ) {
emit errorMessage( i18n( "Unable to get PID from file '%1'.")
.arg( fileName ) );
return false;
}
if ( !kill( (pid_t) pid, 0 ) ) {
emit errorMessage( i18n( "Process with PID %1, which is locking the device, is still running.")
.arg( pid ) );
return false;
}
if ( errno != ESRCH ) {
emit errorMessage( i18n( "Unable to emit signal to PID of existing lock file.") );
return false;
}
}
if ( ( lfd = creat( TQFile::encodeName( fileName ).data(), 0644 ) ) == -1 ) {
emit errorMessage( i18n( "Unable to create lock file '%1'. "
"Please check that you have sufficient permissions.")
.arg( fileName ) );
return false;
} }
pid = (int) getpid(); return is_locked;
pw = getpwuid( getuid() );
content.sprintf( "%08d %s %s", pid, "kandy", pw->pw_name );
write( lfd, TQFile::encodeName( content ).data(), content.length() );
::close( lfd );
is_locked = true;
return true;
#endif
} }
void Modem::unlockDevice() void Modem::unlockDevice()
{ {
#ifdef HAVE_LOCKDEV if (fd != -1 && is_locked)
dev_unlock( (*prefs).serialDevice().local8Bit(), getpid() ); {
#else flock(fd, LOCK_UN);
if ( is_locked ) { is_locked = false;
TQStringList pathList = TQStringList::split( "/", (*prefs).serialDevice() ); }
TQFile::remove( (*prefs).lockDirectory() + "/LCK.." + pathList.last() );
is_locked = false;
}
#endif
} }
@ -373,7 +307,7 @@ bool Modem::dsrOn()
int flags; int flags;
if ( !fd ) { if ( fd == -1 ) {
#ifdef MODEM_DEBUG #ifdef MODEM_DEBUG
fprintf( stderr, "Modem: dsrOn(): File not open.\n" ); fprintf( stderr, "Modem: dsrOn(): File not open.\n" );
#endif #endif
@ -396,7 +330,7 @@ bool Modem::ctsOn()
int flags; int flags;
if ( !fd ) { if ( fd == -1 ) {
#ifdef MODEM_DEBUG #ifdef MODEM_DEBUG
fprintf( stderr, "Modem: ctsOn(): File not open.\n" ); fprintf( stderr, "Modem: ctsOn(): File not open.\n" );
#endif #endif
@ -640,7 +574,7 @@ void Modem::init()
{ {
is_locked = false; is_locked = false;
fd = 0; fd = -1;
sn = 0; sn = 0;
cspeed = B38400; cspeed = B38400;
@ -687,7 +621,7 @@ ushort Modem::calcCRC()
int i, j; int i, j;
ushort c = 0; ushort c = 0;
for ( i = 0; i < xsize; i++ ) { for ( i = 0; i < xsize; i++ ) {
c ^= (ushort) buffer[ i ] << 8; c ^= (ushort) buffer[ i ] << 8;
for ( j = 0; j < 8; j++ ) for ( j = 0; j < 8; j++ )

@ -7,7 +7,7 @@
"kmobile" is suite to easily access "Mobile Devices", "kmobile" is suite to easily access "Mobile Devices",
which means, that you have one single interface to access which means, that you have one single interface to access
any type of mobile device (e.g. cellular phone, PDAs, any type of mobile device (e.g. cellular phone, PDAs,
MP3-Players, Digital Cameras and a lot more). MP3-Players, Digital Cameras and a lot more).
Each of this devices have different types of information, Each of this devices have different types of information,
@ -17,11 +17,11 @@ Each of this devices have different types of information,
- calendar entries, - calendar entries,
- a file storage section (e.g. pictures in digital cameras) - a file storage section (e.g. pictures in digital cameras)
- and more - and more
The whole interface is pretty extendable. Each device has The whole interface is pretty extendable. Each device has
a device driver, which reports the capatibilities of the a device driver, which reports the capatibilities of the
connected device to the higher level. connected device to the higher level.
So, if you once write a device driver, you can access it's So, if you once write a device driver, you can access it's
contents from any KDE application later. contents from any KDE application later.
Currently the whole interface is divided into 3 sections: Currently the whole interface is divided into 3 sections:
@ -48,7 +48,7 @@ The mid-layer handles the main functionality, which is entirely
implemented in the kmobile application. All low-level drivers implemented in the kmobile application. All low-level drivers
are loaded by kmobile only, and then all low-level functions are loaded by kmobile only, and then all low-level functions
to any device is made available to other applications to any device is made available to other applications
with a DCOP interface. Normal KDE applications should prefer the with a DCOP interface. Normal KDE applications should prefer the
userland library (see below) instead of using direct DCOP calls. userland library (see below) instead of using direct DCOP calls.
Nevertheless, the DCOP interface might be very interesting to write Nevertheless, the DCOP interface might be very interesting to write
standalone command line tools. standalone command line tools.
@ -86,7 +86,7 @@ HINTS FOR DRIVER DEVELOPERS:
all calls to your driver, so you always will have a clean state all calls to your driver, so you always will have a clean state
- use lockDevice("/dev/ttyS1") and unlockDevice("/dev/ttyS1") to - use lockDevice("/dev/ttyS1") and unlockDevice("/dev/ttyS1") to
lock those devices system-wide (creates /var/lock/LCK..<devname> files), lock those devices system-wide,
and to prevent other applications to access the same physical ports/devices and to prevent other applications to access the same physical ports/devices
- use the helper functions createDirEntry() and createFileEntry() to - use the helper functions createDirEntry() and createFileEntry() to

@ -2,7 +2,7 @@
SUBDIRS = . devices # tdeioslave SUBDIRS = . devices # tdeioslave
bin_PROGRAMS = kmobile bin_PROGRAMS = kmobile
lib_LTLIBRARIES = libkmobiledevice.la libkmobileclient.la lib_LTLIBRARIES = libkmobiledevice.la libkmobileclient.la
@ -21,7 +21,7 @@ noinst_HEADERS = kmobile.h kmobileview.h kmobileitem.h pref.h
# the low-level devices driver library # the low-level devices driver library
libkmobiledevice_la_SOURCES = kmobiledevice.cpp libkmobiledevice_la_SOURCES = kmobiledevice.cpp
libkmobiledevice_la_LDFLAGS = $(all_libraries) -no-undefined -avoid-version libkmobiledevice_la_LDFLAGS = $(all_libraries) -no-undefined -avoid-version
libkmobiledevice_la_LIBADD = $(LIB_TDEABC) $(LIB_LOCKDEV) ../libkcal/libkcal.la libkmobiledevice_la_LIBADD = $(LIB_TDEABC) ../libkcal/libkcal.la
# the KDE application's client library to KMobile # the KDE application's client library to KMobile
libkmobileclient_la_SOURCES = kmobileclient.cpp libkmobileclient_la_SOURCES = kmobileclient.cpp

@ -1,16 +0,0 @@
DO_NOT_COMPILE="$DO_NOT_COMPILE kmobile"
AC_CHECK_HEADERS(baudboy.h,,,
[
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define inline __inline__
])
AC_CHECK_HEADERS(lockdev.h)
AC_CHECK_LIB(lockdev, dev_lock, [ LIB_LOCKDEV="-llockdev" ])
dnl We don't need liblockdev if we have baudboy working
if [[ -n "$HAVE_BAUDBOY_H" ]]; then
LIB_LOCKDEV=""
fi
AC_SUBST(LIB_LOCKDEV)

@ -19,7 +19,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/file.h>
#include <unistd.h> #include <unistd.h>
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
@ -48,8 +48,7 @@
*/ */
KMobileDevice::KMobileDevice(TQObject *obj, const char *name, const TQStringList &args) KMobileDevice::KMobileDevice(TQObject *obj, const char *name, const TQStringList &args)
: KLibFactory(obj,name), : KLibFactory(obj,name), m_config(0L), d(0L), m_fd(-1)
m_config(0L), d(0L)
{ {
setClassType(Unclassified); setClassType(Unclassified);
setCapabilities(hasNothing); setCapabilities(hasNothing);
@ -348,103 +347,33 @@ void KMobileDevice::special( const TQByteArray & )
// and no one is in this group. Only the binary /usr/sbin/lockdev is // and no one is in this group. Only the binary /usr/sbin/lockdev is
// owned by this group and has the setgid flag set. This binary is called // owned by this group and has the setgid flag set. This binary is called
// in ttylock etc ... // in ttylock etc ...
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <baudboy.h> # include <baudboy.h>
# include <cstdlib> # include <cstdlib>
#else
# ifdef HAVE_LOCKDEV_H
// Library shipped with newer RedHat and Debian(?) distributions.
// Use this if bauddev is not available.
# include <lockdev.h>
# include <sys/types.h>
# include <unistd.h>
# else
// If lockdev.h is also unavailable do locking
// like described in the serial HOWTO.
# include <sys/types.h>
# include <sys/stat.h>
# include <unistd.h>
# include <tqfile.h>
# include <signal.h>
# include <errno.h>
# endif
#endif #endif
#define DEVICE_LOCK_PATH_PREFIX "/var/lock/LCK.."
bool KMobileDevice::lockDevice(const TQString &device, TQString &err_reason) bool KMobileDevice::lockDevice(const TQString &device, TQString &err_reason)
{ {
#ifdef HAVE_BAUDBOY_H #ifdef HAVE_BAUDBOY_H
return ttylock(device.local8bit()) == EXIT_SUCCESS; return ttylock(device.local8Bit()) == EXIT_SUCCESS;
#else #else
# ifdef HAVE_LOCKDEV_H if (m_fd != -1)
return !dev_lock(device.local8bit()); return true;
# else
int pid = -1; TQCString dev = TQFile::encodeName(device.local8Bit());
TQStringList all = TQStringList::split('/', device); const char *fdev = dev.data();
if (!all.count()) { if ((m_fd = open(fdev, O_RDWR)) == -1)
err_reason = i18n("Invalid device (%1)").arg(device); {
return false; PRINT_DEBUG << i18n("Unable to open device '%1'. "
} "Please check that you have sufficient permissions.").arg(fdev);
TQString lockName = DEVICE_LOCK_PATH_PREFIX + all[all.count()-1];
TQFile file(lockName);
if (file.exists() && file.open(IO_ReadOnly)) {
if (file.size() == 0) {
err_reason = i18n("Unable to read lockfile %s. Please check for reason and "
"remove the lockfile by hand.").arg(lockName);
PRINT_DEBUG << err_reason;
return false;
}
if (file.size() == 4 && sizeof(int)==4) {
file.readLine((char *)(&pid), 4); /* Kermit-style lockfile */
} else {
TQTextStream ts(&file);
ts >> pid; /* Ascii lockfile */
}
file.close();
if (pid > 0 && kill((pid_t)pid, 0) < 0 && errno == ESRCH) {
PRINT_DEBUG << TQString("Lockfile %1 is stale. Overriding it..\n").arg(lockName);
sleep(1);
if (!file.remove()) {
PRINT_DEBUG << TQString("Overriding failed, please check the permissions\n");
PRINT_DEBUG << TQString("Cannot lock device %1\n").arg(device);
err_reason = i18n("Lockfile %1 is stale. Please check permissions.").arg(lockName);
return false; return false;
} }
} else { if (flock(m_fd, LOCK_EX))
err_reason = i18n("Device %1 already locked.").arg(device); {
return false; // Locking failed
} PRINT_DEBUG << i18n("Unable to lock device '%1'.").arg(fdev);
} return false;
}
/* Try to create a new file, with 0644 mode */
int fd = open(lockName.local8Bit(), O_CREAT | O_EXCL | O_WRONLY, 0644);
if (fd == -1) {
if (errno == EEXIST)
err_reason = i18n("Device %1 seems to be locked by unknown process.").arg(device);
else if (errno == EACCES)
err_reason = i18n("Please check permission on lock directory.");
else if (errno == ENOENT)
err_reason = i18n("Cannot create lockfile %1. Please check for existence of path.").arg(lockName);
else
err_reason = i18n("Could not create lockfile %1. Error-Code is %2.").arg(lockName).arg(errno);
return false;
}
TQString lockText;
lockText = TQString("%1 kmobile\n").arg(getpid(),10);
write(fd, lockText.utf8(), lockText.utf8().length());
close(fd);
PRINT_DEBUG << TQString("%1: Device %2 locked with lockfile %3.\n")
.arg(deviceName()).arg(device).arg(lockName);
err_reason = TQString();
return true; return true;
# endif
#endif #endif
} }
@ -453,17 +382,12 @@ bool KMobileDevice::unlockDevice(const TQString &device)
#ifdef HAVE_BAUDBOY_H #ifdef HAVE_BAUDBOY_H
return ttyunlock(device.local8bit()) == EXIT_SUCCESS; return ttyunlock(device.local8bit()) == EXIT_SUCCESS;
#else #else
# ifdef HAVE_LOCKDEV_H if (m_fd != -1)
return 0 <= dev_unlock(device.local8bit(), getpid()); {
# else flock(m_fd, LOCK_UN);
TQStringList all = TQStringList::split('/', device); }
if (!all.count()) return false; close(m_fd);
TQString lockName = DEVICE_LOCK_PATH_PREFIX + all[all.count()-1]; m_fd = -1;
TQFile file(lockName);
if (!file.exists())
return true;
return file.remove();
# endif
#endif #endif
} }

@ -65,7 +65,7 @@ class TDEConfig;
class KDE_EXPORT KMobileDevice : public KLibFactory class KDE_EXPORT KMobileDevice : public KLibFactory
{ {
Q_OBJECT Q_OBJECT
friend class KMobileView; friend class KMobileView;
public: public:
@ -497,6 +497,7 @@ protected:
TQString m_connectionName; // e.g. "IRDA", "USB", "Cable", "gnokii", "gammu", ... TQString m_connectionName; // e.g. "IRDA", "USB", "Cable", "gnokii", "gammu", ...
int m_caps; // see enum Capabilities int m_caps; // see enum Capabilities
bool m_connected; bool m_connected;
int m_fd; // file descriptor used for locking/unlocking devices
private: private:
class KMobileDevicePrivate *d; class KMobileDevicePrivate *d;

Loading…
Cancel
Save