source: MondoRescue/branches/3.3/mondo/src/common/libmondo-tools.c@ 3790

Last change on this file since 3790 was 3790, checked in by Bruno Cornec, 21 months ago

Backport link fixes made for 3.2.2 to allow build on recent gcc versions

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