Bug 827999 - Use SD card for test root if present. r=wlach

This commit is contained in:
Mark Cote 2013-02-07 23:04:40 -05:00
Родитель df23111db7
Коммит 2ac5103443
10 изменённых файлов: 240 добавлений и 71 удалений

Просмотреть файл

@ -6,6 +6,7 @@ SRCS=\
src/Buffer.cpp \
src/BufferedSocket.cpp \
src/CommandEventHandler.cpp \
src/Config.cpp \
src/EventHandler.cpp \
src/Hash.cpp \
src/HeartbeatEventHandler.cpp \

Просмотреть файл

@ -3,6 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "CommandEventHandler.h"
#include "Config.h"
#include "Hash.h"
#include "Logger.h"
#include "Logging.h"
@ -235,32 +236,6 @@ CommandEventHandler::sendPrompt()
}
std::string
CommandEventHandler::readTextFile(std::string path)
{
const char *cpath = path.c_str();
FILE *fp = fopen(cpath, "r");
if (!fp)
{
fprintf(stderr, "Error on fopen: %s, with mode r.\n", cpath);
return agentWarn("Cannot open file");
}
char buffer[BUFSIZE];
std::ostringstream output;
while (fgets(buffer, BUFSIZE, fp))
output << std::string(buffer);
fclose(fp);
std::string str = output.str();
if (str.size())
str.erase(str.size() - 1);
return str;
}
int
CommandEventHandler::getFirstIntPos(char *str, int limit)
{
@ -277,6 +252,7 @@ CommandEventHandler::getFirstIntPos(char *str, int limit)
std::string
CommandEventHandler::joinPaths(std::string p1, std::string p2)
{
// FIXME: depends on POSIX-like paths
if (p1[p1.length() - 1] == '/')
p1 = p1.substr(0, p1.length() - 1);
if (p2[0] == '/')
@ -515,9 +491,12 @@ CommandEventHandler::uptime()
std::string
CommandEventHandler::uptimemillis()
{
std::string uptime_file = readTextFile("/proc/uptime");
std::string uptimeStr;
if (!readTextFile("/proc/uptime", uptimeStr))
return agentWarn("could not read /proc/uptime");
double uptime;
sscanf(&uptime_file[0], "%lf", &uptime);
sscanf(&uptimeStr[0], "%lf", &uptime);
uptime *= 1000;
std::ostringstream out;
out << (int) uptime;
@ -529,7 +508,10 @@ CommandEventHandler::uptimemillis()
std::string
CommandEventHandler::screen()
{
return readTextFile("/sys/devices/virtual/graphics/fb0/modes");
std::string out;
if (!readTextFile("/sys/devices/virtual/graphics/fb0/modes", out))
return agentWarn("could not read screen mode");
return out;
}
@ -557,14 +539,16 @@ CommandEventHandler::memory()
std::string
CommandEventHandler::power()
{
std::string capacity, status;
if (!readTextFile("/sys/class/power_supply/battery/capacity", capacity))
return agentWarn("could not read battery capacity");
if (!readTextFile("/sys/class/power_supply/battery/status", status))
return agentWarn("could not read battery status");
std::ostringstream ret;
ret << "Power status:" << ENDL;
ret << "\tCurrent %: ";
ret << readTextFile("/sys/class/power_supply/battery/capacity");
ret << "\tStatus: ";
ret << readTextFile("/sys/class/power_supply/battery/status");
ret << "\tCurrent %: " << capacity;
ret << "\tStatus: " << status;
return ret.str();
}
@ -687,7 +671,8 @@ CommandEventHandler::rebt(std::vector<std::string>& args)
// store callback IP and PORT in REBOOT_FILE, if specified
if (args.size() == 2)
{
FILE *f = fopen(REBOOT_FILE, "w");
FILE *f = fopen(joinPaths(Config::instance()->mTestRoot,
REBOOT_FILE).c_str(), "w");
if (!f)
return agentWarn("Could not write to reboot callback file");
fprintf(f, "%s %s\n", args[0].c_str(), args[1].c_str());
@ -863,7 +848,7 @@ CommandEventHandler::setutime(std::vector<std::string>& args)
std::string
CommandEventHandler::testroot(std::vector<std::string>& args)
{
return std::string(TESTROOT);
return Config::instance()->mTestRoot;
}

Просмотреть файл

@ -10,9 +10,7 @@
#include "BufferedSocket.h"
#include "EventHandler.h"
#define TESTROOT "/data/local"
#define REBOOT_FILE "/data/local/.SUTAgent_rebt"
#define REBOOT_FILE ".SUTAgent_rebt"
class CommandEventHandler: public EventHandler
@ -43,7 +41,6 @@ private:
void sendPrompt();
void do_rmdr(std::string path, std::ostringstream &out);
std::string readTextFile(std::string path);
int getFirstIntPos(char *str, int limit);
std::string joinPaths(std::string p1, std::string p2);
bool checkDataEventHandler(PRPollDesc desc);

87
src/Config.cpp Normal file
Просмотреть файл

@ -0,0 +1,87 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Config.h"
#include <iostream>
#include <prerror.h>
#include <prio.h>
#include <string.h>
#include "Shell.h"
Config* Config::mInstance = NULL;
Config::Config()
{
}
Config*
Config::instance()
{
if (!mInstance)
mInstance = new Config();
return mInstance;
}
void
Config::setTestRoot(std::string testRoot)
{
if (testRoot.empty())
setDefaultTestRoot();
else
mTestRoot = testRoot;
PRFileInfo info;
PRStatus st = PR_GetFileInfo(mTestRoot.c_str(), &info);
if (st == PR_SUCCESS)
{
if (info.type != PR_FILE_DIRECTORY)
std::cerr << "Test root " << mTestRoot
<< " exists but is not a directory." << std::endl;
return;
}
if (PR_MkDir(mTestRoot.c_str(), 0777) == PR_FAILURE)
{
std::cerr << "Failed to create test root " << mTestRoot
<< ": " << PR_GetError() << std::endl;
}
}
void
Config::setDefaultTestRoot()
{
// FIXME: POSIX specific
std::string mounts;
if (readTextFile("/proc/mounts", mounts))
{
char mountsc[mounts.size()+1];
strcpy(mountsc, mounts.c_str());
char* line = strtok(mountsc, "\n");
while (line)
{
char* beg = strchr(line, ' ');
if (!beg)
continue;
beg++;
char* end = strchr(beg, ' ');
if (!end)
continue;
*end = 0;
if (strcmp(beg, SD_CARD_MOUNT) == 0)
{
mTestRoot = TESTROOT_SD_CARD;
break;
}
line = strtok(NULL, "\n");
}
}
if (mTestRoot.empty())
mTestRoot = TESTROOT_NO_SD_CARD;
}

30
src/Config.h Normal file
Просмотреть файл

@ -0,0 +1,30 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef negatus_config_h
#define negatus_config_h
#include <string>
#define SD_CARD_MOUNT "/mnt/sdcard"
#define TESTROOT_SD_CARD "/mnt/sdcard/test"
#define TESTROOT_NO_SD_CARD "/data/local/tmp"
class Config
{
public:
static Config* instance();
std::string mTestRoot;
/* If testRoot is empty, use default, preferring attached SD card. */
void setTestRoot(std::string testRoot);
private:
static Config* mInstance;
Config();
void setDefaultTestRoot();
};
#endif

Просмотреть файл

@ -4,11 +4,10 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#define DEBUG
#include "CommandEventHandler.h"
#include "Logger.h"
#include <string>
#include "Config.h"
#include "CommandEventHandler.h"
#include "Strings.h"
Logger* Logger::mInstance = NULL;
PRLogModuleInfo* Logger::logModule = NULL;
@ -16,19 +15,21 @@ PRLogModuleInfo* Logger::logModule = NULL;
Logger::Logger()
{
logModule = PR_NewLogModule("NegatusLOG");
std::string log_path = std::string(TESTROOT) + "/Negatus.log";
std::string log_path = Config::instance()->mTestRoot + "/Negatus.log";
PR_SetLogFile(log_path.c_str());
PR_LOG(logModule, PR_LOG_ALWAYS, ("NegatusLOG init.\n"));
}
Logger*
Logger::instance()
{
if (!mInstance)
mInstance = new Logger();
return mInstance;
if (!mInstance)
mInstance = new Logger();
return mInstance;
}
void
Logger::log(std::string msg) {
PR_LOG(logModule, PR_LOG_ALWAYS, (msg.c_str()));

Просмотреть файл

@ -6,19 +6,20 @@
#define negatus_logger_h
#include <prlog.h>
#include <string>
class Logger {
public:
static Logger* instance();
void log(std::string msg);
class Logger
{
public:
static Logger* instance();
void log(std::string msg);
static std::string mTestRoot;
private:
static Logger* mInstance;
static PRLogModuleInfo* logModule;
private:
static Logger* mInstance;
static PRLogModuleInfo* logModule;
Logger();
Logger();
};
#endif

Просмотреть файл

@ -18,17 +18,25 @@
#include <prtypes.h>
#include "CommandEventHandler.h"
#include "Config.h"
#include "HeartbeatEventHandler.h"
#include "Logger.h"
#include "Strings.h"
#include "Reactor.h"
#include "SocketAcceptor.h"
#include "Registration.h"
#include "Shell.h"
#include "SocketAcceptor.h"
#include "Strings.h"
// FIXME: This is not portable!
#include <signal.h>
static const PLLongOpt longOpts[] = {
{ "heartbeat", 'b', PR_TRUE },
{ "testroot", 't', PR_TRUE },
{ NULL, }
};
bool wantToDie = false;
void signalHandler(int signal)
@ -112,22 +120,36 @@ int main(int argc, char **argv)
signal(SIGTERM, &signalHandler);
signal(SIGINT, &signalHandler);
signal(SIGHUP, &signalHandler);
PRInt16 port = 20701;
PRInt16 port = 20701, heartbeatPort = 20700;
std::string testRoot;
bool optionError = false;
PLOptState* optState = PL_CreateOptState(argc, argv, "p:");
std::ostringstream usageo;
usageo << "Usage: " << argv[0]
<< " [-p <port>] [--heartbeat <port>] [--testroot <testroot>]";
std::string usage(usageo.str());
PLOptState* optState = PL_CreateLongOptState(argc, argv, "hp:", longOpts);
while (true)
{
PLOptStatus status = PL_GetNextOpt(optState);
if (status == PL_OPT_BAD)
{
std::cerr << "Incorrect option(s). Usage: " << argv[0] << " [-p <port>]"
<< std::endl;
std::cerr << "Incorrect option(s). " << usage << std::endl;
optionError = true;
break;
}
else if (status == PL_OPT_OK)
{
if (optState->option == 'p')
if (optState->option == 0 && optState->longOptIndex < 0)
{
// Ignore positional parameters.
continue;
}
if (optState->longOption == 'h')
{
std::cout << usage << std::endl;
}
else if (optState->longOption == 'p')
{
port = PR_strtod(optState->value, NULL);
if (port <= 0)
@ -137,6 +159,18 @@ int main(int argc, char **argv)
break;
}
}
else if (optState->longOption == 'b')
{
heartbeatPort = PR_strtod(optState->value, NULL);
if (heartbeatPort <= 0)
{
std::cerr << "Invalid heartbeat port number." << std::endl;
optionError = true;
break;
}
}
else if (optState->longOption == 't')
testRoot = std::string(optState->value);
}
else if (status == PL_OPT_EOL)
break;
@ -147,12 +181,14 @@ int main(int argc, char **argv)
if (optionError)
return 1;
Config::instance()->setTestRoot(testRoot);
PRNetAddr cmdAddr, heartbeatAddr;
if(!setUpAcceptor(new CommandEventHandlerFactory(), "Command", port,
cmdAddr))
if (!setUpAcceptor(new CommandEventHandlerFactory(), "Command", port,
cmdAddr))
return 1;
if(!setUpAcceptor(new HeartbeatEventHandlerFactory(), "Heartbeat", 20700,
heartbeatAddr))
if (!setUpAcceptor(new HeartbeatEventHandlerFactory(), "Heartbeat",
heartbeatPort, heartbeatAddr))
return 1;
dict reg_data = get_reg_data();

Просмотреть файл

@ -3,10 +3,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Subprocess.h"
#include "Shell.h"
#include <sstream>
#include <stdio.h>
#include <string.h>
#include "Logging.h"
#include "Subprocess.h"
std::string
id()
@ -30,3 +32,31 @@ id()
}
return std::string("00:00:00:00:00:00");
}
bool
readTextFile(std::string path, std::string& contents)
{
const char *cpath = path.c_str();
FILE *fp = fopen(cpath, "r");
if (!fp)
{
fprintf(stderr, "Error on fopen: %s, with mode r.\n", cpath);
return false;
}
char buffer[BUFSIZE];
std::ostringstream output;
while (fgets(buffer, BUFSIZE, fp))
output << std::string(buffer);
fclose(fp);
std::string str = output.str();
if (str.size())
str.erase(str.size() - 1);
contents = str;
return true;
}

Просмотреть файл

@ -8,5 +8,6 @@
#include <string>
std::string id();
bool readTextFile(std::string path, std::string& contents);
#endif