source: MondoRescue/branches/2.06/mondo/mondo/common/libmondo-files.c@ 296

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

Replaced partimagehack with ntfsclone from ntfsprogs package. Replaced
all occurrences of strings 'partimagehack' and 'partimage' with 'ntfsprog'.

  • Property svn:keywords set to Id
File size: 39.6 KB
Line 
1/* libmondo-files.c file manipulation
2 $Id: libmondo-files.c 296 2006-01-11 09:10:31Z 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 296 2006-01-11 09:10:31Z 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
344 if (!kernel[0]) {
345 strcpy(kernel,
346 call_program_and_get_last_line_of_output
347 ("mindi --findkernel 2> /dev/null"));
348 }
349 log_it("Calling Mindi with kernel path of '%s'", kernel);
350 while (!kernel[0]) {
351 if (!ask_me_yes_or_no
352 ("Kernel not found or invalid. Choose another?")) {
353 return (1);
354 }
355 if (!popup_and_get_string
356 ("Kernel path",
357 "What is the full path and filename of your kernel, please?",
358 kernel, MAX_STR_LEN / 4)) {
359 fatal_error
360 ("Kernel not found. Please specify with the '-k' flag.");
361 }
362 sprintf(tmp, "User says kernel is at %s", kernel);
363 log_it(tmp);
364 }
365 return (0);
366}
367
368
369
370
371
372
373/**
374 * Find location of specified executable in user's PATH.
375 * @param fname The basename of the executable to search for (e.g. @c afio).
376 * @return The full path to the executable, or "" if it does not exist, or NULL if @c file could not be found.
377 * @note The returned string points to static storage that will be overwritten with each call.
378 * @bug The checks with @c file and @c dirname seem pointless. If @c incoming is "", then you're calling
379 * <tt>dirname 2\>/dev/null</tt> or <tt>file 2\>/dev/null | cut -d':' -f1 2\>/dev/null</tt>, which basically amounts
380 * to nothing.
381 */
382char *find_home_of_exe(char *fname)
383{
384 /*@ buffers ********************* */
385 static char output[MAX_STR_LEN];
386 char *incoming;
387 char *command;
388
389 malloc_string(incoming);
390 malloc_string(command);
391 incoming[0] = '\0';
392 /*@******************************* */
393
394 assert_string_is_neither_NULL_nor_zerolength(fname);
395 sprintf(command, "which %s 2> /dev/null", fname);
396 strcpy(incoming, call_program_and_get_last_line_of_output(command));
397 if (incoming[0] == '\0') {
398 if (system("which file > /dev/null 2> /dev/null")) {
399 paranoid_free(incoming);
400 paranoid_free(command);
401 output[0] = '\0';
402 return (NULL); // forget it :)
403 }
404 sprintf(command,
405 "file %s 2> /dev/null | cut -d':' -f1 2> /dev/null",
406 incoming);
407 strcpy(incoming,
408 call_program_and_get_last_line_of_output(command));
409 }
410 if (incoming[0] == '\0') // yes, it is == '\0' twice, not once :)
411 {
412 sprintf(command, "dirname %s 2> /dev/null", incoming);
413 strcpy(incoming,
414 call_program_and_get_last_line_of_output(command));
415 }
416 strcpy(output, incoming);
417 if (output[0] != '\0' && does_file_exist(output)) {
418 log_msg(4, "find_home_of_exe () --- Found %s at %s", fname,
419 incoming);
420 } else {
421 output[0] = '\0';
422 log_msg(4, "find_home_of_exe() --- Could not find %s", fname);
423 }
424 paranoid_free(incoming);
425 paranoid_free(command);
426 if (!output[0]) {
427 return (NULL);
428 } else {
429 return (output);
430 }
431}
432
433
434
435
436
437
438
439
440/**
441 * Get the last sequence of digits surrounded by non-digits in the first 32k of
442 * a file.
443 * @param logfile The file to look in.
444 * @return The number found, or 0 if none.
445 */
446int get_trackno_from_logfile(char *logfile)
447{
448
449 /*@ pointers ********************************************************* */
450 FILE *fin;
451
452 /*@ int ************************************************************** */
453 int trackno = 0;
454 size_t len = 0;
455
456 /*@ buffer ************************************************************ */
457 char datablock[32701];
458
459 assert_string_is_neither_NULL_nor_zerolength(logfile);
460 if (!(fin = fopen(logfile, "r"))) {
461 log_OS_error("Unable to open logfile");
462 fatal_error("Unable to open logfile to read trackno");
463 }
464 len = fread(datablock, 1, 32700, fin);
465 paranoid_fclose(fin);
466 if (len <= 0) {
467 return (0);
468 }
469 for (; len > 0 && !isdigit(datablock[len - 1]); len--);
470 datablock[len--] = '\0';
471 for (; len > 0 && isdigit(datablock[len - 1]); len--);
472 trackno = atoi(datablock + len);
473 /*
474 sprintf(tmp,"datablock=%s; trackno=%d",datablock+len, trackno);
475 log_it(tmp);
476 */
477 return (trackno);
478}
479
480
481
482
483
484
485
486/**
487 * Get a percentage from the last line of @p filename. We look for the string
488 * "% done" on the last line and, if we find it, grab the number before the last % sign.
489 * @param filename The file to get the percentage from.
490 * @return The percentage found, or 0 for error.
491 */
492int grab_percentage_from_last_line_of_file(char *filename)
493{
494
495 /*@ buffers ***************************************************** */
496 char tmp[MAX_STR_LEN];
497 char lastline[MAX_STR_LEN];
498 char command[MAX_STR_LEN];
499 /*@ pointers **************************************************** */
500 char *p;
501
502 /*@ int's ******************************************************* */
503 int i;
504
505 for (i = NOOF_ERR_LINES - 1;
506 i >= 0 && !strstr(err_log_lines[i], "% Done")
507 && !strstr(err_log_lines[i], "% done"); i--);
508 if (i < 0) {
509 sprintf(command,
510 "tail -n3 %s | fgrep -i \"%c\" | tail -n1 | awk '{print $0;}'",
511 filename, '%');
512 strcpy(lastline,
513 call_program_and_get_last_line_of_output(command));
514 if (!lastline[0]) {
515 return (0);
516 }
517 } else {
518 strcpy(lastline, err_log_lines[i]);
519 }
520
521 p = strrchr(lastline, '%');
522 if (p) {
523 *p = '\0';
524 }
525// log_msg(2, "lastline='%s', ", p, lastline);
526 if (!p) {
527 return (0);
528 }
529 *p = '\0';
530 for (p--; *p != ' ' && p != lastline; p--);
531 if (p != lastline) {
532 p++;
533 }
534 i = atoi(p);
535
536 sprintf(tmp, "'%s' --> %d", p, i);
537// log_to_screen(tmp);
538
539 return (i);
540}
541
542
543
544
545
546/**
547 * Return the last line of @p filename.
548 * @param filename The file to get the last line of.
549 * @return The last line of the file.
550 * @note The returned string points to static storage that will be overwritten with each call.
551 */
552char *last_line_of_file(char *filename)
553{
554 /*@ buffers ***************************************************** */
555 static char output[MAX_STR_LEN];
556 static char command[MAX_STR_LEN * 2];
557 static char tmp[MAX_STR_LEN];
558
559 /*@ pointers **************************************************** */
560 FILE *fin;
561
562 /*@ end vars **************************************************** */
563
564 if (!does_file_exist(filename)) {
565 sprintf(tmp, "Tring to get last line of nonexistent file (%s)",
566 filename);
567 log_it(tmp);
568 output[0] = '\0';
569 return (output);
570 }
571 sprintf(command, "tail -n1 %s", filename);
572 fin = popen(command, "r");
573 (void) fgets(output, MAX_STR_LEN, fin);
574 paranoid_pclose(fin);
575 while (strlen(output) > 0 && output[strlen(output) - 1] < 32) {
576 output[strlen(output) - 1] = '\0';
577 }
578 return (output);
579}
580
581/**
582 * Get the length of @p filename in bytes.
583 * @param filename The file to get the length of.
584 * @return The length of the file, or -1 for error.
585 */
586long long length_of_file(char *filename)
587{
588 /*@ pointers *************************************************** */
589 FILE *fin;
590
591 /*@ long long ************************************************* */
592 long long length;
593
594 fin = fopen(filename, "r");
595 if (!fin) {
596 log_it("filename=%s", filename);
597 log_OS_error("Unable to openin filename");
598 return (-1);
599 }
600 fseek(fin, 0, SEEK_END);
601 length = ftell(fin);
602 paranoid_fclose(fin);
603 return (length);
604}
605
606
607
608/**
609 * ?????
610 * @bug I don't know what this function does. However, it seems orphaned, so it should probably be removed.
611 */
612int
613make_checksum_list_file(char *filelist, char *cksumlist, char *comppath)
614{
615 /*@ pointers **************************************************** */
616 FILE *fin;
617 FILE *fout;
618
619 /*@ int ******************************************************* */
620 int percentage;
621 int i;
622 int counter = 0;
623
624 /*@ buffer ****************************************************** */
625 char stub_fname[1000];
626 char curr_fname[1000];
627 char curr_cksum[1000];
628 char tmp[1000];
629
630 /*@ long [long] ************************************************* */
631 long long filelist_length;
632 long curr_pos;
633 long start_time;
634 long current_time;
635 long time_taken;
636 long time_remaining;
637
638 /*@ end vars *************************************************** */
639
640 start_time = get_time();
641 filelist_length = length_of_file(filelist);
642 sprintf(tmp, "filelist = %s; cksumlist = %s", filelist, cksumlist);
643 log_it(tmp);
644 fin = fopen(filelist, "r");
645 if (fin == NULL) {
646 log_OS_error("Unable to fopen-in filelist");
647 log_to_screen("Can't open filelist");
648 return (1);
649 }
650 fout = fopen(cksumlist, "w");
651 if (fout == NULL) {
652 log_OS_error("Unable to openout cksumlist");
653 paranoid_fclose(fin);
654 log_to_screen("Can't open checksum list");
655 return (1);
656 }
657 for (fgets(stub_fname, 999, fin); !feof(fin);
658 fgets(stub_fname, 999, fin)) {
659 if (stub_fname[(i = strlen(stub_fname) - 1)] < 32) {
660 stub_fname[i] = '\0';
661 }
662 sprintf(tmp, "%s%s", comppath, stub_fname);
663 strcpy(curr_fname, tmp + 1);
664 strcpy(curr_cksum, calc_file_ugly_minichecksum(curr_fname));
665 fprintf(fout, "%s\t%s\n", curr_fname, curr_cksum);
666 if (counter++ > 12) {
667 current_time = get_time();
668 counter = 0;
669 curr_fname[37] = '\0';
670 curr_pos = ftell(fin) / 1024;
671 percentage = (int) (curr_pos * 100 / filelist_length);
672 time_taken = current_time - start_time;
673 if (percentage == 0) {
674 /* printf("%0d%% done \r",percentage); */
675 } else {
676 time_remaining =
677 time_taken * 100 / (long) (percentage) - time_taken;
678 sprintf(tmp,
679 "%02d%% done %02d:%02d taken %02d:%02d remaining %-37s\r",
680 percentage, (int) (time_taken / 60),
681 (int) (time_taken % 60),
682 (int) (time_remaining / 60),
683 (int) (time_remaining % 60), curr_fname);
684 log_to_screen(tmp);
685 }
686 sync();
687 }
688 }
689 paranoid_fclose(fout);
690 paranoid_fclose(fin);
691 log_it("Done.");
692 return (0);
693}
694
695
696/**
697 * Create the directory @p outdir_fname and all parent directories. Equivalent to <tt>mkdir -p</tt>.
698 * @param outdir_fname The directory to create.
699 * @return The return value of @c mkdir.
700 */
701int make_hole_for_dir(char *outdir_fname)
702{
703 char tmp[MAX_STR_LEN * 2];
704 int res = 0;
705
706 assert_string_is_neither_NULL_nor_zerolength(outdir_fname);
707 sprintf(tmp, "mkdir -p %s", outdir_fname);
708 res = system(tmp);
709 return (res);
710}
711
712
713/**
714 * Create the parent directories of @p outfile_fname.
715 * @param outfile_fname The file to make a "hole" for.
716 * @return 0, always.
717 * @bug Return value unnecessary.
718 */
719int make_hole_for_file(char *outfile_fname)
720{
721 /*@ buffer ****************************************************** */
722 char command[MAX_STR_LEN * 2];
723
724 /*@ int ******************************************************** */
725 int res = 0;
726
727 /*@ end vars *************************************************** */
728
729 assert_string_is_neither_NULL_nor_zerolength(outfile_fname);
730 assert(!strstr(outfile_fname, MNT_CDROM));
731 assert(!strstr(outfile_fname, "/dev/cdrom"));
732 sprintf(command, "mkdir -p \"%s\" 2> /dev/null", outfile_fname);
733 res += system(command);
734 sprintf(command, "rmdir \"%s\" 2> /dev/null", outfile_fname);
735 res += system(command);
736 sprintf(command, "rm -f \"%s\" 2> /dev/null", outfile_fname);
737 res += system(command);
738 unlink(outfile_fname);
739 return (0);
740}
741
742
743
744
745/**
746 * Get the number of lines in @p filelist_fname that contain the string @p wildcard.
747 * @param filelist_fname The file to search through.
748 * @param wildcard The string to search for. This is @e not a shell glob or a regular expression.
749 * @return The number of lines matched.
750 */
751long noof_lines_that_match_wildcard(char *filelist_fname, char *wildcard)
752{
753 /*@ long ******************************************************* */
754 long matches = 0;
755
756 /*@ pointers *************************************************** */
757 FILE *fin;
758
759 /*@ buffers **************************************************** */
760 char incoming[MAX_STR_LEN];
761
762 /*@ end vars *************************************************** */
763
764
765 fin = fopen(filelist_fname, "r");
766
767 if (!fin) {
768 log_OS_error("Unable to openin filelist_fname");
769 return (0);
770 }
771 (void) fgets(incoming, MAX_STR_LEN - 1, fin);
772 while (!feof(fin)) {
773 if (strstr(incoming, wildcard)) {
774 matches++;
775 }
776 (void) fgets(incoming, MAX_STR_LEN - 1, fin);
777 }
778 paranoid_fclose(fin);
779 return (matches);
780}
781
782
783
784
785/**
786 * Register our PID in a file in /var/run.
787 * The PID will be put in /var/run/monitas-<tt>name_str</tt>.pid.
788 * @param pid 0 to remove file, anything else to create it.
789 * @param name_str The basename of the PID file (e.g. "mondo" or "server")
790 * @note This function does not provide support against multiple instances, unless you check for that yourself.
791 */
792void register_pid(pid_t pid, char *name_str)
793{
794 char tmp[MAX_STR_LEN + 1], lockfile_fname[MAX_STR_LEN + 1];
795 int res;
796 FILE *fin;
797
798 sprintf(lockfile_fname, "/var/run/monitas-%s.pid", name_str);
799 if (!pid) {
800 log_it("Unregistering PID");
801 if (unlink(lockfile_fname)) {
802 log_it("Error unregistering PID");
803 }
804 return;
805 }
806 if (does_file_exist(lockfile_fname)) {
807 tmp[0] = '\0';
808 if ((fin = fopen(lockfile_fname, "r"))) {
809 (void) fgets(tmp, MAX_STR_LEN, fin);
810 paranoid_fclose(fin);
811 } else {
812 log_OS_error("Unable to openin lockfile_fname");
813 }
814 pid = (pid_t) atol(tmp);
815 sprintf(tmp, "ps %ld > /dev/null 2> /dev/null", (long int) pid);
816 res = system(tmp);
817 if (!res) {
818 log_it
819 ("I believe the daemon is already running. If it isn't, please delete %s and try again.",
820 lockfile_fname);
821 }
822 }
823 sprintf(tmp, "echo %ld > %s 2> /dev/null", (long int) getpid(),
824 lockfile_fname);
825 if (system(tmp)) {
826 fatal_error("Cannot register PID");
827 }
828}
829
830
831
832/**
833 * Determine the size (in KB) of @p dev in the mountlist in <tt>tmpdir</tt>/mountlist.txt.
834 * @param tmpdir The tempdir where the mountlist is stored.
835 * @param dev The device to search for.
836 * @return The size of the partition in KB.
837 */
838long size_of_partition_in_mountlist_K(char *tmpdir, char *dev)
839{
840 char command[MAX_STR_LEN];
841 char mountlist[MAX_STR_LEN];
842 char sz_res[MAX_STR_LEN];
843 long file_len_K;
844
845 sprintf(mountlist, "%s/mountlist.txt", tmpdir);
846 sprintf(command,
847 "grep \"%s \" %s/mountlist.txt | head -n1 | awk '{print $4}'",
848 dev, tmpdir);
849 log_it(command);
850 strcpy(sz_res, call_program_and_get_last_line_of_output(command));
851 file_len_K = atol(sz_res);
852 log_msg(4, "%s --> %s --> %ld", command, sz_res, file_len_K);
853 return (file_len_K);
854}
855
856/**
857 * Calculate the total size (in KB) of all the biggiefiles in this backup.
858 * @param bkpinfo The backup information structure. Only the @c bkpinfo->tmpdir field is used.
859 * @return The total size of all biggiefiles in KB.
860 */
861long size_of_all_biggiefiles_K(struct s_bkpinfo *bkpinfo)
862{
863 /*@ buffers ***************************************************** */
864 char *fname;
865 char *biggielist;
866 char *comment;
867 char *tmp;
868 char *command;
869
870 /*@ long ******************************************************** */
871 long scratchL = 0;
872 long file_len_K;
873
874 /*@ pointers *************************************************** */
875 FILE *fin = NULL;
876
877 /*@ end vars *************************************************** */
878
879 malloc_string(fname);
880 malloc_string(biggielist);
881 malloc_string(comment);
882 malloc_string(tmp);
883 malloc_string(command);
884 log_it("Calculating size of all biggiefiles (in total)");
885 sprintf(biggielist, "%s/biggielist.txt", bkpinfo->tmpdir);
886 log_it("biggielist = %s", biggielist);
887 if (!(fin = fopen(biggielist, "r"))) {
888 log_OS_error
889 ("Cannot open biggielist. OK, so estimate is based on filesets only.");
890 } else {
891 log_msg(4, "Reading it...");
892 for (fgets(fname, MAX_STR_LEN, fin); !feof(fin);
893 fgets(fname, MAX_STR_LEN, fin)) {
894 if (fname[strlen(fname) - 1] <= 32) {
895 fname[strlen(fname) - 1] = '\0';
896 }
897 if (0 == strncmp(fname, "/dev/", 5)) {
898 if (is_dev_an_NTFS_dev(fname)) {
899 if ( !find_home_of_exe("ntfsresize")) {
900 fatal_error("ntfsresize not found");
901 }
902 sprintf(command, "ntfsresize --force --info %s|grep '^You might resize at '|cut -d' ' -f5", fname);
903 log_it("command = %s", command);
904 strcpy (tmp, call_program_and_get_last_line_of_output(command));
905 log_it("res of it = %s", tmp);
906 file_len_K = atoll(tmp) / 1024L;
907 } else {
908 file_len_K = get_phys_size_of_drive(fname) * 1024L;
909 }
910 } else {
911 file_len_K = (long) (length_of_file(fname) / 1024);
912 }
913 if (file_len_K > 0) {
914 scratchL += file_len_K;
915 log_msg(4, "%s --> %ld K", fname, file_len_K);
916 }
917 sprintf(comment,
918 "After adding %s, scratchL+%ld now equals %ld", fname,
919 file_len_K, scratchL);
920 log_msg(4, comment);
921 if (feof(fin)) {
922 break;
923 }
924 }
925 }
926 log_it("Closing...");
927 paranoid_fclose(fin);
928 log_it("Finished calculating total size of all biggiefiles");
929 paranoid_free(fname);
930 paranoid_free(biggielist);
931 paranoid_free(comment);
932 paranoid_free(tmp);
933 paranoid_free(command);
934 return (scratchL);
935}
936
937/**
938 * Determine the amount of space (in KB) occupied by a mounted CD.
939 * This can also be used to find the space used for other directories.
940 * @param mountpt The mountpoint/directory to check.
941 * @return The amount of space occupied in KB.
942 */
943long long space_occupied_by_cd(char *mountpt)
944{
945 /*@ buffer ****************************************************** */
946 char tmp[MAX_STR_LEN];
947 char command[MAX_STR_LEN * 2];
948 long long llres;
949 /*@ pointers **************************************************** */
950 char *p;
951 FILE *fin;
952
953 /*@ end vars *************************************************** */
954
955 sprintf(command, "du -sk %s", mountpt);
956 fin = popen(command, "r");
957 (void) fgets(tmp, MAX_STR_LEN, fin);
958 paranoid_pclose(fin);
959 p = strchr(tmp, '\t');
960 if (p) {
961 *p = '\0';
962 }
963 for (p = tmp, llres = 0; *p != '\0'; p++) {
964 llres *= 10;
965 llres += (int) (*p - '0');
966 }
967 return (llres);
968}
969
970
971/**
972 * Update a CRC checksum to include another character.
973 * @param crc The original CRC checksum.
974 * @param c The character to add.
975 * @return The new CRC checksum.
976 * @ingroup utilityGroup
977 */
978unsigned int updcrc(unsigned int crc, unsigned int c)
979{
980 unsigned int tmp;
981 tmp = (crc >> 8) ^ c;
982 crc = (crc << 8) ^ crctttab[tmp & 255];
983 return crc;
984}
985
986/**
987 * Update a reverse CRC checksum to include another character.
988 * @param crc The original CRC checksum.
989 * @param c The character to add.
990 * @return The new CRC checksum.
991 * @ingroup utilityGroup
992 */
993unsigned int updcrcr(unsigned int crc, unsigned int c)
994{
995 unsigned int tmp;
996 tmp = crc ^ c;
997 crc = (crc >> 8) ^ crc16tab[tmp & 0xff];
998 return crc;
999}
1000
1001
1002
1003
1004/**
1005 * Check for an executable on the user's system; write a message to the
1006 * screen and the log if we can't find it.
1007 * @param fname The executable basename to look for.
1008 * @return 0 if it's found, nonzero if not.
1009 */
1010int whine_if_not_found(char *fname)
1011{
1012 /*@ buffers *** */
1013 char command[MAX_STR_LEN * 2];
1014 char errorstr[MAX_STR_LEN];
1015
1016
1017 sprintf(command, "which %s > /dev/null 2> /dev/null", fname);
1018 sprintf(errorstr,
1019 "Please install '%s'. I cannot find it on your system.",
1020 fname);
1021 if (system(command)) {
1022 log_to_screen(errorstr);
1023 log_to_screen
1024 ("There may be hyperlink at http://www.mondorescue.com which");
1025 log_to_screen("will take you to the relevant (missing) package.");
1026 return (1);
1027 } else {
1028 return (0);
1029 }
1030}
1031
1032
1033
1034
1035
1036
1037/**
1038 * Create a data file at @p fname containing @p contents.
1039 * The data actually can be multiple lines, despite the name.
1040 * @param fname The file to create.
1041 * @param contents The data to put in it.
1042 * @return 0 for success, 1 for failure.
1043 */
1044int write_one_liner_data_file(char *fname, char *contents)
1045{
1046 /*@ pointers *************************************************** */
1047 FILE *fout;
1048 int res = 0;
1049
1050 /*@ end vars *************************************************** */
1051
1052 assert_string_is_neither_NULL_nor_zerolength(fname);
1053 if (!contents) {
1054 log_it("%d: Warning - writing NULL to %s", __LINE__, fname);
1055 }
1056 if (!(fout = fopen(fname, "w"))) {
1057 log_it("fname=%s");
1058 log_OS_error("Unable to openout fname");
1059 return (1);
1060 }
1061 fprintf(fout, "%s\n", contents);
1062 paranoid_fclose(fout);
1063 return (res);
1064}
1065
1066
1067
1068/**
1069 * Read @p fname into @p contents.
1070 * @param fname The file to read.
1071 * @param contents Where to put its contents.
1072 * @return 0 for success, nonzero for failure.
1073 */
1074int read_one_liner_data_file(char *fname, char *contents)
1075{
1076 /*@ pointers *************************************************** */
1077 FILE *fin;
1078 int res = 0;
1079 int i;
1080
1081 /*@ end vars *************************************************** */
1082
1083 assert_string_is_neither_NULL_nor_zerolength(fname);
1084 if (!contents) {
1085 log_it("%d: Warning - reading NULL from %s", __LINE__, fname);
1086 }
1087 if (!(fin = fopen(fname, "r"))) {
1088 log_it("fname=%s", fname);
1089 log_OS_error("Unable to openin fname");
1090 return (1);
1091 }
1092 fscanf(fin, "%s\n", contents);
1093 i = strlen(contents);
1094 if (i > 0 && contents[i - 1] < 32) {
1095 contents[i - 1] = '\0';
1096 }
1097 paranoid_fclose(fin);
1098 return (res);
1099}
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109/**
1110 * Copy the files that Mondo/Mindi need to run to the scratchdir or tempdir.
1111 * Currently this includes: copy Mondo's home directory to scratchdir, untar "mondo_home/payload.tgz"
1112 * if it exists, copy LAST-FILELIST-NUMBER to scratchdir, copy mondorestore
1113 * and post-nuke.tgz (if it exists) to tmpdir, and run "hostname > scratchdir/HOSTNAME".
1114 * @param bkpinfo The backup information structure. Fields used:
1115 * - @c bkpinfo->postnuke_tarball
1116 * - @c bkpinfo->scratchdir
1117 * - @c bkpinfo->tmpdir
1118 */
1119void copy_mondo_and_mindi_stuff_to_scratchdir(struct s_bkpinfo *bkpinfo)
1120{
1121 /*@ Char buffers ** */
1122 char command[MAX_STR_LEN * 2];
1123 char tmp[MAX_STR_LEN];
1124 char old_pwd[MAX_STR_LEN];
1125
1126 mvaddstr_and_log_it(g_currentY, 0,
1127 "Copying Mondo's core files to the scratch directory");
1128
1129 log_msg(4, "g_mondo_home='%s'", g_mondo_home);
1130 if (strlen(g_mondo_home) < 2) {
1131 find_and_store_mondoarchives_home(g_mondo_home);
1132 }
1133 sprintf(command, CP_BIN " --parents -pRdf %s %s", g_mondo_home,
1134 bkpinfo->scratchdir);
1135
1136 log_msg(4, "command = %s", command);
1137 if (run_program_and_log_output(command, 1)) {
1138 fatal_error("Failed to copy Mondo's stuff to scratchdir");
1139 }
1140
1141 sprintf(tmp, "%s/payload.tgz", g_mondo_home);
1142 if (does_file_exist(tmp)) {
1143 log_it("Untarring payload %s to scratchdir %s", tmp,
1144 bkpinfo->scratchdir);
1145 (void) getcwd(old_pwd, MAX_STR_LEN - 1);
1146 chdir(bkpinfo->scratchdir);
1147 sprintf(command, "tar -zxvf %s", tmp);
1148 if (run_program_and_log_output(command, FALSE)) {
1149 fatal_error("Failed to untar payload");
1150 }
1151 chdir(old_pwd);
1152 }
1153
1154 sprintf(command, "cp -f %s/LAST-FILELIST-NUMBER %s", bkpinfo->tmpdir,
1155 bkpinfo->scratchdir);
1156
1157 if (run_program_and_log_output(command, FALSE)) {
1158 fatal_error("Failed to copy LAST-FILELIST-NUMBER to scratchdir");
1159 }
1160
1161 strcpy(tmp,
1162 call_program_and_get_last_line_of_output("which mondorestore"));
1163 if (!tmp[0]) {
1164 fatal_error
1165 ("'which mondorestore' returned null. Where's your mondorestore? `which` can't find it. That's odd. Did you install mondorestore?");
1166 }
1167 sprintf(command, "cp -f %s %s", tmp, bkpinfo->tmpdir);
1168 if (run_program_and_log_output(command, FALSE)) {
1169 fatal_error("Failed to copy mondorestore to tmpdir");
1170 }
1171
1172 sprintf(command, "hostname > %s/HOSTNAME", bkpinfo->scratchdir);
1173 paranoid_system(command);
1174
1175 if (bkpinfo->postnuke_tarball[0]) {
1176 sprintf(command, "cp -f %s %s/post-nuke.tgz",
1177 bkpinfo->postnuke_tarball, bkpinfo->tmpdir);
1178 if (run_program_and_log_output(command, FALSE)) {
1179 fatal_error("Unable to copy post-nuke tarball to tmpdir");
1180 }
1181 }
1182
1183
1184 mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1185}
1186
1187
1188
1189
1190
1191/**
1192 * Store the client's NFS configuration in files to be restored at restore-time.
1193 * Assumes that @c bkpinfo->media_type = nfs, but does not check for this.
1194 * @param bkpinfo The backup information structure. Fields used:
1195 * - @c nfs_mount
1196 * - @c nfs_remote_dir
1197 * - @c tmpdir
1198 */
1199void store_nfs_config(struct s_bkpinfo *bkpinfo)
1200{
1201
1202 /*@ buffers ******** */
1203 char outfile[MAX_STR_LEN];
1204 char nfs_dev[MAX_STR_LEN];
1205 char nfs_mount[MAX_STR_LEN];
1206 char nfs_client_ipaddr[MAX_STR_LEN];
1207 char nfs_client_netmask[MAX_STR_LEN];
1208 char nfs_client_broadcast[MAX_STR_LEN];
1209 char nfs_client_defgw[MAX_STR_LEN];
1210 char nfs_server_ipaddr[MAX_STR_LEN];
1211 char tmp[MAX_STR_LEN];
1212 char command[MAX_STR_LEN * 2];
1213
1214 /*@ pointers ***** */
1215 char *p;
1216 FILE *fout;
1217
1218
1219
1220 log_it("Storing NFS configuration");
1221 strcpy(tmp, bkpinfo->nfs_mount);
1222 p = strchr(tmp, ':');
1223 if (!p) {
1224 fatal_error
1225 ("NFS mount doesn't have a colon in it, e.g. 192.168.1.4:/home/nfs");
1226 }
1227 *(p++) = '\0';
1228 strcpy(nfs_server_ipaddr, tmp);
1229 strcpy(nfs_mount, p);
1230 sprintf(command,
1231 "ifconfig | tr '\n' '#' | sed s/##// | tr '#' ' ' | tr '' '\n' | head -n1 | cut -d' ' -f1");
1232 strcpy(nfs_dev, call_program_and_get_last_line_of_output(command));
1233 sprintf(command,
1234 "ifconfig | tr '\n' '#' | sed s/##// | tr '#' ' ' | tr '' '\\n' | head -n1 | tr -s '\t' ' ' | cut -d' ' -f7 | cut -d':' -f2");
1235 strcpy(nfs_client_ipaddr,
1236 call_program_and_get_last_line_of_output(command));
1237 sprintf(command,
1238 "ifconfig | tr '\n' '#' | sed s/##// | tr '#' ' ' | tr '' '\\n' | head -n1 | tr -s '\t' ' ' | cut -d' ' -f9 | cut -d':' -f2");
1239 strcpy(nfs_client_netmask,
1240 call_program_and_get_last_line_of_output(command));
1241 sprintf(command,
1242 "ifconfig | tr '\n' '#' | sed s/##// | tr '#' ' ' | tr '' '\\n' | head -n1 | tr -s '\t' ' ' | cut -d' ' -f8 | cut -d':' -f2");
1243 strcpy(nfs_client_broadcast,
1244 call_program_and_get_last_line_of_output(command));
1245 sprintf(command,
1246 "route -n | grep '^0.0.0.0' | awk '{print $2}'");
1247 strcpy(nfs_client_defgw,
1248 call_program_and_get_last_line_of_output(command));
1249 sprintf(tmp,
1250 "nfs_client_ipaddr=%s; nfs_server_ipaddr=%s; nfs_mount=%s",
1251 nfs_client_ipaddr, nfs_server_ipaddr, nfs_mount);
1252 if (strlen(nfs_dev) < 2) {
1253 fatal_error
1254 ("Unable to find ethN (eth0, eth1, ...) adapter via NFS mount you specified.");
1255 }
1256 sprintf(outfile, "%s/start-nfs", bkpinfo->tmpdir);
1257 sprintf(tmp, "outfile = %s", outfile);
1258 log_it(tmp);
1259 if (!(fout = fopen(outfile, "w"))) {
1260 fatal_error("Cannot store NFS config");
1261 }
1262 fprintf(fout, "#!/bin/sh\n");
1263 fprintf(fout, "# number of ping\n");
1264 fprintf(fout, "ipcount=3\n");
1265 fprintf(fout, "for i in `cat /proc/cmdline` ; do\n");
1266 fprintf(fout, " echo $i | grep -qi ping= && ipcount=`echo $i | cut -d= -f2`\n");
1267 fprintf(fout, "done\n");
1268 fprintf(fout, "ifconfig lo 127.0.0.1 # config loopback\n");
1269 fprintf(fout, "ipaddress=%s\n", nfs_client_ipaddr);
1270 fprintf(fout, "ipnetmask=%s\n", nfs_client_netmask);
1271 fprintf(fout, "ipbroadcast=%s\n", nfs_client_broadcast);
1272 fprintf(fout, "ipgateway=%s\n", nfs_client_defgw);
1273 fprintf(fout, "ipconf=\n");
1274 fprintf(fout, "for i in `cat /proc/cmdline` ; do\n");
1275 fprintf(fout, " echo $i | grep -qi ipconf= && ipconf=`echo $i | cut -d= -f2`\n");
1276 fprintf(fout, "done\n");
1277 fprintf(fout, "if [ \"$ipconf\" = \"dhcp\" ]; then\n");
1278 fprintf(fout, " udhcpc -i %s\n", nfs_dev);
1279 fprintf(fout, "else\n");
1280 fprintf(fout, " if [ \"$ipconf\" != \"\" ]; then\n");
1281 fprintf(fout, " ipaddress=`echo $ipconf | cut -d: -f1`\n");
1282 fprintf(fout, " ipnetmask=`echo $ipconf | cut -d: -f2`\n");
1283 fprintf(fout, " ipbroadcast=`echo $ipconf | cut -d: -f3`\n");
1284 fprintf(fout, " ipgateway=`echo $ipconf | cut -d: -f4`\n");
1285 fprintf(fout, " fi\n");
1286 fprintf(fout, " ifconfig %s $ipaddress netmask $ipnetmask broadcast $ipbroadcast\n", nfs_dev);
1287 fprintf(fout, " route add default gw $ipgateway\n");
1288 fprintf(fout, "fi\n");
1289 fprintf(fout, "ping -c $ipcount %s # ping server\n", nfs_server_ipaddr);
1290 fprintf(fout, "mount -t nfs -o nolock %s /tmp/isodir\n",
1291 bkpinfo->nfs_mount);
1292 paranoid_fclose(fout);
1293 chmod(outfile, 0777);
1294 make_hole_for_dir("/var/cache/mondo-archive");
1295
1296// paranoid_system ("mkdir -p /var/cache/mondo-archive 2> /dev/null");
1297
1298 sprintf(tmp, "cp -f %s /var/cache/mondo-archive", outfile);
1299 run_program_and_log_output(tmp, FALSE);
1300
1301 sprintf(tmp, "%s/NFS-DEV", bkpinfo->tmpdir);
1302 write_one_liner_data_file(tmp, nfs_dev);
1303
1304 sprintf(tmp, "%s/NFS-CLIENT-IPADDR", bkpinfo->tmpdir);
1305 write_one_liner_data_file(tmp, nfs_client_ipaddr);
1306 sprintf(tmp, "%s/NFS-CLIENT-NETMASK", bkpinfo->tmpdir);
1307 write_one_liner_data_file(tmp, nfs_client_netmask);
1308 sprintf(tmp, "%s/NFS-CLIENT-BROADCAST", bkpinfo->tmpdir);
1309 write_one_liner_data_file(tmp, nfs_client_broadcast);
1310 sprintf(tmp, "%s/NFS-CLIENT-DEFGW", bkpinfo->tmpdir);
1311 write_one_liner_data_file(tmp, nfs_client_defgw);
1312 sprintf(tmp, "%s/NFS-SERVER-IPADDR", bkpinfo->tmpdir);
1313 write_one_liner_data_file(tmp, nfs_server_ipaddr);
1314 sprintf(tmp, "%s/NFS-SERVER-MOUNT", bkpinfo->tmpdir);
1315 write_one_liner_data_file(tmp, bkpinfo->nfs_mount);
1316 sprintf(tmp, "%s/NFS-SERVER-PATH", bkpinfo->tmpdir);
1317 write_one_liner_data_file(tmp, bkpinfo->nfs_remote_dir);
1318 sprintf(tmp, "%s/ISO-PREFIX", bkpinfo->tmpdir);
1319 write_one_liner_data_file(tmp, bkpinfo->prefix);
1320 log_it("Finished storing NFS configuration");
1321}
1322
1323
1324
1325
1326
1327
1328/**
1329 * Determine the approximate number of media that the backup will take up,
1330 * and tell the user. The uncompressed size is estimated as size_of_all_biggiefiles_K()
1331 * plus (noof_sets x bkpinfo->optimal_set_size). The compression factor is estimated as
1332 * 2/3 for LZO and 1/2 for bzip2. The data is not saved anywhere. If there are any
1333 * "imagedevs", the estimate is not shown as it will be wildly inaccurate.
1334 * If there are more than 50 media estimated, the estimate will not be shown.
1335 * @param bkpinfo The backup information structure. Fields used:
1336 * - @c bkpinfo->backup_media_type
1337 * - @c bkpinfo->image_devs
1338 * - @c bkpinfo->media_size
1339 * - @c bkpinfo->optimal_set_size
1340 * - @c bkpinfo->use_lzo
1341 * @param noof_sets The number of filesets created.
1342 * @ingroup archiveGroup
1343 */
1344void
1345estimate_noof_media_required(struct s_bkpinfo *bkpinfo, long noof_sets)
1346{
1347 /*@ buffers *************** */
1348 char tmp[MAX_STR_LEN];
1349
1350 /*@ long long ************* */
1351 long long scratchLL;
1352
1353 if (bkpinfo->media_size[1] <= 0 || bkpinfo->backup_media_type == nfs) {
1354 log_to_screen("Number of media required: UNKNOWN");
1355 return;
1356 }
1357
1358 log_it("Estimating number of media required...");
1359 scratchLL =
1360 (long long) (noof_sets) * (long long) (bkpinfo->optimal_set_size)
1361 + (long long) (size_of_all_biggiefiles_K(bkpinfo));
1362 scratchLL = (scratchLL / 1024) / bkpinfo->media_size[1];
1363 scratchLL++;
1364 if (bkpinfo->use_lzo) {
1365 scratchLL = (scratchLL * 2) / 3;
1366 } else {
1367 scratchLL = scratchLL / 2;
1368 }
1369 if (!scratchLL) {
1370 scratchLL++;
1371 }
1372 if (scratchLL <= 1) {
1373 sprintf(tmp,
1374 "Your backup will probably occupy a single %s. Maybe two.",
1375 media_descriptor_string(bkpinfo->backup_media_type));
1376 } else if (scratchLL > 4) {
1377 sprintf(tmp,
1378 "Your backup will occupy one meeeeellion media! (maybe %s)",
1379 number_to_text((int) (scratchLL + 1)));
1380 } else {
1381 sprintf(tmp, "Your backup will occupy approximately %s media.",
1382 number_to_text((int) (scratchLL + 1)));
1383 }
1384 if (!bkpinfo->image_devs[0] && (scratchLL < 50)) {
1385 log_to_screen(tmp);
1386 }
1387}
1388
1389
1390/**
1391 * Get the last suffix of @p instr.
1392 * If @p instr was "httpd.log.gz", we would return "gz".
1393 * @param instr The filename to get the suffix of.
1394 * @return The suffix (without a dot), or "" if none.
1395 * @note The returned string points to static storage that will be overwritten with each call.
1396 */
1397char *sz_last_suffix(char *instr)
1398{
1399 static char outstr[MAX_STR_LEN];
1400 char *p;
1401
1402 p = strrchr(instr, '.');
1403 if (!p) {
1404 outstr[0] = '\0';
1405 } else {
1406 strcpy(outstr, p);
1407 }
1408 return (outstr);
1409}
1410
1411
1412/**
1413 * Determine whether a file is compressed. This is done
1414 * by reading through the "do-not-compress-these" file distributed with Mondo.
1415 * @param filename The file to check.
1416 * @return TRUE if it's compressed, FALSE if not.
1417 */
1418bool is_this_file_compressed(char *filename)
1419{
1420 char do_not_compress_these[MAX_STR_LEN];
1421 char tmp[MAX_STR_LEN];
1422 char *p;
1423
1424 sprintf(tmp, "%s/do-not-compress-these", g_mondo_home);
1425 if (!does_file_exist(tmp)) {
1426 return (FALSE);
1427 }
1428 strcpy(do_not_compress_these, last_line_of_file(tmp));
1429 for (p = do_not_compress_these; p != NULL; p++) {
1430 strcpy(tmp, p);
1431 if (strchr(tmp, ' ')) {
1432 *(strchr(tmp, ' ')) = '\0';
1433 }
1434 if (!strcmp(sz_last_suffix(filename), tmp)) { /*printf("MATCH\n"); */
1435 return (TRUE);
1436 }
1437 if (!(p = strchr(p, ' '))) {
1438 break;
1439 }
1440 }
1441 return (FALSE);
1442}
1443
1444
1445
1446int mode_of_file(char *fname)
1447{
1448 struct stat buf;
1449
1450 if (lstat(fname, &buf)) {
1451 return (-1);
1452 } // error
1453 else {
1454 return (buf.st_mode);
1455 }
1456}
1457
1458
1459
1460
1461/**
1462 * Create a small script that mounts /boot, calls @c grub-install, and syncs the disks.
1463 * @param outfile Where to put the script.
1464 * @return 0 for success, 1 for failure.
1465 */
1466int make_grub_install_scriptlet(char *outfile)
1467{
1468 FILE *fout;
1469 char *tmp;
1470 int retval = 0;
1471
1472 malloc_string(tmp);
1473 if ((fout = fopen(outfile, "w"))) {
1474 fprintf(fout,
1475 "#!/bin/sh\n\nmount /boot > /dev/null 2> /dev/null\ngrub-install $@\nres=$?\nsync;sync;sync\nexit $res\n");
1476 paranoid_fclose(fout);
1477 log_msg(2, "Created %s", outfile);
1478 sprintf(tmp, "chmod +x %s", outfile);
1479 paranoid_system(tmp);
1480 retval = 0;
1481 } else {
1482 retval = 1;
1483 }
1484 paranoid_free(tmp);
1485 return (retval);
1486}
1487
1488/* @} - end fileGroup */
Note: See TracBrowser for help on using the repository browser.