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