blob: 4626a0fed778280592af8aa5cb45305bf70ee86f [file] [log] [blame]
/* 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/bufprint.h"
#include "android/utils/path.h"
#include "android/utils/debug.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# include "windows.h"
# include "shlobj.h"
#else
# include <unistd.h>
# include <sys/stat.h>
#endif
#define D(...) VERBOSE_PRINT(init,__VA_ARGS__)
/** 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];
int len;
char* sep;
len = GetModuleFileName( 0, appDir, sizeof(appDir)-1 );
if (len == 0) {
fprintf(stderr, "PANIC CITY!!\n");
exit(1);
}
if (len >= (int)sizeof(appDir)) {
len = sizeof(appDir)-1;
appDir[len] = 0;
}
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
const char* home = getenv("ANDROID_SDK_HOME");
if (home != NULL) {
return bufprint(buff, end, "%s\\%s", home, _ANDROID_PATH );
} else {
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("ANDROID_SDK_HOME");
if (home == NULL)
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" );
strncpy(path, "C:\\Temp", sizeof(path) );
}
strncat( path, "\\AndroidEmulator", sizeof(path)-1 );
path_mkdir(path, 0744);
return bufprint(buff, end, "%s", path);
#else
char path[MAX_PATH];
const char* tmppath = getenv("ANDROID_TMP");
if (!tmppath) {
const char* user = getenv("USER");
if (user == NULL || user[0] == '\0')
user = "unknown";
snprintf(path, sizeof path, "/tmp/android-%s", user);
tmppath = path;
}
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;
}