aboutsummaryrefslogtreecommitdiffstats
path: root/android_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'android_utils.c')
-rw-r--r--android_utils.c1946
1 files changed, 0 insertions, 1946 deletions
diff --git a/android_utils.c b/android_utils.c
deleted file mode 100644
index b995504..0000000
--- a/android_utils.c
+++ /dev/null
@@ -1,1946 +0,0 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program 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 General Public License for more details.
-*/
-#include "android_utils.h"
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <fcntl.h>
-#ifdef _WIN32
-#include <process.h>
-#include <shlobj.h>
-#include <tlhelp32.h>
-#include <io.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdint.h>
-#include <limits.h>
-#include <winbase.h>
-#else
-#include <unistd.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <signal.h>
-#endif
-#include "android.h"
-#include "android_debug.h"
-
-#define D(...) VERBOSE_PRINT(init,__VA_ARGS__)
-
-#ifdef _WIN32
-char*
-win32_strsep(char** pline, const char* delim)
-{
- char* line = *pline;
- char* p = line;
-
- if (p == NULL)
- return NULL;
-
- for (;;) {
- int c = *p++;
- const char* q = delim;
-
- if (c == 0) {
- p = NULL;
- break;
- }
-
- while (*q) {
- if (*q == c) {
- p[-1] = 0;
- goto Exit;
- }
- q++;
- }
- }
-Exit:
- *pline = p;
- return line;
-}
-#endif
-
-/** PATH HANDLING ROUTINES
- **
- ** path_parent() can be used to return the n-level parent of a given directory
- ** this understands . and .. when encountered in the input path
- **/
-
-static __inline__ int
-ispathsep(int c)
-{
-#ifdef _WIN32
- return (c == '/' || c == '\\');
-#else
- return (c == '/');
-#endif
-}
-
-char* path_parent( const char* path, int levels )
-{
- const char* end = path + strlen(path);
- char* result;
-
- while (levels > 0) {
- const char* base;
-
- /* trim any trailing path separator */
- while (end > path && ispathsep(end[-1]))
- end--;
-
- base = end;
- while (base > path && !ispathsep(base[-1]))
- base--;
-
- if (base <= path) /* we can't go that far */
- return NULL;
-
- if (end == base+1 && base[0] == '.')
- goto Next;
-
- if (end == base+2 && base[0] == '.' && base[1] == '.') {
- levels += 1;
- goto Next;
- }
-
- levels -= 1;
-
- Next:
- end = base - 1;
- }
- result = malloc( end-path+1 );
- if (result != NULL) {
- memcpy( result, path, end-path );
- result[end-path] = 0;
- }
- return result;
-}
-
-
-/** MISC FILE AND DIRECTORY HANDLING
- **/
-
-int
-path_exists( const char* path )
-{
- int ret;
- CHECKED(ret, access(path, F_OK));
- return (ret == 0) || (errno != ENOENT);
-}
-
-/* checks that a path points to a regular file */
-int
-path_is_regular( const char* path )
-{
- int ret;
- struct stat st;
-
- CHECKED(ret, stat(path, &st));
- if (ret < 0)
- return 0;
-
- return S_ISREG(st.st_mode);
-}
-
-
-/* checks that a path points to a directory */
-int
-path_is_dir( const char* path )
-{
- int ret;
- struct stat st;
-
- CHECKED(ret, stat(path, &st));
- if (ret < 0)
- return 0;
-
- return S_ISDIR(st.st_mode);
-}
-
-/* checks that one can read/write a given (regular) file */
-int
-path_can_read( const char* path )
-{
- int ret;
- CHECKED(ret, access(path, R_OK));
- return (ret == 0);
-}
-
-int
-path_can_write( const char* path )
-{
- int ret;
- CHECKED(ret, access(path, R_OK));
- return (ret == 0);
-}
-
-/* try to make a directory. returns 0 on success, -1 on failure
- * (error code in errno) */
-int
-path_mkdir( const char* path, int mode )
-{
-#ifdef _WIN32
- (void)mode;
- return _mkdir(path);
-#else
- int ret;
- CHECKED(ret, mkdir(path, mode));
- return ret;
-#endif
-}
-
-static int
-path_mkdir_recursive( char* path, unsigned len, int mode )
-{
- char old_c;
- int ret;
- unsigned len2;
-
- /* get rid of trailing separators */
- while (len > 0 && ispathsep(path[len-1]))
- len -= 1;
-
- if (len == 0) {
- errno = ENOENT;
- return -1;
- }
-
- /* check that the parent exists, 'len2' is the length of
- * the parent part of the path */
- len2 = len-1;
- while (len2 > 0 && !ispathsep(path[len2-1]))
- len2 -= 1;
-
- if (len2 > 0) {
- old_c = path[len2];
- path[len2] = 0;
- ret = 0;
- if ( !path_exists(path) ) {
- /* the parent doesn't exist, so try to create it */
- ret = path_mkdir_recursive( path, len2, mode );
- }
- path[len2] = old_c;
-
- if (ret < 0)
- return ret;
- }
-
- /* at this point, we now the parent exists */
- old_c = path[len];
- path[len] = 0;
- ret = path_mkdir( path, mode );
- path[len] = old_c;
-
- return ret;
-}
-
-/* ensure that a given directory exists, create it if not,
- 0 on success, -1 on failure (error code in errno) */
-int
-path_mkdir_if_needed( const char* path, int mode )
-{
- int ret = 0;
-
- if (!path_exists(path)) {
- ret = path_mkdir(path, mode);
-
- if (ret < 0 && errno == ENOENT) {
- char temp[MAX_PATH];
- unsigned len = (unsigned)strlen(path);
-
- if (len > sizeof(temp)-1) {
- errno = EINVAL;
- return -1;
- }
- memcpy( temp, path, len );
- temp[len] = 0;
-
- return path_mkdir_recursive(temp, len, mode);
- }
- }
- return ret;
-}
-
-/* return the size of a given file in '*psize'. returns 0 on
- * success, -1 on failure (error code in errno) */
-int
-path_get_size( const char* path, uint64_t *psize )
-{
-#ifdef _WIN32
- /* avoid _stat64 which is only defined in MSVCRT.DLL, not CRTDLL.DLL */
- /* do not use OpenFile() because it has strange search behaviour that could */
- /* result in getting the size of a different file */
- LARGE_INTEGER size;
- HANDLE file = CreateFile( /* lpFilename */ path,
- /* dwDesiredAccess */ GENERIC_READ,
- /* dwSharedMode */ FILE_SHARE_READ|FILE_SHARE_WRITE,
- /* lpSecurityAttributes */ NULL,
- /* dwCreationDisposition */ OPEN_EXISTING,
- /* dwFlagsAndAttributes */ 0,
- /* hTemplateFile */ NULL );
- if (file == INVALID_HANDLE_VALUE) {
- /* ok, just to play fair */
- errno = ENOENT;
- return -1;
- }
- if (!GetFileSizeEx(file, &size)) {
- /* maybe we tried to get the size of a pipe or something like that ? */
- *psize = 0;
- }
- else {
- *psize = (uint64_t) size.QuadPart;
- }
- CloseHandle(file);
- return 0;
-#else
- int ret;
- struct stat st;
-
- CHECKED(ret, stat(path, &st));
- if (ret == 0) {
- *psize = (uint64_t) st.st_size;
- }
- return ret;
-#endif
-}
-
-
-/** USEFUL STRING BUFFER FUNCTIONS
- **/
-
-char*
-vbufprint( char* buffer,
- char* buffer_end,
- const char* fmt,
- va_list args )
-{
- int len = vsnprintf( buffer, buffer_end - buffer, fmt, args );
- if (len < 0 || buffer+len >= buffer_end) {
- if (buffer < buffer_end)
- buffer_end[-1] = 0;
- return buffer_end;
- }
- return buffer + len;
-}
-
-char*
-bufprint(char* buffer, char* end, const char* fmt, ... )
-{
- va_list args;
- char* result;
-
- va_start(args, fmt);
- result = vbufprint(buffer, end, fmt, args);
- va_end(args);
- return result;
-}
-
-/** USEFUL DIRECTORY SUPPORT
- **
- ** bufprint_app_dir() returns the directory where the emulator binary is located
- **
- ** get_android_home() returns a user-specific directory where the emulator will
- ** store its writable data (e.g. config files, profiles, etc...).
- ** on Unix, this is $HOME/.android, on Windows, this is something like
- ** "%USERPROFILE%/Local Settings/AppData/Android" on XP, and something different
- ** on Vista.
- **
- ** both functions return a string that must be freed by the caller
- **/
-
-#ifdef __linux__
-char*
-bufprint_app_dir(char* buff, char* end)
-{
- char path[1024];
- int len;
- char* x;
-
- len = readlink("/proc/self/exe", path, sizeof(path));
- if (len <= 0 || len >= (int)sizeof(path)) goto Fail;
- path[len] = 0;
-
- x = strrchr(path, '/');
- if (x == 0) goto Fail;
- *x = 0;
-
- return bufprint(buff, end, "%s", path);
-Fail:
- fprintf(stderr,"cannot locate application directory\n");
- exit(1);
- return end;
-}
-
-#elif defined(__APPLE__)
-/* the following hack is needed in order to build with XCode 3.1
- * don't ask me why, but it seems that there were changes in the
- * GCC compiler that we don't have in our pre-compiled version
- */
-#ifndef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
-#define __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ MAC_OS_X_VERSION_10_4
-#endif
-#import <Carbon/Carbon.h>
-#include <unistd.h>
-
-char*
-bufprint_app_dir(char* buff, char* end)
-{
- ProcessSerialNumber psn;
- CFDictionaryRef dict;
- CFStringRef value;
- char s[PATH_MAX];
- char* x;
-
- GetCurrentProcess(&psn);
- dict = ProcessInformationCopyDictionary(&psn, 0xffffffff);
- value = (CFStringRef)CFDictionaryGetValue(dict,
- CFSTR("CFBundleExecutable"));
- CFStringGetCString(value, s, PATH_MAX - 1, kCFStringEncodingUTF8);
- x = strrchr(s, '/');
- if (x == 0) goto fail;
- *x = 0;
-
- return bufprint(buff, end, "%s", s);
-fail:
- fprintf(stderr,"cannot locate application directory\n");
- exit(1);
- return end;
-}
-#elif defined _WIN32
-char*
-bufprint_app_dir(char* buff, char* end)
-{
- char appDir[MAX_PATH];
- char* sep;
-
- GetModuleFileName( 0, appDir, sizeof(appDir)-1 );
- sep = strrchr( appDir, '\\' );
- if (sep)
- *sep = 0;
-
- return bufprint(buff, end, "%s", appDir);
-}
-#else
-char*
-bufprint_app_dir(char* buff, char* end)
-{
- return bufprint(buff, end, ".");
-}
-#endif
-
-#define _ANDROID_PATH ".android"
-
-char*
-bufprint_config_path(char* buff, char* end)
-{
-#ifdef _WIN32
- char path[MAX_PATH];
-
- SHGetFolderPath( NULL, CSIDL_PROFILE,
- NULL, 0, path);
-
- return bufprint(buff, end, "%s\\%s", path, _ANDROID_PATH );
-#else
- const char* home = getenv("HOME");
- if (home == NULL)
- home = "/tmp";
- return bufprint(buff, end, "%s/%s", home, _ANDROID_PATH );
-#endif
-}
-
-char*
-bufprint_config_file(char* buff, char* end, const char* suffix)
-{
- char* p;
- p = bufprint_config_path(buff, end);
- p = bufprint(p, end, PATH_SEP "%s", suffix);
- return p;
-}
-
-char*
-bufprint_temp_dir(char* buff, char* end)
-{
-#ifdef _WIN32
- char path[MAX_PATH];
- DWORD retval;
-
- retval = GetTempPath( sizeof(path), path );
- if (retval > sizeof(path) || retval == 0) {
- D( "can't locate TEMP directory" );
- pstrcpy(path, sizeof(path), "C:\\Temp");
- }
- strncat( path, "\\AndroidEmulator", sizeof(path)-1 );
- _mkdir(path);
-
- return bufprint(buff, end, "%s", path);
-#else
- const char* tmppath = "/tmp/android";
- mkdir(tmppath, 0744);
- return bufprint(buff, end, "%s", tmppath );
-#endif
-}
-
-char*
-bufprint_temp_file(char* buff, char* end, const char* suffix)
-{
- char* p;
- p = bufprint_temp_dir(buff, end);
- p = bufprint(p, end, PATH_SEP "%s", suffix);
- return p;
-}
-
-
-
-/** FILE LOCKS SUPPORT
- **
- ** a FileLock is useful to prevent several emulator instances from using the same
- ** writable file (e.g. the userdata.img disk images).
- **
- ** create a FileLock object with filelock_create(), ithis function should return NULL
- ** only if the corresponding file path could not be locked.
- **
- ** all file locks are automatically released and destroyed when the program exits.
- ** the filelock_lock() function can also detect stale file locks that can linger
- ** when the emulator crashes unexpectedly, and will happily clean them for you
- **
- ** here's how it works, three files are used:
- ** file - the data file accessed by the emulator
- ** lock - a lock file (file + '.lock')
- ** temp - a temporary file make unique with mkstemp
- **
- ** when locking:
- ** create 'temp' and store our pid in it
- ** attemp to link 'lock' to 'temp'
- ** if the link succeeds, we obtain the lock
- ** unlink 'temp'
- **
- ** when unlocking:
- ** unlink 'lock'
- **
- **
- ** on Windows, 'lock' is a directory name. locking is equivalent to
- ** creating it...
- **
- **/
-
-struct FileLock
-{
- const char* file;
- const char* lock;
- char* temp;
- int locked;
- FileLock* next;
-};
-
-/* used to cleanup all locks at emulator exit */
-static FileLock* _all_filelocks;
-
-
-#define LOCK_NAME ".lock"
-#define TEMP_NAME ".tmp-XXXXXX"
-
-#ifdef _WIN32
-#define PIDFILE_NAME "pid"
-#endif
-
-/* returns 0 on success, -1 on failure */
-static int
-filelock_lock( FileLock* lock )
-{
- int ret;
-#ifdef _WIN32
- int pidfile_fd = -1;
-
- ret = _mkdir( lock->lock );
- if (ret < 0) {
- if (errno == ENOENT) {
- D( "could not access directory '%s', check path elements", lock->lock );
- return -1;
- } else if (errno != EEXIST) {
- D( "_mkdir(%s): %s", lock->lock, strerror(errno) );
- return -1;
- }
-
- /* if we get here, it's because the .lock directory already exists */
- /* check to see if there is a pid file in it */
- D("directory '%s' already exist, waiting a bit to ensure that no other emulator instance is starting", lock->lock );
- {
- int _sleep = 200;
- int tries;
-
- for ( tries = 4; tries > 0; tries-- )
- {
- pidfile_fd = open( lock->temp, O_RDONLY );
-
- if (pidfile_fd >= 0)
- break;
-
- Sleep( _sleep );
- _sleep *= 2;
- }
- }
-
- if (pidfile_fd < 0) {
- D( "no pid file in '%s', assuming stale directory", lock->lock );
- }
- else
- {
- /* read the pidfile, and check wether the corresponding process is still running */
- char buf[16];
- int len, lockpid;
- HANDLE processSnapshot;
- PROCESSENTRY32 pe32;
- int is_locked = 0;
-
- len = read( pidfile_fd, buf, sizeof(buf)-1 );
- if (len < 0) {
- D( "could not read pid file '%s'", lock->temp );
- close( pidfile_fd );
- return -1;
- }
- buf[len] = 0;
- lockpid = atoi(buf);
-
- /* PID 0 is the IDLE process, and 0 is returned in case of invalid input */
- if (lockpid == 0)
- lockpid = -1;
-
- close( pidfile_fd );
-
- pe32.dwSize = sizeof( PROCESSENTRY32 );
- processSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
-
- if ( processSnapshot == INVALID_HANDLE_VALUE ) {
- D( "could not retrieve the list of currently active processes\n" );
- is_locked = 1;
- }
- else if ( !Process32First( processSnapshot, &pe32 ) )
- {
- D( "could not retrieve first process id\n" );
- CloseHandle( processSnapshot );
- is_locked = 1;
- }
- else
- {
- do {
- if (pe32.th32ProcessID == lockpid) {
- is_locked = 1;
- break;
- }
- } while (Process32Next( processSnapshot, &pe32 ) );
-
- CloseHandle( processSnapshot );
- }
-
- if (is_locked) {
- D( "the file '%s' is locked by process ID %d\n", lock->file, lockpid );
- return -1;
- }
- }
- }
-
- /* write our PID into the pid file */
- pidfile_fd = open( lock->temp, O_WRONLY | O_CREAT | O_TRUNC );
- if (pidfile_fd < 0) {
- if (errno == EACCES) {
- if ( unlink_file( lock->temp ) < 0 ) {
- D( "could not remove '%s': %s\n", lock->temp, strerror(errno) );
- return -1;
- }
- pidfile_fd = open( lock->temp, O_WRONLY | O_CREAT | O_TRUNC );
- }
- if (pidfile_fd < 0) {
- D( "could not create '%s': %s\n", lock->temp, strerror(errno) );
- return -1;
- }
- }
-
- {
- char buf[16];
- sprintf( buf, "%ld", GetCurrentProcessId() );
- ret = write( pidfile_fd, buf, strlen(buf) );
- close(pidfile_fd);
- if (ret < 0) {
- D( "could not write PID to '%s'\n", lock->temp );
- return -1;
- }
- }
-
- lock->locked = 1;
- return 0;
-#else
- int temp_fd = -1;
- int lock_fd = -1;
- int rc, tries, _sleep;
- FILE* f = NULL;
- char pid[8];
- struct stat st_temp;
-
- strcpy( lock->temp, lock->file );
- strcat( lock->temp, TEMP_NAME );
- temp_fd = mkstemp( lock->temp );
-
- if (temp_fd < 0) {
- D("cannot create locking temp file '%s'", lock->temp );
- goto Fail;
- }
-
- sprintf( pid, "%d", getpid() );
- ret = write( temp_fd, pid, strlen(pid)+1 );
- if (ret < 0) {
- D( "cannot write to locking temp file '%s'", lock->temp);
- goto Fail;
- }
- close( temp_fd );
- temp_fd = -1;
-
- CHECKED(rc, lstat( lock->temp, &st_temp ));
- if (rc < 0) {
- D( "can't properly stat our locking temp file '%s'", lock->temp );
- goto Fail;
- }
-
- /* now attempt to link the temp file to the lock file */
- _sleep = 0;
- for ( tries = 4; tries > 0; tries-- )
- {
- struct stat st_lock;
- int rc;
-
- if (_sleep > 0) {
- if (_sleep > 2000000) {
- D( "cannot acquire lock file '%s'", lock->lock );
- goto Fail;
- }
- usleep( _sleep );
- }
- _sleep += 200000;
-
- /* the return value of link() is buggy on NFS */
- CHECKED(rc, link( lock->temp, lock->lock ));
-
- CHECKED(rc, lstat( lock->lock, &st_lock ));
- if (rc == 0 &&
- st_temp.st_rdev == st_lock.st_rdev &&
- st_temp.st_ino == st_lock.st_ino )
- {
- /* SUCCESS */
- lock->locked = 1;
- CHECKED(rc, unlink( lock->temp ));
- return 0;
- }
-
- /* if we get there, it means that the link() call failed */
- /* check the lockfile to see if it is stale */
- if (rc == 0) {
- char buf[16];
- time_t now;
- int lockpid = 0;
- int lockfd;
- int stale = 2; /* means don't know */
- struct stat st;
-
- CHECKED(rc, time( &now));
- st.st_mtime = now - 120;
-
- CHECKED(lockfd, open( lock->lock,O_RDONLY ));
- if ( lockfd >= 0 ) {
- int len;
-
- CHECKED(len, read( lockfd, buf, sizeof(buf)-1 ));
- buf[len] = 0;
- lockpid = atoi(buf);
-
- CHECKED(rc, fstat( lockfd, &st ));
- if (rc == 0)
- now = st.st_atime;
-
- CHECKED(rc, close(lockfd));
- }
- /* if there is a PID, check that it is still alive */
- if (lockpid > 0) {
- CHECKED(rc, kill( lockpid, 0 ));
- if (rc == 0 || errno == EPERM) {
- stale = 0;
- } else if (rc < 0 && errno == ESRCH) {
- stale = 1;
- }
- }
- if (stale == 2) {
- /* no pid, stale if the file is older than 1 minute */
- stale = (now >= st.st_mtime + 60);
- }
-
- if (stale) {
- D( "removing stale lockfile '%s'", lock->lock );
- CHECKED(rc, unlink( lock->lock ));
- _sleep = 0;
- tries++;
- }
- }
- }
- D("file '%s' is already in use by another process", lock->file );
-
-Fail:
- if (f)
- fclose(f);
-
- if (temp_fd >= 0) {
- close(temp_fd);
- }
-
- if (lock_fd >= 0) {
- close(lock_fd);
- }
-
- unlink( lock->lock );
- unlink( lock->temp );
- return -1;
-#endif
-}
-
-void
-filelock_release( FileLock* lock )
-{
- if (lock->locked) {
-#ifdef _WIN32
- unlink_file( (char*)lock->temp );
- rmdir( (char*)lock->lock );
-#else
- unlink( (char*)lock->lock );
-#endif
- lock->locked = 0;
- }
-}
-
-static void
-filelock_atexit( void )
-{
- FileLock* lock;
-
- for (lock = _all_filelocks; lock != NULL; lock = lock->next)
- filelock_release( lock );
-}
-
-/* create a file lock */
-FileLock*
-filelock_create( const char* file )
-{
- int file_len = strlen(file);
- int lock_len = file_len + sizeof(LOCK_NAME);
-#ifdef _WIN32
- int temp_len = lock_len + 1 + sizeof(PIDFILE_NAME);
-#else
- int temp_len = file_len + sizeof(TEMP_NAME);
-#endif
- int total_len = sizeof(FileLock) + file_len + lock_len + temp_len + 3;
-
- FileLock* lock = malloc(total_len);
-
- lock->file = (const char*)(lock + 1);
- memcpy( (char*)lock->file, file, file_len+1 );
-
- lock->lock = lock->file + file_len + 1;
- memcpy( (char*)lock->lock, file, file_len+1 );
- strcat( (char*)lock->lock, LOCK_NAME );
-
- lock->temp = (char*)lock->lock + lock_len + 1;
-#ifdef _WIN32
- snprintf( (char*)lock->temp, temp_len, "%s\\" PIDFILE_NAME, lock->lock );
-#else
- lock->temp[0] = 0;
-#endif
- lock->locked = 0;
-
- if (filelock_lock(lock) < 0) {
- free(lock);
- return NULL;
- }
-
- lock->next = _all_filelocks;
- _all_filelocks = lock;
-
- if (lock->next == NULL)
- atexit( filelock_atexit );
-
- return lock;
-}
-
-/** TEMP FILE SUPPORT
- **
- ** simple interface to create an empty temporary file on the system.
- **
- ** create the file with tempfile_create(), which returns a reference to a TempFile
- ** object, or NULL if your system is so weird it doesn't have a temporary directory.
- **
- ** you can then call tempfile_path() to retrieve the TempFile's real path to open
- ** it. the returned path is owned by the TempFile object and should not be freed.
- **
- ** all temporary files are destroyed when the program quits, unless you explicitely
- ** close them before that with tempfile_close()
- **/
-
-struct TempFile
-{
- const char* name;
- TempFile* next;
-};
-
-static void tempfile_atexit();
-static TempFile* _all_tempfiles;
-
-TempFile*
-tempfile_create( void )
-{
- TempFile* tempfile;
- const char* tempname = NULL;
-
-#ifdef _WIN32
- char temp_namebuff[MAX_PATH];
- char temp_dir[MAX_PATH];
- char *p = temp_dir, *end = p + sizeof(temp_dir);
- UINT retval;
-
- p = bufprint_temp_dir( p, end );
- if (p >= end) {
- D( "TEMP directory path is too long" );
- return NULL;
- }
-
- retval = GetTempFileName(temp_dir, "TMP", 0, temp_namebuff);
- if (retval == 0) {
- D( "can't create temporary file in '%s'", temp_dir );
- return NULL;
- }
-
- tempname = temp_namebuff;
-#else
-#define TEMPLATE "/tmp/.android-emulator-XXXXXX"
- int tempfd = -1;
- char template[512];
- char *p = template, *end = p + sizeof(template);
-
- p = bufprint_temp_file( p, end, "emulator-XXXXXX" );
- if (p >= end) {
- D( "Xcannot create temporary file in /tmp/android !!" );
- return NULL;
- }
-
- D( "template: %s", template );
- tempfd = mkstemp( template );
- if (tempfd < 0) {
- D("cannot create temporary file in /tmp/android !!");
- return NULL;
- }
- close(tempfd);
- tempname = template;
-#endif
- tempfile = malloc( sizeof(*tempfile) + strlen(tempname) + 1 );
- tempfile->name = (char*)(tempfile + 1);
- strcpy( (char*)tempfile->name, tempname );
-
- tempfile->next = _all_tempfiles;
- _all_tempfiles = tempfile;
-
- if ( !tempfile->next ) {
- atexit( tempfile_atexit );
- }
-
- return tempfile;
-}
-
-const char*
-tempfile_path(TempFile* temp)
-{
- return temp ? temp->name : NULL;
-}
-
-void
-tempfile_close(TempFile* tempfile)
-{
-#ifdef _WIN32
- DeleteFile(tempfile->name);
-#else
- unlink(tempfile->name);
-#endif
-}
-
-/** TEMP FILE CLEANUP
- **
- **/
-
-/* we don't expect to use many temporary files */
-#define MAX_ATEXIT_FDS 16
-
-typedef struct {
- int count;
- int fds[ MAX_ATEXIT_FDS ];
-} AtExitFds;
-
-static void
-atexit_fds_add( AtExitFds* t, int fd )
-{
- if (t->count < MAX_ATEXIT_FDS)
- t->fds[t->count++] = fd;
- else {
- dwarning("%s: over %d calls. Program exit may not cleanup all temporary files",
- __FUNCTION__, MAX_ATEXIT_FDS);
- }
-}
-
-static void
-atexit_fds_del( AtExitFds* t, int fd )
-{
- int nn;
- for (nn = 0; nn < t->count; nn++)
- if (t->fds[nn] == fd) {
- /* move the last element to the current position */
- t->count -= 1;
- t->fds[nn] = t->fds[t->count];
- break;
- }
-}
-
-static void
-atexit_fds_close_all( AtExitFds* t )
-{
- int nn;
- for (nn = 0; nn < t->count; nn++)
- close(t->fds[nn]);
-}
-
-static AtExitFds _atexit_fds[1];
-
-void
-atexit_close_fd(int fd)
-{
- if (fd >= 0)
- atexit_fds_add(_atexit_fds, fd);
-}
-
-void
-atexit_close_fd_remove(int fd)
-{
- if (fd >= 0)
- atexit_fds_del(_atexit_fds, fd);
-}
-
-static void
-tempfile_atexit( void )
-{
- TempFile* tempfile;
-
- atexit_fds_close_all( _atexit_fds );
-
- for (tempfile = _all_tempfiles; tempfile; tempfile = tempfile->next)
- tempfile_close(tempfile);
-}
-
-
-/** OTHER FILE UTILITIES
- **
- ** make_empty_file() creates an empty file at a given path location.
- ** if the file already exists, it is truncated without warning
- **
- ** copy_file() copies one file into another.
- **
- ** both functions return 0 on success, and -1 on error
- **/
-
-int
-make_empty_file( const char* path )
-{
-#ifdef _WIN32
- int fd = _creat( path, S_IWRITE );
-#else
- /* on Unix, only allow the owner to read/write, since the file *
- * may contain some personal data we don't want to see exposed */
- int fd = creat(path, S_IRUSR | S_IWUSR);
-#endif
- if (fd >= 0) {
- close(fd);
- return 0;
- }
- return -1;
-}
-
-int
-copy_file( const char* dest, const char* source )
-{
- int fd, fs, result = -1;
-
- if ( access(source, F_OK) < 0 ||
- make_empty_file(dest) < 0) {
- return -1;
- }
-
-#ifdef _WIN32
- fd = _open(dest, _O_RDWR | _O_BINARY);
- fs = _open(source, _O_RDONLY | _O_BINARY);
-#else
- fd = creat(dest, S_IRUSR | S_IWUSR);
- fs = open(source, S_IREAD);
-#endif
- if (fs >= 0 && fd >= 0) {
- char buf[4096];
- ssize_t total = 0;
- ssize_t n;
- result = 0; /* success */
- while ((n = read(fs, buf, 4096)) > 0) {
- if (write(fd, buf, n) != n) {
- /* write failed. Make it return -1 so that an
- * empty file be created. */
- D("Failed to copy '%s' to '%s': %s (%d)",
- source, dest, strerror(errno), errno);
- result = -1;
- break;
- }
- total += n;
- }
- }
-
- if (fs >= 0) {
- close(fs);
- }
- if (fd >= 0) {
- close(fd);
- }
- return result;
-}
-
-int
-unlink_file( const char* path )
-{
-#ifdef _WIN32
- int ret = _unlink( path );
- if (ret == -1 && errno == EACCES) {
- /* a first call to _unlink will fail if the file is set read-only */
- /* we can however try to change its mode first and call unlink */
- /* again... */
- ret = _chmod( path, _S_IREAD | _S_IWRITE );
- if (ret == 0)
- ret = _unlink( path );
- }
- return ret;
-#else
- return unlink(path);
-#endif
-}
-
-
-void*
-load_text_file(const char *fn)
-{
- char *data;
- int sz;
- int fd;
-
- data = NULL;
- fd = open(fn, O_BINARY | O_RDONLY);
- if(fd < 0) return NULL;
-
- sz = lseek(fd, 0, SEEK_END);
- if(sz < 0) goto oops;
-
- if(lseek(fd, 0, SEEK_SET) != 0) goto oops;
-
- data = (char*) malloc(sz + 1);
- if(data == 0) goto oops;
-
- if(read(fd, data, sz) != sz) goto oops;
- close(fd);
- data[sz] = 0;
-
- return data;
-
-oops:
- close(fd);
- if(data != 0)
- free(data);
- return NULL;
-}
-
-/** HOST RESOLUTION SETTINGS
- **
- ** return the main monitor's DPI resolution according to the host device
- ** beware: this is not always reliable or even obtainable.
- **
- ** returns 0 on success, or -1 in case of error (e.g. the system returns funky values)
- **/
-
-/** NOTE: the following code assumes that we exclusively use X11 on Linux, and Quartz on OS X
- **/
-
-#ifdef _WIN32
-int
-get_monitor_resolution( int *px_dpi, int *py_dpi )
-{
- HDC displayDC = CreateDC( "DISPLAY", NULL, NULL, NULL );
- int xdpi, ydpi;
-
- if (displayDC == NULL) {
- D( "%s: could not get display DC\n", __FUNCTION__ );
- return -1;
- }
- xdpi = GetDeviceCaps( displayDC, LOGPIXELSX );
- ydpi = GetDeviceCaps( displayDC, LOGPIXELSY );
-
- /* sanity checks */
- if (xdpi < 20 || xdpi > 400 || ydpi < 20 || ydpi > 400) {
- D( "%s: bad resolution: xpi=%d ydpi=%d", __FUNCTION__,
- xdpi, ydpi );
- return -1;
- }
-
- *px_dpi = xdpi;
- *py_dpi = ydpi;
- return 0;
-}
-#elif defined __APPLE__
-int
-get_monitor_resolution( int *px_dpi, int *py_dpi )
-{
- fprintf(stderr, "emulator: FIXME: implement get_monitor_resolution on OS X\n" );
- return -1;
-}
-#else /* Linux and others */
-#include <SDL.h>
-#include <SDL_syswm.h>
-#include <dlfcn.h>
-#include <X11/Xlib.h>
-#define MM_PER_INCH 25.4
-
-#define DYNLINK_FUNCTIONS \
- DYNLINK_FUNC(int,XDefaultScreen,(Display*)) \
- DYNLINK_FUNC(int,XDisplayWidth,(Display*,int)) \
- DYNLINK_FUNC(int,XDisplayWidthMM,(Display*,int)) \
- DYNLINK_FUNC(int,XDisplayHeight,(Display*,int)) \
- DYNLINK_FUNC(int,XDisplayHeightMM,(Display*,int)) \
-
-#define DYNLINK_FUNCTIONS_INIT \
- x11_dynlink_init
-
-#include "dynlink.h"
-
-static int x11_lib_inited;
-static void* x11_lib;
-
-int
-x11_lib_init( void )
-{
- if (!x11_lib_inited) {
- x11_lib_inited = 1;
-
- x11_lib = dlopen( "libX11.so", RTLD_NOW );
-
- if (x11_lib == NULL) {
- x11_lib = dlopen( "libX11.so.6", RTLD_NOW );
- }
- if (x11_lib == NULL) {
- D("%s: Could not find libX11.so on this machine",
- __FUNCTION__);
- return -1;
- }
-
- if (x11_dynlink_init(x11_lib) < 0) {
- D("%s: didn't find necessary symbols in libX11.so",
- __FUNCTION__);
- dlclose(x11_lib);
- x11_lib = NULL;
- }
- }
- return x11_lib ? 0 : -1;
-}
-
-
-int
-get_monitor_resolution( int *px_dpi, int *py_dpi )
-{
- SDL_SysWMinfo info;
- Display* display;
- int screen;
- int width, width_mm, height, height_mm, xdpi, ydpi;
-
- SDL_VERSION(&info.version);
-
- if ( !SDL_GetWMInfo(&info) ) {
- D( "%s: SDL_GetWMInfo() failed: %s", __FUNCTION__, SDL_GetError());
- return -1;
- }
-
- if (x11_lib_init() < 0)
- return -1;
-
- display = info.info.x11.display;
- screen = FF(XDefaultScreen)(display);
-
- width = FF(XDisplayWidth)(display, screen);
- width_mm = FF(XDisplayWidthMM)(display, screen);
- height = FF(XDisplayHeight)(display, screen);
- height_mm = FF(XDisplayHeightMM)(display, screen);
-
- if (width_mm <= 0 || height_mm <= 0) {
- D( "%s: bad screen dimensions: width_mm = %d, height_mm = %d",
- __FUNCTION__, width_mm, height_mm);
- return -1;
- }
-
- D( "%s: found screen width=%d height=%d width_mm=%d height_mm=%d",
- __FUNCTION__, width, height, width_mm, height_mm );
-
- xdpi = width * MM_PER_INCH / width_mm;
- ydpi = height * MM_PER_INCH / height_mm;
-
- if (xdpi < 20 || xdpi > 400 || ydpi < 20 || ydpi > 400) {
- D( "%s: bad resolution: xpi=%d ydpi=%d", __FUNCTION__,
- xdpi, ydpi );
- return -1;
- }
-
- *px_dpi = xdpi;
- *py_dpi = ydpi;
-
- return 0;
-}
-#endif
-
-
-
-void
-disable_sigalrm( signal_state_t *state )
-{
-#ifdef _WIN32
- (void)state;
-#else
- sigset_t set;
-
- sigemptyset(&set);
- sigaddset(&set, SIGALRM);
- pthread_sigmask (SIG_BLOCK, &set, &state->old);
-#endif
-}
-
-void
-restore_sigalrm( signal_state_t *state )
-{
-#ifdef _WIN32
- (void)state;
-#else
- pthread_sigmask (SIG_SETMASK, &state->old, NULL);
-#endif
-}
-
-void
-sleep_ms( int timeout_ms )
-{
-#ifdef _WIN32
- if (timeout_ms <= 0)
- return;
-
- Sleep( timeout_ms );
-#else
- if (timeout_ms <= 0)
- return;
-
- BEGIN_NOSIGALRM
- usleep( timeout_ms*1000 );
- END_NOSIGALRM
-#endif
-}
-
-
-extern void
-print_tabular( const char** strings, int count,
- const char* prefix, int width )
-{
- int nrows, ncols, r, c, n, maxw = 0;
-
- for (n = 0; n < count; n++) {
- int len = strlen(strings[n]);
- if (len > maxw)
- maxw = len;
- }
- maxw += 2;
- ncols = width/maxw;
- nrows = (count + ncols-1)/ncols;
-
- for (r = 0; r < nrows; r++) {
- printf( "%s", prefix );
- for (c = 0; c < ncols; c++) {
- int index = c*nrows + r;
- if (index >= count) {
- break;
- }
- printf( "%-*s", maxw, strings[index] );
- }
- printf( "\n" );
- }
-}
-
-extern void
-stralloc_tabular( stralloc_t* out,
- const char** strings, int count,
- const char* prefix, int width )
-{
- int nrows, ncols, r, c, n, maxw = 0;
-
- for (n = 0; n < count; n++) {
- int len = strlen(strings[n]);
- if (len > maxw)
- maxw = len;
- }
- maxw += 2;
- ncols = width/maxw;
- nrows = (count + ncols-1)/ncols;
-
- for (r = 0; r < nrows; r++) {
- stralloc_add_str( out, prefix );
- for (c = 0; c < ncols; c++) {
- int index = c*nrows + r;
- if (index >= count) {
- break;
- }
- stralloc_add_format( out, "%-*s", maxw, strings[index] );
- }
- stralloc_add_str( out, "\n" );
- }
-}
-
-extern void
-string_translate_char( char* str, char from, char to )
-{
- char* p = str;
- while (p != NULL && (p = strchr(p, from)) != NULL)
- *p++ = to;
-}
-
-extern void
-buffer_translate_char( char* buff,
- unsigned buffLen,
- const char* src,
- char fromChar,
- char toChar )
-{
- int len = strlen(src);
-
- if (len >= buffLen)
- len = buffLen-1;
-
- memcpy(buff, src, len);
- buff[len] = 0;
-
- string_translate_char( buff, fromChar, toChar );
-}
-
-
-/** DYNAMIC STRINGS
- **/
-
-extern void
-stralloc_reset( stralloc_t* s )
-{
- free(s->s);
- s->s = NULL;
- s->n = 0;
- s->a = 0;
-}
-
-extern void
-stralloc_ready( stralloc_t* s, unsigned int len )
-{
- unsigned old_max = s->a;
- unsigned new_max = old_max;
-
- while (new_max < len) {
- unsigned new_max2 = new_max + (new_max >> 1) + 16;
- if (new_max2 < new_max)
- new_max2 = UINT_MAX;
- new_max = new_max2;
- }
-
- s->s = realloc( s->s, new_max );
- if (s->s == NULL) {
- derror( "%s: not enough memory to reallocate %ld bytes",
- __FUNCTION__, new_max );
- exit(1);
- }
- s->a = new_max;
-}
-
-extern void
-stralloc_readyplus( stralloc_t* s, unsigned int len )
-{
- unsigned len2 = s->n + len;
-
- if (len2 < s->n) { /* overflow ? */
- derror("%s: trying to grow by too many bytes: %ld",
- __FUNCTION__, len);
- exit(1);
- }
- stralloc_ready( s, len2 );
-}
-
-extern void
-stralloc_copy( stralloc_t* s, stralloc_t* from )
-{
- stralloc_ready(s, from->n);
- memcpy( s->s, from->s, from->n );
- s->n = from->n;
-}
-
-extern void
-stralloc_append( stralloc_t* s, stralloc_t* from )
-{
- stralloc_readyplus( s, from->n );
- memcpy( s->s + s->n, from->s, from->n );
- s->n += from->n;
-}
-
-extern void
-stralloc_add_c( stralloc_t* s, int c )
-{
- stralloc_add_bytes( s, (char*)&c, 1 );
-}
-
-extern void
-stralloc_add_str( stralloc_t* s, const char* str )
-{
- stralloc_add_bytes( s, str, strlen(str) );
-}
-
-extern void
-stralloc_add_bytes( stralloc_t* s, const void* from, unsigned len )
-{
- stralloc_readyplus( s, len );
- memcpy( s->s + s->n, from, len );
- s->n += len;
-}
-
-extern char*
-stralloc_cstr( stralloc_t* s )
-{
- stralloc_readyplus( s, 1 );
- s->s[s->n] = 0;
- return s->s;
-}
-
-extern void
-stralloc_format( stralloc_t* s, const char* fmt, ... )
-{
- stralloc_reset(s);
- stralloc_ready(s, 10);
-
- while (1) {
- int n;
- va_list args;
-
- va_start(args, fmt);
- n = vsnprintf( s->s, s->a, fmt, args );
- va_end(args);
-
- /* funky old C libraries returns -1 when truncation occurs */
- if (n > -1 && n < s->a) {
- s->n = n;
- break;
- }
- if (n > -1) { /* we now precisely what we need */
- stralloc_ready( s, n+1 );
- } else {
- stralloc_ready( s, s->a*2 );
- }
- }
-}
-
-extern void
-stralloc_add_format( stralloc_t* s, const char* fmt, ... )
-{
- STRALLOC_DEFINE(s2);
-
- stralloc_ready(s, 10);
- while (1) {
- int n;
- va_list args;
-
- va_start(args, fmt);
- n = vsnprintf( s2->s, s2->a, fmt, args );
- va_end(args);
-
- /* some C libraries return -1 when truncation occurs */
- if (n > -1 && n < s2->a) {
- s2->n = n;
- break;
- }
- if (n > -1) { /* we now precisely what we need */
- stralloc_ready( s2, n+1 );
- } else {
- stralloc_ready( s2, s2->a*2 );
- }
- }
-
- stralloc_append( s, s2 );
- stralloc_reset( s2 );
-}
-
-
-extern void
-stralloc_add_quote_c( stralloc_t* s, int c )
-{
- stralloc_add_quote_bytes( s, (char*)&c, 1 );
-}
-
-extern void
-stralloc_add_quote_str( stralloc_t* s, const char* str )
-{
- stralloc_add_quote_bytes( s, str, strlen(str) );
-}
-
-extern void
-stralloc_add_quote_bytes( stralloc_t* s, const void* from, unsigned len )
-{
- uint8_t* p = (uint8_t*) from;
- uint8_t* end = p + len;
-
- for ( ; p < end; p++ ) {
- int c = p[0];
-
- if (c == '\\') {
- stralloc_add_str( s, "\\\\" );
- } else if (c >= ' ' && c < 128) {
- stralloc_add_c( s, c );
- } else if (c == '\n') {
- stralloc_add_str( s, "\\n" );
- } else if (c == '\t') {
- stralloc_add_str( s, "\\t" );
- } else if (c == '\r') {
- stralloc_add_str( s, "\\r" );
- } else {
- stralloc_add_format( s, "\\x%02x", c );
- }
- }
-}
-
-extern void
-stralloc_add_hex( stralloc_t* s, unsigned value, int num_digits )
-{
- const char hexdigits[16] = "0123456789abcdef";
- int nn;
-
- if (num_digits <= 0)
- return;
-
- stralloc_readyplus(s, num_digits);
- for (nn = num_digits-1; nn >= 0; nn--) {
- s->s[s->n+nn] = hexdigits[value & 15];
- value >>= 4;
- }
- s->n += num_digits;
-}
-
-extern void
-stralloc_add_hexdump( stralloc_t* s, void* base, int size, const char* prefix )
-{
- uint8_t* p = (uint8_t*)base;
- const int max_count = 16;
- int prefix_len = strlen(prefix);
-
- while (size > 0) {
- int count = size > max_count ? max_count : size;
- int count2;
- int n;
-
- stralloc_add_bytes( s, prefix, prefix_len );
- stralloc_add_hex( s, p[0], 2 );
-
- for (n = 1; n < count; n++) {
- stralloc_add_c( s, ' ' );
- stralloc_add_hex( s, p[n], 2 );
- }
-
- count2 = 4 + 3*(max_count - count);
- stralloc_readyplus( s, count2 );
- memset( s->s + s->n, ' ', count2 );
- s->n += count2;
-
- stralloc_readyplus(s, count+1);
- for (n = 0; n < count; n++) {
- int c = p[n];
-
- if (c < 32 || c > 127)
- c = '.';
-
- s->s[s->n++] = c;
- }
- s->s[s->n++] = '\n';
-
- size -= count;
- p += count;
- }
-}
-
-/** TEMP CHAR STRINGS
- **
- ** implement a circular ring of temporary string buffers
- **/
-
-typedef struct Temptring {
- struct TempString* next;
- char* buffer;
- int size;
-} TempString;
-
-#define MAX_TEMP_STRINGS 16
-
-static TempString _temp_strings[ MAX_TEMP_STRINGS ];
-static int _temp_string_n;
-
-extern char*
-tempstr_get( int size )
-{
- TempString* t = &_temp_strings[_temp_string_n];
-
- if ( ++_temp_string_n >= MAX_TEMP_STRINGS )
- _temp_string_n = 0;
-
- size += 1; /* reserve 1 char for terminating zero */
-
- if (t->size < size) {
- t->buffer = realloc( t->buffer, size );
- if (t->buffer == NULL) {
- derror( "%s: could not allocate %d bytes",
- __FUNCTION__, size );
- exit(1);
- }
- t->size = size;
- }
- return t->buffer;
-}
-
-extern char*
-tempstr_from_stralloc( stralloc_t* s )
-{
- char* q = tempstr_get( s->n );
-
- memcpy( q, s->s, s->n );
- q[s->n] = 0;
- return q;
-}
-
-/** QUOTING
- **
- ** dumps a human-readable version of a string. this replaces
- ** newlines with \n, etc...
- **/
-
-extern const char*
-quote_bytes( const char* str, int len )
-{
- STRALLOC_DEFINE(s);
- char* q;
-
- stralloc_add_quote_bytes( s, str, len );
- q = tempstr_from_stralloc( s );
- stralloc_reset(s);
- return q;
-}
-
-extern const char*
-quote_str( const char* str )
-{
- int len = strlen(str);
- return quote_bytes( str, len );
-}
-
-/** DYNAMIC ARRAYS OF POINTERS
- **/
-
-void
-qvector_init( qvector_t* v )
-{
- v->i = NULL;
- v->n = v->a = 0;
-}
-
-void
-qvector_reset( qvector_t* v )
-{
- free(v->i);
- v->i = NULL;
- v->n = v->a = 0;
-}
-
-void
-qvector_ready( qvector_t* v, unsigned len )
-{
- unsigned old_a = v->a;
- unsigned new_a = old_a;
- unsigned max_a = UINT_MAX/sizeof(v->i[0]);
-
- if (len <= old_a)
- return;
-
- if (len > max_a) {
- derror("panic: %s: length too long (%d)", __FUNCTION__, len);
- exit(1);
- }
-
- while (new_a < len) {
- unsigned new_a2 = new_a + (new_a >> 1) + 8;
- if (new_a2 < new_a || new_a2 > max_a)
- new_a2 = max_a;
- new_a = max_a;
- }
- v->i = realloc( v->i, new_a*sizeof(v->i[0]) );
- v->a = new_a;
-}
-
-void
-qvector_readyplus( qvector_t* v, unsigned len )
-{
- unsigned len2 = len + v->n;
-
- if (len2 < len) {
- derror("panic: %s: length too long (%d)", __FUNCTION__, len);
- exit(1);
- }
- qvector_ready(v, len2);
-}
-
-void
-qvector_add( qvector_t* v, void* item )
-{
- qvector_readyplus(v, 1);
- v->i[v->n] = item;
- v->n += 1;
-}
-
-int
-qvector_del( qvector_t* v, void* item )
-{
- int index = qvector_index(v, item);
- if (index < 0) return 0;
- qvector_remove(v, index);
- return 1;
-}
-
-extern void*
-qvector_get( qvector_t* v, int index )
-{
- if ((unsigned)index >= (unsigned)v->n)
- return NULL;
-
- return v->i[index];
-}
-
-extern void
-qvector_set( qvector_t* v, int index, void* item )
-{
- if ((unsigned)index < (unsigned)v->n)
- v->i[index] = item;
- }
-
-int
-qvector_len( qvector_t* v )
-{
- return v->n;
-}
-
-int
-qvector_index( qvector_t* v, void* item )
-{
- int nn;
- for (nn = 0; nn < v->n; nn++)
- if (v->i[nn] == item)
- return nn;
- return -1;
-}
-
-void
-qvector_insert( qvector_t* v, int index, void* item )
-{
- if (index < 0) index = 0;
- if (index > v->n) index = v->n;
-
- memmove( v->i + index, v->i + index + 1, sizeof(v->i[0]) );
- v->i[index] = item;
- v->n += 1;
-}
-
-void
-qvector_remove( qvector_t* v, int index )
-{
- if (index < 0 || index >= v->n )
- return;
-
- memmove( v->i + index + 1, v->i + index, v->n - index - 1 );
- v->n -= 1;
-}
-
-void
-qvector_remove_n( qvector_t* v, int index, int count )
-{
- int end = index + count;
-
- if (index < 0 || index >= v->n || end <= index)
- return;
-
- if (end > v->n) {
- end = v->n;
- count = end - index;
- }
-
- memmove( v->i + index + count, v->i + index, v->n - index - count );
- v->n -= count;
-}
-
-
-/** HEXADECIMAL CHARACTER SEQUENCES
- **/
-
-static int
-hexdigit( int c )
-{
- unsigned d;
-
- d = (unsigned)(c - '0');
- if (d < 10) return d;
-
- d = (unsigned)(c - 'a');
- if (d < 6) return d+10;
-
- d = (unsigned)(c - 'A');
- if (d < 6) return d+10;
-
- return -1;
-}
-
-int
-hex2int( const uint8_t* hex, int len )
-{
- int result = 0;
- while (len > 0) {
- int c = hexdigit(*hex++);
- if (c < 0)
- return -1;
-
- result = (result << 4) | c;
- len --;
- }
- return result;
-}
-
-void
-int2hex( uint8_t* hex, int len, int val )
-{
- static const uint8_t hexchars[16] = "0123456789abcdef";
- while ( --len >= 0 )
- *hex++ = hexchars[(val >> (len*4)) & 15];
-}