From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/lib/direct/util.c | 519 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 519 insertions(+) create mode 100755 Source/DirectFB/lib/direct/util.c (limited to 'Source/DirectFB/lib/direct/util.c') diff --git a/Source/DirectFB/lib/direct/util.c b/Source/DirectFB/lib/direct/util.c new file mode 100755 index 0000000..9e7a03a --- /dev/null +++ b/Source/DirectFB/lib/direct/util.c @@ -0,0 +1,519 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef CLOCK_MONOTONIC +#include +#endif + +static int no_monotonic_pthread_clock; + +/* + * translates errno to DirectResult + */ +DirectResult +errno2result( int erno ) +{ + switch (erno) { + case 0: + return DR_OK; + case ENOENT: + return DR_FILENOTFOUND; + case EACCES: + case EPERM: + return DR_ACCESSDENIED; + case EBUSY: + case EAGAIN: + return DR_BUSY; + case ECONNREFUSED: + return DR_ACCESSDENIED; + case ENODEV: + case ENXIO: +#ifdef ENOTSUP + /* ENOTSUP is not defined on NetBSD */ + case ENOTSUP: +#endif + return DR_UNSUPPORTED; + } + + return DR_FAILURE; +} + +const char * +DirectResultString( DirectResult result ) +{ + if (!D_RESULT_TYPE_IS( result, 0, 0, 0 )) + return "UNKNOWN RESULT CODE TYPE!"; + + switch (result) { + case DR_OK: + return "OK"; + case DR_FAILURE: + return "General failure!"; + case DR_INIT: + return "Initialization error!"; + case DR_BUG: + return "Internal bug!"; + case DR_DEAD: + return "Interface was released!"; + case DR_UNSUPPORTED: + return "Not supported!"; + case DR_UNIMPLEMENTED: + return "Not implemented!"; + case DR_ACCESSDENIED: + return "Access denied!"; + case DR_INVARG: + return "Invalid argument!"; + case DR_NOLOCALMEMORY: + return "Out of memory!"; + case DR_LOCKED: + return "Resource is locked!"; + case DR_BUFFEREMPTY: + return "Buffer is empty!"; + case DR_FILENOTFOUND: + return "File not found!"; + case DR_IO: + return "General I/O error!"; + case DR_NOIMPL: + return "No (suitable) implementation found!"; + case DR_TIMEOUT: + return "Operation timed out!"; + case DR_BUSY: + return "Resource is busy!"; + case DR_THIZNULL: + return "'thiz' argument is NULL!"; + case DR_IDNOTFOUND: + return "Requested ID not found!"; + case DR_INVAREA: + return "Invalid area present!"; + case DR_DESTROYED: + return "Resource was destroyed!"; + case DR_FUSION: + return "Fusion IPC error detected!"; + case DR_BUFFERTOOLARGE: + return "Buffer is too large!"; + case DR_INTERRUPTED: + return "Operation has been interrupted!"; + case DR_NOCONTEXT: + return "No context available!"; + case DR_TEMPUNAVAIL: + return "Resource temporarily unavailable!"; + case DR_LIMITEXCEEDED: + return "Limit has been exceeded!"; + case DR_NOSUCHMETHOD: + return "No such (remote) method!"; + case DR_NOSUCHINSTANCE: + return "No such (remote) instance!"; + case DR_ITEMNOTFOUND: + return "Appropriate item not found!"; + case DR_VERSIONMISMATCH: + return "Some versions didn't match!"; + case DR_NOSHAREDMEMORY: + return "Out of shared memory!"; + case DR_EOF: + return "End of file!"; + case DR_SUSPENDED: + return "Object is suspended!"; + case DR_INCOMPLETE: + return "Operation incomplete!"; + case DR_NOCORE: + return "No core (loaded)!"; + default: + break; + } + + return "UNKNOWN RESULT CODE!"; +} + +int +direct_safe_dup( int fd ) +{ + int n = 0; + int fc[3]; + + while (fd >= 0 && fd <= 2) { + fc[n++] = fd; + fd = dup (fd); + } + + while (n) + close (fc[--n]); + + return fd; +} + +int +direct_try_open( const char *name1, const char *name2, int flags, bool error_msg ) +{ + int fd; + + fd = open (name1, flags); + if (fd >= 0) + return direct_safe_dup (fd); + + if (errno != ENOENT) { + if (error_msg) + D_PERROR( "Direct/Util: opening '%s' failed\n", name1 ); + return -1; + } + + fd = open (name2, flags); + if (fd >= 0) + return direct_safe_dup (fd); + + if (error_msg) { + if (errno == ENOENT) + D_PERROR( "Direct/Util: opening '%s' and '%s' failed\n", name1, name2 ); + else + D_PERROR( "Direct/Util: opening '%s' failed\n", name2 ); + } + + return -1; +} + +void +direct_trim( char **s ) +{ + int i; + int len = strlen( *s ); + + for (i = len-1; i >= 0; i--) + if ((*s)[i] <= ' ') + (*s)[i] = 0; + else + break; + + while (**s) + if (**s <= ' ') + (*s)++; + else + return; +} + +/* + * Utility function to initialize recursive mutexes. + */ +int +direct_util_recursive_pthread_mutex_init( pthread_mutex_t *mutex ) +{ + int ret; + pthread_mutexattr_t attr; + + pthread_mutexattr_init( &attr ); +#if HAVE_DECL_PTHREAD_MUTEX_RECURSIVE + pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE ); +#endif + ret = pthread_mutex_init( mutex, &attr ); + if (ret) + D_PERROR( "Direct/Lock: Could not initialize recursive mutex!\n" ); + + pthread_mutexattr_destroy( &attr ); + + return ret; +} + +/* + * Utility function to initialize monotonic condition. + */ +int +direct_util_monotonic_pthread_cond_init( pthread_cond_t *cond ) +{ +#if defined(CLOCK_MONOTONIC) && !defined(DIRECT_BUILD_NO_PTHREAD_CONDATTR) + int ret; + pthread_condattr_t attr; + + struct timespec dummy; + pthread_condattr_init( &attr ); + + if(!no_monotonic_pthread_clock) { + if((syscall( __NR_clock_getres, CLOCK_MONOTONIC, &dummy ) == 0) && + (pthread_condattr_setclock( &attr, CLOCK_MONOTONIC ) == 0)) + ; + else + no_monotonic_pthread_clock = 1; + } + + ret = pthread_cond_init( cond, &attr ); + if (ret) + D_PERROR( "Direct/Lock: Could not initialize monotonic condition!\n" ); + + pthread_condattr_destroy( &attr ); + + return ret; +#else + pthread_cond_init( cond, NULL ); + + return 0; +#endif +} + +/* + * Utility function to calibrate timeout for monotonic condition. + */ +void +direct_util_get_monotonic_pthread_timeout( struct timespec *timeout, + int seconds, + int nano_seconds ) +{ + struct timeval now; + + if(no_monotonic_pthread_clock) + gettimeofday( &now, NULL ); + else + direct_monotonic_gettimeofday( &now ); + + timeout->tv_sec = now.tv_sec + seconds; + timeout->tv_nsec = (now.tv_usec * 1000) + nano_seconds; + + timeout->tv_sec += timeout->tv_nsec / 1000000000; + timeout->tv_nsec %= 1000000000; +} + +/* + * Encode/Decode Base-64. + */ +char* +direct_base64_encode( const void *data, int size ) +{ + static const char *enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/="; + const unsigned char *src = (const unsigned char*)data; + char *ret; + char *buf; + + D_ASSERT( data != NULL ); + + buf = ret = D_MALLOC( (size + 2) / 3 * 4 + 1 ); + if (!ret) + return NULL; + + for (; size >= 3; size -= 3) { + buf[0] = enc[((src[0] & 0xfc) >> 2)]; + buf[1] = enc[((src[0] & 0x03) << 4) | ((src[1] & 0xf0) >> 4)]; + buf[2] = enc[((src[1] & 0x0f) << 2) | ((src[2] & 0xc0) >> 6)]; + buf[3] = enc[((src[2] & 0x3f))]; + buf += 4; + src += 3; + } + + if (size > 0) { + buf[0] = enc[(src[0] & 0xfc) >> 2]; + + if (size > 1) { + buf[1] = enc[((src[0] & 0x03) << 4) | ((src[1] & 0xf0) >> 4)]; + buf[2] = enc[((src[1] & 0x0f) << 2)]; + } else { + buf[1] = enc[(src[0] & 0x03) << 4]; + buf[2] = '='; + } + + buf[3] = '='; + buf += 4; + } + + *buf = '\0'; + + return ret; +} + +void* +direct_base64_decode( const char *string, int *ret_size ) +{ + unsigned char dec[256]; + unsigned char *ret; + unsigned char *buf; + int len; + int i, j; + + D_ASSERT( string != NULL ); + + len = strlen( string ); + buf = ret = D_MALLOC( len * 3 / 4 + 3 ); + if (!ret) + return NULL; + + /* generate decode table */ + for (i = 0; i < 255; i++) + dec[i] = 0x80; + for (i = 'A'; i <= 'Z'; i++) + dec[i] = 0 + (i - 'A'); + for (i = 'a'; i <= 'z'; i++) + dec[i] = 26 + (i - 'a'); + for (i = '0'; i <= '9'; i++) + dec[i] = 52 + (i - '0'); + dec['+'] = 62; + dec['/'] = 63; + dec['='] = 0; + + /* decode */ + for (j = 0; j < len; j += 4) { + unsigned char a[4], b[4]; + + for (i = 0; i < 4; i++) { + int c = string[i+j]; + a[i] = c; + b[i] = dec[c]; + } + + *buf++ = (b[0] << 2) | (b[1] >> 4); + *buf++ = (b[1] << 4) | (b[2] >> 2); + *buf++ = (b[2] << 6) | (b[3] ); + if (a[2] == '=' || a[3] == '=') + break; + } + + *buf = '\0'; + + if (ret_size) + *ret_size = buf - ret; + + return ret; +} + +/* + * Compute MD5 sum. + */ +static const u8 S[4][4] = { + { 7, 12, 17, 22 }, /* Round 1 */ + { 5, 9, 14, 20 }, /* Round 2 */ + { 4, 11, 16, 23 }, /* Round 3 */ + { 6, 10, 15, 21 } /* Round 4 */ +}; + +static const u32 T[64] = { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, /* Round 1 */ + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, /* Round 2 */ + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, /* Round 3 */ + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, /* Round 4 */ + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, +}; + +static void +md5_hash( u32 ABCD[4], u32 X[16] ) +{ + u32 a = ABCD[3]; + u32 b = ABCD[2]; + u32 c = ABCD[1]; + u32 d = ABCD[0]; + int t; + int i; + +#ifdef WORDS_BIGENDIAN + for (i = 0; i < 16; i++) + X[i] = BSWAP32(X[i]); +#endif + + for (i = 0; i < 64; i++) { + t = S[i>>4][i&3]; + a += T[i]; + switch (i>>4) { + case 0: a += (d ^ (b&(c^d))) + X[ i &15]; break; + case 1: a += (c ^ (d&(c^b))) + X[(1+5*i)&15]; break; + case 2: a += (b^c^d) + X[(5+3*i)&15]; break; + case 3: a += (c^(b|~d)) + X[( 7*i)&15]; break; + } + a = b + ((a << t) | (a >> (32 - t))); + t = d; d = c; c = b; b = a; a = t; + } + + ABCD[0] += d; + ABCD[1] += c; + ABCD[2] += b; + ABCD[3] += a; +} + +void +direct_md5_sum( void *dst, const void *src, const int len ) +{ + u8 block[64]; + u32 ABCD[4]; + int i, j; + + D_ASSERT( dst != NULL ); + D_ASSERT( src != NULL ); + + ABCD[0] = 0x10325476; + ABCD[1] = 0x98badcfe; + ABCD[2] = 0xefcdab89; + ABCD[3] = 0x67452301; + + for (i = 0, j = 0; i < len; i++) { + block[j++] = ((const u8*)src)[i]; + if (j == 64) { + md5_hash( ABCD, (u32*)block ); + j = 0; + } + } + + block[j++] = 0x80; + memset( &block[j], 0, 64-j ); + + if (j > 56) { + md5_hash( ABCD, (u32*)block ); + memset( block, 0, 64 ); + } + + for (i = 0; i < 8; i++) + block[56+i] = ((u64)len << 3) >> (i << 3); + + md5_hash( ABCD, (u32*)block ); + + for (i = 0; i < 4; i++) +#ifdef WORDS_BIGENDIAN + ((u32*)dst)[i] = BSWAP32(ABCD[3-i]); +#else + ((u32*)dst)[i] = ABCD[3-i]; +#endif +} -- cgit