PageRenderTime 68ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

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

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