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

Last change on this file since 681 was 681, checked in by andree, 14 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.