source: MondoRescue/trunk/mondo/mondo/common/libmondo-tools.c@ 75

Last change on this file since 75 was 75, checked in by andree, 19 years ago

Various changes to get archiving to NFS work in interactive mode. It
wasn't really like were were bugs, it appeared more like it was simply
not finished.

Side note: I believe that bkpinfo->isodir and bkpinfo->prefix were the
wrong way round in libmondo-archive.c and I've swapped them.

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