source: MondoRescue/branches/stable/mondo/mondo/common/libmondo-files.c@ 681

Last change on this file since 681 was 681, checked in by andree, 18 years ago

Replaced all occurrences of egrep with 'grep -E' and of fgrep with
'grep -F' in mondo.
egrep and fgrep are usually just script wrappers around grep these
days which means additional overhead compared to calling grep with the
relevant option. Also, it appears that egrep and fgrep have been
deprecated by POSIX some time ago.

  • Property svn:keywords set to Id
File size: 40.5 KB
Line 
1/* libmondo-files.c file manipulation
2 $Id: libmondo-files.c 681 2006-06-25 02:41:57Z andree $
3.
4
5
604/16/04
7- find_home_of_exe() really does return NULL now if file not found
8
903/22/04
10- added mode_of_file()
11
1210/02/03
13- cleaned up grab_percentage_from_last_line_of_file()
14
1509/18
16- added int make_grub_install_scriptlet()
17
1809/16
19- cleaned up mkisofs feedback window
20
2109/12
22- fixed Teuton-hostile bug in size_of_all_biggiefiles_K()
23
2409/05
25- added size_of_partition_in_mountlist_K()
26- size_of_all_biggiefiles_K() now calls get_phys_size_of_drive(fname)
27
2807/02
29- fixed calls to popup_and_get_string()
30
3105/19
32- added CP_BIN
33
3405/05
35- added Joshua Oreman's FreeBSD patches
36
3705/04
38- find_home_of_exe() now returns NULL if file not found
39
4004/26
41- if >4 media est'd, say one meeeellion
42
4304/25
44- fixed minor bug in find_home_of_exe()
45
4604/24
47- added lots of assert()'s and log_OS_error()'s
48
4904/07
50- fix find_home_of_exe()
51- cleaned up code a bit
52
5303/27
54- copy_mondo_and_mindi_stuff --- if _homedir_/payload.tgz exists then untar it to CD
55
5601/14/2003
57- if backup media type == nfs then don't estimate no. of media reqd
58
5911/25/2002
60- don't log/echo estimated # of media required if >=50
61
6210/01 - 11/09
63- chmod uses 0x, not decimal :)
64- added is_this_file_compressed()
65- replace convoluted grep with wc (KP)
66
6709/01 - 09/30
68- only show "number of media" estimate if no -x
69- run_program_and_log_output() now takes boolean operator to specify
70 whether it will log its activities in the event of _success_
71
7208/01 - 08/31
73- handle unknown media sizes
74- cleaned up some log_it() calls
75
7607/24
77- created
78*/
79
80/**
81 * @file
82 * Functions to manipulate files.
83 */
84
85
86#include "my-stuff.h"
87#include "mondostructures.h"
88#include "libmondo-files.h"
89
90#include "lib-common-externs.h"
91
92#include "libmondo-tools-EXT.h"
93#include "libmondo-gui-EXT.h"
94#include "libmondo-devices-EXT.h"
95#include "libmondo-fork-EXT.h"
96#include "libmondo-string-EXT.h"
97
98/*@unused@*/
99//static char cvsid[] = "$Id: libmondo-files.c 681 2006-06-25 02:41:57Z andree $";
100
101extern char err_log_lines[NOOF_ERR_LINES][MAX_STR_LEN];
102
103extern int g_currentY;
104extern char *g_mondo_home;
105
106/**
107 * @addtogroup fileGroup
108 * @{
109 */
110/**
111 * Get an md5 checksum of the specified file.
112 * @param filename The file to checksum.
113 * @return The 32-character ASCII representation of the 128-bit checksum.
114 * @note The returned string points to static storage that will be overwritten with each call.
115 */
116char *calc_checksum_of_file(char *filename)
117{
118 /*@ buffers ***************************************************** */
119 static char output[MAX_STR_LEN];
120 char command[MAX_STR_LEN * 2];
121 char tmp[MAX_STR_LEN];
122
123 /*@ pointers **************************************************** */
124 char *p;
125 FILE *fin;
126
127 /*@ initialize pointers ***************************************** */
128
129 p = output;
130
131 /*@************************************************************** */
132
133 assert_string_is_neither_NULL_nor_zerolength(filename);
134 if (does_file_exist(filename)) {
135 sprintf(command, "md5sum \"%s\"", filename);
136 fin = popen(command, "r");
137 if (fin) {
138 (void) fgets(output, MAX_STR_LEN, fin);
139 p = strchr(output, ' ');
140 paranoid_pclose(fin);
141 }
142 } else {
143 sprintf(tmp, "File '%s' not found; cannot calc checksum",
144 filename);
145 log_it(tmp);
146 }
147 if (p) {
148 *p = '\0';
149 }
150 return (output);
151}
152
153
154/**
155 * Get a not-quite-unique representation of some of the file's @c stat properties.
156 * The returned string has the form <tt>size-mtime-ctime</tt>.
157 * @param curr_fname The file to generate the "checksum" for.
158 * @return The "checksum".
159 * @note The returned string points to static storage that will be overwritten with each call.
160 */
161char *calc_file_ugly_minichecksum(char *curr_fname)
162{
163
164 /*@ buffers ***************************************************** */
165 static char curr_cksum[1000];
166
167 /*@ pointers **************************************************** */
168
169 /*@ structures ************************************************** */
170 struct stat buf;
171
172 /*@ initialize data *************************************************** */
173 curr_cksum[0] = '\0';
174
175 /*@************************************************************** */
176
177 assert_string_is_neither_NULL_nor_zerolength(curr_fname);
178 if (lstat(curr_fname, &buf)) {
179 return (curr_cksum); // empty
180 }
181
182 sprintf(curr_cksum, "%ld-%ld-%ld", (long) (buf.st_size),
183 (long) (buf.st_mtime), (long) (buf.st_ctime));
184 return (curr_cksum);
185}
186
187
188
189/**
190 * Get the number of lines in @p filename.
191 * @param filename The file to count lines in.
192 * @return The number of lines in @p filename.
193 * @bug This function uses the shell and "wc -l"; it should probably be rewritten in C.
194 */
195long count_lines_in_file(char *filename)
196{
197
198 /*@ buffers ***************************************************** */
199 char command[MAX_STR_LEN * 2];
200 char incoming[MAX_STR_LEN];
201 char tmp[MAX_STR_LEN];
202
203 /*@ long ******************************************************** */
204 long noof_lines = -1L;
205
206 /*@ pointers **************************************************** */
207 FILE *fin;
208
209 /*@ initialize [0] to null ******************************************** */
210 incoming[0] = '\0';
211
212 assert_string_is_neither_NULL_nor_zerolength(filename);
213 if (!does_file_exist(filename)) {
214 sprintf(tmp,
215 "%s does not exist, so I cannot found the number of lines in it",
216 filename);
217 log_it(tmp);
218 return (0);
219 }
220 sprintf(command, "cat %s | wc -l", filename);
221 if (!does_file_exist(filename)) {
222 return (-1);
223 }
224 fin = popen(command, "r");
225 if (fin) {
226 if (feof(fin)) {
227 noof_lines = 0;
228 } else {
229 (void) fgets(incoming, MAX_STR_LEN - 1, fin);
230 while (strlen(incoming) > 0
231 && incoming[strlen(incoming) - 1] < 32) {
232 incoming[strlen(incoming) - 1] = '\0';
233 }
234 noof_lines = atol(incoming);
235 }
236 paranoid_pclose(fin);
237 }
238 return (noof_lines);
239}
240
241
242/**
243 * Check for existence of given @p filename.
244 * @param filename The file to check for.
245 * @return TRUE if it exists, FALSE otherwise.
246 */
247bool does_file_exist(char *filename)
248{
249
250 /*@ structures ************************************************** */
251 struct stat buf;
252
253 /*@************************************************************** */
254
255 assert(filename != NULL);
256 // assert_string_is_neither_NULL_nor_zerolength(filename);
257 if (lstat(filename, &buf)) {
258 log_msg(20, "%s does not exist", filename);
259 return (FALSE);
260 } else {
261 log_msg(20, "%s exists", filename);
262 return (TRUE);
263 }
264}
265
266
267
268
269
270
271/**
272 * Modify @p inout (a file containing a list of files) to only contain files
273 * that exist.
274 * @param inout The filelist to operate on.
275 * @note The original file is renamed beforehand, so it will not be accessible
276 * while the modification is in progress.
277 */
278void exclude_nonexistent_files(char *inout)
279{
280 char infname[MAX_STR_LEN];
281 char outfname[MAX_STR_LEN];
282 char tmp[MAX_STR_LEN];
283 char incoming[MAX_STR_LEN];
284
285 /*@ int ********************************************************* */
286 int i;
287
288 /*@ pointers **************************************************** */
289 FILE *fin, *fout;
290
291
292 /*@ end vars *********************************************************** */
293
294 assert_string_is_neither_NULL_nor_zerolength(inout);
295 sprintf(infname, "%s.in", inout);
296 sprintf(outfname, "%s", inout);
297 sprintf(tmp, "cp -f %s %s", inout, infname);
298 run_program_and_log_output(tmp, FALSE);
299 if (!(fin = fopen(infname, "r"))) {
300 log_OS_error("Unable to openin infname");
301 return;
302 }
303 if (!(fout = fopen(outfname, "w"))) {
304 log_OS_error("Unable to openout outfname");
305 return;
306 }
307 for (fgets(incoming, MAX_STR_LEN, fin); !feof(fin);
308 fgets(incoming, MAX_STR_LEN, fin)) {
309 i = strlen(incoming) - 1;
310 if (i >= 0 && incoming[i] < 32) {
311 incoming[i] = '\0';
312 }
313 if (does_file_exist(incoming)) {
314 fprintf(fout, "%s\n", incoming);
315 } else {
316 sprintf(tmp, "Excluding '%s'-nonexistent\n", incoming);
317 log_it(tmp);
318 }
319 }
320 paranoid_fclose(fout);
321 paranoid_fclose(fin);
322 unlink(infname);
323}
324
325
326
327
328
329
330
331
332
333/**
334 * Attempt to find the user's kernel by calling Mindi.
335 * If Mindi can't find the kernel, ask user. If @p kernel is not empty,
336 * don't do anything.
337 * @param kernel Where to put the found kernel.
338 * @return 0 for success, 1 for failure.
339 */
340int figure_out_kernel_path_interactively_if_necessary(char *kernel)
341{
342 char tmp[MAX_STR_LEN];
343 char *command;
344
345 if (!kernel[0]) {
346 strcpy(kernel,
347 call_program_and_get_last_line_of_output
348 ("mindi --findkernel 2> /dev/null"));
349 }
350 // If we didn't get anything back, check whether mindi raised a fatal error
351 if (!kernel[0]) {
352 malloc_string(command);
353 strcpy(command, "grep 'Fatal error' /var/log/mindi.log");
354 strcpy(tmp, call_program_and_get_last_line_of_output(command));
355 if (strlen(tmp) > 1) {
356 popup_and_OK(tmp);
357 fatal_error("Mindi gave a fatal error. Please check '/var/log/mindi.log'.");
358 }
359 paranoid_free(command);
360 }
361 log_it("Calling Mindi with kernel path of '%s'", kernel);
362 while (!kernel[0]) {
363 if (!ask_me_yes_or_no
364 ("Kernel not found or invalid. Choose another?")) {
365 return (1);
366 }
367 if (!popup_and_get_string
368 ("Kernel path",
369 "What is the full path and filename of your kernel, please?",
370 kernel, MAX_STR_LEN / 4)) {
371 fatal_error
372 ("Kernel not found. Please specify with the '-k' flag.");
373 }
374 sprintf(tmp, "User says kernel is at %s", kernel);
375 log_it(tmp);
376 }
377 return (0);
378}
379
380
381
382
383
384
385/**
386 * Find location of specified executable in user's PATH.
387 * @param fname The basename of the executable to search for (e.g. @c afio).
388 * @return The full path to the executable, or "" if it does not exist, or NULL if @c file could not be found.
389 * @note The returned string points to static storage that will be overwritten with each call.
390 * @bug The checks with @c file and @c dirname seem pointless. If @c incoming is "", then you're calling
391 * <tt>dirname 2\>/dev/null</tt> or <tt>file 2\>/dev/null | cut -d':' -f1 2\>/dev/null</tt>, which basically amounts
392 * to nothing.
393 */
394char *find_home_of_exe(char *fname)
395{
396 /*@ buffers ********************* */
397 static char output[MAX_STR_LEN];
398 char *incoming;
399 char *command;
400
401 malloc_string(incoming);
402 malloc_string(command);
403 incoming[0] = '\0';
404 /*@******************************* */
405
406 assert_string_is_neither_NULL_nor_zerolength(fname);
407 sprintf(command, "which %s 2> /dev/null", fname);
408 strcpy(incoming, call_program_and_get_last_line_of_output(command));
409 if (incoming[0] == '\0') {
410 if (system("which file > /dev/null 2> /dev/null")) {
411 paranoid_free(incoming);
412 paranoid_free(command);
413 output[0] = '\0';
414 return (NULL); // forget it :)
415 }
416 sprintf(command,
417 "file %s 2> /dev/null | cut -d':' -f1 2> /dev/null",
418 incoming);
419 strcpy(incoming,
420 call_program_and_get_last_line_of_output(command));
421 }
422 if (incoming[0] == '\0') // yes, it is == '\0' twice, not once :)
423 {
424 sprintf(command, "dirname %s 2> /dev/null", incoming);
425 strcpy(incoming,
426 call_program_and_get_last_line_of_output(command));
427 }
428 strcpy(output, incoming);
429 if (output[0] != '\0' && does_file_exist(output)) {
430 log_msg(4, "find_home_of_exe () --- Found %s at %s", fname,
431 incoming);
432 } else {
433 output[0] = '\0';
434 log_msg(4, "find_home_of_exe() --- Could not find %s", fname);
435 }
436 paranoid_free(incoming);
437 paranoid_free(command);
438 if (!output[0]) {
439 return (NULL);
440 } else {
441 return (output);
442 }
443}
444
445
446
447
448
449
450
451
452/**
453 * Get the last sequence of digits surrounded by non-digits in the first 32k of
454 * a file.
455 * @param logfile The file to look in.
456 * @return The number found, or 0 if none.
457 */
458int get_trackno_from_logfile(char *logfile)
459{
460
461 /*@ pointers ********************************************************* */
462 FILE *fin;
463
464 /*@ int ************************************************************** */
465 int trackno = 0;
466 size_t len = 0;
467
468 /*@ buffer ************************************************************ */
469 char datablock[32701];
470
471 assert_string_is_neither_NULL_nor_zerolength(logfile);
472 if (!(fin = fopen(logfile, "r"))) {
473 log_OS_error("Unable to open logfile");
474 fatal_error("Unable to open logfile to read trackno");
475 }
476 len = fread(datablock, 1, 32700, fin);
477 paranoid_fclose(fin);
478 if (len <= 0) {
479 return (0);
480 }
481 for (; len > 0 && !isdigit(datablock[len - 1]); len--);
482 datablock[len--] = '\0';
483 for (; len > 0 && isdigit(datablock[len - 1]); len--);
484 trackno = atoi(datablock + len);
485 /*
486 sprintf(tmp,"datablock=%s; trackno=%d",datablock+len, trackno);
487 log_it(tmp);
488 */
489 return (trackno);
490}
491
492
493
494
495
496
497
498/**
499 * Get a percentage from the last line of @p filename. We look for the string
500 * "% done" on the last line and, if we find it, grab the number before the last % sign.
501 * @param filename The file to get the percentage from.
502 * @return The percentage found, or 0 for error.
503 */
504int grab_percentage_from_last_line_of_file(char *filename)
505{
506
507 /*@ buffers ***************************************************** */
508 char tmp[MAX_STR_LEN];
509 char lastline[MAX_STR_LEN];
510 char command[MAX_STR_LEN];
511 /*@ pointers **************************************************** */
512 char *p;
513
514 /*@ int's ******************************************************* */
515 int i;
516
517 for (i = NOOF_ERR_LINES - 1;
518 i >= 0 && !strstr(err_log_lines[i], "% Done")
519 && !strstr(err_log_lines[i], "% done"); i--);
520 if (i < 0) {
521 sprintf(command,
522 "tail -n3 %s | grep -Fi \"%c\" | tail -n1 | awk '{print $0;}'",
523 filename, '%');
524 strcpy(lastline,
525 call_program_and_get_last_line_of_output(command));
526 if (!lastline[0]) {
527 return (0);
528 }
529 } else {
530 strcpy(lastline, err_log_lines[i]);
531 }
532
533 p = strrchr(lastline, '%');
534 if (p) {
535 *p = '\0';
536 }
537// log_msg(2, "lastline='%s', ", p, lastline);
538 if (!p) {
539 return (0);
540 }
541 *p = '\0';
542 for (p--; *p != ' ' && p != lastline; p--);
543 if (p != lastline) {
544 p++;
545 }
546 i = atoi(p);
547
548 sprintf(tmp, "'%s' --> %d", p, i);
549// log_to_screen(tmp);
550
551 return (i);
552}
553
554
555
556
557
558/**
559 * Return the last line of @p filename.
560 * @param filename The file to get the last line of.
561 * @return The last line of the file.
562 * @note The returned string points to static storage that will be overwritten with each call.
563 */
564char *last_line_of_file(char *filename)
565{
566 /*@ buffers ***************************************************** */
567 static char output[MAX_STR_LEN];
568 static char command[MAX_STR_LEN * 2];
569 static char tmp[MAX_STR_LEN];
570
571 /*@ pointers **************************************************** */
572 FILE *fin;
573
574 /*@ end vars **************************************************** */
575
576 if (!does_file_exist(filename)) {
577 sprintf(tmp, "Tring to get last line of nonexistent file (%s)",
578 filename);
579 log_it(tmp);
580 output[0] = '\0';
581 return (output);
582 }
583 sprintf(command, "tail -n1 %s", filename);
584 fin = popen(command, "r");
585 (void) fgets(output, MAX_STR_LEN, fin);
586 paranoid_pclose(fin);
587 while (strlen(output) > 0 && output[strlen(output) - 1] < 32) {
588 output[strlen(output) - 1] = '\0';
589 }
590 return (output);
591}
592
593/**
594 * Get the length of @p filename in bytes.
595 * @param filename The file to get the length of.
596 * @return The length of the file, or -1 for error.
597 */
598long long length_of_file(char *filename)
599{
600 /*@ pointers *************************************************** */
601 FILE *fin;
602
603 /*@ long long ************************************************* */
604 long long length;
605
606 fin = fopen(filename, "r");
607 if (!fin) {
608 log_it("filename=%s", filename);
609 log_OS_error("Unable to openin filename");
610 return (-1);
611 }
612 fseeko(fin, 0, SEEK_END);
613 length = ftell(fin);
614 paranoid_fclose(fin);
615 return (length);
616}
617
618
619
620/**
621 * ?????
622 * @bug I don't know what this function does. However, it seems orphaned, so it should probably be removed.
623 */
624int
625make_checksum_list_file(char *filelist, char *cksumlist, char *comppath)
626{
627 /*@ pointers **************************************************** */
628 FILE *fin;
629 FILE *fout;
630
631 /*@ int ******************************************************* */
632 int percentage;
633 int i;
634 int counter = 0;
635
636 /*@ buffer ****************************************************** */
637 char stub_fname[1000];
638 char curr_fname[1000];
639 char curr_cksum[1000];
640 char tmp[1000];
641
642 /*@ long [long] ************************************************* */
643 long long filelist_length;
644 long curr_pos;
645 long start_time;
646 long current_time;
647 long time_taken;
648 long time_remaining;
649
650 /*@ end vars *************************************************** */
651
652 start_time = get_time();
653 filelist_length = length_of_file(filelist);
654 sprintf(tmp, "filelist = %s; cksumlist = %s", filelist, cksumlist);
655 log_it(tmp);
656 fin = fopen(filelist, "r");
657 if (fin == NULL) {
658 log_OS_error("Unable to fopen-in filelist");
659 log_to_screen("Can't open filelist");
660 return (1);
661 }
662 fout = fopen(cksumlist, "w");
663 if (fout == NULL) {
664 log_OS_error("Unable to openout cksumlist");
665 paranoid_fclose(fin);
666 log_to_screen("Can't open checksum list");
667 return (1);
668 }
669 for (fgets(stub_fname, 999, fin); !feof(fin);
670 fgets(stub_fname, 999, fin)) {
671 if (stub_fname[(i = strlen(stub_fname) - 1)] < 32) {
672 stub_fname[i] = '\0';
673 }
674 sprintf(tmp, "%s%s", comppath, stub_fname);
675 strcpy(curr_fname, tmp + 1);
676 strcpy(curr_cksum, calc_file_ugly_minichecksum(curr_fname));
677 fprintf(fout, "%s\t%s\n", curr_fname, curr_cksum);
678 if (counter++ > 12) {
679 current_time = get_time();
680 counter = 0;
681 curr_fname[37] = '\0';
682 curr_pos = ftell(fin) / 1024;
683 percentage = (int) (curr_pos * 100 / filelist_length);
684 time_taken = current_time - start_time;
685 if (percentage == 0) {
686 /* printf("%0d%% done \r",percentage); */
687 } else {
688 time_remaining =
689 time_taken * 100 / (long) (percentage) - time_taken;
690 sprintf(tmp,
691 "%02d%% done %02d:%02d taken %02d:%02d remaining %-37s\r",
692 percentage, (int) (time_taken / 60),
693 (int) (time_taken % 60),
694 (int) (time_remaining / 60),
695 (int) (time_remaining % 60), curr_fname);
696 log_to_screen(tmp);
697 }
698 sync();
699 }
700 }
701 paranoid_fclose(fout);
702 paranoid_fclose(fin);
703 log_it("Done.");
704 return (0);
705}
706
707
708/**
709 * Create the directory @p outdir_fname and all parent directories. Equivalent to <tt>mkdir -p</tt>.
710 * @param outdir_fname The directory to create.
711 * @return The return value of @c mkdir.
712 */
713int make_hole_for_dir(char *outdir_fname)
714{
715 char tmp[MAX_STR_LEN * 2];
716 int res = 0;
717
718 assert_string_is_neither_NULL_nor_zerolength(outdir_fname);
719 sprintf(tmp, "mkdir -p %s", outdir_fname);
720 res = system(tmp);
721 return (res);
722}
723
724
725/**
726 * Create the parent directories of @p outfile_fname.
727 * @param outfile_fname The file to make a "hole" for.
728 * @return 0, always.
729 * @bug Return value unnecessary.
730 */
731int make_hole_for_file(char *outfile_fname)
732{
733 /*@ buffer ****************************************************** */
734 char command[MAX_STR_LEN * 2];
735
736 /*@ int ******************************************************** */
737 int res = 0;
738
739 /*@ end vars *************************************************** */
740
741 assert_string_is_neither_NULL_nor_zerolength(outfile_fname);
742 assert(!strstr(outfile_fname, MNT_CDROM));
743 assert(!strstr(outfile_fname, "/dev/cdrom"));
744 sprintf(command, "mkdir -p \"%s\" 2> /dev/null", outfile_fname);
745 res += system(command);
746 sprintf(command, "rmdir \"%s\" 2> /dev/null", outfile_fname);
747 res += system(command);
748 sprintf(command, "rm -f \"%s\" 2> /dev/null", outfile_fname);
749 res += system(command);
750 unlink(outfile_fname);
751 return (0);
752}
753
754
755
756
757/**
758 * Get the number of lines in @p filelist_fname that contain the string @p wildcard.
759 * @param filelist_fname The file to search through.
760 * @param wildcard The string to search for. This is @e not a shell glob or a regular expression.
761 * @return The number of lines matched.
762 */
763long noof_lines_that_match_wildcard(char *filelist_fname, char *wildcard)
764{
765 /*@ long ******************************************************* */
766 long matches = 0;
767
768 /*@ pointers *************************************************** */
769 FILE *fin;
770
771 /*@ buffers **************************************************** */
772 char incoming[MAX_STR_LEN];
773
774 /*@ end vars *************************************************** */
775
776
777 fin = fopen(filelist_fname, "r");
778
779 if (!fin) {
780 log_OS_error("Unable to openin filelist_fname");
781 return (0);
782 }
783 (void) fgets(incoming, MAX_STR_LEN - 1, fin);
784 while (!feof(fin)) {
785 if (strstr(incoming, wildcard)) {
786 matches++;
787 }
788 (void) fgets(incoming, MAX_STR_LEN - 1, fin);
789 }
790 paranoid_fclose(fin);
791 return (matches);
792}
793
794
795
796
797/**
798 * Register our PID in a file in /var/run.
799 * The PID will be put in /var/run/monitas-<tt>name_str</tt>.pid.
800 * @param pid 0 to remove file, anything else to create it.
801 * @param name_str The basename of the PID file (e.g. "mondo" or "server")
802 * @note This function does not provide support against multiple instances, unless you check for that yourself.
803 */
804void register_pid(pid_t pid, char *name_str)
805{
806 char tmp[MAX_STR_LEN + 1], lockfile_fname[MAX_STR_LEN + 1];
807 int res;
808 FILE *fin;
809
810 sprintf(lockfile_fname, "/var/run/monitas-%s.pid", name_str);
811 if (!pid) {
812 log_it("Unregistering PID");
813 if (unlink(lockfile_fname)) {
814 log_it("Error unregistering PID");
815 }
816 return;
817 }
818 if (does_file_exist(lockfile_fname)) {
819 tmp[0] = '\0';
820 if ((fin = fopen(lockfile_fname, "r"))) {
821 (void) fgets(tmp, MAX_STR_LEN, fin);
822 paranoid_fclose(fin);
823 } else {
824 log_OS_error("Unable to openin lockfile_fname");
825 }
826 pid = (pid_t) atol(tmp);
827 sprintf(tmp, "ps %ld > /dev/null 2> /dev/null", (long int) pid);
828 res = system(tmp);
829 if (!res) {
830 log_it
831 ("I believe the daemon is already running. If it isn't, please delete %s and try again.",
832 lockfile_fname);
833 }
834 }
835 sprintf(tmp, "echo %ld > %s 2> /dev/null", (long int) getpid(),
836 lockfile_fname);
837 if (system(tmp)) {
838 fatal_error("Cannot register PID");
839 }
840}
841
842
843
844/**
845 * Determine the size (in KB) of @p dev in the mountlist in <tt>tmpdir</tt>/mountlist.txt.
846 * @param tmpdir The tempdir where the mountlist is stored.
847 * @param dev The device to search for.
848 * @return The size of the partition in KB.
849 */
850long size_of_partition_in_mountlist_K(char *tmpdir, char *dev)
851{
852 char command[MAX_STR_LEN];
853 char mountlist[MAX_STR_LEN];
854 char sz_res[MAX_STR_LEN];
855 long file_len_K;
856
857 sprintf(mountlist, "%s/mountlist.txt", tmpdir);
858 sprintf(command,
859 "grep \"%s \" %s/mountlist.txt | head -n1 | awk '{print $4}'",
860 dev, tmpdir);
861 log_it(command);
862 strcpy(sz_res, call_program_and_get_last_line_of_output(command));
863 file_len_K = atol(sz_res);
864 log_msg(4, "%s --> %s --> %ld", command, sz_res, file_len_K);
865 return (file_len_K);
866}
867
868/**
869 * Calculate the total size (in KB) of all the biggiefiles in this backup.
870 * @param bkpinfo The backup information structure. Only the @c bkpinfo->tmpdir field is used.
871 * @return The total size of all biggiefiles in KB.
872 */
873long size_of_all_biggiefiles_K(struct s_bkpinfo *bkpinfo)
874{
875 /*@ buffers ***************************************************** */
876 char *fname;
877 char *biggielist;
878 char *comment;
879 char *tmp;
880 char *command;
881
882 /*@ long ******************************************************** */
883 long scratchL = 0;
884 long file_len_K;
885
886 /*@ pointers *************************************************** */
887 FILE *fin = NULL;
888
889 /*@ end vars *************************************************** */
890
891 malloc_string(fname);
892 malloc_string(biggielist);
893 malloc_string(comment);
894 malloc_string(tmp);
895 malloc_string(command);
896 log_it("Calculating size of all biggiefiles (in total)");
897 sprintf(biggielist, "%s/biggielist.txt", bkpinfo->tmpdir);
898 log_it("biggielist = %s", biggielist);
899 if (!(fin = fopen(biggielist, "r"))) {
900 log_OS_error
901 ("Cannot open biggielist. OK, so estimate is based on filesets only.");
902 } else {
903 log_msg(4, "Reading it...");
904 for (fgets(fname, MAX_STR_LEN, fin); !feof(fin);
905 fgets(fname, MAX_STR_LEN, fin)) {
906 if (fname[strlen(fname) - 1] <= 32) {
907 fname[strlen(fname) - 1] = '\0';
908 }
909 if (0 == strncmp(fname, "/dev/", 5)) {
910 if (is_dev_an_NTFS_dev(fname)) {
911 if ( !find_home_of_exe("ntfsresize")) {
912 fatal_error("ntfsresize not found");
913 }
914 sprintf(command, "ntfsresize --force --info %s|grep '^You might resize at '|cut -d' ' -f5", fname);
915 log_it("command = %s", command);
916 strcpy (tmp, call_program_and_get_last_line_of_output(command));
917 log_it("res of it = %s", tmp);
918 file_len_K = atoll(tmp) / 1024L;
919 } else {
920 file_len_K = get_phys_size_of_drive(fname) * 1024L;
921 }
922 } else {
923 file_len_K = (long) (length_of_file(fname) / 1024);
924 }
925 if (file_len_K > 0) {
926 scratchL += file_len_K;
927 log_msg(4, "%s --> %ld K", fname, file_len_K);
928 }
929 sprintf(comment,
930 "After adding %s, scratchL+%ld now equals %ld", fname,
931 file_len_K, scratchL);
932 log_msg(4, comment);
933 if (feof(fin)) {
934 break;
935 }
936 }
937 }
938 log_it("Closing...");
939 paranoid_fclose(fin);
940 log_it("Finished calculating total size of all biggiefiles");
941 paranoid_free(fname);
942 paranoid_free(biggielist);
943 paranoid_free(comment);
944 paranoid_free(tmp);
945 paranoid_free(command);
946 return (scratchL);
947}
948
949/**
950 * Determine the amount of space (in KB) occupied by a mounted CD.
951 * This can also be used to find the space used for other directories.
952 * @param mountpt The mountpoint/directory to check.
953 * @return The amount of space occupied in KB.
954 */
955long long space_occupied_by_cd(char *mountpt)
956{
957 /*@ buffer ****************************************************** */
958 char tmp[MAX_STR_LEN];
959 char command[MAX_STR_LEN * 2];
960 long long llres;
961 /*@ pointers **************************************************** */
962 char *p;
963 FILE *fin;
964
965 /*@ end vars *************************************************** */
966
967 sprintf(command, "du -sk %s", mountpt);
968 fin = popen(command, "r");
969 (void) fgets(tmp, MAX_STR_LEN, fin);
970 paranoid_pclose(fin);
971 p = strchr(tmp, '\t');
972 if (p) {
973 *p = '\0';
974 }
975 for (p = tmp, llres = 0; *p != '\0'; p++) {
976 llres *= 10;
977 llres += (int) (*p - '0');
978 }
979 return (llres);
980}
981
982
983/**
984 * Update a CRC checksum to include another character.
985 * @param crc The original CRC checksum.
986 * @param c The character to add.
987 * @return The new CRC checksum.
988 * @ingroup utilityGroup
989 */
990unsigned int updcrc(unsigned int crc, unsigned int c)
991{
992 unsigned int tmp;
993 tmp = (crc >> 8) ^ c;
994 crc = (crc << 8) ^ crctttab[tmp & 255];
995 return crc;
996}
997
998/**
999 * Update a reverse CRC checksum to include another character.
1000 * @param crc The original CRC checksum.
1001 * @param c The character to add.
1002 * @return The new CRC checksum.
1003 * @ingroup utilityGroup
1004 */
1005unsigned int updcrcr(unsigned int crc, unsigned int c)
1006{
1007 unsigned int tmp;
1008 tmp = crc ^ c;
1009 crc = (crc >> 8) ^ crc16tab[tmp & 0xff];
1010 return crc;
1011}
1012
1013
1014
1015
1016/**
1017 * Check for an executable on the user's system; write a message to the
1018 * screen and the log if we can't find it.
1019 * @param fname The executable basename to look for.
1020 * @return 0 if it's found, nonzero if not.
1021 */
1022int whine_if_not_found(char *fname)
1023{
1024 /*@ buffers *** */
1025 char command[MAX_STR_LEN * 2];
1026 char errorstr[MAX_STR_LEN];
1027
1028
1029 sprintf(command, "which %s > /dev/null 2> /dev/null", fname);
1030 sprintf(errorstr,
1031 "Please install '%s'. I cannot find it on your system.",
1032 fname);
1033 if (system(command)) {
1034 log_to_screen(errorstr);
1035 log_to_screen
1036 ("There may be hyperlink at http://www.mondorescue.com which");
1037 log_to_screen("will take you to the relevant (missing) package.");
1038 return (1);
1039 } else {
1040 return (0);
1041 }
1042}
1043
1044
1045
1046
1047
1048
1049/**
1050 * Create a data file at @p fname containing @p contents.
1051 * The data actually can be multiple lines, despite the name.
1052 * @param fname The file to create.
1053 * @param contents The data to put in it.
1054 * @return 0 for success, 1 for failure.
1055 */
1056int write_one_liner_data_file(char *fname, char *contents)
1057{
1058 /*@ pointers *************************************************** */
1059 FILE *fout;
1060 int res = 0;
1061
1062 /*@ end vars *************************************************** */
1063
1064 assert_string_is_neither_NULL_nor_zerolength(fname);
1065 if (!contents) {
1066 log_it("%d: Warning - writing NULL to %s", __LINE__, fname);
1067 }
1068 if (!(fout = fopen(fname, "w"))) {
1069 log_it("fname=%s");
1070 log_OS_error("Unable to openout fname");
1071 return (1);
1072 }
1073 fprintf(fout, "%s\n", contents);
1074 paranoid_fclose(fout);
1075 return (res);
1076}
1077
1078
1079
1080/**
1081 * Read @p fname into @p contents.
1082 * @param fname The file to read.
1083 * @param contents Where to put its contents.
1084 * @return 0 for success, nonzero for failure.
1085 */
1086int read_one_liner_data_file(char *fname, char *contents)
1087{
1088 /*@ pointers *************************************************** */
1089 FILE *fin;
1090 int res = 0;
1091 int i;
1092
1093 /*@ end vars *************************************************** */
1094
1095 assert_string_is_neither_NULL_nor_zerolength(fname);
1096 if (!contents) {
1097 log_it("%d: Warning - reading NULL from %s", __LINE__, fname);
1098 }
1099 if (!(fin = fopen(fname, "r"))) {
1100 log_it("fname=%s", fname);
1101 log_OS_error("Unable to openin fname");
1102 return (1);
1103 }
1104 fscanf(fin, "%s\n", contents);
1105 i = strlen(contents);
1106 if (i > 0 && contents[i - 1] < 32) {
1107 contents[i - 1] = '\0';
1108 }
1109 paranoid_fclose(fin);
1110 return (res);
1111}
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121/**
1122 * Copy the files that Mondo/Mindi need to run to the scratchdir or tempdir.
1123 * Currently this includes: copy Mondo's home directory to scratchdir, untar "mondo_home/payload.tgz"
1124 * if it exists, copy LAST-FILELIST-NUMBER to scratchdir, copy mondorestore
1125 * and post-nuke.tgz (if it exists) to tmpdir, and run "hostname > scratchdir/HOSTNAME".
1126 * @param bkpinfo The backup information structure. Fields used:
1127 * - @c bkpinfo->postnuke_tarball
1128 * - @c bkpinfo->scratchdir
1129 * - @c bkpinfo->tmpdir
1130 */
1131void copy_mondo_and_mindi_stuff_to_scratchdir(struct s_bkpinfo *bkpinfo)
1132{
1133 /*@ Char buffers ** */
1134 char command[MAX_STR_LEN * 2];
1135 char tmp[MAX_STR_LEN];
1136 char old_pwd[MAX_STR_LEN];
1137
1138 mvaddstr_and_log_it(g_currentY, 0,
1139 "Copying Mondo's core files to the scratch directory");
1140
1141 log_msg(4, "g_mondo_home='%s'", g_mondo_home);
1142 if (strlen(g_mondo_home) < 2) {
1143 find_and_store_mondoarchives_home(g_mondo_home);
1144 }
1145 sprintf(command, CP_BIN " --parents -pRdf %s %s", g_mondo_home,
1146 bkpinfo->scratchdir);
1147
1148 log_msg(4, "command = %s", command);
1149 if (run_program_and_log_output(command, 1)) {
1150 fatal_error("Failed to copy Mondo's stuff to scratchdir");
1151 }
1152
1153 sprintf(tmp, "%s/payload.tgz", g_mondo_home);
1154 if (does_file_exist(tmp)) {
1155 log_it("Untarring payload %s to scratchdir %s", tmp,
1156 bkpinfo->scratchdir);
1157 (void) getcwd(old_pwd, MAX_STR_LEN - 1);
1158 chdir(bkpinfo->scratchdir);
1159 sprintf(command, "tar -zxvf %s", tmp);
1160 if (run_program_and_log_output(command, FALSE)) {
1161 fatal_error("Failed to untar payload");
1162 }
1163 chdir(old_pwd);
1164 }
1165
1166 sprintf(command, "cp -f %s/LAST-FILELIST-NUMBER %s", bkpinfo->tmpdir,
1167 bkpinfo->scratchdir);
1168
1169 if (run_program_and_log_output(command, FALSE)) {
1170 fatal_error("Failed to copy LAST-FILELIST-NUMBER to scratchdir");
1171 }
1172
1173 strcpy(tmp,
1174 call_program_and_get_last_line_of_output("which mondorestore"));
1175 if (!tmp[0]) {
1176 fatal_error
1177 ("'which mondorestore' returned null. Where's your mondorestore? `which` can't find it. That's odd. Did you install mondorestore?");
1178 }
1179 sprintf(command, "cp -f %s %s", tmp, bkpinfo->tmpdir);
1180 if (run_program_and_log_output(command, FALSE)) {
1181 fatal_error("Failed to copy mondorestore to tmpdir");
1182 }
1183
1184 sprintf(command, "hostname > %s/HOSTNAME", bkpinfo->scratchdir);
1185 paranoid_system(command);
1186
1187 if (bkpinfo->postnuke_tarball[0]) {
1188 sprintf(command, "cp -f %s %s/post-nuke.tgz",
1189 bkpinfo->postnuke_tarball, bkpinfo->tmpdir);
1190 if (run_program_and_log_output(command, FALSE)) {
1191 fatal_error("Unable to copy post-nuke tarball to tmpdir");
1192 }
1193 }
1194
1195
1196 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1197}
1198
1199
1200
1201
1202
1203/**
1204 * Store the client's NFS configuration in files to be restored at restore-time.
1205 * Assumes that @c bkpinfo->media_type = nfs, but does not check for this.
1206 * @param bkpinfo The backup information structure. Fields used:
1207 * - @c nfs_mount
1208 * - @c nfs_remote_dir
1209 * - @c tmpdir
1210 */
1211void store_nfs_config(struct s_bkpinfo *bkpinfo)
1212{
1213
1214 /*@ buffers ******** */
1215 char outfile[MAX_STR_LEN];
1216 char nfs_dev[MAX_STR_LEN];
1217 char nfs_mount[MAX_STR_LEN];
1218 char nfs_client_ipaddr[MAX_STR_LEN];
1219 char nfs_client_netmask[MAX_STR_LEN];
1220 char nfs_client_broadcast[MAX_STR_LEN];
1221 char nfs_client_defgw[MAX_STR_LEN];
1222 char nfs_server_ipaddr[MAX_STR_LEN];
1223 char tmp[MAX_STR_LEN];
1224 char command[MAX_STR_LEN * 2];
1225
1226 /*@ pointers ***** */
1227 char *p;
1228 FILE *fout;
1229
1230
1231
1232 log_it("Storing NFS configuration");
1233 strcpy(tmp, bkpinfo->nfs_mount);
1234 p = strchr(tmp, ':');
1235 if (!p) {
1236 fatal_error
1237 ("NFS mount doesn't have a colon in it, e.g. 192.168.1.4:/home/nfs");
1238 }
1239 *(p++) = '\0';
1240 strcpy(nfs_server_ipaddr, tmp);
1241 strcpy(nfs_mount, p);
1242 sprintf(command,
1243 "ifconfig | tr '\n' '#' | sed s/##// | tr '#' ' ' | tr '' '\n' | head -n1 | cut -d' ' -f1");
1244 strcpy(nfs_dev, call_program_and_get_last_line_of_output(command));
1245 sprintf(command,
1246 "ifconfig | tr '\n' '#' | sed s/##// | tr '#' ' ' | tr '' '\\n' | head -n1 | tr -s '\t' ' ' | cut -d' ' -f7 | cut -d':' -f2");
1247 strcpy(nfs_client_ipaddr,
1248 call_program_and_get_last_line_of_output(command));
1249 sprintf(command,
1250 "ifconfig | tr '\n' '#' | sed s/##// | tr '#' ' ' | tr '' '\\n' | head -n1 | tr -s '\t' ' ' | cut -d' ' -f9 | cut -d':' -f2");
1251 strcpy(nfs_client_netmask,
1252 call_program_and_get_last_line_of_output(command));
1253 sprintf(command,
1254 "ifconfig | tr '\n' '#' | sed s/##// | tr '#' ' ' | tr '' '\\n' | head -n1 | tr -s '\t' ' ' | cut -d' ' -f8 | cut -d':' -f2");
1255 strcpy(nfs_client_broadcast,
1256 call_program_and_get_last_line_of_output(command));
1257 sprintf(command,
1258 "route -n | grep '^0.0.0.0' | awk '{print $2}'");
1259 strcpy(nfs_client_defgw,
1260 call_program_and_get_last_line_of_output(command));
1261 sprintf(tmp,
1262 "nfs_client_ipaddr=%s; nfs_server_ipaddr=%s; nfs_mount=%s",
1263 nfs_client_ipaddr, nfs_server_ipaddr, nfs_mount);
1264 if (strlen(nfs_dev) < 2) {
1265 fatal_error
1266 ("Unable to find ethN (eth0, eth1, ...) adapter via NFS mount you specified.");
1267 }
1268 sprintf(outfile, "%s/start-nfs", bkpinfo->tmpdir);
1269 sprintf(tmp, "outfile = %s", outfile);
1270 log_it(tmp);
1271 if (!(fout = fopen(outfile, "w"))) {
1272 fatal_error("Cannot store NFS config");
1273 }
1274 fprintf(fout, "#!/bin/sh\n");
1275 fprintf(fout, "# number of ping\n");
1276 fprintf(fout, "ipcount=3\n");
1277 fprintf(fout, "for i in `cat /proc/cmdline` ; do\n");
1278 fprintf(fout, " echo $i | grep -qi ping= && ipcount=`echo $i | cut -d= -f2`\n");
1279 fprintf(fout, "done\n");
1280 fprintf(fout, "ifconfig lo 127.0.0.1 # config loopback\n");
1281 fprintf(fout, "ipdev=%s\n", nfs_dev);
1282 fprintf(fout, "ipaddress=%s\n", nfs_client_ipaddr);
1283 fprintf(fout, "ipnetmask=%s\n", nfs_client_netmask);
1284 fprintf(fout, "ipbroadcast=%s\n", nfs_client_broadcast);
1285 fprintf(fout, "ipgateway=%s\n", nfs_client_defgw);
1286 fprintf(fout, "ipconf=\n");
1287 fprintf(fout, "nfsmount=%s\n", bkpinfo->nfs_mount);
1288 fprintf(fout, "for i in `cat /proc/cmdline` ; do\n");
1289 fprintf(fout, " echo $i | grep -qi ipconf= && ipconf=`echo $i | cut -d= -f2`\n");
1290 fprintf(fout, " echo $i | grep -qi nfsmount= && nfsmount=`echo $i | cut -d= -f2`\n");
1291 fprintf(fout, "done\n");
1292 fprintf(fout, "nfs_server_ipaddr=`echo $nfsmount | cut -d: -f1`\n");
1293 fprintf(fout, "echo \"$ipconf\" | grep -q \"dhcp\"\n");
1294 fprintf(fout, "if [ $? -eq 0 ]; then\n");
1295 fprintf(fout, " ipdev=`echo $ipconf | cut -d: -f1`\n");
1296 fprintf(fout, " echo \"Making DHCP request on $ipdev\"\n");
1297 fprintf(fout, " udhcpc -i $ipdev\n");
1298 fprintf(fout, "else\n");
1299 fprintf(fout, " if [ \"$ipconf\" != \"\" ]; then\n");
1300 fprintf(fout, " ipdev=`echo $ipconf | cut -d: -f1`\n");
1301 fprintf(fout, " ipaddress=`echo $ipconf | cut -d: -f2`\n");
1302 fprintf(fout, " ipnetmask=`echo $ipconf | cut -d: -f3`\n");
1303 fprintf(fout, " ipbroadcast=`echo $ipconf | cut -d: -f4`\n");
1304 fprintf(fout, " ipgateway=`echo $ipconf | cut -d: -f5`\n");
1305 fprintf(fout, " fi\n");
1306 fprintf(fout, " ifconfig $ipdev $ipaddress netmask $ipnetmask broadcast $ipbroadcast\n");
1307 fprintf(fout, " route add default gw $ipgateway\n");
1308 fprintf(fout, "fi\n");
1309 fprintf(fout, "ping -c $ipcount $nfs_server_ipaddr # ping server\n");
1310 fprintf(fout, "mount -t nfs -o nolock $nfsmount /tmp/isodir\n");
1311 paranoid_fclose(fout);
1312 chmod(outfile, 0777);
1313 make_hole_for_dir("/var/cache/mondo-archive");
1314
1315// paranoid_system ("mkdir -p /var/cache/mondo-archive 2> /dev/null");
1316
1317 sprintf(tmp, "cp -f %s /var/cache/mondo-archive", outfile);
1318 run_program_and_log_output(tmp, FALSE);
1319
1320 sprintf(tmp, "%s/NFS-DEV", bkpinfo->tmpdir);
1321 write_one_liner_data_file(tmp, nfs_dev);
1322
1323 sprintf(tmp, "%s/NFS-CLIENT-IPADDR", bkpinfo->tmpdir);
1324 write_one_liner_data_file(tmp, nfs_client_ipaddr);
1325 sprintf(tmp, "%s/NFS-CLIENT-NETMASK", bkpinfo->tmpdir);
1326 write_one_liner_data_file(tmp, nfs_client_netmask);
1327 sprintf(tmp, "%s/NFS-CLIENT-BROADCAST", bkpinfo->tmpdir);
1328 write_one_liner_data_file(tmp, nfs_client_broadcast);
1329 sprintf(tmp, "%s/NFS-CLIENT-DEFGW", bkpinfo->tmpdir);
1330 write_one_liner_data_file(tmp, nfs_client_defgw);
1331 sprintf(tmp, "%s/NFS-SERVER-IPADDR", bkpinfo->tmpdir);
1332 write_one_liner_data_file(tmp, nfs_server_ipaddr);
1333 sprintf(tmp, "%s/NFS-SERVER-MOUNT", bkpinfo->tmpdir);
1334 write_one_liner_data_file(tmp, bkpinfo->nfs_mount);
1335 sprintf(tmp, "%s/NFS-SERVER-PATH", bkpinfo->tmpdir);
1336 write_one_liner_data_file(tmp, bkpinfo->nfs_remote_dir);
1337 sprintf(tmp, "%s/ISO-PREFIX", bkpinfo->tmpdir);
1338 write_one_liner_data_file(tmp, bkpinfo->prefix);
1339 log_it("Finished storing NFS configuration");
1340}
1341
1342
1343
1344
1345
1346
1347/**
1348 * Determine the approximate number of media that the backup will take up,
1349 * and tell the user. The uncompressed size is estimated as size_of_all_biggiefiles_K()
1350 * plus (noof_sets x bkpinfo->optimal_set_size). The compression factor is estimated as
1351 * 2/3 for LZO and 1/2 for bzip2. The data is not saved anywhere. If there are any
1352 * "imagedevs", the estimate is not shown as it will be wildly inaccurate.
1353 * If there are more than 50 media estimated, the estimate will not be shown.
1354 * @param bkpinfo The backup information structure. Fields used:
1355 * - @c bkpinfo->backup_media_type
1356 * - @c bkpinfo->image_devs
1357 * - @c bkpinfo->media_size
1358 * - @c bkpinfo->optimal_set_size
1359 * - @c bkpinfo->use_lzo
1360 * @param noof_sets The number of filesets created.
1361 * @ingroup archiveGroup
1362 */
1363void
1364estimate_noof_media_required(struct s_bkpinfo *bkpinfo, long noof_sets)
1365{
1366 /*@ buffers *************** */
1367 char tmp[MAX_STR_LEN];
1368
1369 /*@ long long ************* */
1370 long long scratchLL;
1371
1372 if (bkpinfo->media_size[1] <= 0 || bkpinfo->backup_media_type == nfs) {
1373 log_to_screen("Number of media required: UNKNOWN");
1374 return;
1375 }
1376
1377 log_it("Estimating number of media required...");
1378 scratchLL =
1379 (long long) (noof_sets) * (long long) (bkpinfo->optimal_set_size)
1380 + (long long) (size_of_all_biggiefiles_K(bkpinfo));
1381 scratchLL = (scratchLL / 1024) / bkpinfo->media_size[1];
1382 scratchLL++;
1383 if (bkpinfo->use_lzo) {
1384 scratchLL = (scratchLL * 2) / 3;
1385 } else {
1386 scratchLL = scratchLL / 2;
1387 }
1388 if (!scratchLL) {
1389 scratchLL++;
1390 }
1391 if (scratchLL <= 1) {
1392 sprintf(tmp,
1393 "Your backup will probably occupy a single %s. Maybe two.",
1394 media_descriptor_string(bkpinfo->backup_media_type));
1395 } else if (scratchLL > 4) {
1396 sprintf(tmp,
1397 "Your backup will occupy one meeeeellion media! (maybe %s)",
1398 number_to_text((int) (scratchLL + 1)));
1399 } else {
1400 sprintf(tmp, "Your backup will occupy approximately %s media.",
1401 number_to_text((int) (scratchLL + 1)));
1402 }
1403 if (!bkpinfo->image_devs[0] && (scratchLL < 50)) {
1404 log_to_screen(tmp);
1405 }
1406}
1407
1408
1409/**
1410 * Get the last suffix of @p instr.
1411 * If @p instr was "httpd.log.gz", we would return "gz".
1412 * @param instr The filename to get the suffix of.
1413 * @return The suffix (without a dot), or "" if none.
1414 * @note The returned string points to static storage that will be overwritten with each call.
1415 */
1416char *sz_last_suffix(char *instr)
1417{
1418 static char outstr[MAX_STR_LEN];
1419 char *p;
1420
1421 p = strrchr(instr, '.');
1422 if (!p) {
1423 outstr[0] = '\0';
1424 } else {
1425 strcpy(outstr, p);
1426 }
1427 return (outstr);
1428}
1429
1430
1431/**
1432 * Determine whether a file is compressed. This is done
1433 * by reading through the "do-not-compress-these" file distributed with Mondo.
1434 * @param filename The file to check.
1435 * @return TRUE if it's compressed, FALSE if not.
1436 */
1437bool is_this_file_compressed(char *filename)
1438{
1439 char do_not_compress_these[MAX_STR_LEN];
1440 char tmp[MAX_STR_LEN];
1441 char *p;
1442
1443 sprintf(tmp, "%s/do-not-compress-these", g_mondo_home);
1444 if (!does_file_exist(tmp)) {
1445 return (FALSE);
1446 }
1447 strcpy(do_not_compress_these, last_line_of_file(tmp));
1448 for (p = do_not_compress_these; p != NULL; p++) {
1449 strcpy(tmp, p);
1450 if (strchr(tmp, ' ')) {
1451 *(strchr(tmp, ' ')) = '\0';
1452 }
1453 if (!strcmp(sz_last_suffix(filename), tmp)) { /*printf("MATCH\n"); */
1454 return (TRUE);
1455 }
1456 if (!(p = strchr(p, ' '))) {
1457 break;
1458 }
1459 }
1460 return (FALSE);
1461}
1462
1463
1464
1465int mode_of_file(char *fname)
1466{
1467 struct stat buf;
1468
1469 if (lstat(fname, &buf)) {
1470 return (-1);
1471 } // error
1472 else {
1473 return (buf.st_mode);
1474 }
1475}
1476
1477
1478
1479
1480/**
1481 * Create a small script that mounts /boot, calls @c grub-install, and syncs the disks.
1482 * @param outfile Where to put the script.
1483 * @return 0 for success, 1 for failure.
1484 */
1485int make_grub_install_scriptlet(char *outfile)
1486{
1487 FILE *fout;
1488 char *tmp;
1489 int retval = 0;
1490
1491 malloc_string(tmp);
1492 if ((fout = fopen(outfile, "w"))) {
1493 fprintf(fout,
1494 "#!/bin/sh\n\nmount /boot > /dev/null 2> /dev/null\ngrub-install $@\nres=$?\nsync;sync;sync\nexit $res\n");
1495 paranoid_fclose(fout);
1496 log_msg(2, "Created %s", outfile);
1497 sprintf(tmp, "chmod +x %s", outfile);
1498 paranoid_system(tmp);
1499 retval = 0;
1500 } else {
1501 retval = 1;
1502 }
1503 paranoid_free(tmp);
1504 return (retval);
1505}
1506
1507/* @} - end fileGroup */
Note: See TracBrowser for help on using the repository browser.