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