source: MondoRescue/tags/3.2.2/mondo/src/common/libmondo-tools.c@ 3789

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

More fixes for global vars which should not be initialized when declared with extern

  • Property svn:keywords set to Id
File size: 40.4 KB
Line 
1/*
2 $Id: libmondo-tools.c 3789 2022-08-24 19:17: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_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 3789 2022-08-24 19:17:43Z 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.
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 = FALSE; ///< 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 */
58extern char *g_mondo_home;
59
60/**
61 * The serial string (used to differentiate between backups) of the current backup.
62 */
63extern char *g_serial_string;
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 mr_asprintf(tmp, "%s", call_program_and_get_last_line_of_output("uname -r"));
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 *isofs_cmd = NULL;
355 int retval = 0;
356 char *cdr_exe = NULL;
357 char *tmp = NULL;
358 char *call_before_iso_user = NULL;
359 char *iso_dev = NULL;
360 char *iso_mnt = NULL;
361 char *iso_tmp = NULL;
362 char *iso_dir = NULL;
363 char *uefistr = NULL;
364
365 assert(bkpinfo != NULL);
366
367 bkpinfo->optimal_set_size = (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type) ? 16 : 16) * 1024L;
368
369 log_msg(1, "Post-param");
370 if (bkpinfo->backup_media_type == tape) {
371 if (whine_if_not_found("mt") == 1) {
372 fatal_error("Please install the mt command");
373 }
374 log_msg(1, "Tape");
375 if (bkpinfo->media_device == NULL) {
376 return(1);
377 }
378 mr_asprintf(tmp, "mt -f %s status", bkpinfo->media_device);
379 log_msg(1, "tmp = '%s'", tmp);
380 if (run_program_and_log_output(tmp, 3)) {
381 mr_free(tmp);
382 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.");
383 }
384 mr_free(tmp);
385 }
386 if (bkpinfo->backup_media_type == iso)
387 make_hole_for_dir(bkpinfo->isodir);
388
389 run_program_and_log_output("uname -a", 5);
390 run_program_and_log_output("cat /etc/*-release", 5);
391 run_program_and_log_output("cat /etc/*issue*", 5);
392#ifdef __FreeBSD__
393#else
394 run_program_and_log_output("cat /proc/cpuinfo", 5);
395 /*
396 run_program_and_log_output("rpm -q newt newt-devel slang slang-devel ncurses ncurses-devel gcc", 5);
397 */
398#endif
399
400 if (bkpinfo->use_lzo) {
401 strcpy(bkpinfo->zip_exe, "lzop");
402 strcpy(bkpinfo->zip_suffix, "lzo");
403 } else if (bkpinfo->use_gzip) {
404 strcpy(bkpinfo->zip_exe, "gzip");
405 strcpy(bkpinfo->zip_suffix, "gz");
406 } else if (bkpinfo->use_lzma) {
407 strcpy(bkpinfo->zip_exe, "lzma");
408 strcpy(bkpinfo->zip_suffix, "lzma");
409 } else if (bkpinfo->compression_level != 0) {
410 strcpy(bkpinfo->zip_exe, "bzip2");
411 strcpy(bkpinfo->zip_suffix, "bz2");
412 } else {
413 bkpinfo->zip_exe[0] = bkpinfo->zip_suffix[0] = '\0';
414 }
415
416// DVD
417
418 if (bkpinfo->backup_media_type == dvd) {
419 if (find_home_of_exe("growisofs")) {
420 mr_asprintf(cdr_exe, "growisofs");
421 } // unlikely to be used
422 else {
423 fatal_error("Please install growisofs.");
424 }
425 if (bkpinfo->nonbootable_backup) {
426 mr_asprintf(mondo_mkisofs_sz, MONDO_GROWISOFS_NONBOOT);
427 } else if
428#ifdef __FreeBSD__
429 (TRUE)
430#else
431 (bkpinfo->make_cd_use_lilo)
432#endif
433#ifdef __IA64__
434 {
435 mr_asprintf(mondo_mkisofs_sz, MONDO_GROWISOFS_REGULAR_ELILO);
436 }
437#else
438 {
439 mr_asprintf(mondo_mkisofs_sz, MONDO_GROWISOFS_REGULAR_LILO);
440 }
441#endif
442 else {
443 mr_asprintf(mondo_mkisofs_sz, MONDO_GROWISOFS_REGULAR_SYSLINUX);
444 }
445 if (bkpinfo->manual_cd_tray) {
446 fatal_error("Manual CD tray + DVD not supported yet.");
447 // -m isn't supported by growisofs, BTW...
448 } else {
449 sprintf(bkpinfo->call_make_iso, "%s %s -Z %s . 2>> _ERR_", mondo_mkisofs_sz, "", bkpinfo->media_device);
450 }
451 mr_free(mondo_mkisofs_sz);
452 if (getenv ("SUDO_COMMAND")) {
453 mr_asprintf(command, "strings `which growisofs` | grep -c SUDO_COMMAND");
454 if (!strcmp(call_program_and_get_last_line_of_output(command), "1")) {
455 mr_free(command);
456 popup_and_OK("Fatal Error: Can't write DVDs as sudo because growisofs doesn't support this - see the growisofs manpage for details.");
457 fatal_error("Can't write DVDs as sudo because growisofs doesn't support this - see the growisofs manpage for details.");
458 }
459 mr_free(command);
460 }
461 log_msg(2, "call_make_iso (DVD res) is ... %s", bkpinfo->call_make_iso);
462 } // end of DVD code
463
464// CD-R or CD-RW
465 if (bkpinfo->backup_media_type == cdrw
466 || bkpinfo->backup_media_type == cdr) {
467 if (!bkpinfo->manual_cd_tray) {
468 mr_asprintf(extra_cdrom_params, "-waiti ");
469 }
470 if (bkpinfo->backup_media_type == cdrw) {
471 mr_asprintf(extra_cdrom_params, "blank=fast ");
472 }
473 if (extra_cdrom_params == NULL) {
474 // If not initialized earlier, do it now
475 mr_asprintf(extra_cdrom_params, " ");
476 }
477 if (find_home_of_exe("cdrecord")) {
478 mr_asprintf(cdr_exe, "cdrecord");
479 } else if (find_home_of_exe("dvdrecord")) {
480 mr_asprintf(cdr_exe, "dvdrecord");
481 } else {
482 fatal_error("Please install either cdrecord or dvdrecord.");
483 }
484 if (find_home_of_exe("xorriso")) {
485 mr_asprintf(isofs_cmd, "%s", MONDO_XORRISO_CMD);
486 } else if (find_home_of_exe("genisoimage")) {
487 mr_asprintf(isofs_cmd, "%s", MONDO_GENISOIMAGE_CMD);
488 } else {
489 mr_asprintf(isofs_cmd, "%s", MONDO_MKISOFS_CMD);
490 }
491 if (bkpinfo->nonbootable_backup) {
492 mr_asprintf(mondo_mkisofs_sz, "%s%s", isofs_cmd, MONDO_MKISOFS);
493 } else if
494#ifdef __FreeBSD__
495 (TRUE)
496#else
497 (bkpinfo->make_cd_use_lilo)
498#endif
499#ifdef __IA64__
500 {
501 mr_asprintf(mondo_mkisofs_sz, "%s%s ", isofs_cmd, MONDO_MKISOFS_REGULAR_ELILO);
502 }
503#else
504 {
505 mr_asprintf(mondo_mkisofs_sz, "%s%s ", isofs_cmd, MONDO_MKISOFS_REGULAR_LILO);
506 }
507#endif
508 else {
509 if (bkpinfo->boot_type == UEFI) {
510 if (strstr(isofs_cmd,"xorriso")) {
511 /* xorriso needs another '-' before efi-boot */
512 mr_asprintf(uefistr, "%s -%s", MONDO_UEFI_PREFIX, MONDO_MKISOFS_UEFI);
513 } else {
514 mr_asprintf(uefistr, "%s %s", MONDO_UEFI_PREFIX, MONDO_MKISOFS_UEFI);
515 }
516 } else {
517 mr_asprintf(uefistr, "%s",MONDO_MKISOFS_CMS);
518 }
519
520 mr_asprintf(mondo_mkisofs_sz, "%s%s%s ", isofs_cmd, MONDO_MKISOFS_REGULAR_SYSLINUX,uefistr);
521 }
522 mr_free(isofs_cmd);
523
524 if (bkpinfo->manual_cd_tray) {
525 if (bkpinfo->call_before_iso[0] == '\0') {
526 sprintf(bkpinfo->call_before_iso, "%s -o %s/"MONDO_TMPISOS" . 2>> _ERR_", mondo_mkisofs_sz, bkpinfo->tmpdir);
527 } else {
528 mr_asprintf(call_before_iso_user, "%s", bkpinfo->call_before_iso);
529 sprintf(bkpinfo->call_before_iso, "( %s -o %s/"MONDO_TMPISOS" . 2>> _ERR_ ; %s )", mondo_mkisofs_sz, bkpinfo->tmpdir, call_before_iso_user);
530 mr_free(call_before_iso_user);
531 }
532 log_it("bkpinfo->call_before_iso = %s", bkpinfo->call_before_iso);
533 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);
534 } else {
535 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);
536 }
537 mr_free(cdr_exe);
538 mr_free(mondo_mkisofs_sz);
539 mr_free(extra_cdrom_params);
540 } // end of CD code
541
542 if (bkpinfo->backup_media_type == iso) {
543
544/* Break up isodir into iso_mnt and iso_dir
545 * These will be used along with iso-dev at restore time
546 * to locate the ISOs where ever they're mounted
547 */
548
549 log_it("isodir = %s", bkpinfo->isodir);
550 mr_asprintf(command, "df -P %s | tail -n1 | cut -d' ' -f1", bkpinfo->isodir);
551 log_it("command = %s", command);
552 mr_asprintf(iso_dev, "%s", call_program_and_get_last_line_of_output(command));
553 log_it("res of it = %s", iso_dev);
554 mr_asprintf(tmp, "%s/ISO-DEV", bkpinfo->tmpdir);
555 write_one_liner_data_file(tmp, iso_dev);
556 mr_free(tmp);
557 mr_free(command);
558
559 mr_asprintf(command, "mount | grep -w %s | tail -n1 | cut -d' ' -f3", iso_dev);
560 mr_free(iso_dev);
561
562 log_it("command = %s", command);
563 mr_asprintf(iso_mnt, "%s", call_program_and_get_last_line_of_output(command));
564 log_it("res of it = %s", iso_mnt);
565 mr_asprintf(tmp, "%s/ISO-MNT", bkpinfo->tmpdir);
566 write_one_liner_data_file(tmp, iso_mnt);
567 mr_free(tmp);
568 mr_free(command);
569
570 log_it("iso_mnt: %s, %d", iso_mnt, strlen(iso_mnt));
571 mr_asprintf(iso_tmp, "%s", bkpinfo->isodir);
572 if (strlen(iso_tmp) < strlen(iso_mnt)) {
573 mr_asprintf(iso_dir, "%s", "");
574 } else {
575 // If iso_mnt is only / then iso_dir is the full dir
576 // (the formula bellow doesn't work in this case)
577 if (strcmp(iso_mnt, "/") == 0) {
578 mr_asprintf(iso_dir, "%s", iso_tmp);
579 // else it's a part of iso_tmp
580 } else {
581 mr_asprintf(iso_dir, "%s", iso_tmp + strlen(iso_mnt));
582 }
583 }
584 mr_free(iso_mnt);
585 mr_free(iso_tmp);
586
587 mr_asprintf(tmp, "%s/ISO-DIR", bkpinfo->tmpdir);
588 write_one_liner_data_file(tmp, iso_dir);
589 mr_free(tmp);
590
591 log_it("iso-dir: %s", iso_dir);
592 mr_free(iso_dir);
593
594 mr_asprintf(tmp, "%s/ISO-PREFIX", bkpinfo->tmpdir);
595 write_one_liner_data_file(tmp, bkpinfo->prefix);
596 mr_free(tmp);
597
598 log_it("iso-prefix: %s", bkpinfo->prefix);
599
600/* End patch */
601 } // end of iso code
602
603 if (bkpinfo->backup_media_type == netfs) {
604 mr_asprintf(tmp, "%s/ISO-PREFIX", bkpinfo->tmpdir);
605 write_one_liner_data_file(tmp, bkpinfo->prefix);
606 mr_free(tmp);
607
608 mr_asprintf(tmp, "%s/ISO-MNT", bkpinfo->tmpdir);
609 write_one_liner_data_file(tmp, bkpinfo->isodir);
610 mr_free(tmp);
611
612 mr_asprintf(tmp, "%s/ISO-DIR", bkpinfo->tmpdir);
613 write_one_liner_data_file(tmp, bkpinfo->netfs_remote_dir);
614 mr_free(tmp);
615
616 if (bkpinfo->netfs_mount) {
617 mr_asprintf(tmp, "%s/NETFS-SERVER-MOUNT", bkpinfo->tmpdir);
618 write_one_liner_data_file(tmp, bkpinfo->netfs_mount);
619 mr_free(tmp);
620 } else {
621 log_it("netfs_mount is NULL");
622 retval++;
623 }
624 }
625
626 log_it("Finished processing incoming params");
627 if (retval) {
628 fprintf(stderr, "Type 'man mondoarchive' for help.\n");
629 }
630 if (bkpinfo->include_paths == NULL) {
631 mr_asprintf(bkpinfo->include_paths, "/");
632 }
633 g_backup_media_type = bkpinfo->backup_media_type;
634 return (retval);
635}
636
637
638
639/**
640 * Do some miscellaneous setup tasks to be performed before filling @c bkpinfo.
641 * Seeds the random-number generator, loads important modules, checks the sanity
642 * of the user's Linux distribution, and deletes logfile.
643 * @param bkpinfo The backup information structure. Will be initialized.
644 * @return number of errors (0 for success)
645 */
646int pre_param_configuration()
647{
648 int res = 0;
649 char *tmp = NULL;
650
651 make_hole_for_dir(MNT_CDROM);
652 assert(bkpinfo != NULL);
653 srandom((unsigned long) (time(NULL)));
654 insmod_crucial_modules();
655 if (bkpinfo->disaster_recovery) {
656 if (!does_nonMS_partition_exist()) {
657 fatal_error("I am in disaster recovery mode\nPlease don't run mondoarchive.");
658 }
659 }
660
661 mr_asprintf(tmp,"rm -Rf %s/changed.files*",MONDO_CACHE);
662 run_program_and_log_output(tmp, FALSE);
663 paranoid_free(tmp);
664 if (find_and_store_mondoarchives_home(g_mondo_home)) {
665 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");
666 res++;
667 return (res);
668 }
669 res += some_basic_system_sanity_checks();
670 if (res) {
671 log_it("Your distribution did not pass Mondo's sanity test.");
672 }
673 g_current_media_number = 1;
674 bkpinfo->postnuke_tarball[0] = '\0';
675 return (res);
676}
677
678/* From busybox under GPLv2 */
679#ifndef HAVE_MKDTEMP
680/* This is now actually part of POSIX.1, but was only added in 2008 */
681char* mkdtemp(char *template)
682{
683 if (mkstemp(template) == -1) {
684 return NULL;
685 }
686 unlink(template);
687 if (mkdir(template, 0700) != 0) {
688 return NULL;
689 }
690 return template;
691}
692#endif
693
694void setup_tmpdir(char *path) {
695
696 char *tmp = NULL;
697 char *p = NULL;
698
699 if (bkpinfo->tmpdir[0] != '\0') {
700 /* purging a potential old tmpdir */
701 if (chdir("/tmp")) {
702 // FIXME
703 }
704 if (strstr(bkpinfo->tmpdir,"mondo.tmp.") != NULL) {
705 log_it("Purging old tmpdir %s", bkpinfo->tmpdir);
706 mr_asprintf(tmp,"rm -Rf %s",bkpinfo->tmpdir);
707 } else {
708 log_it("Purging old tmpdir %s/mondo.tmp.*", bkpinfo->tmpdir);
709 mr_asprintf(tmp,"rm -Rf %s/mondo.tmp.*",bkpinfo->tmpdir);
710 }
711 paranoid_system(tmp);
712 mr_free(tmp);
713 }
714
715 /* Always take in account arg first, then env, then default */
716 if (path != NULL) {
717 mr_system("mkdir -p %s",path);
718 log_it("Created temporary directory %s", path);
719 mr_asprintf(tmp, "%s/mondo.tmp.XXXXXX", path);
720 } else if (getenv("TMPDIR")) {
721 mr_system("mkdir -p %s",getenv("TMPDIR"));
722 log_it("Created temporary directory %s", getenv("TMPDIR"));
723 mr_asprintf(tmp, "%s/mondo.tmp.XXXXXX", getenv("TMPDIR"));
724 } else if (getenv("MRTMP")) {
725 mr_system("mkdir -p %s",getenv("MRTMP"));
726 log_it("Created temporary directory %s", getenv("MRTMP"));
727 mr_asprintf(tmp, "%s/mondo.tmp.XXXXXX", getenv("MRTMP"));
728 } else {
729 mr_asprintf(tmp, "/tmp/mondo.tmp.XXXXXX");
730 }
731 p = mkdtemp(tmp);
732 if (p == NULL) {
733 printf("Failed to create global tmp directory %s for Mondo.",tmp);
734 mr_free(tmp);
735 finish(-1);
736 }
737 strcpy(bkpinfo->tmpdir,p);
738 mr_free(tmp);
739
740 log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir);
741
742 mr_system("mkdir -p %s/tmpfs", bkpinfo->tmpdir);
743}
744
745void setup_scratchdir(char *path) {
746
747 char *tmp = NULL;
748 char *p = NULL;
749
750 if (bkpinfo->scratchdir != NULL) {
751 /* purging a potential old scratchdir */
752 if (chdir("/tmp")) {
753 // FIXME
754 }
755 if (strstr(bkpinfo->scratchdir,"mondo.scratch.") != NULL) {
756 log_it("Purging old scratchdir %s", bkpinfo->scratchdir);
757 mr_asprintf(tmp,"rm -Rf %s",bkpinfo->scratchdir);
758 } else {
759 log_it("Purging old scratchdir %s/mondo.scratch.*", bkpinfo->scratchdir);
760 mr_asprintf(tmp,"rm -Rf %s/mondo.scratch.*",bkpinfo->scratchdir);
761 }
762 paranoid_system(tmp);
763 mr_free(tmp);
764 }
765
766 /* Always take in account arg first, then env, then default */
767 if (path != NULL) {
768 mr_system("mkdir -p %s",path);
769 log_it("Created scratch directory %s", path);
770 mr_asprintf(tmp, "%s/mondo.scratch.XXXXXX", path);
771 } else if (getenv("MRSCRATCH")) {
772 mr_system("mkdir -p %s",getenv("MRSCRATCH"));
773 log_it("Created scratch directory %s", getenv("MRSCRATCH"));
774 mr_asprintf(tmp, "%s/mondo.scratch.XXXXXX", getenv("MRSCRATCH"));
775 } else {
776 mr_asprintf(tmp, "/tmp/mondo.scratch.XXXXXX");
777 }
778 p = mkdtemp(tmp);
779 if (p == NULL) {
780 log_it("Failed to create global scratch directory %s for Mondo.",tmp);
781 finish(-1);
782 }
783 strcpy(bkpinfo->scratchdir,p);
784 log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
785 paranoid_free(tmp);
786
787 mr_asprintf(tmp, "mkdir -p %s", bkpinfo->scratchdir);
788 paranoid_system(tmp);
789 mr_free(tmp);
790}
791
792
793/**
794 * Reset all fields of the backup information structure to a sensible default.
795 * @param bkpinfo The @c bkpinfo to reset.
796 */
797void reset_bkpinfo()
798{
799 assert(bkpinfo != NULL);
800 memset((void *) bkpinfo, 0, sizeof(struct s_bkpinfo));
801
802 bkpinfo->media_device[0] = '\0';
803 bkpinfo->media_size = -1;
804 bkpinfo->boot_loader = '\0';
805 bkpinfo->boot_device = NULL;
806 bkpinfo->zip_exe[0] = '\0';
807 bkpinfo->zip_suffix[0] = '\0';
808 bkpinfo->image_devs[0] = '\0';
809 bkpinfo->compression_level = 3;
810 bkpinfo->use_lzo = FALSE;
811 bkpinfo->use_gzip = FALSE;
812 bkpinfo->use_lzma = FALSE;
813 bkpinfo->verify_data = FALSE;
814 bkpinfo->backup_data = FALSE;
815 bkpinfo->restore_data = FALSE;
816 bkpinfo->use_star = FALSE;
817 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
818
819 /* We need tmpdir as early as possible for further function calls */
820 bkpinfo->tmpdir[0] = '\0'; // Really setup after
821 bkpinfo->scratchdir[0] = '\0'; // Really setup after
822 setup_tmpdir(NULL);
823 setup_scratchdir(NULL);
824
825 bkpinfo->disaster_recovery = am_I_in_disaster_recovery_mode();
826 if (bkpinfo->disaster_recovery) {
827 strcpy(bkpinfo->isodir, "/");
828 } else {
829 strcpy(bkpinfo->isodir, MONDO_CACHE);
830 }
831 strcpy(bkpinfo->prefix, STD_PREFIX);
832 bkpinfo->optimal_set_size = 0L;
833 bkpinfo->backup_media_type = none;
834 bkpinfo->make_filelist = TRUE; // unless -J supplied to mondoarchive
835 bkpinfo->exclude_paths = NULL;
836 bkpinfo->include_paths = NULL;
837 bkpinfo->exclude_devs = NULL;
838 bkpinfo->restore_path[0] = '\0';
839 bkpinfo->call_before_iso[0] = '\0';
840 bkpinfo->call_make_iso[0] = '\0';
841 bkpinfo->call_burn_iso[0] = '\0';
842 bkpinfo->call_after_iso[0] = '\0';
843 bkpinfo->kernel_path[0] = '\0';
844 bkpinfo->netfs_mount = NULL;
845 bkpinfo->netfs_proto = NULL;
846 bkpinfo->netfs_user = NULL;
847 bkpinfo->netfs_remote_dir = NULL;
848 bkpinfo->postnuke_tarball[0] = '\0';
849 bkpinfo->subdir = NULL;
850 bkpinfo->wipe_media_first = FALSE;
851 bkpinfo->differential = 0;
852 bkpinfo->please_dont_eject = FALSE;
853 bkpinfo->cdrw_speed = 0;
854 bkpinfo->manual_cd_tray = FALSE;
855 bkpinfo->nonbootable_backup = FALSE;
856 bkpinfo->make_cd_use_lilo = FALSE;
857 bkpinfo->use_obdr = FALSE;
858 bkpinfo->restore_mode = interactive;
859 bkpinfo->boot_type = BIOS;
860}
861
862
863/**
864 * Get the remaining free space (in MB) on @p partition.
865 * @param partition The partition to check free space on (either a device or a mountpoint).
866 * @return The free space on @p partition, in MB.
867 */
868long free_space_on_given_partition(char *partition)
869{
870 char *out_sz = NULL;
871 char *command = NULL;
872 long res;
873
874 assert_string_is_neither_NULL_nor_zerolength(partition);
875
876 mr_asprintf(command, "df -m -P %s 1> /dev/null 2> /dev/null", partition);
877 if (system(command)) {
878 mr_free(command);
879 return (-1);
880 } // partition does not exist
881 mr_free(command);
882
883 mr_asprintf(command, "df -m -P %s | tail -n1 | tr -s ' ' '\t' | cut -f4", partition);
884 mr_asprintf(out_sz, "%s", call_program_and_get_last_line_of_output(command));
885 mr_free(command);
886
887 if (strlen(out_sz) == 0) {
888 mr_free(out_sz);
889 return (-1);
890 } // error within df, probably
891 res = atol(out_sz);
892 mr_free(out_sz);
893 return (res);
894}
895
896
897
898/**
899 * Check the user's system for sanity. Checks performed:
900 * - make sure user has enough RAM (32mb required, 64mb recommended)
901 * - make sure user has enough free space in @c /
902 * - check kernel for ramdisk support
903 * - make sure afio, cdrecord, mkisofs, bzip2, awk, md5sum, strings, mindi, and buffer exist
904 * - make sure CD-ROM is unmounted
905 * - make sure user's mountlist is OK by running <tt>mindi --makemountlist</tt>
906 *
907 * @return number of problems with the user's setup (0 for success)
908 */
909int some_basic_system_sanity_checks()
910{
911
912 /*@ buffers ************ */
913 char *tmp = NULL;
914
915 /*@ int's *************** */
916 int retval = 0;
917
918 mvaddstr_and_log_it(g_currentY, 0, "Checking sanity of your Linux distribution");
919#ifndef __FreeBSD__
920 if (system("which mkfs.vfat 2> /dev/null 1> /dev/null")
921 && !system("which mkfs.msdos 2> /dev/null 1> /dev/null")) {
922 log_it("OK, you've got mkfs.msdos but not mkfs.vfat; time for the fairy to wave her magic wand...");
923 run_program_and_log_output("ln -sf `which mkfs.msdos` /sbin/mkfs.vfat", FALSE);
924 }
925 mr_asprintf(tmp, "%s", call_program_and_get_last_line_of_output("free | grep Mem | head -n1 | tr -s ' ' '\t' | cut -f2"));
926 if (atol(tmp) < 35000) {
927 retval++;
928 log_to_screen("You must have at least 32MB of RAM to use Mondo.");
929 }
930 if (atol(tmp) < 66000) {
931 log_to_screen("WARNING! You have very little RAM. Please upgrade to 64MB or more.");
932 }
933 mr_free(tmp);
934#endif
935
936 if (system("which " MKE2FS_OR_NEWFS " > /dev/null 2> /dev/null")) {
937 retval++;
938 log_to_screen
939 ("Unable to find " MKE2FS_OR_NEWFS " in system path.");
940 fatal_error
941 ("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. :)");
942 }
943#ifndef __FreeBSD__
944 if (run_program_and_log_output
945 ("grep ramdisk /proc/devices", FALSE)) {
946 /* Some SuSE have ramdisk as modules, so insert it first, then test again */
947 run_program_and_log_output("modprobe brd 2> /dev/null > /dev/null",FALSE);
948 if (run_program_and_log_output("grep ramdisk /proc/devices", FALSE)) {
949 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?")) {
950 // retval++;
951 log_to_screen("It looks as if your kernel lacks ramdisk and initrd support.");
952 log_to_screen("I'll allow you to proceed but FYI, if I'm right, your kernel is broken.");
953 }
954 }
955 }
956#endif
957 retval += whine_if_not_found(MKE2FS_OR_NEWFS);
958 if (system("which xorriso > /dev/null 2> /dev/null")) {
959 if (system("which genisoimage > /dev/null 2> /dev/null")) {
960 retval += whine_if_not_found("mkisofs");
961 }
962 }
963 if (system("which wodim > /dev/null 2> /dev/null")) {
964 retval += whine_if_not_found("cdrecord");
965 }
966 retval += whine_if_not_found("bzip2");
967 retval += whine_if_not_found("gzip");
968 retval += whine_if_not_found("awk");
969 retval += whine_if_not_found("md5sum");
970 retval += whine_if_not_found("strings");
971 retval += whine_if_not_found("mindi");
972 retval += whine_if_not_found("buffer");
973
974 // abort if Windows partition but no ms-sys and parted
975 if (!run_program_and_log_output("mount | grep -Ew 'vfat|fat|dos' | grep -vE \"/dev/fd|nexdisk\"", 0)) {
976 if (!run_program_and_log_output("mount | grep -Ew 'vfat|fat|dos' | grep -Ew efi", 0)) {
977 log_to_screen("I think you have a EFI/UEFI partition.");
978 } else {
979 log_to_screen("I think you have a Windows 9x partition.");
980 }
981 retval += whine_if_not_found("parted");
982 }
983
984 if (!find_home_of_exe("cmp")) {
985 whine_if_not_found("cmp");
986 }
987 run_program_and_log_output("umount `mount | grep cdr | cut -d' ' -f3 | tr '\n' ' '`", 5);
988 mr_asprintf(tmp, "%s", call_program_and_get_last_line_of_output("mount | grep -E \"cdr(om|w)\""));
989 if (strcmp("", tmp)) {
990 if (strstr(tmp, "autofs")) {
991 log_to_screen("Your CD-ROM is mounted via autofs. I therefore cannot tell");
992 log_to_screen("if a CD actually is inserted. If a CD is inserted, please");
993 log_to_screen("eject it. Thank you.");
994 log_it("Ignoring autofs CD-ROM 'mount' since we hope nothing's in it.");
995 } else
996 if (run_program_and_log_output("uname -a | grep Knoppix", 5)) {
997 retval++;
998 mr_free(tmp);
999 fatal_error("Your CD-ROM drive is mounted. Please unmount it.");
1000 }
1001 }
1002 mr_free(tmp);
1003
1004 run_program_and_log_output("cat /etc/fstab", 5);
1005#ifdef __FreeBSD__
1006 run_program_and_log_output("vinum printconfig", 5);
1007#else
1008 run_program_and_log_output("cat /etc/raidtab", 5);
1009#endif
1010
1011 if (run_program_and_log_output("mindi -V", 1)) {
1012 log_to_screen("Could not ascertain mindi's version number.");
1013 log_to_screen("You have not installed Mondo and/or Mindi properly.");
1014 log_to_screen("Please uninstall and reinstall them both.");
1015 fatal_error("Please reinstall Mondo and Mindi.");
1016 }
1017 mr_asprintf(tmp, "mindi --makemountlist %s/mountlist.txt.test", bkpinfo->tmpdir);
1018 if (run_program_and_log_output(tmp, 5)) {
1019 log_to_screen("%s failed for some reason.", tmp);
1020 mr_free(tmp);
1021 log_to_screen("Please run that command by hand and examine "MINDI_LOGFILE);
1022 log_to_screen("for more information. Perhaps your /etc/fstab file is insane.");
1023 log_to_screen("Perhaps Mindi's MakeMountlist() subroutine has a bug. We'll see.");
1024 retval++;
1025 }
1026 mr_free(tmp);
1027
1028 if (!run_program_and_log_output("mr-parted2fdisk -l 2>/dev/null | grep -i raid", 1) && !does_file_exist("/etc/raidtab")) {
1029 log_to_screen("You have RAID partitions but no /etc/raidtab - creating one from /proc/mdstat");
1030 create_raidtab_from_mdstat(MDSTAT_FILE,"/etc/raidtab");
1031 }
1032
1033 if (retval) {
1034 mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1035 } else {
1036 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1037 }
1038 return (retval);
1039}
1040
1041/**
1042 * Retrieve the line containing @p label from the config file.
1043 * @param config_file The file to read from, usually @c /tmp/mondorestore.cfg.
1044 * @param label What to read from the file.
1045 * @param value Where to put it.
1046 * @return 0 for success, 1 for failure.
1047 */
1048int read_cfg_var(char *config_file, char *label, char *value)
1049{
1050 /*@ buffer ****************************************************** */
1051 char *command = NULL;
1052
1053 /*@ end vars *************************************************** */
1054
1055 assert_string_is_neither_NULL_nor_zerolength(config_file);
1056 assert_string_is_neither_NULL_nor_zerolength(label);
1057 if (!does_file_exist(config_file)) {
1058 log_to_screen("(read_cfg_var) Cannot find %s config file", config_file);
1059 value[0] = '\0';
1060 return (1);
1061 } else if ((value != NULL) && (strstr(value, "/dev/") && strstr(value, "t0") && !strcmp(label, "media-dev"))) {
1062 log_msg(2, "FYI, I can't read new value for %s - already got %s", label, value);
1063 return (0);
1064 } else {
1065 mr_asprintf(command, "grep '%s .*' %s| cut -d' ' -f2,3,4,5", label, config_file);
1066 strcpy(value, call_program_and_get_last_line_of_output(command));
1067 mr_free(command);
1068
1069 log_msg(4, "Configuration item %s is %s", label, value);
1070 if (strlen(value) == 0) {
1071 return (1);
1072 } else {
1073 return (0);
1074 }
1075 }
1076}
1077
1078
1079
1080/**
1081 * Remount @c supermount if it was unmounted earlier.
1082 */
1083void remount_supermounts_if_necessary()
1084{
1085 if (g_remount_cdrom_at_end) {
1086 run_program_and_log_output("mount " MNT_CDROM, FALSE);
1087 }
1088 if (g_remount_floppy_at_end) {
1089 run_program_and_log_output("mount " MNT_FLOPPY, FALSE);
1090 }
1091}
1092
1093/**
1094 * Unmount @c supermount if it's mounted.
1095 */
1096void unmount_supermounts_if_necessary()
1097{
1098 if (run_program_and_log_output
1099 ("mount | grep cdrom | grep super", FALSE) == 0) {
1100 g_remount_cdrom_at_end = TRUE;
1101 run_program_and_log_output("umount " MNT_CDROM, FALSE);
1102 }
1103 if (run_program_and_log_output
1104 ("mount | grep floppy | grep super", FALSE) == 0) {
1105 g_remount_floppy_at_end = TRUE;
1106 run_program_and_log_output("umount " MNT_FLOPPY, FALSE);
1107 }
1108}
1109
1110/**
1111 * Whether we had to stop autofs (if so, restart it at end).
1112 */
1113bool g_autofs_stopped = FALSE;
1114
1115/**
1116 * Path to the autofs initscript ("" if none exists).
1117 */
1118char g_autofs_exe[MAX_STR_LEN];
1119
1120/**
1121 * Autofs initscript in Xandros Linux distribution.
1122 */
1123#define XANDROS_AUTOFS_FNAME "/etc/init.d/xandros-autofs"
1124
1125/**
1126 * Autofs initscript in most Linux distributions.
1127 */
1128#define STOCK_AUTOFS_FNAME "/etc/rc.d/init.d/autofs"
1129
1130/**
1131 * If autofs is mounted, stop it (restart at end).
1132 */
1133void stop_autofs_if_necessary()
1134{
1135 char *tmp = NULL;
1136
1137 g_autofs_exe[0] = '\0';
1138 if (does_file_exist(XANDROS_AUTOFS_FNAME)) {
1139 strcpy(g_autofs_exe, XANDROS_AUTOFS_FNAME);
1140 } else if (does_file_exist(STOCK_AUTOFS_FNAME)) {
1141 strcpy(g_autofs_exe, STOCK_AUTOFS_FNAME);
1142 }
1143
1144 if (!g_autofs_exe[0]) {
1145 log_msg(3, "No autofs detected.");
1146 } else {
1147 log_msg(3, "%s --- autofs detected", g_autofs_exe);
1148 // FIXME -- only disable it if it's running --- sprintf(tmp, "%s status", autofs_exe);
1149 mr_asprintf(tmp, "%s stop", g_autofs_exe);
1150 if (run_program_and_log_output(tmp, 2)) {
1151 log_it("Failed to stop autofs - I assume it wasn't running");
1152 } else {
1153 g_autofs_stopped = TRUE;
1154 log_it("Stopped autofs OK");
1155 }
1156 mr_free(tmp);
1157 }
1158}
1159
1160/**
1161 * If autofs was stopped earlier, restart it.
1162 */
1163void restart_autofs_if_necessary()
1164{
1165 char *tmp = NULL;
1166
1167 if (!g_autofs_stopped || !g_autofs_exe[0]) {
1168 log_msg(3, "No autofs detected.");
1169 return;
1170 }
1171 mr_asprintf(tmp, "%s start", g_autofs_exe);
1172 if (run_program_and_log_output(tmp, 2)) {
1173 log_it("Failed to start autofs");
1174 } else {
1175 g_autofs_stopped = FALSE;
1176 log_it("Started autofs OK");
1177 }
1178 mr_free(tmp);
1179}
1180
1181
1182/**
1183 * If this is a distribution like Gentoo that doesn't keep /boot mounted, mount it.
1184 */
1185void mount_boot_if_necessary() {
1186 char *tmp = NULL;
1187 char *command = NULL;
1188
1189 log_msg(1, "Started sub");
1190 log_msg(4, "About to set g_boot_mountpt[0] to '\\0'");
1191 g_boot_mountpt[0] = '\0';
1192 log_msg(4, "Done. Great. Seeting command to something");
1193 mr_asprintf(command, "%s", "grep -v \":\" /etc/fstab | grep -vE '^#.*$' | grep -E \"[ ]/boot[ ]\" | tr -s ' ' '\t' | cut -f1 | head -n1");
1194 log_msg(4, "Cool. Command = '%s'", command);
1195 mr_asprintf(tmp, "%s", call_program_and_get_last_line_of_output(command));
1196 mr_free(command);
1197
1198 log_msg(4, "tmp = '%s'", tmp);
1199 log_it("/boot is at %s according to /etc/fstab", tmp);
1200 mr_asprintf(command, "mount | grep -Ew '/boot'");
1201 mr_free(tmp);
1202
1203 mr_asprintf(tmp, "%s", call_program_and_get_last_line_of_output(command));
1204 mr_free(command);
1205
1206 if (!strcmp(tmp,"")) {
1207 if ((strstr(tmp, "LABEL=") != NULL) || (strstr(tmp,"UUID=") != NULL)) {
1208 if (!run_program_and_log_output("mount /boot", 5)) {
1209 strcpy(g_boot_mountpt, "/boot");
1210 log_msg(1, "Mounted /boot");
1211 } else {
1212 log_it("...ignored cos it's a label or uuid :-)");
1213 }
1214 } else {
1215 mr_asprintf(command, "mount | grep -E '^%s'", tmp);
1216 log_msg(3, "command = %s", command);
1217 if (run_program_and_log_output(command, 5)) {
1218 strcpy(g_boot_mountpt, tmp);
1219 mr_free(tmp);
1220 log_it("%s (your /boot partition) is not mounted. I'll mount it before backing up", g_boot_mountpt);
1221
1222 mr_asprintf(tmp, "mount %s", g_boot_mountpt);
1223 if (run_program_and_log_output(tmp, 5)) {
1224 g_boot_mountpt[0] = '\0';
1225 log_msg(1, "Plan B");
1226 if (!run_program_and_log_output("mount /boot", 5)) {
1227 strcpy(g_boot_mountpt, "/boot");
1228 log_msg(1, "Plan B worked");
1229 } else {
1230 log_msg(1,
1231 "Plan B failed. Unable to mount /boot for backup purposes. This probably means /boot is mounted already, or doesn't have its own partition.");
1232 }
1233 }
1234 }
1235 mr_free(command);
1236 }
1237 }
1238 mr_free(tmp);
1239 log_msg(1, "Ended sub");
1240}
1241
1242
1243/**
1244 * If we mounted /boot earlier, unmount it.
1245 */
1246void unmount_boot_if_necessary()
1247{
1248 char *tmp = NULL;
1249
1250 log_msg(3, "starting");
1251 if (g_boot_mountpt[0]) {
1252 mr_asprintf(tmp, "umount %s", g_boot_mountpt);
1253 if (run_program_and_log_output(tmp, 5)) {
1254 log_it("WARNING - unable to unmount /boot");
1255 }
1256 mr_free(tmp);
1257 }
1258 log_msg(3, "leaving");
1259}
1260
1261
1262
1263/**
1264 * Write a line to a configuration file. Writes a line of the form,
1265 * @c label @c value.
1266 * @param config_file The file to write to. Usually @c mondorestore.cfg.
1267 * @param label What to call this bit of data you're writing.
1268 * @param value The bit of data you're writing.
1269 * @return 0 for success, 1 for failure.
1270 */
1271int write_cfg_var(char *config_file, char *label, char *value)
1272{
1273 /*@ buffers ***************************************************** */
1274 char *command = NULL;
1275 char *tempfile = NULL;
1276
1277
1278 /*@ end vars *************************************************** */
1279 assert_string_is_neither_NULL_nor_zerolength(config_file);
1280 assert_string_is_neither_NULL_nor_zerolength(label);
1281 assert(value != NULL);
1282 if (!does_file_exist(config_file)) {
1283 log_to_screen("(write_cfg_file) Cannot find %s config file", config_file);
1284 return (1);
1285 }
1286 mr_asprintf(tempfile, "%s/mojo-jojo.blah", bkpinfo->tmpdir);
1287 if (does_file_exist(config_file)) {
1288 mr_asprintf(command, "grep -vE '^%s .*$' %s > %s", label, config_file, tempfile);
1289 paranoid_system(command);
1290 mr_free(command);
1291 }
1292 mr_asprintf(command, "echo \"%s %s\" >> %s", label, value, tempfile);
1293 paranoid_system(command);
1294 mr_free(command);
1295
1296 mr_asprintf(command, "mv -f %s %s", tempfile, config_file);
1297 paranoid_system(command);
1298 mr_free(command);
1299 unlink(tempfile);
1300 mr_free(tempfile);
1301 return (0);
1302}
1303
1304
1305/**
1306 * The standard log_debug_msg() (log_msg() also due to a macro). Writes some describing
1307 * information to the logfile.
1308 */
1309void standard_log_debug_msg(int debug_level, const char *szFile, const char *szFunction, int nLine, const char *fmt, ...) {
1310
1311 va_list args;
1312 static int depth = 0;
1313 FILE *fout;
1314
1315 if (depth > 5) {
1316 depth--;
1317 return;
1318 }
1319 depth++;
1320
1321 if (debug_level <= g_loglevel) {
1322 if (!(fout = fopen(MONDO_LOGFILE, "a"))) {
1323 return;
1324 }
1325
1326 // add tabs to distinguish log levels
1327 if (debug_level > 0) {
1328 fprintf(fout, "DBG%d: ", debug_level);
1329 if (getpid() == g_main_pid)
1330 fprintf(fout, "[Main] %s->%s#%d: ", szFile, szFunction, nLine);
1331 else if (getpid() == g_buffer_pid && g_buffer_pid > 0)
1332 fprintf(fout, "[Buff] %s->%s#%d: ", szFile, szFunction, nLine);
1333 else
1334 fprintf(fout, "[TH=%d] %s->%s#%d: ", getpid(), szFile, szFunction, nLine);
1335 } else {
1336 fprintf(fout, "INFO: ");
1337 }
1338 va_start(args, fmt);
1339 vfprintf(fout, fmt, args);
1340 va_end(args);
1341
1342 fprintf(fout, "\n");
1343 paranoid_fclose(fout);
1344 }
1345 depth--;
1346}
1347
1348/**
1349 * Function pointer to the @c log_debug_msg function to use. Points to standard_log_debug_msg() by default.
1350 */
1351void (*log_debug_msg) (int, const char *, const char *, int, const char *, ...) = standard_log_debug_msg;
1352
1353
1354/**
1355 * Allocate or free important globals, depending on @p mal.
1356 * @param mal If TRUE, malloc; if FALSE, free.
1357 */
1358void do_libmondo_global_strings_thing(int mal)
1359{
1360 if (mal) {
1361 malloc_string(g_boot_mountpt);
1362 malloc_string(g_mondo_home);
1363 malloc_string(g_serial_string);
1364 malloc_string(g_magicdev_command);
1365 } else {
1366 paranoid_free(g_boot_mountpt);
1367 paranoid_free(g_mondo_home);
1368 paranoid_free(g_magicdev_command);
1369
1370 mr_free(g_serial_string);
1371 }
1372}
1373
1374/**
1375 * Allocate important globals.
1376 * @see do_libmondo_global_strings_thing
1377 */
1378void malloc_libmondo_global_strings(void)
1379{
1380 do_libmondo_global_strings_thing(1);
1381}
1382
1383/**
1384 * Free important globals.
1385 * @see do_libmondo_global_strings_thing
1386 */
1387void free_libmondo_global_strings(void)
1388{
1389 do_libmondo_global_strings_thing(0);
1390}
1391
1392
1393
1394/**
1395 * Stop @c magicdev if it's running.
1396 * The command used to start it is saved in @p g_magicdev_command.
1397 */
1398void stop_magicdev_if_necessary()
1399{
1400 strcpy(g_magicdev_command, call_program_and_get_last_line_of_output("ps ax | grep -w magicdev | grep -v grep | tr -s '\t' ' '| cut -d' ' -f6-99"));
1401 if (g_magicdev_command[0]) {
1402 log_msg(1, "g_magicdev_command = '%s'", g_magicdev_command);
1403 paranoid_system("killall magicdev");
1404 }
1405}
1406
1407
1408/**
1409 * Restart magicdev if it was stopped.
1410 */
1411void restart_magicdev_if_necessary()
1412{
1413 char *tmp = NULL;
1414
1415 if (g_magicdev_command && g_magicdev_command[0]) {
1416 mr_asprintf(tmp, "%s &", g_magicdev_command);
1417 paranoid_system(tmp);
1418 mr_free(tmp);
1419 }
1420}
1421
1422/* @} - end of utilityGroup */
Note: See TracBrowser for help on using the repository browser.