1/* 2 * This file Copyright (C) Mnemosyne LLC 3 * 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) 6 * so that the bulk of its code can remain under the MIT license. 7 * This exemption does not extend to derived works not owned by 8 * the Transmission project. 9 * 10 * $Id: utils.h 13577 2012-10-16 03:13:05Z jordan $ 11 */ 12 13#ifndef TR_UTILS_H 14#define TR_UTILS_H 1 15 16#include <inttypes.h> 17#include <stddef.h> /* size_t */ 18#include <time.h> /* time_t */ 19 20#ifdef __cplusplus 21extern "C" { 22#endif 23 24/*** 25**** 26***/ 27 28/** 29 * @addtogroup utils Utilities 30 * @{ 31 */ 32 33#ifndef UNUSED 34 #ifdef __GNUC__ 35 #define UNUSED __attribute__ ( ( unused ) ) 36 #else 37 #define UNUSED 38 #endif 39#endif 40 41#ifndef TR_GNUC_PRINTF 42 #ifdef __GNUC__ 43 #define TR_GNUC_PRINTF( fmt, args ) __attribute__ ( ( format ( printf, fmt, args ) ) ) 44 #else 45 #define TR_GNUC_PRINTF( fmt, args ) 46 #endif 47#endif 48 49#ifndef TR_GNUC_NONNULL 50 #ifdef __GNUC__ 51 #define TR_GNUC_NONNULL( ... ) __attribute__((nonnull (__VA_ARGS__))) 52 #else 53 #define TR_GNUC_NONNULL( ... ) 54 #endif 55#endif 56 57#ifndef TR_GNUC_NULL_TERMINATED 58 #if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 3 ) 59 #define TR_GNUC_NULL_TERMINATED __attribute__ ( ( __sentinel__ ) ) 60 #define TR_GNUC_HOT __attribute ( ( hot ) ) 61 #else 62 #define TR_GNUC_NULL_TERMINATED 63 #define TR_GNUC_HOT 64 #endif 65#endif 66 67#if __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 96 ) 68 #define TR_GNUC_MALLOC __attribute__ ( ( __malloc__ ) ) 69#else 70 #define TR_GNUC_MALLOC 71#endif 72 73 74/*** 75**** 76***/ 77 78const char * tr_strip_positional_args( const char * fmt ); 79 80#if !defined( _ ) 81 #if defined( HAVE_LIBINTL_H ) && !defined( SYS_DARWIN ) 82 #include <libintl.h> 83 #define _( a ) gettext ( a ) 84 #else 85 #define _( a ) ( a ) 86 #endif 87#endif 88 89/* #define DISABLE_GETTEXT */ 90#ifndef DISABLE_GETTEXT 91 #if defined(WIN32) || defined(TR_LIGHTWEIGHT) 92 #define DISABLE_GETTEXT 93 #endif 94#endif 95#ifdef DISABLE_GETTEXT 96 #undef _ 97 #define _( a ) tr_strip_positional_args( a ) 98#endif 99 100/**** 101***** 102****/ 103 104#define TR_MAX_MSG_LOG 10000 105 106extern tr_msg_level __tr_message_level; 107 108static inline tr_msg_level tr_getMessageLevel( void ) 109{ 110 return __tr_message_level; 111} 112 113static inline bool tr_msgLoggingIsActive( tr_msg_level level ) 114{ 115 return tr_getMessageLevel() >= level; 116} 117 118void tr_msg( const char * file, int line, 119 tr_msg_level level, 120 const char * torrent, 121 const char * fmt, ... ) TR_GNUC_PRINTF( 5, 6 ); 122 123#define tr_nerr( n, ... ) \ 124 do { \ 125 if( tr_msgLoggingIsActive( TR_MSG_ERR ) ) \ 126 tr_msg( __FILE__, __LINE__, TR_MSG_ERR, n, __VA_ARGS__ ); \ 127 } while( 0 ) 128 129#define tr_ninf( n, ... ) \ 130 do { \ 131 if( tr_msgLoggingIsActive( TR_MSG_INF) ) \ 132 tr_msg( __FILE__, __LINE__, TR_MSG_INF, n, __VA_ARGS__ ); \ 133 } while( 0 ) 134 135#define tr_ndbg( n, ... ) \ 136 do { \ 137 if( tr_msgLoggingIsActive( TR_MSG_DBG) ) \ 138 tr_msg( __FILE__, __LINE__, TR_MSG_DBG, n, __VA_ARGS__ ); \ 139 } while( 0 ) 140 141#define tr_torerr( tor, ... ) \ 142 do { \ 143 if( tr_msgLoggingIsActive( TR_MSG_ERR ) ) \ 144 tr_msg( __FILE__, __LINE__, TR_MSG_ERR, tr_torrentName( tor ), __VA_ARGS__ ); \ 145 } while( 0 ) 146 147#define tr_torinf( tor, ... ) \ 148 do { \ 149 if( tr_msgLoggingIsActive( TR_MSG_INF ) ) \ 150 tr_msg( __FILE__, __LINE__, TR_MSG_INF, tr_torrentName( tor ), __VA_ARGS__ ); \ 151 } while( 0 ) 152 153#define tr_tordbg( tor, ... ) \ 154 do { \ 155 if( tr_msgLoggingIsActive( TR_MSG_DBG ) ) \ 156 tr_msg( __FILE__, __LINE__, TR_MSG_DBG, tr_torrentName( tor ), __VA_ARGS__ ); \ 157 } while( 0 ) 158 159#define tr_err( ... ) \ 160 do { \ 161 if( tr_msgLoggingIsActive( TR_MSG_ERR ) ) \ 162 tr_msg( __FILE__, __LINE__, TR_MSG_ERR, NULL, __VA_ARGS__ ); \ 163 } while( 0 ) 164 165#define tr_inf( ... ) \ 166 do { \ 167 if( tr_msgLoggingIsActive( TR_MSG_INF ) ) \ 168 tr_msg( __FILE__, __LINE__, TR_MSG_INF, NULL, __VA_ARGS__ ); \ 169 } while( 0 ) 170 171#define tr_dbg( ... ) \ 172 do { \ 173 if( tr_msgLoggingIsActive( TR_MSG_DBG ) ) \ 174 tr_msg( __FILE__, __LINE__, TR_MSG_DBG, NULL, __VA_ARGS__ ); \ 175 } while( 0 ) 176 177 178 179void* tr_getLog( void ); 180 181/** @brief return true if deep logging has been enabled by the user; false otherwise */ 182bool tr_deepLoggingIsActive( void ); 183 184void tr_deepLog( const char * file, 185 int line, 186 const char * name, 187 const char * fmt, 188 ... ) TR_GNUC_PRINTF( 4, 5 ) TR_GNUC_NONNULL(1,4); 189 190/** @brief set the buffer with the current time formatted for deep logging. */ 191char* tr_getLogTimeStr( char * buf, int buflen ) TR_GNUC_NONNULL(1); 192 193 194/** 195 * @brief Rich Salz's classic implementation of shell-style pattern matching for ?, \, [], and * characters. 196 * @return 1 if the pattern matches, 0 if it doesn't, or -1 if an error occured 197 */ 198bool tr_wildmat( const char * text, const char * pattern ) TR_GNUC_NONNULL(1,2); 199 200/** @brief Portability wrapper for basename() that uses the system implementation if available */ 201char* tr_basename( const char * path ) TR_GNUC_MALLOC; 202 203/** @brief Portability wrapper for dirname() that uses the system implementation if available */ 204char* tr_dirname( const char * path ) TR_GNUC_MALLOC; 205 206/** 207 * Like mkdir, but makes parent directories as needed. 208 * 209 * @return zero on success, or -1 if an error occurred 210 * (in which case errno is set appropriately). 211 */ 212int tr_mkdirp( const char * path, int permissions ) TR_GNUC_NONNULL(1); 213 214/** @brief Portability wrapper for mkdtemp() that uses the system implementation if available */ 215char* tr_mkdtemp( char * _template ); 216 217 218/** 219 * @brief Loads a file and returns its contents. 220 * On failure, NULL is returned and errno is set. 221 */ 222uint8_t* tr_loadFile( const char * filename, size_t * size ) TR_GNUC_MALLOC 223 TR_GNUC_NONNULL(1); 224 225 226/** @brief build a filename from a series of elements using the 227 platform's correct directory separator. */ 228char* tr_buildPath( const char * first_element, ... ) TR_GNUC_NULL_TERMINATED 229 TR_GNUC_MALLOC; 230 231bool tr_fileExists( const char * filename, time_t * mtime ); 232 233 234struct event; 235 236/** 237 * @brief Convenience wrapper around timer_add() to have a timer wake up in a number of seconds and microseconds 238 * @param timer 239 * @param seconds 240 * @param microseconds 241 */ 242void tr_timerAdd( struct event * timer, int seconds, int microseconds ) TR_GNUC_NONNULL(1); 243 244/** 245 * @brief Convenience wrapper around timer_add() to have a timer wake up in a number of milliseconds 246 * @param timer 247 * @param milliseconds 248 */ 249void tr_timerAddMsec( struct event * timer, int milliseconds ) TR_GNUC_NONNULL(1); 250 251 252/** @brief return the current date in milliseconds */ 253uint64_t tr_time_msec( void ); 254 255/** @brief sleep the specified number of milliseconds */ 256void tr_wait_msec( long int delay_milliseconds ); 257 258/** 259 * @brief make a copy of 'str' whose non-utf8 content has been corrected or stripped 260 * @return a newly-allocated string that must be freed with tr_free() 261 * @param str the string to make a clean copy of 262 * @param len the length of the string to copy. If -1, the entire string is used. 263 */ 264char* tr_utf8clean( const char * str, int len ) TR_GNUC_MALLOC; 265 266 267/*** 268**** 269***/ 270 271/* Sometimes the system defines MAX/MIN, sometimes not. 272 In the latter case, define those here since we will use them */ 273#ifndef MAX 274 #define MAX( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) ) 275#endif 276#ifndef MIN 277 #define MIN( a, b ) ( ( a ) > ( b ) ? ( b ) : ( a ) ) 278#endif 279 280/*** 281**** 282***/ 283 284/** @brief Portability wrapper around malloc() in which `0' is a safe argument */ 285void* tr_malloc( size_t size ); 286 287/** @brief Portability wrapper around calloc() in which `0' is a safe argument */ 288void* tr_malloc0( size_t size ); 289 290/** @brief Portability wrapper around free() in which `NULL' is a safe argument */ 291void tr_free( void * p ); 292 293/** 294 * @brief make a newly-allocated copy of a chunk of memory 295 * @param src the memory to copy 296 * @param byteCount the number of bytes to copy 297 * @return a newly-allocated copy of `src' that can be freed with tr_free() 298 */ 299void* tr_memdup( const void * src, size_t byteCount ); 300 301#define tr_new( struct_type, n_structs ) \ 302 ( (struct_type *) tr_malloc ( sizeof ( struct_type ) * ( ( size_t) ( n_structs ) ) ) ) 303 304#define tr_new0( struct_type, n_structs ) \ 305 ( (struct_type *) tr_malloc0 ( sizeof ( struct_type ) * ( ( size_t) ( n_structs ) ) ) ) 306 307#define tr_renew( struct_type, mem, n_structs ) \ 308 ( (struct_type *) realloc ( ( mem ), sizeof ( struct_type ) * ( ( size_t) ( n_structs ) ) ) ) 309 310void* tr_valloc( size_t bufLen ); 311 312/** 313 * @brief make a newly-allocated copy of a substring 314 * @param in is a void* so that callers can pass in both signed & unsigned without a cast 315 * @param len length of the substring to copy. if a length less than zero is passed in, strlen( len ) is used 316 * @return a newly-allocated copy of `in' that can be freed with tr_free() 317 */ 318char* tr_strndup( const void * in, int len ) TR_GNUC_MALLOC; 319 320/** 321 * @brief make a newly-allocated copy of a string 322 * @param in is a void* so that callers can pass in both signed & unsigned without a cast 323 * @return a newly-allocated copy of `in' that can be freed with tr_free() 324 */ 325char* tr_strdup( const void * in ); 326 327/** 328 * @brief like strcmp() but gracefully handles NULL strings 329 */ 330int tr_strcmp0( const char * str1, const char * str2 ); 331 332 333 334struct evbuffer; 335 336char* evbuffer_free_to_str( struct evbuffer * buf ); 337 338/** @brief similar to bsearch() but returns the index of the lower bound */ 339int tr_lowerBound( const void * key, 340 const void * base, 341 size_t nmemb, 342 size_t size, 343 int (* compar)(const void* key, const void* arrayMember), 344 bool * exact_match ) TR_GNUC_HOT TR_GNUC_NONNULL(1,5,6); 345 346 347/** 348 * @brief sprintf() a string into a newly-allocated buffer large enough to hold it 349 * @return a newly-allocated string that can be freed with tr_free() 350 */ 351char* tr_strdup_printf( const char * fmt, ... ) TR_GNUC_PRINTF( 1, 2 ) 352 TR_GNUC_MALLOC; 353 354/** 355 * @brief Translate a block of bytes into base64 356 * @return a newly-allocated string that can be freed with tr_free() 357 */ 358char* tr_base64_encode( const void * input, 359 int inlen, 360 int * outlen ) TR_GNUC_MALLOC; 361 362/** 363 * @brief Translate a block of bytes from base64 into raw form 364 * @return a newly-allocated string that can be freed with tr_free() 365 */ 366char* tr_base64_decode( const void * input, 367 int inlen, 368 int * outlen ) TR_GNUC_MALLOC; 369 370/** @brief Portability wrapper for strlcpy() that uses the system implementation if available */ 371size_t tr_strlcpy( char * dst, const void * src, size_t siz ); 372 373/** @brief Portability wrapper for snprintf() that uses the system implementation if available */ 374int tr_snprintf( char * buf, size_t buflen, 375 const char * fmt, ... ) TR_GNUC_PRINTF( 3, 4 ) TR_GNUC_NONNULL(1,3); 376 377/** @brief Convenience wrapper around strerorr() guaranteed to not return NULL 378 @param errno */ 379const char* tr_strerror( int ); 380 381/** @brief strips leading and trailing whitspace from a string 382 @return the stripped string */ 383char* tr_strstrip( char * str ); 384 385/** @brief Returns true if the string ends with the specified case-insensitive suffix */ 386bool tr_str_has_suffix( const char *str, const char *suffix ); 387 388 389/** @brief Portability wrapper for memmem() that uses the system implementation if available */ 390const char* tr_memmem( const char * haystack, size_t haystack_len, 391 const char * needle, size_t needle_len ); 392 393/** @brief Portability wrapper for strsep() that uses the system implementation if available */ 394char* tr_strsep( char ** str, const char * delim ); 395 396/*** 397**** 398***/ 399 400int compareInt( const void * va, const void * vb ); 401 402void tr_sha1_to_hex( char * out, const uint8_t * sha1 ) TR_GNUC_NONNULL(1,2); 403 404void tr_hex_to_sha1( uint8_t * out, const char * hex ) TR_GNUC_NONNULL(1,2); 405 406/** @brief convenience function to determine if an address is an IP address (IPv4 or IPv6) */ 407bool tr_addressIsIP( const char * address ); 408 409/** @brief return true if the url is a http or https url that Transmission understands */ 410bool tr_urlIsValidTracker( const char * url ) TR_GNUC_NONNULL(1); 411 412/** @brief return true if the url is a [ http, https, ftp, ftps ] url that Transmission understands */ 413bool tr_urlIsValid( const char * url, int url_len ) TR_GNUC_NONNULL(1); 414 415/** @brief parse a URL into its component parts 416 @return zero on success or an error number if an error occurred */ 417int tr_urlParse( const char * url, 418 int url_len, 419 char ** setme_scheme, 420 char ** setme_host, 421 int * setme_port, 422 char ** setme_path ) TR_GNUC_NONNULL(1); 423 424 425/** @brief return TR_RATIO_NA, TR_RATIO_INF, or a number in [0..1] 426 @return TR_RATIO_NA, TR_RATIO_INF, or a number in [0..1] */ 427double tr_getRatio( uint64_t numerator, uint64_t denominator ); 428 429/** 430 * @brief Given a string like "1-4" or "1-4,6,9,14-51", this returns a 431 * newly-allocated array of all the integers in the set. 432 * @return a newly-allocated array of integers that must be freed with tr_free(), 433 * or NULL if a fragment of the string can't be parsed. 434 * 435 * For example, "5-8" will return [ 5, 6, 7, 8 ] and setmeCount will be 4. 436 */ 437int* tr_parseNumberRange( const char * str, 438 int str_len, 439 int * setmeCount ) TR_GNUC_MALLOC TR_GNUC_NONNULL(1); 440 441 442/** 443 * @brief truncate a double value at a given number of decimal places. 444 * 445 * this can be used to prevent a printf() call from rounding up: 446 * call with the decimal_places argument equal to the number of 447 * decimal places in the printf()'s precision: 448 * 449 * - printf("%.2f%%", 99.999 ) ==> "100.00%" 450 * 451 * - printf("%.2f%%", tr_truncd(99.999, 2)) ==> "99.99%" 452 * ^ ^ 453 * | These should match | 454 * +------------------------+ 455 */ 456double tr_truncd( double x, int decimal_places ); 457 458/* return a percent formatted string of either x.xx, xx.x or xxx */ 459char* tr_strpercent( char * buf, double x, size_t buflen ); 460 461/** 462 * @param buf the buffer to write the string to 463 * @param buflef buf's size 464 * @param ratio the ratio to convert to a string 465 * @param the string represntation of "infinity" 466 */ 467char* tr_strratio( char * buf, size_t buflen, double ratio, const char * infinity ) TR_GNUC_NONNULL(1,4); 468 469/** @brief Portability wrapper for localtime_r() that uses the system implementation if available */ 470struct tm * tr_localtime_r( const time_t *_clock, struct tm *_result ); 471 472 473/** 474 * @brief move a file 475 * @return 0 on success; otherwise, return -1 and set errno 476 */ 477int tr_moveFile( const char * oldpath, const char * newpath, 478 bool * renamed ) TR_GNUC_NONNULL(1,2); 479 480/** @brief Test to see if the two filenames point to the same file. */ 481bool tr_is_same_file( const char * filename1, const char * filename2 ); 482 483/** @brief convenience function to remove an item from an array */ 484void tr_removeElementFromArray( void * array, 485 unsigned int index_to_remove, 486 size_t sizeof_element, 487 size_t nmemb ); 488 489/*** 490**** 491***/ 492 493/** @brief Private libtransmission variable that's visible only for inlining in tr_time() */ 494extern time_t __tr_current_time; 495 496/** 497 * @brief very inexpensive form of time(NULL) 498 * @return the current epoch time in seconds 499 * 500 * This function returns a second counter that is updated once per second. 501 * If something blocks the libtransmission thread for more than a second, 502 * that counter may be thrown off, so this function is not guaranteed 503 * to always be accurate. However, it is *much* faster when 100% accuracy 504 * isn't needed 505 */ 506static inline time_t tr_time( void ) { return __tr_current_time; } 507 508/** @brief Private libtransmission function to update tr_time()'s counter */ 509static inline void tr_timeUpdate( time_t now ) { __tr_current_time = now; } 510 511#ifdef WIN32 512 #include <windef.h> /* MAX_PATH */ 513 #define TR_PATH_MAX (MAX_PATH + 1) 514#else 515 #include <limits.h> /* PATH_MAX */ 516 #ifdef PATH_MAX 517 #define TR_PATH_MAX PATH_MAX 518 #else 519 #define TR_PATH_MAX 4096 520 #endif 521#endif 522 523/** @brief Portability wrapper for realpath() that uses the system implementation if available. 524 @param resolved_path should be TR_PATH_MAX or larger */ 525char* tr_realpath( const char *path, char * resolved_path ); 526 527/** @brief Portability wrapper for htonll() that uses the system implementation if available */ 528uint64_t tr_htonll( uint64_t ); 529 530/** @brief Portability wrapper for htonll() that uses the system implementation if available */ 531uint64_t tr_ntohll( uint64_t ); 532 533/*** 534**** 535***/ 536 537/* example: tr_formatter_size_init( 1024, _("KiB"), _("MiB"), _("GiB"), _("TiB") ); */ 538 539void tr_formatter_size_init( unsigned int kilo, const char * kb, const char * mb, 540 const char * gb, const char * tb ); 541 542void tr_formatter_speed_init( unsigned int kilo, const char * kb, const char * mb, 543 const char * gb, const char * tb ); 544 545void tr_formatter_mem_init( unsigned int kilo, const char * kb, const char * mb, 546 const char * gb, const char * tb ); 547 548extern unsigned int tr_speed_K; 549extern unsigned int tr_mem_K; 550extern unsigned int tr_size_K; 551 552/* format a speed from KBps into a user-readable string. */ 553char* tr_formatter_speed_KBps( char * buf, double KBps, size_t buflen ); 554 555/* format a memory size from bytes into a user-readable string. */ 556char* tr_formatter_mem_B( char * buf, int64_t bytes, size_t buflen ); 557 558/* format a memory size from MB into a user-readable string. */ 559static inline char* tr_formatter_mem_MB( char * buf, double MBps, size_t buflen ) { return tr_formatter_mem_B( buf, MBps * tr_mem_K * tr_mem_K, buflen ); } 560 561/* format a file size from bytes into a user-readable string. */ 562char* tr_formatter_size_B( char * buf, int64_t bytes, size_t buflen ); 563 564void tr_formatter_get_units( struct tr_benc * dict ); 565 566/*** 567**** 568***/ 569 570#ifdef __cplusplus 571} 572#endif 573 574/** @} */ 575 576#endif 577