source: MondoRescue/branches/2.2.4/mondo/src/common/libmondo-tools.c@ 1437

Last change on this file since 1437 was 1437, checked in by andree, 17 years ago

New define 'MINDI_CACHE' set to '/var/cache/mindi' rather than
hardcoding this in the code. Makes it easy to change the location. Also
adjusted some of the messages related to boot floppies or CDs.

(Also added missing debug level to log_debug() call.)

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