source: MondoRescue/branches/stable/mondo/mondo/common/libmondo-tools.c@ 679

Last change on this file since 679 was 679, checked in by andree, 18 years ago

Avoid false alerts about growisofs not running under sudo. This is
achieved by examining the growisofs binary and searching exactly one
occurrence of the string SUDO_COMMAND. This test is designed to
avoid false positives. Note that this check is only required for
growisofs and not for other tools that may be used in the future to
write DVDs.

To enhance usability, the associated error message will now also appear
in a pop-up rather than just as part of a bunch of diagnostics output on
the command line.

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