/* Probe the filesystem to check if an emulator executable named like
 * <progDir>/<prefix><arch> exists.
 *
 * |progDir| is an optional program directory. If NULL, the executable
 * will be searched in the current directory.
 * |variant| is an optional variant. If not NULL, then a name like
 * 'emulator-<variant>-<archSuffix>' will be searched, instead of
 * 'emulator-<archSuffix>'.
 * |archSuffix| is an architecture-specific suffix, like "arm", or 'x86"
 * If |search_for_64bit_emulator| is true, lookup for 64-bit emulator first,
 * then the 32-bit version.
 * If |try_current_path|, try to look into the current path if no
 * executable was found under |progDir|.
 * On success, returns the path of the executable (string must be freed by
 * the caller) and sets |*is_64bit| to indicate whether the binary is a
 * 64-bit executable. On failure, return NULL.
 */
static char*
probeTargetEmulatorPath(const char* progDir,
                        const char* variant,
                        const char* archSuffix,
                        bool search_for_64bit_emulator,
                        bool try_current_path,
                        bool* is_64bit)
{
    char path[PATH_MAX], *pathEnd = path + sizeof(path), *p;

    static const char kEmulatorPrefix[] = "emulator-";
    static const char kEmulator64Prefix[] = "emulator64-";
#ifdef _WIN32
    const char kExeExtension[] = ".exe";
#else
    const char kExeExtension[] = "";
#endif

    // First search for the 64-bit emulator binary.
    if (search_for_64bit_emulator) {
        p = bufprint_emulatorName(path,
                                  pathEnd,
                                  progDir,
                                  kEmulator64Prefix,
                                  variant,
                                  archSuffix,
                                  kExeExtension);
        D("Probing program: %s\n", path);
        if (p < pathEnd && path_exists(path)) {
            *is_64bit = true;
            return strdup(path);
        }
    }

    // Then for the 32-bit one.
    p = bufprint_emulatorName(path,
                                pathEnd,
                                progDir,
                                kEmulatorPrefix,
                                variant,
                                archSuffix,
                                kExeExtension);
    D("Probing program: %s\n", path);
    if (p < pathEnd && path_exists(path)) {
        *is_64bit = false;
        return strdup(path);
    }

    // Not found, try in the current path then
    if (try_current_path) {
        char* result;

        if (search_for_64bit_emulator) {
            p = bufprint_emulatorName(path,
                                      pathEnd,
                                      NULL,
                                      kEmulator64Prefix,
                                      variant,
                                      archSuffix,
                                      kExeExtension);
            if (p < pathEnd) {
                D("Probing path for: %s\n", path);
                result = path_search_exec(path);
                if (result) {
                    *is_64bit = true;
                    return result;
                }
            }
        }

        p = bufprint_emulatorName(path,
                                    pathEnd,
                                    NULL,
                                    kEmulatorPrefix,
                                    variant,
                                    archSuffix,
                                    kExeExtension);
        if (p < pathEnd) {
            D("Probing path for: %s\n", path);
            result = path_search_exec(path);
            if (result) {
                *is_64bit = false;
                return result;
            }
        }
    }

    return NULL;
}
/* Find the target-specific emulator binary. This will be something
 * like  <programDir>/emulator-<targetArch>, where <programDir> is
 * the directory of the current program.
 */
static char*
getTargetEmulatorPath(const char* progName, const char* avdArch, const int force_32bit)
{
    char*  progDir;
    char   path[PATH_MAX], *pathEnd=path+sizeof(path), *p;
    const char* emulatorPrefix = "emulator-";
    const char* emulator64Prefix = "emulator64-";
#ifdef _WIN32
    const char* exeExt = ".exe";
    /* ToDo: currently amd64-mingw32msvc-gcc doesn't work (http://b/issue?id=5949152)
             which prevents us from generating 64-bit emulator for Windows */
    int search_for_64bit_emulator = 0;
#else
    const char* exeExt = "";
    int search_for_64bit_emulator = !force_32bit && getHostOSBitness() == 64;
#endif

    /* Get program's directory name in progDir */
    path_split(progName, &progDir, NULL);

    if (search_for_64bit_emulator) {
        /* Find 64-bit emulator first */
        p = bufprint(path, pathEnd, "%s/%s%s%s", progDir, emulator64Prefix, avdArch, exeExt);
        if (p >= pathEnd) {
            APANIC("Path too long: %s\n", progName);
        }
        if (path_exists(path)) {
            free(progDir);
            return strdup(path);
        }
    }

    /* Find 32-bit emulator */
    p = bufprint(path, pathEnd, "%s/%s%s%s", progDir, emulatorPrefix, avdArch, exeExt);
    free(progDir);
    if (p >= pathEnd) {
        APANIC("Path too long: %s\n", progName);
    }

    if (path_exists(path)) {
        return strdup(path);
    }

    /* Mmm, the file doesn't exist, If there is no slash / backslash
     * in our path, we're going to try to search it in our path.
     */
#ifdef _WIN32
    if (strchr(progName, '/') == NULL && strchr(progName, '\\') == NULL) {
#else
    if (strchr(progName, '/') == NULL) {
#endif
        if (search_for_64bit_emulator) {
           p = bufprint(path, pathEnd, "%s%s%s", emulator64Prefix, avdArch, exeExt);
           if (p < pathEnd) {
               char*  resolved = path_search_exec(path);
               if (resolved != NULL)
                   return resolved;
           }
        }

        p = bufprint(path, pathEnd, "%s%s%s", emulatorPrefix, avdArch, exeExt);
        if (p < pathEnd) {
            char*  resolved = path_search_exec(path);
            if (resolved != NULL)
                return resolved;
        }
    }

    /* Otherwise, the program is missing */
    APANIC("Missing arch-specific emulator program: %s\n", path);
    return NULL;
}

/* return 1 iff <path>/<filename> exists */
static int
probePathForFile(const char* path, const char* filename)
{
    char  temp[PATH_MAX], *p=temp, *end=p+sizeof(temp);
    p = bufprint(temp, end, "%s/%s", path, filename);
    D("Probing for: %s\n", temp);
    return (p < end && path_exists(temp));
}