add win32/posix wrapper function tr_lockfile() to libT and use it in daemon/gtk.

This commit is contained in:
Charles Kerr 2008-02-28 19:06:23 +00:00
parent 288547ffb8
commit d870c12f40
4 changed files with 105 additions and 95 deletions

View File

@ -32,7 +32,6 @@
#include <assert.h>
#include <errno.h>
#include <event.h>
#include <fcntl.h>
#include <getopt.h>
#include <signal.h>
#include <stdarg.h>
@ -42,6 +41,7 @@
#include <unistd.h>
#include <libtransmission/trcompat.h>
#include <libtransmission/platform.h>
#include <libtransmission/version.h>
#include "errors.h"
@ -52,14 +52,12 @@
static void usage ( const char *, ... );
static void readargs ( int, char **, int *, int *, char **, char ** );
static int trylocksock ( const char * );
static int getlock ( const char * );
static int getsock ( const char * );
static void exitcleanup ( void );
static void setupsigs ( struct event_base * );
static void gotsig ( int, short, void * );
static int savepid ( const char * );
static int gl_lockfd = -1;
static char gl_lockpath[MAXPATHLEN] = "";
static int gl_sockfd = -1;
static char gl_sockpath[MAXPATHLEN] = "";
@ -183,6 +181,28 @@ readargs( int argc, char ** argv, int * nofork, int * debug, char ** sock,
}
}
static int
getlock( const char * filename )
{
const int state = tr_lockfile( filename );
const int success = state == TR_LOCKFILE_SUCCESS;
if( !success ) switch( state ) {
case TR_LOCKFILE_EOPEN:
errnomsg( "failed to open file: %s", filename );
break;
case TR_LOCKFILE_ELOCK:
errmsg( "another copy of %s is already running", getmyname() );
break;
default:
errmsg( "unhandled tr_lockfile error: %d", state );
break;
}
return success;
}
int
trylocksock( const char * sockpath )
{
@ -197,12 +217,8 @@ trylocksock( const char * sockpath )
}
confpath( path, sizeof path, CONF_FILE_LOCK, 0 );
fd = getlock( path );
if( 0 > fd )
{
if( !getlock( path ) )
return -1;
}
gl_lockfd = fd;
strlcpy( gl_lockpath, path, sizeof gl_lockpath );
if( NULL == sockpath )
@ -221,46 +237,6 @@ trylocksock( const char * sockpath )
return fd;
}
int
getlock( const char * path )
{
struct flock lk;
int fd;
char pid[64];
fd = open( path, O_RDWR | O_CREAT, 0666 );
if( 0 > fd )
{
errnomsg( "failed to open file: %s", path );
return -1;
}
memset( &lk, 0, sizeof lk );
lk.l_start = 0;
lk.l_len = 0;
lk.l_type = F_WRLCK;
lk.l_whence = SEEK_SET;
if( 0 > fcntl( fd, F_SETLK, &lk ) )
{
if( EAGAIN == errno )
{
errmsg( "another copy of %s is already running", getmyname() );
}
else
{
errnomsg( "failed to obtain lock on file: %s", path );
}
close( fd );
return -1;
}
ftruncate( fd, 0 );
snprintf( pid, sizeof pid, "%i\n", getpid() );
write( fd, pid, strlen( pid ) );
return fd;
}
int
getsock( const char * path )
{
@ -305,11 +281,9 @@ exitcleanup( void )
{
unlink( gl_pidfile );
}
if( 0 <= gl_lockfd )
{
if( *gl_lockpath )
unlink( gl_lockpath );
close( gl_lockfd );
}
}
void

View File

@ -28,9 +28,6 @@
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <glib.h>
@ -39,6 +36,7 @@
#include <libtransmission/transmission.h>
#include <libtransmission/bencode.h>
#include <libtransmission/platform.h>
#include "conf.h"
#include "util.h"
@ -72,47 +70,27 @@ cf_init(const char *dir, char **errstr)
***/
/* errstr may be NULL, this might be called before GTK is initialized */
static int
lockfile(const char *file, char **errstr)
static gboolean
lockfile(const char * filename, char **errstr)
{
int fd;
struct flock lk;
const int state = tr_lockfile( filename );
const gboolean success = state == TR_LOCKFILE_SUCCESS;
if( errstr )
*errstr = NULL;
fd = open( file, O_RDWR | O_CREAT, 0666 );
if( fd < 0 )
{
const int savederr = errno;
if( errstr )
*errstr = g_strdup_printf(
_("Failed to open the file %s for writing:\n%s"),
file, g_strerror( errno ) );
errno = savederr;
return -1;
if( errstr ) switch( state ) {
case TR_LOCKFILE_EOPEN:
*errstr = g_strdup_printf( _("Failed to open lockfile %s: %s"),
filename, g_strerror( errno ) );
break;
case TR_LOCKFILE_ELOCK:
*errstr = g_strdup_printf( _( "%s is already running." ),
g_get_application_name( ) );
break;
case TR_LOCKFILE_SUCCESS:
*errstr = NULL;
break;
}
memset( &lk, 0, sizeof( lk ) );
lk.l_start = 0;
lk.l_len = 0;
lk.l_type = F_WRLCK;
lk.l_whence = SEEK_SET;
if( -1 == fcntl( fd, F_SETLK, &lk ) )
{
const int savederr = errno;
if( errstr )
*errstr = ( errno == EAGAIN )
? g_strdup_printf( _( "Another copy of %s is already running." ),
g_get_application_name( ) )
: g_strdup_printf( _( "Failed to lock the file %s:\n%s" ),
file, g_strerror( errno ) );
close( fd );
errno = savederr;
return -1;
}
return fd;
return success;
}
static char*
@ -134,12 +112,12 @@ gboolean
cf_lock( char ** errstr )
{
char * path = getLockFilename( );
int fd = lockfile( path, errstr );
if( fd >= 0 )
const gboolean didLock = lockfile( path, errstr );
if( didLock )
gl_lockpath = g_strdup( path );
g_atexit( cf_removelocks );
g_free( path );
return fd >= 0;
return didLock;
}
char*

View File

@ -449,3 +449,51 @@ tr_getTorrentsDirectory( void )
init = 1;
return buf;
}
/***
****
***/
int
tr_lockfile( const char * filename )
{
int ret;
#ifdef WIN32
HANDLE file = CreateFile( filename,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL );
if( file == INVALID_HANDLE_VALUE )
ret = TR_LOCKFILE_EOPEN;
else if( !LockFile( file, 0, 0, 1, 1 ) )
ret = TR_LOCKFILE_ELOCK;
else
ret = TR_LOCKFILE_SUCCESS;
#else
int fd = open( filename, O_RDWR | O_CREAT, 0666 );
if( fd < 0 )
ret = TR_LOCKFILE_EOPEN;
else {
struct flock lk;
memset( &lk, 0, sizeof( lk ) );
lk.l_start = 0;
lk.l_len = 0;
lk.l_type = F_WRLCK;
lk.l_whence = SEEK_SET;
if( -1 == fcntl( fd, F_SETLK, &lk ) )
ret = TR_LOCKFILE_ELOCK;
else
ret = TR_LOCKFILE_SUCCESS;
}
#endif
return ret;
}

View File

@ -48,4 +48,14 @@ void tr_lockLock ( tr_lock * );
void tr_lockUnlock ( tr_lock * );
int tr_lockHave ( const tr_lock * );
enum
{
TR_LOCKFILE_SUCCESS,
TR_LOCKFILE_EOPEN,
TR_LOCKFILE_ELOCK
};
int tr_lockfile ( const char * filename );
#endif