source: MondoRescue/branches/3.1/mondo/src/common/libmondo-tools.c@ 3190

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