• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
35 char*
vbufprint(char * buffer,char * buffer_end,const char * fmt,va_list args)36 vbufprint( 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 
50 char*
bufprint(char * buffer,char * end,const char * fmt,...)51 bufprint(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__
76 char*
bufprint_app_dir(char * buff,char * end)77 bufprint_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);
92 Fail:
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 
109 char*
bufprint_app_dir(char * buff,char * end)110 bufprint_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);
128 fail:
129     fprintf(stderr,"cannot locate application directory\n");
130     exit(1);
131     return end;
132 }
133 #elif defined _WIN32
134 char*
bufprint_app_dir(char * buff,char * end)135 bufprint_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
158 char*
bufprint_app_dir(char * buff,char * end)159 bufprint_app_dir(char*  buff, char*  end)
160 {
161     return bufprint(buff, end, ".");
162 }
163 #endif
164 
165 #define  _ANDROID_PATH   ".android"
166 
167 char*
bufprint_config_path(char * buff,char * end)168 bufprint_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 
192 char*
bufprint_config_file(char * buff,char * end,const char * suffix)193 bufprint_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 
201 char*
bufprint_temp_dir(char * buff,char * end)202 bufprint_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 
233 char*
bufprint_temp_file(char * buff,char * end,const char * suffix)234 bufprint_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