10578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato/*
20578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato * Copyright (C) 2016 The Android Open Source Project
30578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato *
40578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato * Licensed under the Apache License, Version 2.0 (the "License");
50578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato * you may not use this file except in compliance with the License.
60578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato * You may obtain a copy of the License at
70578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato *
80578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato *      http://www.apache.org/licenses/LICENSE-2.0
90578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato *
100578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato * Unless required by applicable law or agreed to in writing, software
110578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato * distributed under the License is distributed on an "AS IS" BASIS,
120578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato * See the License for the specific language governing permissions and
140578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato * limitations under the License.
150578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato */
160578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
170578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato#include "adb.h"
180578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
190578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato#include "command.h"
200578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato#include "print.h"
210578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato#include "util.h"
220578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
230578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato#include <errno.h>
240578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato#include <string.h>
250578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato#include <stdlib.h>
260578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato#include <unistd.h>
270578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato#include <sys/types.h>
280578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato#include <sys/wait.h>
290578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato#include <limits.h>
300578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
310578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato#include <iostream>
320578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato#include <istream>
330578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato#include <streambuf>
340578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
350578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratousing namespace std;
360578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
370578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratostruct Buffer: public streambuf
380578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
390578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    Buffer(char* begin, size_t size);
400578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato};
410578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
420578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe OnoratoBuffer::Buffer(char* begin, size_t size)
430578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
440578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    this->setg(begin, begin, begin + size);
450578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
460578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
470578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoint
480578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratorun_adb(const char* first, ...)
490578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
500578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    Command cmd("adb");
510578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
520578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (first == NULL) {
530578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return 0;
540578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
550578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
560578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    cmd.AddArg(first);
570578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
580578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_list args;
590578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_start(args, first);
600578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    while (true) {
610578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        const char* arg = va_arg(args, char*);
620578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        if (arg == NULL) {
630578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            break;
640578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        }
650578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        cmd.AddArg(arg);
660578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
670578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_end(args);
680578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
690578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    return run_command(cmd);
700578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
710578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
720578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratostring
730578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoget_system_property(const string& name, int* err)
740578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
750578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    Command cmd("adb");
760578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    cmd.AddArg("shell");
770578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    cmd.AddArg("getprop");
780578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    cmd.AddArg(name);
790578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
800578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    return trim(get_command_output(cmd, err, false));
810578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
820578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
830578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
840578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratostatic uint64_t
850578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoread_varint(int fd, int* err, bool* done)
860578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
870578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    uint32_t bits = 0;
880578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    uint64_t result = 0;
890578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    while (true) {
900578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        uint8_t byte;
910578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        ssize_t amt = read(fd, &byte, 1);
920578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        if (amt == 0) {
930578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            *done = true;
940578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return result;
950578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        } else if (amt < 0) {
960578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return *err = errno;
970578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        }
980578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        result |= uint64_t(byte & 0x7F) << bits;
990578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        if ((byte & 0x80) == 0) {
1000578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return result;
1010578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        }
1020578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        bits += 7;
1030578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        if (bits > 64) {
1040578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            *err = -1;
1050578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return 0;
1060578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        }
1070578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
1080578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
1090578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
1100578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratostatic char*
1110578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoread_sized_buffer(int fd, int* err, size_t* resultSize)
1120578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
1130578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    bool done = false;
1140578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    uint64_t size = read_varint(fd, err, &done);
1150578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (*err != 0 || done) {
1160578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return NULL;
1170578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
1180578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (size == 0) {
1190578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        *resultSize = 0;
1200578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return NULL;
1210578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
1220578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    // 10 MB seems like a reasonable limit.
1230578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (size > 10*1024*1024) {
1240578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        print_error("result buffer too large: %llu", size);
1250578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return NULL;
1260578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
1270578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    char* buf = (char*)malloc(size);
1280578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (buf == NULL) {
1290578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        print_error("Can't allocate a buffer of size for test results: %llu", size);
1300578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return NULL;
1310578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
1320578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    int pos = 0;
1330578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    while (size - pos > 0) {
1340578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        ssize_t amt = read(fd, buf+pos, size-pos);
1350578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        if (amt == 0) {
1360578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            // early end of pipe
1370578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            print_error("Early end of pipe.");
1380578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            *err = -1;
1390578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            free(buf);
1400578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return NULL;
1410578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        } else if (amt < 0) {
1420578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            // error
1430578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            *err = errno;
1440578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            free(buf);
1450578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return NULL;
1460578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        }
1470578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        pos += amt;
1480578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
1490578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    *resultSize = (size_t)size;
1500578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    return buf;
1510578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
1520578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
1530578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratostatic int
1540578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoread_sized_proto(int fd, Message* message)
1550578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
1560578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    int err = 0;
1570578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    size_t size;
1580578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    char* buf = read_sized_buffer(fd, &err, &size);
1590578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (err != 0) {
1600578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        if (buf != NULL) {
1610578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            free(buf);
1620578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        }
1630578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return err;
1640578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    } else if (size == 0) {
1650578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        if (buf != NULL) {
1660578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            free(buf);
1670578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        }
1680578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return 0;
1690578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    } else if (buf == NULL) {
1700578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return -1;
1710578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
1720578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    Buffer buffer(buf, size);
1730578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    istream in(&buffer);
1740578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
1750578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    err = message->ParseFromIstream(&in) ? 0 : -1;
1760578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
1770578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    free(buf);
1780578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    return err;
1790578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
1800578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
1810578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratostatic int
1820578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoskip_bytes(int fd, ssize_t size, char* scratch, int scratchSize)
1830578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
1840578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    while (size > 0) {
1850578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        ssize_t amt = size < scratchSize ? size : scratchSize;
1860578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        fprintf(stderr, "skipping %lu/%ld bytes\n", size, amt);
1870578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        amt = read(fd, scratch, amt);
1880578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        if (amt == 0) {
1890578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            // early end of pipe
1900578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            print_error("Early end of pipe.");
1910578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return -1;
1920578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        } else if (amt < 0) {
1930578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            // error
1940578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return errno;
1950578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        }
1960578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        size -= amt;
1970578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
1980578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    return 0;
1990578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
2000578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
2010578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratostatic int
2020578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoskip_unknown_field(int fd, uint64_t tag, char* scratch, int scratchSize) {
2030578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    bool done;
2040578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    int err;
2050578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    uint64_t size;
2060578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    switch (tag & 0x7) {
2070578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        case 0: // varint
2080578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            read_varint(fd, &err, &done);
2090578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            if (err != 0) {
2100578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                return err;
2110578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            } else if (done) {
2120578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                return -1;
2130578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            } else {
2140578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                return 0;
2150578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            }
2160578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        case 1:
2170578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return skip_bytes(fd, 8, scratch, scratchSize);
2180578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        case 2:
2190578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            size = read_varint(fd, &err, &done);
2200578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            if (err != 0) {
2210578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                return err;
2220578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            } else if (done) {
2230578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                return -1;
2240578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            }
2250578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            if (size > INT_MAX) {
2260578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                // we'll be here a long time but this keeps it from overflowing
2270578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                return -1;
2280578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            }
2290578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return skip_bytes(fd, (ssize_t)size, scratch, scratchSize);
2300578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        case 5:
2310578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return skip_bytes(fd, 4, scratch, scratchSize);
2320578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        default:
2330578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            print_error("bad wire type for tag 0x%lx\n", tag);
2340578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return -1;
2350578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
2360578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
2370578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
2380578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratostatic int
2390578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoread_instrumentation_results(int fd, char* scratch, int scratchSize,
2400578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        InstrumentationCallbacks* callbacks)
2410578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
2420578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    bool done = false;
2430578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    int err = 0;
2440578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    string result;
2450578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    while (true) {
2460578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        uint64_t tag = read_varint(fd, &err, &done);
2470578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        if (done) {
2480578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            // Done reading input (this is the only place that a stream end isn't an error).
2490578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return 0;
2500578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        } else if (err != 0) {
2510578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return err;
2520578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        } else if (tag == 0xa) { // test_status
2530578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            TestStatus status;
2540578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            err = read_sized_proto(fd, &status);
2550578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            if (err != 0) {
2560578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                return err;
2570578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            }
2580578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            callbacks->OnTestStatus(status);
2590578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        } else if (tag == 0x12) { // session_status
2600578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            SessionStatus status;
2610578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            err = read_sized_proto(fd, &status);
2620578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            if (err != 0) {
2630578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                return err;
2640578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            }
2650578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            callbacks->OnSessionStatus(status);
2660578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        } else {
2670578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            err = skip_unknown_field(fd, tag, scratch, scratchSize);
2680578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            if (err != 0) {
2690578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                return err;
2700578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            }
2710578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        }
2720578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
2730578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    return 0;
2740578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
2750578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
2760578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoint
2770578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratorun_instrumentation_test(const string& packageName, const string& runner, const string& className,
2780578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        InstrumentationCallbacks* callbacks)
2790578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
2800578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    Command cmd("adb");
2810578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    cmd.AddArg("shell");
2820578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    cmd.AddArg("am");
2830578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    cmd.AddArg("instrument");
2840578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    cmd.AddArg("-w");
2850578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    cmd.AddArg("-m");
286164e7967b1f47586338805e2ebfdee02a5de85dbMakoto Onuki    const int classLen = className.length();
287164e7967b1f47586338805e2ebfdee02a5de85dbMakoto Onuki    if (classLen > 0) {
288164e7967b1f47586338805e2ebfdee02a5de85dbMakoto Onuki        if (classLen > 1 && className[classLen - 1] == '.') {
289164e7967b1f47586338805e2ebfdee02a5de85dbMakoto Onuki            cmd.AddArg("-e");
290164e7967b1f47586338805e2ebfdee02a5de85dbMakoto Onuki            cmd.AddArg("package");
291164e7967b1f47586338805e2ebfdee02a5de85dbMakoto Onuki
292164e7967b1f47586338805e2ebfdee02a5de85dbMakoto Onuki            // "am" actually accepts without removing the last ".", but for cleanlines...
293164e7967b1f47586338805e2ebfdee02a5de85dbMakoto Onuki            cmd.AddArg(className.substr(0, classLen - 1));
294164e7967b1f47586338805e2ebfdee02a5de85dbMakoto Onuki        } else {
295164e7967b1f47586338805e2ebfdee02a5de85dbMakoto Onuki            cmd.AddArg("-e");
296164e7967b1f47586338805e2ebfdee02a5de85dbMakoto Onuki            cmd.AddArg("class");
297164e7967b1f47586338805e2ebfdee02a5de85dbMakoto Onuki            cmd.AddArg(className);
298164e7967b1f47586338805e2ebfdee02a5de85dbMakoto Onuki        }
2990578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
3000578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    cmd.AddArg(packageName + "/" + runner);
3010578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
3020578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    print_command(cmd);
3030578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
3040578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    int fds[2];
305c7edf078f92c7ce083f8c243a79f8aecdfff4ac1Chih-Hung Hsieh    if (0 != pipe(fds)) {
306c7edf078f92c7ce083f8c243a79f8aecdfff4ac1Chih-Hung Hsieh        return errno;
307c7edf078f92c7ce083f8c243a79f8aecdfff4ac1Chih-Hung Hsieh    }
3080578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
3090578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    pid_t pid = fork();
3100578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
3110578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (pid == -1) {
3120578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        // fork error
3130578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return errno;
3140578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    } else if (pid == 0) {
3150578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        // child
3160578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        while ((dup2(fds[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {}
3170578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        close(fds[1]);
3180578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        close(fds[0]);
3190578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        const char* prog = cmd.GetProg();
3200578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        char* const* argv = cmd.GetArgv();
3210578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        char* const* env = cmd.GetEnv();
32231617e3b8ff01bb016446a0d2cb687b25aee42c6Joe Onorato        exec_with_path_search(prog, argv, env);
3230578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        print_error("Unable to run command: %s", prog);
3240578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        exit(1);
3250578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    } else {
3260578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        // parent
3270578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        close(fds[1]);
3280578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        string result;
3290578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        const int size = 16*1024;
3300578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        char* buf = (char*)malloc(size);
3310578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        int err = read_instrumentation_results(fds[0], buf, size, callbacks);
3320578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        free(buf);
3330578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        int status;
3340578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        waitpid(pid, &status, 0);
3350578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        if (err != 0) {
3360578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return err;
3370578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        }
3380578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        if (WIFEXITED(status)) {
3390578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return WEXITSTATUS(status);
3400578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        } else {
3410578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return -1;
3420578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        }
3430578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
3440578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
3450578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
3460578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato/**
3470578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato * Get the second to last bundle in the args list. Stores the last name found
3480578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato * in last. If the path is not found or if the args list is empty, returns NULL.
3490578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato */
3500578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratostatic const ResultsBundleEntry *
3510578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratofind_penultimate_entry(const ResultsBundle& bundle, va_list args)
3520578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
3530578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    const ResultsBundle* b = &bundle;
3540578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    const char* arg = va_arg(args, char*);
3550578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    while (arg) {
3560578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        string last = arg;
3570578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        arg = va_arg(args, char*);
3580578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        bool found = false;
3590578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        for (int i=0; i<b->entries_size(); i++) {
3600578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            const ResultsBundleEntry& e = b->entries(i);
3610578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            if (e.key() == last) {
3620578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                if (arg == NULL) {
3630578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                    return &e;
3640578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                } else if (e.has_value_bundle()) {
3650578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                    b = &e.value_bundle();
3660578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                    found = true;
3670578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato                }
3680578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            }
3690578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        }
3700578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        if (!found) {
3710578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return NULL;
3720578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        }
3730578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        if (arg == NULL) {
3740578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato            return NULL;
3750578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        }
3760578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
3770578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    return NULL;
3780578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
3790578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
3800578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratostring
3810578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoget_bundle_string(const ResultsBundle& bundle, bool* found, ...)
3820578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
3830578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_list args;
3840578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_start(args, found);
3850578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    const ResultsBundleEntry* entry = find_penultimate_entry(bundle, args);
3860578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_end(args);
3870578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (entry == NULL) {
3880578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        *found = false;
3890578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return string();
3900578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
3910578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (entry->has_value_string()) {
3920578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        *found = true;
3930578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return entry->value_string();
3940578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
3950578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    *found = false;
3960578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    return string();
3970578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
3980578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
3990578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoint32_t
4000578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoget_bundle_int(const ResultsBundle& bundle, bool* found, ...)
4010578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
4020578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_list args;
4030578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_start(args, found);
4040578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    const ResultsBundleEntry* entry = find_penultimate_entry(bundle, args);
4050578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_end(args);
4060578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (entry == NULL) {
4070578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        *found = false;
4080578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return 0;
4090578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
4100578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (entry->has_value_int()) {
4110578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        *found = true;
4120578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return entry->value_int();
4130578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
4140578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    *found = false;
4150578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    return 0;
4160578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
4170578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
4180578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratofloat
4190578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoget_bundle_float(const ResultsBundle& bundle, bool* found, ...)
4200578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
4210578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_list args;
4220578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_start(args, found);
4230578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    const ResultsBundleEntry* entry = find_penultimate_entry(bundle, args);
4240578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_end(args);
4250578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (entry == NULL) {
4260578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        *found = false;
4270578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return 0;
4280578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
4290578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (entry->has_value_float()) {
4300578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        *found = true;
4310578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return entry->value_float();
4320578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
4330578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    *found = false;
4340578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    return 0;
4350578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
4360578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
4370578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratodouble
4380578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoget_bundle_double(const ResultsBundle& bundle, bool* found, ...)
4390578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
4400578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_list args;
4410578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_start(args, found);
4420578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    const ResultsBundleEntry* entry = find_penultimate_entry(bundle, args);
4430578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_end(args);
4440578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (entry == NULL) {
4450578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        *found = false;
4460578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return 0;
4470578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
4480578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (entry->has_value_double()) {
4490578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        *found = true;
4500578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return entry->value_double();
4510578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
4520578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    *found = false;
4530578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    return 0;
4540578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
4550578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
4560578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoint64_t
4570578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onoratoget_bundle_long(const ResultsBundle& bundle, bool* found, ...)
4580578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato{
4590578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_list args;
4600578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_start(args, found);
4610578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    const ResultsBundleEntry* entry = find_penultimate_entry(bundle, args);
4620578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    va_end(args);
4630578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (entry == NULL) {
4640578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        *found = false;
4650578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return 0;
4660578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
4670578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    if (entry->has_value_long()) {
4680578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        *found = true;
4690578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato        return entry->value_long();
4700578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    }
4710578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    *found = false;
4720578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato    return 0;
4730578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato}
4740578cbc6c527bc09a38a0fcd8b9642c25c8ea023Joe Onorato
475