Home | History | Annotate | Download | only in utils
      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*
     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*
     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*
     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*
    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*
    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*
    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*
    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*
    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*
    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*
    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