45 #include <sys/types.h>
51 typedef std::set<io::ObservedFile>
fileset;
64 : interval(5000), rounds(3), path(
"/"), regex_str(
"^\\."),
65 bundle_group(
false), invert(
false), quiet(
false), fat(
false), enabled(
true)
78 std::string regex_str;
91 {
"destination", required_argument, 0,
'd'},
92 {
"help", no_argument, 0,
'h'},
93 {
"group", no_argument, 0,
'g'},
94 {
"workdir", required_argument, 0,
'w'},
95 {
"interval", required_argument, 0,
'i'},
96 {
"rounds", required_argument, 0,
'r'},
97 {
"path", required_argument, 0,
'p'},
98 {
"regex", required_argument, 0,
'R'},
99 {
"quiet", no_argument, 0,
'q'},
104 std::cout <<
"-- dtnoutbox (IBR-DTN) --" << std::endl;
105 std::cout <<
"Syntax: dtnoutbox [options] <name> <outbox> <destination>" << std::endl;
106 std::cout <<
" <name> The application name" << std::endl;
108 std::cout <<
" <outbox> Location of outgoing files, directory or vfat-image" << std::endl;
110 std::cout <<
" <outbox> Directory of outgoing files" << std::endl;
112 std::cout <<
" <destination> The destination EID for all outgoing files" << std::endl << std::endl;
113 std::cout <<
"* optional parameters *" << std::endl;
114 std::cout <<
" -h|--help Display this text" << std::endl;
115 std::cout <<
" -g|--group Receiver is a destination group" << std::endl;
116 std::cout <<
" -w|--workdir <dir>" << std::endl;
117 std::cout <<
" Temporary work directory" << std::endl;
118 std::cout <<
" -i|--interval <milliseconds>" << std::endl;
119 std::cout <<
" Interval in milliseconds, in which <outbox> is scanned" << std::endl;
120 std::cout <<
" for new/changed files. default: 5000" << std::endl;
121 std::cout <<
" -r|--rounds <n> Number of rounds of intervals, after which a unchanged" << std::endl;
122 std::cout <<
" file is considered as written. default: 3" << std::endl;
124 std::cout <<
" -p|--path <path> Path of outbox within vfat-image. default: /" << std::endl;
126 std::cout <<
" -R|--regex <regex>" << std::endl;
127 std::cout <<
" All files in <outbox> matching this regular expression" << std::endl;
128 std::cout <<
" will be ignored. default: ^\\." << std::endl;
129 std::cout <<
" -I|--invert Invert the regular expression defined with -R"<< std::endl;
130 std::cout <<
" -q|--quiet Only print error messages" << std::endl;
148 int option_index = 0;
149 int c = getopt_long (argc, argv,
"hw:i:r:p:R:qIg",
163 printf (
" with arg %s", optarg);
172 conf.bundle_group =
true;
175 conf.workdir = std::string(optarg);
178 conf.interval = atoi(optarg);
181 conf.rounds = atoi(optarg);
184 conf.path = std::string(optarg);
187 conf.regex_str = std::string(optarg);
203 conf.name = std::string(argv[optind]);
204 conf.destination = std::string(argv[optind+2]);
205 conf.outbox = std::string(argv[optind+1]);
208 if (conf.regex_str.length() > 0 && regcomp(&conf.regex,conf.regex_str.c_str(),0))
210 std::cout <<
"ERROR: invalid regex: " << optarg << std::endl;
216 if (conf.outbox.at(conf.outbox.length()-1) ==
'/')
217 conf.outbox = conf.outbox.substr(0,conf.outbox.length() -1);
251 int main(
int argc,
char** argv )
255 sighandler.
handle(SIGINT);
256 sighandler.
handle(SIGTERM);
258 sighandler.
handle(SIGUSR1);
271 if (conf.workdir.length() > 0)
282 unsigned int backoff = 2;
287 fileset new_files, prev_files, deleted_files, files_to_send;
303 const io::FATFile fat_root(*imagereader, conf.path);
306 std::cout <<
"ERROR: image-file provided, but this tool has been compiled without libtffs support!" << std::endl;
312 if (!outbox_file.
exists()) {
318 if (!conf.quiet) std::cout <<
"-- dtnoutbox --" << std::endl;
348 std::set_difference(prev_files.begin(), prev_files.end(), current_files.begin(), current_files.end(), std::inserter(deleted_files, deleted_files.begin()));
351 for (fileset::const_iterator iter = deleted_files.begin(); iter != deleted_files.end(); ++iter)
356 for (hashlist::iterator hash_it = sent_hashes.begin(); hash_it != sent_hashes.end(); ) {
358 sent_hashes.erase(hash_it++);
365 observed_files.remove(deletedFile);
368 if (!conf.quiet) std::cout <<
"file removed: " << deletedFile.
getFile().
getBasename() << std::endl;
373 std::set_difference(current_files.begin(), current_files.end(), prev_files.begin(), prev_files.end(), std::inserter(new_files, new_files.begin()));
376 for (fileset::const_iterator iter = new_files.begin(); iter != new_files.end(); ++iter)
381 if (!reg_ret && !conf.invert)
383 if (reg_ret && conf.invert)
387 if (reg_ret && reg_ret != REG_NOMATCH)
390 regerror(reg_ret,&conf.regex,msgbuf,
sizeof(msgbuf));
391 std::cerr <<
"ERROR: regex match failed : " << std::string(msgbuf) << std::endl;
395 observed_files.push_back(of);
398 if (!conf.quiet) std::cout <<
"file found: " << of.
getFile().
getBasename() << std::endl;
403 prev_files.insert(current_files.begin(), current_files.end());
406 files_to_send.clear();
408 for (filelist::iterator iter = observed_files.begin(); iter != observed_files.end(); ++iter)
417 if (sent_hashes.find(of.
getHash()) == sent_hashes.end())
419 sent_hashes.insert(of.
getHash());
420 files_to_send.insert(*iter);
425 if (!files_to_send.empty())
429 std::cout <<
"send files: ";
430 for (fileset::const_iterator it = files_to_send.begin(); it != files_to_send.end(); ++it) {
431 std::cout << (*it).getFile().getBasename() <<
" ";
433 std::cout << std::endl;
459 if (conf.bundle_group)
466 std::cerr <<
"send failed: " << e.
what() << std::endl;
473 _wait_cond.
wait(conf.interval);
479 regfree(&conf.regex);
492 std::cout <<
"Connection to bundle daemon failed. Retry in " << backoff <<
" seconds." << std::endl;
499 backoff = backoff * 2;
507 std::cout <<
"Connection to bundle daemon failed. Retry in " << backoff <<
" seconds." << std::endl;
514 backoff = backoff * 2;
518 catch (
const std::exception&) { };
522 observed_files.clear();
526 if (imagereader != NULL)
delete imagereader;
529 return (EXIT_SUCCESS);