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, 14 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.