PageRenderTime 53ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/amanda/tags/3_1_5/application-src/amstar.c

#
C | 1007 lines | 824 code | 115 blank | 68 comment | 205 complexity | fe8aee2fb59ad871b45412199f644909 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: amstar.c 8888 2007-10-02 13:40:42Z martineau $
  28. *
  29. * send estimated backup sizes using dump
  30. */
  31. /* PROPERTY:
  32. *
  33. * STAR-PATH (default STAR)
  34. * STAR-TARDUMP
  35. * STAR-DLE-TARDUMP
  36. * ONE-FILE-SYSTEM
  37. * SPARSE
  38. * NORMAL
  39. * IGNORE
  40. * STRANGE
  41. * INCLUDE-LIST (for restore only)
  42. * EXCLUDE-LIST (for restore only)
  43. * DIRECTORY
  44. */
  45. #include "amanda.h"
  46. #include "match.h"
  47. #include "pipespawn.h"
  48. #include "amfeatures.h"
  49. #include "amandates.h"
  50. #include "clock.h"
  51. #include "util.h"
  52. #include "getfsent.h"
  53. #include "client_util.h"
  54. #include "conffile.h"
  55. #include "getopt.h"
  56. #include "sendbackup.h"
  57. int debug_application = 1;
  58. #define application_debug(i, ...) do { \
  59. if ((i) <= debug_application) { \
  60. dbprintf(__VA_ARGS__); \
  61. } \
  62. } while (0)
  63. static amregex_t init_re_table[] = {
  64. /* tar prints the size in bytes */
  65. AM_SIZE_RE("star: [0-9][0-9]* blocks", 10240, 1),
  66. AM_NORMAL_RE("^could not open conf file"),
  67. AM_NORMAL_RE("^Type of this level "),
  68. AM_NORMAL_RE("^Date of this level "),
  69. AM_NORMAL_RE("^Date of last level "),
  70. AM_NORMAL_RE("^Dump record level "),
  71. AM_NORMAL_RE("^Throughput"),
  72. AM_NORMAL_RE("^.*is sparse$"),
  73. #ifdef IGNORE_TAR_ERRORS
  74. AM_NORMAL_RE("^.*shrunk*$"),
  75. AM_NORMAL_RE("^.*changed size.*$"),
  76. AM_NORMAL_RE("^.*Cannot listxattr for.*$"),
  77. AM_NORMAL_RE("^.Cannot: stat .*$"),
  78. AM_NORMAL_RE("^.Missing links .*$"),
  79. AM_NORMAL_RE("^.Cannot get xattr.*$"),
  80. AM_NORMAL_RE("^.Cannot.*acl.*$"),
  81. #endif
  82. AM_NORMAL_RE("^star: dumped [0-9][0-9]* (tar )?files"),
  83. AM_NORMAL_RE("^.*The following problems occurred during .* processing.*$"),
  84. AM_NORMAL_RE("^.*Processed all possible files, despite earlier errors.*$"),
  85. AM_NORMAL_RE("^.*not written due to problems during backup.*$"),
  86. AM_STRANGE_RE("^Perform a level 0 dump first.*$"),
  87. /* catch-all: DMP_STRANGE is returned for all other lines */
  88. AM_STRANGE_RE(NULL)
  89. };
  90. static amregex_t *re_table;
  91. /* local functions */
  92. int main(int argc, char **argv);
  93. typedef struct application_argument_s {
  94. char *config;
  95. char *host;
  96. int message;
  97. int collection;
  98. int calcsize;
  99. GSList *level;
  100. GSList *command_options;
  101. dle_t dle;
  102. int argc;
  103. char **argv;
  104. } application_argument_t;
  105. enum { CMD_ESTIMATE, CMD_BACKUP };
  106. static void amstar_support(application_argument_t *argument);
  107. static void amstar_selfcheck(application_argument_t *argument);
  108. static void amstar_estimate(application_argument_t *argument);
  109. static void amstar_backup(application_argument_t *argument);
  110. static void amstar_restore(application_argument_t *argument);
  111. static void amstar_validate(application_argument_t *argument);
  112. static GPtrArray *amstar_build_argv(application_argument_t *argument,
  113. int level,
  114. int command);
  115. static char *star_path;
  116. static char *star_tardumps;
  117. static int star_dle_tardumps;
  118. static int star_onefilesystem;
  119. static int star_sparse;
  120. static int star_acl;
  121. static char *star_directory;
  122. static GSList *normal_message = NULL;
  123. static GSList *ignore_message = NULL;
  124. static GSList *strange_message = NULL;
  125. static struct option long_options[] = {
  126. {"config" , 1, NULL, 1},
  127. {"host" , 1, NULL, 2},
  128. {"disk" , 1, NULL, 3},
  129. {"device" , 1, NULL, 4},
  130. {"level" , 1, NULL, 5},
  131. {"index" , 1, NULL, 6},
  132. {"message" , 1, NULL, 7},
  133. {"collection" , 0, NULL, 8},
  134. {"record" , 0, NULL, 9},
  135. {"star-path" , 1, NULL, 10},
  136. {"star-tardump" , 1, NULL, 11},
  137. {"star-dle-tardump", 1, NULL, 12},
  138. {"one-file-system" , 1, NULL, 13},
  139. {"sparse" , 1, NULL, 14},
  140. {"calcsize" , 0, NULL, 15},
  141. {"normal" , 1, NULL, 16},
  142. {"ignore" , 1, NULL, 17},
  143. {"strange" , 1, NULL, 18},
  144. {"include-list" , 1, NULL, 19},
  145. {"exclude-list" , 1, NULL, 20},
  146. {"directory" , 1, NULL, 21},
  147. {"command-options" , 1, NULL, 22},
  148. {"acl" , 1, NULL, 24},
  149. { NULL, 0, NULL, 0}
  150. };
  151. int
  152. main(
  153. int argc,
  154. char ** argv)
  155. {
  156. int c;
  157. char *command;
  158. application_argument_t argument;
  159. #ifdef STAR
  160. star_path = STAR;
  161. #else
  162. star_path = NULL;
  163. #endif
  164. star_tardumps = "/etc/tardumps";
  165. star_dle_tardumps = 0;
  166. star_onefilesystem = 1;
  167. star_sparse = 1;
  168. star_acl = 1;
  169. star_directory = NULL;
  170. /* initialize */
  171. /*
  172. * Configure program for internationalization:
  173. * 1) Only set the message locale for now.
  174. * 2) Set textdomain for all amanda related programs to "amanda"
  175. * We don't want to be forced to support dozens of message catalogs.
  176. */
  177. setlocale(LC_MESSAGES, "C");
  178. textdomain("amanda");
  179. if (argc < 2) {
  180. printf("ERROR no command given to amstar\n");
  181. error(_("No command given to amstar"));
  182. }
  183. /* drop root privileges */
  184. if (!set_root_privs(0)) {
  185. if (strcmp(argv[1], "selfcheck") == 0) {
  186. printf("ERROR amstar must be run setuid root\n");
  187. }
  188. error(_("amstar must be run setuid root"));
  189. }
  190. safe_fd(3, 2);
  191. set_pname("amstar");
  192. /* Don't die when child closes pipe */
  193. signal(SIGPIPE, SIG_IGN);
  194. #if defined(USE_DBMALLOC)
  195. malloc_size_1 = malloc_inuse(&malloc_hist_1);
  196. #endif
  197. add_amanda_log_handler(amanda_log_stderr);
  198. add_amanda_log_handler(amanda_log_syslog);
  199. dbopen(DBG_SUBDIR_CLIENT);
  200. startclock();
  201. dbprintf(_("version %s\n"), VERSION);
  202. config_init(CONFIG_INIT_CLIENT, NULL);
  203. //check_running_as(RUNNING_AS_DUMPUSER_PREFERRED);
  204. //root for amrecover
  205. //RUNNING_AS_CLIENT_LOGIN from selfcheck, sendsize, sendbackup
  206. /* parse argument */
  207. command = argv[1];
  208. argument.config = NULL;
  209. argument.host = NULL;
  210. argument.message = 0;
  211. argument.collection = 0;
  212. argument.calcsize = 0;
  213. argument.level = NULL;
  214. argument.command_options = NULL;
  215. init_dle(&argument.dle);
  216. opterr = 0;
  217. while (1) {
  218. int option_index = 0;
  219. c = getopt_long (argc, argv, "", long_options, &option_index);
  220. if (c == -1)
  221. break;
  222. switch (c) {
  223. case 1: argument.config = stralloc(optarg);
  224. break;
  225. case 2: argument.host = stralloc(optarg);
  226. break;
  227. case 3: argument.dle.disk = stralloc(optarg);
  228. break;
  229. case 4: argument.dle.device = stralloc(optarg);
  230. break;
  231. case 5: argument.level = g_slist_append(argument.level,
  232. GINT_TO_POINTER(atoi(optarg)));
  233. break;
  234. case 6: argument.dle.create_index = 1;
  235. break;
  236. case 7: argument.message = 1;
  237. break;
  238. case 8: argument.collection = 1;
  239. break;
  240. case 9: argument.dle.record = 1;
  241. break;
  242. case 10: star_path = stralloc(optarg);
  243. break;
  244. case 11: star_tardumps = stralloc(optarg);
  245. break;
  246. case 12: if (optarg && strcasecmp(optarg, "NO") == 0)
  247. star_dle_tardumps = 0;
  248. else if (optarg && strcasecmp(optarg, "YES") == 0)
  249. star_dle_tardumps = 1;
  250. else if (strcasecmp(command, "selfcheck") == 0)
  251. printf(_("ERROR [%s: bad STAR-DLE-TARDUMP property value (%s)]\n"), get_pname(), optarg);
  252. break;
  253. case 13: if (optarg && strcasecmp(optarg, "YES") != 0) {
  254. /* This option is required to be YES */
  255. /* star_onefilesystem = 0; */
  256. }
  257. break;
  258. case 14: if (optarg && strcasecmp(optarg, "NO") == 0)
  259. star_sparse = 0;
  260. else if (optarg && strcasecmp(optarg, "YES") == 0)
  261. star_sparse = 1;
  262. else if (strcasecmp(command, "selfcheck") == 0)
  263. printf(_("ERROR [%s: bad SPARSE property value (%s)]\n"), get_pname(), optarg);
  264. break;
  265. case 15: argument.calcsize = 1;
  266. break;
  267. case 16: if (optarg)
  268. normal_message =
  269. g_slist_append(normal_message, optarg);
  270. break;
  271. case 17: if (optarg)
  272. ignore_message =
  273. g_slist_append(ignore_message, optarg);
  274. break;
  275. case 18: if (optarg)
  276. strange_message =
  277. g_slist_append(strange_message, optarg);
  278. break;
  279. case 19: if (optarg)
  280. argument.dle.include_list =
  281. append_sl(argument.dle.include_list, optarg);
  282. break;
  283. case 20: if (optarg)
  284. argument.dle.exclude_list =
  285. append_sl(argument.dle.exclude_list, optarg);
  286. break;
  287. case 21: if (optarg)
  288. star_directory = stralloc(optarg);
  289. break;
  290. case 22: argument.command_options =
  291. g_slist_append(argument.command_options,
  292. stralloc(optarg));
  293. case 24: if (optarg && strcasecmp(optarg, "NO") == 0)
  294. star_acl = 0;
  295. else if (optarg && strcasecmp(optarg, "YES") == 0)
  296. star_acl = 1;
  297. else if (strcasecmp(command, "selfcheck") == 0)
  298. printf(_("ERROR [%s: bad ACL property value (%s)]\n"), get_pname(), optarg);
  299. break;
  300. case ':':
  301. case '?':
  302. break;
  303. }
  304. }
  305. if (!argument.dle.disk && argument.dle.device)
  306. argument.dle.disk = stralloc(argument.dle.device);
  307. if (!argument.dle.device && argument.dle.disk)
  308. argument.dle.device = stralloc(argument.dle.disk);
  309. argument.argc = argc - optind;
  310. argument.argv = argv + optind;
  311. if (argument.config) {
  312. /* overlay this configuration on the existing (nameless) configuration */
  313. config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY,
  314. argument.config);
  315. dbrename(get_config_name(), DBG_SUBDIR_CLIENT);
  316. }
  317. if (config_errors(NULL) >= CFGERR_ERRORS) {
  318. g_critical(_("errors processing config file"));
  319. }
  320. re_table = build_re_table(init_re_table, normal_message, ignore_message,
  321. strange_message);
  322. if (strcmp(command, "support") == 0) {
  323. amstar_support(&argument);
  324. } else if (strcmp(command, "selfcheck") == 0) {
  325. amstar_selfcheck(&argument);
  326. } else if (strcmp(command, "estimate") == 0) {
  327. amstar_estimate(&argument);
  328. } else if (strcmp(command, "backup") == 0) {
  329. amstar_backup(&argument);
  330. } else if (strcmp(command, "restore") == 0) {
  331. amstar_restore(&argument);
  332. } else if (strcmp(command, "validate") == 0) {
  333. amstar_validate(&argument);
  334. } else {
  335. fprintf(stderr, "Unknown command `%s'.\n", command);
  336. exit (1);
  337. }
  338. return 0;
  339. }
  340. static void
  341. amstar_support(
  342. application_argument_t *argument)
  343. {
  344. (void)argument;
  345. fprintf(stdout, "CONFIG YES\n");
  346. fprintf(stdout, "HOST YES\n");
  347. fprintf(stdout, "DISK YES\n");
  348. fprintf(stdout, "MAX-LEVEL 9\n");
  349. fprintf(stdout, "INDEX-LINE YES\n");
  350. fprintf(stdout, "INDEX-XML NO\n");
  351. fprintf(stdout, "MESSAGE-LINE YES\n");
  352. fprintf(stdout, "MESSAGE-XML NO\n");
  353. fprintf(stdout, "RECORD YES\n");
  354. fprintf(stdout, "INCLUDE-FILE NO\n");
  355. fprintf(stdout, "INCLUDE-LIST YES\n");
  356. fprintf(stdout, "EXCLUDE-FILE YES\n");
  357. fprintf(stdout, "EXCLUDE-LIST YES\n");
  358. fprintf(stdout, "COLLECTION NO\n");
  359. fprintf(stdout, "MULTI-ESTIMATE YES\n");
  360. fprintf(stdout, "CALCSIZE YES\n");
  361. fprintf(stdout, "CLIENT-ESTIMATE YES\n");
  362. }
  363. static void
  364. amstar_selfcheck(
  365. application_argument_t *argument)
  366. {
  367. fprintf(stdout, "OK amstar\n");
  368. if (argument->dle.disk) {
  369. char *qdisk = quote_string(argument->dle.disk);
  370. fprintf(stdout, "OK %s\n", qdisk);
  371. amfree(qdisk);
  372. }
  373. if (argument->dle.device) {
  374. char *qdevice = quote_string(argument->dle.device);
  375. fprintf(stdout, "OK %s\n", qdevice);
  376. amfree(qdevice);
  377. }
  378. if (star_directory) {
  379. char *qdirectory = quote_string(star_directory);
  380. fprintf(stdout, "OK %s\n", qdirectory);
  381. amfree(qdirectory);
  382. }
  383. if (argument->dle.include_list &&
  384. argument->dle.include_list->nb_element >= 0) {
  385. fprintf(stdout, "ERROR include-list not supported for backup\n");
  386. }
  387. if (argument->dle.exclude_list &&
  388. argument->dle.exclude_list->nb_element >= 0) {
  389. fprintf(stdout, "ERROR exclude-list not supported for backup\n");
  390. }
  391. if (!star_path) {
  392. fprintf(stdout, "ERROR STAR-PATH not defined\n");
  393. } else {
  394. check_file(star_path, X_OK);
  395. }
  396. if (argument->calcsize) {
  397. char *calcsize = vstralloc(amlibexecdir, "/", "calcsize", NULL);
  398. check_file(calcsize, X_OK);
  399. check_suid(calcsize);
  400. amfree(calcsize);
  401. }
  402. {
  403. char *amandates_file;
  404. amandates_file = getconf_str(CNF_AMANDATES);
  405. check_file(amandates_file, R_OK|W_OK);
  406. }
  407. }
  408. static void
  409. amstar_estimate(
  410. application_argument_t *argument)
  411. {
  412. GPtrArray *argv_ptr;
  413. char *cmd = NULL;
  414. int nullfd;
  415. int pipefd;
  416. FILE *dumpout = NULL;
  417. off_t size = -1;
  418. char line[32768];
  419. char *errmsg = NULL;
  420. char *qerrmsg;
  421. char *qdisk;
  422. amwait_t wait_status;
  423. int starpid;
  424. amregex_t *rp;
  425. times_t start_time;
  426. int level = 0;
  427. GSList *levels = NULL;
  428. if (!argument->level) {
  429. fprintf(stderr, "ERROR No level argument\n");
  430. error(_("No level argument"));
  431. }
  432. if (!argument->dle.disk) {
  433. fprintf(stderr, "ERROR No disk argument\n");
  434. error(_("No disk argument"));
  435. }
  436. if (!argument->dle.device) {
  437. fprintf(stderr, "ERROR No device argument\n");
  438. error(_("No device argument"));
  439. }
  440. if (argument->dle.include_list &&
  441. argument->dle.include_list->nb_element >= 0) {
  442. fprintf(stderr, "ERROR include-list not supported for backup\n");
  443. }
  444. if (argument->dle.exclude_list &&
  445. argument->dle.exclude_list->nb_element >= 0) {
  446. fprintf(stderr, "ERROR exclude-list not supported for backup\n");
  447. }
  448. qdisk = quote_string(argument->dle.disk);
  449. if (argument->calcsize) {
  450. char *dirname;
  451. if (star_directory) {
  452. dirname = amname_to_dirname(star_directory);
  453. } else {
  454. dirname = amname_to_dirname(argument->dle.device);
  455. }
  456. run_calcsize(argument->config, "STAR", argument->dle.disk, dirname,
  457. argument->level, NULL, NULL);
  458. return;
  459. }
  460. if (!star_path) {
  461. errmsg = vstrallocf(_("STAR-PATH not defined"));
  462. goto common_error;
  463. }
  464. cmd = stralloc(star_path);
  465. start_time = curclock();
  466. for (levels = argument->level; levels != NULL; levels = levels->next) {
  467. level = GPOINTER_TO_INT(levels->data);
  468. argv_ptr = amstar_build_argv(argument, level, CMD_ESTIMATE);
  469. if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
  470. errmsg = vstrallocf(_("Cannot access /dev/null : %s"),
  471. strerror(errno));
  472. goto common_error;
  473. }
  474. starpid = pipespawnv(cmd, STDERR_PIPE, 1,
  475. &nullfd, &nullfd, &pipefd,
  476. (char **)argv_ptr->pdata);
  477. dumpout = fdopen(pipefd,"r");
  478. if (!dumpout) {
  479. errmsg = vstrallocf(_("Can't fdopen: %s"), strerror(errno));
  480. goto common_error;
  481. }
  482. size = (off_t)-1;
  483. while (size < 0 && (fgets(line, sizeof(line), dumpout)) != NULL) {
  484. if (line[strlen(line)-1] == '\n') /* remove trailling \n */
  485. line[strlen(line)-1] = '\0';
  486. if (line[0] == '\0')
  487. continue;
  488. dbprintf("%s\n", line);
  489. /* check for size match */
  490. /*@ignore@*/
  491. for(rp = re_table; rp->regex != NULL; rp++) {
  492. if(match(rp->regex, line)) {
  493. if (rp->typ == DMP_SIZE) {
  494. size = ((the_num(line, rp->field)*rp->scale+1023.0)/1024.0);
  495. if(size < 0.0)
  496. size = 1.0; /* found on NeXT -- sigh */
  497. }
  498. break;
  499. }
  500. }
  501. /*@end@*/
  502. }
  503. while ((fgets(line, sizeof(line), dumpout)) != NULL) {
  504. dbprintf("%s", line);
  505. }
  506. dbprintf(".....\n");
  507. dbprintf(_("estimate time for %s level %d: %s\n"),
  508. qdisk,
  509. level,
  510. walltime_str(timessub(curclock(), start_time)));
  511. if(size == (off_t)-1) {
  512. errmsg = vstrallocf(_("no size line match in %s output"),
  513. cmd);
  514. dbprintf(_("%s for %s\n"), errmsg, qdisk);
  515. dbprintf(".....\n");
  516. } else if(size == (off_t)0 && argument->level == 0) {
  517. dbprintf(_("possible %s problem -- is \"%s\" really empty?\n"),
  518. cmd, argument->dle.disk);
  519. dbprintf(".....\n");
  520. }
  521. dbprintf(_("estimate size for %s level %d: %lld KB\n"),
  522. qdisk,
  523. level,
  524. (long long)size);
  525. kill(-starpid, SIGTERM);
  526. dbprintf(_("waiting for %s \"%s\" child\n"), cmd, qdisk);
  527. waitpid(starpid, &wait_status, 0);
  528. if (WIFSIGNALED(wait_status)) {
  529. errmsg = vstrallocf(_("%s terminated with signal %d: see %s"),
  530. cmd, WTERMSIG(wait_status), dbfn());
  531. } else if (WIFEXITED(wait_status)) {
  532. if (WEXITSTATUS(wait_status) != 0) {
  533. errmsg = vstrallocf(_("%s exited with status %d: see %s"),
  534. cmd, WEXITSTATUS(wait_status), dbfn());
  535. } else {
  536. /* Normal exit */
  537. }
  538. } else {
  539. errmsg = vstrallocf(_("%s got bad exit: see %s"), cmd, dbfn());
  540. }
  541. dbprintf(_("after %s %s wait\n"), cmd, qdisk);
  542. g_ptr_array_free_full(argv_ptr);
  543. aclose(nullfd);
  544. afclose(dumpout);
  545. fprintf(stdout, "%d %lld 1\n", level, (long long)size);
  546. }
  547. amfree(qdisk);
  548. amfree(cmd);
  549. return;
  550. common_error:
  551. dbprintf("%s\n", errmsg);
  552. qerrmsg = quote_string(errmsg);
  553. amfree(qdisk);
  554. dbprintf("%s", errmsg);
  555. fprintf(stdout, "ERROR %s\n", qerrmsg);
  556. amfree(errmsg);
  557. amfree(qerrmsg);
  558. amfree(cmd);
  559. }
  560. static void
  561. amstar_backup(
  562. application_argument_t *argument)
  563. {
  564. int dumpin;
  565. char *cmd = NULL;
  566. char *qdisk;
  567. char line[32768];
  568. amregex_t *rp;
  569. off_t dump_size = -1;
  570. char *type;
  571. char startchr;
  572. GPtrArray *argv_ptr;
  573. int starpid;
  574. int dataf = 1;
  575. int mesgf = 3;
  576. int indexf = 4;
  577. int outf;
  578. FILE *mesgstream;
  579. FILE *indexstream = NULL;
  580. FILE *outstream;
  581. int level;
  582. regex_t regex_root;
  583. regex_t regex_dir;
  584. regex_t regex_file;
  585. regex_t regex_special;
  586. regex_t regex_symbolic;
  587. regex_t regex_hard;
  588. mesgstream = fdopen(mesgf, "w");
  589. if (!mesgstream) {
  590. error(_("error mesgstream(%d): %s\n"), mesgf, strerror(errno));
  591. }
  592. if (!argument->level) {
  593. fprintf(mesgstream, "? No level argument\n");
  594. error(_("No level argument"));
  595. }
  596. if (!argument->dle.disk) {
  597. fprintf(mesgstream, "? No disk argument\n");
  598. error(_("No disk argument"));
  599. }
  600. if (!argument->dle.device) {
  601. fprintf(mesgstream, "? No device argument\n");
  602. error(_("No device argument"));
  603. }
  604. if (argument->dle.include_list &&
  605. argument->dle.include_list->nb_element >= 0) {
  606. fprintf(mesgstream, "? include-list not supported for backup\n");
  607. }
  608. if (argument->dle.exclude_list &&
  609. argument->dle.exclude_list->nb_element >= 0) {
  610. fprintf(mesgstream, "? exclude-list not supported for backup\n");
  611. }
  612. level = GPOINTER_TO_INT(argument->level->data);
  613. qdisk = quote_string(argument->dle.disk);
  614. argv_ptr = amstar_build_argv(argument, level, CMD_BACKUP);
  615. cmd = stralloc(star_path);
  616. starpid = pipespawnv(cmd, STDIN_PIPE|STDERR_PIPE, 1,
  617. &dumpin, &dataf, &outf, (char **)argv_ptr->pdata);
  618. g_ptr_array_free_full(argv_ptr);
  619. /* close the write ends of the pipes */
  620. aclose(dumpin);
  621. aclose(dataf);
  622. if (argument->dle.create_index) {
  623. indexstream = fdopen(indexf, "w");
  624. if (!indexstream) {
  625. error(_("error indexstream(%d): %s\n"), indexf, strerror(errno));
  626. }
  627. }
  628. outstream = fdopen(outf, "r");
  629. if (!outstream) {
  630. error(_("error outstream(%d): %s\n"), outf, strerror(errno));
  631. }
  632. regcomp(&regex_root, "^a \\.\\/ directory$", REG_EXTENDED|REG_NEWLINE);
  633. regcomp(&regex_dir, "^a (.*) directory$", REG_EXTENDED|REG_NEWLINE);
  634. regcomp(&regex_file, "^a (.*) (.*) bytes", REG_EXTENDED|REG_NEWLINE);
  635. regcomp(&regex_special, "^a (.*) special", REG_EXTENDED|REG_NEWLINE);
  636. regcomp(&regex_symbolic, "^a (.*) symbolic", REG_EXTENDED|REG_NEWLINE);
  637. regcomp(&regex_hard, "^a (.*) link to", REG_EXTENDED|REG_NEWLINE);
  638. while ((fgets(line, sizeof(line), outstream)) != NULL) {
  639. regmatch_t regmatch[3];
  640. if (line[strlen(line)-1] == '\n') /* remove trailling \n */
  641. line[strlen(line)-1] = '\0';
  642. if (regexec(&regex_root, line, 1, regmatch, 0) == 0) {
  643. if (argument->dle.create_index)
  644. fprintf(indexstream, "%s\n", "/");
  645. continue;
  646. }
  647. if (regexec(&regex_dir, line, 3, regmatch, 0) == 0) {
  648. if (argument->dle.create_index && regmatch[1].rm_so == 2) {
  649. line[regmatch[1].rm_eo+1]='\0';
  650. fprintf(indexstream, "/%s\n", &line[regmatch[1].rm_so]);
  651. }
  652. continue;
  653. }
  654. if (regexec(&regex_file, line, 3, regmatch, 0) == 0 ||
  655. regexec(&regex_special, line, 3, regmatch, 0) == 0 ||
  656. regexec(&regex_symbolic, line, 3, regmatch, 0) == 0 ||
  657. regexec(&regex_hard, line, 3, regmatch, 0) == 0) {
  658. if (argument->dle.create_index && regmatch[1].rm_so == 2) {
  659. line[regmatch[1].rm_eo]='\0';
  660. fprintf(indexstream, "/%s\n", &line[regmatch[1].rm_so]);
  661. }
  662. continue;
  663. }
  664. for (rp = re_table; rp->regex != NULL; rp++) {
  665. if (match(rp->regex, line)) {
  666. break;
  667. }
  668. }
  669. if (rp->typ == DMP_SIZE) {
  670. dump_size = (off_t)((the_num(line, rp->field)* rp->scale+1023.0)/1024.0);
  671. }
  672. switch (rp->typ) {
  673. case DMP_IGNORE:
  674. continue;
  675. case DMP_NORMAL:
  676. type = "normal";
  677. startchr = '|';
  678. break;
  679. case DMP_STRANGE:
  680. type = "strange";
  681. startchr = '?';
  682. break;
  683. case DMP_SIZE:
  684. type = "size";
  685. startchr = '|';
  686. break;
  687. case DMP_ERROR:
  688. type = "error";
  689. startchr = '?';
  690. break;
  691. default:
  692. type = "unknown";
  693. startchr = '!';
  694. break;
  695. }
  696. dbprintf("%3d: %7s(%c): %s\n", rp->srcline, type, startchr, line);
  697. fprintf(mesgstream,"%c %s\n", startchr, line);
  698. }
  699. regfree(&regex_root);
  700. regfree(&regex_dir);
  701. regfree(&regex_file);
  702. regfree(&regex_special);
  703. regfree(&regex_symbolic);
  704. regfree(&regex_hard);
  705. dbprintf(_("gnutar: %s: pid %ld\n"), cmd, (long)starpid);
  706. dbprintf("sendbackup: size %lld\n", (long long)dump_size);
  707. fprintf(mesgstream, "sendbackup: size %lld\n", (long long)dump_size);
  708. dbprintf("sendbackup: end\n");
  709. fprintf(mesgstream, "sendbackup: end\n");
  710. fclose(mesgstream);
  711. if (argument->dle.create_index)
  712. fclose(indexstream);
  713. amfree(qdisk);
  714. amfree(cmd);
  715. }
  716. static void
  717. amstar_restore(
  718. application_argument_t *argument)
  719. {
  720. char *cmd;
  721. GPtrArray *argv_ptr = g_ptr_array_new();
  722. char **env;
  723. int j;
  724. char *e;
  725. if (!star_path) {
  726. error(_("STAR-PATH not defined"));
  727. }
  728. cmd = stralloc(star_path);
  729. g_ptr_array_add(argv_ptr, stralloc(star_path));
  730. if (star_directory) {
  731. struct stat stat_buf;
  732. if(stat(star_directory, &stat_buf) != 0) {
  733. fprintf(stderr,"can not stat directory %s: %s\n", star_directory, strerror(errno));
  734. exit(1);
  735. }
  736. if (!S_ISDIR(stat_buf.st_mode)) {
  737. fprintf(stderr,"%s is not a directory\n", star_directory);
  738. exit(1);
  739. }
  740. if (access(star_directory, W_OK) != 0 ) {
  741. fprintf(stderr, "Can't write to %s: %s\n", star_directory, strerror(errno));
  742. exit(1);
  743. }
  744. g_ptr_array_add(argv_ptr, stralloc("-C"));
  745. g_ptr_array_add(argv_ptr, stralloc(star_directory));
  746. }
  747. g_ptr_array_add(argv_ptr, stralloc("-x"));
  748. g_ptr_array_add(argv_ptr, stralloc("-v"));
  749. g_ptr_array_add(argv_ptr, stralloc("-xattr"));
  750. g_ptr_array_add(argv_ptr, stralloc("-acl"));
  751. g_ptr_array_add(argv_ptr, stralloc("errctl=WARN|SAMEFILE|SETTIME|DIFF|SETACL|SETXATTR|SETMODE|BADACL *"));
  752. g_ptr_array_add(argv_ptr, stralloc("-no-fifo"));
  753. g_ptr_array_add(argv_ptr, stralloc("-f"));
  754. g_ptr_array_add(argv_ptr, stralloc("-"));
  755. if (argument->dle.exclude_list &&
  756. argument->dle.exclude_list->nb_element == 1) {
  757. g_ptr_array_add(argv_ptr, stralloc("-exclude-from"));
  758. g_ptr_array_add(argv_ptr,
  759. stralloc(argument->dle.exclude_list->first->name));
  760. }
  761. if (argument->dle.include_list &&
  762. argument->dle.include_list->nb_element == 1) {
  763. FILE *include_list = fopen(argument->dle.include_list->first->name, "r");
  764. char line[2*PATH_MAX+2];
  765. while (fgets(line, 2*PATH_MAX, include_list)) {
  766. line[strlen(line)-1] = '\0'; /* remove '\n' */
  767. if (strncmp(line, "./", 2) == 0)
  768. g_ptr_array_add(argv_ptr, stralloc(line+2)); /* remove ./ */
  769. else if (strcmp(line, ".") != 0)
  770. g_ptr_array_add(argv_ptr, stralloc(line));
  771. }
  772. fclose(include_list);
  773. }
  774. for (j=1; j< argument->argc; j++) {
  775. if (strncmp(argument->argv[j], "./", 2) == 0)
  776. g_ptr_array_add(argv_ptr, stralloc(argument->argv[j]+2));/*remove ./ */
  777. else if (strcmp(argument->argv[j], ".") != 0)
  778. g_ptr_array_add(argv_ptr, stralloc(argument->argv[j]));
  779. }
  780. g_ptr_array_add(argv_ptr, NULL);
  781. debug_executing(argv_ptr);
  782. env = safe_env();
  783. become_root();
  784. execve(cmd, (char **)argv_ptr->pdata, env);
  785. e = strerror(errno);
  786. error(_("error [exec %s: %s]"), cmd, e);
  787. }
  788. static void
  789. amstar_validate(
  790. application_argument_t *argument G_GNUC_UNUSED)
  791. {
  792. char *cmd;
  793. GPtrArray *argv_ptr = g_ptr_array_new();
  794. char **env;
  795. char *e;
  796. char buf[32768];
  797. if (!star_path) {
  798. dbprintf("STAR-PATH not set; Piping to /dev/null\n");
  799. fprintf(stderr,"STAR-PATH not set; Piping to /dev/null\n");
  800. goto pipe_to_null;
  801. }
  802. cmd = stralloc(star_path);
  803. g_ptr_array_add(argv_ptr, stralloc(star_path));
  804. g_ptr_array_add(argv_ptr, stralloc("-t"));
  805. g_ptr_array_add(argv_ptr, stralloc("-f"));
  806. g_ptr_array_add(argv_ptr, stralloc("-"));
  807. g_ptr_array_add(argv_ptr, NULL);
  808. debug_executing(argv_ptr);
  809. env = safe_env();
  810. execve(cmd, (char **)argv_ptr->pdata, env);
  811. e = strerror(errno);
  812. dbprintf("failed to execute %s: %s; Piping to /dev/null\n", cmd, e);
  813. fprintf(stderr,"failed to execute %s: %s; Piping to /dev/null\n", cmd, e);
  814. pipe_to_null:
  815. while (read(0, buf, 32768) > 0) {
  816. }
  817. }
  818. static GPtrArray *amstar_build_argv(
  819. application_argument_t *argument,
  820. int level,
  821. int command)
  822. {
  823. char *dirname;
  824. char *fsname;
  825. char levelstr[NUM_STR_SIZE+7];
  826. GPtrArray *argv_ptr = g_ptr_array_new();
  827. char *s;
  828. char *tardumpfile;
  829. GSList *copt;
  830. if (star_directory) {
  831. dirname = amname_to_dirname(star_directory);
  832. } else {
  833. dirname = amname_to_dirname(argument->dle.device);
  834. }
  835. fsname = vstralloc("fs-name=", dirname, NULL);
  836. for (s = fsname; *s != '\0'; s++) {
  837. if (iscntrl((int)*s))
  838. *s = '-';
  839. }
  840. snprintf(levelstr, SIZEOF(levelstr), "-level=%d", level);
  841. if (star_dle_tardumps) {
  842. char *sdisk = sanitise_filename(argument->dle.disk);
  843. tardumpfile = vstralloc(star_tardumps, sdisk, NULL);
  844. amfree(sdisk);
  845. } else {
  846. tardumpfile = stralloc(star_tardumps);
  847. }
  848. g_ptr_array_add(argv_ptr, stralloc(star_path));
  849. g_ptr_array_add(argv_ptr, stralloc("-c"));
  850. g_ptr_array_add(argv_ptr, stralloc("-f"));
  851. if (command == CMD_ESTIMATE) {
  852. g_ptr_array_add(argv_ptr, stralloc("/dev/null"));
  853. } else {
  854. g_ptr_array_add(argv_ptr, stralloc("-"));
  855. }
  856. g_ptr_array_add(argv_ptr, stralloc("-C"));
  857. #if defined(__CYGWIN__)
  858. {
  859. char tmppath[PATH_MAX];
  860. cygwin_conv_to_full_posix_path(dirname, tmppath);
  861. g_ptr_array_add(argv_ptr, stralloc(tmppath));
  862. }
  863. #else
  864. g_ptr_array_add(argv_ptr, stralloc(dirname));
  865. #endif
  866. g_ptr_array_add(argv_ptr, stralloc(fsname));
  867. if (star_onefilesystem)
  868. g_ptr_array_add(argv_ptr, stralloc("-xdev"));
  869. g_ptr_array_add(argv_ptr, stralloc("-link-dirs"));
  870. g_ptr_array_add(argv_ptr, stralloc(levelstr));
  871. g_ptr_array_add(argv_ptr, stralloc2("tardumps=", tardumpfile));
  872. if (command == CMD_BACKUP)
  873. g_ptr_array_add(argv_ptr, stralloc("-wtardumps"));
  874. g_ptr_array_add(argv_ptr, stralloc("-xattr"));
  875. if (star_acl)
  876. g_ptr_array_add(argv_ptr, stralloc("-acl"));
  877. g_ptr_array_add(argv_ptr, stralloc("H=exustar"));
  878. g_ptr_array_add(argv_ptr, stralloc("errctl=WARN|SAMEFILE|DIFF|GROW|SHRINK|SPECIALFILE|GETXATTR|BADACL *"));
  879. if (star_sparse)
  880. g_ptr_array_add(argv_ptr, stralloc("-sparse"));
  881. g_ptr_array_add(argv_ptr, stralloc("-dodesc"));
  882. for (copt = argument->command_options; copt != NULL; copt = copt->next) {
  883. g_ptr_array_add(argv_ptr, stralloc((char *)copt->data));
  884. }
  885. if (command == CMD_BACKUP && argument->dle.create_index)
  886. g_ptr_array_add(argv_ptr, stralloc("-v"));
  887. g_ptr_array_add(argv_ptr, stralloc("."));
  888. g_ptr_array_add(argv_ptr, NULL);
  889. amfree(tardumpfile);
  890. amfree(fsname);
  891. return(argv_ptr);
  892. }