Changeset 13625 for trunk/libtransmission/platform.c
- Timestamp:
- Dec 5, 2012, 5:29:46 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/platform.c
r12684 r13625 3 3 * 4 4 * This file is licensed by the GPL version 2. Works owned by the 5 * Transmission project are granted a special exemption to clause 2 (b)5 * Transmission project are granted a special exemption to clause 2 (b) 6 6 * so that the bulk of its code can remain under the MIT license. 7 7 * This exemption does not extend to derived works not owned by … … 69 69 70 70 static tr_thread_id 71 tr_getCurrentThread ( void)72 { 73 #ifdef WIN32 74 return GetCurrentThreadId();75 #else 76 return pthread_self();71 tr_getCurrentThread (void) 72 { 73 #ifdef WIN32 74 return GetCurrentThreadId (); 75 #else 76 return pthread_self (); 77 77 #endif 78 78 } 79 79 80 80 static bool 81 tr_areThreadsEqual ( tr_thread_id a, tr_thread_id b)82 { 83 #ifdef WIN32 84 85 #else 86 return pthread_equal( a, b) != 0;81 tr_areThreadsEqual (tr_thread_id a, tr_thread_id b) 82 { 83 #ifdef WIN32 84 return a == b; 85 #else 86 return pthread_equal (a, b) != 0; 87 87 #endif 88 88 } … … 91 91 struct tr_thread 92 92 { 93 void ( * func )( void *);94 void *arg;95 tr_thread_idthread;96 #ifdef WIN32 97 HANDLEthread_handle;93 void (* func)(void *); 94 void * arg; 95 tr_thread_id thread; 96 #ifdef WIN32 97 HANDLE thread_handle; 98 98 #endif 99 99 }; 100 100 101 101 bool 102 tr_amInThread ( const tr_thread * t)103 { 104 return tr_areThreadsEqual( tr_getCurrentThread( ), t->thread);102 tr_amInThread (const tr_thread * t) 103 { 104 return tr_areThreadsEqual (tr_getCurrentThread (), t->thread); 105 105 } 106 106 … … 112 112 113 113 static ThreadFuncReturnType 114 ThreadFunc ( void * _t)115 { 116 117 118 t->func( t->arg);119 120 tr_free( t);121 #ifdef WIN32 122 _endthreadex( 0);123 114 ThreadFunc (void * _t) 115 { 116 tr_thread * t = _t; 117 118 t->func (t->arg); 119 120 tr_free (t); 121 #ifdef WIN32 122 _endthreadex (0); 123 return 0; 124 124 #endif 125 125 } 126 126 127 127 tr_thread * 128 tr_threadNew( void ( *func )(void *), 129 void * arg ) 130 { 131 tr_thread * t = tr_new0( tr_thread, 1 ); 132 133 t->func = func; 134 t->arg = arg; 135 136 #ifdef WIN32 137 { 138 unsigned int id; 139 t->thread_handle = 140 (HANDLE) _beginthreadex( NULL, 0, &ThreadFunc, t, 0, 141 &id ); 142 t->thread = (DWORD) id; 143 } 144 #else 145 pthread_create( &t->thread, NULL, (void*(*)(void*))ThreadFunc, t ); 146 pthread_detach( t->thread ); 147 148 #endif 149 150 return t; 128 tr_threadNew (void (*func)(void *), void * arg) 129 { 130 tr_thread * t = tr_new0 (tr_thread, 1); 131 132 t->func = func; 133 t->arg = arg; 134 135 #ifdef WIN32 136 { 137 unsigned int id; 138 t->thread_handle = (HANDLE) _beginthreadex (NULL, 0, &ThreadFunc, t, 0, &id); 139 t->thread = (DWORD) id; 140 } 141 #else 142 pthread_create (&t->thread, NULL, (void* (*)(void*))ThreadFunc, t); 143 pthread_detach (t->thread); 144 #endif 145 146 return t; 151 147 } 152 148 … … 158 154 struct tr_lock 159 155 { 160 161 #ifdef WIN32 162 163 164 #else 165 166 156 int depth; 157 #ifdef WIN32 158 CRITICAL_SECTION lock; 159 DWORD lockThread; 160 #else 161 pthread_mutex_t lock; 162 pthread_t lockThread; 167 163 #endif 168 164 }; 169 165 170 166 tr_lock* 171 tr_lockNew ( void)172 { 173 tr_lock * l = tr_new0( tr_lock, 1);174 175 #ifdef WIN32 176 InitializeCriticalSection( &l->lock); /* supports recursion */177 #else 178 179 pthread_mutexattr_init( &attr);180 pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE);181 pthread_mutex_init( &l->lock, &attr);182 #endif 183 184 167 tr_lockNew (void) 168 { 169 tr_lock * l = tr_new0 (tr_lock, 1); 170 171 #ifdef WIN32 172 InitializeCriticalSection (&l->lock); /* supports recursion */ 173 #else 174 pthread_mutexattr_t attr; 175 pthread_mutexattr_init (&attr); 176 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); 177 pthread_mutex_init (&l->lock, &attr); 178 #endif 179 180 return l; 185 181 } 186 182 187 183 void 188 tr_lockFree ( tr_lock * l)189 { 190 #ifdef WIN32 191 DeleteCriticalSection ( &l->lock);192 #else 193 pthread_mutex_destroy ( &l->lock);194 #endif 195 tr_free ( l);184 tr_lockFree (tr_lock * l) 185 { 186 #ifdef WIN32 187 DeleteCriticalSection (&l->lock); 188 #else 189 pthread_mutex_destroy (&l->lock); 190 #endif 191 tr_free (l); 196 192 } 197 193 198 194 void 199 tr_lockLock ( tr_lock * l)200 { 201 #ifdef WIN32 202 EnterCriticalSection( &l->lock);203 #else 204 pthread_mutex_lock( &l->lock);205 #endif 206 assert( l->depth >= 0 ); 207 if( l->depth )208 assert( tr_areThreadsEqual( l->lockThread, tr_getCurrentThread( ) ));209 l->lockThread = tr_getCurrentThread();210 195 tr_lockLock (tr_lock * l) 196 { 197 #ifdef WIN32 198 EnterCriticalSection (&l->lock); 199 #else 200 pthread_mutex_lock (&l->lock); 201 #endif 202 203 assert (l->depth >= 0); 204 assert (!l->depth || tr_areThreadsEqual (l->lockThread, tr_getCurrentThread ())); 205 l->lockThread = tr_getCurrentThread (); 206 ++l->depth; 211 207 } 212 208 213 209 int 214 tr_lockHave ( const tr_lock * l)215 { 216 return ( l->depth > 0 )217 && ( tr_areThreadsEqual( l->lockThread, tr_getCurrentThread( ) ));210 tr_lockHave (const tr_lock * l) 211 { 212 return (l->depth > 0) && 213 (tr_areThreadsEqual (l->lockThread, tr_getCurrentThread ())); 218 214 } 219 215 220 216 void 221 tr_lockUnlock ( tr_lock * l)222 { 223 assert( l->depth > 0);224 assert( tr_areThreadsEqual( l->lockThread, tr_getCurrentThread( ) ));225 226 227 assert( l->depth >= 0);228 #ifdef WIN32 229 LeaveCriticalSection( &l->lock);230 #else 231 pthread_mutex_unlock( &l->lock);217 tr_lockUnlock (tr_lock * l) 218 { 219 assert (l->depth > 0); 220 assert (tr_areThreadsEqual (l->lockThread, tr_getCurrentThread ())); 221 222 --l->depth; 223 assert (l->depth >= 0); 224 #ifdef WIN32 225 LeaveCriticalSection (&l->lock); 226 #else 227 pthread_mutex_unlock (&l->lock); 232 228 #endif 233 229 } … … 242 238 243 239 static const char * 244 getHomeDir ( void)245 { 246 247 248 if( !home)249 { 250 home = tr_strdup( getenv( "HOME" ));251 252 if( !home)240 getHomeDir (void) 241 { 242 static char * home = NULL; 243 244 if (!home) 245 { 246 home = tr_strdup (getenv ("HOME")); 247 248 if (!home) 253 249 { 254 250 #ifdef WIN32 255 char appdata[MAX_PATH]; /* SHGetFolderPath() requires MAX_PATH */256 257 SHGetFolderPath( NULL, CSIDL_PERSONAL, NULL, 0, appdata);258 home = tr_strdup( appdata);259 #else 260 struct passwd * pw = getpwuid( getuid( ));261 if( pw)262 home = tr_strdup( pw->pw_dir);263 endpwent();251 char appdata[MAX_PATH]; /* SHGetFolderPath () requires MAX_PATH */ 252 *appdata = '\0'; 253 SHGetFolderPath (NULL, CSIDL_PERSONAL, NULL, 0, appdata); 254 home = tr_strdup (appdata); 255 #else 256 struct passwd * pw = getpwuid (getuid ()); 257 if (pw) 258 home = tr_strdup (pw->pw_dir); 259 endpwent (); 264 260 #endif 265 261 } 266 262 267 if( !home)268 home = tr_strdup( "");269 } 270 271 263 if (!home) 264 home = tr_strdup (""); 265 } 266 267 return home; 272 268 } 273 269 274 270 static const char * 275 getOldConfigDir ( void)276 { 277 278 279 if( !path)271 getOldConfigDir (void) 272 { 273 static char * path = NULL; 274 275 if (!path) 280 276 { 281 277 #ifdef SYS_DARWIN 282 path = tr_buildPath( getHomeDir(), "Library",283 284 "Transmission", NULL);285 #elif defined ( WIN32)286 char appdata[MAX_PATH]; /* SHGetFolderPath() requires MAX_PATH */287 SHGetFolderPath( NULL, CSIDL_APPDATA, NULL, 0, appdata);288 path = tr_buildPath( appdata, "Transmission", NULL);289 #elif defined ( __HAIKU__)290 291 find_directory( B_USER_SETTINGS_DIRECTORY, -1, true, buf, sizeof(buf));292 path = tr_buildPath( buf, "Transmission", NULL);293 #else 294 path = tr_buildPath( getHomeDir( ), ".transmission", NULL);295 #endif 296 } 297 298 299 } 300 301 #if defined (SYS_DARWIN) || defined(WIN32)278 path = tr_buildPath (getHomeDir (), "Library", 279 "Application Support", 280 "Transmission", NULL); 281 #elif defined (WIN32) 282 char appdata[MAX_PATH]; /* SHGetFolderPath () requires MAX_PATH */ 283 SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, appdata); 284 path = tr_buildPath (appdata, "Transmission", NULL); 285 #elif defined (__HAIKU__) 286 char buf[TR_PATH_MAX]; 287 find_directory (B_USER_SETTINGS_DIRECTORY, -1, true, buf, sizeof (buf)); 288 path = tr_buildPath (buf, "Transmission", NULL); 289 #else 290 path = tr_buildPath (getHomeDir (), ".transmission", NULL); 291 #endif 292 } 293 294 return path; 295 } 296 297 #if defined (SYS_DARWIN) || defined (WIN32) 302 298 #define RESUME_SUBDIR "Resume" 303 299 #define TORRENT_SUBDIR "Torrents" … … 308 304 309 305 static const char * 310 getOldTorrentsDir ( void)311 { 312 313 314 if( !path)315 path = tr_buildPath( getOldConfigDir( ), TORRENT_SUBDIR, NULL);316 317 306 getOldTorrentsDir (void) 307 { 308 static char * path = NULL; 309 310 if (!path) 311 path = tr_buildPath (getOldConfigDir (), TORRENT_SUBDIR, NULL); 312 313 return path; 318 314 } 319 315 320 316 static const char * 321 getOldCacheDir ( void)322 { 323 324 325 if( !path)326 { 327 #if defined ( WIN32)328 path = tr_buildPath( getOldConfigDir( ), "Cache", NULL);329 #elif defined ( SYS_DARWIN)330 path = tr_buildPath( getHomeDir( ), "Library", "Caches", "Transmission", NULL);331 #else 332 path = tr_buildPath( getOldConfigDir( ), "cache", NULL);333 #endif 334 } 335 336 317 getOldCacheDir (void) 318 { 319 static char * path = NULL; 320 321 if (!path) 322 { 323 #if defined (WIN32) 324 path = tr_buildPath (getOldConfigDir (), "Cache", NULL); 325 #elif defined (SYS_DARWIN) 326 path = tr_buildPath (getHomeDir (), "Library", "Caches", "Transmission", NULL); 327 #else 328 path = tr_buildPath (getOldConfigDir (), "cache", NULL); 329 #endif 330 } 331 332 return path; 337 333 } 338 334 339 335 static void 340 moveFiles( const char * oldDir, 341 const char * newDir ) 342 { 343 if( oldDir && newDir && strcmp( oldDir, newDir ) ) 344 { 345 DIR * dirh = opendir( oldDir ); 346 if( dirh ) 336 moveFiles (const char * oldDir, const char * newDir) 337 { 338 if (oldDir && newDir && strcmp (oldDir, newDir)) 339 { 340 DIR * dirh = opendir (oldDir); 341 if (dirh) 347 342 { 348 intcount = 0;349 350 while( ( dirp = readdir( dirh ) ))343 int count = 0; 344 struct dirent * dirp; 345 while ((dirp = readdir (dirh))) 351 346 { 352 353 if( name && strcmp( name, "." ) && strcmp( name, ".." ))347 const char * name = dirp->d_name; 348 if (name && strcmp (name, ".") && strcmp (name, "..")) 354 349 { 355 char * o = tr_buildPath( oldDir, name, NULL);356 char * n = tr_buildPath( newDir, name, NULL);357 rename( o, n);358 359 tr_free( n);360 tr_free( o);350 char * o = tr_buildPath (oldDir, name, NULL); 351 char * n = tr_buildPath (newDir, name, NULL); 352 rename (o, n); 353 ++count; 354 tr_free (n); 355 tr_free (o); 361 356 } 362 357 } 363 358 364 if( count)365 tr_inf( _( "Migrated %1$d files from \"%2$s\" to \"%3$s\"" ),366 count, oldDir, newDir ); 367 closedir( dirh);359 if (count) 360 tr_inf (_ ("Migrated %1$d files from \"%2$s\" to \"%3$s\""), count, oldDir, newDir); 361 362 closedir (dirh); 368 363 } 369 364 } … … 376 371 */ 377 372 static void 378 migrateFiles( const tr_session * session ) 379 { 380 static int migrated = false; 381 const bool should_migrate = strstr( getOldConfigDir(), ".transmission" ) != NULL; 382 383 if( !migrated && should_migrate ) 384 { 385 const char * oldDir; 386 const char * newDir; 387 migrated = true; 388 389 oldDir = getOldTorrentsDir( ); 390 newDir = tr_getTorrentDir( session ); 391 moveFiles( oldDir, newDir ); 392 393 oldDir = getOldCacheDir( ); 394 newDir = tr_getResumeDir( session ); 395 moveFiles( oldDir, newDir ); 373 migrateFiles (const tr_session * session) 374 { 375 static int migrated = false; 376 const bool should_migrate = strstr (getOldConfigDir (), ".transmission") != NULL; 377 378 if (!migrated && should_migrate) 379 { 380 const char * oldDir; 381 const char * newDir; 382 383 migrated = true; 384 385 oldDir = getOldTorrentsDir (); 386 newDir = tr_getTorrentDir (session); 387 moveFiles (oldDir, newDir); 388 389 oldDir = getOldCacheDir (); 390 newDir = tr_getResumeDir (session); 391 moveFiles (oldDir, newDir); 396 392 } 397 393 } 398 394 399 395 void 400 tr_setConfigDir ( tr_session * session, const char * configDir)401 { 402 403 404 session->configDir = tr_strdup( configDir);405 406 path = tr_buildPath( configDir, RESUME_SUBDIR, NULL);407 tr_mkdirp( path, 0777);408 409 410 path = tr_buildPath( configDir, TORRENT_SUBDIR, NULL);411 tr_mkdirp( path, 0777);412 413 414 migrateFiles( session);396 tr_setConfigDir (tr_session * session, const char * configDir) 397 { 398 char * path; 399 400 session->configDir = tr_strdup (configDir); 401 402 path = tr_buildPath (configDir, RESUME_SUBDIR, NULL); 403 tr_mkdirp (path, 0777); 404 session->resumeDir = path; 405 406 path = tr_buildPath (configDir, TORRENT_SUBDIR, NULL); 407 tr_mkdirp (path, 0777); 408 session->torrentDir = path; 409 410 migrateFiles (session); 415 411 } 416 412 417 413 const char * 418 tr_sessionGetConfigDir ( const tr_session * session)419 { 420 414 tr_sessionGetConfigDir (const tr_session * session) 415 { 416 return session->configDir; 421 417 } 422 418 423 419 const char * 424 tr_getTorrentDir ( const tr_session * session)425 { 426 420 tr_getTorrentDir (const tr_session * session) 421 { 422 return session->torrentDir; 427 423 } 428 424 429 425 const char * 430 tr_getResumeDir ( const tr_session * session)431 { 432 426 tr_getResumeDir (const tr_session * session) 427 { 428 return session->resumeDir; 433 429 } 434 430 435 431 const char* 436 tr_getDefaultConfigDir ( const char * appname)437 { 438 439 440 if( !appname || !*appname)441 442 443 if( !s)444 { 445 if( ( s = getenv( "TRANSMISSION_HOME" ) ))432 tr_getDefaultConfigDir (const char * appname) 433 { 434 static char * s = NULL; 435 436 if (!appname || !*appname) 437 appname = "Transmission"; 438 439 if (!s) 440 { 441 if ((s = getenv ("TRANSMISSION_HOME"))) 446 442 { 447 s = tr_strdup( s);443 s = tr_strdup (s); 448 444 } 449 445 else 450 446 { 451 447 #ifdef SYS_DARWIN 452 s = tr_buildPath( getHomeDir( ), "Library", "Application Support", 453 appname, NULL ); 454 #elif defined( WIN32 ) 455 char appdata[TR_PATH_MAX]; /* SHGetFolderPath() requires MAX_PATH */ 456 SHGetFolderPath( NULL, CSIDL_APPDATA, NULL, 0, appdata ); 457 s = tr_buildPath( appdata, appname, NULL ); 458 #elif defined( __HAIKU__ ) 459 char buf[TR_PATH_MAX]; 460 find_directory( B_USER_SETTINGS_DIRECTORY, -1, true, buf, sizeof(buf) ); 461 s = tr_buildPath( buf, appname, NULL ); 462 #else 463 if( ( s = getenv( "XDG_CONFIG_HOME" ) ) ) 464 s = tr_buildPath( s, appname, NULL ); 465 else 466 s = tr_buildPath( getHomeDir( ), ".config", appname, NULL ); 448 s = tr_buildPath (getHomeDir (), "Library", "Application Support", appname, NULL); 449 #elif defined (WIN32) 450 char appdata[TR_PATH_MAX]; /* SHGetFolderPath () requires MAX_PATH */ 451 SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, appdata); 452 s = tr_buildPath (appdata, appname, NULL); 453 #elif defined (__HAIKU__) 454 char buf[TR_PATH_MAX]; 455 find_directory (B_USER_SETTINGS_DIRECTORY, -1, true, buf, sizeof (buf)); 456 s = tr_buildPath (buf, appname, NULL); 457 #else 458 if ((s = getenv ("XDG_CONFIG_HOME"))) 459 s = tr_buildPath (s, appname, NULL); 460 else 461 s = tr_buildPath (getHomeDir (), ".config", appname, NULL); 467 462 #endif 468 463 } 469 464 } 470 465 471 466 return s; 472 467 } 473 468 474 469 const char* 475 tr_getDefaultDownloadDir ( void)476 { 477 478 479 if( user_dir == NULL)480 { 481 482 483 484 485 486 487 config_home = getenv( "XDG_CONFIG_HOME");488 if( config_home && *config_home)489 config_file = tr_buildPath( config_home, "user-dirs.dirs", NULL);490 491 config_file = tr_buildPath( getHomeDir( ), ".config", "user-dirs.dirs", NULL);492 493 494 content = (char *) tr_loadFile( config_file, &content_len);495 if( content && content_len>0)470 tr_getDefaultDownloadDir (void) 471 { 472 static char * user_dir = NULL; 473 474 if (user_dir == NULL) 475 { 476 const char * config_home; 477 char * config_file; 478 char * content; 479 size_t content_len; 480 481 /* figure out where to look for user-dirs.dirs */ 482 config_home = getenv ("XDG_CONFIG_HOME"); 483 if (config_home && *config_home) 484 config_file = tr_buildPath (config_home, "user-dirs.dirs", NULL); 485 else 486 config_file = tr_buildPath (getHomeDir (), ".config", "user-dirs.dirs", NULL); 487 488 /* read in user-dirs.dirs and look for the download dir entry */ 489 content = (char *) tr_loadFile (config_file, &content_len); 490 if (content && content_len>0) 496 491 { 497 498 char * line = strstr( content, key);499 if( line != NULL)492 const char * key = "XDG_DOWNLOAD_DIR=\""; 493 char * line = strstr (content, key); 494 if (line != NULL) 500 495 { 501 char * value = line + strlen( key);502 char * end = strchr( value, '"');503 504 if( end)496 char * value = line + strlen (key); 497 char * end = strchr (value, '"'); 498 499 if (end) 505 500 { 506 507 508 if( !memcmp( value, "$HOME/", 6 ))509 user_dir = tr_buildPath( getHomeDir( ), value+6, NULL);510 511 user_dir = tr_strdup( value);501 *end = '\0'; 502 503 if (!memcmp (value, "$HOME/", 6)) 504 user_dir = tr_buildPath (getHomeDir (), value+6, NULL); 505 else 506 user_dir = tr_strdup (value); 512 507 } 513 508 } 514 509 } 515 510 516 if( user_dir == NULL)511 if (user_dir == NULL) 517 512 #ifdef __HAIKU__ 518 user_dir = tr_buildPath( getHomeDir( ), "Desktop", NULL);519 #else 520 user_dir = tr_buildPath( getHomeDir( ), "Downloads", NULL);521 #endif 522 523 tr_free( content);524 tr_free( config_file);525 } 526 527 513 user_dir = tr_buildPath (getHomeDir (), "Desktop", NULL); 514 #else 515 user_dir = tr_buildPath (getHomeDir (), "Downloads", NULL); 516 #endif 517 518 tr_free (content); 519 tr_free (config_file); 520 } 521 522 return user_dir; 528 523 } 529 524 … … 533 528 534 529 static int 535 isWebClientDir( const char * path ) 536 { 537 struct stat sb; 538 char * tmp = tr_buildPath( path, "index.html", NULL ); 539 const int ret = !stat( tmp, &sb ); 540 tr_inf( _( "Searching for web interface file \"%s\"" ), tmp ); 541 tr_free( tmp ); 542 return ret; 530 isWebClientDir (const char * path) 531 { 532 struct stat sb; 533 char * tmp = tr_buildPath (path, "index.html", NULL); 534 const int ret = !stat (tmp, &sb); 535 tr_inf (_ ("Searching for web interface file \"%s\""), tmp); 536 tr_free (tmp); 537 538 return ret; 543 539 } 544 540 545 541 const char * 546 tr_getWebClientDir ( const tr_session * session UNUSED)547 { 548 549 550 if( !s)551 { 552 if( ( s = getenv( "CLUTCH_HOME" ) ))542 tr_getWebClientDir (const tr_session * session UNUSED) 543 { 544 static char * s = NULL; 545 546 if (!s) 547 { 548 if ((s = getenv ("CLUTCH_HOME"))) 553 549 { 554 s = tr_strdup( s);550 s = tr_strdup (s); 555 551 } 556 else if( ( s = getenv( "TRANSMISSION_WEB_HOME" ) ))552 else if ((s = getenv ("TRANSMISSION_WEB_HOME"))) 557 553 { 558 s = tr_strdup( s);554 s = tr_strdup (s); 559 555 } 560 556 else 561 557 { 562 558 563 559 #ifdef SYS_DARWIN /* on Mac, look in the Application Support folder first, then in the app bundle. */ 564 560 565 /* Look in the Application Support folder */ 566 s = tr_buildPath( tr_sessionGetConfigDir( session ), "web", NULL ); 567 568 if( !isWebClientDir( s ) ) { 569 tr_free( s ); 570 571 CFURLRef appURL = CFBundleCopyBundleURL( CFBundleGetMainBundle( ) ); 572 CFStringRef appRef = CFURLCopyFileSystemPath( appURL, 573 kCFURLPOSIXPathStyle ); 574 const CFIndex appStringLength = CFStringGetMaximumSizeOfFileSystemRepresentation(appRef); 575 576 char * appString = tr_malloc( appStringLength ); 577 const bool success = CFStringGetFileSystemRepresentation( appRef, appString, appStringLength ); 578 assert( success ); 579 580 CFRelease( appURL ); 581 CFRelease( appRef ); 582 583 /* Fallback to the app bundle */ 584 s = tr_buildPath( appString, "Contents", "Resources", "web", NULL ); 585 if( !isWebClientDir( s ) ) { 586 tr_free( s ); 587 s = NULL; 561 /* Look in the Application Support folder */ 562 s = tr_buildPath (tr_sessionGetConfigDir (session), "web", NULL); 563 564 if (!isWebClientDir (s)) 565 { 566 tr_free (s); 567 568 CFURLRef appURL = CFBundleCopyBundleURL (CFBundleGetMainBundle ()); 569 CFStringRef appRef = CFURLCopyFileSystemPath (appURL, 570 kCFURLPOSIXPathStyle); 571 const CFIndex appStringLength = CFStringGetMaximumSizeOfFileSystemRepresentation (appRef); 572 573 char * appString = tr_malloc (appStringLength); 574 const bool success = CFStringGetFileSystemRepresentation (appRef, appString, appStringLength); 575 assert (success); 576 577 CFRelease (appURL); 578 CFRelease (appRef); 579 580 /* Fallback to the app bundle */ 581 s = tr_buildPath (appString, "Contents", "Resources", "web", NULL); 582 if (!isWebClientDir (s)) 583 { 584 tr_free (s); 585 s = NULL; 588 586 } 589 587 590 tr_free( appString);588 tr_free (appString); 591 589 } 592 590 593 #elif defined( WIN32 ) 594 595 /* SHGetFolderPath explicitly requires MAX_PATH length */ 596 char dir[MAX_PATH]; 597 598 /* Generally, Web interface should be stored in a Web subdir of 599 * calling executable dir. */ 600 601 if( s == NULL ) { 602 /* First, we should check personal AppData/Transmission/Web */ 603 SHGetFolderPath( NULL, CSIDL_COMMON_APPDATA, NULL, 0, dir ); 604 s = tr_buildPath( dir, "Transmission", "Web", NULL ); 605 if( !isWebClientDir( s ) ) { 606 tr_free( s ); 607 s = NULL; 591 #elif defined (WIN32) 592 593 /* SHGetFolderPath explicitly requires MAX_PATH length */ 594 char dir[MAX_PATH]; 595 596 /* Generally, Web interface should be stored in a Web subdir of 597 * calling executable dir. */ 598 599 if (s == NULL) /* check personal AppData/Transmission/Web */ 600 { 601 SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA, NULL, 0, dir); 602 s = tr_buildPath (dir, "Transmission", "Web", NULL); 603 if (!isWebClientDir (s)) 604 { 605 tr_free (s); 606 s = NULL; 608 607 } 609 608 } 610 609 611 if( s == NULL ) { 612 /* check personal AppData */ 613 SHGetFolderPath( NULL, CSIDL_APPDATA, NULL, 0, dir ); 614 s = tr_buildPath( dir, "Transmission", "Web", NULL ); 615 if( !isWebClientDir( s ) ) { 616 tr_free( s ); 617 s = NULL; 610 if (s == NULL) /* check personal AppData */ 611 { 612 SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, dir); 613 s = tr_buildPath (dir, "Transmission", "Web", NULL); 614 if (!isWebClientDir (s)) 615 { 616 tr_free (s); 617 s = NULL; 618 618 } 619 619 } 620 620 621 if( s == NULL) { 622 /* check calling module place */ 623 GetModuleFileName( GetModuleHandle( NULL ), dir, sizeof( dir ) ); 624 s = tr_buildPath( dirname( dir ), "Web", NULL ); 625 if( !isWebClientDir( s ) ) { 626 tr_free( s ); 621 if (s == NULL) /* check calling module place */ 622 { 623 GetModuleFileName (GetModuleHandle (NULL), dir, sizeof (dir)); 624 s = tr_buildPath (dirname (dir), "Web", NULL); 625 if (!isWebClientDir (s)) 626 { 627 tr_free (s); 627 628 s = NULL; 629 } 630 } 631 632 #else /* everyone else, follow the XDG spec */ 633 634 tr_list *candidates = NULL, *l; 635 const char * tmp; 636 637 /* XDG_DATA_HOME should be the first in the list of candidates */ 638 tmp = getenv ("XDG_DATA_HOME"); 639 if (tmp && *tmp) 640 { 641 tr_list_append (&candidates, tr_strdup (tmp)); 642 } 643 else 644 { 645 char * dhome = tr_buildPath (getHomeDir (), ".local", "share", NULL); 646 tr_list_append (&candidates, dhome); 647 } 648 649 /* XDG_DATA_DIRS are the backup directories */ 650 { 651 const char * pkg = PACKAGE_DATA_DIR; 652 const char * xdg = getenv ("XDG_DATA_DIRS"); 653 const char * fallback = "/usr/local/share:/usr/share"; 654 char * buf = tr_strdup_printf ("%s:%s:%s", (pkg?pkg:""), (xdg?xdg:""), fallback); 655 tmp = buf; 656 while (tmp && *tmp) 657 { 658 const char * end = strchr (tmp, ':'); 659 if (end) 660 { 661 if ((end - tmp) > 1) 662 tr_list_append (&candidates, tr_strndup (tmp, end - tmp)); 663 tmp = end + 1; 664 } 665 else if (tmp && *tmp) 666 { 667 tr_list_append (&candidates, tr_strdup (tmp)); 668 break; 669 } 670 } 671 tr_free (buf); 672 } 673 674 /* walk through the candidates & look for a match */ 675 for (l=candidates; l; l=l->next) 676 { 677 char * path = tr_buildPath (l->data, "transmission", "web", NULL); 678 const int found = isWebClientDir (path); 679 if (found) 680 { 681 s = path; 682 break; 628 683 } 684 tr_free (path); 629 685 } 630 686 631 #else /* everyone else, follow the XDG spec */ 632 633 tr_list *candidates = NULL, *l; 634 const char * tmp; 635 636 /* XDG_DATA_HOME should be the first in the list of candidates */ 637 tmp = getenv( "XDG_DATA_HOME" ); 638 if( tmp && *tmp ) 639 tr_list_append( &candidates, tr_strdup( tmp ) ); 640 else { 641 char * dhome = tr_buildPath( getHomeDir( ), ".local", "share", NULL ); 642 tr_list_append( &candidates, dhome ); 643 } 644 645 /* XDG_DATA_DIRS are the backup directories */ 646 { 647 const char * pkg = PACKAGE_DATA_DIR; 648 const char * xdg = getenv( "XDG_DATA_DIRS" ); 649 const char * fallback = "/usr/local/share:/usr/share"; 650 char * buf = tr_strdup_printf( "%s:%s:%s", (pkg?pkg:""), (xdg?xdg:""), fallback ); 651 tmp = buf; 652 while( tmp && *tmp ) { 653 const char * end = strchr( tmp, ':' ); 654 if( end ) { 655 if( ( end - tmp ) > 1 ) 656 tr_list_append( &candidates, tr_strndup( tmp, end - tmp ) ); 657 tmp = end + 1; 658 } else if( tmp && *tmp ) { 659 tr_list_append( &candidates, tr_strdup( tmp ) ); 660 break; 661 } 662 } 663 tr_free( buf ); 664 } 665 666 /* walk through the candidates & look for a match */ 667 for( l=candidates; l; l=l->next ) { 668 char * path = tr_buildPath( l->data, "transmission", "web", NULL ); 669 const int found = isWebClientDir( path ); 670 if( found ) { 671 s = path; 672 break; 673 } 674 tr_free( path ); 675 } 676 677 tr_list_free( &candidates, tr_free ); 687 tr_list_free (&candidates, tr_free); 678 688 679 689 #endif … … 682 692 } 683 693 684 694 return s; 685 695 } 686 696 … … 690 700 691 701 int64_t 692 tr_getFreeSpace ( const char * path)693 { 694 #ifdef WIN32 695 696 return GetDiskFreeSpaceEx(path, &freeBytesAvailable, NULL, NULL)697 698 699 #elif defined (HAVE_STATVFS)700 701 return statvfs( path, &buf) ? -1 : (int64_t)buf.f_bavail * (int64_t)buf.f_frsize;702 #else 703 704 702 tr_getFreeSpace (const char * path) 703 { 704 #ifdef WIN32 705 uint64_t freeBytesAvailable = 0; 706 return GetDiskFreeSpaceEx (path, &freeBytesAvailable, NULL, NULL) 707 ? (int64_t)freeBytesAvailable 708 : -1; 709 #elif defined (HAVE_STATVFS) 710 struct statvfs buf; 711 return statvfs (path, &buf) ? -1 : (int64_t)buf.f_bavail * (int64_t)buf.f_frsize; 712 #else 713 #warning FIXME: not implemented 714 return -1; 705 715 #endif 706 716 } … … 713 723 714 724 /* The following mmap functions are by Joerg Walter, and were taken from 715 * his paper at: http://www.genesys-e.de/jwalter/mix4win.htm 716 */ 717 718 #if defined(_MSC_VER) 719 __declspec( align( 4 ) ) static LONG volatile g_sl; 720 #else 721 static LONG volatile g_sl __attribute__ ( ( aligned ( 4 ) ) ); 725 * his paper at: http://www.genesys-e.de/jwalter/mix4win.htm */ 726 727 #if defined (_MSC_VER) 728 __declspec (align (4)) static LONG volatile g_sl; 729 #else 730 static LONG volatile g_sl __attribute__ ((aligned (4))); 722 731 #endif 723 732 724 733 /* Wait for spin lock */ 725 734 static int 726 slwait ( LONG volatile *sl)727 { 728 while( InterlockedCompareExchange ( sl, 1, 0 ) != 0)729 Sleep ( 0);730 731 735 slwait (LONG volatile *sl) 736 { 737 while (InterlockedCompareExchange (sl, 1, 0) != 0) 738 Sleep (0); 739 740 return 0; 732 741 } 733 742 734 743 /* Release spin lock */ 735 744 static int 736 slrelease ( LONG volatile *sl)737 { 738 InterlockedExchange ( sl, 0);739 745 slrelease (LONG volatile *sl) 746 { 747 InterlockedExchange (sl, 0); 748 return 0; 740 749 } 741 750 742 751 /* getpagesize for windows */ 743 752 static long 744 getpagesize( void ) 745 { 746 static long g_pagesize = 0; 747 748 if( !g_pagesize ) 749 { 750 SYSTEM_INFO system_info; 751 GetSystemInfo ( &system_info ); 752 g_pagesize = system_info.dwPageSize; 753 } 754 return g_pagesize; 753 getpagesize (void) 754 { 755 static long g_pagesize = 0; 756 757 if (!g_pagesize) 758 { 759 SYSTEM_INFO system_info; 760 GetSystemInfo (&system_info); 761 g_pagesize = system_info.dwPageSize; 762 } 763 764 return g_pagesize; 755 765 } 756 766 757 767 static long 758 getregionsize( void ) 759 { 760 static long g_regionsize = 0; 761 762 if( !g_regionsize ) 763 { 764 SYSTEM_INFO system_info; 765 GetSystemInfo ( &system_info ); 766 g_regionsize = system_info.dwAllocationGranularity; 767 } 768 return g_regionsize; 768 getregionsize (void) 769 { 770 static long g_regionsize = 0; 771 772 if (!g_regionsize) 773 { 774 SYSTEM_INFO system_info; 775 GetSystemInfo (&system_info); 776 g_regionsize = system_info.dwAllocationGranularity; 777 } 778 779 return g_regionsize; 769 780 } 770 781 771 782 void * 772 mmap( void *ptr, 773 long size, 774 long prot, 775 long type, 776 long handle, 777 long arg ) 778 { 779 static long g_pagesize; 780 static long g_regionsize; 781 782 /* Wait for spin lock */ 783 slwait ( &g_sl ); 784 /* First time initialization */ 785 if( !g_pagesize ) 786 g_pagesize = getpagesize ( ); 787 if( !g_regionsize ) 788 g_regionsize = getregionsize ( ); 789 /* Allocate this */ 790 ptr = VirtualAlloc ( ptr, size, 791 MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, 792 PAGE_READWRITE ); 793 if( !ptr ) 794 { 795 ptr = (void *) -1; 796 goto mmap_exit; 797 } 783 mmap (void *ptr, long size, long prot, long type, long handle, long arg) 784 { 785 static long g_pagesize; 786 static long g_regionsize; 787 788 /* Wait for spin lock */ 789 slwait (&g_sl); 790 791 /* First time initialization */ 792 if (!g_pagesize) 793 g_pagesize = getpagesize (); 794 if (!g_regionsize) 795 g_regionsize = getregionsize (); 796 797 /* Allocate this */ 798 ptr = VirtualAlloc (ptr, size, MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE); 799 if (!ptr) 800 { 801 ptr = (void *) -1; 802 goto mmap_exit; 803 } 804 798 805 mmap_exit: 799 800 slrelease ( &g_sl);801 806 /* Release spin lock */ 807 slrelease (&g_sl); 808 return ptr; 802 809 } 803 810 804 811 long 805 munmap( void *ptr, 806 long size ) 807 { 808 static long g_pagesize; 809 static long g_regionsize; 810 int rc = -1; 811 812 /* Wait for spin lock */ 813 slwait ( &g_sl ); 814 /* First time initialization */ 815 if( !g_pagesize ) 816 g_pagesize = getpagesize ( ); 817 if( !g_regionsize ) 818 g_regionsize = getregionsize ( ); 819 /* Free this */ 820 if( !VirtualFree ( ptr, 0, 821 MEM_RELEASE ) ) 822 goto munmap_exit; 823 rc = 0; 812 munmap (void *ptr, long size) 813 { 814 static long g_pagesize; 815 static long g_regionsize; 816 int rc = -1; 817 818 /* Wait for spin lock */ 819 slwait (&g_sl); 820 821 /* First time initialization */ 822 if (!g_pagesize) 823 g_pagesize = getpagesize (); 824 if (!g_regionsize) 825 g_regionsize = getregionsize (); 826 827 /* Free this */ 828 if (!VirtualFree (ptr, 0, MEM_RELEASE)) 829 goto munmap_exit; 830 831 rc = 0; 832 824 833 munmap_exit: 825 826 slrelease ( &g_sl);827 828 } 829 830 #endif 834 /* Release spin lock */ 835 slrelease (&g_sl); 836 return rc; 837 } 838 839 #endif
Note: See TracChangeset
for help on using the changeset viewer.