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

Last change on this file since 1140 was 1140, checked in by Bruno Cornec, 17 years ago

Try to fix some valgrind reports (note that this version still doesn't work)

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