2006-07-16 19:39:23 +00:00
/******************************************************************************
* $ Id $
*
2008-01-01 17:20:20 +00:00
* Copyright ( c ) 2005 - 2008 Transmission authors and contributors
2006-07-16 19:39:23 +00:00
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
* FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-04 01:17:39 +00:00
# ifdef __BEOS__
2007-08-03 16:28:32 +00:00
# include <signal.h>
2006-07-16 19:39:23 +00:00
# include <fs_info.h>
# include <FindDirectory.h>
2007-07-30 15:27:52 +00:00
# include <kernel/OS.h>
# define BEOS_MAX_THREADS 256
2007-08-01 00:40:49 +00:00
# elif defined(WIN32)
2007-08-02 19:43:29 +00:00
# include <windows.h>
# include <shlobj.h> /* for CSIDL_APPDATA, CSIDL_PROFILE */
2007-07-30 15:27:52 +00:00
# else
2007-12-02 16:35:44 +00:00
# define _XOPEN_SOURCE 500 /* needed for recursive locks. */
2007-12-02 17:15:52 +00:00
# ifndef __USE_UNIX98
# define __USE_UNIX98 /* some older Linuxes need it spelt out for them */
# endif
2007-07-30 15:27:52 +00:00
# include <pthread.h>
2006-07-16 19:39:23 +00:00
# endif
2007-07-30 15:27:52 +00:00
2007-12-07 19:25:54 +00:00
# include <assert.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
2008-07-11 04:11:22 +00:00
# include <sys/stat.h>
2006-07-16 19:39:23 +00:00
# include <sys/types.h>
# include <dirent.h>
2007-11-27 15:39:59 +00:00
# include <fcntl.h>
# include <unistd.h> /* getuid getpid close */
2007-07-29 18:11:21 +00:00
2006-07-16 19:39:23 +00:00
# include "transmission.h"
2008-07-11 04:07:14 +00:00
# include "list.h"
2007-07-31 14:26:44 +00:00
# include "platform.h"
2007-07-30 15:27:52 +00:00
# include "utils.h"
/***
* * * * THREADS
* * */
2007-10-01 15:17:15 +00:00
# ifdef __BEOS__
typedef thread_id tr_thread_id ;
# elif defined(WIN32)
typedef DWORD tr_thread_id ;
# else
typedef pthread_t tr_thread_id ;
# endif
static tr_thread_id
tr_getCurrentThread ( void )
{
# ifdef __BEOS__
return find_thread ( NULL ) ;
# elif defined(WIN32)
return GetCurrentThreadId ( ) ;
# else
return pthread_self ( ) ;
# endif
}
static int
tr_areThreadsEqual ( tr_thread_id a , tr_thread_id b )
{
# ifdef __BEOS__
return a = = b ;
# elif defined(WIN32)
return a = = b ;
# else
return pthread_equal ( a , b ) ;
# endif
}
2007-09-20 16:32:01 +00:00
struct tr_thread
2007-07-30 15:27:52 +00:00
{
void ( * func ) ( void * ) ;
void * arg ;
2007-09-20 16:32:01 +00:00
const char * name ;
2008-02-28 16:40:31 +00:00
tr_thread_id thread ;
# ifdef WIN32
HANDLE thread_handle ;
2007-07-30 15:27:52 +00:00
# endif
} ;
2007-10-01 15:17:15 +00:00
int
tr_amInThread ( const tr_thread * t )
{
return tr_areThreadsEqual ( tr_getCurrentThread ( ) , t - > thread ) ;
}
2007-07-31 19:56:40 +00:00
# ifdef WIN32
# define ThreadFuncReturnType unsigned WINAPI
# else
# define ThreadFuncReturnType void
# endif
static ThreadFuncReturnType
2007-07-30 15:27:52 +00:00
ThreadFunc ( void * _t )
{
2007-09-20 16:32:01 +00:00
tr_thread * t = _t ;
const char * name = t - > name ;
2007-07-30 15:27:52 +00:00
2007-08-04 01:17:39 +00:00
# ifdef __BEOS__
2007-07-30 15:27:52 +00:00
/* This is required because on BeOS, SIGINT is sent to each thread,
which kills them not nicely */
signal ( SIGINT , SIG_IGN ) ;
# endif
tr_dbg ( " Thread '%s' started " , name ) ;
t - > func ( t - > arg ) ;
tr_dbg ( " Thread '%s' exited " , name ) ;
2007-07-31 19:56:40 +00:00
# ifdef WIN32
_endthreadex ( 0 ) ;
return 0 ;
# endif
2007-07-30 15:27:52 +00:00
}
2007-09-20 16:32:01 +00:00
tr_thread *
2007-07-30 15:27:52 +00:00
tr_threadNew ( void ( * func ) ( void * ) ,
void * arg ,
const char * name )
{
2007-09-20 16:32:01 +00:00
tr_thread * t = tr_new0 ( tr_thread , 1 ) ;
2008-02-29 01:58:46 +00:00
t - > func = func ;
t - > arg = arg ;
t - > name = name ;
2007-07-30 15:27:52 +00:00
2007-08-04 01:17:39 +00:00
# ifdef __BEOS__
2007-07-30 15:27:52 +00:00
t - > thread = spawn_thread ( ( void * ) ThreadFunc , name , B_NORMAL_PRIORITY , t ) ;
resume_thread ( t - > thread ) ;
2007-07-31 19:56:40 +00:00
# elif defined(WIN32)
2008-02-29 01:58:46 +00:00
{
unsigned int id ;
t - > thread_handle = ( HANDLE ) _beginthreadex ( NULL , 0 , & ThreadFunc , t , 0 , & id ) ;
t - > thread = ( DWORD ) id ;
}
2007-07-30 15:27:52 +00:00
# else
pthread_create ( & t - > thread , NULL , ( void * ( * ) ( void * ) ) ThreadFunc , t ) ;
# endif
return t ;
}
2007-09-05 23:01:56 +00:00
2007-07-30 15:27:52 +00:00
/***
* * * * LOCKS
* * */
2007-09-20 16:32:01 +00:00
struct tr_lock
2007-07-30 15:27:52 +00:00
{
2007-12-02 16:35:44 +00:00
int depth ;
2007-08-04 01:17:39 +00:00
# ifdef __BEOS__
2007-07-30 15:27:52 +00:00
sem_id lock ;
2007-10-01 15:17:15 +00:00
thread_id lockThread ;
2007-07-31 19:56:40 +00:00
# elif defined(WIN32)
CRITICAL_SECTION lock ;
2007-10-01 15:17:15 +00:00
DWORD lockThread ;
2007-07-30 15:27:52 +00:00
# else
pthread_mutex_t lock ;
2007-10-01 15:17:15 +00:00
pthread_t lockThread ;
2007-07-30 15:27:52 +00:00
# endif
} ;
2007-09-20 16:32:01 +00:00
tr_lock *
2007-07-30 15:27:52 +00:00
tr_lockNew ( void )
{
2007-09-20 16:32:01 +00:00
tr_lock * l = tr_new0 ( tr_lock , 1 ) ;
2007-07-30 15:27:52 +00:00
2007-08-04 01:17:39 +00:00
# ifdef __BEOS__
2007-07-30 15:27:52 +00:00
l - > lock = create_sem ( 1 , " " ) ;
2007-07-31 19:56:40 +00:00
# elif defined(WIN32)
2008-04-18 23:17:40 +00:00
InitializeCriticalSection ( & l - > lock ) ; /* supports recursion */
2007-07-30 15:27:52 +00:00
# else
2007-12-02 16:35:44 +00:00
pthread_mutexattr_t attr ;
pthread_mutexattr_init ( & attr ) ;
pthread_mutexattr_settype ( & attr , PTHREAD_MUTEX_RECURSIVE ) ;
pthread_mutex_init ( & l - > lock , & attr ) ;
2007-07-30 15:27:52 +00:00
# endif
return l ;
}
void
2007-09-20 16:32:01 +00:00
tr_lockFree ( tr_lock * l )
2007-07-30 15:27:52 +00:00
{
2007-08-04 01:17:39 +00:00
# ifdef __BEOS__
2007-07-30 15:27:52 +00:00
delete_sem ( l - > lock ) ;
2007-07-31 19:56:40 +00:00
# elif defined(WIN32)
DeleteCriticalSection ( & l - > lock ) ;
2007-07-30 15:27:52 +00:00
# else
pthread_mutex_destroy ( & l - > lock ) ;
# endif
tr_free ( l ) ;
}
void
2007-09-20 16:32:01 +00:00
tr_lockLock ( tr_lock * l )
2007-07-30 15:27:52 +00:00
{
2007-08-04 01:17:39 +00:00
# ifdef __BEOS__
2007-12-02 16:35:44 +00:00
acquire_sem ( l - > lock ) ;
2007-07-31 19:56:40 +00:00
# elif defined(WIN32)
2007-12-02 16:35:44 +00:00
EnterCriticalSection ( & l - > lock ) ;
2007-07-30 15:27:52 +00:00
# else
2007-12-02 16:35:44 +00:00
pthread_mutex_lock ( & l - > lock ) ;
2007-07-30 15:27:52 +00:00
# endif
2007-12-03 04:06:45 +00:00
assert ( l - > depth > = 0 ) ;
if ( l - > depth )
assert ( tr_areThreadsEqual ( l - > lockThread , tr_getCurrentThread ( ) ) ) ;
2007-12-02 18:20:37 +00:00
l - > lockThread = tr_getCurrentThread ( ) ;
2007-12-02 16:35:44 +00:00
+ + l - > depth ;
2007-10-01 15:17:15 +00:00
}
int
tr_lockHave ( const tr_lock * l )
{
return ( l - > depth > 0 )
2007-12-02 17:15:52 +00:00
& & ( tr_areThreadsEqual ( l - > lockThread , tr_getCurrentThread ( ) ) ) ;
2007-07-30 15:27:52 +00:00
}
void
2007-09-20 16:32:01 +00:00
tr_lockUnlock ( tr_lock * l )
2007-07-30 15:27:52 +00:00
{
2007-12-02 17:15:52 +00:00
assert ( l - > depth > 0 ) ;
assert ( tr_areThreadsEqual ( l - > lockThread , tr_getCurrentThread ( ) ) ) ;
2007-10-01 15:17:15 +00:00
2007-12-02 18:20:37 +00:00
- - l - > depth ;
assert ( l - > depth > = 0 ) ;
2007-08-04 01:17:39 +00:00
# ifdef __BEOS__
2007-12-02 16:35:44 +00:00
release_sem ( l - > lock ) ;
2007-07-31 19:56:40 +00:00
# elif defined(WIN32)
2007-12-02 16:35:44 +00:00
LeaveCriticalSection ( & l - > lock ) ;
2007-07-30 15:27:52 +00:00
# else
2007-12-02 16:35:44 +00:00
pthread_mutex_unlock ( & l - > lock ) ;
2007-07-30 15:27:52 +00:00
# endif
}
/***
* * * * PATHS
* * */
2006-07-16 19:39:23 +00:00
2007-08-04 01:17:39 +00:00
# if !defined(WIN32) && !defined(__BEOS__) && !defined(__AMIGAOS4__)
2006-10-13 06:29:26 +00:00
# include <pwd.h>
2007-08-02 19:43:29 +00:00
# endif
2006-10-13 06:29:26 +00:00
2007-12-15 22:22:30 +00:00
static const char *
2008-04-05 20:12:11 +00:00
getHomeDir ( void )
2006-10-13 06:29:26 +00:00
{
2008-04-05 20:12:11 +00:00
static char * home = NULL ;
2006-10-13 06:29:26 +00:00
2008-04-05 20:12:11 +00:00
if ( ! home )
{
home = tr_strdup ( getenv ( " HOME " ) ) ;
2006-10-13 06:29:26 +00:00
2008-04-05 20:12:11 +00:00
if ( ! home )
{
2007-08-02 19:43:29 +00:00
# ifdef WIN32
2008-04-18 15:33:24 +00:00
SHGetFolderPath ( NULL , CSIDL_PROFILE , NULL , 0 , home ) ;
2007-08-04 01:17:39 +00:00
# elif defined(__BEOS__) || defined(__AMIGAOS4__)
2008-04-05 20:12:11 +00:00
home = tr_strdup ( " " ) ;
2007-08-02 19:43:29 +00:00
# else
2008-04-05 20:12:11 +00:00
struct passwd * pw = getpwuid ( getuid ( ) ) ;
if ( pw )
home = tr_strdup ( pw - > pw_dir ) ;
2008-04-18 23:17:40 +00:00
endpwent ( ) ;
2007-08-02 19:43:29 +00:00
# endif
2006-07-16 19:39:23 +00:00
}
2008-04-05 20:12:11 +00:00
if ( ! home )
home = tr_strdup ( " " ) ;
2006-07-16 19:39:23 +00:00
}
2008-04-05 20:12:11 +00:00
return home ;
2006-07-16 19:39:23 +00:00
}
2008-04-05 20:12:11 +00:00
static const char *
getOldConfigDir ( void )
2006-07-16 19:39:23 +00:00
{
2008-04-05 20:12:11 +00:00
static char * path = NULL ;
2006-07-16 19:39:23 +00:00
2008-04-05 20:12:11 +00:00
if ( ! path )
2007-12-15 22:22:30 +00:00
{
2008-04-05 20:12:11 +00:00
char buf [ MAX_PATH_LENGTH ] ;
2007-08-04 01:17:39 +00:00
# ifdef __BEOS__
2007-12-15 22:22:30 +00:00
find_directory ( B_USER_SETTINGS_DIRECTORY ,
dev_for_path ( " /boot " ) , true ,
buf , sizeof ( buf ) ) ;
strcat ( buf , " /Transmission " ) ;
2006-07-16 19:39:23 +00:00
# elif defined( SYS_DARWIN )
2008-04-05 20:12:11 +00:00
tr_buildPath ( buf , sizeof ( buf ) , getHomeDir ( ) ,
" Library " , " Application Support " ,
" Transmission " , NULL ) ;
2006-07-23 19:39:02 +00:00
# elif defined(__AMIGAOS4__)
2008-05-18 16:44:30 +00:00
tr_strlcpy ( buf , " PROGDIR:.transmission " , sizeof ( buf ) ) ;
2007-08-02 19:43:29 +00:00
# elif defined(WIN32)
2007-12-15 22:22:30 +00:00
char appdata [ MAX_PATH_LENGTH ] ;
SHGetFolderPath ( NULL , CSIDL_APPDATA , NULL , 0 , appdata ) ;
tr_buildPath ( buf , sizeof ( buf ) ,
2008-04-05 20:12:11 +00:00
appdata , " Transmission " , NULL ) ;
2006-07-16 19:39:23 +00:00
# else
2008-04-05 20:12:11 +00:00
tr_buildPath ( buf , sizeof ( buf ) ,
getHomeDir ( ) , " .transmission " , NULL ) ;
2006-07-16 19:39:23 +00:00
# endif
2008-04-05 20:12:11 +00:00
path = tr_strdup ( buf ) ;
2007-12-15 22:22:30 +00:00
}
2006-07-16 19:39:23 +00:00
2008-04-05 20:12:11 +00:00
return path ;
}
2006-07-16 19:39:23 +00:00
2008-04-05 20:12:11 +00:00
static const char *
getOldTorrentsDir ( void )
{
static char * path = NULL ;
if ( ! path )
{
char buf [ MAX_PATH_LENGTH ] ;
const char * p = getOldConfigDir ( ) ;
# if defined(__BEOS__) || defined(WIN32) || defined(SYS_DARWIN)
tr_buildPath ( buf , sizeof ( buf ) , p , " Torrents " , NULL ) ;
# else
tr_buildPath ( buf , sizeof ( buf ) , p , " torrents " , NULL ) ;
2006-07-16 19:39:23 +00:00
# endif
2008-04-05 20:12:11 +00:00
path = tr_strdup ( buf ) ;
}
2006-07-16 19:39:23 +00:00
2008-04-05 20:12:11 +00:00
return path ;
}
static const char *
getOldCacheDir ( void )
2006-07-16 19:39:23 +00:00
{
2008-04-05 20:12:11 +00:00
static char * path = NULL ;
2006-07-16 19:39:23 +00:00
2008-04-05 20:12:11 +00:00
if ( ! path )
{
char buf [ MAX_PATH_LENGTH ] ;
2007-08-04 01:17:39 +00:00
# if defined(__BEOS__) || defined(WIN32)
2008-04-23 13:26:30 +00:00
const char * p = getOldConfigDir ( ) ;
2008-04-05 20:12:11 +00:00
tr_buildPath ( buf , sizeof ( buf ) , p , " Cache " , NULL ) ;
2006-07-16 19:39:23 +00:00
# elif defined( SYS_DARWIN )
2008-04-05 20:12:11 +00:00
tr_buildPath ( buf , sizeof ( buf ) , getHomeDir ( ) ,
" Library " , " Caches " , " Transmission " , NULL ) ;
2006-07-16 19:39:23 +00:00
# else
2008-04-23 13:26:30 +00:00
const char * p = getOldConfigDir ( ) ;
2008-04-05 20:12:11 +00:00
tr_buildPath ( buf , sizeof ( buf ) , p , " cache " , NULL ) ;
2006-07-16 19:39:23 +00:00
# endif
2008-04-05 20:12:11 +00:00
path = tr_strdup ( buf ) ;
}
2006-07-16 19:39:23 +00:00
2008-04-05 20:12:11 +00:00
return path ;
}
static void
moveFiles ( const char * oldDir , const char * newDir )
{
if ( oldDir & & newDir & & strcmp ( oldDir , newDir ) )
{
DIR * dirh = opendir ( oldDir ) ;
if ( dirh )
{
int count = 0 ;
struct dirent * dirp ;
while ( ( dirp = readdir ( dirh ) ) )
{
if ( strcmp ( dirp - > d_name , " . " ) & & strcmp ( dirp - > d_name , " .. " ) )
{
char o [ MAX_PATH_LENGTH ] ;
char n [ MAX_PATH_LENGTH ] ;
tr_buildPath ( o , sizeof ( o ) , oldDir , dirp - > d_name , NULL ) ;
tr_buildPath ( n , sizeof ( n ) , newDir , dirp - > d_name , NULL ) ;
rename ( o , n ) ;
+ + count ;
}
}
2008-04-10 02:53:03 +00:00
if ( count )
tr_inf ( _ ( " Migrated %1$d files from \" %2$s \" to \" %3$s \" " ) ,
count , oldDir , newDir ) ;
2008-04-05 20:12:11 +00:00
closedir ( dirh ) ;
}
}
}
static void
migrateFiles ( const tr_handle * handle )
{
static int migrated = FALSE ;
if ( ! migrated )
{
const char * oldDir ;
const char * newDir ;
migrated = TRUE ;
oldDir = getOldTorrentsDir ( ) ;
newDir = tr_getTorrentDir ( handle ) ;
moveFiles ( oldDir , newDir ) ;
oldDir = getOldCacheDir ( ) ;
newDir = tr_getResumeDir ( handle ) ;
moveFiles ( oldDir , newDir ) ;
}
}
# ifdef SYS_DARWIN
# define RESUME_SUBDIR "Resume"
# define TORRENT_SUBDIR "Torrents"
# else
# define RESUME_SUBDIR "resume"
# define TORRENT_SUBDIR "torrents"
# endif
void
tr_setConfigDir ( tr_handle * handle , const char * configDir )
{
char buf [ MAX_PATH_LENGTH ] ;
handle - > configDir = tr_strdup ( configDir ) ;
tr_buildPath ( buf , sizeof ( buf ) , configDir , RESUME_SUBDIR , NULL ) ;
tr_mkdirp ( buf , 0777 ) ;
handle - > resumeDir = tr_strdup ( buf ) ;
tr_buildPath ( buf , sizeof ( buf ) , configDir , TORRENT_SUBDIR , NULL ) ;
2007-12-09 15:22:01 +00:00
tr_mkdirp ( buf , 0777 ) ;
2008-04-05 20:12:11 +00:00
handle - > torrentDir = tr_strdup ( buf ) ;
2006-07-16 19:39:23 +00:00
2008-04-05 20:12:11 +00:00
migrateFiles ( handle ) ;
}
2006-07-16 19:39:23 +00:00
2008-04-05 20:12:11 +00:00
const char *
2008-05-18 16:44:30 +00:00
tr_sessionGetConfigDir ( const tr_handle * handle )
2008-04-05 20:12:11 +00:00
{
return handle - > configDir ;
2006-07-16 19:39:23 +00:00
}
2007-06-18 19:39:52 +00:00
const char *
2008-04-05 20:12:11 +00:00
tr_getTorrentDir ( const tr_handle * handle )
2006-07-16 19:39:23 +00:00
{
2008-04-05 20:12:11 +00:00
return handle - > torrentDir ;
}
2006-07-16 19:39:23 +00:00
2008-04-05 20:12:11 +00:00
const char *
tr_getResumeDir ( const tr_handle * handle )
{
return handle - > resumeDir ;
}
2007-06-18 19:39:52 +00:00
2008-04-05 20:12:11 +00:00
const char *
tr_getDefaultConfigDir ( void )
{
static char * s = NULL ;
2006-07-16 19:39:23 +00:00
2008-04-05 20:12:11 +00:00
if ( ! s )
{
char path [ MAX_PATH_LENGTH ] ;
if ( ( s = getenv ( " TRANSMISSION_HOME " ) ) )
{
2008-07-15 17:16:57 +00:00
tr_snprintf ( path , sizeof ( path ) , s ) ;
2008-04-05 20:12:11 +00:00
}
else
{
2008-04-05 20:27:13 +00:00
# ifdef SYS_DARWIN
2008-04-05 20:12:11 +00:00
tr_buildPath ( path , sizeof ( path ) ,
getHomeDir ( ) , " Library " , " Application Support " ,
" Transmission " , NULL ) ;
# elif defined(WIN32)
char appdata [ MAX_PATH_LENGTH ] ;
SHGetFolderPath ( NULL , CSIDL_APPDATA , NULL , 0 , appdata ) ;
tr_buildPath ( path , sizeof ( path ) ,
appdata , " Transmission " , NULL ) ;
2006-07-16 19:39:23 +00:00
# else
2008-04-05 20:12:11 +00:00
if ( ( s = getenv ( " XDG_CONFIG_HOME " ) ) )
tr_buildPath ( path , sizeof ( path ) ,
s , " transmission " , NULL ) ;
else
tr_buildPath ( path , sizeof ( path ) ,
getHomeDir ( ) , " .config " , " transmission " , NULL ) ;
2006-07-16 19:39:23 +00:00
# endif
2008-04-05 20:12:11 +00:00
}
2006-07-16 19:39:23 +00:00
2008-04-05 20:12:11 +00:00
s = tr_strdup ( path ) ;
}
return s ;
2006-07-16 19:39:23 +00:00
}
2008-02-28 19:06:23 +00:00
2008-07-11 04:07:14 +00:00
/***
* * * *
* * */
static int
isClutchDir ( const char * path )
{
struct stat sb ;
char tmp [ MAX_PATH_LENGTH ] ;
tr_buildPath ( tmp , sizeof ( tmp ) , path , " javascript " , " transmission.js " , NULL ) ;
2008-07-11 17:09:53 +00:00
tr_inf ( _ ( " Searching for web interface file \" %s \" " ) , tmp ) ;
2008-07-11 04:07:14 +00:00
return ! stat ( tmp , & sb ) ;
}
const char *
tr_getClutchDir ( const tr_session * session UNUSED )
{
static char * s = NULL ;
if ( ! s )
{
2008-07-14 16:00:20 +00:00
char path [ MAX_PATH_LENGTH ] = { ' \0 ' } ;
2008-07-11 04:07:14 +00:00
if ( ( s = getenv ( " CLUTCH_HOME " ) ) )
{
2008-07-15 17:16:57 +00:00
tr_snprintf ( path , sizeof ( path ) , s ) ;
2008-07-11 04:07:14 +00:00
}
2008-07-14 16:00:20 +00:00
else if ( ( s = getenv ( " TRANSMISSION_WEB_HOME " ) ) )
{
2008-07-15 17:16:57 +00:00
tr_snprintf ( path , sizeof ( path ) , s ) ;
2008-07-14 16:00:20 +00:00
}
2008-07-11 04:07:14 +00:00
else
{
# ifdef SYS_DARWIN
2008-07-11 04:19:23 +00:00
# warning hey BentMyWookie can this be implemented here without passing anything into initFull()
2008-07-11 04:07:14 +00:00
# elif defined(WIN32)
2008-07-11 04:19:23 +00:00
# warning hey win32 people is this good or is there a better implementation of the next four lines
2008-07-11 04:07:14 +00:00
char appdata [ MAX_PATH_LENGTH ] ;
SHGetFolderPath ( NULL , CSIDL_APPDATA , NULL , 0 , appdata ) ;
tr_buildPath ( path , sizeof ( path ) ,
appdata , " Transmission " , NULL ) ;
# else
tr_list * candidates = NULL , * l ;
/* XDG_DATA_HOME should be the first in the list of candidates */
s = getenv ( " XDG_DATA_HOME " ) ;
if ( s & & * s )
tr_list_append ( & candidates , tr_strdup ( s ) ) ;
else {
char tmp [ MAX_PATH_LENGTH ] ;
tr_buildPath ( tmp , sizeof ( tmp ) , getHomeDir ( ) , " .local " , " share " , NULL ) ;
tr_list_append ( & candidates , tr_strdup ( tmp ) ) ;
}
/* XDG_DATA_DIRS are the backup directories */
s = getenv ( " XDG_DATA_DIRS " ) ;
if ( ! s | | ! * s )
s = " /usr/local/share/:/usr/share/ " ;
while ( s & & * s ) {
char * end = strchr ( s , ' : ' ) ;
if ( end ) {
tr_list_append ( & candidates , tr_strndup ( s , end - s ) ) ;
s = end + 1 ;
} else {
tr_list_append ( & candidates , tr_strdup ( s ) ) ;
break ;
}
}
for ( l = candidates ; l ; l = l - > next ) {
2008-07-14 16:00:20 +00:00
tr_buildPath ( path , sizeof ( path ) , l - > data , " transmission " , " web " , NULL ) ;
2008-07-11 04:07:14 +00:00
if ( isClutchDir ( path ) )
break ;
* path = ' \0 ' ;
}
tr_list_free ( & candidates , tr_free ) ;
# endif
}
if ( ! * path )
2008-07-16 02:31:08 +00:00
{
tr_strlcpy ( path , " /dev/null " , sizeof ( path ) ) ;
2008-07-11 17:09:53 +00:00
tr_err ( _ ( " Couldn't find the web interface's files! To customize this, set the CLUTCH_HOME environmental variable to the folder where index.html is located. " ) ) ;
2008-07-16 02:31:08 +00:00
}
2008-07-11 04:07:14 +00:00
s = tr_strdup ( path ) ;
}
return s ;
}
2008-02-28 19:06:23 +00:00
/***
* * * *
* * */
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 ;
}