source: trunk/libtransmission/platform.c @ 4232

Last change on this file since 4232 was 4232, checked in by livings124, 13 years ago

remove unused variables

  • Property svn:keywords set to Date Rev Author Id
File size: 10.3 KB
Line 
1/******************************************************************************
2 * $Id: platform.c 4232 2007-12-20 01:15:13Z livings124 $
3 *
4 * Copyright (c) 2005 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#ifdef __BEOS__
26  #include <signal.h> 
27  #include <fs_info.h>
28  #include <FindDirectory.h>
29  #include <kernel/OS.h>
30  #define BEOS_MAX_THREADS 256
31#elif defined(WIN32)
32  #include <windows.h>
33  #include <shlobj.h> /* for CSIDL_APPDATA, CSIDL_PROFILE */
34#else
35  #define _XOPEN_SOURCE 500 /* needed for recursive locks. */
36  #ifndef __USE_UNIX98
37  #define __USE_UNIX98 /* some older Linuxes need it spelt out for them */
38  #endif
39  #include <pthread.h>
40#endif
41
42#include <assert.h>
43#include <errno.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47
48#include <sys/types.h>
49#include <dirent.h>
50#include <fcntl.h>
51#include <unistd.h> /* getuid getpid close */
52
53#include "transmission.h"
54#include "list.h"
55#include "net.h"
56#include "platform.h"
57#include "trcompat.h"
58#include "utils.h"
59
60/***
61****  THREADS
62***/
63
64#ifdef __BEOS__
65typedef thread_id tr_thread_id;
66#elif defined(WIN32)
67typedef DWORD tr_thread_id;
68#else
69typedef pthread_t tr_thread_id;
70#endif
71
72static tr_thread_id
73tr_getCurrentThread( void )
74{
75#ifdef __BEOS__
76    return find_thread( NULL );
77#elif defined(WIN32)
78    return GetCurrentThreadId();
79#else
80    return pthread_self( );
81#endif
82}
83
84static int
85tr_areThreadsEqual( tr_thread_id a, tr_thread_id b )
86{
87#ifdef __BEOS__
88    return a == b;
89#elif defined(WIN32)
90    return a == b;
91#else
92    return pthread_equal( a, b );
93#endif
94}
95
96struct tr_thread
97{
98    void          (* func ) ( void * );
99    void           * arg;
100    const char     * name;
101
102#ifdef __BEOS__
103    thread_id        thread;
104#elif defined(WIN32)
105    HANDLE           thread;
106    unsigned int     thread_id;
107#else
108    pthread_t        thread;
109#endif
110
111};
112
113int
114tr_amInThread ( const tr_thread * t )
115{
116    return tr_areThreadsEqual( tr_getCurrentThread(), t->thread );
117}
118
119#ifdef WIN32
120#define ThreadFuncReturnType unsigned WINAPI
121#else
122#define ThreadFuncReturnType void
123#endif
124
125static ThreadFuncReturnType
126ThreadFunc( void * _t )
127{
128    tr_thread * t = _t;
129    const char * name = t->name;
130
131#ifdef __BEOS__
132    /* This is required because on BeOS, SIGINT is sent to each thread,
133       which kills them not nicely */
134    signal( SIGINT, SIG_IGN );
135#endif
136
137    tr_dbg( "Thread '%s' started", name );
138    t->func( t->arg );
139    tr_dbg( "Thread '%s' exited", name );
140
141#ifdef WIN32
142    _endthreadex( 0 );
143    return 0;
144#endif
145}
146
147tr_thread *
148tr_threadNew( void (*func)(void *),
149              void * arg,
150              const char * name )
151{
152    tr_thread * t = tr_new0( tr_thread, 1 );
153    t->func = func;
154    t->arg  = arg;
155    t->name = name;
156
157#ifdef __BEOS__
158    t->thread = spawn_thread( (void*)ThreadFunc, name, B_NORMAL_PRIORITY, t );
159    resume_thread( t->thread );
160#elif defined(WIN32)
161    t->thread = (HANDLE) _beginthreadex( NULL, 0, &ThreadFunc, t, 0, &t->thread_id );
162#else
163    pthread_create( &t->thread, NULL, (void * (*) (void *)) ThreadFunc, t );
164#endif
165
166    return t;
167}
168   
169void
170tr_threadJoin( tr_thread * t )
171{
172    if( t != NULL )
173    {
174#ifdef __BEOS__
175        long exit;
176        wait_for_thread( t->thread, &exit );
177#elif defined(WIN32)
178        WaitForSingleObject( t->thread, INFINITE );
179        CloseHandle( t->thread );
180#else
181        pthread_join( t->thread, NULL );
182#endif
183
184        tr_dbg( "Thread '%s' joined", t->name );
185        t->name = NULL;
186        t->func = NULL;
187        tr_free( t );
188    }
189}
190
191/***
192****  LOCKS
193***/
194
195struct tr_lock
196{
197    int depth;
198#ifdef __BEOS__
199    sem_id lock;
200    thread_id lockThread;
201#elif defined(WIN32)
202    CRITICAL_SECTION lock;
203    DWORD lockThread;
204#else
205    pthread_mutex_t lock;
206    pthread_t lockThread;
207#endif
208};
209
210tr_lock*
211tr_lockNew( void )
212{
213    tr_lock * l = tr_new0( tr_lock, 1 );
214
215#ifdef __BEOS__
216    l->lock = create_sem( 1, "" );
217#elif defined(WIN32)
218    InitializeCriticalSection( &l->lock ); /* critical sections support recursion */
219#else
220    pthread_mutexattr_t attr;
221    pthread_mutexattr_init( &attr );
222    pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
223    pthread_mutex_init( &l->lock, &attr );
224#endif
225
226    return l;
227}
228
229void
230tr_lockFree( tr_lock * l )
231{
232#ifdef __BEOS__
233    delete_sem( l->lock );
234#elif defined(WIN32)
235    DeleteCriticalSection( &l->lock );
236#else
237    pthread_mutex_destroy( &l->lock );
238#endif
239    tr_free( l );
240}
241
242void
243tr_lockLock( tr_lock * l )
244{
245#ifdef __BEOS__
246    acquire_sem( l->lock );
247#elif defined(WIN32)
248    EnterCriticalSection( &l->lock );
249#else
250    pthread_mutex_lock( &l->lock );
251#endif
252    assert( l->depth >= 0 );
253    if( l->depth )
254        assert( tr_areThreadsEqual( l->lockThread, tr_getCurrentThread() ) );
255    l->lockThread = tr_getCurrentThread( );
256    ++l->depth;
257}
258
259int
260tr_lockHave( const tr_lock * l )
261{
262    return ( l->depth > 0 )
263        && ( tr_areThreadsEqual( l->lockThread, tr_getCurrentThread() ) );
264}
265
266void
267tr_lockUnlock( tr_lock * l )
268{
269    assert( l->depth > 0 );
270    assert( tr_areThreadsEqual( l->lockThread, tr_getCurrentThread() ));
271
272    --l->depth;
273    assert( l->depth >= 0 );
274#ifdef __BEOS__
275    release_sem( l->lock );
276#elif defined(WIN32)
277    LeaveCriticalSection( &l->lock );
278#else
279    pthread_mutex_unlock( &l->lock );
280#endif
281}
282
283/***
284****  PATHS
285***/
286
287#if !defined(WIN32) && !defined(__BEOS__) && !defined(__AMIGAOS4__)
288#include <pwd.h>
289#endif
290
291static const char *
292tr_getHomeDirectory( void )
293{
294    static char buf[MAX_PATH_LENGTH];
295    static int init = 0;
296    const char * envHome;
297
298    if( init )
299        return buf;
300
301    envHome = getenv( "HOME" );
302    if( envHome )
303        snprintf( buf, sizeof(buf), "%s", envHome );
304    else {
305#ifdef WIN32
306        SHGetFolderPath( NULL, CSIDL_PROFILE, NULL, 0, buf );
307#elif defined(__BEOS__) || defined(__AMIGAOS4__)
308        *buf = '\0';
309#else
310        struct passwd * pw = getpwuid( getuid() );
311        endpwent();
312        if( pw != NULL )
313            snprintf( buf, sizeof(buf), "%s", pw->pw_dir );
314#endif
315    }
316
317    init = 1;
318    return buf;
319}
320
321
322static void
323tr_migrateResume( const char *oldDirectory, const char *newDirectory )
324{
325    DIR * dirh = opendir( oldDirectory );
326
327    if( dirh != NULL )
328    {
329        struct dirent * dirp;
330
331        while( ( dirp = readdir( dirh ) ) )
332        {
333            if( !strncmp( "resume.", dirp->d_name, 7 ) )
334            {
335                char o[MAX_PATH_LENGTH];
336                char n[MAX_PATH_LENGTH];
337                tr_buildPath( o, sizeof(o), oldDirectory, dirp->d_name, NULL );
338                tr_buildPath( n, sizeof(n), newDirectory, dirp->d_name, NULL );
339                rename( o, n );
340            }
341        }
342
343        closedir( dirh );
344    }
345}
346
347const char *
348tr_getPrefsDirectory( void )
349{
350    static char   buf[MAX_PATH_LENGTH];
351    static int    init = 0;
352    const char * trhome;
353
354    if( init )
355        return buf;
356
357    trhome = getenv( "TRANSMISSION_HOME" );
358    if( trhome != NULL )
359    {
360        strlcpy( buf, trhome, sizeof( buf ) );
361    }
362    else
363    {
364#ifdef __BEOS__
365        find_directory( B_USER_SETTINGS_DIRECTORY,
366                        dev_for_path("/boot"), true,
367                        buf, sizeof( buf ) );
368        strcat( buf, "/Transmission" );
369#elif defined( SYS_DARWIN )
370        tr_buildPath ( buf, sizeof( buf ),
371                       tr_getHomeDirectory( ),
372                       "Library",
373                       "Application Support",
374                       "Transmission",
375                       NULL );
376#elif defined(__AMIGAOS4__)
377        strlcpy( buf, "PROGDIR:.transmission", sizeof( buf ) );
378#elif defined(WIN32)
379        char appdata[MAX_PATH_LENGTH];
380        SHGetFolderPath( NULL, CSIDL_APPDATA, NULL, 0, appdata );
381        tr_buildPath( buf, sizeof(buf),
382                      appdata,
383                      "Transmission",
384                      NULL );
385#else
386        tr_buildPath ( buf, sizeof(buf), tr_getHomeDirectory( ), ".transmission", NULL );
387#endif
388    }
389
390    tr_mkdirp( buf, 0777 );
391    init = 1;
392
393#ifdef SYS_DARWIN
394    char old[MAX_PATH_LENGTH];
395    tr_buildPath ( old, sizeof(old),
396                   tr_getHomeDirectory(), ".transmission", NULL );
397    tr_migrateResume( old, buf );
398    rmdir( old );
399#endif
400
401    return buf;
402}
403
404const char *
405tr_getCacheDirectory( void )
406{
407    static char buf[MAX_PATH_LENGTH];
408    static int  init = 0;
409    static const size_t buflen = sizeof(buf);
410    const char * p;
411
412    if( init )
413        return buf;
414
415    p = tr_getPrefsDirectory();
416#if defined(__BEOS__) || defined(WIN32)
417    tr_buildPath( buf, buflen, p, "Cache", NULL );
418#elif defined( SYS_DARWIN )
419    tr_buildPath( buf, buflen, tr_getHomeDirectory(),
420                  "Library", "Caches", "Transmission", NULL );
421#else
422    tr_buildPath( buf, buflen, p, "cache", NULL );
423#endif
424
425    tr_mkdirp( buf, 0777 );
426    init = 1;
427
428    if( strcmp( p, buf ) )
429        tr_migrateResume( p, buf );
430
431    return buf;
432}
433
434const char *
435tr_getTorrentsDirectory( void )
436{
437    static char buf[MAX_PATH_LENGTH];
438    static int  init = 0;
439    static const size_t buflen = sizeof(buf);
440    const char * p;
441
442    if( init )
443        return buf;
444
445    p = tr_getPrefsDirectory ();
446
447#if defined(__BEOS__) || defined(WIN32)
448    tr_buildPath( buf, buflen, p, "Torrents", NULL );
449#elif defined( SYS_DARWIN )
450    tr_buildPath( buf, buflen, p, "Torrents", NULL );
451#else
452    tr_buildPath( buf, buflen, p, "torrents", NULL );
453#endif
454
455    tr_mkdirp( buf, 0777 );
456    init = 1;
457    return buf;
458}
Note: See TracBrowser for help on using the repository browser.