source: MondoRescue/branches/3.0/mondo/src/common/libmondo-tools.c

Last change on this file was 3192, checked in by Bruno Cornec, 11 years ago
  • revert r3188 & r3189 as I started to work on branch 3.0 before deciding it was much better to do it in 3.2. This will allow some small maintenance work on 3.0 if needed, while pushing all the rest to 3.2 and providing early access to it.
  • Property svn:keywords set to Id
File size: 41.2 KB
Line 
1/*
2 $Id: libmondo-tools.c 3192 2013-09-25 07:03:25Z bruno $
3*/
4
5
6/**
7 * @file
8 * Miscellaneous tools that didn't really fit anywhere else.
9 */
10
11#include "my-stuff.h"
12#include "mr_mem.h"
13#include "mondostructures.h"
14#include "lib-common-externs.h"
15#include "libmondo-tools.h"
16#include "libmondo-gui-EXT.h"
17#include "libmondo-files-EXT.h"
18#include "libmondo-fork-EXT.h"
19#include "libmondo-raid-EXT.h"
20#include "libmondo-devices-EXT.h"
21#include <sys/socket.h>
22#include <netdb.h>
23#include <stdlib.h>
24#include <netinet/in.h>
25#include <arpa/inet.h>
26#include <sys/utsname.h>
27
28/*@unused@*/
29//static char cvsid[] = "$Id: libmondo-tools.c 3192 2013-09-25 07:03:25Z bruno $";
30
31extern int g_tape_buffer_size_MB;
32extern char *g_serial_string;
33extern bool g_text_mode;
34extern int g_currentY;
35extern int g_current_media_number;
36extern char *MONDO_LOGFILE;
37
38/* Reference to global bkpinfo */
39extern struct s_bkpinfo *bkpinfo;
40
41/**
42 * @addtogroup globalGroup
43 * @{
44 */
45bool g_remount_cdrom_at_end, ///< TRUE if we unmounted the CD-ROM and should remount it when done with the backup.
46 g_remount_floppy_at_end; ///< TRUE if we unmounted the floppy and should remount it when done with the backup.
47bool g_cd_recovery; ///< TRUE if we're making an "autonuke" backup.
48double g_kernel_version;
49
50/**
51 * The place where /boot is mounted.
52 */
53char *g_boot_mountpt = NULL;
54
55/**
56 * The location of Mondo's home directory.
57 */
58char *g_mondo_home = NULL;
59
60/**
61 * The serial string (used to differentiate between backups) of the current backup.
62 */
63char *g_serial_string = NULL;
64
65/**
66 * The location where tmpfs is mounted, or "" if it's not mounted.
67char *g_tmpfs_mountpt = NULL;
68 */
69char *g_magicdev_command = NULL;
70
71/**
72 * The default maximum level to log messages at or below.
73 */
74int g_loglevel = DEFAULT_DEBUG_LEVEL;
75
76/* @} - end of globalGroup */
77
78
79extern pid_t g_buffer_pid;
80extern pid_t g_main_pid;
81
82extern t_bkptype g_backup_media_type;
83
84extern bool am_I_in_disaster_recovery_mode(void);
85
86/*-----------------------------------------------------------*/
87
88
89/**
90 * @addtogroup utilityGroup
91 * @{
92 */
93/**
94 * Assertion handler. Prints a friendly message to the user,
95 * offering to ignore all, dump core, break to debugger,
96 * exit, or ignore. Intended to be used with an assert() macro.
97 *
98 * @param file The file in which the assertion triggered.
99 * @param function The function (@c __FUNCTION__) in which the assertion triggered.
100 * @param line The line number of the assert() statement.
101 * @param exp The expression that failed (as a string).
102 */
103void _mondo_assert_fail(const char *file,
104 const char *function, int line, const char *exp)
105{
106 static int ignoring_assertions = 0;
107 bool is_valid = TRUE;
108
109 log_it("ASSERTION FAILED: `%s' at %s:%d in %s", exp, file, line,
110 function);
111 if (ignoring_assertions) {
112 log_it("Well, the user doesn't care...");
113 return;
114 }
115#ifndef _XWIN
116 if (!g_text_mode)
117 newtSuspend();
118#endif
119 printf("ASSERTION FAILED: `%s'\n", exp);
120 printf("\tat %s:%d in %s\n\n", file, line, function);
121 printf("(I)gnore, ignore (A)ll, (D)ebug, a(B)ort, or (E)xit? ");
122 do {
123 is_valid = TRUE;
124 switch (toupper(getchar())) {
125 case 'A': // ignore (A)ll
126 ignoring_assertions = 1;
127 break;
128 case 'B': // a(B)ort
129 signal(SIGABRT, SIG_DFL); /* prevent SIGABRT handler from running */
130 raise(SIGABRT);
131 break; /* "can't get here" */
132 case 'D': // (D)ebug, aka asm("int 3")
133#ifdef __IA32__
134 __asm__ __volatile__("int $3"); // break to debugger
135#endif
136 break;
137 case 'E': // (E)xit
138 fatal_error("Failed assertion -- see above for details");
139 break; /* "can't get here" */
140 case 'I': // (I)gnore
141 break;
142 /* These next two work as follows:
143 the `default' catches the user's invalid choice and says so;
144 the '\n' catches the newline on the end and prints the prompt again.
145 */
146 case '\n':
147 printf
148 ("(I)gnore, ignore (A)ll, (D)ebug, a(B)ort, or (E)xit? ");
149 break;
150 default:
151 is_valid = FALSE;
152 printf("Invalid choice.\n");
153 break;
154 }
155 } while (!is_valid);
156
157 if (ignoring_assertions) {
158 log_it("Ignoring ALL assertions from now on.");
159 } else {
160 log_it("Ignoring assertion: %s", exp);
161 }
162
163 getchar(); // skip \n
164
165#ifndef _XWIN
166 if (!g_text_mode)
167 newtResume();
168#endif
169}
170
171/**
172 * Clean's up users' KDE desktops.
173 * @bug Details about this function are unknown.
174 */
175void clean_up_KDE_desktop_if_necessary(void)
176{
177 char *tmp;
178
179 malloc_string(tmp);
180 strcpy(tmp,
181 "for i in `find /root /home -maxdepth 2 -type d -name Desktop`; do \
182file=$i/.directory; if [ -f \"$file\" ] ; then mv -f $file $file.old ; \
183awk '{if (index($0, \"rootimagesmindi\")) { while (length($0)>2) { getline;} ; } \
184else { print $0;};}' $file.old > $file ; fi ; done");
185 run_program_and_log_output(tmp, 5);
186 paranoid_free(tmp);
187}
188
189
190/**
191 * Locate mondoarchive's home directory. Searches in /usr/local/mondo, /usr/share/mondo,
192 * /usr/local/share/mondo, /opt, or if all else fails, search /usr.
193 *
194 * @param home_sz String to store the home directory ("" if it could not be found).
195 * @return 0 for success, nonzero for failure.
196 */
197int find_and_store_mondoarchives_home(char *home_sz)
198{
199 assert(home_sz != NULL);
200 strcpy(home_sz, MONDO_SHARE);
201 return (0);
202}
203
204
205char *get_architecture(void) {
206#ifdef __IA32__
207# ifdef __X86_64__
208 return ("x86_64");
209# else
210 return ("i386");
211# endif
212#endif
213#ifdef __IA64__
214 return ("ia64");
215#endif
216 return ("unknown");
217}
218
219
220char *get_uname_m(void) {
221
222 struct utsname utsn;
223 char *tmp = NULL;
224
225 uname(&utsn);
226 mr_asprintf(tmp, "%s", utsn.machine);
227 return (tmp);
228}
229
230
231
232double get_kernel_version(void)
233{
234 char *p, tmp[200];
235 double d;
236#ifdef __FreeBSD__
237 // JOSH - FIXME :)
238 d = 5.2; // :-)
239#else
240 strcpy(tmp, call_program_and_get_last_line_of_output("uname -r"));
241 p = strchr(tmp, '.');
242 if (p) {
243 p = strchr(++p, '.');
244 if (p) {
245 while (*p) {
246 *p = *(p + 1);
247 p++;
248 }
249 }
250 }
251// log_msg(1, "tmp = '%s'", tmp);
252 d = atof(tmp);
253#endif
254 log_msg(1, "g_kernel_version = %f", d);
255 return (d);
256}
257
258
259
260
261
262/**
263 * Get the current time.
264 * @return number of seconds since the epoch.
265 */
266long get_time()
267{
268 return (long) time((void *) 0);
269}
270
271
272
273
274
275
276
277/**
278 * Initialize a RAID volume structure, setting fields to zero. The
279 * actual hard drive is unaffected.
280 *
281 * @param raidrec The RAID volume structure to initialize.
282 * @note This function is system dependent.
283 */
284#ifdef __FreeBSD__
285void initialize_raidrec(struct vinum_volume *raidrec)
286{
287 int i, j;
288 raidrec->volname[0] = '\0';
289 raidrec->plexes = 0;
290 for (i = 0; i < 9; ++i) {
291 raidrec->plex[i].raidlevel = -1;
292 raidrec->plex[i].stripesize = 0;
293 raidrec->plex[i].subdisks = 0;
294 for (j = 0; j < 9; ++j) {
295 strcpy(raidrec->plex[i].sd[j].which_device, "");
296 }
297 }
298}
299#else
300void initialize_raidrec(struct raid_device_record *raidrec)
301{
302 assert(raidrec != NULL);
303 raidrec->raid_device[0] = '\0';
304 raidrec->raid_level = -9;
305 raidrec->persistent_superblock = 1;
306 raidrec->chunk_size = 64;
307 raidrec->parity = -1;
308 raidrec->data_disks.entries = 0;
309 raidrec->spare_disks.entries = 0;
310 raidrec->parity_disks.entries = 0;
311 raidrec->failed_disks.entries = 0;
312 raidrec->additional_vars.entries = 0;
313}
314#endif
315
316
317
318
319/**
320 * Insert modules that Mondo requires.
321 * Currently inserts @c msdos, @c vfat, and @c loop for Linux;
322 * @c msdosfs and @c ext2fs for FreeBSD.
323 */
324void insmod_crucial_modules(void)
325{
326#ifdef __FreeBSD__
327 paranoid_system("kldstat | grep msdosfs || kldload msdosfs 2> /dev/null");
328 paranoid_system("kldstat | grep ext2fs || kldload ext2fs 2> /dev/null");
329#else
330 paranoid_system("modprobe -a msdos vfat loop &> /dev/null");
331#endif
332}
333
334/**
335 * Finish configuring the backup information structure. Call this function
336 * to set the parameters that depend on those that can be given on the command
337 * line.
338 *
339 * @param bkpinfo The backup information structure. Fields modified/used:
340 * - Used: @c bkpinfo->backup_data
341 * - Used: @c bkpinfo->backup_media_type
342 * - Used: @c bkpinfo->cdrw_speed
343 * - Used: @c bkpinfo->compression_level
344 * - Used: @c bkpinfo->include_paths
345 * - Used: @c bkpinfo->prefix
346 * - Used: @c bkpinfo->isodir
347 * - Used: @c bkpinfo->manual_cd_tray
348 * - Used: @c bkpinfo->make_cd_use_lilo
349 * - Used: @c bkpinfo->media_device
350 * - Used: @c bkpinfo->netfs_mount
351 * - Used: @c bkpinfo->nonbootable_backup
352 * - Used: @c bkpinfo->scratchdir
353 * - Used: @c bkpinfo->tmpdir
354 * - Used: @c bkpinfo->use_lzo
355 * - Modified: @c bkpinfo->call_before_iso
356 * - Modified: @c bkpinfo->call_make_iso
357 * - Modified: @c bkpinfo->optimal_set_size
358 * - Modified: @c bkpinfo->zip_exe
359 * - Modified: @c bkpinfo->zip_suffix
360 *
361 * @return number of errors, or 0 for success.
362 * @note Also creates directories that are specified in the @c bkpinfo structure but
363 * do not exist.
364 */
365int post_param_configuration()
366{
367 char *extra_cdrom_params = NULL;
368 char *mondo_mkisofs_sz = NULL;
369 char *command = NULL;
370 char *mtpt;
371 char *hostname;
372 char *isofs_cmd = NULL;
373 char *ip_address = NULL;
374 int retval = 0;
375 char *colon;
376 char *cdr_exe;
377 char *tmp = NULL;
378 char call_before_iso_user[MAX_STR_LEN] = "\0";
379 /*
380 long avm = 0;
381 int rdsiz_MB;
382 */
383 char *iso_dev = NULL;
384 char *iso_mnt = NULL;
385 char *iso_tmp = NULL;
386 char *iso_path = NULL;
387
388 assert(bkpinfo != NULL);
389 malloc_string(mtpt);
390 malloc_string(hostname);
391 malloc_string(cdr_exe);
392 bkpinfo->optimal_set_size =
393 (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type) ? 16 : 16) *
394 1024;
395
396 log_msg(1, "Post-param");
397 if (bkpinfo->backup_media_type == tape) {
398 if (whine_if_not_found("mt") == 1) {
399 fatal_error("Please install the mt command");
400 }
401 log_msg(1, "Tape");
402 mr_asprintf(tmp, "mt -f %s status", bkpinfo->media_device);
403 log_msg(1, "tmp = '%s'", tmp);
404 if (run_program_and_log_output(tmp, 3)) {
405 mr_free(tmp);
406 fatal_error
407 ("Unable to open tape device. If you haven't specified it with -d, do so. If you already have, check your parameter. I think it's wrong.");
408 }
409 mr_free(tmp);
410 }
411 if (bkpinfo->backup_media_type == iso)
412 make_hole_for_dir(bkpinfo->isodir);
413
414 run_program_and_log_output("uname -a", 5);
415 run_program_and_log_output("cat /etc/*-release", 5);
416 run_program_and_log_output("cat /etc/*issue*", 5);
417#ifdef __FreeBSD__
418#else
419 run_program_and_log_output("cat /proc/cpuinfo", 5);
420 run_program_and_log_output
421 ("rpm -q newt newt-devel slang slang-devel ncurses ncurses-devel gcc",
422 5);
423#endif
424
425 if (bkpinfo->use_lzo) {
426 strcpy(bkpinfo->zip_exe, "lzop");
427 strcpy(bkpinfo->zip_suffix, "lzo");
428 } else if (bkpinfo->use_gzip) {
429 strcpy(bkpinfo->zip_exe, "gzip");
430 strcpy(bkpinfo->zip_suffix, "gz");
431 } else if (bkpinfo->compression_level != 0) {
432 strcpy(bkpinfo->zip_exe, "bzip2");
433 strcpy(bkpinfo->zip_suffix, "bz2");
434 } else {
435 bkpinfo->zip_exe[0] = bkpinfo->zip_suffix[0] = '\0';
436 }
437
438// DVD
439
440 if (bkpinfo->backup_media_type == dvd) {
441 if (find_home_of_exe("growisofs")) {
442 strcpy(cdr_exe, "growisofs");
443 } // unlikely to be used
444 else {
445 fatal_error("Please install growisofs.");
446 }
447 if (bkpinfo->nonbootable_backup) {
448 mr_asprintf(mondo_mkisofs_sz, MONDO_GROWISOFS_NONBOOT);
449 } else if
450#ifdef __FreeBSD__
451 (TRUE)
452#else
453 (bkpinfo->make_cd_use_lilo)
454#endif
455#ifdef __IA64__
456 {
457 mr_asprintf(mondo_mkisofs_sz, MONDO_GROWISOFS_REGULAR_ELILO);
458 }
459#else
460 {
461 mr_asprintf(mondo_mkisofs_sz, MONDO_GROWISOFS_REGULAR_LILO);
462 }
463#endif
464 else
465 {
466 mr_asprintf(mondo_mkisofs_sz, MONDO_GROWISOFS_REGULAR_SYSLINUX);
467 }
468 if (bkpinfo->manual_cd_tray) {
469 paranoid_free(mondo_mkisofs_sz);
470 fatal_error("Manual CD tray + DVD not supported yet.");
471 // -m isn't supported by growisofs, BTW...
472 } else {
473 sprintf(bkpinfo->call_make_iso,
474 "%s %s -Z %s . 2>> _ERR_",
475 mondo_mkisofs_sz,
476 "", bkpinfo->media_device);
477 paranoid_free(mondo_mkisofs_sz);
478 }
479 if (getenv ("SUDO_COMMAND")) {
480 mr_asprintf(command, "strings `which growisofs` | grep -c SUDO_COMMAND");
481 if (!strcmp(call_program_and_get_last_line_of_output(command), "1")) {
482 mr_free(command);
483 popup_and_OK("Fatal Error: Can't write DVDs as sudo because growisofs doesn't support this - see the growisofs manpage for details.");
484 fatal_error("Can't write DVDs as sudo because growisofs doesn't support this - see the growisofs manpage for details.");
485 }
486 mr_free(command);
487 }
488 log_msg(2, "call_make_iso (DVD res) is ... %s",
489 bkpinfo->call_make_iso);
490 } // end of DVD code
491
492// CD-R or CD-RW
493 if (bkpinfo->backup_media_type == cdrw
494 || bkpinfo->backup_media_type == cdr) {
495 if (!bkpinfo->manual_cd_tray) {
496 mr_asprintf(extra_cdrom_params, "-waiti ");
497 }
498 if (bkpinfo->backup_media_type == cdrw) {
499 mr_asprintf(extra_cdrom_params, "blank=fast ");
500 }
501 if (extra_cdrom_params == NULL) {
502 // If not initialized earlier, do it now
503 mr_asprintf(extra_cdrom_params, " ");
504 }
505 if (find_home_of_exe("cdrecord")) {
506 strcpy(cdr_exe, "cdrecord");
507 } else if (find_home_of_exe("dvdrecord")) {
508 strcpy(cdr_exe, "dvdrecord");
509 } else {
510 fatal_error("Please install either cdrecord or dvdrecord.");
511 }
512 if (find_home_of_exe("genisoimage")) {
513 mr_asprintf(isofs_cmd, "%s", MONDO_GENISOIMAGE_CMD);
514 } else {
515 mr_asprintf(isofs_cmd, "%s", MONDO_MKISOFS_CMD);
516 }
517 if (bkpinfo->nonbootable_backup) {
518 mr_asprintf(mondo_mkisofs_sz, "%s%s", isofs_cmd, MONDO_MKISOFS);
519 } else if
520#ifdef __FreeBSD__
521 (TRUE)
522#else
523 (bkpinfo->make_cd_use_lilo)
524#endif
525#ifdef __IA64__
526 {
527 mr_asprintf(mondo_mkisofs_sz, "%s%s -V _CD#_", isofs_cmd, MONDO_MKISOFS_REGULAR_ELILO);
528 }
529#else
530 {
531 mr_asprintf(mondo_mkisofs_sz, "%s%s -V _CD#_", isofs_cmd, MONDO_MKISOFS_REGULAR_LILO);
532 }
533#endif
534 else
535 {
536 mr_asprintf(mondo_mkisofs_sz, "%s%s -V _CD#_", isofs_cmd, MONDO_MKISOFS_REGULAR_SYSLINUX);
537 }
538 mr_free(isofs_cmd);
539
540 if (bkpinfo->manual_cd_tray) {
541 if (bkpinfo->call_before_iso[0] == '\0') {
542 sprintf(bkpinfo->call_before_iso,
543 "%s -o %s/"MONDO_TMPISOS" . 2>> _ERR_",
544 mondo_mkisofs_sz, bkpinfo->tmpdir);
545 } else {
546 strncpy(call_before_iso_user, bkpinfo->call_before_iso, MAX_STR_LEN);
547 sprintf (bkpinfo->call_before_iso,
548 "( %s -o %s/"MONDO_TMPISOS" . 2>> _ERR_ ; %s )",
549 mondo_mkisofs_sz, bkpinfo->tmpdir, call_before_iso_user);
550 }
551 log_it("bkpinfo->call_before_iso = %s", bkpinfo->call_before_iso);
552 sprintf(bkpinfo->call_make_iso,
553 "%s %s -v %s fs=4m dev=%s speed=%d %s/"MONDO_TMPISOS,
554 cdr_exe, (bkpinfo->please_dont_eject) ? " " : "-eject",
555 extra_cdrom_params, bkpinfo->media_device,
556 bkpinfo->cdrw_speed, bkpinfo->tmpdir);
557 } else {
558 sprintf(bkpinfo->call_make_iso,
559 "%s . 2>> _ERR_ | %s %s %s fs=4m dev=%s speed=%d -",
560 mondo_mkisofs_sz, cdr_exe,
561 (bkpinfo->please_dont_eject) ? " " : "-eject",
562 extra_cdrom_params, bkpinfo->media_device,
563 bkpinfo->cdrw_speed);
564 }
565 paranoid_free(mondo_mkisofs_sz);
566 paranoid_free(extra_cdrom_params);
567 } // end of CD code
568
569 if (bkpinfo->backup_media_type == iso) {
570
571/* Patch by Conor Daly <conor.daly@met.ie>
572 * 23-june-2004
573 * Break up isodir into iso_mnt and iso_path
574 * These will be used along with iso-dev at restore time
575 * to locate the ISOs where ever they're mounted
576 */
577
578 log_it("isodir = %s", bkpinfo->isodir);
579 mr_asprintf(command, "df -P %s | tail -n1 | cut -d' ' -f1",
580 bkpinfo->isodir);
581 log_it("command = %s", command);
582 log_it("res of it = %s", call_program_and_get_last_line_of_output(command));
583 mr_asprintf(iso_dev, "%s", call_program_and_get_last_line_of_output(command));
584 mr_asprintf(tmp, "%s/ISO-DEV", bkpinfo->tmpdir);
585 write_one_liner_data_file(tmp, call_program_and_get_last_line_of_output(command));
586 mr_free(tmp);
587 mr_free(command);
588
589 mr_asprintf(command, "mount | grep -w %s | tail -n1 | cut -d' ' -f3", iso_dev);
590 mr_free(iso_dev);
591
592 log_it("command = %s", command);
593 log_it("res of it = %s", call_program_and_get_last_line_of_output(command));
594 mr_asprintf(iso_mnt, "%s", call_program_and_get_last_line_of_output(command));
595 mr_asprintf(tmp, "%s/ISO-MNT", bkpinfo->tmpdir);
596 write_one_liner_data_file(tmp, call_program_and_get_last_line_of_output(command));
597 mr_free(tmp);
598 mr_free(command);
599
600 log_it("isomnt: %s, %d", iso_mnt, strlen(iso_mnt));
601 mr_asprintf(iso_tmp, "%s", bkpinfo->isodir);
602 if (strlen(iso_tmp) < strlen(iso_mnt)) {
603 mr_asprintf(iso_path, "%s", "");
604 } else {
605 // If iso_mnt is only / then iso_path is the full dir
606 // (the formula bellow doesn't work in this case)
607 if (strcmp(iso_mnt, "/") == 0) {
608 mr_asprintf(iso_path, "%s", iso_tmp);
609 // else it's a part of iso_tmp
610 } else {
611 mr_asprintf(iso_path, "%s", iso_tmp + strlen(iso_mnt));
612 }
613 }
614 mr_free(iso_tmp);
615 mr_free(iso_mnt);
616
617 mr_asprintf(tmp, "%s/ISODIR", bkpinfo->tmpdir);
618 write_one_liner_data_file(tmp, iso_path);
619 mr_free(tmp);
620
621 log_it("isodir: %s", iso_path);
622 mr_free(iso_path);
623
624 mr_asprintf(tmp, "%s/ISO-PREFIX", bkpinfo->tmpdir);
625 write_one_liner_data_file(tmp, bkpinfo->prefix);
626 mr_free(tmp);
627
628 log_it("iso-prefix: %s", bkpinfo->prefix);
629
630/* End patch */
631 } // end of iso code
632
633 if (bkpinfo->backup_media_type == netfs) {
634 strcpy(hostname, bkpinfo->netfs_mount);
635 colon = strchr(hostname, ':');
636 if (!colon) {
637 log_it("netfs mount doesn't have a colon in it");
638 retval++;
639 } else {
640 struct hostent *hent;
641
642 *colon = '\0';
643 colon = strchr(hostname, '@');
644 if (colon) {
645 *colon = '\0';
646 colon++;
647 hent = gethostbyname(colon);
648 mr_asprintf(bkpinfo->netfs_user,"%s", hostname);
649 } else {
650 hent = gethostbyname(hostname);
651 }
652 if (!hent) {
653 log_it("Can't resolve Network mount (%s): %s", hostname,
654 hstrerror(h_errno));
655 retval++;
656 } else {
657 mr_asprintf(ip_address, "%s", inet_ntoa((struct in_addr) *((struct in_addr *) hent->h_addr)));
658 mr_strcat(ip_address, strchr(bkpinfo->netfs_mount, ':'));
659 strcpy(bkpinfo->netfs_mount, ip_address);
660 paranoid_free(ip_address);
661 }
662 }
663 store_netfs_config();
664 }
665
666 log_it("Finished processing incoming params");
667 if (retval) {
668 fprintf(stderr, "Type 'man mondoarchive' for help.\n");
669 }
670 if (strlen(bkpinfo->tmpdir) < 2 || strlen(bkpinfo->scratchdir) < 2) {
671 log_it("tmpdir or scratchdir are blank/missing");
672 retval++;
673 }
674 if (bkpinfo->include_paths[0] == '\0') {
675 // fatal_error ("Why no backup path?");
676 strcpy(bkpinfo->include_paths, "/");
677 }
678 chmod(bkpinfo->scratchdir, 0700);
679 g_backup_media_type = bkpinfo->backup_media_type;
680 paranoid_free(mtpt);
681 paranoid_free(hostname);
682 paranoid_free(cdr_exe);
683 return (retval);
684}
685
686
687
688/**
689 * Do some miscellaneous setup tasks to be performed before filling @c bkpinfo.
690 * Seeds the random-number generator, loads important modules, checks the sanity
691 * of the user's Linux distribution, and deletes logfile.
692 * @param bkpinfo The backup information structure. Will be initialized.
693 * @return number of errors (0 for success)
694 */
695int pre_param_configuration()
696{
697 int res = 0;
698 char *tmp = NULL;
699
700 make_hole_for_dir(MNT_CDROM);
701 assert(bkpinfo != NULL);
702 srandom((unsigned long) (time(NULL)));
703 insmod_crucial_modules();
704 if (bkpinfo->disaster_recovery) {
705 if (!does_nonMS_partition_exist()) {
706 fatal_error
707 ("I am in disaster recovery mode\nPlease don't run mondoarchive.");
708 }
709 }
710
711 mr_asprintf(tmp,"rm -Rf %s/changed.files*",MONDO_CACHE);
712 run_program_and_log_output(tmp, FALSE);
713 paranoid_free(tmp);
714 if (find_and_store_mondoarchives_home(g_mondo_home)) {
715 fprintf(stderr,
716 "Cannot find Mondo's homedir. I think you have >1 'mondo' directory on your hard disk. Please delete the superfluous 'mondo' directories and try again\n");
717 res++;
718 return (res);
719 }
720 res += some_basic_system_sanity_checks();
721 if (res) {
722 log_it("Your distribution did not pass Mondo's sanity test.");
723 }
724 g_current_media_number = 1;
725 bkpinfo->postnuke_tarball[0] = bkpinfo->netfs_mount[0] = '\0';
726 return (res);
727}
728
729/* From busybox under GPLv2 */
730#ifndef HAVE_MKDTEMP
731/* This is now actually part of POSIX.1, but was only added in 2008 */
732char* mkdtemp(char *template)
733{
734 if (mktemp(template) == NULL || mkdir(template, 0700) != 0)
735 return NULL;
736 return template;
737}
738#endif
739
740void setup_tmpdir(char *path) {
741
742 char *tmp = NULL;
743 char *p = NULL;
744
745 if (bkpinfo->tmpdir != NULL) {
746 /* purging a potential old tmpdir */
747 if (chdir("/tmp")) {
748 // FIXME
749 }
750 if (strstr(bkpinfo->tmpdir,"mondo.tmp.") != NULL) {
751 log_it("Purging old tmpdir %s", bkpinfo->tmpdir);
752 mr_asprintf(tmp,"rm -Rf %s",bkpinfo->tmpdir);
753 } else {
754 log_it("Purging old tmpdir %s/mondo.tmp.*", bkpinfo->tmpdir);
755 mr_asprintf(tmp,"rm -Rf %s/mondo.tmp.*",bkpinfo->tmpdir);
756 }
757 paranoid_system(tmp);
758 mr_free(tmp);
759 }
760
761 /* Always take in account arg first, then env, then default */
762 if (path != NULL) {
763 mr_asprintf(tmp, "%s/mondo.tmp.XXXXXX", path);
764 } else if (getenv("TMPDIR")) {
765 mr_asprintf(tmp, "%s/mondo.tmp.XXXXXX", getenv("TMPDIR"));
766 } else if (getenv("MRTMP")) {
767 mr_asprintf(tmp, "%s/mondo.tmp.XXXXXX", getenv("MRTMP"));
768 } else {
769 mr_asprintf(tmp, "/tmp/mondo.tmp.XXXXXX");
770 }
771 p = mkdtemp(tmp);
772 if (p == NULL) {
773 log_it("Failed to create global tmp directory %s for Mondo.",tmp);
774 finish(-1);
775 }
776 strcpy(bkpinfo->tmpdir,p);
777 paranoid_free(tmp);
778
779 mr_asprintf(tmp, "mkdir -p %s/tmpfs", bkpinfo->tmpdir);
780 paranoid_system(tmp);
781 mr_free(tmp);
782}
783
784void setup_scratchdir(char *path) {
785
786 char *tmp = NULL;
787 char *p = NULL;
788
789 if (bkpinfo->scratchdir != NULL) {
790 /* purging a potential old scratchdir */
791 if (chdir("/tmp")) {
792 // FIXME
793 }
794 if (strstr(bkpinfo->scratchdir,"mondo.scratch.") != NULL) {
795 log_it("Purging old scratchdir %s", bkpinfo->scratchdir);
796 mr_asprintf(tmp,"rm -Rf %s",bkpinfo->scratchdir);
797 } else {
798 log_it("Purging old scratchdir %s/mondo.scratch.*", bkpinfo->scratchdir);
799 mr_asprintf(tmp,"rm -Rf %s/mondo.scratch.*",bkpinfo->scratchdir);
800 }
801 paranoid_system(tmp);
802 mr_free(tmp);
803 }
804
805 /* Always take in account arg first, then env, then default */
806 if (path != NULL) {
807 mr_asprintf(tmp, "%s/mondo.scratch.XXXXXX", path);
808 } else if (getenv("MRSCRATCH")) {
809 mr_asprintf(tmp, "%s/mondo.scratch.XXXXXX", getenv("MRSCRATCH"));
810 } else {
811 mr_asprintf(tmp, "/tmp/mondo.scratch.XXXXXX");
812 }
813 p = mkdtemp(tmp);
814 if (p == NULL) {
815 log_it("Failed to create global scratch directory %s for Mondo.",tmp);
816 finish(-1);
817 }
818 strcpy(bkpinfo->scratchdir,p);
819 paranoid_free(tmp);
820
821 mr_asprintf(tmp, "mkdir -p %s", bkpinfo->scratchdir);
822 paranoid_system(tmp);
823 mr_free(tmp);
824}
825
826
827/**
828 * Reset all fields of the backup information structure to a sensible default.
829 * @param bkpinfo The @c bkpinfo to reset.
830 */
831void reset_bkpinfo()
832{
833 int i;
834
835 log_msg(1, "Hi");
836 assert(bkpinfo != NULL);
837 memset((void *) bkpinfo, 0, sizeof(struct s_bkpinfo));
838
839 bkpinfo->media_device[0] = '\0';
840 bkpinfo->media_size = -1;
841 bkpinfo->boot_loader = '\0';
842 bkpinfo->boot_device[0] = '\0';
843 bkpinfo->zip_exe[0] = '\0';
844 bkpinfo->zip_suffix[0] = '\0';
845 bkpinfo->image_devs[0] = '\0';
846 bkpinfo->compression_level = 3;
847 bkpinfo->use_lzo = FALSE;
848 bkpinfo->use_gzip = FALSE;
849 bkpinfo->do_not_compress_these[0] = '\0';
850 bkpinfo->verify_data = FALSE;
851 bkpinfo->backup_data = FALSE;
852 bkpinfo->restore_data = FALSE;
853 bkpinfo->use_star = FALSE;
854 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
855 bkpinfo->disaster_recovery =
856 (am_I_in_disaster_recovery_mode()? TRUE : FALSE);
857 if (bkpinfo->disaster_recovery) {
858 strcpy(bkpinfo->isodir, "/");
859 } else {
860 strcpy(bkpinfo->isodir, MONDO_CACHE);
861 }
862 strcpy(bkpinfo->prefix, STD_PREFIX);
863 setup_tmpdir(NULL);
864 setup_scratchdir(NULL);
865
866 bkpinfo->optimal_set_size = 0;
867 strcpy(bkpinfo->include_paths, "/");
868 bkpinfo->make_filelist = TRUE; // unless -J supplied to mondoarchive
869 bkpinfo->include_paths[0] = '\0';
870 bkpinfo->exclude_devs = NULL;
871 bkpinfo->restore_path[0] = '\0';
872 bkpinfo->call_before_iso[0] = '\0';
873 bkpinfo->call_make_iso[0] = '\0';
874 bkpinfo->call_burn_iso[0] = '\0';
875 bkpinfo->call_after_iso[0] = '\0';
876 bkpinfo->kernel_path[0] = '\0';
877 bkpinfo->netfs_mount[0] = '\0';
878 bkpinfo->netfs_proto = NULL;
879 bkpinfo->netfs_user = NULL;
880 bkpinfo->netfs_remote_dir[0] = '\0';
881 bkpinfo->exclude_paths = NULL;
882 bkpinfo->subdir = NULL;
883 bkpinfo->postnuke_tarball[0] = '\0';
884 bkpinfo->wipe_media_first = FALSE;
885 bkpinfo->differential = 0;
886 bkpinfo->please_dont_eject = FALSE;
887 bkpinfo->cdrw_speed = 0;
888 bkpinfo->manual_cd_tray = FALSE;
889 bkpinfo->nonbootable_backup = FALSE;
890 bkpinfo->make_cd_use_lilo = FALSE;
891 bkpinfo->use_obdr = FALSE;
892 bkpinfo->restore_mode = interactive;
893}
894
895
896
897
898/**
899 * Get the remaining free space (in MB) on @p partition.
900 * @param partition The partition to check free space on (either a device or a mountpoint).
901 * @return The free space on @p partition, in MB.
902 */
903long free_space_on_given_partition(char *partition)
904{
905 char *out_sz = NULL;
906 char *command = NULL;
907 long res;
908
909 assert_string_is_neither_NULL_nor_zerolength(partition);
910
911 mr_asprintf(command, "df -m -P %s 1> /dev/null 2> /dev/null", partition);
912 if (system(command)) {
913 mr_free(command);
914 return (-1);
915 } // partition does not exist
916 mr_free(command);
917
918 mr_asprintf(command, "df -m -P %s | tail -n1 | tr -s ' ' '\t' | cut -f4",
919 partition);
920 mr_asprintf(out_sz, "%s", call_program_and_get_last_line_of_output(command));
921 mr_free(command);
922
923 if (strlen(out_sz) == 0) {
924 mr_free(out_sz);
925 return (-1);
926 } // error within df, probably
927 res = atol(out_sz);
928 mr_free(out_sz);
929 return (res);
930}
931
932
933
934/**
935 * Check the user's system for sanity. Checks performed:
936 * - make sure user has enough RAM (32mb required, 64mb recommended)
937 * - make sure user has enough free space in @c /
938 * - check kernel for ramdisk support
939 * - make sure afio, cdrecord, mkisofs, bzip2, awk, md5sum, strings, mindi, and buffer exist
940 * - make sure CD-ROM is unmounted
941 * - make sure user's mountlist is OK by running <tt>mindi --makemountlist</tt>
942 *
943 * @return number of problems with the user's setup (0 for success)
944 */
945int some_basic_system_sanity_checks()
946{
947
948 /*@ buffers ************ */
949 char *tmp = NULL;
950
951 /*@ int's *************** */
952 int retval = 0;
953
954 mvaddstr_and_log_it(g_currentY, 0,
955 "Checking sanity of your Linux distribution");
956#ifndef __FreeBSD__
957 if (system("which mkfs.vfat 2> /dev/null 1> /dev/null")
958 && !system("which mkfs.msdos 2> /dev/null 1> /dev/null")) {
959 log_it
960 ("OK, you've got mkfs.msdos but not mkfs.vfat; time for the fairy to wave her magic wand...");
961 run_program_and_log_output
962 ("ln -sf `which mkfs.msdos` /sbin/mkfs.vfat", FALSE);
963 }
964 mr_asprintf(tmp, "%s",
965 call_program_and_get_last_line_of_output
966 ("free | grep Mem | head -n1 | tr -s ' ' '\t' | cut -f2"));
967 if (atol(tmp) < 35000) {
968 retval++;
969 log_to_screen("You must have at least 32MB of RAM to use Mondo.");
970 }
971 if (atol(tmp) < 66000) {
972 log_to_screen
973 ("WARNING! You have very little RAM. Please upgrade to 64MB or more.");
974 }
975 mr_free(tmp);
976#endif
977
978 if (system("which " MKE2FS_OR_NEWFS " > /dev/null 2> /dev/null")) {
979 retval++;
980 log_to_screen
981 ("Unable to find " MKE2FS_OR_NEWFS " in system path.");
982 fatal_error
983 ("Please use \"su -\", not \"su\" to become root. OK? ...and please don't e-mail the mailing list or me about this. Just read the message. :)");
984 }
985#ifndef __FreeBSD__
986 if (run_program_and_log_output
987 ("grep ramdisk /proc/devices", FALSE)) {
988 /* Some SuSE have ramdisk as modules, so insert it first, then test again */
989 run_program_and_log_output("modprobe brd 2> /dev/null > /dev/null",FALSE);
990 if (run_program_and_log_output
991 ("grep ramdisk /proc/devices", FALSE)) {
992 if (!ask_me_yes_or_no
993 ("Your kernel has no ramdisk support. That's mind-numbingly stupid but I'll allow it if you're planning to use a failsafe kernel. Are you?"))
994 {
995 // retval++;
996 log_to_screen
997 ("It looks as if your kernel lacks ramdisk and initrd support.");
998 log_to_screen
999 ("I'll allow you to proceed but FYI, if I'm right, your kernel is broken.");
1000 }
1001 }
1002 }
1003#endif
1004 retval += whine_if_not_found(MKE2FS_OR_NEWFS);
1005 if (system("which genisoimage > /dev/null 2> /dev/null")) {
1006 retval += whine_if_not_found("mkisofs");
1007 }
1008 if (system("which wodim > /dev/null 2> /dev/null")) {
1009 retval += whine_if_not_found("cdrecord");
1010 }
1011 retval += whine_if_not_found("bzip2");
1012 retval += whine_if_not_found("gzip");
1013 retval += whine_if_not_found("awk");
1014 retval += whine_if_not_found("md5sum");
1015 retval += whine_if_not_found("strings");
1016 retval += whine_if_not_found("mindi");
1017 retval += whine_if_not_found("buffer");
1018
1019 // abort if Windows partition but no ms-sys and parted
1020 if (!run_program_and_log_output("mount | grep -Ew 'vfat|fat|dos' | grep -vE \"/dev/fd|nexdisk\"", 0)) {
1021 log_to_screen("I think you have a Windows 9x partition.");
1022 retval += whine_if_not_found("parted");
1023 }
1024
1025 if (!find_home_of_exe("cmp")) {
1026 whine_if_not_found("cmp");
1027 }
1028 run_program_and_log_output
1029 ("umount `mount | grep cdr | cut -d' ' -f3 | tr '\n' ' '`", 5);
1030 mr_asprintf(tmp, "%s",
1031 call_program_and_get_last_line_of_output
1032 ("mount | grep -E \"cdr(om|w)\""));
1033 if (strcmp("", tmp)) {
1034 if (strstr(tmp, "autofs")) {
1035 log_to_screen
1036 ("Your CD-ROM is mounted via autofs. I therefore cannot tell");
1037 log_to_screen
1038 ("if a CD actually is inserted. If a CD is inserted, please");
1039 log_to_screen("eject it. Thank you.");
1040 log_it
1041 ("Ignoring autofs CD-ROM 'mount' since we hope nothing's in it.");
1042 } else
1043 if (run_program_and_log_output("uname -a | grep Knoppix", 5)) {
1044 retval++;
1045 mr_free(tmp);
1046 fatal_error("Your CD-ROM drive is mounted. Please unmount it.");
1047 }
1048 }
1049 mr_free(tmp);
1050
1051 run_program_and_log_output("cat /etc/fstab", 5);
1052#ifdef __FreeBSD__
1053 run_program_and_log_output("vinum printconfig", 5);
1054#else
1055 run_program_and_log_output("cat /etc/raidtab", 5);
1056#endif
1057
1058 if (run_program_and_log_output("mindi -V", 1)) {
1059 log_to_screen("Could not ascertain mindi's version number.");
1060 log_to_screen
1061 ("You have not installed Mondo and/or Mindi properly.");
1062 log_to_screen("Please uninstall and reinstall them both.");
1063 fatal_error("Please reinstall Mondo and Mindi.");
1064 }
1065 mr_asprintf(tmp, "mindi --makemountlist %s/mountlist.txt.test", bkpinfo->tmpdir);
1066 if (run_program_and_log_output(tmp, 5)) {
1067 mr_free(tmp);
1068 mr_asprintf(tmp, "mindi --makemountlist %s/mountlist.txt.test failed for some reason.", bkpinfo->tmpdir);
1069 log_to_screen(tmp);
1070 log_to_screen
1071 ("Please run that command by hand and examine /var/log/mindi.log");
1072 log_to_screen
1073 ("for more information. Perhaps your /etc/fstab file is insane.");
1074 log_to_screen
1075 ("Perhaps Mindi's MakeMountlist() subroutine has a bug. We'll see.");
1076 retval++;
1077 }
1078 mr_free(tmp);
1079
1080 if (!run_program_and_log_output("parted2fdisk -l 2>/dev/null | grep -i raid", 1)
1081 && !does_file_exist("/etc/raidtab")) {
1082 log_to_screen
1083 ("You have RAID partitions but no /etc/raidtab - creating one from /proc/mdstat");
1084 create_raidtab_from_mdstat(MDSTAT_FILE,"/etc/raidtab");
1085 }
1086
1087 if (retval) {
1088 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1089 } else {
1090 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1091 }
1092 return (retval);
1093}
1094
1095/**
1096 * Retrieve the line containing @p label from the config file.
1097 * @param config_file The file to read from, usually @c /tmp/mondo-restore.cfg.
1098 * @param label What to read from the file.
1099 * @param value Where to put it.
1100 * @return 0 for success, 1 for failure.
1101 */
1102int read_cfg_var(char *config_file, char *label, char *value)
1103{
1104 /*@ buffer ****************************************************** */
1105 char *command = NULL;
1106 char *tmp = NULL;
1107
1108 /*@ end vars *************************************************** */
1109
1110 assert_string_is_neither_NULL_nor_zerolength(config_file);
1111 assert_string_is_neither_NULL_nor_zerolength(label);
1112 if (!does_file_exist(config_file)) {
1113 mr_asprintf(tmp, "(read_cfg_var) Cannot find %s config file",
1114 config_file);
1115 log_to_screen(tmp);
1116 mr_free(tmp);
1117
1118 value[0] = '\0';
1119 return (1);
1120 } else if ((value != NULL) && (strstr(value, "/dev/") && strstr(value, "t0") && !strcmp(label, "media-dev"))) {
1121 log_msg(2, "FYI, I can't read new value for %s - already got %s", label, value);
1122 return (0);
1123 } else {
1124 mr_asprintf(command, "grep '%s .*' %s| cut -d' ' -f2,3,4,5",
1125 label, config_file);
1126 strcpy(value, call_program_and_get_last_line_of_output(command));
1127 mr_free(command);
1128
1129 if (strlen(value) == 0) {
1130 return (1);
1131 } else {
1132 return (0);
1133 }
1134 }
1135}
1136
1137
1138
1139/**
1140 * Remount @c supermount if it was unmounted earlier.
1141 */
1142void remount_supermounts_if_necessary()
1143{
1144 if (g_remount_cdrom_at_end) {
1145 run_program_and_log_output("mount " MNT_CDROM, FALSE);
1146 }
1147 if (g_remount_floppy_at_end) {
1148 run_program_and_log_output("mount " MNT_FLOPPY, FALSE);
1149 }
1150}
1151
1152/**
1153 * Unmount @c supermount if it's mounted.
1154 */
1155void unmount_supermounts_if_necessary()
1156{
1157 if (run_program_and_log_output
1158 ("mount | grep cdrom | grep super", FALSE) == 0) {
1159 g_remount_cdrom_at_end = TRUE;
1160 run_program_and_log_output("umount " MNT_CDROM, FALSE);
1161 }
1162 if (run_program_and_log_output
1163 ("mount | grep floppy | grep super", FALSE) == 0) {
1164 g_remount_floppy_at_end = TRUE;
1165 run_program_and_log_output("umount " MNT_FLOPPY, FALSE);
1166 }
1167}
1168
1169/**
1170 * Whether we had to stop autofs (if so, restart it at end).
1171 */
1172bool g_autofs_stopped = FALSE;
1173
1174/**
1175 * Path to the autofs initscript ("" if none exists).
1176 */
1177char g_autofs_exe[MAX_STR_LEN];
1178
1179/**
1180 * Autofs initscript in Xandros Linux distribution.
1181 */
1182#define XANDROS_AUTOFS_FNAME "/etc/init.d/xandros-autofs"
1183
1184/**
1185 * Autofs initscript in most Linux distributions.
1186 */
1187#define STOCK_AUTOFS_FNAME "/etc/rc.d/init.d/autofs"
1188
1189/**
1190 * If autofs is mounted, stop it (restart at end).
1191 */
1192void stop_autofs_if_necessary()
1193{
1194 char *tmp = NULL;
1195
1196 g_autofs_exe[0] = '\0';
1197 if (does_file_exist(XANDROS_AUTOFS_FNAME)) {
1198 strcpy(g_autofs_exe, XANDROS_AUTOFS_FNAME);
1199 } else if (does_file_exist(STOCK_AUTOFS_FNAME)) {
1200 strcpy(g_autofs_exe, STOCK_AUTOFS_FNAME);
1201 }
1202
1203 if (!g_autofs_exe[0]) {
1204 log_msg(3, "No autofs detected.");
1205 } else {
1206 log_msg(3, "%s --- autofs detected", g_autofs_exe);
1207 // FIXME -- only disable it if it's running --- sprintf(tmp, "%s status", autofs_exe);
1208 mr_asprintf(tmp, "%s stop", g_autofs_exe);
1209 if (run_program_and_log_output(tmp, 2)) {
1210 log_it("Failed to stop autofs - I assume it wasn't running");
1211 } else {
1212 g_autofs_stopped = TRUE;
1213 log_it("Stopped autofs OK");
1214 }
1215 mr_free(tmp);
1216 }
1217}
1218
1219/**
1220 * If autofs was stopped earlier, restart it.
1221 */
1222void restart_autofs_if_necessary()
1223{
1224 char *tmp = NULL;
1225
1226 if (!g_autofs_stopped || !g_autofs_exe[0]) {
1227 log_msg(3, "No autofs detected.");
1228 return;
1229 }
1230 mr_asprintf(tmp, "%s start", g_autofs_exe);
1231 if (run_program_and_log_output(tmp, 2)) {
1232 log_it("Failed to start autofs");
1233 } else {
1234 g_autofs_stopped = FALSE;
1235 log_it("Started autofs OK");
1236 }
1237 mr_free(tmp);
1238}
1239
1240
1241/**
1242 * If this is a distribution like Gentoo that doesn't keep /boot mounted, mount it.
1243 */
1244void mount_boot_if_necessary()
1245{
1246 char *tmp = NULL;
1247 char *command = NULL;
1248
1249 log_msg(1, "Started sub");
1250 log_msg(4, "About to set g_boot_mountpt[0] to '\\0'");
1251 g_boot_mountpt[0] = '\0';
1252 log_msg(4, "Done. Great. Seeting command to something");
1253 mr_asprintf(command, "%s",
1254 "grep -v \":\" /etc/fstab | grep -vE '^#.*$' | grep -E \"[ ]/boot[ ]\" | tr -s ' ' '\t' | cut -f1 | head -n1");
1255 log_msg(4, "Cool. Command = '%s'", command);
1256 mr_asprintf(tmp, "%s", call_program_and_get_last_line_of_output(command));
1257 mr_free(command);
1258
1259 log_msg(4, "tmp = '%s'", tmp);
1260 if (tmp[0]) {
1261 log_it("/boot is at %s according to /etc/fstab", tmp);
1262 mr_asprintf(command, "mount | grep -Ew '/boot'");
1263 mr_free(tmp);
1264 mr_asprintf(tmp, call_program_and_get_last_line_of_output(command));
1265 mr_free(command);
1266
1267 if (!strcmp(tmp,"")) {
1268 if (((strstr(tmp, "LABEL=") != NULL) || (strstr(tmp,"UUID=")) != NULL)) {
1269 if (!run_program_and_log_output("mount /boot", 5)) {
1270 strcpy(g_boot_mountpt, "/boot");
1271 log_msg(1, "Mounted /boot");
1272 } else {
1273 log_it("...ignored cos it's a label or uuid :-)");
1274 }
1275 } else {
1276 mr_asprintf(command, "mount | grep -E '^%s'", tmp);
1277 log_msg(3, "command = %s", command);
1278 if (run_program_and_log_output(command, 5)) {
1279 strcpy(g_boot_mountpt, tmp);
1280 mr_free(tmp);
1281 mr_asprintf(tmp,
1282 "%s (your /boot partition) is not mounted. I'll mount it before backing up",
1283 g_boot_mountpt);
1284 log_it(tmp);
1285 mr_free(tmp);
1286
1287 mr_asprintf(tmp, "mount %s", g_boot_mountpt);
1288 if (run_program_and_log_output(tmp, 5)) {
1289 g_boot_mountpt[0] = '\0';
1290 log_msg(1, "Plan B");
1291 if (!run_program_and_log_output("mount /boot", 5)) {
1292 strcpy(g_boot_mountpt, "/boot");
1293 log_msg(1, "Plan B worked");
1294 } else {
1295 log_msg(1,
1296 "Plan B failed. Unable to mount /boot for backup purposes. This probably means /boot is mounted already, or doesn't have its own partition.");
1297 }
1298 }
1299 mr_free(tmp);
1300 }
1301 mr_free(command);
1302 }
1303 }
1304 }
1305 log_msg(1, "Ended sub");
1306}
1307
1308
1309/**
1310 * If we mounted /boot earlier, unmount it.
1311 */
1312void unmount_boot_if_necessary()
1313{
1314 char *tmp = NULL;
1315
1316 log_msg(3, "starting");
1317 if (g_boot_mountpt[0]) {
1318 mr_asprintf(tmp, "umount %s", g_boot_mountpt);
1319 if (run_program_and_log_output(tmp, 5)) {
1320 log_it("WARNING - unable to unmount /boot");
1321 }
1322 mr_free(tmp);
1323 }
1324 log_msg(3, "leaving");
1325}
1326
1327
1328
1329/**
1330 * Write a line to a configuration file. Writes a line of the form,
1331 * @c label @c value.
1332 * @param config_file The file to write to. Usually @c mondo-restore.cfg.
1333 * @param label What to call this bit of data you're writing.
1334 * @param value The bit of data you're writing.
1335 * @return 0 for success, 1 for failure.
1336 */
1337int write_cfg_var(char *config_file, char *label, char *value)
1338{
1339 /*@ buffers ***************************************************** */
1340 char *command = NULL;
1341 char *tempfile = NULL;
1342 char *tmp = NULL;
1343
1344
1345 /*@ end vars *************************************************** */
1346 assert_string_is_neither_NULL_nor_zerolength(config_file);
1347 assert_string_is_neither_NULL_nor_zerolength(label);
1348 assert(value != NULL);
1349 if (!does_file_exist(config_file)) {
1350 mr_asprintf(tmp, "(write_cfg_file) Cannot find %s config file",
1351 config_file);
1352 log_to_screen(tmp);
1353 mr_free(tmp);
1354 return (1);
1355 }
1356 mr_asprintf(tempfile, "%s/mojo-jojo.blah", bkpinfo->tmpdir);
1357 if (does_file_exist(config_file)) {
1358 mr_asprintf(command, "grep -vE '^%s .*$' %s > %s",
1359 label, config_file, tempfile);
1360 paranoid_system(command);
1361 mr_free(command);
1362 }
1363 mr_asprintf(command, "echo \"%s %s\" >> %s", label, value, tempfile);
1364 paranoid_system(command);
1365 mr_free(command);
1366
1367 mr_asprintf(command, "mv -f %s %s", tempfile, config_file);
1368 paranoid_system(command);
1369 mr_free(command);
1370 unlink(tempfile);
1371 mr_free(tempfile);
1372 return (0);
1373}
1374
1375
1376/**
1377 * The standard log_debug_msg() (log_msg() also due to a macro). Writes some describing
1378 * information to the logfile.
1379 */
1380void standard_log_debug_msg(int debug_level, const char *szFile,
1381 const char *szFunction, int nLine,
1382 const char *fmt, ...)
1383{
1384 va_list args;
1385 int i;
1386 static int depth = 0;
1387 FILE *fout;
1388
1389 if (depth > 5) {
1390 depth--;
1391 return;
1392 }
1393 depth++;
1394
1395 if (debug_level <= g_loglevel) {
1396 if (!(fout = fopen(MONDO_LOGFILE, "a"))) {
1397 return;
1398 } // fatal_error("Failed to openout to logfile - sheesh..."); }
1399
1400 // add tabs to distinguish log levels
1401 if (debug_level > 0) {
1402 for (i = 1; i < debug_level; i++)
1403 fprintf(fout, "\t");
1404 if (getpid() == g_main_pid)
1405 fprintf(fout, "[Main] %s->%s#%d: ", szFile, szFunction, nLine);
1406 else if (getpid() == g_buffer_pid && g_buffer_pid > 0)
1407 fprintf(fout, "[Buff] %s->%s#%d: ", szFile, szFunction, nLine);
1408 else
1409 fprintf(fout, "[TH=%d] %s->%s#%d: ", getpid(), szFile, szFunction, nLine);
1410 }
1411 va_start(args, fmt);
1412 vfprintf(fout, fmt, args);
1413 va_end(args);
1414
1415 // do not slow down the progran if standard debug level
1416 // must be enabled: if no flush, the log won't be up-to-date if there
1417 // is a segfault
1418 //if (g_dwDebugLevel != 1)
1419
1420 fprintf(fout, "\n");
1421 paranoid_fclose(fout);
1422 }
1423 depth--;
1424}
1425
1426/**
1427 * Function pointer to the @c log_debug_msg function to use. Points to standard_log_debug_msg() by default.
1428 */
1429void (*log_debug_msg) (int, const char *, const char *, int, const char *,
1430 ...) = standard_log_debug_msg;
1431
1432
1433/**
1434 * If @p y, malloc @p x, else free @p x.
1435 * @bug This function seems orphaned. Please remove.
1436 */
1437#define do_alloc_or_free_depending(x,y) { if(y) {x=malloc(MAX_STR_LEN);} else {paranoid_free(x);} }
1438
1439/**
1440 * Allocate or free important globals, depending on @p mal.
1441 * @param mal If TRUE, malloc; if FALSE, free.
1442 */
1443void do_libmondo_global_strings_thing(int mal)
1444{
1445 if (mal) {
1446 malloc_string(g_boot_mountpt);
1447 malloc_string(g_mondo_home);
1448 /*
1449 malloc_string(g_tmpfs_mountpt);
1450 */
1451 malloc_string(g_serial_string);
1452 malloc_string(g_magicdev_command);
1453 } else {
1454 paranoid_free(g_boot_mountpt);
1455 paranoid_free(g_mondo_home);
1456 /*
1457 paranoid_free(g_tmpfs_mountpt);
1458 */
1459 paranoid_free(g_serial_string);
1460 paranoid_free(g_magicdev_command);
1461
1462 }
1463
1464 /*
1465 char**list_of_arrays[] = {
1466 &g_boot_mountpt,
1467 &g_mondo_home,
1468 &g_tmpfs_mountpt,
1469 &g_serial_string,
1470 &g_magicdev_command,
1471 NULL};
1472
1473 char**ppcurr;
1474 int i;
1475
1476 for(i=0;list_of_arrays[i];i++)
1477 {
1478 log_msg(5, "Allocating %d", i);
1479 ppcurr = list_of_arrays[i];
1480 if (mal)
1481 { *ppcurr = malloc(MAX_STR_LEN); }
1482 else
1483 {
1484 if (*ppcurr)
1485 {
1486 free(*ppcurr);
1487 }
1488 }
1489 }
1490 log_msg(5, "Returning");
1491 */
1492}
1493
1494/**
1495 * Allocate important globals.
1496 * @see do_libmondo_global_strings_thing
1497 */
1498void malloc_libmondo_global_strings(void)
1499{
1500 do_libmondo_global_strings_thing(1);
1501}
1502
1503/**
1504 * Free important globals.
1505 * @see do_libmondo_global_strings_thing
1506 */
1507void free_libmondo_global_strings(void)
1508{
1509 do_libmondo_global_strings_thing(0);
1510}
1511
1512
1513
1514/**
1515 * Stop @c magicdev if it's running.
1516 * The command used to start it is saved in @p g_magicdev_command.
1517 */
1518void stop_magicdev_if_necessary()
1519{
1520 strcpy(g_magicdev_command,
1521 call_program_and_get_last_line_of_output
1522 ("ps ax | grep -w magicdev | grep -v grep | tr -s '\t' ' '| cut -d' ' -f6-99"));
1523 if (g_magicdev_command[0]) {
1524 log_msg(1, "g_magicdev_command = '%s'", g_magicdev_command);
1525 paranoid_system("killall magicdev");
1526 }
1527}
1528
1529
1530/**
1531 * Restart magicdev if it was stopped.
1532 */
1533void restart_magicdev_if_necessary()
1534{
1535 char *tmp = NULL;
1536
1537 if (g_magicdev_command && g_magicdev_command[0]) {
1538 mr_asprintf(tmp, "%s &", g_magicdev_command);
1539 paranoid_system(tmp);
1540 mr_free(tmp);
1541 }
1542}
1543
1544/* @} - end of utilityGroup */
Note: See TracBrowser for help on using the repository browser.