Added push command. Added forgotten PullFileEventHandler files.

This commit is contained in:
Mark Côté 2012-08-23 18:01:44 -04:00
Родитель 26a08159a3
Коммит 2d7da6b467
11 изменённых файлов: 394 добавлений и 40 удалений

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

@ -6,12 +6,15 @@ SRCS=\
src/Buffer.cpp \
src/BufferedSocket.cpp \
src/CommandEventHandler.cpp \
src/Hash.cpp \
src/Logging.cpp \
src/PullFileEventHandler.cpp \
src/PushFileEventHandler.cpp \
src/Reactor.cpp \
src/SocketAcceptor.cpp \
src/Strings.cpp \
src/SUTAgent.cpp
src/SUTAgent.cpp \
src/Subprocess.cpp
OBJS=$(subst .cpp,.o,$(SRCS))

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

@ -3,9 +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 "CommandEventHandler.h"
#include "Hash.h"
#include "Logging.h"
#include "PullFileEventHandler.h"
#include "PushFileEventHandler.h"
#include "Strings.h"
#include "Subprocess.h"
#include <dirent.h>
#include <stdint.h>
@ -162,6 +165,8 @@ CommandEventHandler::handleLine(std::string line)
result = ps(cl.args);
else if (cl.cmd.compare("pull") == 0)
result = pull(cl.args);
else if (cl.cmd.compare("push") == 0)
result = push(cl.args);
else if (cl.cmd.compare("isDir") == 0)
result = isDir(cl.args);
else if (cl.cmd.compare("ls") == 0)
@ -188,35 +193,6 @@ CommandEventHandler::sendPrompt()
}
FILE*
CommandEventHandler::checkPopen(std::string cmd, std::string mode)
{
FILE *fp = popen(cmd.c_str(), mode.c_str());
if (!fp)
{
fprintf(stderr, "Error on popen: %s, with mode %s.\n", cmd.c_str(),
mode.c_str());
exit(1);
}
return fp;
}
std::string
CommandEventHandler::getCmdOutput(std::string cmd)
{
FILE *fp = checkPopen(cmd, "r");
char buffer[BUFSIZE];
std::string output;
while (fgets(buffer, BUFSIZE, fp))
output += std::string(buffer);
pclose(fp);
return output;
}
std::string
CommandEventHandler::readTextFile(std::string path)
{
@ -433,14 +409,12 @@ CommandEventHandler::hash(std::vector<std::string>& args)
{
if (args.size() < 1)
return agentWarnInvalidNumArgs(1);
const char *cpath = args[0].c_str();
char buffer[BUFSIZE];
std::string path = args[0];
if (PR_Access(cpath, PR_ACCESS_READ_OK) != PR_SUCCESS)
return std::string("");
if (PR_Access(path.c_str(), PR_ACCESS_READ_OK) != PR_SUCCESS)
return std::string(agentWarn("cannot open file for reading"));
sprintf(buffer, "md5sum %s", cpath);
return getCmdOutput(std::string(buffer));
return fileHash(path) + std::string(ENDL);
}
@ -573,6 +547,18 @@ CommandEventHandler::pull(std::vector<std::string>& args)
}
std::string
CommandEventHandler::push(std::vector<std::string>& args)
{
if (args.size() < 2)
return agentWarnInvalidNumArgs(2);
std::string path(args[0]);
PRUint64 size = PR_strtod(args[1].c_str(), NULL);
mDataEventHandler = new PushFileEventHandler(mBufSocket, path, size);
return "";
}
std::string
CommandEventHandler::isDir(std::vector<std::string>& args)
{

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

@ -10,8 +10,6 @@
#include "BufferedSocket.h"
#include "EventHandler.h"
#define BUFSIZE 1024
class CommandEventHandler: public EventHandler
{
public:
@ -39,8 +37,6 @@ private:
void sendPrompt();
void do_rmdr(std::string path, std::ostringstream &out);
FILE *checkPopen(std::string cmd, std::string mode);
std::string getCmdOutput(std::string cmd);
std::string readTextFile(std::string path);
int getFirstIntPos(char *str, int limit);
std::string joinPaths(std::string p1, std::string p2);
@ -64,6 +60,7 @@ private:
std::string power(std::vector<std::string>& args);
std::string ps(std::vector<std::string>& args);
std::string pull(std::vector<std::string>& args);
std::string push(std::vector<std::string>& args);
std::string quit(std::vector<std::string>& args);
std::string screen(std::vector<std::string>& args);
std::string systime(std::vector<std::string>& args);

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

@ -0,0 +1,18 @@
/* -*- 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 "Hash.h"
#include "Subprocess.h"
#include <sstream>
std::string
fileHash(std::string path)
{
std::ostringstream ss;
ss << "md5sum " << path;
std::string hash = getCmdOutput(ss.str());
// strip everything past actual hash string
return hash.substr(0, hash.find(" "));
}

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

@ -0,0 +1,12 @@
/* -*- 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_hash_h
#define negatus_hash_h
#include <string>
std::string fileHash(std::string path);
#endif

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

@ -0,0 +1,130 @@
/* -*- 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 "PullFileEventHandler.h"
#include <sstream>
#include <prerror.h>
#include "BufferedSocket.h"
#include "Logging.h"
#include "Strings.h"
PullFileEventHandler::PullFileEventHandler(BufferedSocket& bufSocket,
std::string path,
PRUint64 start,
PRUint64 size)
: mBufSocket(bufSocket), mPath(path), mFile(NULL), mBytesRead(0), mSize(size),
mTmpBuf(new char[BLOCK_SIZE])
{
if (PR_Access(path.c_str(), PR_ACCESS_EXISTS) != PR_SUCCESS)
{
mBufSocket.write(agentWarn("file does not exist"));
close();
return;
}
if (PR_Access(path.c_str(), PR_ACCESS_READ_OK) != PR_SUCCESS)
{
mBufSocket.write(agentWarn("insufficient permissions to read file"));
close();
return;
}
mFile = PR_Open(path.c_str(), PR_RDONLY, 0);
if (!mFile)
{
mBufSocket.write(agentWarn("could not open file"));
close();
return;
}
PRFileInfo fileInfo;
if (PR_GetOpenFileInfo(mFile, &fileInfo) != PR_SUCCESS)
{
mBufSocket.write(agentWarn("failed to read file info"));
close();
return;
}
if (fileInfo.size <= start)
{
mBufSocket.write(agentWarn("start position is at or past end of file"));
close();
return;
}
if (start > 0)
{
PRInt64 seekBytes = PR_Seek64(mFile, start, PR_SEEK_SET);
if (seekBytes == -1)
{
mBufSocket.write(agentWarn("failed to seek"));
close();
return;
}
}
if (mSize == 0)
mSize = fileInfo.size - start;
std::stringstream out;
out << path << "," << mSize << ENDL;
mBufSocket.write(out.str());
}
PullFileEventHandler::~PullFileEventHandler()
{
delete[] mTmpBuf;
}
void
PullFileEventHandler::close()
{
EventHandler::close();
if (mFile)
{
PR_Close(mFile);
mFile = NULL;
}
}
void
PullFileEventHandler::getPollDescs(std::vector<PRPollDesc>& descs)
{
if (!mBufSocket.closed())
{
PRPollDesc desc;
desc.fd = mBufSocket.fd();
desc.in_flags = PR_POLL_WRITE;
descs.push_back(desc);
}
}
void
PullFileEventHandler::handleEvent(PRPollDesc desc)
{
if (desc.fd != mBufSocket.fd())
return;
if (!(desc.out_flags & PR_POLL_WRITE))
return;
PRUint32 blockSize = (mSize - mBytesRead) < BLOCK_SIZE ? mSize - mBytesRead
: BLOCK_SIZE;
PRInt32 bytes = PR_Read(mFile, mTmpBuf, blockSize);
if (bytes > 0)
{
mBytesRead += bytes;
mBufSocket.write(mTmpBuf, bytes);
}
else if (bytes == 0)
close();
else if (bytes < 0)
{
// FIXME: log error
close();
}
if (mSize == mBytesRead)
close();
}

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

@ -0,0 +1,37 @@
/* -*- 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_pull_file_event_handler_h
#define negatus_pull_file_event_handler_h
#include <string>
#include <prio.h>
#include "EventHandler.h"
#define BLOCK_SIZE 1024
class BufferedSocket;
class PullFileEventHandler: public EventHandler
{
public:
PullFileEventHandler(BufferedSocket& bufSocket, std::string path,
PRUint64 start, PRUint64 size);
virtual ~PullFileEventHandler();
virtual void close();
virtual void getPollDescs(std::vector<PRPollDesc>& descs);
virtual void handleEvent(PRPollDesc desc);
virtual std::string name() { return "PullFileEventHandler"; }
private:
BufferedSocket& mBufSocket;
std::string mPath;
PRFileDesc* mFile;
PRUint64 mBytesRead;
PRUint64 mSize;
char* mTmpBuf;
};
#endif

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

@ -0,0 +1,81 @@
/* -*- 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 "PushFileEventHandler.h"
#include "BufferedSocket.h"
#include "Hash.h"
#include "Logging.h"
#include "Strings.h"
PushFileEventHandler::PushFileEventHandler(BufferedSocket& bufSocket,
std::string path, PRUint64 size)
: mBufSocket(bufSocket), mPath(path), mSize(size), mBytesWritten(0),
mTmpBuf(new char[BLOCK_SIZE])
{
mFile = PR_Open(path.c_str(), PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
PR_IRWXU | PR_IRWXG);
if (!mFile)
{
mBufSocket.write(agentWarn("could not open file for writing"));
close();
return;
}
}
PushFileEventHandler::~PushFileEventHandler()
{
delete[] mTmpBuf;
}
void
PushFileEventHandler::close()
{
EventHandler::close();
if (mFile)
{
PR_Close(mFile);
mFile = NULL;
}
}
void
PushFileEventHandler::getPollDescs(std::vector<PRPollDesc>& descs)
{
if (!mBufSocket.closed())
{
PRPollDesc desc;
desc.fd = mBufSocket.fd();
desc.in_flags = PR_POLL_READ;
descs.push_back(desc);
}
}
void
PushFileEventHandler::handleEvent(PRPollDesc desc)
{
if (desc.fd != mBufSocket.fd())
return;
if (!(desc.out_flags & PR_POLL_READ))
return;
PRUint32 blockSize = (mSize - mBytesWritten) < BLOCK_SIZE
? mSize - mBytesWritten : BLOCK_SIZE;
PRUint32 bytes = mBufSocket.read(mTmpBuf, blockSize);
if (bytes > 0)
{
PR_Write(mFile, mTmpBuf, bytes);
mBytesWritten += bytes;
}
// a closed socket will be detected automatically by CommandEventHandler.
if (mSize == mBytesWritten)
{
close();
mBufSocket.write(std::string(ENDL) + fileHash(mPath) + std::string(ENDL));
}
}

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

@ -0,0 +1,37 @@
/* -*- 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_push_file_event_handler_h
#define negatus_push_file_event_handler_h
#include <string>
#include <prio.h>
#include "EventHandler.h"
#define BLOCK_SIZE 1024
class BufferedSocket;
class PushFileEventHandler: public EventHandler
{
public:
PushFileEventHandler(BufferedSocket& bufSocket, std::string path,
PRUint64 size);
virtual ~PushFileEventHandler();
virtual void close();
virtual void getPollDescs(std::vector<PRPollDesc>& descs);
virtual void handleEvent(PRPollDesc desc);
virtual std::string name() { return "PushFileEventHandler"; }
private:
BufferedSocket& mBufSocket;
std::string mPath;
PRFileDesc* mFile;
PRUint64 mBytesWritten;
PRUint64 mSize;
char* mTmpBuf;
};
#endif

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

@ -0,0 +1,37 @@
/* -*- 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 "Subprocess.h"
#include <iostream>
#include <stdio.h>
FILE*
checkPopen(std::string cmd, std::string mode)
{
FILE *fp = popen(cmd.c_str(), mode.c_str());
if (!fp)
{
std::cerr << "Error on popen: " << cmd << " , with mode " << mode
<< std::endl;
return NULL;
}
return fp;
}
std::string
getCmdOutput(std::string cmd)
{
FILE *fp = checkPopen(cmd, "r");
if (!fp)
return "";
char buffer[BUFSIZE];
std::string output;
while (fgets(buffer, BUFSIZE, fp))
output += std::string(buffer);
pclose(fp);
return output;
}

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

@ -0,0 +1,16 @@
/* -*- 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_subprocess_h
#define negatus_subprocess_h
#include <string>
#define BUFSIZE 1024
FILE* checkPopen(std::string cmd, std::string mode);
std::string getCmdOutput(std::string cmd);
#endif