summaryrefslogtreecommitdiff
path: root/Source/DirectFB/lib/direct/util.c
diff options
context:
space:
mode:
authorBenjamin Franzke <benjaminfranzke@googlemail.com>2013-01-15 08:46:13 +0100
committerBenjamin Franzke <benjaminfranzke@googlemail.com>2013-01-15 08:46:13 +0100
commit7fe60435bce6595a9c58a9bfd8244d74b5320e96 (patch)
tree1ac714a916e02fc90901ddac8bc2a3c6d051d28c /Source/DirectFB/lib/direct/util.c
downloaddirectfb-voodoo-7fe60435bce6595a9c58a9bfd8244d74b5320e96.tar.gz
directfb-voodoo-7fe60435bce6595a9c58a9bfd8244d74b5320e96.tar.bz2
directfb-voodoo-7fe60435bce6595a9c58a9bfd8244d74b5320e96.zip
Import DirectFB141_2k11R3_beta5
Diffstat (limited to 'Source/DirectFB/lib/direct/util.c')
-rwxr-xr-xSource/DirectFB/lib/direct/util.c519
1 files changed, 519 insertions, 0 deletions
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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+#include <direct/clock.h>
+
+#ifdef CLOCK_MONOTONIC
+#include <sys/syscall.h>
+#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
+}