#include "port.h"
#ifndef WIN32
#include <unistd.h>
#endif
#include "zcav_io.h"
#include "thread.h"
#ifdef NON_UNIX
#include "getopt.h"
#endif
#define TOO_MANY_LOOPS 100
void usage()
{
fprintf(stderr
, "Usage: zcav [-b block-size] [-c count] [-s max-size] [-w]\n"
#ifndef NON_UNIX
" [-u uid-to-use:gid-to-use] [-g gid-to-use]\n"
#endif
" [-l log-file] [-f] file-name\n"
" [-l log-file [-f] file-name]...\n"
"\n"
"File name of \"-\" means standard input\n"
"Count is the number of times to read the data (default 1).\n"
"Max size is the amount of data to read from each device.\n"
"\n"
"Version: " BON_VERSION "\n");
exit(1);
}
class MultiZcav : public Thread
{
public:
MultiZcav();
MultiZcav(int threadNum, const MultiZcav *parent);
virtual ~MultiZcav();
virtual int action(PVOID param);
int runit();
void setFileLogNames(const char *file, const char *log)
{
m_fileNames.push_back(file);
m_logNames.push_back(log);
m_readers->push_back(new ZcavRead);
}
void setBlockSize(int block_size)
{
m_block_size = block_size;
if(m_block_size < 1)
usage();
}
void setLoops(int max_loops)
{
m_max_loops = max_loops;
if(max_loops < 1 || max_loops > TOO_MANY_LOOPS)
usage();
}
void setMaxSize(int max_size)
{
m_max_size = max_size;
if(max_size < 1)
usage();
}
private:
virtual Thread *newThread(int threadNum)
{ return new MultiZcav(threadNum, this); }
vector<const char *> m_fileNames, m_logNames;
vector<ZcavRead *> *m_readers;
int m_block_size, m_max_loops, m_max_size;
MultiZcav(const MultiZcav &m);
MultiZcav & operator =(const MultiZcav &m);
};
MultiZcav::MultiZcav()
{
m_block_size = 100;
m_max_loops = 1;
m_max_size = 0;
m_readers = new vector<ZcavRead *>;
}
MultiZcav::MultiZcav(int threadNum, const MultiZcav *parent)
: Thread(threadNum, parent)
, m_readers(parent->m_readers)
, m_block_size(parent->m_block_size)
, m_max_loops(parent->m_max_loops)
, m_max_size(parent->m_max_size)
{
}
int MultiZcav::action(PVOID)
{
ZcavRead *zc = (*m_readers)[getThreadNum() - 1];
int rc = zc->Read(m_max_loops, m_max_size / m_block_size, m_write);
zc->Close();
return rc;
}
MultiZcav::~MultiZcav()
{
if(getThreadNum() < 1)
{
while(m_readers->size())
{
delete m_readers->back();
m_readers->pop_back();
}
delete m_readers;
}
}
int MultiZcav::runit()
{
unsigned int i;
unsigned int num_threads = m_fileNames.size();
if(num_threads < 1)
usage();
for(i = 0; i < num_threads; i++)
{
if((*m_readers)[i]->Open(NULL, m_block_size, m_fileNames[i], m_logNames[i]))
{
return 1;
}
}
go(NULL, num_threads);
int res = 0;
while(num_threads)
{
char c = 0;
if(Read(&c, 1, 0) != 1)
printf("can't read!\n");
num_threads--;
if(c > res)
res = c;
}
return res;
}
int main(int argc, char *argv[])
{
MultiZcav mz;
if(argc < 2)
usage();
#ifndef NON_UNIX
char *userName = NULL, *groupName = NULL;
#endif
int c;
const char *log = "-";
while(-1 != (c = getopt(argc, argv, "-c:b:f:l:s:w"
#ifndef NON_UNIX
"u:g:"
#endif
)) )
{
switch(char(c))
{
case 'b':
mz.setBlockSize(atoi(optarg));
break;
case 'c':
mz.setLoops(atoi(optarg));
break;
case 'l':
log = optarg;
break;
case 's':
mz.setMaxSize(atoi(optarg));
break;
#ifndef NON_UNIX
case 'g':
if(groupName)
usage();
groupName = optarg;
break;
case 'u':
{
if(userName)
usage();
userName = strdup(optarg);
int i;
for(i = 0; userName[i] && userName[i] != ':'; i++);
if(userName[i] == ':')
{
if(groupName)
usage();
userName[i] = '\0';
groupName = &userName[i + 1];
}
}
#endif
break;
break;
case 'f':
case char(1):
mz.setFileLogNames(optarg, log);
log = "-";
break;
default:
usage();
}
}
#ifndef NON_UNIX
if(userName || groupName)
{
if(bon_setugid(userName, groupName, false))
return 1;
if(userName)
free(userName);
}
#endif
int rc = mz.runit();
sleep(2); // time for all threads to complete
return rc;
}
syntax highlighted by Code2HTML, v. 0.9.1