190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber/* Copyright (C) 2007-2008 The Android Open Source Project 2f71323e297a928af368937089d3ed71239786f86Andreas Huber** 390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber** This software is licensed under the terms of the GNU General Public 4f71323e297a928af368937089d3ed71239786f86Andreas Huber** License version 2, as published by the Free Software Foundation, and 5f71323e297a928af368937089d3ed71239786f86Andreas Huber** may be copied, distributed, and modified under those terms. 6f71323e297a928af368937089d3ed71239786f86Andreas Huber** 7f71323e297a928af368937089d3ed71239786f86Andreas Huber** This program is distributed in the hope that it will be useful, 8f71323e297a928af368937089d3ed71239786f86Andreas Huber** but WITHOUT ANY WARRANTY; without even the implied warranty of 990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber** GNU General Public License for more details. 1190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber*/ 1290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 1390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include "android/utils/bufprint.h" 1490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include "android/utils/path.h" 1590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include "android/utils/debug.h" 1690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include <stdio.h> 1790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include <stdlib.h> 1890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include <string.h> 1990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 2090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#ifdef _WIN32 2190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# define WIN32_LEAN_AND_MEAN 2290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# include "windows.h" 2390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# include "shlobj.h" 2490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#else 2590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# include <unistd.h> 2690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber# include <sys/stat.h> 2790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif 2890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 2990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define D(...) VERBOSE_PRINT(init,__VA_ARGS__) 3090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 3190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 3290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber/** USEFUL STRING BUFFER FUNCTIONS 3390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber **/ 3490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 3590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberchar* 3690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Hubervbufprint( char* buffer, 3790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber char* buffer_end, 3890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber const char* fmt, 3990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber va_list args ) 4090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 4190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int len = vsnprintf( buffer, buffer_end - buffer, fmt, args ); 4290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (len < 0 || buffer+len >= buffer_end) { 4390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (buffer < buffer_end) 4490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber buffer_end[-1] = 0; 4590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return buffer_end; 4690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 4790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return buffer + len; 4890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 4990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 5090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberchar* 5190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberbufprint(char* buffer, char* end, const char* fmt, ... ) 5290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 5390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber va_list args; 5490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber char* result; 5590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 5690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber va_start(args, fmt); 5790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber result = vbufprint(buffer, end, fmt, args); 5890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber va_end(args); 5990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return result; 6090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 6190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 6290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber/** USEFUL DIRECTORY SUPPORT 6390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber ** 6490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber ** bufprint_app_dir() returns the directory where the emulator binary is located 6590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber ** 6690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber ** get_android_home() returns a user-specific directory where the emulator will 6790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber ** store its writable data (e.g. config files, profiles, etc...). 6890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber ** on Unix, this is $HOME/.android, on Windows, this is something like 6990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber ** "%USERPROFILE%/Local Settings/AppData/Android" on XP, and something different 7090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber ** on Vista. 7190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber ** 72538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber ** both functions return a string that must be freed by the caller 7390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber **/ 7490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 7590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#ifdef __linux__ 7690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberchar* 7790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberbufprint_app_dir(char* buff, char* end) 7890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 7990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber char path[1024]; 8090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int len; 8190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber char* x; 8290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 8390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber len = readlink("/proc/self/exe", path, sizeof(path)); 8490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (len <= 0 || len >= (int)sizeof(path)) goto Fail; 8590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber path[len] = 0; 8690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 8790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber x = strrchr(path, '/'); 8890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (x == 0) goto Fail; 8990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber *x = 0; 9090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 9190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return bufprint(buff, end, "%s", path); 9290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas HuberFail: 9390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber fprintf(stderr,"cannot locate application directory\n"); 9490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber exit(1); 9590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return end; 9690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 9790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 9890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#elif defined(__APPLE__) 9990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber/* the following hack is needed in order to build with XCode 3.1 10090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber * don't ask me why, but it seems that there were changes in the 10190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber * GCC compiler that we don't have in our pre-compiled version 10290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber */ 10390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#ifndef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ 10490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ MAC_OS_X_VERSION_10_4 10590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif 10690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#import <Carbon/Carbon.h> 10790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#include <unistd.h> 10890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 10990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberchar* 11090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberbufprint_app_dir(char* buff, char* end) 11190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 11290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber ProcessSerialNumber psn; 11390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber CFDictionaryRef dict; 11490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber CFStringRef value; 11590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber char s[PATH_MAX]; 11690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber char* x; 11790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 11890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber GetCurrentProcess(&psn); 11990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber dict = ProcessInformationCopyDictionary(&psn, 0xffffffff); 12090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber value = (CFStringRef)CFDictionaryGetValue(dict, 12190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber CFSTR("CFBundleExecutable")); 12290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber CFStringGetCString(value, s, PATH_MAX - 1, kCFStringEncodingUTF8); 12390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber x = strrchr(s, '/'); 12490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (x == 0) goto fail; 12590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber *x = 0; 12690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 12790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return bufprint(buff, end, "%s", s); 12890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberfail: 12990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber fprintf(stderr,"cannot locate application directory\n"); 13090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber exit(1); 13190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return end; 13290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 13390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#elif defined _WIN32 13490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberchar* 13590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberbufprint_app_dir(char* buff, char* end) 13690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 13790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber char appDir[MAX_PATH]; 13890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber int len; 13990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber char* sep; 14090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 14190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber len = GetModuleFileName( 0, appDir, sizeof(appDir)-1 ); 14290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (len == 0) { 14390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber fprintf(stderr, "PANIC CITY!!\n"); 14490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber exit(1); 14590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 14690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (len >= (int)sizeof(appDir)) { 14790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber len = sizeof(appDir)-1; 14890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber appDir[len] = 0; 14990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber } 15090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 15190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber sep = strrchr(appDir, '\\'); 15290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (sep) 15390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber *sep = 0; 15490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 15590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return bufprint(buff, end, "%s", appDir); 15690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 15790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#else 15890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberchar* 15990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberbufprint_app_dir(char* buff, char* end) 16090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 16190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return bufprint(buff, end, "."); 16290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber} 16390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#endif 16490d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 16590d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#define _ANDROID_PATH ".android" 16690d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber 16790d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberchar* 16890d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huberbufprint_config_path(char* buff, char* end) 16990d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber{ 17090d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber#ifdef _WIN32 17190d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber const char* home = getenv("ANDROID_SDK_HOME"); 17290d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber if (home != NULL) { 17390d3ed91ae9228e1c8bab561b6138d4cb8c1e4fdAndreas Huber return bufprint(buff, end, "%s\\%s", home, _ANDROID_PATH ); 174 } else { 175 char path[MAX_PATH]; 176 177 SHGetFolderPath( NULL, CSIDL_PROFILE, 178 NULL, 0, path); 179 180 return bufprint(buff, end, "%s\\%s", path, _ANDROID_PATH ); 181 } 182#else 183 const char* home = getenv("ANDROID_SDK_HOME"); 184 if (home == NULL) 185 home = getenv("HOME"); 186 if (home == NULL) 187 home = "/tmp"; 188 return bufprint(buff, end, "%s/%s", home, _ANDROID_PATH ); 189#endif 190} 191 192char* 193bufprint_config_file(char* buff, char* end, const char* suffix) 194{ 195 char* p; 196 p = bufprint_config_path(buff, end); 197 p = bufprint(p, end, PATH_SEP "%s", suffix); 198 return p; 199} 200 201char* 202bufprint_temp_dir(char* buff, char* end) 203{ 204#ifdef _WIN32 205 char path[MAX_PATH]; 206 DWORD retval; 207 208 retval = GetTempPath( sizeof(path), path ); 209 if (retval > sizeof(path) || retval == 0) { 210 D( "can't locate TEMP directory" ); 211 strncpy(path, "C:\\Temp", sizeof(path) ); 212 } 213 strncat( path, "\\AndroidEmulator", sizeof(path)-1 ); 214 path_mkdir(path, 0744); 215 216 return bufprint(buff, end, "%s", path); 217#else 218 char path[MAX_PATH]; 219 const char* tmppath = getenv("ANDROID_TMP"); 220 if (!tmppath) { 221 const char* user = getenv("USER"); 222 if (user == NULL || user[0] == '\0') 223 user = "unknown"; 224 225 snprintf(path, sizeof path, "/tmp/android-%s", user); 226 tmppath = path; 227 } 228 mkdir(tmppath, 0744); 229 return bufprint(buff, end, "%s", tmppath ); 230#endif 231} 232 233char* 234bufprint_temp_file(char* buff, char* end, const char* suffix) 235{ 236 char* p; 237 p = bufprint_temp_dir(buff, end); 238 p = bufprint(p, end, PATH_SEP "%s", suffix); 239 return p; 240} 241 242