source: MondoRescue/branches/2.05/mondo/mondo/common/libmondo-tools.c@ 196

Last change on this file since 196 was 196, checked in by bcornec, 18 years ago

Usage of parted2fdisk instead of fdisk everywhere.
on ia64 this is mandatory, and simplifies the infrastructure
on other archs, it doesn't change anything as parted2fdisk here is a link to fdisk

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