00001 #include "config.h"
00002
00003 #include <iostream>
00004 #include <string>
00005 #include <fstream>
00006 #include <vector>
00007 #include <map>
00008 #include <algorithm>
00009 #include <cctype>
00010
00011 #include "asserts.h"
00012 #include "error.h"
00013 #include "estring.h"
00014 #include "fs.h"
00015 #include "tstamp.h"
00016
00017 #include "rconfig.h"
00018
00019
00020
00021
00022 void archive_path_element::clear(void)
00023 {
00024 m_type = jobname;
00025 m_literal.erase();
00026 }
00027
00028
00029 archive_path_element::archive_path_element()
00030 {
00031 clear();
00032 }
00033
00034
00035 archive_path_element::archive_path_element(
00036 const archive_path_element& a_class)
00037 {
00038 clear();
00039 assign(a_class);
00040 }
00041
00042
00043 archive_path_element::archive_path_element(
00044 const archive_path_element::element_type& a_enum
00045 )
00046 {
00047 clear();
00048 assign(a_enum);
00049 }
00050
00051
00052 archive_path_element::archive_path_element(const std::string& a_str)
00053 {
00054 clear();
00055 assign(a_str);
00056 }
00057
00058
00059 void archive_path_element::assign(const archive_path_element& a_class)
00060 {
00061 if (this == &a_class)
00062 return;
00063
00064 if (a_class.type() == literal)
00065 assign(a_class.str());
00066 else
00067 assign(a_class.type());
00068 }
00069
00070
00071 void archive_path_element::assign(
00072 const archive_path_element::element_type& a_enum
00073 )
00074 {
00075 m_type = a_enum;
00076 if (m_type != literal) {
00077 m_literal.erase();
00078 }
00079 }
00080
00081
00082 void archive_path_element::assign(const std::string& a_str)
00083 {
00084 std::string es;
00085 std::string str;
00086 std::string::size_type idx;
00087
00088 TRY_nomem(es = "Invalid archive-path keyword: \"");
00089 TRY_nomem(es += a_str);
00090 TRY_nomem(es += "\"");
00091
00092 if (a_str.size() == 0) {
00093 throw(ERROR(0,es));
00094 }
00095 if (a_str[0] == '"') {
00096 if (a_str.size() < 3) {
00097 throw(ERROR(0,es));
00098 }
00099 if (a_str[a_str.size()-1] != '"') {
00100 throw(ERROR(0,es));
00101 }
00102 TRY_nomem(str = a_str.substr(1,a_str.size()-2));
00103
00104 idx = str.find('"');
00105 while (idx != std::string::npos) {
00106 if ((idx > 0) && (str[idx-1] != '\\'))
00107 throw(ERROR(0,es));
00108 idx = str.find('"',idx+1);
00109 }
00110
00111 idx = str.find("\\\"");
00112 while (idx != std::string::npos) {
00113 str.erase(idx,1);
00114 idx = str.find("\\\"");
00115 }
00116
00117 TRY_nomem(m_literal = str);
00118 m_type = literal;
00119 }
00120 else {
00121 str = estring(a_str).lower();
00122 if (str == "jobname") {
00123 assign(jobname);
00124 }
00125 else if (str == "groupname") {
00126 assign(groupname);
00127 }
00128 else if (str == "hostname") {
00129 assign(hostname);
00130 }
00131 else if (str == "pathname") {
00132 assign(pathname);
00133 }
00134 else if (str == "permutation") {
00135 assign(permutation);
00136 }
00137 else {
00138 throw(ERROR(0,es));
00139 }
00140 }
00141 }
00142
00143
00144 const archive_path_element::element_type&
00145 archive_path_element::type(void) const
00146 {
00147 return(m_type);
00148 }
00149
00150
00151 const std::string& archive_path_element::value(void) const
00152 {
00153 return(m_literal);
00154 }
00155
00156
00157 const std::string archive_path_element::str(void) const
00158 {
00159 std::string::size_type idx;
00160 std::string value;
00161
00162 if (m_type == jobname) {
00163 TRY_nomem(value = "jobname");
00164 }
00165 else if (m_type == groupname) {
00166 TRY_nomem(value = "groupname");
00167 }
00168 else if (m_type == hostname) {
00169 TRY_nomem(value = "hostname");
00170 }
00171 else if (m_type == pathname) {
00172 TRY_nomem(value = "pathname");
00173 }
00174 else if (m_type == permutation) {
00175 TRY_nomem(value = "permutation");
00176 }
00177 else {
00178 TRY_nomem(value = "\"");
00179 for (idx = 0; idx != m_literal.size(); idx++) {
00180 if (m_literal[idx] == '"') {
00181 TRY_nomem(value += '\\');
00182 }
00183 TRY_nomem(value += m_literal[idx]);
00184 }
00185 TRY_nomem(value += '"');
00186 }
00187
00188 return(value);
00189 }
00190
00191
00192 archive_path_element&
00193 archive_path_element::operator=(const archive_path_element& a_class)
00194 {
00195 clear();
00196 assign(a_class);
00197
00198 return(*this);
00199 }
00200
00201
00202 archive_path_element&
00203 archive_path_element::operator=(
00204 const archive_path_element::element_type a_enum)
00205 {
00206 clear();
00207 assign(a_enum);
00208
00209 return(*this);
00210 }
00211
00212
00213 archive_path_element&
00214 archive_path_element::operator=(const std::string& a_str)
00215 {
00216 clear();
00217 assign(a_str);
00218
00219 return(*this);
00220 }
00221
00222
00223
00224
00225 void archive_path::reset(void)
00226 {
00227 clear();
00228 push_back("hostname/pathname");
00229 }
00230
00231
00232 archive_path::archive_path()
00233 {
00234 reset();
00235 }
00236
00237
00238 archive_path::archive_path(const archive_path& a_class)
00239 {
00240 push_back(a_class);
00241 }
00242
00243
00244 archive_path::archive_path(const archive_path_element& a_class)
00245 {
00246 push_back(a_class);
00247 }
00248
00249
00250 archive_path::archive_path(const std::string& a_str)
00251 {
00252 push_back(a_str);
00253 }
00254
00255
00256 void archive_path::push_back(const archive_path& a_class)
00257 {
00258 const_iterator li;
00259
00260 for (li = a_class.begin(); li != a_class.end(); li++) {
00261 TRY_nomem(push_back(*li));
00262 }
00263 }
00264
00265
00266 void archive_path::push_back(const archive_path_element& a_class)
00267 {
00268 TRY_nomem(type::push_back(a_class));
00269 }
00270
00271
00272 void archive_path::push_back(const std::string& a_str)
00273 {
00274 std::string es;
00275 std::string keyword;
00276 std::string str;
00277 std::string::size_type idx;
00278 archive_path_element ape;
00279
00280 if (a_str.size() == 0)
00281 return;
00282
00283 TRY_nomem(str = a_str);
00284 if (str[0] == '/')
00285 str.erase(0,1);
00286 if (str[str.size()-1] == '/')
00287 str.erase(str.size()-1,1);
00288
00289 while (str.size() > 0) {
00290 idx = str.find('/');
00291 if (idx == std::string::npos) {
00292 TRY_nomem(keyword = str);
00293 str.erase();
00294 }
00295 else {
00296 TRY_nomem(keyword = str.substr(0,idx));
00297 str.erase(0,idx+1);
00298 }
00299
00300 ape.clear();
00301 TRY_nomem(es = "At: \"");
00302 TRY_nomem(es += keyword);
00303 TRY_nomem(es += "\"");
00304 TRY(ape.assign(keyword),es);
00305 TRY_nomem(push_back(ape));
00306 }
00307 }
00308
00309
00310 const std::string archive_path::str(void) const
00311 {
00312 std::string str;
00313 const_iterator li;
00314
00315 for (li = begin(); li != end(); li++) {
00316 if (li != begin()) {
00317 TRY_nomem(str += '/');
00318 }
00319 TRY_nomem(str += (*li).str());
00320 }
00321
00322 return(str);
00323 }
00324
00325
00326 void archive_path::assign(const archive_path& a_class)
00327 {
00328 if (this != &a_class) {
00329 clear();
00330 push_back(a_class);
00331 }
00332 }
00333
00334
00335 void archive_path::assign(const archive_path_element& a_class)
00336 {
00337 clear();
00338 push_back(a_class);
00339 }
00340
00341
00342 void archive_path::assign(const std::string& a_str)
00343 {
00344 clear();
00345 push_back(a_str);
00346 }
00347
00348
00349 archive_path& archive_path::operator=(const archive_path& a_class)
00350 {
00351 assign(a_class);
00352
00353 return(*this);
00354 }
00355
00356
00357 archive_path& archive_path::operator=(const archive_path_element& a_class)
00358 {
00359 assign(a_class);
00360
00361 return(*this);
00362 }
00363
00364
00365 archive_path& archive_path::operator=(const std::string& a_str)
00366 {
00367 assign(a_str);
00368
00369 return(*this);
00370 }
00371
00372
00373
00374
00375 const uint16 rsync_behavior::default_behavior;
00376
00377
00378 void rsync_behavior::clear(void)
00379 {
00380 m_map.clear();
00381 m_default = retry;
00382 }
00383
00384
00385 void rsync_behavior::reset(void)
00386 {
00387 clear();
00388 m_default = retry;
00389 TRY_nomem(
00390 m_map[0] = ok;
00391 m_map[1] = fail;
00392 m_map[2] = fail;
00393 m_map[4] = fail;
00394 m_map[23] = retry_without_hardlinks;
00395 m_map[124] = fail;
00396 m_map[125] = fail;
00397 m_map[126] = fail;
00398 m_map[127] = fail;
00399 );
00400 }
00401
00402
00403 rsync_behavior::rsync_behavior()
00404 {
00405 reset();
00406 }
00407
00408
00409 rsync_behavior::rsync_behavior(const rsync_behavior& a_class)
00410 {
00411 assign(a_class);
00412 }
00413
00414
00415 void rsync_behavior::assign(const uint16 a_code, const value_type a_action)
00416 {
00417 if (a_code == default_behavior)
00418 m_default = a_action;
00419 else {
00420 TRY_nomem(m_map[a_code] = a_action);
00421 }
00422 }
00423
00424
00425 void rsync_behavior::assign(const rsync_behavior& a_class)
00426 {
00427 if (this == &a_class)
00428 return;
00429
00430 clear();
00431 m_default = a_class.default_value();
00432 TRY_nomem(m_map = a_class.map_value());
00433 }
00434
00435
00436
00437
00438
00439 void rsync_behavior::assign(const std::string& a_str)
00440 {
00441 std::string es;
00442 std::string code_str;
00443 std::string action_str;
00444 uint16 code;
00445 rsync_behavior::behavior_type action;
00446 std::string::size_type idx;
00447
00448 TRY_nomem(es = "Invalid rsync-behavior value: \"");
00449 TRY_nomem(es += a_str);
00450 TRY_nomem(es += "\"");
00451
00452 TRY_nomem(action_str = a_str);
00453 idx = 0;
00454 while (isdigit(action_str[idx]) || (action_str[idx] == '*'))
00455 ++idx;
00456 TRY_nomem(code_str = action_str.substr(0,idx));
00457 action_str.erase(0,idx);
00458 if (code_str.size() == 0)
00459 throw(ERROR(0,es));
00460
00461 idx = 0;
00462 while ((action_str[idx] == ' ') || (action_str[idx] == '\t'))
00463 idx++;
00464 action_str.erase(0,idx);
00465
00466 if (action_str[0] != '=')
00467 throw(ERROR(0,es));
00468 action_str.erase(0,1);
00469
00470 idx = 0;
00471 while ((action_str[idx] == ' ') || (action_str[idx] == '\t'))
00472 idx++;
00473 action_str.erase(0,idx);
00474
00475 if (code_str == "*")
00476 code = rsync_behavior::default_behavior;
00477 else
00478 code = estring(code_str);
00479 if (estring(action_str).lower() == "ok")
00480 action = rsync_behavior::ok;
00481 else if (estring(action_str).lower() == "fail")
00482 action = rsync_behavior::fail;
00483 else if (estring(action_str).lower() == "retry")
00484 action = rsync_behavior::retry;
00485 else if (estring(action_str).lower() == "retry-without-hardlinks")
00486 action = rsync_behavior::retry_without_hardlinks;
00487 else if (estring(action_str).lower() == "ok")
00488 action = rsync_behavior::quit;
00489 else
00490 throw(ERROR(0,es));
00491 assign(code, action);
00492 }
00493
00494
00495 const rsync_behavior::value_type
00496 rsync_behavior::operator[](const uint16 a_code) const
00497 {
00498 if (a_code == default_behavior) {
00499 return(m_default);
00500 }
00501 if (m_map.find(a_code) != m_map.end()) {
00502 return(m_map.find(a_code)->second);
00503 }
00504 return(m_default);
00505 }
00506
00507
00508 rsync_behavior::value_type&
00509 rsync_behavior::operator[](const uint16 a_code)
00510 {
00511 if (a_code == default_behavior) {
00512 return(m_default);
00513 }
00514 return(m_map[a_code]);
00515 }
00516
00517
00518 rsync_behavior& rsync_behavior::operator=(const rsync_behavior& a_class)
00519 {
00520 assign(a_class);
00521
00522 return(*this);
00523 }
00524
00525
00526 rsync_behavior&
00527 rsync_behavior::operator=(const rsync_behavior::behavior_type a_enum)
00528 {
00529 assign(default_behavior, a_enum);
00530
00531 return(*this);
00532 }
00533
00534
00535 rsync_behavior& rsync_behavior::operator=(const std::string& a_str)
00536 {
00537 assign(a_str);
00538
00539 return(*this);
00540 }
00541
00542
00543 const rsync_behavior::behavior_type rsync_behavior::default_value(void) const
00544 {
00545 return(m_default);
00546 }
00547
00548
00549 const rsync_behavior::map_type& rsync_behavior::map_value(void) const
00550 {
00551 return(m_map);
00552 }
00553
00554
00555
00556
00557 job::job()
00558 {
00559 clear();
00560 }
00561
00562
00563 job::job(const job& a_job)
00564 {
00565 clear();
00566 assign(a_job);
00567 }
00568
00569
00570 void job::clear(void)
00571 {
00572 default_config_path.erase();
00573 default_config_line = 0;
00574 config_path.erase();
00575 config_line = 0;
00576 archive_path = "hostname/pathname";
00577 excludes.clear();
00578 includes.clear();
00579 groupname.erase();
00580 hostname.erase();
00581 jobname.erase();
00582 paths.clear();
00583 rsync_behavior.reset();
00584 rsync_connection = connection_remote;
00585 rsync_hardlink = true;
00586 rsync_options.erase();
00587 rsync_remote_user.erase();
00588 rsync_remote_path.erase();
00589 rsync_remote_port = 0;
00590 rsync_remote_module.erase();
00591 rsync_retry_count = 3;
00592 rsync_timeout = 60 * 60 * 4;
00593 }
00594
00595
00596 void job::assign(const job& a_job)
00597 {
00598 clear();
00599
00600 default_config_path = a_job.default_config_path;
00601 default_config_line = a_job.default_config_line;
00602 config_path = a_job.config_path;
00603 config_line = a_job.config_line;
00604 archive_path = a_job.archive_path;
00605 excludes = a_job.excludes;
00606 includes = a_job.includes;
00607 groupname = a_job.groupname;
00608 hostname = a_job.hostname;
00609 jobname = a_job.jobname;
00610 paths = a_job.paths;
00611 rsync_behavior.clear();
00612 rsync_behavior = a_job.rsync_behavior;
00613 rsync_connection = a_job.rsync_connection;
00614 rsync_hardlink = a_job.rsync_hardlink;
00615 rsync_options = a_job.rsync_options;
00616 rsync_remote_user = a_job.rsync_remote_user;
00617 rsync_remote_path = a_job.rsync_remote_path;
00618 rsync_remote_port = a_job.rsync_remote_port;
00619 rsync_remote_module = a_job.rsync_remote_module;
00620 rsync_retry_count = a_job.rsync_retry_count;
00621 rsync_timeout = a_job.rsync_timeout;
00622 }
00623
00624
00625 job& job::operator=(const job& a_job)
00626 {
00627 assign(a_job);
00628
00629 return(*this);
00630 }
00631
00632
00633 const std::string job::generate_archive_path(const std::string& a_path) const
00634 {
00635 std::string es;
00636 std::string path;
00637 archive_path::const_iterator capi;
00638
00639 for (capi = archive_path.begin(); capi != archive_path.end(); ++capi) {
00640 if (capi->type() == archive_path_element::jobname) {
00641 if (jobname.size() == 0) {
00642 TRY_nomem(es = "archive-path references jobname, ");
00643 TRY_nomem(es += "but jobname is empty");
00644 throw(ERROR(0,es));
00645 }
00646 if (path.size() != 0) {
00647 TRY_nomem(path += '/');
00648 }
00649 TRY_nomem(path += jobname);
00650 }
00651 else if (capi->type() == archive_path_element::groupname) {
00652 if (groupname.size() == 0) {
00653 TRY_nomem(es = "archive-path references groupname, ");
00654 TRY_nomem(es += "but groupname is empty");
00655 throw(ERROR(0,es));
00656 }
00657 if (path.size() != 0) {
00658 TRY_nomem(path += '/');
00659 }
00660 TRY_nomem(path += groupname);
00661 }
00662 else if (capi->type() == archive_path_element::hostname) {
00663 if (hostname.size() == 0) {
00664 TRY_nomem(es = "archive-path references hostname, ");
00665 TRY_nomem(es += "but hostname is empty");
00666 throw(ERROR(0,es));
00667 }
00668 if (path.size() != 0) {
00669 TRY_nomem(path += '/');
00670 }
00671 TRY_nomem(path += hostname);
00672 }
00673 else if (capi->type() == archive_path_element::pathname) {
00674 if (a_path.size() == 0) {
00675 TRY_nomem(es = "archive-path references path name, ");
00676 TRY_nomem(es += "but path name is empty");
00677 throw(ERROR(0,es));
00678 }
00679 if (path.size() != 0) {
00680 TRY_nomem(path += '/');
00681 }
00682 TRY_nomem(path += a_path);
00683 }
00684 else if (capi->type() == archive_path_element::permutation) {
00685 if (a_path.size() == 0) {
00686 TRY_nomem(es = "archive-path references path name, ");
00687 TRY_nomem(es += "but path name is empty");
00688 throw(ERROR(0,es));
00689 }
00690 if (path.size() != 0) {
00691 TRY_nomem(path += '/');
00692 }
00693 TRY_nomem(path += permute_path(a_path));
00694 }
00695 else if (capi->type() == archive_path_element::literal) {
00696 if (capi->value().size() == 0) {
00697 TRY_nomem(es = "archive-path references literal string, ");
00698 TRY_nomem(es += "but literal string value is empty");
00699 throw(INTERNAL_ERROR(0,es));
00700 }
00701 if (path.size() != 0) {
00702 TRY_nomem(path += '/');
00703 }
00704 TRY_nomem(path += capi->value());
00705 }
00706 else
00707 throw(INTERNAL_ERROR(0,"Unknown archive path element type"));
00708 }
00709
00710
00711 while ((path.size() > 0) && (path[path.size()-1] != '/'))
00712 path.erase(path.size()-1);
00713
00714 path = reform_path(path);
00715
00716 return(path);
00717 }
00718
00719
00720 const std::string job::generate_source_path(const std::string& a_path) const
00721 {
00722 estring path;
00723
00724 if (rsync_connection == connection_server) {
00725 path += "rsync://";
00726 if (rsync_remote_user.size() != 0) {
00727 path += rsync_remote_user;
00728 path += "@";
}
TRY_nomem(path += hostname);
if (rsync_remote_port != 0) {
path += ":";
00729 path += estring(rsync_remote_port);
00730 }
00731 if (rsync_remote_module.size() != 0) {
00732 path += "/";
00733 path += rsync_remote_module;
00734 if ((a_path.size() > 0) && (a_path[0] != '/'))
00735 path += "/";
00736 }
00737 }
00738 else if (rsync_connection == connection_remote) {
00739 if (rsync_remote_user.size() != 0) {
00740 path += rsync_remote_user;
00741 path += "@";
}
path += hostname;
path += ":";
00742 }
00743 path += a_path;
00744
00745 return(path);
00746 }
00747
00748
00749 const std::string job::generate_job_id(void) const
00750 {
00751 std::string es;
00752 std::string path;
00753 archive_path::const_iterator capi;
00754
00755 for (capi = archive_path.begin(); capi != archive_path.end(); ++capi) {
00756 if (capi->type() == archive_path_element::jobname) {
00757 if (jobname.size() == 0) {
00758 TRY_nomem(es = "archive-path references jobname, ");
00759 TRY_nomem(es += "but jobname is empty");
00760 throw(ERROR(0,es));
00761 }
00762 if (path.size() != 0) {
00763 TRY_nomem(path += '/');
00764 }
00765 TRY_nomem(path += jobname);
00766 }
00767 else if (capi->type() == archive_path_element::groupname) {
00768 if (groupname.size() == 0) {
00769 TRY_nomem(es = "archive-path references groupname, ");
00770 TRY_nomem(es += "but groupname is empty");
00771 throw(ERROR(0,es));
00772 }
00773 if (path.size() != 0) {
00774 TRY_nomem(path += '/');
00775 }
00776 TRY_nomem(path += groupname);
00777 }
00778 else if (capi->type() == archive_path_element::hostname) {
00779 if (hostname.size() == 0) {
00780 TRY_nomem(es = "archive-path references hostname, ");
00781 TRY_nomem(es += "but hostname is empty");
00782 throw(ERROR(0,es));
00783 }
00784 if (path.size() != 0) {
00785 TRY_nomem(path += '/');
00786 }
00787 TRY_nomem(path += hostname);
00788 }
00789 else if (capi->type() == archive_path_element::literal) {
00790 if (capi->value().size() == 0) {
00791 TRY_nomem(es = "archive-path references literal string, ");
00792 TRY_nomem(es += "but literal string value is empty");
00793 throw(INTERNAL_ERROR(0,es));
00794 }
00795 if (path.size() != 0) {
00796 TRY_nomem(path += '/');
00797 }
00798 TRY_nomem(path += capi->value());
00799 }
00800 }
00801
00802 path = reform_path(path);
00803
00804 return(path);
00805 }
00806
00807
00808 void job::check(void)
00809 {
00810 std::string es;
00811 std::string this_path;
00812 std::string that_path;
00813 paths_type::const_iterator cpi;
00814 configuration_manager::jobs_type::const_iterator cji;
00815 paths_type::const_iterator cjapi;
00816
00817 if (
00818 (
00819 (rsync_connection == connection_remote)
00820 || (rsync_connection == connection_server)
00821 )
00822 && (hostname.size() == 0)
00823 )
00824 {
00825 TRY_nomem(es = "rsync-connection-type references hostname, ");
00826 TRY_nomem(es += "but hostname is empty");
00827 throw(ERROR(0,es));
00828 }
00829
00830 if ((rsync_remote_module.size() != 0)
00831 && (rsync_connection != connection_server))
00832 {
00833 TRY_nomem(es = "rsync-remote-module specifies a module, but ");
00834 TRY_nomem(es = "rsync-connection-type is not server");
00835 throw(ERROR(0,es));
00836 }
00837
00838 if (paths.size() == 0) {
00839 throw(ERROR(0,"No paths defined for this job"));
00840 }
00841
00842 for (cpi = paths.begin() ; cpi != paths.end(); cpi++) {
00843 TRY_nomem(this_path = generate_archive_path(*cpi));
00844
00845 for (
00846 cji = config.jobs().begin();
00847 cji != config.jobs().end();
00848 cji++
00849 )
00850 {
00851 for (
00852 cjapi = cji->paths.begin();
00853 cjapi != cji->paths.end();
00854 cjapi++
00855 )
00856 {
00857 TRY_nomem(that_path = cji->generate_archive_path(*cjapi));
00858
00859 if (this_path == that_path) {
00860 error e(0);
00861
00862 TRY_nomem(es = "Duplicate archive-path values detected");
00863 e.push_back(ERROR_INSTANCE(es));
00864 TRY_nomem(es = "Archive path: \"");
00865 TRY_nomem(es += this_path);
00866 TRY_nomem(es += "\"");
00867 e.push_back(ERROR_INSTANCE(es));
00868 TRY_nomem(es = "Previously defined at ");
00869 TRY_nomem(es += cji->config_path);
00870 TRY_nomem(es += "[");
00871 TRY_nomem(es += estring(cji->config_line));
00872 TRY_nomem(es += "]");
00873 e.push_back(ERROR_INSTANCE(es));
00874 throw(e);
00875 }
00876
00877 if (
00878 (this_path.size() < that_path.size())
00879 && (this_path == that_path.substr(0,this_path.size()))
00880 && (
00881 (that_path[this_path.size()] == '/')
00882 || (this_path.size() == 0)
00883 )
00884 )
00885 {
00886 error e(0);
00887
00888 TRY_nomem(es = "Overlapping archive-path values detected");
00889 e.push_back(ERROR_INSTANCE(es));
00890 TRY_nomem(es = "Defined archive-path: \"");
00891 TRY_nomem(es += this_path);
00892 TRY_nomem(es += "\"");
00893 e.push_back(ERROR_INSTANCE(es));
00894 TRY_nomem(es = "Is in a parent directory of another job's previously defined archive-path");
00895 e.push_back(ERROR_INSTANCE(es));
00896 TRY_nomem(es = "At ");
00897 TRY_nomem(es += cji->config_path);
00898 TRY_nomem(es += "[");
00899 TRY_nomem(es += estring(cji->config_line));
00900 TRY_nomem(es += "]");
00901 e.push_back(ERROR_INSTANCE(es));
00902 throw(e);
00903 }
00904
00905 if (
00906 (this_path.size() > that_path.size())
00907 && (this_path.substr(0,that_path.size()) == that_path)
00908 && (
00909 (this_path[that_path.size()] == '/')
00910 || (that_path.size() == 0)
00911 )
00912 )
00913 {
00914 error e(0);
00915
00916 TRY_nomem(es = "Overlapping archive-path values detected");
00917 e.push_back(ERROR_INSTANCE(es));
00918 TRY_nomem(es = "Defined archive-path: \"");
00919 TRY_nomem(es += this_path);
00920 TRY_nomem(es += "\"");
00921 e.push_back(ERROR_INSTANCE(es));
00922 TRY_nomem(es = "Is in a subdirectory of another job's previously defined archive-path");
00923 e.push_back(ERROR_INSTANCE(es));
00924 TRY_nomem(es = "At ");
00925 TRY_nomem(es += cji->config_path);
00926 TRY_nomem(es += "[");
00927 TRY_nomem(es += estring(cji->config_line));
00928 TRY_nomem(es += "]");
00929 e.push_back(ERROR_INSTANCE(es));
00930 throw(e);
00931 }
00932 }
00933 }
00934 }
00935 }
00936
00937
00938
00939
00940 void configuration_manager::clear(void)
00941 {
00942 m_initialized = false;
00943 m_configs_read = 0;
00944 m_default = true;
00945 TRY_nomem(m_default_file = CONFIGFILE);
00946 m_action = action_help;
00947 m_timestamp.set();
00948 m_cfgfiles.clear();
00949 m_link_catalog_dir.erase();
00950 TRY_nomem(m_log_dir = LOGDIR);
00951 m_rsync_local_path.erase();
00952 if (strlen(LOCAL_RSYNC) > 0) {
00953 TRY_nomem(m_rsync_local_path = LOCAL_RSYNC);
00954 }
00955 m_rsync_parallel = 1;
00956 m_io_poll_interval = 1;
00957 m_vaults.clear();
00958 m_vault_overflow_behavior = overflow_quit;
00959 m_vault_overflow_blocks = 10;
00960 m_vault_overflow_inodes = 10;
00961 m_vault_selection_behavior = selection_round_robin;
00962 m_default_job.clear();
00963 m_logging_level = logging_rsync;
00964 m_jobs.clear();
00965 }
00966
00967
00968 configuration_manager::configuration_manager()
00969 {
00970 if (this != &config)
00971 throw(
00972 INTERNAL_ERROR(0,"Attempt to allocate multiple configuration managers")
00973 );
00974 clear();
00975 }
00976
00977
00978 void configuration_manager::init(int argc, char *argv[])
00979 {
00980 int c;
00981 estring opt;
00982 estring arg;
00983 std::string es;
00984 std::string tes;
00985 cfgfiles_type::const_iterator cfi;
00986 bool use_custom_timestamp = false;
00987 class timestamp custom_timestamp;
00988
00989 for (c = 1; c < argc; c++) {
00990 TRY_nomem(opt = argv[c]);
00991 if (c+1 == argc) {
00992 TRY_nomem(arg = "");
00993 }
00994 else {
00995 TRY_nomem(arg = argv[c+1]);
00996 }
00997
00998 if (opt == "--archive") {
00999 m_action = action_archive;
01000 }
01001 else if (opt == "--relink") {
01002 m_action = action_relink;
01003 }
01004 else if (opt == "--help") {
01005 m_action = action_help;
01006 }
01007 else if (opt == "--version") {
01008 m_action = action_version;
01009 }
01010 else if (opt == "--check-config") {
01011 m_action = action_check_config;
01012 }
01013 else if (opt == "--no-default-config") {
01014 m_default = false;
01015 }
01016 else if (opt == "--config") {
01017 directory dir;
01018 directory::const_iterator cdi;
01019
01020 TRY_nomem(es = "Error finding configuration file(s) ");
01021 TRY_nomem(es += "matching command line argument [");
01022 TRY_nomem(es += estring(c+1));
01023 TRY_nomem(es += "]: \"");
01024 TRY_nomem(es += arg);
01025 TRY_nomem(es += "\"");
01026
01027 try {
01028 dir.path(arg);
01029 }
01030 catch(error e) {
01031 e.push_back(ERROR_INSTANCE(es));
01032 throw(e);
01033 }
01034 catch(...) {
01035 error e = err_unknown;
01036
01037 e.push_back(ERROR_INSTANCE(es));
01038 throw(e);
01039 }
01040 if (dir.size() == 0) {
01041 TRY_nomem(es = "No configuration file(s) found matching ");
01042 TRY_nomem(es += "command line argument [");
01043 TRY_nomem(es += estring(c+1));
01044 TRY_nomem(es += "]: \"");
01045 TRY_nomem(es += arg);
01046 TRY_nomem(es += "\"");
01047
01048 throw(ERROR(0,es));
01049 }
01050 for (cdi = dir.begin(); cdi != dir.end(); cdi++) {
01051 TRY_nomem(m_cfgfiles.push_back(cfgfile_element(config_file, arg)));
01052 }
01053
01054 c++;
01055 }
01056 else if (opt == "--job") {
01057 directory dir;
01058 directory::const_iterator cdi;
01059
01060 TRY_nomem(es = "Error finding job file(s) ");
01061 TRY_nomem(es += "matching command line argument [");
01062 TRY_nomem(es += estring(c+1));
01063 TRY_nomem(es += "]: \"");
01064 TRY_nomem(es += arg);
01065 TRY_nomem(es += "\"");
01066
01067 try {
01068 dir.path(arg);
01069 }
01070 catch(error e) {
01071 e.push_back(ERROR_INSTANCE(es));
01072 throw(e);
01073 }
01074 catch(...) {
01075 error e = err_unknown;
01076 throw(e);
01077 }
01078 if (dir.size() == 0) {
01079 TRY_nomem(es = "No job file(s) found matching ");
01080 TRY_nomem(es += "command line argument [");
01081 TRY_nomem(es += estring(c+1));
01082 TRY_nomem(es += "]: \"");
01083 TRY_nomem(es += arg);
01084 TRY_nomem(es += "\"");
01085
01086 throw(ERROR(0,es));
01087 }
01088 for (cdi = dir.begin(); cdi != dir.end(); cdi++) {
01089 TRY_nomem(m_cfgfiles.push_back(cfgfile_element(job_file, arg)));
01090 }
01091
01092 c++;
01093 }
01094 else if (opt == "--timestamp") {
01095 TRY_nomem(es = "From command line argument ");
01096 TRY_nomem(es += estring(c+1));
01097 TRY(custom_timestamp.assign(arg),es);
01098 use_custom_timestamp = true;
01099 c++;
01100 TRY_nomem(tes = es);
01101 }
01102 else {
01103 TRY_nomem(es = "Unknown command line option: \"");
01104 TRY_nomem(es += opt);
01105 TRY_nomem(es += "\"");
01106 throw(ERROR(0,es));
01107 }
01108 }
01109
01110 m_initialized = true;
01111
01112 if ((m_action == action_help) || (m_action == action_version))
01113 return;
01114
01115 if (use_default())
01116 read_config(m_default_file);
01117
01118 for (cfi = m_cfgfiles.begin(); cfi != m_cfgfiles.end(); cfi++) {
01119 if (cfi->first == config_file) {
01120 read_config(cfi->second);
01121 }
01122 else {
01123 read_job(cfi->second);
01124 }
01125 }
01126
01127 if (m_configs_read == 0) {
01128 throw(ERROR(0,"No configuration file(s) read"));
01129 }
01130
01131 if (use_custom_timestamp) {
01132 TRY(m_timestamp = custom_timestamp,tes);
01133 }
01134
01135 check();
01136 }
01137
01138
01139 void configuration_manager::check(void) const
01140 {
01141 std::string es;
01142 subdirectory subdir;
01143 filestatus fstat;
01144
01145 if (!initialized())
01146 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01147
01148
01149
01150 if (m_log_dir.size() == 0) {
01151 throw(ERROR(0,"log-dir not set"));
01152 }
01153 TRY_nomem(es = "Invalid log-dir value: \"");
01154 TRY_nomem(es += m_log_dir);
01155 TRY_nomem(es += "\"");
01156 TRY_instead(subdir.path(m_log_dir,"*"),es);
01157
01158
01159
01160
01161 TRY_nomem(es = "Invalid rsync-local-path value: \"");
01162 TRY_nomem(es += m_rsync_local_path);
01163 TRY_nomem(es += "\"");
01164 TRY(fstat.path(m_rsync_local_path),es);
01165
01166
01167 if (m_vaults.size() == 0) {
01168 throw(ERROR(0,"No vaults defined"));
01169 }
01170 }
01171
01172
01173 const bool configuration_manager::initialized(void) const
01174 {
01175 return(m_initialized);
01176 }
01177
01178
01179 const configuration_manager::action_type
01180 configuration_manager::action(void) const
01181 {
01182 if (!initialized())
01183 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01184
01185 return(m_action);
01186 }
01187
01188
01189 const bool configuration_manager::use_default(void) const
01190 {
01191 if (!initialized())
01192 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01193
01194 return(m_default);
01195 }
01196
01197
01198 void configuration_manager::default_file(const std::string& a_path)
01199 {
01200 TRY_nomem(m_default_file = a_path);
01201 }
01202
01203
01204 const std::string& configuration_manager::default_file(void) const
01205 {
01206 if (!initialized())
01207 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01208
01209 return(m_default_file);
01210 }
01211
01212
01213 void configuration_manager::default_logdir(const std::string& a_path)
01214 {
01215 TRY_nomem(m_log_dir = a_path);
01216 }
01217
01218
01219 const class timestamp& configuration_manager::timestamp(void) const
01220 {
01221 if (!initialized())
01222 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01223
01224 return(m_timestamp);
01225 }
01226
01227
01228 const std::string& configuration_manager::link_catalog_dir(void) const
01229 {
01230 if (!initialized())
01231 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01232
01233 return(m_link_catalog_dir);
01234 }
01235
01236
01237 const std::string& configuration_manager::log_dir(void) const
01238 {
01239 if (!initialized())
01240 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01241
01242 return(m_log_dir);
01243 }
01244
01245
01246 const std::string& configuration_manager::rsync_local_path(void) const
01247 {
01248 if (!initialized())
01249 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01250
01251 return(m_rsync_local_path);
01252 }
01253
01254
01255 const uint16& configuration_manager::rsync_parallel(void) const
01256 {
01257 if (!initialized())
01258 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01259
01260 return(m_rsync_parallel);
01261 }
01262
01263
01264 const uint16& configuration_manager::io_poll_interval(void) const
01265 {
01266 if (!initialized())
01267 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01268
01269 return(m_io_poll_interval);
01270 }
01271
01272
01273 const timestamp::resolution_type configuration_manager::timestamp_resolution(void) const
01274 {
01275 if (!initialized())
01276 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01277
01278 return(m_timestamp.resolution());
01279 }
01280
01281
01282 const configuration_manager::vaults_type& configuration_manager::vaults(void) const
01283 {
01284 if (!initialized())
01285 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01286
01287 return(m_vaults);
01288 }
01289
01290
01291 const configuration_manager::overflow_type& configuration_manager::vault_overflow_behavior(void) const
01292 {
01293 if (!initialized())
01294 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01295
01296 return(m_vault_overflow_behavior);
01297 }
01298
01299
01300 const uint16& configuration_manager::vault_overflow_blocks(void) const
01301 {
01302 if (!initialized())
01303 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01304
01305 return(m_vault_overflow_blocks);
01306 }
01307
01308
01309 const uint16& configuration_manager::vault_overflow_inodes(void) const
01310 {
01311 if (!initialized())
01312 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01313
01314 return(m_vault_overflow_inodes);
01315 }
01316
01317
01318 const configuration_manager::selection_type& configuration_manager::vault_selection_behavior(void) const
01319 {
01320 if (!initialized())
01321 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01322
01323 return(m_vault_selection_behavior);
01324 }
01325
01326
01327 const job& configuration_manager::default_job(void) const
01328 {
01329 if (!initialized())
01330 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01331
01332 return(m_default_job);
01333 }
01334
01335
01336 const configuration_manager::jobs_type& configuration_manager::jobs(void) const
01337 {
01338 if (!initialized())
01339 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01340
01341 return(m_jobs);
01342 }
01343
01344
01345 const configuration_manager::logging_type& configuration_manager::logging_level(void) const
01346 {
01347 if (!initialized())
01348 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
01349
01350 return(m_logging_level);
01351 }
01352
01353
01354 void configuration_manager::read_config(const std::string& a_path)
01355 {
01356 std::string es;
01357 std::ifstream in;
01358 uint16 line = 0;
01359
01360 in.open(a_path.c_str());
01361 if (!in.is_open()) {
01362 TRY_nomem(es = "Could not open configuration file: \"");
01363 TRY_nomem(es += a_path);
01364 TRY_nomem(es += "\"");
01365 throw(ERROR(errno,es));
01366 }
01367
01368 global_parser(a_path, line, in);
01369
01370 in.close();
01371 m_configs_read++;
01372 }
01373
01374
01375 void configuration_manager::read_job(const std::string& a_path)
01376 {
01377 std::string es;
01378 std::ifstream in;
01379 job njob;
01380 uint16 line = 0;
01381
01382 in.open(a_path.c_str());
01383 if (!in.is_open()) {
01384 TRY_nomem(es = "Could not open job file: \"");
01385 TRY_nomem(es += a_path);
01386 TRY_nomem(es += "\"");
01387 throw(ERROR(errno,es));
01388 }
01389
01390 njob = m_default_job;
01391
01392 job_parser(&njob, a_path, line, in, "", false);
01393
01394 njob.check();
01395
01396 in.close();
01397 }
01398
01399
01400
01401
01402 void parse_line(
01403 std::istream& a_in,
01404 std::string& a_keyword,
01405 std::string& a_value
01406 )
01407 {
01408 std::string es;
01409 char ch;
01410
01411 a_keyword.erase();
01412 a_value.erase();
01413
01414 while (true) {
01415 a_in.get(ch);
01416
01417 while ((a_in) && ((ch == ' ') || (ch == '\t'))) {
01418 a_in.get(ch);
01419 }
01420
01421 while ((a_in) && ((ch != ' ') && (ch != '\t') && (ch != '\n'))) {
01422 TRY_nomem(a_keyword += ch);
01423 a_in.get(ch);
01424 }
01425 if (!a_in)
01426 return;
01427
01428
01429 if (a_keyword.size() == 0)
01430 return;
01431
01432
01433 if (a_keyword[0] == '#') {
01434
01435 while ((a_in) && (ch != '\n')) {
01436 a_in.get(ch);
01437 }
01438 return;
01439 }
01440
01441 a_keyword = estring(a_keyword).lower();
01442
01443
01444 if (ch == '\n')
01445 return;
01446
01447
01448 a_in.get(ch);
01449 while ((a_in) && ((ch == ' ') || (ch == '\t'))) {
01450 a_in.get(ch);
01451 }
01452 if (!a_in)
01453 return;
01454 a_in.putback(ch);
01455 if (!a_in)
01456 return;
01457
01458
01459 a_in.get(ch);
01460 while ((a_in) && (ch != '\n')) {
01461 TRY_nomem(a_value += ch);
01462 a_in.get(ch);
01463 }
01464 return;
01465 }
01466 }
01467
01468
01469 const std::string parse_dirname(const std::string& a_path)
01470 {
01471 std::string rpath;
01472
01473 TRY_nomem(rpath = a_path);
01474
01475 if (rpath.find_last_of('/') != std::string::npos)
01476 rpath.erase(rpath.find_last_of('/'));
01477
01478 if (rpath.size() == 0) {
01479 TRY_nomem(rpath = "./");
01480 return(rpath);
01481 }
01482
01483 if (rpath[rpath.size()-1] != '/') {
01484 TRY_nomem(rpath += '/');
01485 }
01486
01487 return(rpath);
01488 }
01489
01490
01491 const std::string parse_basename(const std::string& a_path)
01492 {
01493 std::string es;
01494 std::string rpath;
01495
01496 TRY_nomem(rpath = a_path);
01497
01498 if (rpath.find_last_of('/') != std::string::npos)
01499 rpath.erase(0,rpath.find_last_of('/'));
01500
01501 return(rpath);
01502 }
01503
01504
01505
01506
01507 global_parser::global_parser(
01508 const std::string& a_path,
01509 uint16& a_line,
01510 std::istream& a_in
01511 )
01512 {
01513 m_in = &a_in;
01514 m_path = &a_path;
01515 m_line = &a_line;
01516
01517 parse();
01518 }
01519
01520
01521
01522 const std::string global_parser::location(void)
01523 {
01524 std::string es;
01525
01526 TRY_nomem(es = "At ");
01527 TRY_nomem(es += (*m_path));
01528 TRY_nomem(es += "[");
01529 TRY_nomem(es += estring((*m_line)));
01530 TRY_nomem(es += "]");
01531
01532 return(es);
01533 }
01534
01535
01536 void global_parser::read_config(const std::string& a_path)
01537 {
01538 std::string es;
01539 std::ifstream in;
01540 uint16 line = 0;
01541
01542 in.open(a_path.c_str());
01543 if (!in.is_open()) {
01544 TRY_nomem(es = "Could not open configuraiton file: \"");
01545 TRY_nomem(es += a_path);
01546 TRY_nomem(es += "\"");
01547 throw(ERROR(errno,es));
01548 }
01549
01550 global_parser(a_path, line, in);
01551
01552 in.close();
01553 config.m_configs_read++;
01554 }
01555
01556
01557 void global_parser::read_job(const std::string& a_path, job& a_job)
01558 {
01559 std::string es;
01560 std::ifstream in;
01561 uint16 line = 0;
01562
01563 in.open(a_path.c_str());
01564 if (!in.is_open()) {
01565 TRY_nomem(es = "Could not open job file: \"");
01566 TRY_nomem(es += a_path);
01567 TRY_nomem(es += "\"");
01568 throw(ERROR(errno,es));
01569 }
01570
01571 job_parser(&a_job, a_path, line, in, "", false);
01572
01573 TRY_nomem(a_job.config_path = *m_path);
01574 TRY_nomem(a_job.config_line = *m_line);
01575 a_job.check();
01576
01577 in.close();
01578 }
01579
01580
01581 void global_parser::parse(void)
01582 {
01583 std::string es;
01584 std::string keyword;
01585 std::string value;
01586
01587 while ((*m_in)) {
01588 (*m_line)++;
01589
01590 try {
01591 parse_line((*m_in), keyword, value);
01592 }
01593 catch(error e) {
01594 e.push_back(ERROR_INSTANCE(location()));
01595 throw(e);
01596 }
01597 catch(...) {
01598 error e = err_unknown;
01599
01600 e.push_back(ERROR_INSTANCE(location()));
01601 throw(e);
01602 }
01603
01604 if (keyword.size() == 0)
01605 continue;
01606 if (keyword[0] == '#')
01607 continue;
01608
01609 try {
01610 if (keyword == "<default>") {
01611 parse_default(value);
01612 }
01613 else if (keyword == "include") {
01614 parse_include(value);
01615 }
01616 else if (keyword == "include-job") {
01617 parse_include_job(value);
01618 }
01619 else if (keyword == "<job>") {
01620 parse_job(value);
01621 }
01622 else if (keyword == "link-catalog-dir") {
01623 parse_link_catalog_dir(value);
01624 }
01625 else if (keyword == "log-dir") {
01626 parse_log_dir(value);
01627 }
01628 else if (keyword == "logging-level") {
01629 parse_logging_level(value);
01630 }
01631 else if (keyword == "rsync-local-path") {
01632 parse_rsync_local_path(value);
01633 }
01634 else if (keyword == "rsync-parallel") {
01635 parse_rsync_parallel(value);
01636 }
01637 else if (keyword == "io-poll-interval") {
01638 parse_io_poll_interval(value);
01639 }
01640 else if (keyword == "timestamp-resolution") {
01641 parse_timestamp_resolution(value);
01642 }
01643 else if (keyword == "vault") {
01644 try {
01645 parse_vault(value);
01646 }
01647 catch(error e) {
01648 std::cerr << e;
01649 }
01650 catch(...) {
01651 throw(err_unknown);
01652 }
01653 }
01654 else if (keyword == "vault-overflow-behavior") {
01655 parse_vault_overflow_behavior(value);
01656 }
01657 else if (keyword == "vault-overflow-blocks") {
01658 parse_vault_overflow_blocks(value);
01659 }
01660 else if (keyword == "vault-overflow-inodes") {
01661 parse_vault_overflow_inodes(value);
01662 }
01663 else if (keyword == "vault-selection-behavior") {
01664 parse_vault_selection_behavior(value);
01665 }
01666 else {
01667 error e(0);
01668
01669 TRY_nomem(es = "Unknown command in global context: \"");
01670 TRY_nomem(es += keyword);
01671 TRY_nomem(es += "\"");
01672 throw(ERROR(0,es));
01673 }
01674 }
01675 catch(error e) {
01676 e.push_back(ERROR_INSTANCE(location()));
01677 throw(e);
01678 }
01679 catch(...) {
01680 error e = err_unknown;
01681
01682 e.push_back(ERROR_INSTANCE(location()));
01683 throw(e);
01684 }
01685 }
01686 }
01687
01688
01689 void global_parser::parse_default(const std::string& a_value)
01690 {
01691 std::string delimiter;
01692 std::string default_config_path;
01693 uint16 default_config_line;
01694 job* jobPtr = &config.m_default_job;
01695
01696 config.m_default_job.clear();
01697
01698 TRY_nomem(default_config_path = *m_path);
01699 TRY_nomem(default_config_line = *m_line);
01700 TRY_nomem(delimiter = "</default>");
01701
01702 job_parser(jobPtr, *m_path, *m_line, *m_in, delimiter, true);
01703
01704 TRY_nomem(jobPtr->default_config_path = default_config_path);
01705 jobPtr->default_config_line = default_config_line;
01706 }
01707
01708
01709 void global_parser::parse_include(const std::string& a_value)
01710 {
01711 std::string es;
01712 directory dir;
01713 directory::const_iterator cdi;
01714 std::string rpath;
01715 std::string ipath;
01716
01717 if (a_value.size() == 0) {
01718 TRY_nomem(es = "Invalid include path: \"");
01719 TRY_nomem(es += a_value);
01720 TRY_nomem(es += "\"");
01721 throw(ERROR(0,es));
01722 }
01723
01724 if (a_value[0] != '/') {
01725 TRY_nomem(rpath = parse_dirname(*m_path));
01726 }
01727
01728 TRY_nomem(ipath = rpath + a_value);
01729
01730 TRY_nomem(es = "No configuration file(s) found: \"");
01731 TRY_nomem(es += a_value);
01732 TRY_nomem(es += "\"");
01733 TRY_instead(dir.path(ipath),es);
01734 if (dir.size() == 0)
01735 throw(ERROR(0,es));
01736
01737 for (cdi = dir.begin(); cdi != dir.end(); cdi++) {
01738 if (dir.size() > 1) {
01739 TRY_nomem(es = "For files found matching: \"");
01740 TRY_nomem(es += a_value);
01741 TRY_nomem(es += "\"");
01742 try {
01743 read_config(*cdi);
01744 }
01745 catch(error e) {
01746 e.push_back(ERROR_INSTANCE(es));
01747 throw(e);
01748 }
01749 catch(...) {
01750 error e = err_unknown;
01751
01752 e.push_back(ERROR_INSTANCE(es));
01753 throw(e);
01754 }
01755 }
01756 else
01757 read_config(*cdi);
01758 }
01759 }
01760
01761
01762 void global_parser::parse_include_job(const std::string& a_value)
01763 {
01764 std::string es;
01765 directory dir;
01766 directory::const_iterator cdi;
01767 std::string rpath;
01768 std::string ipath;
01769
01770 if (a_value.size() == 0) {
01771 TRY_nomem(es = "Invalid include-job path: \"");
01772 TRY_nomem(es += a_value);
01773 TRY_nomem(es += "\"");
01774 throw(ERROR(0,es));
01775 }
01776
01777 if (a_value[0] != '/') {
01778 TRY_nomem(rpath = parse_dirname(*m_path));
01779 }
01780
01781 TRY_nomem(ipath = rpath + a_value);
01782
01783 TRY_nomem(es = "No job file(s) found: \"");
01784 TRY_nomem(es += a_value);
01785 TRY_nomem(es += "\"");
01786 TRY(dir.path(ipath),es);
01787 if (dir.size() == 0)
01788 throw(ERROR(0,es));
01789
01790 for (cdi = dir.begin(); cdi != dir.end(); cdi++) {
01791 job new_job;
01792
01793 new_job = config.m_default_job;
01794
01795 if (dir.size() > 1) {
01796 TRY_nomem(es = "For files found matching: \"");
01797 TRY_nomem(es += a_value);
01798 TRY_nomem(es += "\"");
01799 try {
01800 read_job(*cdi, new_job);
01801 }
01802 catch(error e) {
01803 e.push_back(ERROR_INSTANCE(es));
01804 throw(e);
01805 }
01806 catch(...) {
01807 error e = err_unknown;
01808
01809 e.push_back(ERROR_INSTANCE(es));
01810 throw(e);
01811 }
01812 }
01813 else
01814 read_job(*cdi, new_job);
01815 TRY_nomem(config.m_jobs.push_back(new_job));
01816 }
01817 }
01818
01819
01820 void global_parser::parse_job(const std::string& a_value)
01821 {
01822 std::string delimiter;
01823 std::string config_path;
01824 uint16 config_line;
01825 job new_job;
01826
01827 TRY_nomem(config_path = *m_path);
01828 config_line = *m_line;
01829 new_job = config.m_default_job;
01830
01831 TRY_nomem(new_job.config_path = config_path);
01832 new_job.config_line = config_line;
01833 TRY_nomem(delimiter = "</job>");
01834
01835 job_parser(&new_job, *m_path, *m_line, *m_in, delimiter, false);
01836
01837 new_job.check();
01838
01839 TRY_nomem(config.m_jobs.push_back(new_job));
01840 }
01841
01842
01843 void global_parser::parse_link_catalog_dir(const std::string& a_value)
01844 {
01845 std::string es;
01846 subdirectory subdir;
01847
01848 TRY_nomem(es = "Invalid link-catalog-dir path: \"");
01849 TRY_nomem(es += a_value);
01850 TRY_nomem(es += "\"");
01851 TRY_instead(subdir.path(a_value,"*"),es);
01852 TRY_nomem(config.m_link_catalog_dir = a_value);
01853 }
01854
01855
01856 void global_parser::parse_log_dir(const std::string& a_value)
01857 {
01858 std::string es;
01859 subdirectory subdir;
01860
01861 TRY_nomem(es = "Invalid log-dir path: \"");
01862 TRY_nomem(es += a_value);
01863 TRY_nomem(es += "\"");
01864 TRY_instead(subdir.path(a_value,"*"),es);
01865 TRY_nomem(config.m_log_dir = a_value);
01866 }
01867
01868
01869 void global_parser::parse_logging_level(const std::string& a_value)
01870 {
01871 std::string es;
01872 estring str;
01873
01874 TRY_nomem(es = "Invalid logging-level value: \"");
01875 TRY_nomem(es += a_value);
01876 TRY_nomem(es += "\"");
01877 TRY_nomem(str = estring(a_value).lower());
01878 if (str == "manager") {
01879 config.m_logging_level = configuration_manager::logging_manager;
01880 }
01881 else if (str == "child") {
01882 config.m_logging_level = configuration_manager::logging_child;
01883 }
01884 else if (str == "rsync") {
01885 config.m_logging_level = configuration_manager::logging_rsync;
01886 }
01887 else {
01888 throw(ERROR(0,es));
01889 }
01890 }
01891
01892
01893 void global_parser::parse_rsync_local_path(const std::string& a_value)
01894 {
01895 std::string es;
01896 filestatus fstat;
01897
01898 TRY_nomem(es = "Invalid rsync-local-path value: \"");
01899 TRY_nomem(es += a_value);
01900 TRY_nomem(es += "\"");
01901 TRY_instead(fstat.path(a_value),es);
01902 TRY_nomem(config.m_rsync_local_path = a_value);
01903 }
01904
01905
01906 void global_parser::parse_rsync_parallel(const std::string& a_value)
01907 {
01908 std::string es;
01909 uint16 num;
01910
01911 TRY_nomem(es = "Invalid rsync-parallel value: \"");
01912 TRY_nomem(es += a_value);
01913 TRY_nomem(es += "\"");
01914 TRY_instead(num = estring(a_value),es);
01915 if (num == 0)
01916 throw(ERROR(0,es));
01917 config.m_rsync_parallel = num;
01918 }
01919
01920
01921 void global_parser::parse_io_poll_interval(const std::string& a_value)
01922 {
01923 std::string es;
01924 uint16 num;
01925
01926 TRY_nomem(es = "Invalid io-poll-interval value: \"");
01927 TRY_nomem(es += a_value);
01928 TRY_nomem(es += "\"");
01929 TRY_instead(num = estring(a_value),es);
01930 if (num == 0)
01931 throw(ERROR(0,es));
01932 config.m_io_poll_interval = num;
01933 }
01934
01935
01936 void global_parser::parse_timestamp_resolution(const std::string& a_value)
01937 {
01938 std::string es;
01939 estring str;
01940
01941 TRY_nomem(es = "Invalid timestamp-resolution: \"");
01942 TRY_nomem(es += a_value);
01943 TRY_nomem(es += "\"");
01944 TRY(str = estring(a_value).lower(),es);
01945 if (str == "year") {
01946 config.m_timestamp.resolution(timestamp::resolution_year);
01947 }
01948 else if (str == "month") {
01949 config.m_timestamp.resolution(timestamp::resolution_month);
01950 }
01951 else if (str == "day") {
01952 config.m_timestamp.resolution(timestamp::resolution_day);
01953 }
01954 else if (str == "hour") {
01955 config.m_timestamp.resolution(timestamp::resolution_hour);
01956 }
01957 else if (str == "minute") {
01958 config.m_timestamp.resolution(timestamp::resolution_minute);
01959 }
01960 else if (str == "second") {
01961 config.m_timestamp.resolution(timestamp::resolution_second);
01962 }
01963 else {
01964 throw(ERROR(0,es));
01965 }
01966 }
01967
01968
01969 void global_parser::parse_vault(const std::string& a_value)
01970 {
01971 std::string es;
01972 directory dir;
01973 directory::const_iterator cdi;
01974 filestatus fstat;
01975 subdirectory subdir;
01976
01977 TRY_nomem(es = "Invalid vault path: \"");
01978 TRY_nomem(es += a_value);
01979 TRY_nomem(es += "\"");
01980
01981 if (a_value.size() == 0)
01982 throw(ERROR(0,es));
01983
01984 TRY_instead(dir.path(a_value),es);
01985
01986 if (dir.size() == 0) {
01987 TRY_instead(subdir.path(a_value,"*"),es);
01988 TRY_nomem(config.m_vaults.push_back(a_value));
01989 return;
01990 }
01991
01992 for (cdi = dir.begin(); cdi != dir.end(); cdi++) {
01993 try {
01994 subdir.path(*cdi,"*");
01995 }
01996 catch(error e) {
01997 e.clear_stack();
01998
01999 if (dir.size() > 1) {
02000 TRY_nomem(es = "Invalid vault path: \"");
02001 TRY_nomem(es += *cdi);
02002 TRY_nomem(es += "\"");
02003 e.push_back(es);
02004
02005 TRY_nomem(es = "For paths found matching: \"");
02006 TRY_nomem(es += a_value);
02007 TRY_nomem(es += "\"");
02008 e.push_back(es);
02009 }
02010 else
02011 e.push_back(es);
02012
02013 throw(e);
02014 }
02015 catch(...) {
02016 if (errno == ENOMEM) {
02017 throw(err_nomem);
02018 }
02019 error e = err_unknown;
02020
02021 if (dir.size() > 1) {
02022 TRY_nomem(es = "Invalid vault path: \"");
02023 TRY_nomem(es += *cdi);
02024 TRY_nomem(es += "\"");
02025 e.push_back(es);
02026
02027 TRY_nomem(es = "For paths found matching: \"");
02028 TRY_nomem(es += a_value);
02029 TRY_nomem(es += "\"");
02030 e.push_back(es);
02031 }
02032 else
02033 e.push_back(es);
02034
02035 throw(e);
02036 }
02037 TRY_nomem(config.m_vaults.push_back(*cdi));
02038 }
02039 }
02040
02041
02042 void global_parser::parse_vault_overflow_behavior(const std::string& a_value)
02043 {
02044 std::string es;
02045 estring str;
02046
02047 TRY_nomem(es = "Invalid vault-overflow-behavior value: \"");
02048 TRY_nomem(es += a_value);
02049 TRY_nomem(es += "\"");
02050 TRY(str = estring(a_value).lower(),es);
02051 if (str == "quit") {
02052 config.m_vault_overflow_behavior = configuration_manager::overflow_quit;
02053 }
02054 else if (str == "delete-oldest") {
02055 config.m_vault_overflow_behavior = configuration_manager::overflow_delete_oldest;
02056 }
02057 else if (str == "delete-until-free") {
02058 config.m_vault_overflow_behavior = configuration_manager::overflow_delete_until_free;
02059 }
02060 else {
02061 throw(ERROR(0,es));
02062 }
02063 }
02064
02065
02066 void global_parser::parse_vault_overflow_blocks(const std::string& a_value)
02067 {
02068 std::string es;
02069 uint16 num;
02070
02071 TRY_nomem(es = "Invalid vault-overflow-blocks value: \"");
02072 TRY_nomem(es += a_value);
02073 TRY_nomem(es += "\"");
02074 TRY(num = estring(a_value),es);
02075 if (num > 50)
02076 throw(ERROR(0,es));
02077 config.m_vault_overflow_blocks = num;
02078 }
02079
02080
02081 void global_parser::parse_vault_overflow_inodes(const std::string& a_value)
02082 {
02083 std::string es;
02084 uint16 num;
02085
02086 TRY_nomem(es = "Invalid vault-overflow-inodes value: \"");
02087 TRY_nomem(es += a_value);
02088 TRY_nomem(es += "\"");
02089 TRY(num = estring(a_value),es);
02090 if (num > 50)
02091 throw(ERROR(0,es));
02092 config.m_vault_overflow_inodes = num;
02093 }
02094
02095
02096 void global_parser::parse_vault_selection_behavior(const std::string& a_value)
02097 {
02098 std::string es;
02099 estring str;
02100
02101 TRY_nomem(es = "Invalid vault-selection-behavior value: \"");
02102 TRY_nomem(es += a_value);
02103 TRY_nomem(es += "\"");
02104 TRY(str = estring(a_value).lower(),es);
02105 if (str == "max-free") {
02106 config.m_vault_selection_behavior = configuration_manager::selection_max_free;
02107 }
02108 else if (str == "round-robin") {
02109 config.m_vault_selection_behavior = configuration_manager::selection_round_robin;
02110 }
02111 else {
02112 throw(ERROR(0,es));
02113 }
02114 }
02115
02116
02117
02118
02119 job_parser::job_parser(
02120 job * a_job,
02121 const std::string& a_path,
02122 uint16& a_line,
02123 std::istream& a_in,
02124 const std::string& a_block_delimiter,
02125 const bool a_default_context = false
02126 )
02127 {
02128 m_job = a_job;
02129 m_in = &a_in;
02130 m_path = &a_path;
02131 m_line = &a_line;
02132 m_delimiter = &a_block_delimiter;
02133 m_default_context = a_default_context;
02134
02135 parse();
02136 }
02137
02138
02139
02140 const std::string job_parser::location(void)
02141 {
02142 std::string es;
02143
02144 TRY_nomem(es = "At ");
02145 TRY_nomem(es += (*m_path));
02146 TRY_nomem(es += "[");
02147 TRY_nomem(es += estring((*m_line)));
02148 TRY_nomem(es += "]");
02149
02150 return(es);
02151 }
02152
02153
02154 void job_parser::read_job(const std::string& a_path)
02155 {
02156 std::string es;
02157 std::ifstream in;
02158 uint16 line = 0;
02159
02160 in.open(a_path.c_str());
02161 if (!in.is_open()) {
02162 TRY_nomem(es = "Could not open job file: \"");
02163 TRY_nomem(es += a_path);
02164 TRY_nomem(es += "\"");
02165 throw(ERROR(errno,es));
02166 }
02167
02168 job_parser(m_job, a_path, line, in, "", m_default_context);
02169
02170 in.close();
02171 }
02172
02173
02174 void job_parser::parse(void)
02175 {
02176 std::string es;
02177 std::string keyword;
02178 std::string value;
02179
02180 while ((*m_in)) {
02181 (*m_line)++;
02182
02183 try {
02184 parse_line((*m_in), keyword, value);
02185 }
02186 catch(error e) {
02187 e.push_back(ERROR_INSTANCE(location()));
02188 throw(e);
02189 }
02190 catch(...) {
02191 error e = err_unknown;
02192
02193 e.push_back(ERROR_INSTANCE(location()));
02194 throw(e);
02195 }
02196
02197 if (!(*m_in) && (m_delimiter->size() != 0)) {
02198 TRY_nomem(es = "Unexpected end of file, expected \"");
02199 TRY_nomem(es += *m_delimiter);
02200 TRY_nomem(es += "\" here");
02201 throw(ERROR(errno,es));
02202 }
02203
02204 if (keyword.size() == 0)
02205 continue;
02206 if (keyword[0] == '#')
02207 continue;
02208
02209 try {
02210 if (keyword == *m_delimiter) {
02211 return;
02212 }
02213 else if (keyword == "archive-path") {
02214 parse_archive_path(value);
02215 }
02216 else if (keyword == "clear") {
02217 parse_clear(value);
02218 }
02219 else if (keyword == "exclude-from") {
02220 parse_exclude_from(value);
02221 }
02222 else if (keyword == "include-from") {
02223 parse_include_from(value);
02224 }
02225 else if (keyword == "groupname") {
02226 parse_groupname(value);
02227 }
02228 else if (keyword == "hostname") {
02229 parse_hostname(value);
02230 }
02231 else if (keyword == "include") {
02232 parse_include(value);
02233 }
02234 else if ((keyword == "jobname") && (*m_delimiter == "</job>")) {
02235 parse_jobname(value);
02236 }
02237 else if (keyword == "path") {
02238 parse_path(value);
02239 }
02240 else if (keyword == "rsync-behavior") {
02241 parse_rsync_behavior(value);
02242 }
02243 else if (keyword == "rsync-connection-type") {
02244 parse_rsync_connection_type(value);
02245 }
02246 else if (keyword == "rsync-hardlink") {
02247 parse_rsync_hardlink(value);
02248 }
02249 else if (keyword == "rsync-options") {
02250 parse_rsync_options(value);
02251 }
02252 else if (keyword == "<rsync-options>") {
02253 parse_rsync_options_context(value);
02254 }
02255 else if (keyword == "rsync-remote-user") {
02256 parse_rsync_remote_user(value);
02257 }
02258 else if (keyword == "rsync-remote-path") {
02259 parse_rsync_remote_path(value);
02260 }
02261 else if (keyword == "rsync-remote-port") {
02262 parse_rsync_remote_port(value);
02263 }
02264 else if (keyword == "rsync-remote-module") {
02265 parse_rsync_remote_module(value);
02266 }
02267 else if (keyword == "rsync-retry-count") {
02268 parse_rsync_retry_count(value);
02269 }
02270 else if (keyword == "rsync-timeout") {
02271 parse_rsync_timeout(value);
02272 }
02273 else {
02274 error e(0);
02275
02276 TRY_nomem(es = "Unknown command in ");
02277 if (m_default_context) {
02278 TRY_nomem(es += "default");
02279 }
02280 else {
02281 TRY_nomem(es += "job");
02282 }
02283 TRY_nomem(es += " context: \"");
02284 TRY_nomem(es += keyword);
02285 TRY_nomem(es += "\"");
02286 throw(ERROR(0,es));
02287 }
02288 }
02289 catch(error e) {
02290 if ((*m_delimiter).size() == 0)
02291 e.push_back(ERROR_INSTANCE(location()));
02292 throw(e);
02293 }
02294 catch(...) {
02295 error e = err_unknown;
02296
02297 e.push_back(ERROR_INSTANCE(location()));
02298 throw(e);
02299 }
02300 }
02301 }
02302
02303
02304 void job_parser::parse_archive_path(const std::string& a_value)
02305 {
02306 std::string es;
02307
02308 TRY_nomem(es = "Invalid archive-path value");
02309 TRY((*m_job).archive_path = a_value,es);
02310 }
02311
02312
02313 void job_parser::parse_clear(const std::string& a_value)
02314 {
02315 std::string es;
02316 estring str;
02317
02318 TRY_nomem(es = "Invalid clear value: \"");
02319 TRY_nomem(es += a_value);
02320 TRY_nomem(es += "\"");
02321 TRY(str = estring(a_value).lower(),es);
02322 if (str == "archive-path") {
02323 m_job->archive_path.clear();
02324 }
02325 else if (str == "exclude-from") {
02326 m_job->excludes.clear();
02327 }
02328 else if (str == "groupname") {
02329 m_job->groupname.erase();
02330 }
02331 else if (str == "hostname") {
02332 m_job->hostname.erase();
02333 }
02334 else if (str == "include-from") {
02335 m_job->includes.clear();
02336 }
02337 else if ((str == "jobname") && (*m_delimiter == "</job>")) {
02338 m_job->jobname.erase();
02339 }
02340 else if (str == "paths") {
02341 m_job->paths.clear();
02342 }
02343 else if (str == "rsync-behavior") {
02344 m_job->rsync_behavior.clear();
02345 }
02346 else if (str == "rsync-options") {
02347 m_job->rsync_options.erase();
02348 }
02349 else if (str == "rsync-remote-user") {
02350 m_job->rsync_remote_user.erase();
02351 }
02352 else if (str == "rsync-remotr-port") {
02353 m_job->rsync_remote_port = 0;
02354 }
02355 else if (str == "rsync-remote-module") {
02356 m_job->rsync_remote_module.erase();
02357 }
02358 else if (str == "rsync-remote-path") {
02359 m_job->rsync_remote_path.erase();
02360 }
02361 else {
02362 throw(ERROR(0,es));
02363 }
02364 }
02365
02366
02367 void job_parser::parse_exclude_from(const std::string& a_value)
02368 {
02369 std::string es;
02370 directory dir;
02371 directory::const_iterator cdi;
02372 std::string rpath;
02373 std::string ipath;
02374
02375 if (a_value.size() == 0) {
02376 TRY_nomem(es = "Invalid exclude-from path: \"");
02377 TRY_nomem(es += a_value);
02378 TRY_nomem(es += "\"");
02379 throw(ERROR(0,es));
02380 }
02381
02382 if (a_value[0] != '/') {
02383 TRY_nomem(rpath = parse_dirname(*m_path));
02384 }
02385
02386 TRY_nomem(ipath = rpath + a_value);
02387
02388 TRY_nomem(es = "No exclude-from file(s) found: \"");
02389 TRY_nomem(es += a_value);
02390 TRY_nomem(es += "\"");
02391 TRY(dir.path(ipath),es);
02392 if (dir.size() == 0)
02393 throw(ERROR(0,es));
02394
02395 for (cdi = dir.begin(); cdi != dir.end(); cdi++) {
02396 TRY_nomem((*m_job).excludes.push_back(*cdi));
02397 }
02398 }
02399
02400
02401 void job_parser::parse_include_from(const std::string& a_value)
02402 {
02403 std::string es;
02404 directory dir;
02405 directory::const_iterator cdi;
02406 std::string rpath;
02407 std::string ipath;
02408
02409 if (a_value.size() == 0) {
02410 TRY_nomem(es = "Invalid include-from path: \"");
02411 TRY_nomem(es += a_value);
02412 TRY_nomem(es += "\"");
02413 throw(ERROR(0,es));
02414 }
02415
02416 if (a_value[0] != '/') {
02417 TRY_nomem(rpath = parse_dirname(*m_path));
02418 }
02419
02420 TRY_nomem(ipath = rpath + a_value);
02421
02422 TRY_nomem(es = "No include-from file(s) found: \"");
02423 TRY_nomem(es += a_value);
02424 TRY_nomem(es += "\"");
02425 TRY(dir.path(ipath),es);
02426 if (dir.size() == 0)
02427 throw(ERROR(0,es));
02428
02429 for (cdi = dir.begin(); cdi != dir.end(); cdi++) {
02430 TRY_nomem((*m_job).includes.push_back(*cdi));
02431 }
02432 }
02433
02434
02435 void job_parser::parse_groupname(const std::string& a_value)
02436 {
02437 TRY_nomem((*m_job).groupname = a_value);
02438 }
02439
02440
02441 void job_parser::parse_hostname(const std::string& a_value)
02442 {
02443 TRY_nomem((*m_job).hostname = a_value);
02444 }
02445
02446
02447 void job_parser::parse_include(const std::string& a_value)
02448 {
02449 std::string es;
02450 directory dir;
02451 directory::const_iterator cdi;
02452 std::string rpath;
02453 std::string ipath;
02454
02455 if (a_value.size() == 0) {
02456 TRY_nomem(es = "Invalid include path: \"");
02457 TRY_nomem(es += a_value);
02458 TRY_nomem(es += "\"");
02459 throw(ERROR(0,es));
02460 }
02461
02462 if (a_value[0] != '/') {
02463 TRY_nomem(rpath = parse_dirname(*m_path));
02464 }
02465
02466 TRY_nomem(ipath = rpath + a_value);
02467
02468 TRY_nomem(es = "No configuration file(s) found: \"");
02469 TRY_nomem(es += a_value);
02470 TRY_nomem(es += "\"");
02471 TRY_instead(dir.path(ipath),es);
02472 if (dir.size() == 0)
02473 throw(ERROR(0,es));
02474
02475 for (cdi = dir.begin(); cdi != dir.end(); cdi++) {
02476 if (dir.size() > 1) {
02477 TRY_nomem(es = "For files found matching: \"");
02478 TRY_nomem(es += a_value);
02479 TRY_nomem(es += "\"");
02480 try {
02481 read_job(*cdi);
02482 }
02483 catch(error e) {
02484 e.push_back(ERROR_INSTANCE(es));
02485 throw(e);
02486 }
02487 catch(...) {
02488 error e = err_unknown;
02489
02490 e.push_back(ERROR_INSTANCE(es));
02491 throw(e);
02492 }
02493 }
02494 else
02495 read_job(*cdi);
02496 }
02497 }
02498
02499
02500 void job_parser::parse_jobname(const std::string& a_value)
02501 {
02502 TRY_nomem((*m_job).jobname = a_value);
02503 }
02504
02505
02506 void job_parser::parse_path(const std::string& a_value)
02507 {
02508 TRY_nomem((*m_job).paths.push_back(a_value));
02509 }
02510
02511
02512 void job_parser::parse_rsync_behavior(const std::string& a_value)
02513 {
02514 std::string es;
02515 estring str;
02516
02517 TRY_nomem(es = "Invalid rsync-behavior value: \"");
02518 TRY_nomem(es += a_value);
02519 TRY_nomem(es += "\"");
02520 TRY(str = estring(a_value).lower(),es);
02521 if (str == "clear") {
02522 (*m_job).rsync_behavior.clear();
02523 }
02524 else if (str == "reset") {
02525 (*m_job).rsync_behavior.reset();
02526 }
02527 else
02528 (*m_job).rsync_behavior.assign(a_value);
02529 }
02530
02531
02532 void job_parser::parse_rsync_connection_type(const std::string& a_value)
02533 {
02534 std::string es;
02535 estring str;
02536
02537 TRY_nomem(es = "Invalid rsync-connection-type value: \"");
02538 TRY_nomem(es += a_value);
02539 TRY_nomem(es += "\"");
02540 TRY(str = estring(a_value).lower(),es);
02541 if (str == "local") {
02542 (*m_job).rsync_connection = job::connection_local;
02543 }
02544 else if (str == "remote") {
02545 (*m_job).rsync_connection = job::connection_remote;
02546 }
02547 else if (str == "server") {
02548 (*m_job).rsync_connection = job::connection_server;
02549 }
02550 else {
02551 throw(ERROR(0,es));
02552 }
02553 }
02554
02555
02556 void job_parser::parse_rsync_hardlink(const std::string& a_value)
02557 {
02558 std::string es;
02559 estring str;
02560
02561 TRY_nomem(es = "Invalid rsync-hardlink value: \"");
02562 TRY_nomem(es += a_value);
02563 TRY_nomem(es += "\"");
02564 TRY(str = estring(a_value).lower(),es);
02565 if (
02566 (str == "y")
02567 || (str == "yes")
02568 || (str == "t")
02569 || (str == "true")
02570 || (str == "1")
02571 || (str == "on")
02572 ) {
02573 (*m_job).rsync_hardlink = true;
02574 }
02575 else if (
02576 (str == "n")
02577 || (str == "no")
02578 || (str == "f")
02579 || (str == "false")
02580 || (str == "0")
02581 || (str == "off")
02582 ) {
02583 (*m_job).rsync_hardlink = false;
02584 }
02585 else {
02586 throw(ERROR(0,es));
02587 }
02588 }
02589
02590
02591 void job_parser::parse_rsync_options(const std::string& a_value)
02592 {
02593 if (*m_delimiter == "</default>") {
02594 TRY_nomem((*m_job).rsync_options = a_value);
02595 }
02596 else {
02597 if ((*m_job).rsync_options.size() != 0) {
02598 TRY_nomem((*m_job).rsync_options += " ");
02599 }
02600 TRY_nomem((*m_job).rsync_options += a_value);
02601 }
02602 }
02603
02604
02605 void job_parser::parse_rsync_options_context(const std::string& a_value)
02606 {
02607 std::string es;
02608 std::string value;
02609 std::string rsync_options;
02610 char ch;
02611
02612 while ((*m_in)) {
02613 (*m_line)++;
02614
02615 value.erase();
02616
02617 (*m_in).get(ch);
02618 while ((ch == ' ') || (ch == '\t'))
02619 (*m_in).get(ch);
02620 while (((*m_in)) && (ch != '\n')) {
02621 TRY_nomem(value += ch);
02622 (*m_in).get(ch);
02623 }
02624
02625 if ((!(*m_in)) && (value != "</rsync-options>")) {
02626 TRY_nomem(es = "Unexpected end of file, expected ");
02627 TRY_nomem(es += "\"</rsync-options>\" here");
02628 throw(ERROR(errno,es));
02629 }
02630
02631 if (value.size() == 0)
02632 continue;
02633 if (value[0] == '#')
02634 continue;
02635
02636 if (value == "</rsync-options>") {
02637 parse_rsync_options(rsync_options);
02638 return;
02639 }
02640
02641 if (rsync_options.size() != 0) {
02642 TRY_nomem(rsync_options += ' ');
02643 }
02644 TRY_nomem(rsync_options += value);
02645 }
02646 }
02647
02648
02649 void job_parser::parse_rsync_remote_user(const std::string& a_value)
02650 {
02651 TRY_nomem((*m_job).rsync_remote_user = a_value);
02652 }
02653
02654
02655 void job_parser::parse_rsync_remote_path(const std::string& a_value)
02656 {
02657 TRY_nomem((*m_job).rsync_remote_path = a_value);
02658 }
02659
02660
02661 void job_parser::parse_rsync_remote_port(const std::string& a_value)
02662 {
02663 std::string es;
02664 estring str;
02665 uint16 num;
02666
02667 TRY_nomem(es = "Invalid rsync-remote-port value: \"");
02668 TRY_nomem(es += a_value);
02669 TRY_nomem(es += "\"");
02670 TRY_nomem(str = a_value);
02671 TRY(num = str,es);
02672 (*m_job).rsync_remote_port = num;
02673 }
02674
02675
02676 void job_parser::parse_rsync_remote_module(const std::string& a_value)
02677 {
02678 TRY_nomem((*m_job).rsync_remote_module = a_value);
02679 }
02680
02681
02682 void job_parser::parse_rsync_retry_count(const std::string& a_value)
02683 {
02684 std::string es;
02685 estring str;
02686 uint16 num;
02687
02688 TRY_nomem(es = "Invalid rsync-retry-count value: \"");
02689 TRY_nomem(es += a_value);
02690 TRY_nomem(es += "\"");
02691 TRY_nomem(str = a_value);
02692 TRY(num = str,es);
02693 (*m_job).rsync_retry_count = num;
02694 }
02695
02696
02697 void job_parser::parse_rsync_timeout(const std::string& a_value)
02698 {
02699 std::string es;
02700 estring str;
02701 uint16 num;
02702
02703 TRY_nomem(es = "Invalid rsync-timeout value: \"");
02704 TRY_nomem(es += a_value);
02705 TRY_nomem(es += "\"");
02706 TRY_nomem(str = a_value);
02707 TRY(num = str,es);
02708 (*m_job).rsync_timeout = num;
02709 }
02710
02711
02712
02713
02714 configuration_manager config;
02715