#include "port.h" #ifndef WIN32 #include #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 m_fileNames, m_logNames; vector *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; } 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; }