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

View file

@ -113,7 +113,7 @@ public:
sigemptyset(&m_blkcld); sigemptyset(&m_blkcld);
} }
// Child process code // Child process code
inline void dochild(const std::string &cmd, const char **argv, inline void dochild(const std::string& cmd, const char **argv,
const char **envv, bool has_input, bool has_output); const char **envv, bool has_input, bool has_output);
}; };
bool ExecCmd::Internal::o_useVfork = false; bool ExecCmd::Internal::o_useVfork = false;
@ -121,8 +121,9 @@ bool ExecCmd::Internal::o_useVfork = false;
ExecCmd::ExecCmd(int) ExecCmd::ExecCmd(int)
{ {
m = new Internal(); m = new Internal();
if (m) if (m) {
m->reset(); m->reset();
}
} }
void ExecCmd::setAdvise(ExecCmdAdvise *adv) void ExecCmd::setAdvise(ExecCmdAdvise *adv)
{ {
@ -134,10 +135,11 @@ void ExecCmd::setProvide(ExecCmdProvide *p)
} }
void ExecCmd::setTimeout(int mS) void ExecCmd::setTimeout(int mS)
{ {
if (mS > 30) if (mS > 30) {
m->m_timeoutMs = mS; m->m_timeoutMs = mS;
}
} }
void ExecCmd::setStderr(const std::string &stderrFile) void ExecCmd::setStderr(const std::string& stderrFile)
{ {
m->m_stderrFile = stderrFile; m->m_stderrFile = stderrFile;
} }
@ -158,9 +160,10 @@ void ExecCmd::zapChild()
bool ExecCmd::requestChildExit() bool ExecCmd::requestChildExit()
{ {
if (m->m_pid > 0) { if (m->m_pid > 0) {
if (kill(m->m_pid, SIGTERM) == 0) if (kill(m->m_pid, SIGTERM) == 0) {
return true; return true;
} }
}
return false; return false;
} }
@ -182,8 +185,9 @@ static bool exec_is_there(const char *candidate)
bool ExecCmd::which(const string& cmd, string& exepath, const char* path) bool ExecCmd::which(const string& cmd, string& exepath, const char* path)
{ {
if (cmd.empty()) if (cmd.empty()) {
return false; return false;
}
if (cmd[0] == '/') { if (cmd[0] == '/') {
if (exec_is_there(cmd.c_str())) { if (exec_is_there(cmd.c_str())) {
exepath = cmd; exepath = cmd;
@ -199,14 +203,16 @@ bool ExecCmd::which(const string& cmd, string& exepath, const char* path)
} else { } else {
pp = getenv("PATH"); pp = getenv("PATH");
} }
if (pp == 0) if (pp == 0) {
return false; return false;
}
vector<string> pels; vector<string> pels;
stringToTokens(pp, pels, ":"); stringToTokens(pp, pels, ":");
for (vector<string>::iterator it = pels.begin(); it != pels.end(); it++) { for (vector<string>::iterator it = pels.begin(); it != pels.end(); it++) {
if (it->empty()) if (it->empty()) {
*it = "."; *it = ".";
}
string candidate = (it->empty() ? string(".") : *it) + "/" + cmd; string candidate = (it->empty() ? string(".") : *it) + "/" + cmd;
if (exec_is_there(candidate.c_str())) { if (exec_is_there(candidate.c_str())) {
exepath = candidate; exepath = candidate;
@ -227,12 +233,12 @@ void ExecCmd::useVfork(bool on)
Internal::o_useVfork = on; Internal::o_useVfork = on;
} }
void ExecCmd::putenv(const string &ea) void ExecCmd::putenv(const string& ea)
{ {
m->m_env.push_back(ea); m->m_env.push_back(ea);
} }
void ExecCmd::putenv(const string &name, const string& value) void ExecCmd::putenv(const string& name, const string& value)
{ {
string ea = name + "=" + value; string ea = name + "=" + value;
putenv(ea); putenv(ea);
@ -258,19 +264,24 @@ public:
m_active = false; m_active = false;
} }
~ExecCmdRsrc() { ~ExecCmdRsrc() {
if (!m_active || !m_parent) if (!m_active || !m_parent) {
return; return;
}
LOGDEB1(("~ExecCmdRsrc: working. mypid: %d\n", (int)getpid())); LOGDEB1(("~ExecCmdRsrc: working. mypid: %d\n", (int)getpid()));
// Better to close the descs first in case the child is waiting in read // Better to close the descs first in case the child is waiting in read
if (m_parent->m_pipein[0] >= 0) if (m_parent->m_pipein[0] >= 0) {
close(m_parent->m_pipein[0]); close(m_parent->m_pipein[0]);
if (m_parent->m_pipein[1] >= 0) }
if (m_parent->m_pipein[1] >= 0) {
close(m_parent->m_pipein[1]); close(m_parent->m_pipein[1]);
if (m_parent->m_pipeout[0] >= 0) }
if (m_parent->m_pipeout[0] >= 0) {
close(m_parent->m_pipeout[0]); close(m_parent->m_pipeout[0]);
if (m_parent->m_pipeout[1] >= 0) }
if (m_parent->m_pipeout[1] >= 0) {
close(m_parent->m_pipeout[1]); close(m_parent->m_pipeout[1]);
}
// It's apparently possible for m_pid to be > 0 and getpgid to fail. In // It's apparently possible for m_pid to be > 0 and getpgid to fail. In
// this case, we have to conclude that the child process does // this case, we have to conclude that the child process does
@ -285,8 +296,9 @@ public:
msleep(i == 0 ? 5 : (i == 1 ? 100 : 2000)); msleep(i == 0 ? 5 : (i == 1 ? 100 : 2000));
int status; int status;
(void)waitpid(m_parent->m_pid, &status, WNOHANG); (void)waitpid(m_parent->m_pid, &status, WNOHANG);
if (kill(m_parent->m_pid, 0) != 0) if (kill(m_parent->m_pid, 0) != 0) {
break; break;
}
if (i == 2) { if (i == 2) {
LOGDEB(("ExecCmd: killpg(%d, SIGKILL)\n", grp)); LOGDEB(("ExecCmd: killpg(%d, SIGKILL)\n", grp));
killpg(grp, SIGKILL); killpg(grp, SIGKILL);
@ -311,8 +323,9 @@ private:
ExecCmd::~ExecCmd() ExecCmd::~ExecCmd()
{ {
ExecCmdRsrc(this->m); ExecCmdRsrc(this->m);
if (m) if (m) {
delete m; delete m;
}
} }
// In child process. Set up pipes and exec command. // In child process. Set up pipes and exec command.
@ -328,7 +341,7 @@ ExecCmd::~ExecCmd()
// If one of the calls block, the problem manifests itself by 20mn // If one of the calls block, the problem manifests itself by 20mn
// (filter timeout) of looping on "ExecCmd::doexec: selectloop // (filter timeout) of looping on "ExecCmd::doexec: selectloop
// returned 1', because the father is waiting on the read descriptor // returned 1', because the father is waiting on the read descriptor
inline void ExecCmd::Internal::dochild(const string &cmd, const char **argv, inline void ExecCmd::Internal::dochild(const string& cmd, const char **argv,
const char **envv, const char **envv,
bool has_input, bool has_output) bool has_input, bool has_output)
{ {
@ -411,9 +424,9 @@ inline void ExecCmd::Internal::dochild(const string &cmd, const char **argv,
} }
// Do we need to redirect stderr ? // Do we need to redirect stderr ?
if (!m_stderrFile.empty()) { if (!m_stderrFile.empty()) {
int fd = open(m_stderrFile.c_str(), O_WRONLY|O_CREAT int fd = open(m_stderrFile.c_str(), O_WRONLY | O_CREAT
#ifdef O_APPEND #ifdef O_APPEND
|O_APPEND | O_APPEND
#endif #endif
, 0600); , 0600);
if (fd < 0) { if (fd < 0) {
@ -443,10 +456,11 @@ void ExecCmd::setrlimit_as(int mbytes)
m->m_rlimit_as_mbytes = mbytes; m->m_rlimit_as_mbytes = mbytes;
} }
int ExecCmd::startExec(const string &cmd, const vector<string>& args, int ExecCmd::startExec(const string& cmd, const vector<string>& args,
bool has_input, bool has_output) bool has_input, bool has_output)
{ {
{ // Debug and logging {
// Debug and logging
string command = cmd + " "; string command = cmd + " ";
for (vector<string>::const_iterator it = args.begin(); for (vector<string>::const_iterator it = args.begin();
it != args.end(); it++) { it != args.end(); it++) {
@ -478,7 +492,7 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
// Allocate arg vector (2 more for arg0 + final 0) // Allocate arg vector (2 more for arg0 + final 0)
typedef const char *Ccharp; typedef const char *Ccharp;
Ccharp *argv; Ccharp *argv;
argv = (Ccharp *)malloc((args.size()+2) * sizeof(char *)); argv = (Ccharp *)malloc((args.size() + 2) * sizeof(char *));
if (argv == 0) { if (argv == 0) {
LOGERR(("ExecCmd::doexec: malloc() failed. errno %d\n", errno)); LOGERR(("ExecCmd::doexec: malloc() failed. errno %d\n", errno));
return -1; return -1;
@ -495,8 +509,9 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
Ccharp *envv; Ccharp *envv;
int envsize; int envsize;
for (envsize = 0; ; envsize++) for (envsize = 0; ; envsize++)
if (environ[envsize] == 0) if (environ[envsize] == 0) {
break; break;
}
envv = (Ccharp *)malloc((envsize + m->m_env.size() + 2) * sizeof(char *)); envv = (Ccharp *)malloc((envsize + m->m_env.size() + 2) * sizeof(char *));
if (envv == 0) { if (envv == 0) {
LOGERR(("ExecCmd::doexec: malloc() failed. errno %d\n", errno)); LOGERR(("ExecCmd::doexec: malloc() failed. errno %d\n", errno));
@ -504,8 +519,9 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
return -1; return -1;
} }
int eidx; int eidx;
for (eidx = 0; eidx < envsize; eidx++) for (eidx = 0; eidx < envsize; eidx++) {
envv[eidx] = environ[eidx]; envv[eidx] = environ[eidx];
}
for (vector<string>::const_iterator it = m->m_env.begin(); for (vector<string>::const_iterator it = m->m_env.begin();
it != m->m_env.end(); it++) { it != m->m_env.end(); it++) {
envv[eidx++] = it->c_str(); envv[eidx++] = it->c_str();
@ -526,7 +542,7 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
// Note that posix_spawn provides no way to setrlimit() the child. // Note that posix_spawn provides no way to setrlimit() the child.
{ {
posix_spawnattr_t attrs; posix_spawnattr_t attrs;
posix_spawnattr_init (&attrs); posix_spawnattr_init(&attrs);
short flags; short flags;
posix_spawnattr_getflags(&attrs, &flags); posix_spawnattr_getflags(&attrs, &flags);
@ -537,7 +553,7 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
sigset_t sset; sigset_t sset;
sigemptyset(&sset); sigemptyset(&sset);
posix_spawnattr_setsigmask (&attrs, &sset); posix_spawnattr_setsigmask(&attrs, &sset);
flags |= POSIX_SPAWN_SETSIGMASK; flags |= POSIX_SPAWN_SETSIGMASK;
sigemptyset(&sset); sigemptyset(&sset);
@ -567,7 +583,7 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
// Do we need to redirect stderr ? // Do we need to redirect stderr ?
if (!m->m_stderrFile.empty()) { if (!m->m_stderrFile.empty()) {
int oflags = O_WRONLY|O_CREAT; int oflags = O_WRONLY | O_CREAT;
#ifdef O_APPEND #ifdef O_APPEND
oflags |= O_APPEND; oflags |= O_APPEND;
#endif #endif
@ -670,10 +686,10 @@ public:
m_cmd->m_pipein[1] = -1; m_cmd->m_pipein[1] = -1;
m_cmd->m_tocmd.reset(); m_cmd->m_tocmd.reset();
} }
virtual int data(NetconData *con, Netcon::Event reason) virtual int data(NetconData *con, Netcon::Event reason) {
{ if (!m_input) {
if (!m_input)
return -1; return -1;
}
LOGDEB1(("ExecWriter: input m_cnt %d input length %d\n", m_cnt, LOGDEB1(("ExecWriter: input m_cnt %d input length %d\n", m_cnt,
m_input->length())); m_input->length()));
if (m_cnt >= m_input->length()) { if (m_cnt >= m_input->length()) {
@ -715,10 +731,9 @@ private:
class ExecReader : public NetconWorker { class ExecReader : public NetconWorker {
public: public:
ExecReader(string *output, ExecCmdAdvise *advise) ExecReader(string *output, ExecCmdAdvise *advise)
: m_output(output), m_advise(advise) : m_output(output), m_advise(advise) {
{} }
virtual int data(NetconData *con, Netcon::Event reason) virtual int data(NetconData *con, Netcon::Event reason) {
{
char buf[8192]; char buf[8192];
int n = con->receive(buf, 8192); int n = con->receive(buf, 8192);
LOGDEB1(("ExecReader: got %d from command\n", n)); LOGDEB1(("ExecReader: got %d from command\n", n));
@ -726,8 +741,9 @@ public:
LOGERR(("ExecCmd::doexec: receive failed. errno %d\n", errno)); LOGERR(("ExecCmd::doexec: receive failed. errno %d\n", errno));
} else if (n > 0) { } else if (n > 0) {
m_output->append(buf, n); m_output->append(buf, n);
if (m_advise) if (m_advise) {
m_advise->newData(n); m_advise->newData(n);
}
} // else n == 0, just return } // else n == 0, just return
return n; return n;
} }
@ -737,7 +753,7 @@ private:
}; };
int ExecCmd::doexec(const string &cmd, const vector<string>& args, int ExecCmd::doexec(const string& cmd, const vector<string>& args,
const string *input, string *output) const string *input, string *output)
{ {
@ -781,8 +797,9 @@ int ExecCmd::doexec(const string &cmd, const vector<string>& args,
myloop.setperiodichandler(0, 0, m->m_timeoutMs); myloop.setperiodichandler(0, 0, m->m_timeoutMs);
while ((ret = myloop.doLoop()) > 0) { while ((ret = myloop.doLoop()) > 0) {
LOGDEB(("ExecCmd::doexec: selectloop returned %d\n", ret)); LOGDEB(("ExecCmd::doexec: selectloop returned %d\n", ret));
if (m->m_advise) if (m->m_advise) {
m->m_advise->newData(0); m->m_advise->newData(0);
}
if (m->m_killRequest) { if (m->m_killRequest) {
LOGINFO(("ExecCmd::doexec: cancel request\n")); LOGINFO(("ExecCmd::doexec: cancel request\n"));
break; break;
@ -790,8 +807,9 @@ int ExecCmd::doexec(const string &cmd, const vector<string>& args,
} }
LOGDEB0(("ExecCmd::doexec: selectloop returned %d\n", ret)); LOGDEB0(("ExecCmd::doexec: selectloop returned %d\n", ret));
// Check for interrupt request: we won't want to waitpid() // Check for interrupt request: we won't want to waitpid()
if (m->m_advise) if (m->m_advise) {
m->m_advise->newData(0); m->m_advise->newData(0);
}
// The netcons don't take ownership of the fds: we have to close them // The netcons don't take ownership of the fds: we have to close them
// (have to do it before wait, this may be the signal the child is // (have to do it before wait, this may be the signal the child is
@ -810,8 +828,9 @@ int ExecCmd::doexec(const string &cmd, const vector<string>& args,
e.inactivate(); e.inactivate();
int ret1 = ExecCmd::wait(); int ret1 = ExecCmd::wait();
if (ret) if (ret) {
return -1; return -1;
}
return ret1; return ret1;
} }
@ -824,8 +843,9 @@ int ExecCmd::send(const string& data)
} }
unsigned int nwritten = 0; unsigned int nwritten = 0;
while (nwritten < data.length()) { while (nwritten < data.length()) {
if (m->m_killRequest) if (m->m_killRequest) {
break; break;
}
int n = con->send(data.c_str() + nwritten, data.length() - nwritten); int n = con->send(data.c_str() + nwritten, data.length() - nwritten);
if (n < 0) { if (n < 0) {
LOGERR(("ExecCmd::send: send failed\n")); LOGERR(("ExecCmd::send: send failed\n"));
@ -873,8 +893,9 @@ int ExecCmd::getline(string& data)
const int BS = 1024; const int BS = 1024;
char buf[BS]; char buf[BS];
int timeosecs = m->m_timeoutMs / 1000; int timeosecs = m->m_timeoutMs / 1000;
if (timeosecs == 0) if (timeosecs == 0) {
timeosecs = 1; timeosecs = 1;
}
// Note that we only go once through here, except in case of // Note that we only go once through here, except in case of
// timeout, which is why I think that the goto is more expressive // timeout, which is why I think that the goto is more expressive
@ -884,8 +905,9 @@ again:
if (n < 0) { if (n < 0) {
if (con->timedout()) { if (con->timedout()) {
LOGDEB(("ExecCmd::getline: timeout\n")); LOGDEB(("ExecCmd::getline: timeout\n"));
if (m->m_advise) if (m->m_advise) {
m->m_advise->newData(0); m->m_advise->newData(0);
}
goto again; goto again;
} }
LOGERR(("ExecCmd::getline: error\n")); LOGERR(("ExecCmd::getline: error\n"));
@ -1006,15 +1028,16 @@ void ReExec::init(int argc, char *args[])
} }
m_cfd = open(".", 0); m_cfd = open(".", 0);
char *cd = getcwd(0, 0); char *cd = getcwd(0, 0);
if (cd) if (cd) {
m_curdir = cd; m_curdir = cd;
}
free(cd); free(cd);
} }
void ReExec::insertArgs(const vector<string>& args, int idx) void ReExec::insertArgs(const vector<string>& args, int idx)
{ {
vector<string>::iterator it, cit; vector<string>::iterator it, cit;
unsigned int cmpoffset = (unsigned int)-1; unsigned int cmpoffset = (unsigned int) - 1;
if (idx == -1 || string::size_type(idx) >= m_argv.size()) { if (idx == -1 || string::size_type(idx) >= m_argv.size()) {
it = m_argv.end(); it = m_argv.end();
@ -1029,7 +1052,7 @@ void ReExec::insertArgs(const vector<string>& args, int idx)
} }
// Check that the option is not already there // Check that the option is not already there
if (cmpoffset != (unsigned int)-1) { if (cmpoffset != (unsigned int) - 1) {
bool allsame = true; bool allsame = true;
for (unsigned int i = 0; i < args.size(); i++) { for (unsigned int i = 0; i < args.size(); i++) {
if (m_argv[cmpoffset + i] != args[i]) { if (m_argv[cmpoffset + i] != args[i]) {
@ -1037,9 +1060,10 @@ void ReExec::insertArgs(const vector<string>& args, int idx)
break; break;
} }
} }
if (allsame) if (allsame) {
return; return;
} }
}
m_argv.insert(it, args.begin(), args.end()); m_argv.insert(it, args.begin(), args.end());
} }
@ -1048,9 +1072,10 @@ void ReExec::removeArg(const string& arg)
{ {
for (vector<string>::iterator it = m_argv.begin(); for (vector<string>::iterator it = m_argv.begin();
it != m_argv.end(); it++) { it != m_argv.end(); it++) {
if (*it == arg) if (*it == arg) {
it = m_argv.erase(it); it = m_argv.erase(it);
} }
}
} }
// Reexecute myself, as close as possible to the initial exec // Reexecute myself, as close as possible to the initial exec
@ -1059,10 +1084,10 @@ void ReExec::reexec()
#if 0 #if 0
char *cwd; char *cwd;
cwd = getcwd(0,0); cwd = getcwd(0, 0);
FILE *fp = stdout; //fopen("/tmp/exectrace", "w"); FILE *fp = stdout; //fopen("/tmp/exectrace", "w");
if (fp) { if (fp) {
fprintf(fp, "reexec: pwd: [%s] args: ", cwd?cwd:"getcwd failed"); fprintf(fp, "reexec: pwd: [%s] args: ", cwd ? cwd : "getcwd failed");
for (vector<string>::const_iterator it = m_argv.begin(); for (vector<string>::const_iterator it = m_argv.begin();
it != m_argv.end(); it++) { it != m_argv.end(); it++) {
fprintf(fp, "[%s] ", it->c_str()); fprintf(fp, "[%s] ", it->c_str());
@ -1091,7 +1116,7 @@ void ReExec::reexec()
// Allocate arg vector (1 more for final 0) // Allocate arg vector (1 more for final 0)
typedef const char *Ccharp; typedef const char *Ccharp;
Ccharp *argv; Ccharp *argv;
argv = (Ccharp *)malloc((m_argv.size()+1) * sizeof(char *)); argv = (Ccharp *)malloc((m_argv.size() + 1) * sizeof(char *));
if (argv == 0) { if (argv == 0) {
LOGERR(("ExecCmd::doexec: malloc() failed. errno %d\n", errno)); LOGERR(("ExecCmd::doexec: malloc() failed. errno %d\n", errno));
return; return;
@ -1167,7 +1192,7 @@ bool exercise_mhexecm(const string& cmdstr, const string& mimetype,
} }
// Read answer // Read answer
for (int loop=0;;loop++) { for (int loop = 0;; loop++) {
string name, data; string name, data;
// Code from mh_execm.cpp: readDataElement // Code from mh_execm.cpp: readDataElement
@ -1217,8 +1242,9 @@ bool exercise_mhexecm(const string& cmdstr, const string& mimetype,
} }
// Empty element: end of message // Empty element: end of message
if (name.empty()) if (name.empty()) {
break; break;
}
cerr << "Got name: [" << name << "] data [" << data << "]\n"; cerr << "Got name: [" << name << "] data [" << data << "]\n";
} }
} }
@ -1228,19 +1254,19 @@ bool exercise_mhexecm(const string& cmdstr, const string& mimetype,
static char *thisprog; static char *thisprog;
static char usage [] = static char usage [] =
"trexecmd [-c -r -i -o] cmd [arg1 arg2 ...]\n" "trexecmd [-c -r -i -o] cmd [arg1 arg2 ...]\n"
" -c : test cancellation (ie: trexecmd -c sleep 1000)\n" " -c : test cancellation (ie: trexecmd -c sleep 1000)\n"
" -r : run reexec. Must be separate option.\n" " -r : run reexec. Must be separate option.\n"
" -i : command takes input\n" " -i : command takes input\n"
" -o : command produces output\n" " -o : command produces output\n"
" If -i is set, we send /etc/group contents to whatever command is run\n" " If -i is set, we send /etc/group contents to whatever command is run\n"
" If -o is set, we print whatever comes out\n" " If -o is set, we print whatever comes out\n"
"trexecmd -m <filter> <mimetype> <file> [file ...]: test execm:\n" "trexecmd -m <filter> <mimetype> <file> [file ...]: test execm:\n"
" <filter> should be the path to an execm filter\n" " <filter> should be the path to an execm filter\n"
" <mimetype> the type of the file parameters\n" " <mimetype> the type of the file parameters\n"
"trexecmd -w cmd : do the 'which' thing\n" "trexecmd -w cmd : do the 'which' thing\n"
"trexecmd -l cmd test getline\n" "trexecmd -l cmd test getline\n"
; ;
static void Usage(void) static void Usage(void)
{ {
@ -1285,14 +1311,14 @@ public:
FILE *m_fp; FILE *m_fp;
string *m_input; string *m_input;
MEPv(string *i) MEPv(string *i)
: m_input(i) : m_input(i) {
{
m_fp = fopen("/etc/group", "r"); m_fp = fopen("/etc/group", "r");
} }
~MEPv() { ~MEPv() {
if (m_fp) if (m_fp) {
fclose(m_fp); fclose(m_fp);
} }
}
void newData() { void newData() {
char line[1024]; char line[1024];
if (m_fp && fgets(line, 1024, m_fp)) { if (m_fp && fgets(line, 1024, m_fp)) {
@ -1322,36 +1348,59 @@ int main(int argc, char *argv[])
} }
thisprog = argv[0]; thisprog = argv[0];
argc--; argv++; argc--;
argv++;
while (argc > 0 && **argv == '-') { while (argc > 0 && **argv == '-') {
(*argv)++; (*argv)++;
if (!(**argv)) if (!(**argv))
/* Cas du "adb - core" */ /* Cas du "adb - core" */
{
Usage(); Usage();
}
while (**argv) while (**argv)
switch (*(*argv)++) { switch (*(*argv)++) {
case 'c': op_flags |= OPT_c; break; case 'c':
case 'r': op_flags |= OPT_r; break; op_flags |= OPT_c;
case 'w': op_flags |= OPT_w; break; break;
case 'r':
op_flags |= OPT_r;
break;
case 'w':
op_flags |= OPT_w;
break;
#ifdef BUILDING_RECOLL #ifdef BUILDING_RECOLL
case 'm': op_flags |= OPT_m; break; case 'm':
op_flags |= OPT_m;
break;
#endif #endif
case 'i': op_flags |= OPT_i; break; case 'i':
case 'l': op_flags |= OPT_l; break; op_flags |= OPT_i;
case 'o': op_flags |= OPT_o; break; break;
default: Usage(); break; case 'l':
} op_flags |= OPT_l;
argc--; argv++; break;
} case 'o':
op_flags |= OPT_o;
if (argc < 1) break;
default:
Usage(); Usage();
break;
}
argc--;
argv++;
}
string arg1 = *argv++; argc--; if (argc < 1) {
Usage();
}
string arg1 = *argv++;
argc--;
vector<string> l; vector<string> l;
while (argc > 0) { while (argc > 0) {
l.push_back(*argv++); argc--; l.push_back(*argv++);
argc--;
} }
#ifdef BUILDING_RECOLL #ifdef BUILDING_RECOLL
@ -1384,8 +1433,9 @@ int main(int argc, char *argv[])
return 1; return 1;
#ifdef BUILDING_RECOLL #ifdef BUILDING_RECOLL
} else if (op_flags & OPT_m) { } else if (op_flags & OPT_m) {
if (l.size() < 2) if (l.size() < 2) {
Usage(); Usage();
}
string mimetype = l[0]; string mimetype = l[0];
l.erase(l.begin()); l.erase(l.begin());
return exercise_mhexecm(arg1, mimetype, l) ? 0 : 1; return exercise_mhexecm(arg1, mimetype, l) ? 0 : 1;
@ -1403,7 +1453,7 @@ int main(int argc, char *argv[])
cerr << "Waiting\n"; cerr << "Waiting\n";
int status = mexec.wait(); int status = mexec.wait();
cerr << "Got status " << status << endl; cerr << "Got status " << status << endl;
exit (status); exit(status);
} else { } else {
// Default: execute command line arguments // Default: execute command line arguments
ExecCmd mexec; ExecCmd mexec;
@ -1447,7 +1497,7 @@ int main(int argc, char *argv[])
if (op_flags & OPT_o) { if (op_flags & OPT_o) {
cout << output; cout << output;
} }
exit (status >> 8); exit(status >> 8);
} }
} }
#endif // TEST #endif // TEST

View file

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

View file

@ -116,12 +116,12 @@ int Netcon::select1(int fd, int timeo, int write)
FD_ZERO(&rd); FD_ZERO(&rd);
FD_SET(fd, &rd); FD_SET(fd, &rd);
if (write) { if (write) {
ret = select(fd+1, 0, &rd, 0, &tv); ret = select(fd + 1, 0, &rd, 0, &tv);
} else { } else {
ret = select(fd+1, &rd, 0, 0, &tv); ret = select(fd + 1, &rd, 0, 0, &tv);
} }
if (!FD_ISSET(fd, &rd)) { if (!FD_ISSET(fd, &rd)) {
LOGDEB2(("Netcon::select1: fd %d timeout\n",fd)); LOGDEB2(("Netcon::select1: fd %d timeout\n", fd));
} }
return ret; return ret;
} }
@ -199,11 +199,11 @@ int SelectLoop::doLoop()
// Walk the netcon map and set up the read and write fd_sets // Walk the netcon map and set up the read and write fd_sets
// for select() // for select()
nfds = 0; 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++) { it != m_polldata.end(); it++) {
NetconP &pll = it->second; NetconP& pll = it->second;
int fd = it->first; 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) { if (pll->m_wantedEvents & Netcon::NETCONPOLL_READ) {
FD_SET(fd, &rd); FD_SET(fd, &rd);
nfds = MAX(nfds, fd + 1); nfds = MAX(nfds, fd + 1);
@ -275,7 +275,7 @@ int SelectLoop::doLoop()
continue; continue;
} }
map<int,NetconP>::iterator it = m_polldata.find(fd); map<int, NetconP>::iterator it = m_polldata.find(fd);
if (it == m_polldata.end()) { if (it == m_polldata.end()) {
/// This should not happen actually /// This should not happen actually
LOGDEB2(("Netcon::selectloop: fd %d not found\n", fd)); 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) // Next start will be one beyond last serviced (modulo nfds)
m_placetostart = fd + 1; m_placetostart = fd + 1;
NetconP &pll = it->second; NetconP& pll = it->second;
if (canread && pll->cando(Netcon::NETCONPOLL_READ) <= 0) { if (canread && pll->cando(Netcon::NETCONPOLL_READ) <= 0) {
pll->m_wantedEvents &= ~Netcon::NETCONPOLL_READ; pll->m_wantedEvents &= ~Netcon::NETCONPOLL_READ;
} }
if (canwrite && pll->cando(Netcon::NETCONPOLL_WRITE) <= 0) { if (canwrite && pll->cando(Netcon::NETCONPOLL_WRITE) <= 0) {
pll->m_wantedEvents &= ~Netcon::NETCONPOLL_WRITE; 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", LOGDEB0(("Netcon::selectloop: fd %d has 0x%x mask, erasing\n",
it->first, it->second->m_wantedEvents)); it->first, it->second->m_wantedEvents));
m_polldata.erase(it); m_polldata.erase(it);
@ -324,7 +324,7 @@ int SelectLoop::remselcon(NetconP con)
return -1; return -1;
} }
LOGDEB1(("Netcon::remselcon: fd %d\n", con->m_fd)); 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()) { if (it == m_polldata.end()) {
LOGDEB1(("Netcon::remselcon: con not found for fd %d\n", con->m_fd)); LOGDEB1(("Netcon::remselcon: con not found for fd %d\n", con->m_fd));
return -1; return -1;
@ -369,7 +369,7 @@ void Netcon::setpeer(const char *hostname)
int Netcon::settcpnodelay(int on) int Netcon::settcpnodelay(int on)
{ {
LOGDEB2(( "Netcon::settcpnodelay\n" )); LOGDEB2(("Netcon::settcpnodelay\n"));
if (m_fd < 0) { if (m_fd < 0) {
LOGERR(("Netcon::settcpnodelay: connection not opened\n")); LOGERR(("Netcon::settcpnodelay: connection not opened\n"));
return -1; return -1;
@ -386,7 +386,7 @@ int Netcon::settcpnodelay(int on)
int Netcon::set_nonblock(int onoff) int Netcon::set_nonblock(int onoff)
{ {
int flags = fcntl(m_fd, F_GETFL, 0); int flags = fcntl(m_fd, F_GETFL, 0);
if (flags != -1 ) { if (flags != -1) {
int newflags = onoff ? flags | O_NONBLOCK : flags & ~O_NONBLOCK; int newflags = onoff ? flags | O_NONBLOCK : flags & ~O_NONBLOCK;
if (newflags != flags) if (newflags != flags)
if (fcntl(m_fd, F_SETFL, newflags) < 0) { 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)); LOGDEB2(("Netcon::doreceive: cnt %d, timeo %d\n", cnt, timeo));
cur = 0; cur = 0;
while (cnt > cur) { while (cnt > cur) {
got = receive(buf, cnt-cur, timeo); got = receive(buf, cnt - cur, timeo);
LOGDEB2(("Netcon::doreceive: got %d\n", got)); LOGDEB2(("Netcon::doreceive: got %d\n", got));
if (got < 0) { if (got < 0) {
return -1; return -1;
@ -551,7 +551,7 @@ int NetconData::getline(char *buf, int cnt, int timeo)
for (;;) { for (;;) {
// Transfer from buffer. Have to take a lot of care to keep counts and // Transfer from buffer. Have to take a lot of care to keep counts and
// pointers consistant in all end cases // pointers consistant in all end cases
int maxtransf = MIN(m_bufbytes, cnt-1); int maxtransf = MIN(m_bufbytes, cnt - 1);
int nn = maxtransf; int nn = maxtransf;
LOGDEB2(("Before loop, bufbytes %d, maxtransf %d, nn: %d\n", LOGDEB2(("Before loop, bufbytes %d, maxtransf %d, nn: %d\n",
m_bufbytes, maxtransf, nn)); m_bufbytes, maxtransf, nn));
@ -723,7 +723,7 @@ int NetconCli::openconn(const char *host, const char *serv, int timeo)
if (host[0] != '/') { if (host[0] != '/') {
struct servent *sp; struct servent *sp;
if ((sp = getservbyname(serv, "tcp")) == 0) { 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; return -1;
} }
// Callee expects the port number in host byte order // 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")); LOGDEB1(("NetconServLis::openservice: service opened ok\n"));
ret = 0; ret = 0;
out: out:
if (ret < 0 && m_fd >= 0) { if (ret < 0 && m_fd >= 0) {
close(m_fd); close(m_fd);
m_fd = -1; m_fd = -1;
@ -846,9 +846,9 @@ int NetconServLis::openservice(int port, int backlog)
LOGSYSERR("NetconServLis", "socket", ""); LOGSYSERR("NetconServLis", "socket", "");
return -1; 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 #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*/ #endif /*SO_REUSEPORT*/
memset(&ipaddr, 0, sizeof(ipaddr)); memset(&ipaddr, 0, sizeof(ipaddr));
ipaddr.sin_family = AF_INET; ipaddr.sin_family = AF_INET;
@ -1033,7 +1033,7 @@ NetconServLis::checkperms(void *cl, int)
if (i < okmasks.len) { if (i < okmasks.len) {
mask = okmasks.intarray[i]; mask = okmasks.intarray[i];
} else { } else {
mask = okmasks.intarray[okmasks.len-1]; mask = okmasks.intarray[okmasks.len - 1];
} }
LOGDEB2(("checkperms: trying okaddr 0x%x, mask 0x%x\n", LOGDEB2(("checkperms: trying okaddr 0x%x, mask 0x%x\n",
okaddrs.intarray[i], mask)); okaddrs.intarray[i], mask));
@ -1271,7 +1271,7 @@ public:
} }
if (reason & Netcon::NETCONPOLL_READ) { if (reason & Netcon::NETCONPOLL_READ) {
#define LL 200 #define LL 200
char buf[LL+1]; char buf[LL + 1];
int n; int n;
if ((n = con->receive(buf, LL)) < 0) { if ((n = con->receive(buf, LL)) < 0) {
fprintf(stderr, "receive failed\n"); fprintf(stderr, "receive failed\n");
@ -1282,7 +1282,7 @@ public:
} }
buf[n] = 0; buf[n] = 0;
fprintf(stderr, "%d received \"%s\"\n", getpid(), buf); 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; return 0;
} }
@ -1292,7 +1292,7 @@ private:
class MyNetconServLis : public NetconServLis { class MyNetconServLis : public NetconServLis {
public: public:
MyNetconServLis(SelectLoop &loop) MyNetconServLis(SelectLoop& loop)
: NetconServLis(), m_loop(loop) { : NetconServLis(), m_loop(loop) {
} }
protected: protected:

View file

@ -48,7 +48,7 @@ class SelectLoop;
class Netcon { class Netcon {
public: public:
enum Event {NETCONPOLL_READ = 0x1, NETCONPOLL_WRITE=0x2}; enum Event {NETCONPOLL_READ = 0x1, NETCONPOLL_WRITE = 0x2};
Netcon() Netcon()
: m_peer(0), m_fd(-1), m_ownfd(true), m_didtimo(0), m_wantedEvents(0), : m_peer(0), m_fd(-1), m_ownfd(true), m_didtimo(0), m_wantedEvents(0),
m_loop(0) { m_loop(0) {

View file

@ -22,12 +22,16 @@
#endif #endif
#include <errno.h> #include <errno.h>
#include "safefcntl.h"
#include <sys/types.h> #include <sys/types.h>
#ifdef _WIN32
#include "safefcntl.h"
#include "safesysstat.h" #include "safesysstat.h"
#include "safeunistd.h" #include "safeunistd.h"
#ifndef _WIN32 #else
#define O_BINARY 0 #define O_BINARY 0
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#endif #endif
#include <string> #include <string>
@ -41,8 +45,9 @@ public:
FileToString(string& data) : m_data(data) {} FileToString(string& data) : m_data(data) {}
string& m_data; string& m_data;
bool init(size_t size, string *reason) { bool init(size_t size, string *reason) {
if (size > 0) if (size > 0) {
m_data.reserve(size); m_data.reserve(size);
}
return true; return true;
} }
bool data(const char *buf, int cnt, string *reason) { bool data(const char *buf, int cnt, string *reason) {
@ -56,18 +61,18 @@ public:
} }
}; };
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); 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) string *reason)
{ {
FileToString accum(data); FileToString accum(data);
return file_scan(fn, &accum, offs, cnt, reason); 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); 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()) // 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 // Also tried a version with mmap, but it's actually slower on the mac and not
// faster on linux. // 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) size_t cnttoread, string *reason)
{ {
if (startoffs < 0) { if (startoffs < 0) {
@ -94,7 +99,7 @@ bool file_scan(const string &fn, FileScanDo* doer, off_t startoffs,
// If we have a file name, open it, else use stdin. // If we have a file name, open it, else use stdin.
if (!fn.empty()) { if (!fn.empty()) {
fd = open(fn.c_str(), O_RDONLY|O_BINARY); fd = open(fn.c_str(), O_RDONLY | O_BINARY);
if (fd < 0 || fstat(fd, &st) < 0) { if (fd < 0 || fstat(fd, &st) < 0) {
catstrerror(reason, "open/stat", errno); catstrerror(reason, "open/stat", errno);
return false; return false;
@ -108,10 +113,10 @@ bool file_scan(const string &fn, FileScanDo* doer, off_t startoffs,
} }
#endif #endif
if (cnttoread != (size_t)-1 && cnttoread) { if (cnttoread != (size_t) - 1 && cnttoread) {
doer->init(cnttoread+1, reason); doer->init(cnttoread + 1, reason);
} else if (st.st_size > 0) { } 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 { } else {
doer->init(0, reason); doer->init(0, reason);
} }
@ -141,25 +146,29 @@ bool file_scan(const string &fn, FileScanDo* doer, off_t startoffs,
catstrerror(reason, "read", errno); catstrerror(reason, "read", errno);
goto out; goto out;
} }
if (n == 0) if (n == 0) {
break; break;
}
curoffs += n; curoffs += n;
if (curoffs - n < startoffs) if (curoffs - n < startoffs) {
continue; continue;
}
if (!doer->data(buf, n, reason)) { if (!doer->data(buf, n, reason)) {
goto out; goto out;
} }
totread += n; totread += n;
if (cnttoread > 0 && totread >= cnttoread) if (cnttoread > 0 && totread >= cnttoread) {
break; break;
} }
}
ret = true; ret = true;
out: out:
if (fd >= 0 && !noclosing) if (fd >= 0 && !noclosing) {
close(fd); close(fd);
}
return ret; return ret;
} }
@ -181,11 +190,10 @@ using namespace std;
using namespace std; using namespace std;
class myCB : public FsTreeWalkerCB { class myCB : public FsTreeWalkerCB {
public: public:
FsTreeWalker::Status processone(const string &path, FsTreeWalker::Status processone(const string& path,
const struct stat *st, const struct stat *st,
FsTreeWalker::CbFlag flg) FsTreeWalker::CbFlag flg) {
{
if (flg == FsTreeWalker::FtwDirEnter) { if (flg == FsTreeWalker::FtwDirEnter) {
//cout << "[Entering " << path << "]" << endl; //cout << "[Entering " << path << "]" << endl;
} else if (flg == FsTreeWalker::FtwDirReturn) { } else if (flg == FsTreeWalker::FtwDirReturn) {
@ -214,8 +222,8 @@ static int op_flags;
static const char *thisprog; static const char *thisprog;
static char usage [] = static char usage [] =
"trreadfile [-o offs] [-c cnt] topdirorfile\n\n" "trreadfile [-o offs] [-c cnt] topdirorfile\n\n"
; ;
static void static void
Usage(void) Usage(void)
{ {
@ -228,29 +236,48 @@ int main(int argc, const char **argv)
off_t offs = 0; off_t offs = 0;
size_t cnt = size_t(-1); size_t cnt = size_t(-1);
thisprog = argv[0]; thisprog = argv[0];
argc--; argv++; argc--;
argv++;
while (argc > 0 && **argv == '-') { while (argc > 0 && **argv == '-') {
(*argv)++; (*argv)++;
if (!(**argv)) if (!(**argv))
/* Cas du "adb - core" */ /* Cas du "adb - core" */
{
Usage(); Usage();
}
while (**argv) while (**argv)
switch (*(*argv)++) { switch (*(*argv)++) {
case 'c': op_flags |= OPT_c; if (argc < 2) Usage(); case 'c':
cnt = atoll(*(++argv)); argc--; op_flags |= OPT_c;
goto b1; if (argc < 2) {
case 'o': op_flags |= OPT_o; if (argc < 2) Usage(); Usage();
offs = strtoull(*(++argv), 0, 0); argc--;
goto b1;
default: Usage(); break;
} }
b1: argc--; argv++; 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) if (argc != 1) {
Usage(); Usage();
string top = *argv++;argc--; }
string top = *argv++;
argc--;
cerr << "filename " << top << " offs " << offs << " cnt " << cnt << endl; cerr << "filename " << top << " offs " << offs << " cnt " << cnt << endl;
struct stat st; struct stat st;
@ -262,8 +289,9 @@ int main(int argc, const char **argv)
FsTreeWalker walker; FsTreeWalker walker;
myCB cb; myCB cb;
walker.walk(top, cb); walker.walk(top, cb);
if (walker.getErrCnt() > 0) if (walker.getErrCnt() > 0) {
cout << walker.getReason(); cout << walker.getReason();
}
} else { } else {
string s, reason; string s, reason;
if (!file_to_string(top, s, offs, cnt, &reason)) { if (!file_to_string(top, s, offs, cnt, &reason)) {

View file

@ -31,20 +31,20 @@ public:
virtual bool init(size_t size, std::string *reason) = 0; virtual bool init(size_t size, std::string *reason) = 0;
virtual bool data(const char *buf, int cnt, 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) /* Same but only process count cnt from offset offs. Set cnt to size_t(-1)
* for no limit */ * 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); std::string *reason = 0);
/** /**
* Read file into string. * Read file into string.
* @return true for ok, false else * @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 */ /** 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); off_t offs, size_t cnt, std::string *reason = 0);
#endif /* _READFILE_H_INCLUDED_ */ #endif /* _READFILE_H_INCLUDED_ */