PageRenderTime 56ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/amanda/tags/amanda260p2/client-src/sendsize.c

#
C | 2335 lines | 1976 code | 227 blank | 132 comment | 461 complexity | d3ece5f7e918c7bdbdb90dfd64493ed1 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: sendsize.c,v 1.171 2006/08/24 01:57:15 paddy_s Exp $
  28. *
  29. * send estimated backup sizes using dump
  30. */
  31. #include "amanda.h"
  32. #include "pipespawn.h"
  33. #include "amfeatures.h"
  34. #include "amandates.h"
  35. #include "clock.h"
  36. #include "util.h"
  37. #include "getfsent.h"
  38. #include "version.h"
  39. #include "client_util.h"
  40. #include "conffile.h"
  41. #include "amandad.h"
  42. #ifdef SAMBA_CLIENT
  43. #include "findpass.h"
  44. #endif
  45. #define sendsize_debug(i, ...) do { \
  46. if ((i) <= debug_sebdsize) { \
  47. dbprintf(__VA_ARGS__); \
  48. } \
  49. } while (0)
  50. #ifdef HAVE_SETPGID
  51. # define SETPGRP setpgid(getpid(), getpid())
  52. # define SETPGRP_FAILED() do { \
  53. dbprintf(_("setpgid(%ld,%ld) failed: %s\n"), \
  54. (long)getpid(), (long)getpid(), strerror(errno)); \
  55. } while(0)
  56. #else /* () line 0 */
  57. #if defined(SETPGRP_VOID)
  58. # define SETPGRP setpgrp()
  59. # define SETPGRP_FAILED() do { \
  60. dbprintf(_("setpgrp() failed: %s\n"), strerror(errno)); \
  61. } while(0)
  62. #else
  63. # define SETPGRP setpgrp(0, getpid())
  64. # define SETPGRP_FAILED() do { \
  65. dbprintf(_("setpgrp(0,%ld) failed: %s\n"), \
  66. (long)getpid(), strerror(errno)); \
  67. } while(0)
  68. #endif
  69. #endif
  70. typedef struct level_estimates_s {
  71. time_t dumpsince;
  72. int estsize;
  73. int needestimate;
  74. } level_estimate_t;
  75. typedef struct disk_estimates_s {
  76. struct disk_estimates_s *next;
  77. char *amname;
  78. char *qamname;
  79. char *amdevice;
  80. char *qamdevice;
  81. char *dirname;
  82. char *qdirname;
  83. char *program;
  84. char *calcprog;
  85. int program_is_backup_api;
  86. int spindle;
  87. pid_t child;
  88. int done;
  89. option_t *options;
  90. level_estimate_t est[DUMP_LEVELS];
  91. } disk_estimates_t;
  92. disk_estimates_t *est_list;
  93. static am_feature_t *our_features = NULL;
  94. static char *our_feature_string = NULL;
  95. static g_option_t *g_options = NULL;
  96. /* local functions */
  97. int main(int argc, char **argv);
  98. void add_diskest(char *disk, char *amdevice, int level, int spindle,
  99. int program_is_backup_api, char *prog, char *calcprog,
  100. option_t *options);
  101. void calc_estimates(disk_estimates_t *est);
  102. void free_estimates(disk_estimates_t *est);
  103. void dump_calc_estimates(disk_estimates_t *);
  104. void star_calc_estimates(disk_estimates_t *);
  105. void smbtar_calc_estimates(disk_estimates_t *);
  106. void gnutar_calc_estimates(disk_estimates_t *);
  107. void backup_api_calc_estimate(disk_estimates_t *);
  108. void generic_calc_estimates(disk_estimates_t *);
  109. int
  110. main(
  111. int argc,
  112. char ** argv)
  113. {
  114. int level, spindle;
  115. char *prog, *calcprog, *dumpdate;
  116. option_t *options = NULL;
  117. int program_is_backup_api;
  118. disk_estimates_t *est;
  119. disk_estimates_t *est1;
  120. disk_estimates_t *est_prev;
  121. char *line = NULL;
  122. char *s, *fp;
  123. int ch;
  124. char *err_extra = NULL;
  125. int done;
  126. int need_wait;
  127. int dumpsrunning;
  128. char *disk = NULL;
  129. char *qdisk = NULL;
  130. char *qlist = NULL;
  131. char *amdevice = NULL;
  132. char *qamdevice = NULL;
  133. char *amandates_file;
  134. int amandates_read = 0;
  135. (void)argc; /* Quiet unused parameter warning */
  136. (void)argv; /* Quiet unused parameter warning */
  137. /* initialize */
  138. /*
  139. * Configure program for internationalization:
  140. * 1) Only set the message locale for now.
  141. * 2) Set textdomain for all amanda related programs to "amanda"
  142. * We don't want to be forced to support dozens of message catalogs.
  143. */
  144. setlocale(LC_MESSAGES, "C");
  145. textdomain("amanda");
  146. safe_fd(-1, 0);
  147. safe_cd();
  148. set_pname("sendsize");
  149. /* Don't die when child closes pipe */
  150. signal(SIGPIPE, SIG_IGN);
  151. erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG);
  152. dbopen(DBG_SUBDIR_CLIENT);
  153. startclock();
  154. dbprintf(_("version %s\n"), version());
  155. our_features = am_init_feature_set();
  156. our_feature_string = am_feature_to_string(our_features);
  157. config_init(CONFIG_INIT_CLIENT, NULL);
  158. check_running_as(RUNNING_AS_CLIENT_LOGIN);
  159. /* handle all service requests */
  160. for(; (line = agets(stdin)) != NULL; free(line)) {
  161. if (line[0] == '\0')
  162. continue;
  163. if(strncmp_const(line, "OPTIONS ") == 0) {
  164. g_options = parse_g_options(line+8, 1);
  165. if(!g_options->hostname) {
  166. g_options->hostname = alloc(MAX_HOSTNAME_LENGTH+1);
  167. gethostname(g_options->hostname, MAX_HOSTNAME_LENGTH);
  168. g_options->hostname[MAX_HOSTNAME_LENGTH] = '\0';
  169. }
  170. g_printf("OPTIONS ");
  171. if(am_has_feature(g_options->features, fe_rep_options_features)) {
  172. g_printf("features=%s;", our_feature_string);
  173. }
  174. if(am_has_feature(g_options->features, fe_rep_options_maxdumps)) {
  175. g_printf("maxdumps=%d;", g_options->maxdumps);
  176. }
  177. if(am_has_feature(g_options->features, fe_rep_options_hostname)) {
  178. g_printf("hostname=%s;", g_options->hostname);
  179. }
  180. g_printf("\n");
  181. fflush(stdout);
  182. if (g_options->config) {
  183. /* overlay this configuration on the existing (nameless) configuration */
  184. config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY,
  185. g_options->config);
  186. dbrename(config_name, DBG_SUBDIR_CLIENT);
  187. }
  188. continue;
  189. }
  190. if (amandates_read == 0) {
  191. amandates_file = getconf_str(CNF_AMANDATES);
  192. if(!start_amandates(amandates_file, 0))
  193. error("error [opening %s: %s]", amandates_file,
  194. strerror(errno));
  195. amandates_read = 1;
  196. }
  197. s = line;
  198. ch = *s++;
  199. skip_whitespace(s, ch); /* find the program name */
  200. if(ch == '\0') {
  201. err_extra = stralloc(_("no program name"));
  202. goto err; /* no program name */
  203. }
  204. prog = s - 1;
  205. skip_non_whitespace(s, ch);
  206. s[-1] = '\0';
  207. program_is_backup_api=0;
  208. if(strncmp_const(prog, "CALCSIZE") == 0) {
  209. skip_whitespace(s, ch); /* find the program name */
  210. if(ch == '\0') {
  211. err_extra = stralloc(_("no program name"));
  212. goto err;
  213. }
  214. calcprog = s - 1;
  215. skip_non_whitespace(s, ch);
  216. s[-1] = '\0';
  217. if (strcmp(calcprog,"BACKUP") == 0) {
  218. program_is_backup_api=1;
  219. skip_whitespace(s, ch); /* find dumper name */
  220. if (ch == '\0') {
  221. goto err; /* no program */
  222. }
  223. calcprog = s - 1;
  224. skip_non_whitespace(s, ch);
  225. s[-1] = '\0';
  226. }
  227. }
  228. else {
  229. calcprog = NULL;
  230. if (strcmp(prog,"BACKUP") == 0) {
  231. program_is_backup_api=1;
  232. skip_whitespace(s, ch); /* find dumper name */
  233. if (ch == '\0') {
  234. goto err; /* no program */
  235. }
  236. prog = s - 1;
  237. skip_non_whitespace(s, ch);
  238. s[-1] = '\0';
  239. }
  240. }
  241. skip_whitespace(s, ch); /* find the disk name */
  242. if(ch == '\0') {
  243. err_extra = stralloc(_("no disk name"));
  244. goto err; /* no disk name */
  245. }
  246. if (qdisk != NULL)
  247. amfree(qdisk);
  248. if (disk != NULL)
  249. amfree(disk);
  250. fp = s - 1;
  251. skip_quoted_string(s, ch);
  252. s[-1] = '\0'; /* terminate the disk name */
  253. qdisk = stralloc(fp);
  254. disk = unquote_string(qdisk);
  255. skip_whitespace(s, ch); /* find the device or level */
  256. if (ch == '\0') {
  257. err_extra = stralloc(_("bad level"));
  258. goto err;
  259. }
  260. if(!isdigit((int)s[-1])) {
  261. fp = s - 1;
  262. skip_quoted_string(s, ch);
  263. s[-1] = '\0';
  264. qamdevice = stralloc(fp);
  265. amdevice = unquote_string(qamdevice);
  266. skip_whitespace(s, ch); /* find level number */
  267. }
  268. else {
  269. amdevice = stralloc(disk);
  270. qamdevice = stralloc(qdisk);
  271. }
  272. /* find the level number */
  273. if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
  274. err_extra = stralloc(_("bad level"));
  275. goto err; /* bad level */
  276. }
  277. if (level < 0 || level >= DUMP_LEVELS) {
  278. err_extra = stralloc(_("bad level"));
  279. goto err;
  280. }
  281. skip_integer(s, ch);
  282. skip_whitespace(s, ch); /* find the dump date */
  283. if(ch == '\0') {
  284. err_extra = stralloc(_("no dumpdate"));
  285. goto err; /* no dumpdate */
  286. }
  287. dumpdate = s - 1;
  288. skip_non_whitespace(s, ch);
  289. s[-1] = '\0';
  290. (void)dumpdate; /* XXX: Set but not used */
  291. spindle = 0; /* default spindle */
  292. skip_whitespace(s, ch); /* find the spindle */
  293. if(ch != '\0') {
  294. if(sscanf(s - 1, "%d", &spindle) != 1) {
  295. err_extra = stralloc(_("bad spindle"));
  296. goto err; /* bad spindle */
  297. }
  298. skip_integer(s, ch);
  299. skip_whitespace(s, ch); /* find the parameters */
  300. if(ch != '\0') {
  301. if(strncmp_const(s-1, "OPTIONS |;") == 0) {
  302. options = parse_options(s + 8,
  303. disk,
  304. amdevice,
  305. g_options->features,
  306. 0);
  307. }
  308. else {
  309. options = alloc(SIZEOF(option_t));
  310. init_options(options);
  311. while (ch != '\0') {
  312. if(strncmp_const(s-1, "exclude-file=") == 0) {
  313. qlist = unquote_string(s+12);
  314. options->exclude_file =
  315. append_sl(options->exclude_file, qlist);
  316. amfree(qlist);
  317. } else if(strncmp_const(s-1, "exclude-list=") == 0) {
  318. qlist = unquote_string(s+12);
  319. options->exclude_list =
  320. append_sl(options->exclude_list, qlist);
  321. amfree(qlist);
  322. } else if(strncmp_const(s-1, "include-file=") == 0) {
  323. qlist = unquote_string(s+12);
  324. options->include_file =
  325. append_sl(options->include_file, qlist);
  326. amfree(qlist);
  327. } else if(strncmp_const(s-1, "include-list=") == 0) {
  328. qlist = unquote_string(s+12);
  329. options->include_list =
  330. append_sl(options->include_list, qlist);
  331. amfree(qlist);
  332. } else {
  333. err_extra = vstrallocf(_("Invalid parameter (%s)"), s-1);
  334. goto err; /* should have gotten to end */
  335. }
  336. skip_quoted_string(s, ch);
  337. skip_whitespace(s, ch); /* find the inclusion list */
  338. amfree(qlist);
  339. }
  340. }
  341. }
  342. else {
  343. options = alloc(SIZEOF(option_t));
  344. init_options(options);
  345. }
  346. }
  347. else {
  348. options = alloc(SIZEOF(option_t));
  349. init_options(options);
  350. }
  351. /*@ignore@*/
  352. add_diskest(disk, amdevice, level, spindle, program_is_backup_api, prog, calcprog, options);
  353. /*@end@*/
  354. amfree(disk);
  355. amfree(qdisk);
  356. amfree(amdevice);
  357. amfree(qamdevice);
  358. }
  359. if (g_options == NULL) {
  360. printf(_("ERROR [Missing OPTIONS line in sendsize input]\n"));
  361. error(_("Missing OPTIONS line in sendsize input\n"));
  362. /*NOTREACHED*/
  363. }
  364. amfree(line);
  365. finish_amandates();
  366. free_amandates();
  367. dumpsrunning = 0;
  368. need_wait = 0;
  369. done = 0;
  370. while(! done) {
  371. done = 1;
  372. /*
  373. * See if we need to wait for a child before we can do anything
  374. * else in this pass.
  375. */
  376. if(need_wait) {
  377. pid_t child_pid;
  378. amwait_t child_status;
  379. need_wait = 0;
  380. dbprintf(_("waiting for any estimate child: %d running\n"),
  381. dumpsrunning);
  382. child_pid = wait(&child_status);
  383. if(child_pid == -1) {
  384. error(_("wait failed: %s"), strerror(errno));
  385. /*NOTREACHED*/
  386. }
  387. if (!WIFEXITED(child_status) || WEXITSTATUS(child_status) != 0) {
  388. char *child_name = vstrallocf(_("child %ld"), (long)child_pid);
  389. char *child_status_str = str_exit_status(child_name, child_status);
  390. dbprintf("%s\n", child_status_str);
  391. amfree(child_status_str);
  392. amfree(child_name);
  393. }
  394. /*
  395. * Find the child and mark it done.
  396. */
  397. for(est = est_list; est != NULL; est = est->next) {
  398. if(est->child == child_pid) {
  399. break;
  400. }
  401. }
  402. if(est == NULL) {
  403. dbprintf(_("unexpected child %ld\n"), (long)child_pid);
  404. } else {
  405. est->done = 1;
  406. est->child = 0;
  407. dumpsrunning--;
  408. }
  409. }
  410. /*
  411. * If we are already running the maximum number of children
  412. * go back and wait until one of them finishes.
  413. */
  414. if(dumpsrunning >= g_options->maxdumps) {
  415. done = 0;
  416. need_wait = 1;
  417. continue; /* have to wait first */
  418. }
  419. /*
  420. * Find a new child to start.
  421. */
  422. for(est = est_list; est != NULL; est = est->next) {
  423. if(est->done == 0) {
  424. done = 0; /* more to do */
  425. }
  426. if(est->child != 0 || est->done) {
  427. continue; /* child is running or done */
  428. }
  429. /*
  430. * Make sure there is no spindle conflict.
  431. */
  432. if(est->spindle != -1) {
  433. for(est1 = est_list; est1 != NULL; est1 = est1->next) {
  434. if(est1->child == 0 || est == est1 || est1->done) {
  435. /*
  436. * Ignore anything not yet started, ourself,
  437. * and anything completed.
  438. */
  439. continue;
  440. }
  441. if(est1->spindle == est->spindle) {
  442. break; /* oops -- they match */
  443. }
  444. }
  445. if(est1 != NULL) {
  446. continue; /* spindle conflict */
  447. }
  448. }
  449. break; /* start this estimate */
  450. }
  451. if(est == NULL) {
  452. if(dumpsrunning > 0) {
  453. need_wait = 1; /* nothing to do but wait */
  454. }
  455. } else {
  456. done = 0;
  457. if((est->child = fork()) == 0) {
  458. calc_estimates(est); /* child does the estimate */
  459. exit(0);
  460. } else if(est->child == -1) {
  461. error(_("calc_estimates fork failed: %s"), strerror(errno));
  462. /*NOTREACHED*/
  463. }
  464. dumpsrunning++; /* parent */
  465. }
  466. }
  467. est_prev = NULL;
  468. for(est = est_list; est != NULL; est = est->next) {
  469. free_estimates(est);
  470. amfree(est_prev);
  471. est_prev = est;
  472. }
  473. amfree(est_prev);
  474. amfree(our_feature_string);
  475. am_release_feature_set(our_features);
  476. our_features = NULL;
  477. free_g_options(g_options);
  478. dbclose();
  479. return 0;
  480. err:
  481. g_printf(_("FORMAT ERROR IN REQUEST PACKET\n"));
  482. if (err_extra) {
  483. dbprintf(_("REQ packet is bogus: %s\n"), err_extra);
  484. amfree(err_extra);
  485. } else {
  486. dbprintf(_("REQ packet is bogus\n"));
  487. }
  488. dbclose();
  489. return 1;
  490. }
  491. void
  492. add_diskest(
  493. char * disk,
  494. char * amdevice,
  495. int level,
  496. int spindle,
  497. int program_is_backup_api,
  498. char * prog,
  499. char * calcprog,
  500. option_t * options)
  501. {
  502. disk_estimates_t *newp, *curp;
  503. amandates_t *amdp;
  504. int dumplev, estlev;
  505. time_t dumpdate;
  506. if (level < 0)
  507. level = 0;
  508. if (level >= DUMP_LEVELS)
  509. level = DUMP_LEVELS - 1;
  510. for(curp = est_list; curp != NULL; curp = curp->next) {
  511. if(strcmp(curp->amname, disk) == 0) {
  512. /* already have disk info, just note the level request */
  513. curp->est[level].needestimate = 1;
  514. if(options) {
  515. free_sl(options->exclude_file);
  516. free_sl(options->exclude_list);
  517. free_sl(options->include_file);
  518. free_sl(options->include_list);
  519. amfree(options->auth);
  520. amfree(options->str);
  521. amfree(options);
  522. }
  523. return;
  524. }
  525. }
  526. newp = (disk_estimates_t *) alloc(SIZEOF(disk_estimates_t));
  527. memset(newp, 0, SIZEOF(*newp));
  528. newp->next = est_list;
  529. est_list = newp;
  530. newp->amname = stralloc(disk);
  531. newp->qamname = quote_string(disk);
  532. newp->amdevice = stralloc(amdevice);
  533. newp->qamdevice = quote_string(amdevice);
  534. newp->dirname = amname_to_dirname(newp->amdevice);
  535. newp->qdirname = quote_string(newp->dirname);
  536. newp->program = stralloc(prog);
  537. if(calcprog != NULL)
  538. newp->calcprog = stralloc(calcprog);
  539. else
  540. newp->calcprog = NULL;
  541. newp->program_is_backup_api = program_is_backup_api;
  542. newp->spindle = spindle;
  543. newp->est[level].needestimate = 1;
  544. newp->options = options;
  545. /* fill in dump-since dates */
  546. amdp = amandates_lookup(newp->amname);
  547. newp->est[0].dumpsince = EPOCH;
  548. for(dumplev = 0; dumplev < DUMP_LEVELS; dumplev++) {
  549. dumpdate = amdp->dates[dumplev];
  550. for(estlev = dumplev+1; estlev < DUMP_LEVELS; estlev++) {
  551. if(dumpdate > newp->est[estlev].dumpsince)
  552. newp->est[estlev].dumpsince = dumpdate;
  553. }
  554. }
  555. }
  556. void
  557. free_estimates(
  558. disk_estimates_t * est)
  559. {
  560. amfree(est->amname);
  561. amfree(est->qamname);
  562. amfree(est->amdevice);
  563. amfree(est->qamdevice);
  564. amfree(est->dirname);
  565. amfree(est->qdirname);
  566. amfree(est->program);
  567. if(est->options) {
  568. free_sl(est->options->exclude_file);
  569. free_sl(est->options->exclude_list);
  570. free_sl(est->options->include_file);
  571. free_sl(est->options->include_list);
  572. amfree(est->options->str);
  573. amfree(est->options->auth);
  574. amfree(est->options);
  575. }
  576. }
  577. /*
  578. * ------------------------------------------------------------------------
  579. *
  580. */
  581. void
  582. calc_estimates(
  583. disk_estimates_t * est)
  584. {
  585. dbprintf(_("calculating for amname %s, dirname %s, spindle %d\n"),
  586. est->qamname, est->qdirname, est->spindle);
  587. if(est->program_is_backup_api == 1)
  588. backup_api_calc_estimate(est);
  589. else
  590. #ifndef USE_GENERIC_CALCSIZE
  591. if(strcmp(est->program, "DUMP") == 0)
  592. dump_calc_estimates(est);
  593. else
  594. #endif
  595. #ifdef SAMBA_CLIENT
  596. if (strcmp(est->program, "GNUTAR") == 0 &&
  597. est->amdevice[0] == '/' && est->amdevice[1] == '/')
  598. smbtar_calc_estimates(est);
  599. else
  600. #endif
  601. #ifdef GNUTAR
  602. if (strcmp(est->program, "GNUTAR") == 0)
  603. gnutar_calc_estimates(est);
  604. else
  605. #endif
  606. #ifdef SAMBA_CLIENT
  607. if (est->amdevice[0] == '/' && est->amdevice[1] == '/')
  608. dbprintf(_("Can't use CALCSIZE for samba estimate: %s %s\n"),
  609. est->qamname, est->qdirname);
  610. else
  611. #endif
  612. generic_calc_estimates(est);
  613. dbprintf(_("done with amname %s dirname %s spindle %d\n"),
  614. est->qamname, est->qdirname, est->spindle);
  615. }
  616. /*
  617. * ------------------------------------------------------------------------
  618. *
  619. */
  620. /* local functions */
  621. off_t getsize_dump(char *disk, char *amdevice, int level, option_t *options,
  622. char **errmsg);
  623. off_t getsize_smbtar(char *disk, char *amdevice, int level, option_t *options,
  624. char **errmsg);
  625. off_t getsize_gnutar(char *disk, char *amdevice, int level,
  626. option_t *options, time_t dumpsince, char **errmsg);
  627. off_t getsize_backup_api(char *program, char *disk, char *amdevice, int level,
  628. option_t *options, time_t dumpsince, char **errmsg);
  629. off_t handle_dumpline(char *str);
  630. double first_num(char *str);
  631. void
  632. backup_api_calc_estimate(
  633. disk_estimates_t * est)
  634. {
  635. int level;
  636. off_t size;
  637. char *errmsg = NULL, *qerrmsg;
  638. for(level = 0; level < DUMP_LEVELS; level++) {
  639. if (est->est[level].needestimate) {
  640. dbprintf(_("getting size via application API for %s %s level %d\n"),
  641. est->qamname, est->qamdevice, level);
  642. size = getsize_backup_api(est->program, est->amname, est->amdevice,
  643. level, est->options,
  644. est->est[level].dumpsince, &errmsg);
  645. amflock(1, "size");
  646. g_printf(_("%s %d SIZE %lld\n"), est->qamname, level,
  647. (long long)size);
  648. if (errmsg && errmsg[0] != '\0') {
  649. if(am_has_feature(g_options->features,
  650. fe_rep_sendsize_quoted_error)) {
  651. qerrmsg = quote_string(errmsg);
  652. dbprintf(_("errmsg is %s\n"), errmsg);
  653. g_printf(_("%s %d ERROR %s\n"),
  654. est->qamname, level, qerrmsg);
  655. amfree(qerrmsg);
  656. }
  657. }
  658. amfree(errmsg);
  659. fflush(stdout);
  660. amfunlock(1, "size");
  661. }
  662. }
  663. }
  664. void
  665. generic_calc_estimates(
  666. disk_estimates_t * est)
  667. {
  668. int pipefd = -1, nullfd = -1;
  669. char *cmd;
  670. char *cmdline;
  671. char *my_argv[DUMP_LEVELS*2+22];
  672. char number[NUM_STR_SIZE];
  673. int i, level, my_argc;
  674. pid_t calcpid;
  675. int nb_exclude = 0;
  676. int nb_include = 0;
  677. char *file_exclude = NULL;
  678. char *file_include = NULL;
  679. times_t start_time;
  680. FILE *dumpout = NULL;
  681. off_t size = (off_t)1;
  682. char *line = NULL;
  683. char *match_expr;
  684. amwait_t wait_status;
  685. char *errmsg = NULL, *qerrmsg;
  686. char tmppath[PATH_MAX];
  687. cmd = vstralloc(amlibexecdir, "/", "calcsize", versionsuffix(), NULL);
  688. my_argc = 0;
  689. my_argv[my_argc++] = stralloc("calcsize");
  690. if (g_options->config)
  691. my_argv[my_argc++] = stralloc(g_options->config);
  692. else
  693. my_argv[my_argc++] = stralloc("NOCONFIG");
  694. my_argv[my_argc++] = stralloc(est->calcprog);
  695. my_argv[my_argc++] = stralloc(est->amname);
  696. canonicalize_pathname(est->dirname, tmppath);
  697. my_argv[my_argc++] = stralloc(tmppath);
  698. if(est->options->exclude_file)
  699. nb_exclude += est->options->exclude_file->nb_element;
  700. if(est->options->exclude_list)
  701. nb_exclude += est->options->exclude_list->nb_element;
  702. if(est->options->include_file)
  703. nb_include += est->options->include_file->nb_element;
  704. if(est->options->include_list)
  705. nb_include += est->options->include_list->nb_element;
  706. if(nb_exclude > 0)
  707. file_exclude = build_exclude(est->amname,
  708. est->amdevice, est->options, 0);
  709. if(nb_include > 0)
  710. file_include = build_include(est->amname,
  711. est->amdevice, est->options, 0);
  712. if(file_exclude) {
  713. my_argv[my_argc++] = stralloc("-X");
  714. my_argv[my_argc++] = file_exclude;
  715. }
  716. if(file_include) {
  717. my_argv[my_argc++] = stralloc("-I");
  718. my_argv[my_argc++] = file_include;
  719. }
  720. start_time = curclock();
  721. cmdline = stralloc(my_argv[0]);
  722. for(i = 1; i < my_argc; i++)
  723. cmdline = vstrextend(&cmdline, " ", my_argv[i], NULL);
  724. dbprintf(_("running: \"%s\"\n"), cmdline);
  725. amfree(cmdline);
  726. for(level = 0; level < DUMP_LEVELS; level++) {
  727. if(est->est[level].needestimate) {
  728. g_snprintf(number, SIZEOF(number), "%d", level);
  729. my_argv[my_argc++] = stralloc(number);
  730. dbprintf(" %s", number);
  731. g_snprintf(number, SIZEOF(number),
  732. "%ld", (long)est->est[level].dumpsince);
  733. my_argv[my_argc++] = stralloc(number);
  734. dbprintf(" %s", number);
  735. }
  736. }
  737. my_argv[my_argc] = NULL;
  738. dbprintf("\n");
  739. fflush(stderr); fflush(stdout);
  740. if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
  741. errmsg = vstrallocf(_("Cannot access /dev/null : %s"),
  742. strerror(errno));
  743. dbprintf("%s\n", errmsg);
  744. goto common_exit;
  745. }
  746. calcpid = pipespawnv(cmd, STDERR_PIPE, &nullfd, &nullfd, &pipefd, my_argv);
  747. amfree(cmd);
  748. dumpout = fdopen(pipefd,"r");
  749. if (!dumpout) {
  750. error(_("Can't fdopen: %s"), strerror(errno));
  751. /*NOTREACHED*/
  752. }
  753. match_expr = vstralloc(est->qamname," %d SIZE %lld", NULL);
  754. for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) {
  755. long long size_ = (long long)0;
  756. if (line[0] == '\0')
  757. continue;
  758. if(sscanf(line, match_expr, &level, &size_) == 2) {
  759. g_printf("%s\n", line); /* write to amandad */
  760. dbprintf(_("estimate size for %s level %d: %lld KB\n"),
  761. est->qamname,
  762. level,
  763. size_);
  764. }
  765. size = (off_t)size_;
  766. }
  767. amfree(match_expr);
  768. dbprintf(_("waiting for %s %s child (pid=%d)\n"),
  769. my_argv[0], est->qamdevice, (int)calcpid);
  770. waitpid(calcpid, &wait_status, 0);
  771. if (WIFSIGNALED(wait_status)) {
  772. errmsg = vstrallocf(_("%s terminated with signal %d: see %s"),
  773. "calcsize", WTERMSIG(wait_status),
  774. dbfn());
  775. } else if (WIFEXITED(wait_status)) {
  776. if (WEXITSTATUS(wait_status) != 0) {
  777. errmsg = vstrallocf(_("%s exited with status %d: see %s"),
  778. "calcsize", WEXITSTATUS(wait_status),
  779. dbfn());
  780. } else {
  781. /* Normal exit */
  782. }
  783. } else {
  784. errmsg = vstrallocf(_("%s got bad exit: see %s"),
  785. "calcsize", dbfn());
  786. }
  787. dbprintf(_("after %s %s wait: child pid=%d status=%d\n"),
  788. my_argv[0], est->qamdevice,
  789. (int)calcpid, WEXITSTATUS(wait_status));
  790. dbprintf(_(".....\n"));
  791. dbprintf(_("estimate time for %s: %s\n"),
  792. est->qamname,
  793. walltime_str(timessub(curclock(), start_time)));
  794. common_exit:
  795. if (errmsg && errmsg[0] != '\0') {
  796. if(am_has_feature(g_options->features, fe_rep_sendsize_quoted_error)) {
  797. qerrmsg = quote_string(errmsg);
  798. dbprintf(_("errmsg is %s\n"), errmsg);
  799. g_printf("%s %d ERROR %s\n",
  800. est->qamname, 0, qerrmsg);
  801. amfree(qerrmsg);
  802. }
  803. }
  804. amfree(errmsg);
  805. for(i = 0; i < my_argc; i++) {
  806. amfree(my_argv[i]);
  807. }
  808. amfree(cmd);
  809. }
  810. void
  811. dump_calc_estimates(
  812. disk_estimates_t * est)
  813. {
  814. int level;
  815. off_t size;
  816. char *errmsg=NULL, *qerrmsg;
  817. for(level = 0; level < DUMP_LEVELS; level++) {
  818. if(est->est[level].needestimate) {
  819. dbprintf(_("getting size via dump for %s level %d\n"),
  820. est->qamname, level);
  821. size = getsize_dump(est->amname, est->amdevice,
  822. level, est->options, &errmsg);
  823. amflock(1, "size");
  824. g_printf(_("%s %d SIZE %lld\n"),
  825. est->qamname, level, (long long)size);
  826. if (errmsg && errmsg[0] != '\0') {
  827. if(am_has_feature(g_options->features,
  828. fe_rep_sendsize_quoted_error)) {
  829. qerrmsg = quote_string(errmsg);
  830. dbprintf(_("errmsg is %s\n"), errmsg);
  831. g_printf("%s %d ERROR %s\n",
  832. est->qamname, level, qerrmsg);
  833. amfree(qerrmsg);
  834. }
  835. }
  836. amfree(errmsg);
  837. fflush(stdout);
  838. amfunlock(1, "size");
  839. }
  840. }
  841. }
  842. #ifdef SAMBA_CLIENT
  843. void
  844. smbtar_calc_estimates(
  845. disk_estimates_t * est)
  846. {
  847. int level;
  848. off_t size;
  849. char *errmsg = NULL, *qerrmsg;
  850. for(level = 0; level < DUMP_LEVELS; level++) {
  851. if(est->est[level].needestimate) {
  852. dbprintf(_("getting size via smbclient for %s level %d\n"),
  853. est->qamname, level);
  854. size = getsize_smbtar(est->amname, est->amdevice, level,
  855. est->options, &errmsg);
  856. amflock(1, "size");
  857. g_printf(_("%s %d SIZE %lld\n"),
  858. est->qamname, level, (long long)size);
  859. if (errmsg && errmsg[0] != '\0') {
  860. if(am_has_feature(g_options->features,
  861. fe_rep_sendsize_quoted_error)) {
  862. qerrmsg = quote_string(errmsg);
  863. dbprintf(_("errmsg is %s\n"), errmsg);
  864. g_printf("%s %d ERROR %s\n",
  865. est->qamname, level, qerrmsg);
  866. amfree(qerrmsg);
  867. }
  868. }
  869. amfree(errmsg);
  870. fflush(stdout);
  871. amfunlock(1, "size");
  872. }
  873. }
  874. }
  875. #endif
  876. #ifdef GNUTAR
  877. void
  878. gnutar_calc_estimates(
  879. disk_estimates_t * est)
  880. {
  881. int level;
  882. off_t size;
  883. char *errmsg = NULL, *qerrmsg;
  884. for(level = 0; level < DUMP_LEVELS; level++) {
  885. if (est->est[level].needestimate) {
  886. dbprintf(_("getting size via gnutar for %s level %d\n"),
  887. est->qamname, level);
  888. size = getsize_gnutar(est->amname, est->amdevice, level,
  889. est->options, est->est[level].dumpsince,
  890. &errmsg);
  891. amflock(1, "size");
  892. g_printf(_("%s %d SIZE %lld\n"),
  893. est->qamname, level, (long long)size);
  894. if (errmsg && errmsg[0] != '\0') {
  895. if(am_has_feature(g_options->features,
  896. fe_rep_sendsize_quoted_error)) {
  897. qerrmsg = quote_string(errmsg);
  898. dbprintf(_("errmsg is %s\n"), errmsg);
  899. g_printf(_("%s %d ERROR %s\n"),
  900. est->qamname, level, qerrmsg);
  901. amfree(qerrmsg);
  902. }
  903. }
  904. amfree(errmsg);
  905. fflush(stdout);
  906. amfunlock(1, "size");
  907. }
  908. }
  909. }
  910. #endif
  911. typedef struct regex_s {
  912. char *regex;
  913. int scale;
  914. } regex_scale_t;
  915. /*@ignore@*/
  916. regex_scale_t re_size[] = {
  917. #ifdef DUMP
  918. {" DUMP: estimated -*[0-9][0-9]* tape blocks", 1024},
  919. {" DUMP: [Ee]stimated [0-9][0-9]* blocks", 512},
  920. {" DUMP: [Ee]stimated [0-9][0-9]* bytes", 1}, /* Ultrix 4.4 */
  921. {" UFSDUMP: estimated [0-9][0-9]* blocks", 512}, /* NEC EWS-UX */
  922. {"dump: Estimate: [0-9][0-9]* tape blocks", 1024}, /* OSF/1 */
  923. {"backup: There are an estimated [0-9][0-9]* tape blocks.",1024}, /* AIX */
  924. {"backup: estimated [0-9][0-9]* 1k blocks", 1024}, /* AIX */
  925. {"backup: estimated [0-9][0-9]* tape blocks", 1024}, /* AIX */
  926. {"backup: [0-9][0-9]* tape blocks on [0-9][0-9]* tape(s)",1024}, /* AIX */
  927. {"backup: [0-9][0-9]* 1k blocks on [0-9][0-9]* volume(s)",1024}, /* AIX */
  928. {"dump: Estimate: [0-9][0-9]* blocks being output to pipe",1024},
  929. /* DU 4.0 dump */
  930. {"dump: Dumping [0-9][0-9]* bytes, ", 1}, /* DU 4.0 vdump */
  931. {"DUMP: estimated [0-9][0-9]* KB output", 1024}, /* HPUX */
  932. {"DUMP: estimated [0-9][0-9]* KB\\.", 1024}, /* NetApp */
  933. {" UFSDUMP: estimated [0-9][0-9]* blocks", 512}, /* Sinix */
  934. #ifdef HAVE_DUMP_ESTIMATE
  935. {"[0-9][0-9]* blocks, [0-9][0-9]*.[0-9][0-9]* volumes", 1024},
  936. /* DU 3.2g dump -E */
  937. {"^[0-9][0-9]* blocks$", 1024}, /* DU 4.0 dump -E */
  938. {"^[0-9][0-9]*$", 1}, /* Solaris ufsdump -S */
  939. #endif
  940. #endif
  941. #ifdef VDUMP
  942. {"vdump: Dumping [0-9][0-9]* bytes, ", 1}, /* OSF/1 vdump */
  943. #endif
  944. #ifdef VXDUMP
  945. {"vxdump: estimated [0-9][0-9]* blocks", 512}, /* HPUX's vxdump */
  946. {" VXDUMP: estimated [0-9][0-9]* blocks", 512}, /* Sinix */
  947. #endif
  948. #ifdef XFSDUMP
  949. {"xfsdump: estimated dump size: [0-9][0-9]* bytes", 1}, /* Irix 6.2 xfs */
  950. #endif
  951. #ifdef GNUTAR
  952. {"Total bytes written: [0-9][0-9]*", 1}, /* Gnutar client */
  953. #endif
  954. #ifdef SAMBA_CLIENT
  955. #if SAMBA_VERSION >= 2
  956. #define SAMBA_DEBUG_LEVEL "0"
  957. {"Total number of bytes: [0-9][0-9]*", 1}, /* Samba du */
  958. #else
  959. #define SAMBA_DEBUG_LEVEL "3"
  960. {"Total bytes listed: [0-9][0-9]*", 1}, /* Samba dir */
  961. #endif
  962. #endif
  963. { NULL, 0 }
  964. };
  965. /*@end@*/
  966. off_t
  967. getsize_dump(
  968. char *disk,
  969. char *amdevice,
  970. int level,
  971. option_t *options G_GNUC_UNUSED,
  972. char **errmsg)
  973. {
  974. int pipefd[2], nullfd, stdoutfd, killctl[2];
  975. pid_t dumppid;
  976. off_t size;
  977. FILE *dumpout;
  978. char *dumpkeys = NULL;
  979. char *device = NULL;
  980. char *fstype = NULL;
  981. char *cmd = NULL;
  982. char *name = NULL;
  983. char *line = NULL;
  984. char *rundump_cmd = NULL;
  985. char level_str[NUM_STR_SIZE];
  986. int s;
  987. times_t start_time;
  988. char *qdisk = quote_string(disk);
  989. char *qdevice;
  990. char *config;
  991. amwait_t wait_status;
  992. #if defined(DUMP) || defined(VDUMP) || defined(VXDUMP) || defined(XFSDUMP)
  993. int is_rundump = 1;
  994. #endif
  995. g_snprintf(level_str, SIZEOF(level_str), "%d", level);
  996. device = amname_to_devname(amdevice);
  997. qdevice = quote_string(device);
  998. fstype = amname_to_fstype(amdevice);
  999. dbprintf(_("calculating for device %s with %s\n"),
  1000. qdevice, fstype);
  1001. cmd = vstralloc(amlibexecdir, "/rundump", versionsuffix(), NULL);
  1002. rundump_cmd = stralloc(cmd);
  1003. if (g_options->config)
  1004. config = g_options->config;
  1005. else
  1006. config = "NOCONFIG";
  1007. if ((stdoutfd = nullfd = open("/dev/null", O_RDWR)) == -1) {
  1008. *errmsg = vstrallocf(_("getsize_dump could not open /dev/null: %s"),
  1009. strerror(errno));
  1010. dbprintf("%s\n", *errmsg);
  1011. amfree(cmd);
  1012. amfree(rundump_cmd);
  1013. amfree(fstype);
  1014. amfree(device);
  1015. amfree(qdevice);
  1016. amfree(qdisk);
  1017. return(-1);
  1018. }
  1019. pipefd[0] = pipefd[1] = killctl[0] = killctl[1] = -1;
  1020. if (pipe(pipefd) < 0) {
  1021. *errmsg = vstrallocf(_("getsize_dump could create data pipes: %s"),
  1022. strerror(errno));
  1023. dbprintf("%s\n", *errmsg);
  1024. amfree(cmd);
  1025. amfree(rundump_cmd);
  1026. amfree(fstype);
  1027. amfree(device);
  1028. amfree(qdevice);
  1029. amfree(qdisk);
  1030. return(-1);
  1031. }
  1032. #ifdef XFSDUMP /* { */
  1033. #ifdef DUMP /* { */
  1034. if (strcmp(fstype, "xfs") == 0)
  1035. #else /* } { */
  1036. if (1)
  1037. #endif /* } */
  1038. {
  1039. name = stralloc(" (xfsdump)");
  1040. dbprintf(_("running \"%s%s -F -J -l %s - %s\"\n"),
  1041. cmd, name, level_str, qdevice);
  1042. }
  1043. else
  1044. #endif /* } */
  1045. #ifdef VXDUMP /* { */
  1046. #ifdef DUMP /* { */
  1047. if (strcmp(fstype, "vxfs") == 0)
  1048. #else /* } { */
  1049. if (1)
  1050. #endif /* } */
  1051. {
  1052. #ifdef USE_RUNDUMP
  1053. name = stralloc(" (vxdump)");
  1054. #else
  1055. name = stralloc("");
  1056. cmd = newstralloc(cmd, VXDUMP);
  1057. config = skip_argument;
  1058. is_rundump = 0;
  1059. #endif
  1060. dumpkeys = vstralloc(level_str, "s", "f", NULL);
  1061. dbprintf(_("running \"%s%s %s 1048576 - %s\"\n"),
  1062. cmd, name, dumpkeys, qdevice);
  1063. }
  1064. else
  1065. #endif /* } */
  1066. #ifdef VDUMP /* { */
  1067. #ifdef DUMP /* { */
  1068. if (strcmp(fstype, "advfs") == 0)
  1069. #else /* } { */
  1070. if (1)
  1071. #endif /* } */
  1072. {
  1073. name = stralloc(" (vdump)");
  1074. amfree(device);
  1075. amfree(qdevice);
  1076. device = amname_to_dirname(amdevice);
  1077. qdevice = quote_string(device);
  1078. dumpkeys = vstralloc(level_str, "b", "f", NULL);
  1079. dbprintf(_("running \"%s%s %s 60 - %s\"\n"),
  1080. cmd, name, dumpkeys, qdevice);
  1081. }
  1082. else
  1083. #endif /* } */
  1084. #ifdef DUMP /* { */
  1085. if (1) {
  1086. # ifdef USE_RUNDUMP /* { */
  1087. # ifdef AIX_BACKUP /* { */
  1088. name = stralloc(" (backup)");
  1089. # else /* } { */
  1090. name = vstralloc(" (", DUMP, ")", NULL);
  1091. # endif /* } */
  1092. # else /* } { */
  1093. name = stralloc("");
  1094. cmd = newstralloc(cmd, DUMP);
  1095. config = skip_argument;
  1096. is_rundump = 0;
  1097. # endif /* } */
  1098. # ifdef AIX_BACKUP /* { */
  1099. dumpkeys = vstralloc("-", level_str, "f", NULL);
  1100. dbprintf(_("running \"%s%s %s - %s\"\n"),
  1101. cmd, name, dumpkeys, qdevice);
  1102. # else /* } { */
  1103. # ifdef HAVE_DUMP_ESTIMATE
  1104. # define PARAM_DUMP_ESTIMATE HAVE_DUMP_ESTIMATE
  1105. # else
  1106. # define PARAM_DUMP_ESTIMATE ""
  1107. # endif
  1108. # ifdef HAVE_HONOR_NODUMP
  1109. # define PARAM_HONOR_NODUMP "h"
  1110. # else
  1111. # define PARAM_HONOR_NODUMP ""
  1112. # endif
  1113. dumpkeys = vstralloc(level_str,
  1114. PARAM_DUMP_ESTIMATE,
  1115. PARAM_HONOR_NODUMP,
  1116. "s", "f", NULL);
  1117. # ifdef HAVE_DUMP_ESTIMATE
  1118. stdoutfd = pipefd[1];
  1119. # endif
  1120. # ifdef HAVE_HONOR_NODUMP /* { */
  1121. dbprintf(_("running \"%s%s %s 0 1048576 - %s\"\n"),
  1122. cmd, name, dumpkeys, qdevice);
  1123. # else /* } { */
  1124. dbprintf(_("running \"%s%s %s 1048576 - %s\"\n"),
  1125. cmd, name, dumpkeys, qdevice);
  1126. # endif /* } */
  1127. # endif /* } */
  1128. }
  1129. else
  1130. #endif /* } */
  1131. {
  1132. error(_("no dump program available"));
  1133. /*NOTREACHED*/
  1134. }
  1135. if (pipe(killctl) < 0) {
  1136. dbprintf(_("Could not create pipe: %s\n"), strerror(errno));
  1137. /* Message will be printed later... */
  1138. killctl[0] = killctl[1] = -1;
  1139. }
  1140. start_time = curclock();
  1141. switch(dumppid = fork()) {
  1142. case -1:
  1143. *errmsg = vstrallocf(_("cannot fork for killpgrp: %s"),
  1144. strerror(errno));
  1145. dbprintf("%s\n", *errmsg);
  1146. amfree(dumpkeys);
  1147. amfree(cmd);
  1148. amfree(rundump_cmd);
  1149. amfree(device);
  1150. amfree(qdevice);
  1151. amfree(qdisk);
  1152. amfree(name);
  1153. amfree(fstype);
  1154. return -1;
  1155. default:
  1156. break;
  1157. case 0: /* child process */
  1158. if(SETPGRP == -1)
  1159. SETPGRP_FAILED();
  1160. else if (killctl[0] == -1 || killctl[1] == -1)
  1161. dbprintf(_("Trying without killpgrp\n"));
  1162. else {
  1163. switch(fork()) {
  1164. case -1:
  1165. dbprintf(_("fork failed, trying without killpgrp\n"));
  1166. break;
  1167. default:
  1168. {
  1169. char *config;
  1170. char *killpgrp_cmd = vstralloc(amlibexecdir, "/killpgrp",
  1171. versionsuffix(), NULL);
  1172. dbprintf(_("running %s\n"), killpgrp_cmd);
  1173. dup2(killctl[0], 0);
  1174. dup2(nullfd, 1);
  1175. dup2(nullfd, 2);
  1176. close(pipefd[0]);
  1177. close(pipefd[1]);
  1178. close(killctl[1]);
  1179. close(nullfd);
  1180. if (g_options->config)
  1181. config = g_options->config;
  1182. else
  1183. config = "NOCONFIG";
  1184. safe_fd(-1, 0);
  1185. execle(killpgrp_cmd, killpgrp_cmd, config, (char *)0,
  1186. safe_env());
  1187. dbprintf(_("cannot execute %s: %s\n"),
  1188. killpgrp_cmd, strerror(errno));
  1189. exit(-1);
  1190. }
  1191. case 0: /* child process */
  1192. break;
  1193. }
  1194. }
  1195. dup2(nullfd, 0);
  1196. dup2(stdoutfd, 1);
  1197. dup2(pipefd[1], 2);
  1198. aclose(pipefd[0]);
  1199. if (killctl[0] != -1)
  1200. aclose(killctl[0]);
  1201. if (killctl[1] != -1)
  1202. aclose(killctl[1]);
  1203. safe_fd(-1, 0);
  1204. #ifdef XFSDUMP
  1205. #ifdef DUMP
  1206. if (strcmp(fstype, "xfs") == 0)
  1207. #else
  1208. if (1)
  1209. #endif
  1210. if (is_rundump)
  1211. execle(cmd, "rundump", config, "xfsdump", "-F", "-J", "-l",
  1212. level_str, "-", device, (char *)0, safe_env());
  1213. else
  1214. execle(cmd, "xfsdump", "-F", "-J", "-l",
  1215. level_str, "-", device, (char *)0, safe_env());
  1216. else
  1217. #endif
  1218. #ifdef VXDUMP
  1219. #ifdef DUMP
  1220. if (strcmp(fstype, "vxfs") == 0)
  1221. #else
  1222. if (1)
  1223. #endif
  1224. if (is_rundump)
  1225. execle(cmd, "rundump", config, "vxdump", dumpkeys, "1048576",
  1226. "-", device, (char *)0, safe_env());
  1227. else
  1228. execle(cmd, "vxdump", dumpkeys, "1048576", "-",
  1229. device, (char *)0, safe_env());
  1230. else
  1231. #endif
  1232. #ifdef VDUMP
  1233. #ifdef DUMP
  1234. if (strcmp(fstype, "advfs") == 0)
  1235. #else
  1236. if (1)
  1237. #endif
  1238. if (is_rundump)
  1239. execle(cmd, "rundump", config, "vdump", dumpkeys, "60", "-",
  1240. device, (char *)0, safe_env());
  1241. else
  1242. execle(cmd, "vdump", dumpkeys, "60", "-",
  1243. device, (char *)0, safe_env());
  1244. else
  1245. #endif
  1246. #ifdef DUMP
  1247. # ifdef AIX_BACKUP
  1248. if (is_rundump)
  1249. execle(cmd, "rundump", config, "backup", dumpkeys, "-",
  1250. device, (char *)0, safe_env());
  1251. else
  1252. execle(cmd, "backup", dumpkeys, "-",
  1253. device, (char *)0, safe_env());
  1254. # else
  1255. if (is_rundump) {
  1256. execle(cmd, "rundump", config, "dump", dumpkeys,
  1257. #ifdef HAVE_HONOR_NODUMP
  1258. "0",
  1259. #endif
  1260. "1048576", "-", device, (char *)0, safe_env());
  1261. } else {
  1262. execle(cmd, "dump", dumpkeys,
  1263. #ifdef HAVE_HONOR_NODUMP
  1264. "0",
  1265. #endif
  1266. "1048576", "-", device, (char *)0, safe_env());
  1267. }
  1268. # endif
  1269. #endif
  1270. {
  1271. error(_("exec %s failed or no dump program available: %s"),
  1272. cmd, strerror(errno));
  1273. /*NOTREACHED*/
  1274. }
  1275. }
  1276. amfree(dumpkeys);
  1277. amfree(rundump_cmd);
  1278. aclose(pipefd[1]);
  1279. if (killctl[0] != -1)
  1280. aclose(killctl[0]);
  1281. dumpout = fdopen(pipefd[0],"r");
  1282. if (!dumpout) {
  1283. error(_("Can't fdopen: %s"), strerror(errno));
  1284. /*NOTREACHED*/
  1285. }
  1286. for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) {
  1287. if (line[0] == '\0')
  1288. continue;
  1289. dbprintf("%s\n", line);
  1290. size = handle_dumpline(line);
  1291. if(size > (off_t)-1) {
  1292. amfree(line);
  1293. while ((line = agets(dumpout)) != NULL) {
  1294. if (line[0] != '\0')
  1295. break;
  1296. amfree(line);
  1297. }
  1298. if (line != NULL) {
  1299. dbprintf("%s\n", line);
  1300. }
  1301. break;
  1302. }
  1303. }
  1304. amfree(line);
  1305. dbprintf(".....\n");
  1306. dbprintf(_("estimate time for %s level %d: %s\n"),
  1307. qdisk,
  1308. level,
  1309. walltime_str(timessub(curclock(), start_time)));
  1310. if(size == (off_t)-1) {
  1311. *errmsg = vstrallocf(_("no size line match in %s%s output"),
  1312. cmd, name);
  1313. dbprintf(_("%s for %s\n"),
  1314. *errmsg, qdisk);
  1315. dbprintf(".....\n");
  1316. dbprintf(_("Run %s%s manually to check for errors\n"),
  1317. cmd, name);
  1318. } else if(size == (off_t)0 && level == 0) {
  1319. dbprintf(_("possible %s%s problem -- is \"%s\" really empty?\n"),
  1320. cmd, name, disk);
  1321. dbprintf(".....\n");
  1322. } else {
  1323. dbprintf(_("estimate size for %s level %d: %lld KB\n"),
  1324. qdisk,
  1325. level,
  1326. (long long)size);
  1327. }
  1328. if (killctl[1] != -1) {
  1329. dbprintf(_("asking killpgrp to terminate\n"));
  1330. aclose(killctl[1]);
  1331. for(s = 5; s > 0; --s) {
  1332. sleep(1);
  1333. if (waitpid(dumppid, NULL, WNOHANG) != -1)
  1334. goto terminated;
  1335. }
  1336. }
  1337. /*
  1338. * First, try to kill the dump process nicely. If it ignores us
  1339. * for several seconds, hit it harder.
  1340. */
  1341. dbprintf(_("sending SIGTERM to process group %ld\n"), (long)dumppid);
  1342. if (kill(-dumppid, SIGTERM) == -1) {
  1343. dbprintf(_("kill failed: %s\n"), strerror(errno));
  1344. }
  1345. /* Now check whether it dies */
  1346. for(s = 5; s > 0; --s) {
  1347. sleep(1);
  1348. if (waitpid(dumppid, NULL, WNOHANG) != -1)
  1349. goto terminated;
  1350. }
  1351. dbprintf(_("sending SIGKILL to process group %ld\n"), (long)dumppid);
  1352. if (kill(-dumppid, SIGKILL) == -1) {
  1353. dbprintf(_("kill failed: %s\n"), strerror(errno));
  1354. }
  1355. for(s = 5; s > 0; --s) {
  1356. sleep(1);
  1357. if (waitpid(dumppid, NULL, WNOHANG) != -1)
  1358. goto terminated;
  1359. }
  1360. dbprintf(_("waiting for %s%s \"%s\" child\n"), cmd, name, qdisk);
  1361. waitpid(dumppid, &wait_status, 0);
  1362. if (WIFSIGNALED(wait_status)) {
  1363. *errmsg = vstrallocf(_("%s terminated with signal %d: see %s"),
  1364. cmd, WTERMSIG(wait_status), dbfn());
  1365. } else if (WIFEXITED(wait_status)) {
  1366. if (WEXITSTATUS(wait_status) != 0) {
  1367. *errmsg = vstrallocf(_("%s exited with status %d: see %s"),
  1368. cmd, WEXITSTATUS(wait_status), dbfn());
  1369. } else {
  1370. /* Normal exit */
  1371. }
  1372. } else {
  1373. *errmsg = vstrallocf(_("%s got bad exit: see %s"),
  1374. cmd, dbfn());
  1375. }
  1376. dbprintf(_("after %s%s %s wait\n"), cmd, name, qdisk);
  1377. terminated:
  1378. aclose(nullfd);
  1379. afclose(dumpout);
  1380. amfree(device);
  1381. amfree(qdevice);
  1382. amfree(qdisk);
  1383. amfree(fstype);
  1384. amfree(cmd);
  1385. amfree(name);
  1386. return size;
  1387. }
  1388. #ifdef SAMBA_CLIENT
  1389. off_t
  1390. getsize_smbtar(
  1391. char *disk,
  1392. char *amdevice,
  1393. int level,
  1394. option_t *options,
  1395. char **errmsg)
  1396. {
  1397. int pipefd = -1, nullfd = -1, passwdfd = -1;
  1398. pid_t dumppid;
  1399. off_t size;
  1400. FILE *dumpout;
  1401. char *tarkeys, *sharename, *user_and_password = NULL, *domain = NULL;
  1402. char *share = NULL, *subdir = NULL;
  1403. size_t lpass;
  1404. char *pwtext;
  1405. size_t pwtext_len;
  1406. char *line;
  1407. char *pw_fd_env;
  1408. times_t start_time;
  1409. char *error_pn = NULL;
  1410. char *qdisk = quote_string(disk);
  1411. amwait_t wait_status;
  1412. (void)options; /* Quiet unused parameter warning */
  1413. error_pn = stralloc2(get_pname(), "-smbclient");
  1414. parsesharename(amdevice, &share, &subdir);
  1415. if (!share) {
  1416. amfree(share);
  1417. amfree(subdir);
  1418. set_pname(error_pn);
  1419. amfree(error_pn);
  1420. error(_("cannot parse disk entry %s for share/subdir"), qdisk);
  1421. /*NOTREACHED*/
  1422. }
  1423. if ((subdir) && (SAMBA_VERSION < 2)) {
  1424. amfree(share);
  1425. amfree(subdir);
  1426. set_pname(error_pn);
  1427. amfree(error_pn);
  1428. error(_("subdirectory specified for share %s but samba not v2 or better"), qdisk);
  1429. /*NOTREACHED*/
  1430. }
  1431. if ((user_and_password = findpass(share, &domain)) == NULL) {
  1432. if(domain) {
  1433. memset(domain, '\0', strlen(domain));
  1434. amfree(domain);
  1435. }
  1436. set_pname(error_pn);
  1437. amfree(error_pn);
  1438. error(_("cannot find password for %s"), disk);
  1439. /*NOTREACHED*/
  1440. }
  1441. lpass = strlen(user_and_password);
  1442. if ((pwtext = strchr(user_and_password, '%')) == NULL) {
  1443. memset(user_and_password, '\0', (size_t)lpass);
  1444. amfree(user_and_password);
  1445. if(domain) {
  1446. memset(domain, '\0', strlen(domain));
  1447. amfree(domain);
  1448. }
  1449. set_pname(error_pn);
  1450. amfree(error_pn);
  1451. error(_("password field not \'user%%pass\' for %s"), disk);
  1452. /*NOTREACHED*/
  1453. }
  1454. *pwtext++ = '\0';
  1455. pwtext_len = strlen(pwtext);
  1456. if ((sharename = makesharename(share, 0)) == NULL) {
  1457. memset(user_and_password, '\0', (size_t)lpass);
  1458. amfree(user_and_password);
  1459. if(domain) {
  1460. memset(domain, '\0', strlen(domain));
  1461. amfree(domain);
  1462. }
  1463. set_pname(error_pn);
  1464. amfree(error_pn);
  1465. error(_("cannot make share name of %s"), share);
  1466. /*NOTREACHED*/
  1467. }
  1468. if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
  1469. memset(user_and_password, '\0', (size_t)lpass);
  1470. amfree(user_and_password);
  1471. if(domain) {
  1472. memset(domain, '\0', strlen(domain));
  1473. amfree(domain);
  1474. }
  1475. set_pname(error_pn);
  1476. amfree(error_pn);
  1477. amfree(sharename);
  1478. error(_("could not open /dev/null: %s\n"),
  1479. strerror(errno));
  1480. /*NOTREACHED*/
  1481. }
  1482. #if SAMBA_VERSION >= 2
  1483. if (level == 0)
  1484. tarkeys = "archive 0;recurse;du";
  1485. else
  1486. tarkeys = "archive 1;recurse;du";
  1487. #else
  1488. if (level == 0)
  1489. tarkeys = "archive 0;recurse;dir";
  1490. else
  1491. tarkeys = "archive 1;recurse;dir";
  1492. #endif
  1493. start_time = curclock();
  1494. if (pwtext_len > 0) {
  1495. pw_fd_env = "PASSWD_FD";
  1496. } else {
  1497. pw_fd_env = "dummy_PASSWD_FD";
  1498. }
  1499. dumppid = pipespawn(SAMBA_CLIENT, STDERR_PIPE|PASSWD_PIPE,
  1500. &nullfd, &nullfd, &pipefd,
  1501. pw_fd_env, &passwdfd,
  1502. "smbclient",
  1503. sharename,
  1504. "-d", SAMBA_DEBUG_LEVEL,
  1505. *user_and_password ? "-U" : skip_argument,
  1506. *user_and_password ? user_and_password : skip_argument,
  1507. "-E",
  1508. domain ? "-W" : skip_argument,
  1509. domain ? domain : skip_argument,
  1510. #if SAMBA_VERSION >= 2
  1511. subdir ? "-D" : skip_argument,
  1512. subdir ? subdir : skip_argument,
  1513. #endif
  1514. "-c", tarkeys,
  1515. NULL);
  1516. if(domain) {
  1517. memset(domain, '\0', strlen(domain));
  1518. amfree(domain);
  1519. }
  1520. aclose(nullfd);
  1521. if(pwtext_len > 0 && fullwrite(passwdfd, pwtext, (size_t)pwtext_len) < 0) {
  1522. int save_errno = errno;
  1523. memset(user_and_password, '\0', (size_t)lpass);
  1524. amfree(user_and_password);
  1525. aclose(passwdfd);
  1526. set_pname(error_pn);
  1527. amfree(error_pn);
  1528. error(_("password write failed: %s"), strerror(save_errno));
  1529. /*NOTREACHED*/
  1530. }
  1531. memset(user_and_password, '\0', (size_t)lpass);
  1532. amfree(user_and_password);
  1533. aclose(passwdfd);
  1534. amfree(sharename);
  1535. amfree(share);
  1536. amfree(subdir);
  1537. amfree(error_pn);
  1538. dumpout = fdopen(pipefd,"r");
  1539. if (!dumpout) {
  1540. error(_("Can't fdopen: %s"), strerror(errno));
  1541. /*NOTREACHED*/
  1542. }
  1543. for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) {
  1544. if (line[0] == '\0')
  1545. continue;
  1546. dbprintf("%s\n", line);
  1547. size = handle_dumpline(line);
  1548. if(size > -1) {
  1549. amfree(line);
  1550. while ((line = agets(dumpout)) != NULL) {
  1551. if (line[0] != '\0')
  1552. break;
  1553. amfree(line);
  1554. }
  1555. if(line != NULL) {
  1556. dbprintf("%s\n", line);
  1557. }
  1558. break;
  1559. }
  1560. }
  1561. amfree(line);
  1562. dbprintf(".....\n");
  1563. dbprintf(_("estimate time for %s level %d: %s\n"),
  1564. qdisk,
  1565. level,
  1566. walltime_str(timessub(curclock(), start_time)));
  1567. if(size == (off_t)-1) {
  1568. *errmsg = vstrallocf(_("no size line match in %s output"),
  1569. SAMBA_CLIENT);
  1570. dbprintf(_("%s for %s\n"),
  1571. *errmsg, qdisk);
  1572. dbprintf(".....\n");
  1573. } else if(size == (off_t)0 && level == 0) {
  1574. dbprintf(_("possible %s problem -- is \"%s\" really empty?\n"),
  1575. SAMBA_CLIENT, disk);
  1576. dbprintf(".....\n");
  1577. }
  1578. dbprintf(_("estimate size for %s level %d: %lld KB\n"),
  1579. qdisk,
  1580. level,
  1581. (long long)size);
  1582. kill(-dumppid, SIGTERM);
  1583. dbprintf(_("waiting for %s \"%s\" child\n"), SAMBA_CLIENT, qdisk);
  1584. waitpid(dumppid, &wait_status, 0);
  1585. if (WIFSIGNALED(wait_status)) {
  1586. *errmsg = vstrallocf(_("%s terminated with signal %d: see %s"),
  1587. SAMBA_CLIENT, WTERMSIG(wait_status), dbfn());
  1588. } else if (WIFEXITED(wait_status)) {
  1589. if (WEXITSTATUS(wait_status) != 0) {
  1590. *errmsg = vstrallocf(_("%s exited with status %d: see %s"),
  1591. SAMBA_CLIENT, WEXITSTATUS(wait_status),
  1592. dbfn());
  1593. } else {
  1594. /* Normal exit */
  1595. }
  1596. } else {
  1597. *errmsg = vstrallocf(_("%s got bad exit: see %s"),
  1598. SAMBA_CLIENT, dbfn());
  1599. }
  1600. dbprintf(_("after %s %s wait\n"), SAMBA_CLIENT, qdisk);
  1601. afclose(dumpout);
  1602. pipefd = -1;
  1603. amfree(error_pn);
  1604. amfree(qdisk);
  1605. return size;
  1606. }
  1607. #endif
  1608. #ifdef GNUTAR
  1609. off_t
  1610. getsize_gnutar(
  1611. char *disk,
  1612. char *amdevice,
  1613. int level,
  1614. option_t *options,
  1615. time_t dumpsince,
  1616. char **errmsg)
  1617. {
  1618. int pipefd = -1, nullfd = -1;
  1619. pid_t dumppid;
  1620. off_t size = (off_t)-1;
  1621. FILE *dumpout = NULL;
  1622. char *incrname = NULL;
  1623. char *basename = NULL;
  1624. char *dirname = NULL;
  1625. char *inputname = NULL;
  1626. FILE *in = NULL;
  1627. FILE *out = NULL;
  1628. char *line = NULL;
  1629. char *cmd = NULL;
  1630. char dumptimestr[80];
  1631. struct tm *gmtm;
  1632. int nb_exclude = 0;
  1633. int nb_include = 0;
  1634. char **my_argv;
  1635. int i;
  1636. char *file_exclude = NULL;
  1637. char *file_include = NULL;
  1638. times_t start_time;
  1639. int infd, outfd;
  1640. ssize_t nb;
  1641. char buf[32768];
  1642. char *qdisk = quote_string(disk);
  1643. char *gnutar_list_dir;
  1644. amwait_t wait_status;
  1645. char tmppath[PATH_MAX];
  1646. if(options->exclude_file) nb_exclude += options->exclude_file->nb_element;
  1647. if(options->exclude_list) nb_exclude += options->exclude_list->nb_element;
  1648. if(options->include_file) nb_include += options->include_file->nb_element;
  1649. if(options->include_list) nb_include += options->include_list->nb_element;
  1650. if(nb_exclude > 0) file_exclude = build_exclude(disk, amdevice, options, 0);
  1651. if(nb_include > 0) file_include = build_include(disk, amdevice, options, 0);
  1652. my_argv = alloc(SIZEOF(char *) * 22);
  1653. i = 0;
  1654. gnutar_list_dir = getconf_str(CNF_GNUTAR_LIST_DIR);
  1655. if (strlen(gnutar_list_dir) == 0)
  1656. gnutar_list_dir = NULL;
  1657. if (gnutar_list_dir) {
  1658. char number[NUM_STR_SIZE];
  1659. int baselevel;
  1660. char *sdisk = sanitise_filename(disk);
  1661. basename = vstralloc(gnutar_list_dir,
  1662. "/",
  1663. g_options->hostname,
  1664. sdisk,
  1665. NULL);
  1666. amfree(sdisk);
  1667. g_snprintf(number, SIZEOF(number), "%d", level);
  1668. incrname = vstralloc(basename, "_", number, ".new", NULL);
  1669. unlink(incrname);
  1670. /*
  1671. * Open the listed incremental file from the previous level. Search
  1672. * backward until one is found. If none are found (which will also
  1673. * be true for a level 0), arrange to read from /dev/null.
  1674. */
  1675. baselevel = level;
  1676. infd = -1;
  1677. while (infd == -1) {
  1678. if (--baselevel >= 0) {
  1679. g_snprintf(number, SIZEOF(number), "%d", baselevel);
  1680. inputname = newvstralloc(inputname,
  1681. basename, "_", number, NULL);
  1682. } else {
  1683. inputname = newstralloc(inputname, "/dev/null");
  1684. }
  1685. if ((infd = open(inputname, O_RDONLY)) == -1) {
  1686. *errmsg = vstrallocf(_("gnutar: error opening %s: %s"),
  1687. inputname, strerror(errno));
  1688. dbprintf("%s\n", *errmsg);
  1689. if (baselevel < 0) {
  1690. goto common_exit;
  1691. }
  1692. amfree(*errmsg);
  1693. }
  1694. }
  1695. /*
  1696. * Copy the previous listed incremental file to the new one.
  1697. */
  1698. if ((outfd = open(incrname, O_WRONLY|O_CREAT, 0600)) == -1) {
  1699. *errmsg = vstrallocf(_("opening %s: %s"),
  1700. incrname, strerror(errno));
  1701. dbprintf("%s\n", *errmsg);
  1702. goto common_exit;
  1703. }
  1704. while ((nb = read(infd, &buf, SIZEOF(buf))) > 0) {
  1705. if (fullwrite(outfd, &buf, (size_t)nb) < nb) {
  1706. *errmsg = vstrallocf(_("writing to %s: %s"),
  1707. incrname, strerror(errno));
  1708. dbprintf("%s\n", *errmsg);
  1709. goto common_exit;
  1710. }
  1711. }
  1712. if (nb < 0) {
  1713. *errmsg = vstrallocf(_("reading from %s: %s"),
  1714. inputname, strerror(errno));
  1715. dbprintf("%s\n", *errmsg);
  1716. goto common_exit;
  1717. }
  1718. if (close(infd) != 0) {
  1719. *errmsg = vstrallocf(_("closing %s: %s"),
  1720. inputname, strerror(errno));
  1721. dbprintf("%s\n", *errmsg);
  1722. goto common_exit;
  1723. }
  1724. if (close(outfd) != 0) {
  1725. *errmsg = vstrallocf(_("closing %s: %s"),
  1726. incrname, strerror(errno));
  1727. dbprintf("%s\n", *errmsg);
  1728. goto common_exit;
  1729. }
  1730. amfree(inputname);
  1731. amfree(ba

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