bufprint.c revision 2779beecc7410f29102125e87e8174597acb2fe5
1/* Copyright (C) 2007-2008 The Android Open Source Project 2** 3** This software is licensed under the terms of the GNU General Public 4** License version 2, as published by the Free Software Foundation, and 5** may be copied, distributed, and modified under those terms. 6** 7** This program is distributed in the hope that it will be useful, 8** but WITHOUT ANY WARRANTY; without even the implied warranty of 9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10** GNU General Public License for more details. 11*/ 12 13#include "android/utils/bufprint.h" 14#include "android/utils/path.h" 15#include "android/utils/debug.h" 16#include <stdio.h> 17#include <stdlib.h> 18#include <string.h> 19 20#ifdef _WIN32 21# define WIN32_LEAN_AND_MEAN 22# include "windows.h" 23# include "shlobj.h" 24#else 25# include <unistd.h> 26# include <sys/stat.h> 27#endif 28 29#define D(...) VERBOSE_PRINT(init,__VA_ARGS__) 30 31 32/** USEFUL STRING BUFFER FUNCTIONS 33 **/ 34 35char* 36vbufprint( char* buffer, 37 char* buffer_end, 38 const char* fmt, 39 va_list args ) 40{ 41 int len = vsnprintf( buffer, buffer_end - buffer, fmt, args ); 42 if (len < 0 || buffer+len >= buffer_end) { 43 if (buffer < buffer_end) 44 buffer_end[-1] = 0; 45 return buffer_end; 46 } 47 return buffer + len; 48} 49 50char* 51bufprint(char* buffer, char* end, const char* fmt, ... ) 52{ 53 va_list args; 54 char* result; 55 56 va_start(args, fmt); 57 result = vbufprint(buffer, end, fmt, args); 58 va_end(args); 59 return result; 60} 61 62/** USEFUL DIRECTORY SUPPORT 63 ** 64 ** bufprint_app_dir() returns the directory where the emulator binary is located 65 ** 66 ** get_android_home() returns a user-specific directory where the emulator will 67 ** store its writable data (e.g. config files, profiles, etc...). 68 ** on Unix, this is $HOME/.android, on Windows, this is something like 69 ** "%USERPROFILE%/Local Settings/AppData/Android" on XP, and something different 70 ** on Vista. 71 ** 72 ** both functions return a string that must be freed by the caller 73 **/ 74 75#ifdef __linux__ 76char* 77bufprint_app_dir(char* buff, char* end) 78{ 79 char path[1024]; 80 int len; 81 char* x; 82 83 len = readlink("/proc/self/exe", path, sizeof(path)); 84 if (len <= 0 || len >= (int)sizeof(path)) goto Fail; 85 path[len] = 0; 86 87 x = strrchr(path, '/'); 88 if (x == 0) goto Fail; 89 *x = 0; 90 91 return bufprint(buff, end, "%s", path); 92Fail: 93 fprintf(stderr,"cannot locate application directory\n"); 94 exit(1); 95 return end; 96} 97 98#elif defined(__APPLE__) 99/* the following hack is needed in order to build with XCode 3.1 100 * don't ask me why, but it seems that there were changes in the 101 * GCC compiler that we don't have in our pre-compiled version 102 */ 103#ifndef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ 104#define __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ MAC_OS_X_VERSION_10_4 105#endif 106#import <Carbon/Carbon.h> 107#include <unistd.h> 108 109char* 110bufprint_app_dir(char* buff, char* end) 111{ 112 ProcessSerialNumber psn; 113 CFDictionaryRef dict; 114 CFStringRef value; 115 char s[PATH_MAX]; 116 char* x; 117 118 GetCurrentProcess(&psn); 119 dict = ProcessInformationCopyDictionary(&psn, 0xffffffff); 120 value = (CFStringRef)CFDictionaryGetValue(dict, 121 CFSTR("CFBundleExecutable")); 122 CFStringGetCString(value, s, PATH_MAX - 1, kCFStringEncodingUTF8); 123 x = strrchr(s, '/'); 124 if (x == 0) goto fail; 125 *x = 0; 126 127 return bufprint(buff, end, "%s", s); 128fail: 129 fprintf(stderr,"cannot locate application directory\n"); 130 exit(1); 131 return end; 132} 133#elif defined _WIN32 134char* 135bufprint_app_dir(char* buff, char* end) 136{ 137 char appDir[MAX_PATH]; 138 int len; 139 char* sep; 140 141 len = GetModuleFileName( 0, appDir, sizeof(appDir)-1 ); 142 if (len == 0) { 143 fprintf(stderr, "PANIC CITY!!\n"); 144 exit(1); 145 } 146 if (len >= (int)sizeof(appDir)) { 147 len = sizeof(appDir)-1; 148 appDir[len] = 0; 149 } 150 151 sep = strrchr(appDir, '\\'); 152 if (sep) 153 *sep = 0; 154 155 return bufprint(buff, end, "%s", appDir); 156} 157#else 158char* 159bufprint_app_dir(char* buff, char* end) 160{ 161 return bufprint(buff, end, "."); 162} 163#endif 164 165#define _ANDROID_PATH ".android" 166 167char* 168bufprint_config_path(char* buff, char* end) 169{ 170#ifdef _WIN32 171 const char* home = getenv("ANDROID_SDK_HOME"); 172 if (home != NULL) { 173 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 const char* tmppath = getenv("ANDROID_TMP"); 219 if (!tmppath) { 220 tmppath = "/tmp/android"; 221 } 222 mkdir(tmppath, 0744); 223 return bufprint(buff, end, "%s", tmppath ); 224#endif 225} 226 227char* 228bufprint_temp_file(char* buff, char* end, const char* suffix) 229{ 230 char* p; 231 p = bufprint_temp_dir(buff, end); 232 p = bufprint(p, end, PATH_SEP "%s", suffix); 233 return p; 234} 235 236