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

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

Added check for sudo when writing DVDs and terminate if sudo used
because growisofs does't support sudo.

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