This commit is contained in:
Jean-Francois Dockes 2016-03-22 13:50:49 +01:00
parent 90afc535a4
commit ae2962a41c
6 changed files with 785 additions and 703 deletions

File diff suppressed because it is too large Load diff

View file

@ -31,7 +31,7 @@
*
*/
class ExecCmdAdvise {
public:
public:
virtual ~ExecCmdAdvise() {}
virtual void newData(int cnt) = 0;
};
@ -41,7 +41,7 @@ class ExecCmdAdvise {
* into the initial input string, set it to empty to signify eof.
*/
class ExecCmdProvide {
public:
public:
virtual ~ExecCmdProvide() {}
virtual void newData() = 0;
};
@ -65,7 +65,7 @@ class ExecCmdProvide {
*
*/
class ExecCmd {
public:
public:
// Use vfork instead of fork. Our vfork usage is multithread-compatible as
// far as I can see, but just in case...
static void useVfork(bool on);
@ -76,8 +76,8 @@ class ExecCmd {
* times for several variables).
* @param envassign an environment assignment string ("name=value")
*/
void putenv(const std::string &envassign);
void putenv(const std::string &name, const std::string& value);
void putenv(const std::string& envassign);
void putenv(const std::string& name, const std::string& value);
/**
* Try to set a limit on child process vm size. This will use
@ -114,7 +114,7 @@ class ExecCmd {
* If the parameter can't be opened for writing, the command's
* stderr will be closed.
*/
void setStderr(const std::string &stderrFile);
void setStderr(const std::string& stderrFile);
/**
* Execute command.
@ -133,16 +133,17 @@ class ExecCmd {
* @param output Output FROM the command.
* @return the exec output status (0 if ok), or -1
*/
int doexec(const std::string &cmd, const std::vector<std::string>& args,
const std::string *input = 0,
std::string *output = 0);
int doexec(const std::string& cmd, const std::vector<std::string>& args,
const std::string *input = 0,
std::string *output = 0);
/** Same as doexec but cmd and args in one vector */
int doexec1(const std::vector<std::string>& args,
const std::string *input = 0,
std::string *output = 0) {
if (args.empty())
if (args.empty()) {
return -1;
}
return doexec(args[0],
std::vector<std::string>(args.begin() + 1, args.end()),
input, output);
@ -152,8 +153,8 @@ class ExecCmd {
* The next four methods can be used when a Q/A dialog needs to be
* performed with the command
*/
int startExec(const std::string &cmd, const std::vector<std::string>& args,
bool has_input, bool has_output);
int startExec(const std::string& cmd, const std::vector<std::string>& args,
bool has_input, bool has_output);
int send(const std::string& data);
int receive(std::string& data, int cnt = -1);
@ -165,8 +166,8 @@ class ExecCmd {
int wait();
/** Wait with WNOHANG set.
@return true if process exited, false else.
@param O: status, the wait(2) call's status value */
@return true if process exited, false else.
@param O: status, the wait(2) call's status value */
bool maybereap(int *status);
pid_t getChildPid();
@ -198,7 +199,7 @@ class ExecCmd {
// because it avoids windows appearing and
// disappearing when executing stuff for previewing
EXF_SHOWWINDOW = 1,
};
};
ExecCmd(int flags = 0);
~ExecCmd();
@ -221,11 +222,13 @@ class ExecCmd {
static bool backtick(const std::vector<std::string> cmd, std::string& out);
class Internal;
private:
private:
Internal *m;
/* Copyconst and assignment are private and forbidden */
ExecCmd(const ExecCmd &) {}
ExecCmd& operator=(const ExecCmd &) {return *this;};
ExecCmd(const ExecCmd&) {}
ExecCmd& operator=(const ExecCmd&) {
return *this;
};
};
@ -259,13 +262,14 @@ public:
ReExec() {}
ReExec(int argc, char *argv[]);
void init(int argc, char *argv[]);
int atexit(void (*function)(void))
{
m_atexitfuncs.push(function);
return 0;
int atexit(void (*function)(void)) {
m_atexitfuncs.push(function);
return 0;
}
void reexec();
const std::string& getreason() {return m_reason;}
const std::string& getreason() {
return m_reason;
}
// Insert new args into the initial argv. idx designates the place
// before which the new args are inserted (the default of 1
// inserts after argv[0] which would probably be an appropriate

View file

@ -84,9 +84,9 @@ using namespace std;
static const int one = 1;
static const int zero = 0;
#define LOGSYSERR(who, call, spar) \
LOGERR(("%s: %s(%s) errno %d (%s)\n", who, call, \
spar, errno, strerror(errno)))
#define LOGSYSERR(who, call, spar) \
LOGERR(("%s: %s(%s) errno %d (%s)\n", who, call, \
spar, errno, strerror(errno)))
#ifndef MIN
#define MIN(a,b) (a<b?a:b)
@ -99,7 +99,7 @@ static const int zero = 0;
#endif
#define MILLIS(OLD, NEW) ( (long)(((NEW).tv_sec - (OLD).tv_sec) * 1000 + \
((NEW).tv_usec - (OLD).tv_usec) / 1000))
((NEW).tv_usec - (OLD).tv_usec) / 1000))
// Static method
// Simplified interface to 'select()'. Only use one fd, for either
@ -116,12 +116,12 @@ int Netcon::select1(int fd, int timeo, int write)
FD_ZERO(&rd);
FD_SET(fd, &rd);
if (write) {
ret = select(fd+1, 0, &rd, 0, &tv);
ret = select(fd + 1, 0, &rd, 0, &tv);
} else {
ret = select(fd+1, &rd, 0, 0, &tv);
ret = select(fd + 1, &rd, 0, 0, &tv);
}
if (!FD_ISSET(fd, &rd)) {
LOGDEB2(("Netcon::select1: fd %d timeout\n",fd));
LOGDEB2(("Netcon::select1: fd %d timeout\n", fd));
}
return ret;
}
@ -199,11 +199,11 @@ int SelectLoop::doLoop()
// Walk the netcon map and set up the read and write fd_sets
// for select()
nfds = 0;
for (map<int,NetconP>::iterator it = m_polldata.begin();
for (map<int, NetconP>::iterator it = m_polldata.begin();
it != m_polldata.end(); it++) {
NetconP &pll = it->second;
NetconP& pll = it->second;
int fd = it->first;
LOGDEB2(("Selectloop: fd %d flags 0x%x\n",fd, pll->m_wantedEvents));
LOGDEB2(("Selectloop: fd %d flags 0x%x\n", fd, pll->m_wantedEvents));
if (pll->m_wantedEvents & Netcon::NETCONPOLL_READ) {
FD_SET(fd, &rd);
nfds = MAX(nfds, fd + 1);
@ -275,7 +275,7 @@ int SelectLoop::doLoop()
continue;
}
map<int,NetconP>::iterator it = m_polldata.find(fd);
map<int, NetconP>::iterator it = m_polldata.find(fd);
if (it == m_polldata.end()) {
/// This should not happen actually
LOGDEB2(("Netcon::selectloop: fd %d not found\n", fd));
@ -284,14 +284,14 @@ int SelectLoop::doLoop()
// Next start will be one beyond last serviced (modulo nfds)
m_placetostart = fd + 1;
NetconP &pll = it->second;
NetconP& pll = it->second;
if (canread && pll->cando(Netcon::NETCONPOLL_READ) <= 0) {
pll->m_wantedEvents &= ~Netcon::NETCONPOLL_READ;
}
if (canwrite && pll->cando(Netcon::NETCONPOLL_WRITE) <= 0) {
pll->m_wantedEvents &= ~Netcon::NETCONPOLL_WRITE;
}
if (!(pll->m_wantedEvents & (Netcon::NETCONPOLL_WRITE|Netcon::NETCONPOLL_READ))) {
if (!(pll->m_wantedEvents & (Netcon::NETCONPOLL_WRITE | Netcon::NETCONPOLL_READ))) {
LOGDEB0(("Netcon::selectloop: fd %d has 0x%x mask, erasing\n",
it->first, it->second->m_wantedEvents));
m_polldata.erase(it);
@ -324,7 +324,7 @@ int SelectLoop::remselcon(NetconP con)
return -1;
}
LOGDEB1(("Netcon::remselcon: fd %d\n", con->m_fd));
map<int,NetconP>::iterator it = m_polldata.find(con->m_fd);
map<int, NetconP>::iterator it = m_polldata.find(con->m_fd);
if (it == m_polldata.end()) {
LOGDEB1(("Netcon::remselcon: con not found for fd %d\n", con->m_fd));
return -1;
@ -369,7 +369,7 @@ void Netcon::setpeer(const char *hostname)
int Netcon::settcpnodelay(int on)
{
LOGDEB2(( "Netcon::settcpnodelay\n" ));
LOGDEB2(("Netcon::settcpnodelay\n"));
if (m_fd < 0) {
LOGERR(("Netcon::settcpnodelay: connection not opened\n"));
return -1;
@ -386,7 +386,7 @@ int Netcon::settcpnodelay(int on)
int Netcon::set_nonblock(int onoff)
{
int flags = fcntl(m_fd, F_GETFL, 0);
if (flags != -1 ) {
if (flags != -1) {
int newflags = onoff ? flags | O_NONBLOCK : flags & ~O_NONBLOCK;
if (newflags != flags)
if (fcntl(m_fd, F_SETFL, newflags) < 0) {
@ -511,7 +511,7 @@ int NetconData::doreceive(char *buf, int cnt, int timeo)
LOGDEB2(("Netcon::doreceive: cnt %d, timeo %d\n", cnt, timeo));
cur = 0;
while (cnt > cur) {
got = receive(buf, cnt-cur, timeo);
got = receive(buf, cnt - cur, timeo);
LOGDEB2(("Netcon::doreceive: got %d\n", got));
if (got < 0) {
return -1;
@ -551,7 +551,7 @@ int NetconData::getline(char *buf, int cnt, int timeo)
for (;;) {
// Transfer from buffer. Have to take a lot of care to keep counts and
// pointers consistant in all end cases
int maxtransf = MIN(m_bufbytes, cnt-1);
int maxtransf = MIN(m_bufbytes, cnt - 1);
int nn = maxtransf;
LOGDEB2(("Before loop, bufbytes %d, maxtransf %d, nn: %d\n",
m_bufbytes, maxtransf, nn));
@ -723,7 +723,7 @@ int NetconCli::openconn(const char *host, const char *serv, int timeo)
if (host[0] != '/') {
struct servent *sp;
if ((sp = getservbyname(serv, "tcp")) == 0) {
LOGERR(("NetconCli::openconn: getservbyname failed for %s\n",serv));
LOGERR(("NetconCli::openconn: getservbyname failed for %s\n", serv));
return -1;
}
// Callee expects the port number in host byte order
@ -822,7 +822,7 @@ int NetconServLis::openservice(const char *serv, int backlog)
LOGDEB1(("NetconServLis::openservice: service opened ok\n"));
ret = 0;
out:
out:
if (ret < 0 && m_fd >= 0) {
close(m_fd);
m_fd = -1;
@ -841,14 +841,14 @@ int NetconServLis::openservice(int port, int backlog)
}
#endif
int ret = -1;
struct sockaddr_in ipaddr;
struct sockaddr_in ipaddr;
if ((m_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
LOGSYSERR("NetconServLis", "socket", "");
return -1;
}
(void) setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR,(char *)&one, sizeof(one));
(void) setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one));
#ifdef SO_REUSEPORT
(void) setsockopt(m_fd, SOL_SOCKET, SO_REUSEPORT,(char *)&one, sizeof(one));
(void) setsockopt(m_fd, SOL_SOCKET, SO_REUSEPORT, (char *)&one, sizeof(one));
#endif /*SO_REUSEPORT*/
memset(&ipaddr, 0, sizeof(ipaddr));
ipaddr.sin_family = AF_INET;
@ -986,7 +986,7 @@ NetconServLis::accept(int timeo)
if ((hp = gethostbyaddr((char *) & (who.sin_addr),
sizeof(struct in_addr), AF_INET)) == 0) {
LOGERR(("NetconServLis::accept: gethostbyaddr failed for addr 0x%lx\n",
who.sin_addr.s_addr));
who.sin_addr.s_addr));
con->setpeer(inet_ntoa(who.sin_addr));
} else {
con->setpeer(hp->h_name);
@ -1033,7 +1033,7 @@ NetconServLis::checkperms(void *cl, int)
if (i < okmasks.len) {
mask = okmasks.intarray[i];
} else {
mask = okmasks.intarray[okmasks.len-1];
mask = okmasks.intarray[okmasks.len - 1];
}
LOGDEB2(("checkperms: trying okaddr 0x%x, mask 0x%x\n",
okaddrs.intarray[i], mask));
@ -1080,9 +1080,9 @@ Usage()
static int op_flags;
#define OPT_MOINS 0x1
#define OPT_s 0x2 /* Server */
#define OPT_c 0x4 /* Client */
#define OPT_n 0x8 /* Client sleeps forever */
#define OPT_s 0x2 /* Server */
#define OPT_c 0x4 /* Client */
#define OPT_n 0x8 /* Client sleeps forever */
extern int trycli(char *host, char *serv);
extern int tryserv(char *serv);
@ -1118,7 +1118,7 @@ int main(int argc, char **argv)
default:
Usage();
break;
}
}
argc--;
argv++;
}
@ -1210,7 +1210,7 @@ int trycli(char *host, char *serv)
}
int port = atoi(serv);
int ret = port > 0 ?
clicon->openconn(host, port) : clicon->openconn(host, serv);
clicon->openconn(host, port) : clicon->openconn(host, serv);
if (ret < 0) {
fprintf(stderr, "openconn(%s, %s) failed\n", host, serv);
return 1;
@ -1271,7 +1271,7 @@ public:
}
if (reason & Netcon::NETCONPOLL_READ) {
#define LL 200
char buf[LL+1];
char buf[LL + 1];
int n;
if ((n = con->receive(buf, LL)) < 0) {
fprintf(stderr, "receive failed\n");
@ -1282,7 +1282,7 @@ public:
}
buf[n] = 0;
fprintf(stderr, "%d received \"%s\"\n", getpid(), buf);
con->setselevents(Netcon::NETCONPOLL_READ|Netcon::NETCONPOLL_WRITE);
con->setselevents(Netcon::NETCONPOLL_READ | Netcon::NETCONPOLL_WRITE);
}
return 0;
}
@ -1292,7 +1292,7 @@ private:
class MyNetconServLis : public NetconServLis {
public:
MyNetconServLis(SelectLoop &loop)
MyNetconServLis(SelectLoop& loop)
: NetconServLis(), m_loop(loop) {
}
protected:
@ -1345,7 +1345,7 @@ int tryserv(char *serv)
int port = atoi(serv);
int ret = port > 0 ?
servlis->openservice(port) : servlis->openservice(serv);
servlis->openservice(port) : servlis->openservice(serv);
if (ret < 0) {
fprintf(stderr, "openservice(%s) failed\n", serv);
return 1;

View file

@ -48,10 +48,10 @@ class SelectLoop;
class Netcon {
public:
enum Event {NETCONPOLL_READ = 0x1, NETCONPOLL_WRITE=0x2};
enum Event {NETCONPOLL_READ = 0x1, NETCONPOLL_WRITE = 0x2};
Netcon()
: m_peer(0), m_fd(-1), m_ownfd(true), m_didtimo(0), m_wantedEvents(0),
m_loop(0) {
: m_peer(0), m_fd(-1), m_ownfd(true), m_didtimo(0), m_wantedEvents(0),
m_loop(0) {
}
virtual ~Netcon();
/// Remember whom we're talking to. We let external code do this because
@ -59,7 +59,7 @@ public:
virtual void setpeer(const char *hostname);
/// Retrieve the peer's hostname. Only works if it was set before !
virtual const char *getpeer() {
return m_peer ? (const char *)m_peer : "none";
return m_peer ? (const char *)m_peer : "none";
}
/// Set or reset the TCP_NODELAY option.
virtual int settcpnodelay(int on = 1);
@ -111,7 +111,7 @@ public:
static int select1(int fd, int secs, int writing = 0);
protected:
char *m_peer; // Name of the connected host
char *m_peer; // Name of the connected host
int m_fd;
bool m_ownfd;
int m_didtimo;
@ -136,9 +136,9 @@ protected:
class SelectLoop {
public:
SelectLoop()
: m_selectloopDoReturn(false), m_selectloopReturnValue(0),
m_placetostart(0),
m_periodichandler(0), m_periodicparam(0), m_periodicmillis(0) {
: m_selectloopDoReturn(false), m_selectloopReturnValue(0),
m_placetostart(0),
m_periodichandler(0), m_periodicparam(0), m_periodicmillis(0) {
}
/// Loop waiting for events on the connections and call the
@ -151,8 +151,8 @@ public:
/// Call from data handler: make selectloop return the param value
void loopReturn(int value) {
m_selectloopDoReturn = true;
m_selectloopReturnValue = value;
m_selectloopDoReturn = true;
m_selectloopReturnValue = value;
}
/// Add a connection to be monitored (this will usually be called
/// from the server's listen connection's accept callback)
@ -251,10 +251,10 @@ public:
}
private:
char *m_buf; // Buffer. Only used when doing getline()s
char *m_buf; // Buffer. Only used when doing getline()s
char *m_bufbase; // Pointer to current 1st byte of useful data
int m_bufbytes; // Bytes of data.
int m_bufsize; // Total buffer size
int m_bufbytes; // Bytes of data.
int m_bufsize; // Total buffer size
STD_SHARED_PTR<NetconWorker> m_user;
virtual int cando(Netcon::Event reason); // Selectloop slot
};
@ -289,7 +289,7 @@ public:
}
private:
int m_silentconnectfailure; // No logging of connection failures if set
int m_silentconnectfailure; // No logging of connection failures if set
};
class NetconServCon;
@ -316,9 +316,9 @@ class NetconServLis : public Netcon {
public:
NetconServLis() {
#ifdef NETCON_ACCESSCONTROL
permsinit = 0;
okaddrs.len = okmasks.len = 0;
okaddrs.intarray = okmasks.intarray = 0;
permsinit = 0;
okaddrs.len = okmasks.len = 0;
okaddrs.intarray = okmasks.intarray = 0;
#endif /* NETCON_ACCESSCONTROL */
}
~NetconServLis();
@ -356,13 +356,13 @@ private:
class NetconServCon : public NetconData {
public:
NetconServCon(int newfd, Netcon* lis = 0) {
m_liscon = lis;
m_fd = newfd;
m_liscon = lis;
m_fd = newfd;
}
/// This is for forked servers that want to get rid of the main socket
void closeLisCon() {
if (m_liscon) {
m_liscon->closeconn();
if (m_liscon) {
m_liscon->closeconn();
}
}
private:

View file

@ -22,12 +22,16 @@
#endif
#include <errno.h>
#include "safefcntl.h"
#include <sys/types.h>
#ifdef _WIN32
#include "safefcntl.h"
#include "safesysstat.h"
#include "safeunistd.h"
#ifndef _WIN32
#else
#define O_BINARY 0
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#include <string>
@ -41,33 +45,34 @@ public:
FileToString(string& data) : m_data(data) {}
string& m_data;
bool init(size_t size, string *reason) {
if (size > 0)
m_data.reserve(size);
return true;
if (size > 0) {
m_data.reserve(size);
}
return true;
}
bool data(const char *buf, int cnt, string *reason) {
try {
m_data.append(buf, cnt);
} catch (...) {
catstrerror(reason, "append", errno);
return false;
}
return true;
try {
m_data.append(buf, cnt);
} catch (...) {
catstrerror(reason, "append", errno);
return false;
}
return true;
}
};
bool file_to_string(const string &fn, string &data, string *reason)
bool file_to_string(const string& fn, string& data, string *reason)
{
return file_to_string(fn, data, 0, size_t(-1), reason);
}
bool file_to_string(const string &fn, string &data, off_t offs, size_t cnt,
bool file_to_string(const string& fn, string& data, off_t offs, size_t cnt,
string *reason)
{
FileToString accum(data);
return file_scan(fn, &accum, offs, cnt, reason);
}
bool file_scan(const string &fn, FileScanDo* doer, string *reason)
bool file_scan(const string& fn, FileScanDo* doer, string *reason)
{
return file_scan(fn, doer, 0, size_t(-1), reason);
}
@ -77,7 +82,7 @@ const int RDBUFSZ = 8192;
// on both linux i586 and macosx (compared to just append())
// Also tried a version with mmap, but it's actually slower on the mac and not
// faster on linux.
bool file_scan(const string &fn, FileScanDo* doer, off_t startoffs,
bool file_scan(const string& fn, FileScanDo* doer, off_t startoffs,
size_t cnttoread, string *reason)
{
if (startoffs < 0) {
@ -94,12 +99,12 @@ bool file_scan(const string &fn, FileScanDo* doer, off_t startoffs,
// If we have a file name, open it, else use stdin.
if (!fn.empty()) {
fd = open(fn.c_str(), O_RDONLY|O_BINARY);
if (fd < 0 || fstat(fd, &st) < 0) {
catstrerror(reason, "open/stat", errno);
return false;
}
noclosing = false;
fd = open(fn.c_str(), O_RDONLY | O_BINARY);
if (fd < 0 || fstat(fd, &st) < 0) {
catstrerror(reason, "open/stat", errno);
return false;
}
noclosing = false;
}
#if defined O_NOATIME && O_NOATIME != 0
@ -108,12 +113,12 @@ bool file_scan(const string &fn, FileScanDo* doer, off_t startoffs,
}
#endif
if (cnttoread != (size_t)-1 && cnttoread) {
doer->init(cnttoread+1, reason);
if (cnttoread != (size_t) - 1 && cnttoread) {
doer->init(cnttoread + 1, reason);
} else if (st.st_size > 0) {
doer->init(size_t(st.st_size+1), reason);
doer->init(size_t(st.st_size + 1), reason);
} else {
doer->init(0, reason);
doer->init(0, reason);
}
off_t curoffs = 0;
@ -130,36 +135,40 @@ bool file_scan(const string &fn, FileScanDo* doer, off_t startoffs,
for (;;) {
size_t toread = RDBUFSZ;
if (startoffs > 0 && curoffs < startoffs) {
toread = size_t(MIN(RDBUFSZ, startoffs - curoffs));
toread = size_t(MIN(RDBUFSZ, startoffs - curoffs));
}
if (cnttoread != size_t(-1)) {
toread = MIN(toread, cnttoread - totread);
}
ssize_t n = static_cast<ssize_t>(read(fd, buf, toread));
if (n < 0) {
catstrerror(reason, "read", errno);
goto out;
}
if (n == 0)
break;
ssize_t n = static_cast<ssize_t>(read(fd, buf, toread));
if (n < 0) {
catstrerror(reason, "read", errno);
goto out;
}
if (n == 0) {
break;
}
curoffs += n;
if (curoffs - n < startoffs)
if (curoffs - n < startoffs) {
continue;
}
if (!doer->data(buf, n, reason)) {
goto out;
}
if (!doer->data(buf, n, reason)) {
goto out;
}
totread += n;
if (cnttoread > 0 && totread >= cnttoread)
if (cnttoread > 0 && totread >= cnttoread) {
break;
}
}
ret = true;
out:
if (fd >= 0 && !noclosing)
close(fd);
out:
if (fd >= 0 && !noclosing) {
close(fd);
}
return ret;
}
@ -181,29 +190,28 @@ using namespace std;
using namespace std;
class myCB : public FsTreeWalkerCB {
public:
FsTreeWalker::Status processone(const string &path,
const struct stat *st,
FsTreeWalker::CbFlag flg)
{
if (flg == FsTreeWalker::FtwDirEnter) {
//cout << "[Entering " << path << "]" << endl;
} else if (flg == FsTreeWalker::FtwDirReturn) {
//cout << "[Returning to " << path << "]" << endl;
} else if (flg == FsTreeWalker::FtwRegular) {
//cout << path << endl;
string s, reason;
if (!file_to_string(path, s, &reason)) {
cerr << "Failed: " << reason << " : " << path << endl;
} else {
//cout <<
//"================================================" << endl;
cout << path << endl;
// cout << s;
}
reason.clear();
}
return FsTreeWalker::FtwOk;
public:
FsTreeWalker::Status processone(const string& path,
const struct stat *st,
FsTreeWalker::CbFlag flg) {
if (flg == FsTreeWalker::FtwDirEnter) {
//cout << "[Entering " << path << "]" << endl;
} else if (flg == FsTreeWalker::FtwDirReturn) {
//cout << "[Returning to " << path << "]" << endl;
} else if (flg == FsTreeWalker::FtwRegular) {
//cout << path << endl;
string s, reason;
if (!file_to_string(path, s, &reason)) {
cerr << "Failed: " << reason << " : " << path << endl;
} else {
//cout <<
//"================================================" << endl;
cout << path << endl;
// cout << s;
}
reason.clear();
}
return FsTreeWalker::FtwOk;
}
};
@ -214,8 +222,8 @@ static int op_flags;
static const char *thisprog;
static char usage [] =
"trreadfile [-o offs] [-c cnt] topdirorfile\n\n"
;
"trreadfile [-o offs] [-c cnt] topdirorfile\n\n"
;
static void
Usage(void)
{
@ -228,51 +236,71 @@ int main(int argc, const char **argv)
off_t offs = 0;
size_t cnt = size_t(-1);
thisprog = argv[0];
argc--; argv++;
argc--;
argv++;
while (argc > 0 && **argv == '-') {
(*argv)++;
if (!(**argv))
/* Cas du "adb - core" */
Usage();
while (**argv)
switch (*(*argv)++) {
case 'c': op_flags |= OPT_c; if (argc < 2) Usage();
cnt = atoll(*(++argv)); argc--;
goto b1;
case 'o': op_flags |= OPT_o; if (argc < 2) Usage();
offs = strtoull(*(++argv), 0, 0); argc--;
goto b1;
default: Usage(); break;
}
b1: argc--; argv++;
}
while (argc > 0 && **argv == '-') {
(*argv)++;
if (!(**argv))
/* Cas du "adb - core" */
{
Usage();
}
while (**argv)
switch (*(*argv)++) {
case 'c':
op_flags |= OPT_c;
if (argc < 2) {
Usage();
}
cnt = atoll(*(++argv));
argc--;
goto b1;
case 'o':
op_flags |= OPT_o;
if (argc < 2) {
Usage();
}
offs = strtoull(*(++argv), 0, 0);
argc--;
goto b1;
default:
Usage();
break;
}
b1:
argc--;
argv++;
}
if (argc != 1)
Usage();
string top = *argv++;argc--;
cerr << "filename " << top << " offs " << offs << " cnt " << cnt << endl;
if (argc != 1) {
Usage();
}
string top = *argv++;
argc--;
cerr << "filename " << top << " offs " << offs << " cnt " << cnt << endl;
struct stat st;
if (!top.empty() && stat(top.c_str(), &st) < 0) {
perror("stat");
exit(1);
}
if (!top.empty() && S_ISDIR(st.st_mode)) {
FsTreeWalker walker;
myCB cb;
walker.walk(top, cb);
if (walker.getErrCnt() > 0)
cout << walker.getReason();
} else {
string s, reason;
if (!file_to_string(top, s, offs, cnt, &reason)) {
cerr << reason << endl;
exit(1);
} else {
cout << s;
}
}
exit(0);
struct stat st;
if (!top.empty() && stat(top.c_str(), &st) < 0) {
perror("stat");
exit(1);
}
if (!top.empty() && S_ISDIR(st.st_mode)) {
FsTreeWalker walker;
myCB cb;
walker.walk(top, cb);
if (walker.getErrCnt() > 0) {
cout << walker.getReason();
}
} else {
string s, reason;
if (!file_to_string(top, s, offs, cnt, &reason)) {
cerr << reason << endl;
exit(1);
} else {
cout << s;
}
}
exit(0);
}
#endif //TEST_READFILE

View file

@ -31,20 +31,20 @@ public:
virtual bool init(size_t size, std::string *reason) = 0;
virtual bool data(const char *buf, int cnt, std::string* reason) = 0;
};
bool file_scan(const std::string &filename, FileScanDo* doer, std::string *reason = 0);
bool file_scan(const std::string& filename, FileScanDo* doer, std::string *reason = 0);
/* Same but only process count cnt from offset offs. Set cnt to size_t(-1)
* for no limit */
bool file_scan(const std::string &fn, FileScanDo* doer, off_t offs, size_t cnt,
bool file_scan(const std::string& fn, FileScanDo* doer, off_t offs, size_t cnt,
std::string *reason = 0);
/**
* Read file into string.
* @return true for ok, false else
*/
bool file_to_string(const std::string &filename, std::string &data, std::string *reason = 0);
bool file_to_string(const std::string& filename, std::string& data, std::string *reason = 0);
/** Read file chunk into string. Set cnt to size_t(-1) for whole file */
bool file_to_string(const std::string &filename, std::string &data,
bool file_to_string(const std::string& filename, std::string& data,
off_t offs, size_t cnt, std::string *reason = 0);
#endif /* _READFILE_H_INCLUDED_ */