PageRenderTime 62ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/amanda/tags/3_3_0_qa07/client-src/client_util.c

#
C | 1874 lines | 1818 code | 24 blank | 32 comment | 45 complexity | ee8398441e301f99f5b5304aad9c0f41 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Amanda, The Advanced Maryland Automatic Network Disk Archiver
  3. * Copyright (c) 1991-1998 University of Maryland at College Park
  4. * All Rights Reserved.
  5. *
  6. * Permission to use, copy, modify, distribute, and sell this software and its
  7. * documentation for any purpose is hereby granted without fee, provided that
  8. * the above copyright notice appear in all copies and that both that
  9. * copyright notice and this permission notice appear in supporting
  10. * documentation, and that the name of U.M. not be used in advertising or
  11. * publicity pertaining to distribution of the software without specific,
  12. * written prior permission. U.M. makes no representations about the
  13. * suitability of this software for any purpose. It is provided "as is"
  14. * without express or implied warranty.
  15. *
  16. * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
  18. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  21. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22. *
  23. * Authors: the Amanda Development Team. Its members are listed in a
  24. * file named AUTHORS, in the root directory of this distribution.
  25. */
  26. /*
  27. * $Id: client_util.c,v 1.34 2006/05/25 01:47:11 johnfranks Exp $
  28. *
  29. */
  30. #include "amanda.h"
  31. #include "conffile.h"
  32. #include "client_util.h"
  33. #include "getfsent.h"
  34. #include "util.h"
  35. #include "glib-util.h"
  36. #include "timestamp.h"
  37. #include "pipespawn.h"
  38. #include "amxml.h"
  39. #include "glob.h"
  40. #include "clock.h"
  41. #include "amandates.h"
  42. #define MAXMAXDUMPS 16
  43. static int add_exclude(FILE *file_exclude, char *aexc, int verbose);
  44. static int add_include(char *disk, char *device, FILE *file_include, char *ainc, int verbose);
  45. static char *build_name(char *disk, char *exin, int verbose);
  46. static char *get_name(char *diskname, char *exin, time_t t, int n);
  47. char *
  48. fixup_relative(
  49. char * name,
  50. char * device)
  51. {
  52. char *newname;
  53. if(*name != '/') {
  54. char *dirname = amname_to_dirname(device);
  55. newname = vstralloc(dirname, "/", name , NULL);
  56. amfree(dirname);
  57. }
  58. else {
  59. newname = stralloc(name);
  60. }
  61. return newname;
  62. }
  63. /* GDestroyFunc for a hash table whose values are GSLists contianing malloc'd
  64. * strings */
  65. static void
  66. destroy_slist_free_full(gpointer list) {
  67. slist_free_full((GSList *)list, g_free);
  68. }
  69. static char *
  70. get_name(
  71. char * diskname,
  72. char * exin,
  73. time_t t,
  74. int n)
  75. {
  76. char number[NUM_STR_SIZE];
  77. char *filename;
  78. char *ts;
  79. ts = get_timestamp_from_time(t);
  80. if(n == 0)
  81. number[0] = '\0';
  82. else
  83. g_snprintf(number, SIZEOF(number), "%03d", n - 1);
  84. filename = vstralloc(get_pname(), ".", diskname, ".", ts, number, ".",
  85. exin, NULL);
  86. amfree(ts);
  87. return filename;
  88. }
  89. static char *
  90. build_name(
  91. char * disk,
  92. char * exin,
  93. int verbose)
  94. {
  95. int n;
  96. int fd;
  97. char *filename = NULL;
  98. char *afilename = NULL;
  99. char *diskname;
  100. time_t curtime;
  101. char *dbgdir;
  102. char *e = NULL;
  103. DIR *d;
  104. struct dirent *entry;
  105. char *test_name;
  106. size_t match_len, d_name_len;
  107. char *quoted;
  108. time(&curtime);
  109. diskname = sanitise_filename(disk);
  110. dbgdir = stralloc2(AMANDA_TMPDIR, "/");
  111. if((d = opendir(AMANDA_TMPDIR)) == NULL) {
  112. error(_("open debug directory \"%s\": %s"),
  113. AMANDA_TMPDIR, strerror(errno));
  114. /*NOTREACHED*/
  115. }
  116. test_name = get_name(diskname, exin,
  117. curtime - (getconf_int(CNF_DEBUG_DAYS) * 24 * 60 * 60), 0);
  118. match_len = strlen(get_pname()) + strlen(diskname) + 2;
  119. while((entry = readdir(d)) != NULL) {
  120. if(is_dot_or_dotdot(entry->d_name)) {
  121. continue;
  122. }
  123. d_name_len = strlen(entry->d_name);
  124. if(strncmp(test_name, entry->d_name, match_len) != 0
  125. || d_name_len < match_len + 14 + 8
  126. || strcmp(entry->d_name+ d_name_len - 7, exin) != 0) {
  127. continue; /* not one of our files */
  128. }
  129. if(strcmp(entry->d_name, test_name) < 0) {
  130. e = newvstralloc(e, dbgdir, entry->d_name, NULL);
  131. (void) unlink(e); /* get rid of old file */
  132. }
  133. }
  134. amfree(test_name);
  135. amfree(e);
  136. closedir(d);
  137. n=0;
  138. do {
  139. filename = get_name(diskname, exin, curtime, n);
  140. afilename = newvstralloc(afilename, dbgdir, filename, NULL);
  141. if((fd=open(afilename, O_WRONLY|O_CREAT|O_APPEND, 0600)) < 0){
  142. amfree(afilename);
  143. n++;
  144. }
  145. else {
  146. close(fd);
  147. }
  148. amfree(filename);
  149. } while(!afilename && n < 1000);
  150. if(afilename == NULL) {
  151. filename = get_name(diskname, exin, curtime, 0);
  152. afilename = newvstralloc(afilename, dbgdir, filename, NULL);
  153. quoted = quote_string(afilename);
  154. dbprintf(_("Cannot create %s (%s)\n"), quoted, strerror(errno));
  155. if(verbose) {
  156. g_printf(_("ERROR [cannot create %s (%s)]\n"),
  157. quoted, strerror(errno));
  158. }
  159. amfree(quoted);
  160. amfree(afilename);
  161. amfree(filename);
  162. }
  163. amfree(dbgdir);
  164. amfree(diskname);
  165. return afilename;
  166. }
  167. static int
  168. add_exclude(
  169. FILE * file_exclude,
  170. char * aexc,
  171. int verbose)
  172. {
  173. size_t l;
  174. char *quoted, *file;
  175. (void)verbose; /* Quiet unused parameter warning */
  176. l = strlen(aexc);
  177. if(aexc[l-1] == '\n') {
  178. aexc[l-1] = '\0';
  179. l--;
  180. }
  181. file = quoted = quote_string(aexc);
  182. if (*file == '"') {
  183. file[strlen(file) - 1] = '\0';
  184. file++;
  185. }
  186. g_fprintf(file_exclude, "%s\n", file);
  187. amfree(quoted);
  188. return 1;
  189. }
  190. static int
  191. add_include(
  192. char * disk,
  193. char * device,
  194. FILE * file_include,
  195. char * ainc,
  196. int verbose)
  197. {
  198. size_t l;
  199. int nb_exp=0;
  200. char *quoted, *file;
  201. (void)disk; /* Quiet unused parameter warning */
  202. (void)device; /* Quiet unused parameter warning */
  203. l = strlen(ainc);
  204. if(ainc[l-1] == '\n') {
  205. ainc[l-1] = '\0';
  206. l--;
  207. }
  208. if (strncmp(ainc, "./", 2) != 0) {
  209. quoted = quote_string(ainc);
  210. dbprintf(_("include must start with './' (%s)\n"), quoted);
  211. if(verbose) {
  212. g_printf(_("ERROR [include must start with './' (%s)]\n"), quoted);
  213. }
  214. amfree(quoted);
  215. }
  216. else {
  217. char *incname = ainc+2;
  218. int set_root;
  219. set_root = set_root_privs(1);
  220. /* Take as is if not root && many '/' */
  221. if(!set_root && strchr(incname, '/')) {
  222. file = quoted = quote_string(ainc);
  223. if (*file == '"') {
  224. file[strlen(file) - 1] = '\0';
  225. file++;
  226. }
  227. g_fprintf(file_include, "%s\n", file);
  228. amfree(quoted);
  229. nb_exp++;
  230. }
  231. else {
  232. int nb;
  233. glob_t globbuf;
  234. char *cwd;
  235. globbuf.gl_offs = 0;
  236. cwd = g_get_current_dir();
  237. if (chdir(device) != 0) {
  238. error(_("Failed to chdir(%s): %s\n"), device, strerror(errno));
  239. }
  240. glob(incname, 0, NULL, &globbuf);
  241. if (chdir(cwd) != 0) {
  242. error(_("Failed to chdir(%s): %s\n"), cwd, strerror(errno));
  243. }
  244. if (set_root)
  245. set_root_privs(0);
  246. nb_exp = globbuf.gl_pathc;
  247. for (nb=0; nb < nb_exp; nb++) {
  248. file = stralloc2("./", globbuf.gl_pathv[nb]);
  249. quoted = quote_string(file);
  250. if (*file == '"') {
  251. file[strlen(file) - 1] = '\0';
  252. file++;
  253. }
  254. g_fprintf(file_include, "%s\n", file);
  255. amfree(quoted);
  256. amfree(file);
  257. }
  258. }
  259. }
  260. return nb_exp;
  261. }
  262. char *
  263. build_exclude(
  264. dle_t *dle,
  265. int verbose)
  266. {
  267. char *filename;
  268. FILE *file_exclude;
  269. FILE *exclude;
  270. char *aexc;
  271. sle_t *excl;
  272. int nb_exclude = 0;
  273. char *quoted;
  274. if (dle->exclude_file) nb_exclude += dle->exclude_file->nb_element;
  275. if (dle->exclude_list) nb_exclude += dle->exclude_list->nb_element;
  276. if (nb_exclude == 0) return NULL;
  277. if ((filename = build_name(dle->disk, "exclude", verbose)) != NULL) {
  278. if ((file_exclude = fopen(filename,"w")) != NULL) {
  279. if (dle->exclude_file) {
  280. for(excl = dle->exclude_file->first; excl != NULL;
  281. excl = excl->next) {
  282. add_exclude(file_exclude, excl->name,
  283. verbose && dle->exclude_optional == 0);
  284. }
  285. }
  286. if (dle->exclude_list) {
  287. for(excl = dle->exclude_list->first; excl != NULL;
  288. excl = excl->next) {
  289. char *exclname = fixup_relative(excl->name, dle->device);
  290. if((exclude = fopen(exclname, "r")) != NULL) {
  291. while ((aexc = agets(exclude)) != NULL) {
  292. if (aexc[0] == '\0') {
  293. amfree(aexc);
  294. continue;
  295. }
  296. add_exclude(file_exclude, aexc,
  297. verbose && dle->exclude_optional == 0);
  298. amfree(aexc);
  299. }
  300. fclose(exclude);
  301. }
  302. else {
  303. quoted = quote_string(exclname);
  304. dbprintf(_("Can't open exclude file %s (%s)\n"),
  305. quoted, strerror(errno));
  306. if(verbose && (dle->exclude_optional == 0 ||
  307. errno != ENOENT)) {
  308. g_printf(_("ERROR [Can't open exclude file %s (%s)]\n"),
  309. quoted, strerror(errno));
  310. }
  311. amfree(quoted);
  312. }
  313. amfree(exclname);
  314. }
  315. }
  316. fclose(file_exclude);
  317. } else {
  318. quoted = quote_string(filename);
  319. dbprintf(_("Can't create exclude file %s (%s)\n"),
  320. quoted, strerror(errno));
  321. if (verbose) {
  322. g_printf(_("ERROR [Can't create exclude file %s (%s)]\n"),
  323. quoted, strerror(errno));
  324. }
  325. amfree(quoted);
  326. }
  327. }
  328. return filename;
  329. }
  330. char *
  331. build_include(
  332. dle_t *dle,
  333. int verbose)
  334. {
  335. char *filename;
  336. FILE *file_include;
  337. FILE *include;
  338. char *ainc = NULL;
  339. sle_t *incl;
  340. int nb_include = 0;
  341. int nb_exp = 0;
  342. char *quoted;
  343. if (dle->include_file) nb_include += dle->include_file->nb_element;
  344. if (dle->include_list) nb_include += dle->include_list->nb_element;
  345. if (nb_include == 0) return NULL;
  346. if ((filename = build_name(dle->disk, "include", verbose)) != NULL) {
  347. if ((file_include = fopen(filename,"w")) != NULL) {
  348. if (dle->include_file) {
  349. for (incl = dle->include_file->first; incl != NULL;
  350. incl = incl->next) {
  351. nb_exp += add_include(dle->disk, dle->device, file_include,
  352. incl->name,
  353. verbose && dle->include_optional == 0);
  354. }
  355. }
  356. if (dle->include_list) {
  357. for (incl = dle->include_list->first; incl != NULL;
  358. incl = incl->next) {
  359. char *inclname = fixup_relative(incl->name, dle->device);
  360. if ((include = fopen(inclname, "r")) != NULL) {
  361. while ((ainc = agets(include)) != NULL) {
  362. if (ainc[0] == '\0') {
  363. amfree(ainc);
  364. continue;
  365. }
  366. nb_exp += add_include(dle->disk, dle->device,
  367. file_include, ainc,
  368. verbose && dle->include_optional == 0);
  369. amfree(ainc);
  370. }
  371. fclose(include);
  372. }
  373. else {
  374. quoted = quote_string(inclname);
  375. dbprintf(_("Can't open include file %s (%s)\n"),
  376. quoted, strerror(errno));
  377. if (verbose && (dle->include_optional == 0 ||
  378. errno != ENOENT)) {
  379. g_printf(_("ERROR [Can't open include file %s (%s)]\n"),
  380. quoted, strerror(errno));
  381. }
  382. amfree(quoted);
  383. }
  384. amfree(inclname);
  385. }
  386. }
  387. fclose(file_include);
  388. } else {
  389. quoted = quote_string(filename);
  390. dbprintf(_("Can't create include file %s (%s)\n"),
  391. quoted, strerror(errno));
  392. if (verbose) {
  393. g_printf(_("ERROR [Can't create include file %s (%s)]\n"),
  394. quoted, strerror(errno));
  395. }
  396. amfree(quoted);
  397. }
  398. }
  399. if (nb_exp == 0) {
  400. quoted = quote_string(dle->disk);
  401. dbprintf(_("Nothing found to include for disk %s\n"), quoted);
  402. if (verbose && dle->include_optional == 0) {
  403. g_printf(_("ERROR [Nothing found to include for disk %s]\n"), quoted);
  404. }
  405. amfree(quoted);
  406. }
  407. return filename;
  408. }
  409. void
  410. parse_options(
  411. char *str,
  412. dle_t *dle,
  413. am_feature_t *fs,
  414. int verbose)
  415. {
  416. char *exc;
  417. char *inc;
  418. char *p, *tok;
  419. char *quoted;
  420. p = stralloc(str);
  421. tok = strtok(p,";");
  422. while (tok != NULL) {
  423. if(am_has_feature(fs, fe_options_auth)
  424. && BSTRNCMP(tok,"auth=") == 0) {
  425. if (dle->auth != NULL) {
  426. quoted = quote_string(tok + 5);
  427. dbprintf(_("multiple auth option %s\n"), quoted);
  428. if(verbose) {
  429. g_printf(_("ERROR [multiple auth option %s]\n"), quoted);
  430. }
  431. amfree(quoted);
  432. }
  433. dle->auth = stralloc(&tok[5]);
  434. }
  435. else if(am_has_feature(fs, fe_options_bsd_auth)
  436. && BSTRNCMP(tok, "bsd-auth") == 0) {
  437. if (dle->auth != NULL) {
  438. dbprintf(_("multiple auth option\n"));
  439. if (verbose) {
  440. g_printf(_("ERROR [multiple auth option]\n"));
  441. }
  442. }
  443. dle->auth = stralloc("bsd");
  444. }
  445. else if (BSTRNCMP(tok, "compress-fast") == 0) {
  446. if (dle->compress != COMP_NONE) {
  447. dbprintf(_("multiple compress option\n"));
  448. if (verbose) {
  449. g_printf(_("ERROR [multiple compress option]\n"));
  450. }
  451. }
  452. dle->compress = COMP_FAST;
  453. }
  454. else if (BSTRNCMP(tok, "compress-best") == 0) {
  455. if (dle->compress != COMP_NONE) {
  456. dbprintf(_("multiple compress option\n"));
  457. if (verbose) {
  458. g_printf(_("ERROR [multiple compress option]\n"));
  459. }
  460. }
  461. dle->compress = COMP_BEST;
  462. }
  463. else if (BSTRNCMP(tok, "srvcomp-fast") == 0) {
  464. if (dle->compress != COMP_NONE) {
  465. dbprintf(_("multiple compress option\n"));
  466. if (verbose) {
  467. g_printf(_("ERROR [multiple compress option]\n"));
  468. }
  469. }
  470. dle->compress = COMP_SERVER_FAST;
  471. }
  472. else if (BSTRNCMP(tok, "srvcomp-best") == 0) {
  473. if (dle->compress != COMP_NONE) {
  474. dbprintf(_("multiple compress option\n"));
  475. if (verbose) {
  476. g_printf(_("ERROR [multiple compress option]\n"));
  477. }
  478. }
  479. dle->compress = COMP_SERVER_BEST;
  480. }
  481. else if (BSTRNCMP(tok, "srvcomp-cust=") == 0) {
  482. if (dle->compress != COMP_NONE) {
  483. dbprintf(_("multiple compress option\n"));
  484. if (verbose) {
  485. g_printf(_("ERROR [multiple compress option]\n"));
  486. }
  487. }
  488. dle->compprog = stralloc(tok + SIZEOF("srvcomp-cust=") -1);
  489. dle->compress = COMP_SERVER_CUST;
  490. }
  491. else if (BSTRNCMP(tok, "comp-cust=") == 0) {
  492. if (dle->compress != COMP_NONE) {
  493. dbprintf(_("multiple compress option\n"));
  494. if (verbose) {
  495. g_printf(_("ERROR [multiple compress option]\n"));
  496. }
  497. }
  498. dle->compprog = stralloc(tok + SIZEOF("comp-cust=") -1);
  499. dle->compress = COMP_CUST;
  500. /* parse encryption options */
  501. }
  502. else if (BSTRNCMP(tok, "encrypt-serv-cust=") == 0) {
  503. if (dle->encrypt != ENCRYPT_NONE) {
  504. dbprintf(_("multiple encrypt option\n"));
  505. if (verbose) {
  506. g_printf(_("ERROR [multiple encrypt option]\n"));
  507. }
  508. }
  509. dle->srv_encrypt = stralloc(tok + SIZEOF("encrypt-serv-cust=") -1);
  510. dle->encrypt = ENCRYPT_SERV_CUST;
  511. }
  512. else if (BSTRNCMP(tok, "encrypt-cust=") == 0) {
  513. if (dle->encrypt != ENCRYPT_NONE) {
  514. dbprintf(_("multiple encrypt option\n"));
  515. if (verbose) {
  516. g_printf(_("ERROR [multiple encrypt option]\n"));
  517. }
  518. }
  519. dle->clnt_encrypt= stralloc(tok + SIZEOF("encrypt-cust=") -1);
  520. dle->encrypt = ENCRYPT_CUST;
  521. }
  522. else if (BSTRNCMP(tok, "server-decrypt-option=") == 0) {
  523. dle->srv_decrypt_opt = stralloc(tok + SIZEOF("server-decrypt-option=") -1);
  524. }
  525. else if (BSTRNCMP(tok, "client-decrypt-option=") == 0) {
  526. dle->clnt_decrypt_opt = stralloc(tok + SIZEOF("client-decrypt-option=") -1);
  527. }
  528. else if (BSTRNCMP(tok, "no-record") == 0) {
  529. if (dle->record != 1) {
  530. dbprintf(_("multiple no-record option\n"));
  531. if (verbose) {
  532. g_printf(_("ERROR [multiple no-record option]\n"));
  533. }
  534. }
  535. dle->record = 0;
  536. }
  537. else if (BSTRNCMP(tok, "index") == 0) {
  538. if (dle->create_index != 0) {
  539. dbprintf(_("multiple index option\n"));
  540. if (verbose) {
  541. g_printf(_("ERROR [multiple index option]\n"));
  542. }
  543. }
  544. dle->create_index = 1;
  545. }
  546. else if (BSTRNCMP(tok, "exclude-optional") == 0) {
  547. if (dle->exclude_optional != 0) {
  548. dbprintf(_("multiple exclude-optional option\n"));
  549. if (verbose) {
  550. g_printf(_("ERROR [multiple exclude-optional option]\n"));
  551. }
  552. }
  553. dle->exclude_optional = 1;
  554. }
  555. else if (strcmp(tok, "include-optional") == 0) {
  556. if (dle->include_optional != 0) {
  557. dbprintf(_("multiple include-optional option\n"));
  558. if (verbose) {
  559. g_printf(_("ERROR [multiple include-optional option]\n"));
  560. }
  561. }
  562. dle->include_optional = 1;
  563. }
  564. else if (BSTRNCMP(tok,"exclude-file=") == 0) {
  565. exc = unquote_string(&tok[13]);
  566. dle->exclude_file = append_sl(dle->exclude_file, exc);
  567. amfree(exc);
  568. }
  569. else if (BSTRNCMP(tok,"exclude-list=") == 0) {
  570. exc = unquote_string(&tok[13]);
  571. dle->exclude_list = append_sl(dle->exclude_list, exc);
  572. amfree(exc);
  573. }
  574. else if (BSTRNCMP(tok,"include-file=") == 0) {
  575. inc = unquote_string(&tok[13]);
  576. dle->include_file = append_sl(dle->include_file, inc);
  577. amfree(inc);
  578. }
  579. else if (BSTRNCMP(tok,"include-list=") == 0) {
  580. inc = unquote_string(&tok[13]);
  581. dle->include_list = append_sl(dle->include_list, inc);
  582. amfree(inc);
  583. }
  584. else if (BSTRNCMP(tok,"kencrypt") == 0) {
  585. dle->kencrypt = 1;
  586. }
  587. else if (strcmp(tok,"|") != 0) {
  588. quoted = quote_string(tok);
  589. dbprintf(_("unknown option %s\n"), quoted);
  590. if (verbose) {
  591. g_printf(_("ERROR [unknown option: %s]\n"), quoted);
  592. }
  593. amfree(quoted);
  594. }
  595. tok = strtok(NULL, ";");
  596. }
  597. amfree(p);
  598. }
  599. void
  600. application_property_add_to_argv(
  601. GPtrArray *argv_ptr,
  602. dle_t *dle,
  603. backup_support_option_t *bsu,
  604. am_feature_t *amfeatures)
  605. {
  606. sle_t *incl, *excl;
  607. if (bsu) {
  608. if (bsu->include_file && dle->include_file) {
  609. for (incl = dle->include_file->first; incl != NULL;
  610. incl = incl->next) {
  611. g_ptr_array_add(argv_ptr, stralloc("--include-file"));
  612. g_ptr_array_add(argv_ptr, stralloc(incl->name));
  613. }
  614. }
  615. if (bsu->include_list && dle->include_list) {
  616. for (incl = dle->include_list->first; incl != NULL;
  617. incl = incl->next) {
  618. g_ptr_array_add(argv_ptr, stralloc("--include-list"));
  619. g_ptr_array_add(argv_ptr, stralloc(incl->name));
  620. }
  621. }
  622. if (bsu->include_optional && dle->include_optional) {
  623. g_ptr_array_add(argv_ptr, stralloc("--include-optional"));
  624. g_ptr_array_add(argv_ptr, stralloc("yes"));
  625. }
  626. if (bsu->exclude_file && dle->exclude_file) {
  627. for (excl = dle->exclude_file->first; excl != NULL;
  628. excl = excl->next) {
  629. g_ptr_array_add(argv_ptr, stralloc("--exclude-file"));
  630. g_ptr_array_add(argv_ptr, stralloc(excl->name));
  631. }
  632. }
  633. if (bsu->exclude_list && dle->exclude_list) {
  634. for (excl = dle->exclude_list->first; excl != NULL;
  635. excl = excl->next) {
  636. g_ptr_array_add(argv_ptr, stralloc("--exclude-list"));
  637. g_ptr_array_add(argv_ptr, stralloc(excl->name));
  638. }
  639. }
  640. if (bsu->exclude_optional && dle->exclude_optional) {
  641. g_ptr_array_add(argv_ptr, stralloc("--exclude-optional"));
  642. g_ptr_array_add(argv_ptr, stralloc("yes"));
  643. }
  644. if (bsu->features && amfeatures) {
  645. char *feature_string = am_feature_to_string(amfeatures);
  646. g_ptr_array_add(argv_ptr, stralloc("--amfeatures"));
  647. g_ptr_array_add(argv_ptr, feature_string);
  648. }
  649. if (dle->data_path == DATA_PATH_DIRECTTCP &&
  650. bsu->data_path_set & DATA_PATH_DIRECTTCP) {
  651. GSList *directtcp;
  652. g_ptr_array_add(argv_ptr, stralloc("--data-path"));
  653. g_ptr_array_add(argv_ptr, stralloc("directtcp"));
  654. for (directtcp = dle->directtcp_list; directtcp != NULL;
  655. directtcp = directtcp->next) {
  656. g_ptr_array_add(argv_ptr, stralloc("--direct-tcp"));
  657. g_ptr_array_add(argv_ptr, stralloc(directtcp->data));
  658. break; /* XXX temporary; apps only support one ip:port pair */
  659. }
  660. }
  661. }
  662. property_add_to_argv(argv_ptr, dle->application_property);
  663. return;
  664. }
  665. typedef struct {
  666. dle_t *dle;
  667. char *name;
  668. proplist_t dle_proplist;
  669. int verbose;
  670. int good;
  671. } merge_property_t;
  672. static void
  673. merge_property(
  674. gpointer key_p,
  675. gpointer value_p,
  676. gpointer user_data_p)
  677. {
  678. char *property_s = key_p;
  679. property_t *conf_property = value_p;
  680. merge_property_t *merge_p = user_data_p;
  681. property_t *dle_property = g_hash_table_lookup(merge_p->dle_proplist,
  682. property_s);
  683. GSList *value;
  684. char *qdisk = quote_string(merge_p->dle->disk);
  685. if (dle_property) {
  686. if (dle_property->priority && conf_property->priority) {
  687. if (merge_p->verbose) {
  688. g_fprintf(stdout,
  689. _("ERROR %s (%s) Both server client have priority for property '%s'.\n"),
  690. qdisk, merge_p->name, property_s);
  691. }
  692. g_debug("ERROR %s (%s) Both server client have priority for property '%s'.", qdisk, merge_p->name, property_s);
  693. merge_p->good = 0;
  694. /* Use client property */
  695. g_hash_table_remove(merge_p->dle_proplist, key_p);
  696. g_hash_table_insert(merge_p->dle_proplist, key_p, conf_property);
  697. } else if (dle_property->priority) {
  698. if (merge_p->verbose) {
  699. g_fprintf(stdout,
  700. _("ERROR %s (%s) Server set priority for property '%s' but client set the property.\n"),
  701. qdisk, merge_p->name, property_s);
  702. }
  703. g_debug("%s (%s) Server set priority for property '%s' but client set the property.", qdisk, merge_p->name, property_s);
  704. /* use server property */
  705. } else if (conf_property->priority) {
  706. if (merge_p->verbose) {
  707. g_fprintf(stdout,
  708. _("ERROR %s (%s) Client set priority for property '%s' but server set the property.\n"),
  709. qdisk, merge_p->name, property_s);
  710. }
  711. g_debug("%s (%s) Client set priority for property '%s' but server set the property.", qdisk, merge_p->name, property_s);
  712. /* Use client property */
  713. g_hash_table_remove(merge_p->dle_proplist, key_p);
  714. g_hash_table_insert(merge_p->dle_proplist, key_p, conf_property);
  715. } else if (!conf_property->append) {
  716. if (merge_p->verbose) {
  717. g_fprintf(stdout,
  718. _("ERROR %s (%s) Both server and client set property '%s', using client value.\n"),
  719. qdisk, merge_p->name, property_s);
  720. }
  721. g_debug("%s (%s) Both server and client set property '%s', using client value.", qdisk, merge_p->name, property_s);
  722. /* Use client property */
  723. g_hash_table_remove(merge_p->dle_proplist, key_p);
  724. g_hash_table_insert(merge_p->dle_proplist, key_p, conf_property);
  725. } else { /* merge */
  726. for (value = conf_property->values; value != NULL;
  727. value = value->next) {
  728. dle_property->values = g_slist_append(dle_property->values,
  729. value->data);
  730. }
  731. }
  732. } else { /* take value from conf */
  733. g_hash_table_insert(merge_p->dle_proplist, key_p, conf_property);
  734. }
  735. }
  736. int
  737. merge_properties(
  738. dle_t *dle,
  739. char *name,
  740. proplist_t dle_proplist,
  741. proplist_t conf_proplist,
  742. int verbose)
  743. {
  744. merge_property_t merge_p = {dle, name, dle_proplist, verbose, 1};
  745. if (conf_proplist != NULL) {
  746. g_hash_table_foreach(conf_proplist,
  747. &merge_property,
  748. &merge_p);
  749. }
  750. return merge_p.good;
  751. }
  752. int
  753. merge_dles_properties(
  754. dle_t *dles,
  755. int verbose)
  756. {
  757. dle_t *dle;
  758. application_t *app;
  759. GSList *scriptlist;
  760. pp_script_t *pp_script;
  761. int good = 1;
  762. for (dle=dles; dle != NULL; dle=dle->next) {
  763. if (dle->program_is_application_api) {
  764. app = NULL;
  765. if (dle->application_client_name &&
  766. strlen(dle->application_client_name) > 0) {
  767. app = lookup_application(dle->application_client_name);
  768. if (!app) {
  769. char *qamname = quote_string(dle->disk);
  770. char *errmsg = vstrallocf("Application '%s' not found on client",
  771. dle->application_client_name);
  772. char *qerrmsg = quote_string(errmsg);
  773. good = 0;
  774. if (verbose) {
  775. g_fprintf(stdout, _("ERROR %s %s\n"), qamname, qerrmsg);
  776. }
  777. g_debug("%s: %s", qamname, qerrmsg);
  778. amfree(qamname);
  779. amfree(errmsg);
  780. amfree(qerrmsg);
  781. }
  782. } else {
  783. app = lookup_application(dle->program);
  784. }
  785. if (app) {
  786. merge_properties(dle, dle->program,
  787. dle->application_property,
  788. application_get_property(app),
  789. verbose);
  790. }
  791. }
  792. for (scriptlist = dle->scriptlist; scriptlist != NULL;
  793. scriptlist = scriptlist->next) {
  794. script_t *script = scriptlist->data;
  795. pp_script = NULL;
  796. if (script->client_name && strlen(script->client_name) > 0) {
  797. pp_script = lookup_pp_script(script->client_name);
  798. if (!pp_script) {
  799. char *qamname = quote_string(dle->disk);
  800. char *errmsg = vstrallocf("Script '%s' not found on client",
  801. script->client_name);
  802. char *qerrmsg = quote_string(errmsg);
  803. good = 0;
  804. if (verbose) {
  805. g_fprintf(stderr, _("ERROR %s %s\n"), qamname, qerrmsg);
  806. }
  807. g_debug("%s: %s", qamname, qerrmsg);
  808. amfree(qamname);
  809. amfree(errmsg);
  810. amfree(qerrmsg);
  811. }
  812. } else {
  813. pp_script = lookup_pp_script(script->plugin);
  814. }
  815. if (pp_script) {
  816. merge_properties(dle, script->plugin,
  817. script->property,
  818. pp_script_get_property(pp_script),
  819. verbose);
  820. }
  821. }
  822. }
  823. return good;
  824. }
  825. backup_support_option_t *
  826. backup_support_option(
  827. char *program,
  828. g_option_t *g_options,
  829. char *disk,
  830. char *amdevice,
  831. GPtrArray **errarray)
  832. {
  833. pid_t supportpid;
  834. int supportin, supportout, supporterr;
  835. char *cmd;
  836. GPtrArray *argv_ptr = g_ptr_array_new();
  837. FILE *streamout;
  838. FILE *streamerr;
  839. char *line;
  840. int status;
  841. char *err = NULL;
  842. backup_support_option_t *bsu;
  843. *errarray = g_ptr_array_new();
  844. cmd = vstralloc(APPLICATION_DIR, "/", program, NULL);
  845. g_ptr_array_add(argv_ptr, stralloc(program));
  846. g_ptr_array_add(argv_ptr, stralloc("support"));
  847. if (g_options->config) {
  848. g_ptr_array_add(argv_ptr, stralloc("--config"));
  849. g_ptr_array_add(argv_ptr, stralloc(g_options->config));
  850. }
  851. if (g_options->hostname) {
  852. g_ptr_array_add(argv_ptr, stralloc("--host"));
  853. g_ptr_array_add(argv_ptr, stralloc(g_options->hostname));
  854. }
  855. if (disk) {
  856. g_ptr_array_add(argv_ptr, stralloc("--disk"));
  857. g_ptr_array_add(argv_ptr, stralloc(disk));
  858. }
  859. if (amdevice) {
  860. g_ptr_array_add(argv_ptr, stralloc("--device"));
  861. g_ptr_array_add(argv_ptr, stralloc(amdevice));
  862. }
  863. g_ptr_array_add(argv_ptr, NULL);
  864. supporterr = fileno(stderr);
  865. supportpid = pipespawnv(cmd, STDIN_PIPE|STDOUT_PIPE|STDERR_PIPE, 0,
  866. &supportin, &supportout, &supporterr,
  867. (char **)argv_ptr->pdata);
  868. aclose(supportin);
  869. bsu = g_new0(backup_support_option_t, 1);
  870. bsu->config = 1;
  871. bsu->host = 1;
  872. bsu->disk = 1;
  873. streamout = fdopen(supportout, "r");
  874. if (!streamout) {
  875. error(_("Error opening pipe to child: %s"), strerror(errno));
  876. /* NOTREACHED */
  877. }
  878. while((line = agets(streamout)) != NULL) {
  879. dbprintf(_("support line: %s\n"), line);
  880. if (strncmp(line,"CONFIG ", 7) == 0) {
  881. if (strcmp(line+7, "YES") == 0)
  882. bsu->config = 1;
  883. } else if (strncmp(line,"HOST ", 5) == 0) {
  884. if (strcmp(line+5, "YES") == 0)
  885. bsu->host = 1;
  886. } else if (strncmp(line,"DISK ", 5) == 0) {
  887. if (strcmp(line+5, "YES") == 0)
  888. bsu->disk = 1;
  889. } else if (strncmp(line,"INDEX-LINE ", 11) == 0) {
  890. if (strcmp(line+11, "YES") == 0)
  891. bsu->index_line = 1;
  892. } else if (strncmp(line,"INDEX-XML ", 10) == 0) {
  893. if (strcmp(line+10, "YES") == 0)
  894. bsu->index_xml = 1;
  895. } else if (strncmp(line,"MESSAGE-LINE ", 13) == 0) {
  896. if (strcmp(line+13, "YES") == 0)
  897. bsu->message_line = 1;
  898. } else if (strncmp(line,"MESSAGE-XML ", 12) == 0) {
  899. if (strcmp(line+12, "YES") == 0)
  900. bsu->message_xml = 1;
  901. } else if (strncmp(line,"RECORD ", 7) == 0) {
  902. if (strcmp(line+7, "YES") == 0)
  903. bsu->record = 1;
  904. } else if (strncmp(line,"INCLUDE-FILE ", 13) == 0) {
  905. if (strcmp(line+13, "YES") == 0)
  906. bsu->include_file = 1;
  907. } else if (strncmp(line,"INCLUDE-LIST ", 13) == 0) {
  908. if (strcmp(line+13, "YES") == 0)
  909. bsu->include_list = 1;
  910. } else if (strncmp(line,"INCLUDE-LIST-GLOB ", 17) == 0) {
  911. if (strcmp(line+17, "YES") == 0)
  912. bsu->include_list_glob = 1;
  913. } else if (strncmp(line,"INCLUDE-OPTIONAL ", 17) == 0) {
  914. if (strcmp(line+17, "YES") == 0)
  915. bsu->include_optional = 1;
  916. } else if (strncmp(line,"EXCLUDE-FILE ", 13) == 0) {
  917. if (strcmp(line+13, "YES") == 0)
  918. bsu->exclude_file = 1;
  919. } else if (strncmp(line,"EXCLUDE-LIST ", 13) == 0) {
  920. if (strcmp(line+13, "YES") == 0)
  921. bsu->exclude_list = 1;
  922. } else if (strncmp(line,"EXCLUDE-LIST-GLOB ", 17) == 0) {
  923. if (strcmp(line+17, "YES") == 0)
  924. bsu->exclude_list_glob = 1;
  925. } else if (strncmp(line,"EXCLUDE-OPTIONAL ", 17) == 0) {
  926. if (strcmp(line+17, "YES") == 0)
  927. bsu->exclude_optional = 1;
  928. } else if (strncmp(line,"COLLECTION ", 11) == 0) {
  929. if (strcmp(line+11, "YES") == 0)
  930. bsu->collection = 1;
  931. } else if (strncmp(line,"CALCSIZE ", 9) == 0) {
  932. if (strcmp(line+9, "YES") == 0)
  933. bsu->calcsize = 1;
  934. } else if (strncmp(line,"CLIENT-ESTIMATE ", 16) == 0) {
  935. if (strcmp(line+16, "YES") == 0)
  936. bsu->client_estimate = 1;
  937. } else if (strncmp(line,"MULTI-ESTIMATE ", 15) == 0) {
  938. if (strcmp(line+15, "YES") == 0)
  939. bsu->multi_estimate = 1;
  940. } else if (strncmp(line,"MAX-LEVEL ", 10) == 0) {
  941. bsu->max_level = atoi(line+10);
  942. } else if (strncmp(line,"RECOVER-MODE ", 13) == 0) {
  943. if (strcasecmp(line+13, "SMB") == 0)
  944. bsu->smb_recover_mode = 1;
  945. } else if (strncmp(line,"DATA-PATH ", 10) == 0) {
  946. if (strcasecmp(line+10, "AMANDA") == 0)
  947. bsu->data_path_set |= DATA_PATH_AMANDA;
  948. else if (strcasecmp(line+10, "DIRECTTCP") == 0)
  949. bsu->data_path_set |= DATA_PATH_DIRECTTCP;
  950. } else if (strncmp(line,"RECOVER-PATH ", 13) == 0) {
  951. if (strcasecmp(line+13, "CWD") == 0)
  952. bsu->recover_path = RECOVER_PATH_CWD;
  953. else if (strcasecmp(line+13, "REMOTE") == 0)
  954. bsu->recover_path = RECOVER_PATH_REMOTE;
  955. } else if (strncmp(line,"AMFEATURES ", 11) == 0) {
  956. if (strcmp(line+11, "YES") == 0)
  957. bsu->features = 1;
  958. } else {
  959. dbprintf(_("Invalid support line: %s\n"), line);
  960. }
  961. amfree(line);
  962. }
  963. fclose(streamout);
  964. if (bsu->data_path_set == 0)
  965. bsu->data_path_set = DATA_PATH_AMANDA;
  966. streamerr = fdopen(supporterr, "r");
  967. if (!streamerr) {
  968. error(_("Error opening pipe to child: %s"), strerror(errno));
  969. /* NOTREACHED */
  970. }
  971. while((line = agets(streamerr)) != NULL) {
  972. if (strlen(line) > 0) {
  973. g_ptr_array_add(*errarray, line);
  974. dbprintf("Application '%s': %s\n", program, line);
  975. }
  976. amfree(bsu);
  977. }
  978. fclose(streamerr);
  979. if (waitpid(supportpid, &status, 0) < 0) {
  980. err = vstrallocf(_("waitpid failed: %s"), strerror(errno));
  981. } else if (!WIFEXITED(status)) {
  982. err = vstrallocf(_("exited with signal %d"), WTERMSIG(status));
  983. } else if (WEXITSTATUS(status) != 0) {
  984. err = vstrallocf(_("exited with status %d"), WEXITSTATUS(status));
  985. }
  986. if (err) {
  987. g_ptr_array_add(*errarray, err);
  988. dbprintf("Application '%s': %s\n", program, err);
  989. amfree(bsu);
  990. }
  991. g_ptr_array_free_full(argv_ptr);
  992. amfree(cmd);
  993. return bsu;
  994. }
  995. void
  996. run_client_script(
  997. script_t *script,
  998. execute_on_t execute_on,
  999. g_option_t *g_options,
  1000. dle_t *dle)
  1001. {
  1002. pid_t scriptpid;
  1003. int scriptin, scriptout, scripterr;
  1004. char *cmd;
  1005. GPtrArray *argv_ptr = g_ptr_array_new();
  1006. FILE *streamout;
  1007. FILE *streamerr;
  1008. char *line;
  1009. amwait_t wait_status;
  1010. char *command = NULL;
  1011. if ((script->execute_on & execute_on) == 0)
  1012. return;
  1013. if (script->execute_where != ES_CLIENT)
  1014. return;
  1015. cmd = vstralloc(APPLICATION_DIR, "/", script->plugin, NULL);
  1016. g_ptr_array_add(argv_ptr, stralloc(script->plugin));
  1017. switch (execute_on) {
  1018. case EXECUTE_ON_PRE_DLE_AMCHECK:
  1019. command = "PRE-DLE-AMCHECK";
  1020. break;
  1021. case EXECUTE_ON_PRE_HOST_AMCHECK:
  1022. command = "PRE-HOST-AMCHECK";
  1023. break;
  1024. case EXECUTE_ON_POST_DLE_AMCHECK:
  1025. command = "POST-DLE-AMCHECK";
  1026. break;
  1027. case EXECUTE_ON_POST_HOST_AMCHECK:
  1028. command = "POST-HOST-AMCHECK";
  1029. break;
  1030. case EXECUTE_ON_PRE_DLE_ESTIMATE:
  1031. command = "PRE-DLE-ESTIMATE";
  1032. break;
  1033. case EXECUTE_ON_PRE_HOST_ESTIMATE:
  1034. command = "PRE-HOST-ESTIMATE";
  1035. break;
  1036. case EXECUTE_ON_POST_DLE_ESTIMATE:
  1037. command = "POST-DLE-ESTIMATE";
  1038. break;
  1039. case EXECUTE_ON_POST_HOST_ESTIMATE:
  1040. command = "POST-HOST-ESTIMATE";
  1041. break;
  1042. case EXECUTE_ON_PRE_DLE_BACKUP:
  1043. command = "PRE-DLE-BACKUP";
  1044. break;
  1045. case EXECUTE_ON_PRE_HOST_BACKUP:
  1046. command = "PRE-HOST-BACKUP";
  1047. break;
  1048. case EXECUTE_ON_POST_DLE_BACKUP:
  1049. command = "POST-DLE-BACKUP";
  1050. break;
  1051. case EXECUTE_ON_POST_HOST_BACKUP:
  1052. command = "POST-HOST-BACKUP";
  1053. break;
  1054. case EXECUTE_ON_PRE_RECOVER:
  1055. command = "PRE-RECOVER";
  1056. break;
  1057. case EXECUTE_ON_POST_RECOVER:
  1058. command = "POST-RECOVER";
  1059. break;
  1060. case EXECUTE_ON_PRE_LEVEL_RECOVER:
  1061. command = "PRE-LEVEL-RECOVER";
  1062. break;
  1063. case EXECUTE_ON_POST_LEVEL_RECOVER:
  1064. command = "POST-LEVEL-RECOVER";
  1065. break;
  1066. case EXECUTE_ON_INTER_LEVEL_RECOVER:
  1067. command = "INTER-LEVEL-RECOVER";
  1068. break;
  1069. }
  1070. g_ptr_array_add(argv_ptr, stralloc(command));
  1071. g_ptr_array_add(argv_ptr, stralloc("--execute-where"));
  1072. g_ptr_array_add(argv_ptr, stralloc("client"));
  1073. if (g_options->config) {
  1074. g_ptr_array_add(argv_ptr, stralloc("--config"));
  1075. g_ptr_array_add(argv_ptr, stralloc(g_options->config));
  1076. }
  1077. if (g_options->hostname) {
  1078. g_ptr_array_add(argv_ptr, stralloc("--host"));
  1079. g_ptr_array_add(argv_ptr, stralloc(g_options->hostname));
  1080. }
  1081. if (dle->disk) {
  1082. g_ptr_array_add(argv_ptr, stralloc("--disk"));
  1083. g_ptr_array_add(argv_ptr, stralloc(dle->disk));
  1084. }
  1085. if (dle->device) {
  1086. g_ptr_array_add(argv_ptr, stralloc("--device"));
  1087. g_ptr_array_add(argv_ptr, stralloc(dle->device));
  1088. }
  1089. if (dle->levellist) {
  1090. levellist_t levellist;
  1091. char number[NUM_STR_SIZE];
  1092. for (levellist=dle->levellist; levellist; levellist=levellist->next) {
  1093. level_t *alevel = (level_t *)levellist->data;
  1094. g_ptr_array_add(argv_ptr, stralloc("--level"));
  1095. g_snprintf(number, SIZEOF(number), "%d", alevel->level);
  1096. g_ptr_array_add(argv_ptr, stralloc(number));
  1097. }
  1098. }
  1099. property_add_to_argv(argv_ptr, script->property);
  1100. g_ptr_array_add(argv_ptr, NULL);
  1101. scriptpid = pipespawnv(cmd, STDIN_PIPE|STDOUT_PIPE|STDERR_PIPE, 0,
  1102. &scriptin, &scriptout, &scripterr,
  1103. (char **)argv_ptr->pdata);
  1104. close(scriptin);
  1105. script->result = g_new0(client_script_result_t, 1);
  1106. script->result->proplist =
  1107. g_hash_table_new_full(g_str_hash, g_str_equal,
  1108. &g_free, &destroy_slist_free_full);
  1109. script->result->output = g_ptr_array_new();
  1110. script->result->err = g_ptr_array_new();
  1111. streamout = fdopen(scriptout, "r");
  1112. if (streamout) {
  1113. while((line = agets(streamout)) != NULL) {
  1114. dbprintf("script: %s\n", line);
  1115. if (BSTRNCMP(line, "PROPERTY ") == 0) {
  1116. char *property_name, *property_value;
  1117. property_name = line + 9;
  1118. property_value = strchr(property_name,' ');
  1119. if (property_value == NULL) {
  1120. char *msg = g_strdup_printf(
  1121. "ERROR %s: Bad output property: %s",
  1122. script->plugin, line);
  1123. g_ptr_array_add(script->result->output, msg);
  1124. } else {
  1125. property_t *property;
  1126. *property_value++ = '\0';
  1127. property_name = stralloc(property_name);
  1128. property_value = stralloc(property_value);
  1129. property = g_hash_table_lookup(script->result->proplist,
  1130. property_name);
  1131. if (!property) {
  1132. property = g_new0(property_t, 1);
  1133. g_hash_table_insert(script->result->proplist,
  1134. property_name, property);
  1135. }
  1136. property->values = g_slist_append(property->values,
  1137. property_value);
  1138. }
  1139. amfree(line);
  1140. } else {
  1141. g_ptr_array_add(script->result->output, line);
  1142. }
  1143. }
  1144. }
  1145. fclose(streamout);
  1146. streamerr = fdopen(scripterr, "r");
  1147. if (streamerr) {
  1148. while((line = agets(streamerr)) != NULL) {
  1149. g_ptr_array_add(script->result->err,
  1150. g_strdup_printf(_("Script '%s' command '%s': %s"),
  1151. script->plugin, command, line));
  1152. amfree(line);
  1153. }
  1154. }
  1155. waitpid(scriptpid, &wait_status, 0);
  1156. if (WIFSIGNALED(wait_status)) {
  1157. g_ptr_array_add(script->result->err,
  1158. g_strdup_printf(_("Script '%s' command '%s' terminated with signal %d: see %s"),
  1159. script->plugin, command,
  1160. WTERMSIG(wait_status),
  1161. dbfn()));
  1162. } else if (WIFEXITED(wait_status)) {
  1163. if (WEXITSTATUS(wait_status) != 0) {
  1164. g_ptr_array_add(script->result->err,
  1165. g_strdup_printf(_("Script '%s' command '%s' exited with status %d: see %s"),
  1166. script->plugin, command,
  1167. WEXITSTATUS(wait_status),
  1168. dbfn()));
  1169. } else {
  1170. /* Normal exit */
  1171. }
  1172. }
  1173. amfree(cmd);
  1174. g_ptr_array_free_full(argv_ptr);
  1175. }
  1176. void run_client_script_output(gpointer data, gpointer user_data);
  1177. void run_client_script_err_amcheck(gpointer data, gpointer user_data);
  1178. void run_client_script_err_estimate(gpointer data, gpointer user_data);
  1179. void run_client_script_err_backup(gpointer data, gpointer user_data);
  1180. void run_client_script_err_recover(gpointer data, gpointer user_data);
  1181. typedef struct script_output_s {
  1182. FILE *stream;
  1183. dle_t *dle;
  1184. } script_output_t;
  1185. void
  1186. run_client_script_output(
  1187. gpointer data,
  1188. gpointer user_data)
  1189. {
  1190. char *line = data;
  1191. script_output_t *so = user_data;
  1192. if (line && so->stream) {
  1193. g_fprintf(so->stream, "%s\n", line);
  1194. }
  1195. }
  1196. void
  1197. run_client_script_err_amcheck(
  1198. gpointer data,
  1199. gpointer user_data)
  1200. {
  1201. char *line = data;
  1202. script_output_t *so = user_data;
  1203. if (line && so->stream) {
  1204. g_fprintf(so->stream, "ERROR %s\n", line);
  1205. }
  1206. }
  1207. void
  1208. run_client_script_err_estimate(
  1209. gpointer data,
  1210. gpointer user_data)
  1211. {
  1212. char *line = data;
  1213. script_output_t *so = user_data;
  1214. if (line && so->stream) {
  1215. char *qdisk = quote_string(so->dle->disk);
  1216. g_fprintf(so->stream, "%s 0 WARNING \"%s\"\n", qdisk, line);
  1217. amfree(qdisk);
  1218. }
  1219. }
  1220. void
  1221. run_client_script_err_backup(
  1222. gpointer data,
  1223. gpointer user_data)
  1224. {
  1225. char *line = data;
  1226. script_output_t *so = user_data;
  1227. if (line && so->stream) {
  1228. g_fprintf(so->stream, "? %s\n", line);
  1229. }
  1230. }
  1231. void
  1232. run_client_script_err_recover(
  1233. gpointer data,
  1234. gpointer user_data)
  1235. {
  1236. char *line = data;
  1237. script_output_t *so = user_data;
  1238. if (line && so->stream) {
  1239. g_fprintf(so->stream, "%s\n", line);
  1240. }
  1241. }
  1242. void
  1243. run_client_scripts(
  1244. execute_on_t execute_on,
  1245. g_option_t *g_options,
  1246. dle_t *dle,
  1247. FILE *streamout)
  1248. {
  1249. GSList *scriptlist;
  1250. script_t *script;
  1251. GFunc client_script_err = NULL;
  1252. script_output_t so = { streamout, dle };
  1253. for (scriptlist = dle->scriptlist; scriptlist != NULL;
  1254. scriptlist = scriptlist->next) {
  1255. script = (script_t *)scriptlist->data;
  1256. run_client_script(script, execute_on, g_options, dle);
  1257. if (script->result && script->result->output) {
  1258. g_ptr_array_foreach(script->result->output,
  1259. run_client_script_output,
  1260. &so);
  1261. g_ptr_array_free(script->result->output, TRUE);
  1262. script->result->output = NULL;
  1263. }
  1264. if (script->result && script->result->err) {
  1265. switch (execute_on) {
  1266. case EXECUTE_ON_PRE_DLE_AMCHECK:
  1267. case EXECUTE_ON_PRE_HOST_AMCHECK:
  1268. case EXECUTE_ON_POST_DLE_AMCHECK:
  1269. case EXECUTE_ON_POST_HOST_AMCHECK:
  1270. client_script_err = run_client_script_err_amcheck;
  1271. break;
  1272. case EXECUTE_ON_PRE_DLE_ESTIMATE:
  1273. case EXECUTE_ON_PRE_HOST_ESTIMATE:
  1274. case EXECUTE_ON_POST_DLE_ESTIMATE:
  1275. case EXECUTE_ON_POST_HOST_ESTIMATE:
  1276. if (am_has_feature(g_options->features,
  1277. fe_sendsize_rep_warning)) {
  1278. client_script_err = run_client_script_err_estimate;
  1279. }
  1280. break;
  1281. case EXECUTE_ON_PRE_DLE_BACKUP:
  1282. case EXECUTE_ON_PRE_HOST_BACKUP:
  1283. case EXECUTE_ON_POST_DLE_BACKUP:
  1284. case EXECUTE_ON_POST_HOST_BACKUP:
  1285. client_script_err = run_client_script_err_backup;
  1286. break;
  1287. case EXECUTE_ON_PRE_RECOVER:
  1288. case EXECUTE_ON_POST_RECOVER:
  1289. case EXECUTE_ON_PRE_LEVEL_RECOVER:
  1290. case EXECUTE_ON_POST_LEVEL_RECOVER:
  1291. case EXECUTE_ON_INTER_LEVEL_RECOVER:
  1292. client_script_err = run_client_script_err_recover;
  1293. }
  1294. if (client_script_err != NULL) {
  1295. g_ptr_array_foreach(script->result->err,
  1296. client_script_err,
  1297. &so);
  1298. }
  1299. g_ptr_array_free(script->result->err, TRUE);
  1300. script->result->err = NULL;
  1301. }
  1302. }
  1303. }
  1304. void
  1305. run_calcsize(
  1306. char *config,
  1307. char *program,
  1308. char *disk,
  1309. char *dirname,
  1310. GSList *levels,
  1311. char *file_exclude,
  1312. char *file_include)
  1313. {
  1314. char *cmd, *cmdline;
  1315. char *command;
  1316. GPtrArray *argv_ptr = g_ptr_array_new();
  1317. char tmppath[PATH_MAX];
  1318. char number[NUM_STR_SIZE];
  1319. GSList *alevel;
  1320. guint level;
  1321. guint i;
  1322. char *match_expr;
  1323. int pipefd = -1, nullfd = -1;
  1324. pid_t calcpid;
  1325. times_t start_time;
  1326. FILE *dumpout = NULL;
  1327. int dumpsince;
  1328. char *errmsg = NULL;
  1329. char *line = NULL;
  1330. amwait_t wait_status;
  1331. int len;
  1332. char *qdisk;
  1333. amandates_t *amdp;
  1334. char *amandates_file;
  1335. qdisk = quote_string(disk);
  1336. amandates_file = getconf_str(CNF_AMANDATES);
  1337. if(!start_amandates(amandates_file, 0)) {
  1338. char *errstr = strerror(errno);
  1339. char *errmsg = vstrallocf(_("could not open %s: %s"), amandates_file, errstr);
  1340. char *qerrmsg = quote_string(errmsg);
  1341. g_printf(_("ERROR %s\n"), qerrmsg);
  1342. amfree(qdisk);
  1343. amfree(errmsg);
  1344. amfree(qerrmsg);
  1345. return;
  1346. }
  1347. startclock();
  1348. cmd = vstralloc(amlibexecdir, "/", "calcsize", NULL);
  1349. g_ptr_array_add(argv_ptr, stralloc("calcsize"));
  1350. if (config)
  1351. g_ptr_array_add(argv_ptr, stralloc(config));
  1352. else
  1353. g_ptr_array_add(argv_ptr, stralloc("NOCONFIG"));
  1354. g_ptr_array_add(argv_ptr, stralloc(program));
  1355. canonicalize_pathname(disk, tmppath);
  1356. g_ptr_array_add(argv_ptr, stralloc(tmppath));
  1357. canonicalize_pathname(dirname, tmppath);
  1358. g_ptr_array_add(argv_ptr, stralloc(tmppath));
  1359. if (file_exclude) {
  1360. g_ptr_array_add(argv_ptr, stralloc("-X"));
  1361. g_ptr_array_add(argv_ptr, stralloc(file_exclude));
  1362. }
  1363. if (file_include) {
  1364. g_ptr_array_add(argv_ptr, stralloc("-I"));
  1365. g_ptr_array_add(argv_ptr, stralloc(file_include));
  1366. }
  1367. for (alevel = levels; alevel != NULL; alevel = alevel->next) {
  1368. amdp = amandates_lookup(disk);
  1369. level = GPOINTER_TO_INT(alevel->data);
  1370. dbprintf("level: %d\n", level);
  1371. dumpsince = 0;
  1372. for (i=0; i < level; i++) {
  1373. if (dumpsince < amdp->dates[i])
  1374. dumpsince = amdp->dates[i];
  1375. }
  1376. g_snprintf(number, SIZEOF(number), "%d", level);
  1377. g_ptr_array_add(argv_ptr, stralloc(number));
  1378. g_snprintf(number, SIZEOF(number), "%d", dumpsince);
  1379. g_ptr_array_add(argv_ptr, stralloc(number));
  1380. }
  1381. g_ptr_array_add(argv_ptr, NULL);
  1382. command = (char *)g_ptr_array_index(argv_ptr, 0);
  1383. cmdline = stralloc(command);
  1384. for(i = 1; i < argv_ptr->len - 1; i++)
  1385. cmdline = vstrextend(&cmdline, " ",
  1386. (char *)g_ptr_array_index(argv_ptr,i), NULL);
  1387. dbprintf(_("running: \"%s\"\n"), cmdline);
  1388. amfree(cmdline);
  1389. start_time = curclock();
  1390. fflush(stderr); fflush(stdout);
  1391. if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
  1392. errmsg = vstrallocf(_("Cannot access /dev/null : %s"),
  1393. strerror(errno));
  1394. dbprintf("%s\n", errmsg);
  1395. goto common_exit;
  1396. }
  1397. calcpid = pipespawnv(cmd, STDERR_PIPE, 0,
  1398. &nullfd, &nullfd, &pipefd, (char **)argv_ptr->pdata);
  1399. amfree(cmd);
  1400. dumpout = fdopen(pipefd,"r");
  1401. if (!dumpout) {
  1402. error(_("Can't fdopen: %s"), strerror(errno));
  1403. /*NOTREACHED*/
  1404. }
  1405. match_expr = vstralloc(" %d SIZE %lld", NULL);
  1406. len = strlen(qdisk);
  1407. for(; (line = agets(dumpout)) != NULL; free(line)) {
  1408. long long size_ = (long long)0;
  1409. if (line[0] == '\0' || (int)strlen(line) <= len)
  1410. continue;
  1411. /* Don't use sscanf for qdisk because it can have a '%'. */
  1412. if (strncmp(line, qdisk, len) == 0 &&
  1413. sscanf(line+len, match_expr, &level, &size_) == 2) {
  1414. g_printf("%d %lld %d\n", level, size_, 1); /* write to sendsize */
  1415. dbprintf(_("estimate size for %s level %d: %lld KB\n"),
  1416. qdisk, level, size_);
  1417. }
  1418. }
  1419. amfree(match_expr);
  1420. dbprintf(_("waiting for %s %s child (pid=%d)\n"),
  1421. command, qdisk, (int)calcpid);
  1422. waitpid(calcpid, &wait_status, 0);
  1423. if (WIFSIGNALED(wait_status)) {
  1424. errmsg = vstrallocf(_("%s terminated with signal %d: see %s"),
  1425. "calcsize", WTERMSIG(wait_status),
  1426. dbfn());
  1427. } else if (WIFEXITED(wait_status)) {
  1428. if (WEXITSTATUS(wait_status) != 0) {
  1429. errmsg = vstrallocf(_("%s exited with status %d: see %s"),
  1430. "calcsize", WEXITSTATUS(wait_status),
  1431. dbfn());
  1432. } else {
  1433. /* Normal exit */
  1434. }
  1435. } else {
  1436. errmsg = vstrallocf(_("%s got bad exit: see %s"),
  1437. "calcsize", dbfn());
  1438. }
  1439. dbprintf(_("after %s %s wait: child pid=%d status=%d\n"),
  1440. command, qdisk,
  1441. (int)calcpid, WEXITSTATUS(wait_status));
  1442. dbprintf(_(".....\n"));
  1443. dbprintf(_("estimate time for %s: %s\n"),
  1444. qdisk,
  1445. walltime_str(timessub(curclock(), start_time)));
  1446. common_exit:
  1447. if (errmsg && errmsg[0] != '\0') {
  1448. char *qerrmsg = quote_string(errmsg);
  1449. dbprintf(_("errmsg is %s\n"), errmsg);
  1450. g_printf("ERROR %s\n", qerrmsg);
  1451. amfree(qerrmsg);
  1452. }
  1453. amfree(qdisk);
  1454. amfree(errmsg);
  1455. g_ptr_array_free_full(argv_ptr);
  1456. amfree(cmd);
  1457. }
  1458. gboolean
  1459. check_access(
  1460. char * filename,
  1461. int mode)
  1462. {
  1463. char *noun, *adjective;
  1464. char *quoted = quote_string(filename);
  1465. if(mode == F_OK)
  1466. noun = "find", adjective = "exists";
  1467. else if((mode & X_OK) == X_OK)
  1468. noun = "execute", adjective = "executable";
  1469. else if((mode & (W_OK|R_OK)) == (W_OK|R_OK))
  1470. noun = "read/write", adjective = "read/writable";
  1471. else
  1472. noun = "access", adjective = "accessible";
  1473. if(access(filename, mode) == -1) {
  1474. g_printf(_("ERROR [can not %s %s: %s]\n"), noun, quoted, strerror(errno));
  1475. amfree(quoted);
  1476. return FALSE;
  1477. } else {
  1478. g_printf(_("OK %s %s\n"), quoted, adjective);
  1479. }
  1480. amfree(quoted);
  1481. return TRUE;
  1482. }
  1483. gboolean
  1484. check_file(
  1485. char * filename,
  1486. int mode)
  1487. {
  1488. struct stat stat_buf;
  1489. char *quoted;
  1490. if(!stat(filename, &stat_buf)) {
  1491. if(!S_ISREG(stat_buf.st_mode)) {
  1492. quoted = quote_string(filename);
  1493. g_printf(_("ERROR [%s is not a file]\n"), quoted);
  1494. amfree(quoted);
  1495. return FALSE;
  1496. }
  1497. } else {
  1498. int save_errno = errno;
  1499. quoted = quote_string(filename);
  1500. g_printf(_("ERROR [can not stat %s: %s]\n"), quoted,
  1501. strerror(save_errno));
  1502. amfree(quoted);
  1503. return FALSE;
  1504. }
  1505. if (getuid() == geteuid()) {
  1506. return check_access(filename, mode);
  1507. } else {
  1508. quoted = quote_string(filename);
  1509. g_printf("OK %s\n", quoted);
  1510. amfree(quoted);
  1511. }
  1512. return TRUE;
  1513. }
  1514. gboolean
  1515. check_dir(
  1516. char * dirname,
  1517. int mode)
  1518. {
  1519. struct stat stat_buf;
  1520. char *quoted;
  1521. char *dir;
  1522. if(!stat(dirname, &stat_buf)) {
  1523. if(!S_ISDIR(stat_buf.st_mode)) {
  1524. quoted = quote_string(dirname);
  1525. g_printf(_("ERROR [%s is not a directory]\n"), quoted);
  1526. amfree(quoted);
  1527. return FALSE;
  1528. }
  1529. } else {
  1530. int save_errno = errno;
  1531. quoted = quote_string(dirname);
  1532. g_printf(_("ERROR [can not stat %s: %s]\n"), quoted,
  1533. strerror(save_errno));
  1534. amfree(quoted);
  1535. return FALSE;
  1536. }
  1537. if (getuid() == geteuid()) {
  1538. gboolean result;
  1539. dir = stralloc2(dirname, "/.");
  1540. result = check_access(dir, mode);
  1541. amfree(dir);
  1542. return result;
  1543. } else {
  1544. quoted = quote_string(dirname);
  1545. g_printf("OK %s\n", quoted);
  1546. amfree(quoted);
  1547. }
  1548. return TRUE;
  1549. }
  1550. gboolean
  1551. check_suid(
  1552. char * filename)
  1553. {
  1554. #ifndef SINGLE_USERID
  1555. struct stat stat_buf;
  1556. char *quoted = quote_string(filename);
  1557. if(!stat(filename, &stat_buf)) {
  1558. if(stat_buf.st_uid != 0 ) {
  1559. g_printf(_("ERROR [%s is not owned by root]\n"), quoted);
  1560. amfree(quoted);
  1561. return FALSE;
  1562. }
  1563. if((stat_buf.st_mode & S_ISUID) != S_ISUID) {
  1564. g_printf(_("ERROR [%s is not SUID root]\n"), quoted);
  1565. amfree(quoted);
  1566. return FALSE;
  1567. }
  1568. }
  1569. else {
  1570. g_printf(_("ERROR [can not stat %s: %s]\n"), quoted, strerror(errno));
  1571. amfree(quoted);
  1572. return FALSE;
  1573. }
  1574. amfree(quoted);
  1575. #else
  1576. (void)filename; /* Quiet unused parameter warning */
  1577. #endif
  1578. return TRUE;
  1579. }
  1580. /*
  1581. * Returns the value of the first integer in a string.
  1582. */
  1583. double
  1584. the_num(
  1585. char * str,
  1586. int pos)
  1587. {
  1588. char *num;
  1589. int ch;
  1590. double d;
  1591. do {
  1592. ch = *str++;
  1593. while(ch && !isdigit(ch)) ch = *str++;
  1594. if (pos == 1) break;
  1595. pos--;
  1596. while(ch && (isdigit(ch) || ch == '.')) ch = *str++;
  1597. } while (ch);
  1598. num = str - 1;
  1599. while(isdigit(ch) || ch == '.') ch = *str++;
  1600. str[-1] = '\0';
  1601. d = atof(num);
  1602. str[-1] = (char)ch;
  1603. return d;
  1604. }
  1605. char *
  1606. config_errors_to_error_string(
  1607. GSList *errlist)
  1608. {
  1609. char *errmsg;
  1610. gboolean multiple_errors = FALSE;
  1611. if (errlist) {
  1612. errmsg = (char *)errlist->data;
  1613. if (errlist->next)
  1614. multiple_errors = TRUE;
  1615. } else {
  1616. errmsg = _("(no error message)");
  1617. }
  1618. return vstrallocf("ERROR %s%s", errmsg,
  1619. multiple_errors? _(" (additional errors not displayed)"):"");
  1620. }
  1621. void
  1622. add_type_table(
  1623. dmpline_t typ,
  1624. amregex_t **re_table,
  1625. amregex_t *orig_re_table,
  1626. GSList *normal_message,
  1627. GSList *ignore_message,
  1628. GSList *strange_message)
  1629. {
  1630. amregex_t *rp;
  1631. for(rp = orig_re_table; rp->regex != NULL; rp++) {
  1632. if (rp->typ == typ) {
  1633. int found = 0;
  1634. GSList *mes;
  1635. for (mes = normal_message; mes != NULL; mes = mes->next) {
  1636. if (strcmp(rp->regex, (char *)mes->data) == 0)
  1637. found = 1;
  1638. }
  1639. for (mes = ignore_message; mes != NULL; mes = mes->next) {
  1640. if (strcmp(rp->regex, (char *)mes->data) == 0)
  1641. found = 1;
  1642. }
  1643. for (mes = strange_message; mes != NULL; mes = mes->next) {
  1644. if (strcmp(rp->regex, (char *)mes->data) == 0)
  1645. found = 1;
  1646. }
  1647. if (found == 0) {
  1648. (*re_table)->regex = rp->regex;
  1649. (*re_table)->srcline = rp->srcline;
  1650. (*re_table)->scale = rp->scale;
  1651. (*re_table)->field = rp->field;
  1652. (*re_table)->typ = rp->typ;
  1653. (*re_table)++;
  1654. }
  1655. }
  1656. }
  1657. }
  1658. void
  1659. add_list_table(
  1660. dmpline_t typ,
  1661. amregex_t **re_table,
  1662. GSList *message)
  1663. {
  1664. GSList *mes;
  1665. for (mes = message; mes != NULL; mes = mes->next) {
  1666. (*re_table)->regex = (char *)mes->data;
  1667. (*re_table)-

Large files files are truncated, but you can click here to view the full file