PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/amanda/trunk/application-src/amgtar.c

#
C | 1653 lines | 1411 code | 137 blank | 105 comment | 371 complexity | a4c5e62fcb86bc007dd3fbfef91164d6 MD5 | raw 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: amgtar.c 8888 2007-10-02 13:40:42Z martineau $
  28. *
  29. * send estimated backup sizes using dump
  30. */
  31. /* PROPERTY:
  32. *
  33. * GNUTAR-PATH (default GNUTAR)
  34. * GNUTAR-LISTDIR (default CNF_GNUTAR_LIST_DIR)
  35. * DIRECTORY (no default, if set, the backup will be from that directory
  36. * instead of from the --device)
  37. * ONE-FILE-SYSTEM (default YES)
  38. * SPARSE (default YES)
  39. * ATIME-PRESERVE (default YES)
  40. * CHECK-DEVICE (default YES)
  41. * NO-UNQUOTE (default NO)
  42. * ACLS (default NO)
  43. * SELINUX (default NO)
  44. * XATTRS (default NO)
  45. * INCLUDE-FILE
  46. * INCLUDE-LIST
  47. * INCLUDE-LIST-GLOB
  48. * INCLUDE-OPTIONAL
  49. * EXCLUDE-FILE
  50. * EXCLUDE-LIST
  51. * EXCLUDE-LIST-GLOB
  52. * EXCLUDE-OPTIONAL
  53. * NORMAL
  54. * IGNORE
  55. * STRANGE
  56. * EXIT-HANDLING (1=GOOD 2=BAD)
  57. * TAR-BLOCKSIZE (default does not add --blocking-factor option,
  58. * using tar's default)
  59. * VERBOSE
  60. */
  61. #include "amanda.h"
  62. #include "match.h"
  63. #include "pipespawn.h"
  64. #include "amfeatures.h"
  65. #include "clock.h"
  66. #include "util.h"
  67. #include "getfsent.h"
  68. #include "client_util.h"
  69. #include "conffile.h"
  70. #include "getopt.h"
  71. int debug_application = 1;
  72. #define application_debug(i, ...) do { \
  73. if ((i) <= debug_application) { \
  74. dbprintf(__VA_ARGS__); \
  75. } \
  76. } while (0)
  77. static amregex_t init_re_table[] = {
  78. /* tar prints the size in bytes */
  79. AM_SIZE_RE("^ *Total bytes written: [0-9][0-9]*", 1, 1),
  80. AM_NORMAL_RE("^could not open conf file"),
  81. AM_NORMAL_RE("^Elapsed time:"),
  82. AM_NORMAL_RE("^Throughput"),
  83. AM_IGNORE_RE(": Directory is new$"),
  84. AM_IGNORE_RE(": Directory has been renamed"),
  85. /* GNU tar 1.13.17 will print this warning when (not) backing up a
  86. Unix named socket. */
  87. AM_NORMAL_RE(": socket ignored$"),
  88. /* GNUTAR produces a few error messages when files are modified or
  89. removed while it is running. They may cause data to be lost, but
  90. then they may not. We shouldn't consider them NORMAL until
  91. further investigation. */
  92. AM_NORMAL_RE(": File .* shrunk by [0-9][0-9]* bytes, padding with zeros"),
  93. AM_NORMAL_RE(": Cannot add file .*: No such file or directory$"),
  94. AM_NORMAL_RE(": Error exit delayed from previous errors"),
  95. /* catch-all: DMP_STRANGE is returned for all other lines */
  96. AM_STRANGE_RE(NULL)
  97. };
  98. static amregex_t *re_table;
  99. /* local functions */
  100. int main(int argc, char **argv);
  101. typedef struct application_argument_s {
  102. char *config;
  103. char *host;
  104. int message;
  105. int collection;
  106. int calcsize;
  107. char *tar_blocksize;
  108. GSList *level;
  109. GSList *command_options;
  110. char *include_list_glob;
  111. char *exclude_list_glob;
  112. dle_t dle;
  113. int argc;
  114. char **argv;
  115. int verbose;
  116. int ignore_zeros;
  117. } application_argument_t;
  118. enum { CMD_ESTIMATE, CMD_BACKUP };
  119. static void amgtar_support(application_argument_t *argument);
  120. static void amgtar_selfcheck(application_argument_t *argument);
  121. static void amgtar_estimate(application_argument_t *argument);
  122. static void amgtar_backup(application_argument_t *argument);
  123. static void amgtar_restore(application_argument_t *argument);
  124. static void amgtar_validate(application_argument_t *argument);
  125. static void amgtar_build_exinclude(dle_t *dle, int verbose,
  126. int *nb_exclude, char **file_exclude,
  127. int *nb_include, char **file_include);
  128. static char *amgtar_get_incrname(application_argument_t *argument, int level,
  129. FILE *mesgstream, int command);
  130. static GPtrArray *amgtar_build_argv(application_argument_t *argument,
  131. char *incrname, char **file_exclude,
  132. char **file_include, int command);
  133. static char *gnutar_path;
  134. static char *gnutar_listdir;
  135. static char *gnutar_directory;
  136. static int gnutar_onefilesystem;
  137. static int gnutar_atimepreserve;
  138. static int gnutar_acls;
  139. static int gnutar_selinux;
  140. static int gnutar_xattrs;
  141. static int gnutar_checkdevice;
  142. static int gnutar_no_unquote;
  143. static int gnutar_sparse;
  144. static GSList *normal_message = NULL;
  145. static GSList *ignore_message = NULL;
  146. static GSList *strange_message = NULL;
  147. static char *exit_handling;
  148. static int exit_value[256];
  149. static struct option long_options[] = {
  150. {"config" , 1, NULL, 1},
  151. {"host" , 1, NULL, 2},
  152. {"disk" , 1, NULL, 3},
  153. {"device" , 1, NULL, 4},
  154. {"level" , 1, NULL, 5},
  155. {"index" , 1, NULL, 6},
  156. {"message" , 1, NULL, 7},
  157. {"collection" , 0, NULL, 8},
  158. {"record" , 0, NULL, 9},
  159. {"gnutar-path" , 1, NULL, 10},
  160. {"gnutar-listdir" , 1, NULL, 11},
  161. {"one-file-system" , 1, NULL, 12},
  162. {"sparse" , 1, NULL, 13},
  163. {"atime-preserve" , 1, NULL, 14},
  164. {"check-device" , 1, NULL, 15},
  165. {"include-file" , 1, NULL, 16},
  166. {"include-list" , 1, NULL, 17},
  167. {"include-optional", 1, NULL, 18},
  168. {"exclude-file" , 1, NULL, 19},
  169. {"exclude-list" , 1, NULL, 20},
  170. {"exclude-optional", 1, NULL, 21},
  171. {"directory" , 1, NULL, 22},
  172. {"normal" , 1, NULL, 23},
  173. {"ignore" , 1, NULL, 24},
  174. {"strange" , 1, NULL, 25},
  175. {"exit-handling" , 1, NULL, 26},
  176. {"calcsize" , 0, NULL, 27},
  177. {"tar-blocksize" , 1, NULL, 28},
  178. {"no-unquote" , 1, NULL, 29},
  179. {"acls" , 1, NULL, 30},
  180. {"selinux" , 1, NULL, 31},
  181. {"xattrs" , 1, NULL, 32},
  182. {"command-options" , 1, NULL, 33},
  183. {"include-list-glob", 1, NULL, 34},
  184. {"exclude-list-glob", 1, NULL, 35},
  185. {"verbose" , 1, NULL, 36},
  186. {"ignore-zeros" , 1, NULL, 37},
  187. {NULL, 0, NULL, 0}
  188. };
  189. static char *
  190. escape_tar_glob(
  191. char *str,
  192. int *in_argv)
  193. {
  194. char *result = malloc(4*strlen(str)+1);
  195. char *r = result;
  196. char *s;
  197. *in_argv = 0;
  198. for (s = str; *s != '\0'; s++) {
  199. if (*s == '\\') {
  200. char c = *(s+1);
  201. if (c == '\\') {
  202. *r++ = '\\';
  203. *r++ = '\\';
  204. *r++ = '\\';
  205. s++;
  206. } else if (c == '?') {
  207. *r++ = 127;
  208. s++;
  209. continue;
  210. } else if (c == 'a') {
  211. *r++ = 7;
  212. s++;
  213. continue;
  214. } else if (c == 'b') {
  215. *r++ = 8;
  216. s++;
  217. continue;
  218. } else if (c == 'f') {
  219. *r++ = 12;
  220. s++;
  221. continue;
  222. } else if (c == 'n') {
  223. *r++ = 10;
  224. s++;
  225. *in_argv = 1;
  226. continue;
  227. } else if (c == 'r') {
  228. *r++ = 13;
  229. s++;
  230. *in_argv = 1;
  231. continue;
  232. } else if (c == 't') {
  233. *r++ = 9;
  234. s++;
  235. continue;
  236. } else if (c == 'v') {
  237. *r++ = 11;
  238. s++;
  239. continue;
  240. } else if (c >= '0' && c <= '9') {
  241. char d = c-'0';
  242. s++;
  243. c = *(s+1);
  244. if (c >= '0' && c <= '9') {
  245. d = (d*8)+(c-'0');
  246. s++;
  247. c = *(s+1);
  248. if (c >= '0' && c <= '9') {
  249. d = (d*8)+(c-'0');
  250. s++;
  251. }
  252. }
  253. *r++ = d;
  254. continue;
  255. } else {
  256. *r++ = '\\';
  257. }
  258. } else if (*s == '?') {
  259. *r++ = '\\';
  260. *r++ = '\\';
  261. } else if (*s == '*' || *s == '[') {
  262. *r++ = '\\';
  263. }
  264. *r++ = *s;
  265. }
  266. *r = '\0';
  267. return result;
  268. }
  269. int
  270. main(
  271. int argc,
  272. char ** argv)
  273. {
  274. int c;
  275. char *command;
  276. application_argument_t argument;
  277. int i;
  278. #ifdef GNUTAR
  279. gnutar_path = g_strdup(GNUTAR);
  280. #else
  281. gnutar_path = NULL;
  282. #endif
  283. gnutar_listdir = NULL;
  284. gnutar_directory = NULL;
  285. gnutar_onefilesystem = 1;
  286. gnutar_atimepreserve = 1;
  287. gnutar_acls = 0;
  288. gnutar_selinux = 0;
  289. gnutar_xattrs = 0;
  290. gnutar_checkdevice = 1;
  291. gnutar_sparse = 1;
  292. gnutar_no_unquote = 0;
  293. exit_handling = NULL;
  294. /* initialize */
  295. /*
  296. * Configure program for internationalization:
  297. * 1) Only set the message locale for now.
  298. * 2) Set textdomain for all amanda related programs to "amanda"
  299. * We don't want to be forced to support dozens of message catalogs.
  300. */
  301. setlocale(LC_MESSAGES, "C");
  302. textdomain("amanda");
  303. if (argc < 2) {
  304. printf("ERROR no command given to amgtar\n");
  305. error(_("No command given to amgtar"));
  306. }
  307. /* drop root privileges */
  308. if (!set_root_privs(0)) {
  309. if (g_str_equal(argv[1], "selfcheck")) {
  310. printf("ERROR amgtar must be run setuid root\n");
  311. }
  312. error(_("amgtar must be run setuid root"));
  313. }
  314. safe_fd(3, 2);
  315. set_pname("amgtar");
  316. /* Don't die when child closes pipe */
  317. signal(SIGPIPE, SIG_IGN);
  318. #if defined(USE_DBMALLOC)
  319. malloc_size_1 = malloc_inuse(&malloc_hist_1);
  320. #endif
  321. add_amanda_log_handler(amanda_log_stderr);
  322. add_amanda_log_handler(amanda_log_syslog);
  323. dbopen(DBG_SUBDIR_CLIENT);
  324. startclock();
  325. dbprintf(_("version %s\n"), VERSION);
  326. config_init(CONFIG_INIT_CLIENT, NULL);
  327. //check_running_as(RUNNING_AS_DUMPUSER_PREFERRED);
  328. //root for amrecover
  329. //RUNNING_AS_CLIENT_LOGIN from selfcheck, sendsize, sendbackup
  330. /* parse argument */
  331. command = argv[1];
  332. gnutar_listdir = g_strdup(getconf_str(CNF_GNUTAR_LIST_DIR));
  333. argument.config = NULL;
  334. argument.host = NULL;
  335. argument.message = 0;
  336. argument.collection = 0;
  337. argument.calcsize = 0;
  338. argument.tar_blocksize = NULL;
  339. argument.level = NULL;
  340. argument.command_options = NULL;
  341. argument.include_list_glob = NULL;
  342. argument.exclude_list_glob = NULL;
  343. argument.verbose = 0;
  344. argument.ignore_zeros = 1;
  345. init_dle(&argument.dle);
  346. argument.dle.record = 0;
  347. while (1) {
  348. int option_index = 0;
  349. c = getopt_long (argc, argv, "", long_options, &option_index);
  350. if (c == -1) {
  351. break;
  352. }
  353. switch (c) {
  354. case 1: amfree(argument.config);
  355. argument.config = g_strdup(optarg);
  356. break;
  357. case 2: amfree(argument.host);
  358. argument.host = g_strdup(optarg);
  359. break;
  360. case 3: amfree(argument.dle.disk);
  361. argument.dle.disk = g_strdup(optarg);
  362. break;
  363. case 4: amfree(argument.dle.device);
  364. argument.dle.device = g_strdup(optarg);
  365. break;
  366. case 5: argument.level = g_slist_append(argument.level,
  367. GINT_TO_POINTER(atoi(optarg)));
  368. break;
  369. case 6: argument.dle.create_index = 1;
  370. break;
  371. case 7: argument.message = 1;
  372. break;
  373. case 8: argument.collection = 1;
  374. break;
  375. case 9: argument.dle.record = 1;
  376. break;
  377. case 10: amfree(gnutar_path);
  378. gnutar_path = g_strdup(optarg);
  379. break;
  380. case 11: amfree(gnutar_listdir);
  381. gnutar_listdir = g_strdup(optarg);
  382. break;
  383. case 12: if (strcasecmp(optarg, "NO") == 0)
  384. gnutar_onefilesystem = 0;
  385. else if (strcasecmp(optarg, "YES") == 0)
  386. gnutar_onefilesystem = 1;
  387. else if (strcasecmp(command, "selfcheck") == 0)
  388. printf(_("ERROR [%s: bad ONE-FILE-SYSTEM property value (%s)]\n"), get_pname(), optarg);
  389. break;
  390. case 13: if (strcasecmp(optarg, "NO") == 0)
  391. gnutar_sparse = 0;
  392. else if (strcasecmp(optarg, "YES") == 0)
  393. gnutar_sparse = 1;
  394. else if (strcasecmp(command, "selfcheck") == 0)
  395. printf(_("ERROR [%s: bad SPARSE property value (%s)]\n"), get_pname(), optarg);
  396. break;
  397. case 14: if (strcasecmp(optarg, "NO") == 0)
  398. gnutar_atimepreserve = 0;
  399. else if (strcasecmp(optarg, "YES") == 0)
  400. gnutar_atimepreserve = 1;
  401. else if (strcasecmp(command, "selfcheck") == 0)
  402. printf(_("ERROR [%s: bad ATIME-PRESERVE property value (%s)]\n"), get_pname(), optarg);
  403. break;
  404. case 15: if (strcasecmp(optarg, "NO") == 0)
  405. gnutar_checkdevice = 0;
  406. else if (strcasecmp(optarg, "YES") == 0)
  407. gnutar_checkdevice = 1;
  408. else if (strcasecmp(command, "selfcheck") == 0)
  409. printf(_("ERROR [%s: bad CHECK-DEVICE property value (%s)]\n"), get_pname(), optarg);
  410. break;
  411. case 16: argument.dle.include_file =
  412. append_sl(argument.dle.include_file, optarg);
  413. break;
  414. case 17: argument.dle.include_list =
  415. append_sl(argument.dle.include_list, optarg);
  416. break;
  417. case 18: argument.dle.include_optional = 1;
  418. break;
  419. case 19: argument.dle.exclude_file =
  420. append_sl(argument.dle.exclude_file, optarg);
  421. break;
  422. case 20: argument.dle.exclude_list =
  423. append_sl(argument.dle.exclude_list, optarg);
  424. break;
  425. case 21: argument.dle.exclude_optional = 1;
  426. break;
  427. case 22: amfree(gnutar_directory);
  428. gnutar_directory = g_strdup(optarg);
  429. break;
  430. case 23: normal_message =
  431. g_slist_append(normal_message, optarg);
  432. break;
  433. case 24: ignore_message =
  434. g_slist_append(ignore_message, optarg);
  435. break;
  436. case 25: strange_message =
  437. g_slist_append(strange_message, optarg);
  438. break;
  439. case 26: amfree(exit_handling);
  440. exit_handling = g_strdup(optarg);
  441. break;
  442. case 27: argument.calcsize = 1;
  443. break;
  444. case 28: amfree(argument.tar_blocksize);
  445. argument.tar_blocksize = g_strdup(optarg);
  446. break;
  447. case 29: if (strcasecmp(optarg, "NO") == 0)
  448. gnutar_no_unquote = 0;
  449. else if (strcasecmp(optarg, "YES") == 0)
  450. gnutar_no_unquote = 1;
  451. else if (strcasecmp(command, "selfcheck") == 0)
  452. printf(_("ERROR [%s: bad No_UNQUOTE property value (%s)]\n"), get_pname(), optarg);
  453. break;
  454. case 30: if (strcasecmp(optarg, "YES") == 0)
  455. gnutar_acls = 1;
  456. break;
  457. case 31: if (strcasecmp(optarg, "YES") == 0)
  458. gnutar_selinux = 1;
  459. break;
  460. case 32: if (strcasecmp(optarg, "YES") == 0)
  461. gnutar_xattrs = 1;
  462. break;
  463. case 33: argument.command_options =
  464. g_slist_append(argument.command_options,
  465. g_strdup(optarg));
  466. break;
  467. case 34: amfree(argument.include_list_glob);
  468. argument.include_list_glob = g_strdup(optarg);
  469. break;
  470. case 35: amfree(argument.exclude_list_glob);
  471. argument.exclude_list_glob = g_strdup(optarg);
  472. break;
  473. case 36: if (strcasecmp(optarg, "YES") == 0)
  474. argument.verbose = 1;
  475. break;
  476. case 37: if (strcasecmp(optarg, "YES") != 0)
  477. argument.ignore_zeros = 0;
  478. break;
  479. case ':':
  480. case '?':
  481. break;
  482. }
  483. }
  484. if (!argument.dle.disk && argument.dle.device)
  485. argument.dle.disk = g_strdup(argument.dle.device);
  486. if (!argument.dle.device && argument.dle.disk)
  487. argument.dle.device = g_strdup(argument.dle.disk);
  488. argument.argc = argc - optind;
  489. argument.argv = argv + optind;
  490. if (argument.config) {
  491. config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY,
  492. argument.config);
  493. dbrename(get_config_name(), DBG_SUBDIR_CLIENT);
  494. }
  495. if (config_errors(NULL) >= CFGERR_ERRORS) {
  496. g_critical(_("errors processing config file"));
  497. }
  498. re_table = build_re_table(init_re_table, normal_message, ignore_message,
  499. strange_message);
  500. for(i=0;i<256;i++)
  501. exit_value[i] = 1; /* BAD */
  502. exit_value[0] = 0; /* GOOD */
  503. exit_value[1] = 0; /* GOOD */
  504. if (exit_handling) {
  505. char *s = exit_handling;
  506. while (s) {
  507. char *r = strchr(s, '=');
  508. if (r) {
  509. int j = atoi(s);
  510. if (j >= 0 && j < 256) {
  511. r++;
  512. if (strncasecmp(r, "GOOD", 4) == 0) {
  513. exit_value[j] = 0;
  514. }
  515. }
  516. }
  517. s = strchr(s+1, ' ');
  518. }
  519. }
  520. if (strlen(gnutar_listdir) == 0)
  521. amfree(gnutar_listdir);
  522. if (gnutar_path) {
  523. dbprintf("GNUTAR-PATH %s\n", gnutar_path);
  524. } else {
  525. dbprintf("GNUTAR-PATH is not set\n");
  526. }
  527. if (gnutar_listdir) {
  528. dbprintf("GNUTAR-LISTDIR %s\n", gnutar_listdir);
  529. } else {
  530. dbprintf("GNUTAR-LISTDIR is not set\n");
  531. }
  532. if (gnutar_directory) {
  533. dbprintf("DIRECTORY %s\n", gnutar_directory);
  534. }
  535. dbprintf("ONE-FILE-SYSTEM %s\n", gnutar_onefilesystem? "yes":"no");
  536. dbprintf("SPARSE %s\n", gnutar_sparse? "yes":"no");
  537. dbprintf("NO-UNQUOTE %s\n", gnutar_no_unquote? "yes":"no");
  538. dbprintf("ATIME-PRESERVE %s\n", gnutar_atimepreserve? "yes":"no");
  539. dbprintf("ACLS %s\n", gnutar_acls? "yes":"no");
  540. dbprintf("SELINUX %s\n", gnutar_selinux? "yes":"no");
  541. dbprintf("XATTRS %s\n", gnutar_xattrs? "yes":"no");
  542. dbprintf("CHECK-DEVICE %s\n", gnutar_checkdevice? "yes":"no");
  543. {
  544. amregex_t *rp;
  545. for (rp = re_table; rp->regex != NULL; rp++) {
  546. switch (rp->typ) {
  547. case DMP_NORMAL : dbprintf("NORMAL %s\n", rp->regex); break;
  548. case DMP_IGNORE : dbprintf("IGNORE %s\n", rp->regex); break;
  549. case DMP_STRANGE: dbprintf("STRANGE %s\n", rp->regex); break;
  550. case DMP_SIZE : dbprintf("SIZE %s\n", rp->regex); break;
  551. case DMP_ERROR : dbprintf("ERROR %s\n", rp->regex); break;
  552. }
  553. }
  554. }
  555. if (g_str_equal(command, "support")) {
  556. amgtar_support(&argument);
  557. } else if (g_str_equal(command, "selfcheck")) {
  558. amgtar_selfcheck(&argument);
  559. } else if (g_str_equal(command, "estimate")) {
  560. amgtar_estimate(&argument);
  561. } else if (g_str_equal(command, "backup")) {
  562. amgtar_backup(&argument);
  563. } else if (g_str_equal(command, "restore")) {
  564. amgtar_restore(&argument);
  565. } else if (g_str_equal(command, "validate")) {
  566. amgtar_validate(&argument);
  567. } else {
  568. dbprintf("Unknown command `%s'.\n", command);
  569. fprintf(stderr, "Unknown command `%s'.\n", command);
  570. exit (1);
  571. }
  572. return 0;
  573. }
  574. static void
  575. amgtar_support(
  576. application_argument_t *argument)
  577. {
  578. (void)argument;
  579. fprintf(stdout, "CONFIG YES\n");
  580. fprintf(stdout, "HOST YES\n");
  581. fprintf(stdout, "DISK YES\n");
  582. fprintf(stdout, "MAX-LEVEL 399\n");
  583. fprintf(stdout, "INDEX-LINE YES\n");
  584. fprintf(stdout, "INDEX-XML NO\n");
  585. fprintf(stdout, "MESSAGE-LINE YES\n");
  586. fprintf(stdout, "MESSAGE-XML NO\n");
  587. fprintf(stdout, "RECORD YES\n");
  588. fprintf(stdout, "INCLUDE-FILE YES\n");
  589. fprintf(stdout, "INCLUDE-LIST YES\n");
  590. fprintf(stdout, "INCLUDE-LIST-GLOB YES\n");
  591. fprintf(stdout, "INCLUDE-OPTIONAL YES\n");
  592. fprintf(stdout, "EXCLUDE-FILE YES\n");
  593. fprintf(stdout, "EXCLUDE-LIST YES\n");
  594. fprintf(stdout, "EXCLUDE-LIST-GLOB YES\n");
  595. fprintf(stdout, "EXCLUDE-OPTIONAL YES\n");
  596. fprintf(stdout, "COLLECTION NO\n");
  597. fprintf(stdout, "MULTI-ESTIMATE YES\n");
  598. fprintf(stdout, "CALCSIZE YES\n");
  599. fprintf(stdout, "CLIENT-ESTIMATE YES\n");
  600. }
  601. static void
  602. amgtar_selfcheck(
  603. application_argument_t *argument)
  604. {
  605. if (argument->dle.disk) {
  606. char *qdisk = quote_string(argument->dle.disk);
  607. fprintf(stdout, "OK disk %s\n", qdisk);
  608. amfree(qdisk);
  609. }
  610. printf("OK amgtar version %s\n", VERSION);
  611. amgtar_build_exinclude(&argument->dle, 1, NULL, NULL, NULL, NULL);
  612. printf("OK amgtar\n");
  613. if (gnutar_path) {
  614. if (check_file(gnutar_path, X_OK)) {
  615. char *gtar_version;
  616. GPtrArray *argv_ptr = g_ptr_array_new();
  617. g_ptr_array_add(argv_ptr, gnutar_path);
  618. g_ptr_array_add(argv_ptr, "--version");
  619. g_ptr_array_add(argv_ptr, NULL);
  620. gtar_version = get_first_line(argv_ptr);
  621. if (gtar_version) {
  622. char *gv;
  623. for (gv = gtar_version; *gv && !g_ascii_isdigit(*gv); gv++);
  624. printf("OK amgtar gtar-version %s\n", gv);
  625. } else {
  626. printf(_("ERROR [Can't get %s version]\n"), gnutar_path);
  627. }
  628. g_ptr_array_free(argv_ptr, TRUE);
  629. amfree(gtar_version);
  630. }
  631. } else {
  632. printf(_("ERROR [GNUTAR program not available]\n"));
  633. }
  634. set_root_privs(1);
  635. if (gnutar_listdir && strlen(gnutar_listdir) == 0)
  636. gnutar_listdir = NULL;
  637. if (gnutar_listdir) {
  638. check_dir(gnutar_listdir, R_OK|W_OK);
  639. } else {
  640. printf(_("ERROR [No GNUTAR-LISTDIR]\n"));
  641. }
  642. if (gnutar_directory) {
  643. check_dir(gnutar_directory, R_OK);
  644. } else if (argument->dle.device) {
  645. check_dir(argument->dle.device, R_OK);
  646. }
  647. if (argument->calcsize) {
  648. char *calcsize = g_strjoin(NULL, amlibexecdir, "/", "calcsize", NULL);
  649. check_file(calcsize, X_OK);
  650. check_suid(calcsize);
  651. amfree(calcsize);
  652. }
  653. set_root_privs(0);
  654. }
  655. static void
  656. amgtar_estimate(
  657. application_argument_t *argument)
  658. {
  659. char *incrname = NULL;
  660. GPtrArray *argv_ptr;
  661. char *cmd = NULL;
  662. int nullfd = -1;
  663. int pipefd = -1;
  664. FILE *dumpout = NULL;
  665. off_t size = -1;
  666. char line[32768];
  667. char *errmsg = NULL;
  668. char *qerrmsg = NULL;
  669. char *qdisk;
  670. amwait_t wait_status;
  671. int tarpid;
  672. amregex_t *rp;
  673. times_t start_time;
  674. int level;
  675. GSList *levels;
  676. char *file_exclude;
  677. char *file_include;
  678. GString *strbuf;
  679. if (!argument->level) {
  680. fprintf(stderr, "ERROR No level argument\n");
  681. error(_("No level argument"));
  682. }
  683. if (!argument->dle.disk) {
  684. fprintf(stderr, "ERROR No disk argument\n");
  685. error(_("No disk argument"));
  686. }
  687. if (!argument->dle.device) {
  688. fprintf(stderr, "ERROR No device argument\n");
  689. error(_("No device argument"));
  690. }
  691. qdisk = quote_string(argument->dle.disk);
  692. if (argument->calcsize) {
  693. char *dirname;
  694. int nb_exclude;
  695. int nb_include;
  696. if (gnutar_directory) {
  697. dirname = gnutar_directory;
  698. } else {
  699. dirname = argument->dle.device;
  700. }
  701. amgtar_build_exinclude(&argument->dle, 1,
  702. &nb_exclude, &file_exclude,
  703. &nb_include, &file_include);
  704. run_calcsize(argument->config, "GNUTAR", argument->dle.disk, dirname,
  705. argument->level, file_exclude, file_include);
  706. if (argument->verbose == 0) {
  707. if (file_exclude)
  708. unlink(file_exclude);
  709. if (file_include)
  710. unlink(file_include);
  711. }
  712. amfree(file_exclude);
  713. amfree(file_include);
  714. amfree(qdisk);
  715. return;
  716. }
  717. if (!gnutar_path) {
  718. errmsg = g_strdup(_("GNUTAR-PATH not defined"));
  719. goto common_error;
  720. }
  721. if (!gnutar_listdir) {
  722. errmsg = g_strdup(_("GNUTAR-LISTDIR not defined"));
  723. goto common_error;
  724. }
  725. for (levels = argument->level; levels != NULL; levels = levels->next) {
  726. level = GPOINTER_TO_INT(levels->data);
  727. incrname = amgtar_get_incrname(argument, level, stdout, CMD_ESTIMATE);
  728. cmd = g_strdup(gnutar_path);
  729. argv_ptr = amgtar_build_argv(argument, incrname, &file_exclude,
  730. &file_include, CMD_ESTIMATE);
  731. start_time = curclock();
  732. if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
  733. errmsg = g_strdup_printf(_("Cannot access /dev/null : %s"),
  734. strerror(errno));
  735. goto common_exit;
  736. }
  737. tarpid = pipespawnv(cmd, STDERR_PIPE, 1,
  738. &nullfd, &nullfd, &pipefd,
  739. (char **)argv_ptr->pdata);
  740. dumpout = fdopen(pipefd,"r");
  741. if (!dumpout) {
  742. error(_("Can't fdopen: %s"), strerror(errno));
  743. /*NOTREACHED*/
  744. }
  745. size = (off_t)-1;
  746. while (size < 0 && (fgets(line, sizeof(line), dumpout) != NULL)) {
  747. if (strlen(line) > 0 && line[strlen(line)-1] == '\n') {
  748. /* remove trailling \n */
  749. line[strlen(line)-1] = '\0';
  750. }
  751. if (line[0] == '\0')
  752. continue;
  753. dbprintf("%s\n", line);
  754. /* check for size match */
  755. /*@ignore@*/
  756. for(rp = re_table; rp->regex != NULL; rp++) {
  757. if(match(rp->regex, line)) {
  758. if (rp->typ == DMP_SIZE) {
  759. size = ((the_num(line, rp->field)*rp->scale+1023.0)/1024.0);
  760. if(size < 0.0)
  761. size = 1.0; /* found on NeXT -- sigh */
  762. }
  763. break;
  764. }
  765. }
  766. /*@end@*/
  767. }
  768. while (fgets(line, sizeof(line), dumpout) != NULL) {
  769. dbprintf("%s", line);
  770. }
  771. dbprintf(".....\n");
  772. dbprintf(_("estimate time for %s level %d: %s\n"),
  773. qdisk,
  774. level,
  775. walltime_str(timessub(curclock(), start_time)));
  776. if(size == (off_t)-1) {
  777. errmsg = g_strdup_printf(_("no size line match in %s output"), cmd);
  778. dbprintf(_("%s for %s\n"), errmsg, qdisk);
  779. dbprintf(".....\n");
  780. } else if(size == (off_t)0 && argument->level == 0) {
  781. dbprintf(_("possible %s problem -- is \"%s\" really empty?\n"),
  782. cmd, argument->dle.disk);
  783. dbprintf(".....\n");
  784. }
  785. dbprintf(_("estimate size for %s level %d: %lld KB\n"),
  786. qdisk,
  787. level,
  788. (long long)size);
  789. kill(-tarpid, SIGTERM);
  790. dbprintf(_("waiting for %s \"%s\" child\n"), cmd, qdisk);
  791. waitpid(tarpid, &wait_status, 0);
  792. if (WIFSIGNALED(wait_status)) {
  793. strbuf = g_string_new(errmsg);
  794. g_string_append_printf(strbuf, "%s terminated with signal %d: see %s",
  795. cmd, WTERMSIG(wait_status), dbfn());
  796. g_free(errmsg);
  797. errmsg = g_string_free(strbuf, FALSE);
  798. } else if (WIFEXITED(wait_status)) {
  799. if (exit_value[WEXITSTATUS(wait_status)] == 1) {
  800. strbuf = g_string_new(errmsg);
  801. g_string_append_printf(strbuf, "%s exited with status %d: see %s",
  802. cmd, WEXITSTATUS(wait_status), dbfn());
  803. g_free(errmsg);
  804. errmsg = g_string_free(strbuf, FALSE);
  805. } else {
  806. /* Normal exit */
  807. }
  808. } else {
  809. errmsg = g_strdup_printf(_("%s got bad exit: see %s"),
  810. cmd, dbfn());
  811. }
  812. dbprintf(_("after %s %s wait\n"), cmd, qdisk);
  813. common_exit:
  814. if (errmsg) {
  815. dbprintf("%s", errmsg);
  816. fprintf(stdout, "ERROR %s\n", errmsg);
  817. amfree(errmsg);
  818. }
  819. unlink(incrname);
  820. if (argument->verbose == 0) {
  821. if (file_exclude)
  822. unlink(file_exclude);
  823. if (file_include)
  824. unlink(file_include);
  825. }
  826. g_ptr_array_free_full(argv_ptr);
  827. amfree(cmd);
  828. amfree(incrname);
  829. aclose(nullfd);
  830. afclose(dumpout);
  831. fprintf(stdout, "%d %lld 1\n", level, (long long)size);
  832. }
  833. amfree(qdisk);
  834. return;
  835. common_error:
  836. qerrmsg = quote_string(errmsg);
  837. amfree(qdisk);
  838. dbprintf("%s", errmsg);
  839. fprintf(stdout, "ERROR %s\n", qerrmsg);
  840. amfree(errmsg);
  841. amfree(qerrmsg);
  842. return;
  843. }
  844. static void
  845. amgtar_backup(
  846. application_argument_t *argument)
  847. {
  848. int dumpin;
  849. char *cmd = NULL;
  850. char *qdisk;
  851. char *incrname;
  852. char line[32768];
  853. amregex_t *rp;
  854. off_t dump_size = -1;
  855. char *type;
  856. char startchr;
  857. int dataf = 1;
  858. int mesgf = 3;
  859. int indexf = 4;
  860. int outf;
  861. FILE *mesgstream;
  862. FILE *indexstream = NULL;
  863. FILE *outstream;
  864. char *errmsg = NULL;
  865. amwait_t wait_status;
  866. GPtrArray *argv_ptr;
  867. int tarpid;
  868. char *file_exclude;
  869. char *file_include;
  870. mesgstream = fdopen(mesgf, "w");
  871. if (!mesgstream) {
  872. error(_("error mesgstream(%d): %s\n"), mesgf, strerror(errno));
  873. }
  874. if (!gnutar_path) {
  875. error(_("GNUTAR-PATH not defined"));
  876. }
  877. if (!gnutar_listdir) {
  878. error(_("GNUTAR-LISTDIR not defined"));
  879. }
  880. if (!argument->level) {
  881. fprintf(mesgstream, "? No level argument\n");
  882. error(_("No level argument"));
  883. }
  884. if (!argument->dle.disk) {
  885. fprintf(mesgstream, "? No disk argument\n");
  886. error(_("No disk argument"));
  887. }
  888. if (!argument->dle.device) {
  889. fprintf(mesgstream, "? No device argument\n");
  890. error(_("No device argument"));
  891. }
  892. qdisk = quote_string(argument->dle.disk);
  893. incrname = amgtar_get_incrname(argument,
  894. GPOINTER_TO_INT(argument->level->data),
  895. mesgstream, CMD_BACKUP);
  896. cmd = g_strdup(gnutar_path);
  897. argv_ptr = amgtar_build_argv(argument, incrname, &file_exclude,
  898. &file_include, CMD_BACKUP);
  899. tarpid = pipespawnv(cmd, STDIN_PIPE|STDERR_PIPE, 1,
  900. &dumpin, &dataf, &outf, (char **)argv_ptr->pdata);
  901. /* close the write ends of the pipes */
  902. aclose(dumpin);
  903. aclose(dataf);
  904. if (argument->dle.create_index) {
  905. indexstream = fdopen(indexf, "w");
  906. if (!indexstream) {
  907. error(_("error indexstream(%d): %s\n"), indexf, strerror(errno));
  908. }
  909. }
  910. outstream = fdopen(outf, "r");
  911. if (!outstream) {
  912. error(_("error outstream(%d): %s\n"), outf, strerror(errno));
  913. }
  914. while (fgets(line, sizeof(line), outstream) != NULL) {
  915. if (strlen(line) > 0 && line[strlen(line)-1] == '\n') {
  916. /* remove trailling \n */
  917. line[strlen(line)-1] = '\0';
  918. }
  919. if (*line == '.' && *(line+1) == '/') { /* filename */
  920. if (argument->dle.create_index) {
  921. fprintf(indexstream, "%s\n", &line[1]); /* remove . */
  922. }
  923. } else { /* message */
  924. for(rp = re_table; rp->regex != NULL; rp++) {
  925. if(match(rp->regex, line)) {
  926. break;
  927. }
  928. }
  929. if(rp->typ == DMP_SIZE) {
  930. dump_size = (off_t)((the_num(line, rp->field)* rp->scale+1023.0)/1024.0);
  931. }
  932. switch(rp->typ) {
  933. case DMP_NORMAL:
  934. type = "normal";
  935. startchr = '|';
  936. break;
  937. case DMP_IGNORE:
  938. continue;
  939. case DMP_STRANGE:
  940. type = "strange";
  941. startchr = '?';
  942. break;
  943. case DMP_SIZE:
  944. type = "size";
  945. startchr = '|';
  946. break;
  947. case DMP_ERROR:
  948. type = "error";
  949. startchr = '?';
  950. break;
  951. default:
  952. type = "unknown";
  953. startchr = '!';
  954. break;
  955. }
  956. dbprintf("%3d: %7s(%c): %s\n", rp->srcline, type, startchr, line);
  957. fprintf(mesgstream,"%c %s\n", startchr, line);
  958. }
  959. }
  960. fclose(outstream);
  961. waitpid(tarpid, &wait_status, 0);
  962. if (WIFSIGNALED(wait_status)) {
  963. errmsg = g_strdup_printf(_("%s terminated with signal %d: see %s"),
  964. cmd, WTERMSIG(wait_status), dbfn());
  965. } else if (WIFEXITED(wait_status)) {
  966. if (exit_value[WEXITSTATUS(wait_status)] == 1) {
  967. errmsg = g_strdup_printf(_("%s exited with status %d: see %s"),
  968. cmd, WEXITSTATUS(wait_status), dbfn());
  969. } else {
  970. /* Normal exit */
  971. }
  972. } else {
  973. errmsg = g_strdup_printf(_("%s got bad exit: see %s"),
  974. cmd, dbfn());
  975. }
  976. dbprintf(_("after %s %s wait\n"), cmd, qdisk);
  977. dbprintf(_("amgtar: %s: pid %ld\n"), cmd, (long)tarpid);
  978. if (errmsg) {
  979. dbprintf("%s", errmsg);
  980. g_fprintf(mesgstream, "sendbackup: error [%s]\n", errmsg);
  981. }
  982. if (!errmsg && strlen(incrname) > 4) {
  983. if (argument->dle.record) {
  984. char *nodotnew;
  985. nodotnew = g_strdup(incrname);
  986. nodotnew[strlen(nodotnew)-4] = '\0';
  987. if (rename(incrname, nodotnew)) {
  988. dbprintf(_("%s: warning [renaming %s to %s: %s]\n"),
  989. get_pname(), incrname, nodotnew, strerror(errno));
  990. g_fprintf(mesgstream, _("? warning [renaming %s to %s: %s]\n"),
  991. incrname, nodotnew, strerror(errno));
  992. }
  993. amfree(nodotnew);
  994. } else {
  995. if (unlink(incrname) == -1) {
  996. dbprintf(_("%s: warning [unlink %s: %s]\n"),
  997. get_pname(), incrname, strerror(errno));
  998. g_fprintf(mesgstream, _("? warning [unlink %s: %s]\n"),
  999. incrname, strerror(errno));
  1000. }
  1001. }
  1002. }
  1003. dbprintf("sendbackup: size %lld\n", (long long)dump_size);
  1004. fprintf(mesgstream, "sendbackup: size %lld\n", (long long)dump_size);
  1005. dbprintf("sendbackup: end\n");
  1006. fprintf(mesgstream, "sendbackup: end\n");
  1007. if (argument->dle.create_index)
  1008. fclose(indexstream);
  1009. fclose(mesgstream);
  1010. if (argument->verbose == 0) {
  1011. if (file_exclude)
  1012. unlink(file_exclude);
  1013. if (file_include)
  1014. unlink(file_include);
  1015. }
  1016. amfree(incrname);
  1017. amfree(qdisk);
  1018. amfree(cmd);
  1019. amfree(errmsg);
  1020. g_ptr_array_free_full(argv_ptr);
  1021. }
  1022. static void
  1023. amgtar_restore(
  1024. application_argument_t *argument)
  1025. {
  1026. char *cmd;
  1027. GPtrArray *argv_ptr = g_ptr_array_new();
  1028. char **env;
  1029. int j;
  1030. char *e;
  1031. char *include_filename = NULL;
  1032. char *exclude_filename = NULL;
  1033. int tarpid;
  1034. if (!gnutar_path) {
  1035. error(_("GNUTAR-PATH not defined"));
  1036. }
  1037. cmd = g_strdup(gnutar_path);
  1038. g_ptr_array_add(argv_ptr, g_strdup(gnutar_path));
  1039. g_ptr_array_add(argv_ptr, g_strdup("--numeric-owner"));
  1040. if (gnutar_no_unquote)
  1041. g_ptr_array_add(argv_ptr, g_strdup("--no-unquote"));
  1042. if (gnutar_acls)
  1043. g_ptr_array_add(argv_ptr, g_strdup("--acls"));
  1044. if (gnutar_selinux)
  1045. g_ptr_array_add(argv_ptr, g_strdup("--selinux"));
  1046. if (gnutar_xattrs)
  1047. g_ptr_array_add(argv_ptr, g_strdup("--xattrs"));
  1048. /* ignore trailing zero blocks on input (this was the default until tar-1.21) */
  1049. if (argument->ignore_zeros) {
  1050. g_ptr_array_add(argv_ptr, g_strdup("--ignore-zeros"));
  1051. }
  1052. if (argument->tar_blocksize) {
  1053. g_ptr_array_add(argv_ptr, g_strdup("--blocking-factor"));
  1054. g_ptr_array_add(argv_ptr, g_strdup(argument->tar_blocksize));
  1055. }
  1056. g_ptr_array_add(argv_ptr, g_strdup("-xpGvf"));
  1057. g_ptr_array_add(argv_ptr, g_strdup("-"));
  1058. if (gnutar_directory) {
  1059. struct stat stat_buf;
  1060. if(stat(gnutar_directory, &stat_buf) != 0) {
  1061. fprintf(stderr,"can not stat directory %s: %s\n", gnutar_directory, strerror(errno));
  1062. exit(1);
  1063. }
  1064. if (!S_ISDIR(stat_buf.st_mode)) {
  1065. fprintf(stderr,"%s is not a directory\n", gnutar_directory);
  1066. exit(1);
  1067. }
  1068. if (access(gnutar_directory, W_OK) != 0) {
  1069. fprintf(stderr, "Can't write to %s: %s\n", gnutar_directory, strerror(errno));
  1070. exit(1);
  1071. }
  1072. g_ptr_array_add(argv_ptr, g_strdup("--directory"));
  1073. g_ptr_array_add(argv_ptr, g_strdup(gnutar_directory));
  1074. }
  1075. g_ptr_array_add(argv_ptr, g_strdup("--wildcards"));
  1076. if (argument->dle.exclude_list &&
  1077. argument->dle.exclude_list->nb_element == 1) {
  1078. FILE *exclude;
  1079. char *sdisk;
  1080. int in_argv;
  1081. int entry_in_exclude = 0;
  1082. char line[2*PATH_MAX];
  1083. FILE *exclude_list;
  1084. if (argument->dle.disk) {
  1085. sdisk = sanitise_filename(argument->dle.disk);
  1086. } else {
  1087. sdisk = g_strdup_printf("no_dle-%d", getpid());
  1088. }
  1089. exclude_filename= g_strjoin(NULL, AMANDA_TMPDIR, "/", "exclude-", sdisk, NULL);
  1090. exclude_list = fopen(argument->dle.exclude_list->first->name, "r");
  1091. if (!exclude_list) {
  1092. fprintf(stderr, "Cannot open exclude file '%s': %s\n",
  1093. argument->dle.exclude_list->first->name, strerror(errno));
  1094. error("Cannot open exclude file '%s': %s\n",
  1095. argument->dle.exclude_list->first->name, strerror(errno));
  1096. /*NOTREACHED*/
  1097. }
  1098. exclude = fopen(exclude_filename, "w");
  1099. if (!exclude) {
  1100. fprintf(stderr, "Cannot open exclude file '%s': %s\n",
  1101. exclude_filename, strerror(errno));
  1102. fclose(exclude_list);
  1103. error("Cannot open exclude file '%s': %s\n",
  1104. exclude_filename, strerror(errno));
  1105. /*NOTREACHED*/
  1106. }
  1107. while (fgets(line, 2*PATH_MAX, exclude_list)) {
  1108. char *escaped;
  1109. line[strlen(line)-1] = '\0'; /* remove '\n' */
  1110. escaped = escape_tar_glob(line, &in_argv);
  1111. if (in_argv) {
  1112. g_ptr_array_add(argv_ptr, "--exclude");
  1113. g_ptr_array_add(argv_ptr, escaped);
  1114. } else {
  1115. fprintf(exclude,"%s\n", escaped);
  1116. entry_in_exclude++;
  1117. amfree(escaped);
  1118. }
  1119. }
  1120. fclose(exclude);
  1121. fclose(exclude_list);
  1122. g_ptr_array_add(argv_ptr, g_strdup("--exclude-from"));
  1123. g_ptr_array_add(argv_ptr, exclude_filename);
  1124. }
  1125. if (argument->exclude_list_glob) {
  1126. g_ptr_array_add(argv_ptr, g_strdup("--exclude-from"));
  1127. g_ptr_array_add(argv_ptr, g_strdup(argument->exclude_list_glob));
  1128. }
  1129. {
  1130. GPtrArray *argv_include = g_ptr_array_new();
  1131. FILE *include;
  1132. char *sdisk;
  1133. int in_argv;
  1134. guint i;
  1135. int entry_in_include = 0;
  1136. if (argument->dle.disk) {
  1137. sdisk = sanitise_filename(argument->dle.disk);
  1138. } else {
  1139. sdisk = g_strdup_printf("no_dle-%d", getpid());
  1140. }
  1141. include_filename = g_strjoin(NULL, AMANDA_TMPDIR, "/", "include-", sdisk, NULL);
  1142. include = fopen(include_filename, "w");
  1143. if (!include) {
  1144. fprintf(stderr, "Cannot open include file '%s': %s\n",
  1145. include_filename, strerror(errno));
  1146. error("Cannot open include file '%s': %s\n",
  1147. include_filename, strerror(errno));
  1148. /*NOTREACHED*/
  1149. }
  1150. if (argument->dle.include_list &&
  1151. argument->dle.include_list->nb_element == 1) {
  1152. char line[2*PATH_MAX];
  1153. FILE *include_list = fopen(argument->dle.include_list->first->name, "r");
  1154. if (!include_list) {
  1155. fclose(include);
  1156. fprintf(stderr, "Cannot open include file '%s': %s\n",
  1157. argument->dle.include_list->first->name,
  1158. strerror(errno));
  1159. error("Cannot open include file '%s': %s\n",
  1160. argument->dle.include_list->first->name,
  1161. strerror(errno));
  1162. /*NOTREACHED*/
  1163. }
  1164. while (fgets(line, 2*PATH_MAX, include_list)) {
  1165. char *escaped;
  1166. line[strlen(line)-1] = '\0'; /* remove '\n' */
  1167. escaped = escape_tar_glob(line, &in_argv);
  1168. if (in_argv) {
  1169. g_ptr_array_add(argv_include, escaped);
  1170. } else {
  1171. fprintf(include,"%s\n", escaped);
  1172. entry_in_include++;
  1173. amfree(escaped);
  1174. }
  1175. }
  1176. fclose(include_list);
  1177. }
  1178. for (j=1; j< argument->argc; j++) {
  1179. char *escaped = escape_tar_glob(argument->argv[j], &in_argv);
  1180. if (in_argv) {
  1181. g_ptr_array_add(argv_include, escaped);
  1182. } else {
  1183. fprintf(include,"%s\n", escaped);
  1184. entry_in_include++;
  1185. amfree(escaped);
  1186. }
  1187. }
  1188. fclose(include);
  1189. if (entry_in_include) {
  1190. g_ptr_array_add(argv_ptr, g_strdup("--files-from"));
  1191. g_ptr_array_add(argv_ptr, include_filename);
  1192. }
  1193. if (argument->include_list_glob) {
  1194. g_ptr_array_add(argv_ptr, g_strdup("--files-from"));
  1195. g_ptr_array_add(argv_ptr, g_strdup(argument->include_list_glob));
  1196. }
  1197. for (i = 0; i < argv_include->len; i++) {
  1198. g_ptr_array_add(argv_ptr, (char *)g_ptr_array_index(argv_include,i));
  1199. }
  1200. }
  1201. g_ptr_array_add(argv_ptr, NULL);
  1202. debug_executing(argv_ptr);
  1203. tarpid = fork();
  1204. switch (tarpid) {
  1205. case -1: error(_("%s: fork returned: %s"), get_pname(), strerror(errno));
  1206. case 0:
  1207. env = safe_env();
  1208. become_root();
  1209. execve(cmd, (char **)argv_ptr->pdata, env);
  1210. e = strerror(errno);
  1211. error(_("error [exec %s: %s]"), cmd, e);
  1212. break;
  1213. default: break;
  1214. }
  1215. waitpid(tarpid, NULL, 0);
  1216. if (argument->verbose == 0) {
  1217. if (exclude_filename)
  1218. unlink(exclude_filename);
  1219. if (include_filename)
  1220. unlink(include_filename);
  1221. }
  1222. amfree(cmd);
  1223. amfree(include_filename);
  1224. amfree(exclude_filename);
  1225. }
  1226. static void
  1227. amgtar_validate(
  1228. application_argument_t *argument G_GNUC_UNUSED)
  1229. {
  1230. char *cmd = NULL;
  1231. GPtrArray *argv_ptr = g_ptr_array_new();
  1232. char **env;
  1233. char *e;
  1234. char buf[32768];
  1235. if (!gnutar_path) {
  1236. dbprintf("GNUTAR-PATH not set; Piping to /dev/null\n");
  1237. fprintf(stderr,"GNUTAR-PATH not set; Piping to /dev/null\n");
  1238. goto pipe_to_null;
  1239. }
  1240. cmd = g_strdup(gnutar_path);
  1241. g_ptr_array_add(argv_ptr, g_strdup(gnutar_path));
  1242. /* ignore trailing zero blocks on input (this was the default until tar-1.21) */
  1243. g_ptr_array_add(argv_ptr, g_strdup("--ignore-zeros"));
  1244. g_ptr_array_add(argv_ptr, g_strdup("-tf"));
  1245. g_ptr_array_add(argv_ptr, g_strdup("-"));
  1246. g_ptr_array_add(argv_ptr, NULL);
  1247. debug_executing(argv_ptr);
  1248. env = safe_env();
  1249. execve(cmd, (char **)argv_ptr->pdata, env);
  1250. e = strerror(errno);
  1251. dbprintf("failed to execute %s: %s; Piping to /dev/null\n", cmd, e);
  1252. fprintf(stderr,"failed to execute %s: %s; Piping to /dev/null\n", cmd, e);
  1253. pipe_to_null:
  1254. while (read(0, buf, 32768) > 0) {
  1255. }
  1256. amfree(cmd);
  1257. }
  1258. static void
  1259. amgtar_build_exinclude(
  1260. dle_t *dle,
  1261. int verbose,
  1262. int *nb_exclude,
  1263. char **file_exclude,
  1264. int *nb_include,
  1265. char **file_include)
  1266. {
  1267. int n_exclude = 0;
  1268. int n_include = 0;
  1269. char *exclude = NULL;
  1270. char *include = NULL;
  1271. if (dle->exclude_file) n_exclude += dle->exclude_file->nb_element;
  1272. if (dle->exclude_list) n_exclude += dle->exclude_list->nb_element;
  1273. if (dle->include_file) n_include += dle->include_file->nb_element;
  1274. if (dle->include_list) n_include += dle->include_list->nb_element;
  1275. if (n_exclude > 0) exclude = build_exclude(dle, verbose);
  1276. if (n_include > 0) include = build_include(dle, verbose);
  1277. if (nb_exclude)
  1278. *nb_exclude = n_exclude;
  1279. if (file_exclude)
  1280. *file_exclude = exclude;
  1281. else
  1282. amfree(exclude);
  1283. if (nb_include)
  1284. *nb_include = n_include;
  1285. if (file_include)
  1286. *file_include = include;
  1287. else
  1288. amfree(include);
  1289. }
  1290. static char *
  1291. amgtar_get_incrname(
  1292. application_argument_t *argument,
  1293. int level,
  1294. FILE *mesgstream,
  1295. int command)
  1296. {
  1297. char *basename = NULL;
  1298. char *incrname = NULL;
  1299. int infd, outfd;
  1300. ssize_t nb;
  1301. char *inputname = NULL;
  1302. char *errmsg = NULL;
  1303. char *buf;
  1304. if (gnutar_listdir) {
  1305. char number[NUM_STR_SIZE];
  1306. int baselevel;
  1307. char *sdisk = sanitise_filename(argument->dle.disk);
  1308. basename = g_strjoin(NULL, gnutar_listdir,
  1309. "/",
  1310. argument->host,
  1311. sdisk,
  1312. NULL);
  1313. amfree(sdisk);
  1314. snprintf(number, sizeof(number), "%d", level);
  1315. incrname = g_strjoin(NULL, basename, "_", number, ".new", NULL);
  1316. unlink(incrname);
  1317. /*
  1318. * Open the listed incremental file from the previous level. Search
  1319. * backward until one is found. If none are found (which will also
  1320. * be true for a level 0), arrange to read from /dev/null.
  1321. */
  1322. baselevel = level;
  1323. infd = -1;
  1324. while (infd == -1) {
  1325. if (--baselevel >= 0) {
  1326. snprintf(number, sizeof(number), "%d", baselevel);
  1327. g_free(inputname);
  1328. inputname = g_strconcat(basename, "_", number, NULL);
  1329. } else {
  1330. g_free(inputname);
  1331. inputname = g_strdup("/dev/null");
  1332. }
  1333. if ((infd = open(inputname, O_RDONLY)) == -1) {
  1334. errmsg = g_strdup_printf(_("amgtar: error opening %s: %s"),
  1335. inputname, strerror(errno));
  1336. dbprintf("%s\n", errmsg);
  1337. if (baselevel < 0) {
  1338. if (command == CMD_ESTIMATE) {
  1339. fprintf(mesgstream, "ERROR %s\n", errmsg);
  1340. } else {
  1341. fprintf(mesgstream, "? %s\n", errmsg);
  1342. }
  1343. exit(1);
  1344. }
  1345. amfree(errmsg);
  1346. }
  1347. }
  1348. /*
  1349. * Copy the previous listed incremental file to the new one.
  1350. */
  1351. if ((outfd = open(incrname, O_WRONLY|O_CREAT, 0600)) == -1) {
  1352. errmsg = g_strdup_printf(_("error opening %s: %s"),
  1353. incrname, strerror(errno));
  1354. dbprintf("%s\n", errmsg);
  1355. if (command == CMD_ESTIMATE) {
  1356. fprintf(mesgstream, "ERROR %s\n", errmsg);
  1357. } else {
  1358. fprintf(mesgstream, "? %s\n", errmsg);
  1359. }
  1360. exit(1);
  1361. }
  1362. while ((nb = read(infd, &buf, sizeof(buf))) > 0) {
  1363. if (full_write(outfd, &buf, (size_t)nb) < (size_t)nb) {
  1364. errmsg = g_strdup_printf(_("writing to %s: %s"),
  1365. incrname, strerror(errno));
  1366. dbprintf("%s\n", errmsg);
  1367. amfree(incrname);
  1368. amfree(inputname);
  1369. amfree(basename);
  1370. amfree(errmsg);
  1371. dbprintf("%s\n", errmsg);
  1372. if (command == CMD_ESTIMATE) {
  1373. fprintf(mesgstream, "ERROR %s\n", errmsg);
  1374. } else {
  1375. fprintf(mesgstream, "? %s\n", errmsg);
  1376. }
  1377. exit(1);
  1378. }
  1379. }
  1380. if (nb < 0) {
  1381. errmsg = g_strdup_printf(_("reading from %s: %s"),
  1382. inputname, strerror(errno));
  1383. dbprintf("%s\n", errmsg);
  1384. amfree(incrname);
  1385. amfree(inputname);
  1386. amfree(basename);
  1387. amfree(errmsg);
  1388. dbprintf("%s\n", errmsg);
  1389. if (command == CMD_ESTIMATE) {
  1390. fprintf(mesgstream, "ERROR %s\n", errmsg);
  1391. } else {
  1392. fprintf(mesgstream, "? %s\n", errmsg);
  1393. }
  1394. exit(1);
  1395. }
  1396. if (close(infd) != 0) {
  1397. errmsg = g_strdup_printf(_("closing %s: %s"),
  1398. inputname, strerror(errno));
  1399. dbprintf("%s\n", errmsg);
  1400. amfree(incrname);
  1401. amfree(inputname);
  1402. amfree(basename);
  1403. amfree(errmsg);
  1404. dbprintf("%s\n", errmsg);
  1405. if (command == CMD_ESTIMATE) {
  1406. fprintf(mesgstream, "ERROR %s\n", errmsg);
  1407. } else {
  1408. fprintf(mesgstream, "? %s\n", errmsg);
  1409. }
  1410. exit(1);
  1411. }
  1412. if (close(outfd) != 0) {
  1413. errmsg = g_strdup_printf(_("closing %s: %s"),
  1414. incrname, strerror(errno));
  1415. dbprintf("%s\n", errmsg);
  1416. amfree(incrname);
  1417. amfree(inputname);
  1418. amfree(basename);
  1419. amfree(errmsg);
  1420. dbprintf("%s\n", errmsg);
  1421. if (command == CMD_ESTIMATE) {
  1422. fprintf(mesgstream, "ERROR %s\n", errmsg);
  1423. } else {
  1424. fprintf(mesgstream, "? %s\n", errmsg);
  1425. }
  1426. exit(1);
  1427. }
  1428. amfree(inputname);
  1429. amfree(basename);
  1430. } else {
  1431. errmsg = _("GNUTAR-LISTDIR is not defined");
  1432. dbprintf("%s\n", errmsg);
  1433. if (command == CMD_ESTIMATE) {
  1434. fprintf(mesgstream, "ERROR %s\n", errmsg);
  1435. } else {
  1436. fprintf(mesgstream, "? %s\n", errmsg);
  1437. }
  1438. exit(1);
  1439. }
  1440. return incrname;
  1441. }
  1442. GPtrArray *amgtar_build_argv(
  1443. application_argument_t *argument,
  1444. char *incrname,
  1445. char **file_exclude,
  1446. char **file_include,
  1447. int command)
  1448. {
  1449. int nb_exclude;
  1450. int nb_include;
  1451. char *dirname;
  1452. char tmppath[PATH_MAX];
  1453. GPtrArray *argv_ptr = g_ptr_array_new();
  1454. GSList *copt;
  1455. amgtar_build_exinclude(&argument->dle, 1,
  1456. &nb_exclude, file_exclude,
  1457. &nb_include, file_include);
  1458. if (gnutar_directory) {
  1459. dirname = gnutar_directory;
  1460. } else {
  1461. dirname = argument->dle.device;
  1462. }
  1463. g_ptr_array_add(argv_ptr, g_strdup(gnutar_path));
  1464. g_ptr_array_add(argv_ptr, g_strdup("--create"));
  1465. if (command == CMD_BACKUP && argument->dle.create_index)
  1466. g_ptr_array_add(argv_ptr, g_strdup("--verbose"));
  1467. g_ptr_array_add(argv_ptr, g_strdup("--file"));
  1468. if (command == CMD_ESTIMATE) {
  1469. g_ptr_array_add(argv_ptr, g_strdup("/dev/null"));
  1470. } else {
  1471. g_ptr_array_add(argv_ptr, g_strdup("-"));
  1472. }
  1473. if (gnutar_no_unquote)
  1474. g_ptr_array_add(argv_ptr, g_strdup("--no-unquote"));
  1475. g_ptr_array_add(argv_ptr, g_strdup("--directory"));
  1476. canonicalize_pathname(dirname, tmppath);
  1477. g_ptr_array_add(argv_ptr, g_strdup(tmppath));
  1478. if (gnutar_onefilesystem)
  1479. g_ptr_array_add(argv_ptr, g_strdup("--one-file-system"));
  1480. if (gnutar_atimepreserve)
  1481. g_ptr_array_add(argv_ptr, g_strdup("--atime-preserve=system"));
  1482. if (!gnutar_checkdevice)
  1483. g_ptr_array_add(argv_ptr, g_strdup("--no-check-device"));
  1484. if (gnutar_acls)
  1485. g_ptr_array_add(argv_ptr, g_strdup("--acls"));
  1486. if (gnutar_selinux)
  1487. g_ptr_array_add(argv_ptr, g_strdup("--selinux"));
  1488. if (gnutar_xattrs)
  1489. g_ptr_array_add(argv_ptr, g_strdup("--xattrs"));
  1490. g_ptr_array_add(argv_ptr, g_strdup("--listed-incremental"));
  1491. g_ptr_array_add(argv_ptr, g_strdup(incrname));
  1492. if (gnutar_sparse)
  1493. g_ptr_array_add(argv_ptr, g_strdup("--sparse"));
  1494. if (argument->tar_blocksize) {
  1495. g_ptr_array_add(argv_ptr, g_strdup("--blocking-factor"));
  1496. g_ptr_array_add(argv_ptr, g_strdup(argument->tar_blocksize));
  1497. }
  1498. g_ptr_array_add(argv_ptr, g_strdup("--ignore-failed-read"));
  1499. g_ptr_array_add(argv_ptr, g_strdup("--totals"));
  1500. for (copt = argument->command_options; copt != NULL; copt = copt->next) {
  1501. g_ptr_array_add(argv_ptr, g_strdup((char *)copt->data));
  1502. }
  1503. if (*file_exclude) {
  1504. g_ptr_array_add(argv_ptr, g_strdup("--exclude-from"));
  1505. g_ptr_array_add(argv_ptr, g_strdup(*file_exclude));
  1506. }
  1507. if (*file_include) {
  1508. g_ptr_array_add(argv_ptr, g_strdup("--files-from"));
  1509. g_ptr_array_add(argv_ptr, g_strdup(*file_include));
  1510. }
  1511. else {
  1512. g_ptr_array_add(argv_ptr, g_strdup("."));
  1513. }
  1514. g_ptr_array_add(argv_ptr, NULL);
  1515. return(argv_ptr);
  1516. }