source: branches/stable/mondo/src/common/libmondo-string.c @ 1591

Last change on this file since 1591 was 1591, checked in by Bruno Cornec, 13 years ago
  • Improve tape support doc (Tilman Schmidt <tilman_at_imap.cc>)
  • mdadm.conf files added to deplist
  • Fix gentoo issues again (Francesco Talamona ti.liame_at_email.it)
  • Fix bug #187 (Scott Cummings rsc_at_usfamily.net)

(merge -r1579:1590 $SVN_M/branches/2.2.5)

  • Property svn:keywords set to Id
File size: 26.0 KB
Line 
1/*
2   $Id: libmondo-string.c 1591 2007-08-01 22:26:40Z bruno $
3*/
4
5/**
6 * @file
7 * Functions for handling strings.
8 */
9
10#include "my-stuff.h"
11#include "mr_mem.h"
12#include "mr_str.h"
13#include "mr_gettext.h"
14
15#include "mondostructures.h"
16#include "libmondo-string.h"
17#include "libmondo-files-EXT.h"
18#include "newt-specific-EXT.h"
19#include "libmondo-tools-EXT.h"
20#include <math.h>
21
22/*@unused@*/
23//static char cvsid[] = "$Id: libmondo-string.c 1591 2007-08-01 22:26:40Z bruno $";
24
25extern int g_current_media_number;
26extern long long g_tape_posK;
27
28/**
29 * @addtogroup stringGroup
30 * @{
31 */
32/**
33 * Build a partition name from a drive and a partition number.
34 * @param drive The drive basename of the partition name (e.g. /dev/hda)
35 * @param partno The partition number (e.g. 1)
36 * @param partition Where to put the partition name (e.g. /dev/hda1)
37 * @return @p partition.
38 * @note If @p drive ends in a digit, then 'p' (on Linux) or 's' (on *BSD) is added before @p partno.
39 */
40char *build_partition_name(char *partition, const char *drive, int partno)
41{
42    char *p = NULL;
43    char *c = NULL;
44
45    assert(partition != NULL);
46    assert_string_is_neither_NULL_nor_zerolength(drive);
47    assert(partno >= 0);
48
49    p = strcpy(partition, drive);
50    /* is this a devfs device path? */
51    c = strrchr(partition, '/');
52    if (c && strncmp(c, "/disc", 5) == 0) {
53        /* yup it's devfs, return the "part" path */
54        /* format /dev/.../disc */
55        strcpy(c + 1, "part");
56        p = c + 5;
57    } else {
58        p += strlen(p);
59        if (isdigit(p[-1])) {
60            *p++ =
61#ifdef BSD
62                's';
63#else
64                'p';
65#endif
66        }
67    }
68    sprintf(p, "%d", partno);
69    return (partition);
70}
71
72
73/**
74 * Pad a string on both sides so it appears centered.
75 * @param in_out The string to be center-padded (modified).
76 * @param width The width of the final result.
77 */
78void center_string(char *in_out, int width)
79{
80    char *scratch = NULL;
81    int i = 0;                      /* purpose */
82    int len = 0;                    /* purpose */
83    int mid = 0;                    /* purpose */
84    int x = 0;                      /* purpose */
85
86    assert(in_out != NULL);
87    assert(width > 2);
88
89    if (strlen(in_out) == 0) {
90        return;
91    }
92    mr_asprintf(&scratch, in_out);
93    mr_strip_spaces(scratch);
94    len = (int) strlen(scratch);
95    mid = width / 2;
96    x = mid - len / 2;
97    for (i = 0; i < x; i++) {
98        in_out[i] = ' ';
99    }
100    in_out[i] = '\0';
101    strcat(in_out, scratch);
102    for (i = x + len ; i < width - 1; i++) {
103            in_out[i] = ' ';
104        }
105    in_out[i] = '\0';
106}
107
108
109/**
110 * Turn an entry from the RAID editor's disklist into a GUI-friendly string.
111 * The format is: the device left-aligned and padded to 24 places, followed by a space and the
112 * index, right-aligned and padded to eight places. The total string length
113 * is exactly 33.
114 * @param disklist The disklist to operate on.
115 * @param lino The line number from @p disklist to convert to a string.
116 * @return The string form of the disklist entry.
117 * @note The returned string points to static storage and will be overwritten with each call.
118 */
119char *disklist_entry_to_string(struct list_of_disks *disklist, int lino)
120{
121
122    /*@ buffers ********************************************************** */
123    static char output[MAX_STR_LEN];
124
125    assert(disklist != NULL);
126
127    sprintf(output, "%-24s %8d", disklist->el[lino].device,
128            disklist->el[lino].index);
129    return (output);
130}
131
132
133/**
134 * Turn a "friendly" sizestring into a number of megabytes.
135 * Supports the suffixes 'k'/'K', 'm'/'M', and 'g'/'G'. Calls
136 * fatal_error() if an unknown suffix is encountered.
137 * @param incoming The sizestring to convert (e.g. "40m", "2g").
138 * @return The size in megabytes.
139 */
140long friendly_sizestr_to_sizelong(char *incoming)
141{
142    long outval = 0L;
143    int i = 0;
144    char *tmp = NULL;
145    char ch = ' ';
146
147    assert_string_is_neither_NULL_nor_zerolength(incoming);
148
149    if (!incoming[0]) {
150        return(0L);
151    }
152    if (strchr(incoming, '.')) {
153        fatal_error("Please use integers only. No decimal points.");
154    }
155    mr_asprintf(&tmp, "%s", incoming);
156    i = (int) strlen(tmp);
157    if (tmp[i - 1] == 'B' || tmp[i - 1] == 'b') {
158        tmp[i - 1] = '\0';
159    }
160    for (i = 0; i < (int) strlen(tmp) && isdigit(tmp[i]); i++);
161    ch = tmp[i];
162    tmp[i] = '\0';
163    outval = atol(tmp);
164    mr_free(tmp);
165
166    if (ch == 'g' || ch == 'G') {
167        outval = outval * 1024;
168    } else if (ch == 'k' || ch == 'K') {
169        outval = outval / 1024;
170    } else if (ch == 't' || ch == 'T')  // terabyte
171    {
172        outval *= 1048576;
173    } else if (ch == 'Y' || ch == 'y')  // yottabyte - the biggest measure in the info file
174    {
175        log_it
176            ("Oh my gosh. You actually think a YOTTABYTE will get you anywhere? What're you going to do with 1,208,925,819,614,629,174,706,176 bytes of data?!?!");
177        popup_and_OK
178            (_("That sizespec is more than 1,208,925,819,614,629,174,706,176 bytes. You have a shocking amount of data. Please send a screenshot to the list :-)"));
179        fatal_error("Integer overflow.");
180    } else if (ch != 'm' && ch != 'M') {
181        mr_asprintf(&tmp, "Re: parameter '%s' - bad multiplier ('%c')",
182                 incoming, ch);
183        fatal_error(tmp);
184    }
185    return (outval);
186}
187
188
189/**
190 * Turn a marker byte (e.g. BLK_START_OF_BACKUP) into a string (e.g. "BLK_START_OF_BACKUP").
191 * Unknown markers are identified as "BLK_UNKNOWN (%d)" where %d is the decimal value.
192 * @param marker The marker byte to stringify.
193 * @return @p marker as a string.
194 * @note The returned string points to static storage that will be overwritten with each call.
195 */
196char *marker_to_string(int marker)
197{
198    /*@ buffer ****************************************************** */
199    static char outstr[MAX_STR_LEN];
200
201
202    /*@ end vars *************************************************** */
203
204    switch (marker) {
205    case BLK_START_OF_BACKUP:
206        strcpy(outstr, "BLK_START_OF_BACKUP");
207        break;
208    case BLK_START_OF_TAPE:
209        strcpy(outstr, "BLK_START_OF_TAPE");
210        break;
211    case BLK_START_AN_AFIO_OR_SLICE:
212        strcpy(outstr, "BLK_START_AN_AFIO_OR_SLICE");
213        break;
214    case BLK_STOP_AN_AFIO_OR_SLICE:
215        strcpy(outstr, "BLK_STOP_AN_AFIO_OR_SLICE");
216        break;
217    case BLK_START_AFIOBALLS:
218        strcpy(outstr, "BLK_START_AFIOBALLS");
219        break;
220    case BLK_STOP_AFIOBALLS:
221        strcpy(outstr, "BLK_STOP_AFIOBALLS");
222        break;
223    case BLK_STOP_BIGGIEFILES:
224        strcpy(outstr, "BLK_STOP_BIGGIEFILES");
225        break;
226    case BLK_START_A_NORMBIGGIE:
227        strcpy(outstr, "BLK_START_A_NORMBIGGIE");
228        break;
229    case BLK_START_A_PIHBIGGIE:
230        strcpy(outstr, "BLK_START_A_PIHBIGGIE");
231        break;
232    case BLK_START_EXTENDED_ATTRIBUTES:
233        strcpy(outstr, "BLK_START_EXTENDED_ATTRIBUTES");
234        break;
235    case BLK_STOP_EXTENDED_ATTRIBUTES:
236        strcpy(outstr, "BLK_STOP_EXTENDED_ATTRIBUTES");
237        break;
238    case BLK_START_EXAT_FILE:
239        strcpy(outstr, "BLK_START_EXAT_FILE");
240        break;
241    case BLK_STOP_EXAT_FILE:
242        strcpy(outstr, "BLK_STOP_EXAT_FILE");
243        break;
244    case BLK_START_BIGGIEFILES:
245        strcpy(outstr, "BLK_START_BIGGIEFILES");
246        break;
247    case BLK_STOP_A_BIGGIE:
248        strcpy(outstr, "BLK_STOP_A_BIGGIE");
249        break;
250    case BLK_END_OF_TAPE:
251        strcpy(outstr, "BLK_END_OF_TAPE");
252        break;
253    case BLK_END_OF_BACKUP:
254        strcpy(outstr, "BLK_END_OF_BACKUP");
255        break;
256    case BLK_ABORTED_BACKUP:
257        strcpy(outstr, "BLK_ABORTED_BACKUP");
258        break;
259    case BLK_START_FILE:
260        strcpy(outstr, "BLK_START_FILE");
261        break;
262    case BLK_STOP_FILE:
263        strcpy(outstr, "BLK_STOP_FILE");
264        break;
265    default:
266        sprintf(outstr, "BLK_UNKNOWN (%d)", marker);
267        break;
268    }
269    return (outstr);
270}
271
272
273/**
274 * Turn a line from the mountlist into a GUI-friendly string.
275 * The format is as follows: the left-aligned @p device field padded to 24 places,
276 * a space, the left-aligned @p mountpoint field again padded to 24 places, a space,
277 * the left-aligned @p format field padded to 10 places, a space, and the right-aligned
278 * @p size field (in MB) padded to 8 places. The total string length is exactly 69.
279 * @param mountlist The mountlist to operate on.
280 * @param lino The line number in @p mountlist to stringify.
281 * @return The string form of <tt>mountlist</tt>-\>el[<tt>lino</tt>].
282 * @note The returned string points to static storage and will be overwritten with each call.
283 */
284char *mountlist_entry_to_string(struct mountlist_itself *mountlist,
285                                int lino)
286{
287
288    /*@ buffer *********************************************************** */
289    static char output[MAX_STR_LEN];
290
291    assert(mountlist != NULL);
292
293    sprintf(output, "%-24s %-24s %-10s %8lld", mountlist->el[lino].device,
294            mountlist->el[lino].mountpoint, mountlist->el[lino].format,
295            mountlist->el[lino].size / 1024);
296    return (output);
297}
298
299
300/**
301 * Generate a friendly string containing "X blah blah disk(s)"
302 * @param noof_disks The number of disks (the X).
303 * @param label The "blah blah" part in the middle. If you leave this blank
304 * there will be a weird double space in the middle, so pass *something*.
305 * @return The string containing "X blah blah disk(s)".
306 * @note The returned string points to static storage and will be overwritten with each call.
307 */
308char *number_of_disks_as_string(int noof_disks, char *label)
309{
310
311    /*@ buffers ********************************************************* */
312    static char output[MAX_STR_LEN];
313
314    /*@ char     ******************************************************** */
315    char p = ' ';
316
317    assert(label != NULL);
318
319    if (noof_disks > 1) {
320        p = 's';
321    } else {
322        p = ' ';
323    }
324    sprintf(output, "%d %s disk%c", noof_disks, label, p);
325    while (strlen(output) < 14) {
326        strcat(output, " ");
327    }
328    return (output);
329}
330
331
332
333/**
334 * Change @p i into a friendly string. If @p i is \<= 10 then write out the
335 * number (e.g. "one", "two", ..., "nine", "ten", "11", ...).
336 * @param i The number to stringify.
337 * @return The string form of @p i.
338 * @note The returned value points to static strorage that will be overwritten with each call.
339 */
340char *number_to_text(int i)
341{
342
343    /*@ buffers ***************************************************** */
344    static char output[MAX_STR_LEN];
345
346
347    /*@ end vars *************************************************** */
348
349    switch (i) {
350    case 0:
351        strcpy(output, "zero");
352        break;
353    case 1:
354        strcpy(output, "one");
355        break;
356    case 2:
357        strcpy(output, "two");
358        break;
359    case 3:
360        strcpy(output, "three");
361        break;
362    case 4:
363        strcpy(output, "four");
364        break;
365    case 5:
366        strcpy(output, "five");
367        break;
368    case 6:
369        strcpy(output, "six");
370        break;
371    case 7:
372        strcpy(output, "seven");
373        break;
374    case 8:
375        strcpy(output, "eight");
376        break;
377    case 9:
378        strcpy(output, "nine");
379    case 10:
380        strcpy(output, "ten");
381    default:
382        sprintf(output, "%d", i);
383    }
384    return (output);
385}
386
387
388/**
389 * Replace all occurences of @p token with @p value while copying @p ip to @p output.
390 * @param ip The input string containing zero or more <tt>token</tt>s.
391 * @param output The output string written with the <tt>token</tt>s replaced by @p value.
392 * @param token The token to be relaced with @p value.
393 * @param value The value to replace @p token.
394 */
395void resolve_naff_tokens(char *output, char *ip, char *value, char *token)
396{
397    /*@ buffers *** */
398    char *input;
399
400    /*@ pointers * */
401    char *p;
402
403    input = mr_malloc(2000);
404    // BERLIOS: seems to cause invalid errors
405    //assert_string_is_neither_NULL_nor_zerolength(ip);
406    assert_string_is_neither_NULL_nor_zerolength(token);
407    assert(value != NULL);
408
409    strcpy(output, ip);         /* just in case the token doesn't appear in string at all */
410    for (strcpy(input, ip); strstr(input, token); strcpy(input, output)) {
411        strcpy(output, input);
412        p = strstr(output, token);
413        *p = '\0';
414        strcat(output, value);
415        p = strstr(input, token) + strlen(token);
416        strcat(output, p);
417    }
418    mr_free(input);
419}
420
421
422/**
423 * Generate the filename of slice @p sliceno of biggiefile @p bigfileno
424 * in @p path with suffix @p s. The format is as follows: @p path, followed
425 * by "/slice-" and @p bigfileno zero-padded to 7 places, followed by
426 * a dot and @p sliceno zero-padded to 5 places, followed by ".dat" and the
427 * suffix. The string is a minimum of 24 characters long.
428 * @param bigfileno The biggiefile number. Starts from 0.
429 * @param sliceno The slice number of biggiefile @p bigfileno. 0 is a "header"
430 * slice (no suffix) containing the biggiestruct, then are the compressed
431 * slices, then an empty uncompressed "trailer" slice.
432 * @param path The path to append (with a / in the middle) to the slice filename.
433 * @param s If not "" then add a "." and this to the end.
434 * @return The slice filename.
435 * @note The returned value points to static storage and will be overwritten with each call.
436 */
437char *slice_fname(long bigfileno, long sliceno, char *path, char *s)
438{
439
440    /*@ buffers **************************************************** */
441    static char output[MAX_STR_LEN];
442    char *suffix = NULL;
443
444    /*@ end vars *************************************************** */
445
446    assert_string_is_neither_NULL_nor_zerolength(path);
447    if (s[0] != '\0') {
448        mr_asprintf(&suffix, ".%s", s);
449    } else {
450        mr_asprintf(&suffix, "");
451    }
452    sprintf(output, "%s/slice-%07ld.%05ld.dat%s", path, bigfileno, sliceno,
453            suffix);
454    mr_free(suffix);
455    return (output);
456}
457
458
459/**
460 * Generate a spinning symbol based on integer @p i.
461 * The symbol rotates through the characters / - \ | to form an ASCII "spinner"
462 * if successively written to the same location on screen.
463 * @param i The amount of progress or whatever else to use to determine the character
464 * for this iteration of the spinner.
465 * @return The character for this iteration.
466 */
467int special_dot_char(int i)
468{
469    switch (i % 4) {
470    case 0:
471        return ('/');
472    case 1:
473        return ('-');
474    case 2:
475        return ('\\');
476    case 3:
477        return ('|');
478    default:
479        return ('.');
480    }
481    return ('.');
482}
483
484
485/**
486 * Wrap @p flaws_str across three lines. The first two are no more than 74 characters wide.
487 * @param flaws_str The original string to split.
488 * @param flaws_str_A Where to put the first 74-or-less characters.
489 * @param flaws_str_B Where to put the second 74-or-less characters.
490 * @param flaws_str_C Where to put the rest.
491 * @param res The result of the original evaluate_mountlist() operation.
492 * @return TRUE if res == 0, FALSE otherwise.
493 */
494bool
495spread_flaws_across_three_lines(char *flaws_str, char *flaws_str_A,
496                                char *flaws_str_B, char *flaws_str_C,
497                                int res)
498{
499
500    /*@ int ************************************************************* */
501    int i = 0;
502
503    /*@ initialize ****************************************************** */
504    assert(flaws_str_A != NULL);
505    assert(flaws_str_B != NULL);
506    assert(flaws_str_C != NULL);
507    assert(flaws_str != NULL);
508
509    flaws_str_A[0] = flaws_str_B[0] = flaws_str_C[0] = '\0';
510
511
512    if (!res && !strlen(flaws_str)) {
513        return (TRUE);
514    }
515    if (strlen(flaws_str) > 0) {
516        sprintf(flaws_str_A, "%s", flaws_str + 1);
517    }
518    if (strlen(flaws_str_A) >= 74) {
519        for (i = 74; flaws_str_A[i] != ' '; i--);
520        strcpy(flaws_str_B, flaws_str_A + i + 1);
521        flaws_str_A[i] = '\0';
522    }
523    if (strlen(flaws_str_B) >= 74) {
524        for (i = 74; flaws_str_B[i] != ' '; i--);
525        strcpy(flaws_str_C, flaws_str_B + i + 1);
526        flaws_str_B[i] = '\0';
527    }
528    if (res) {
529        return (FALSE);
530    } else {
531        return (TRUE);
532    }
533}
534
535
536/**
537 * Compare @p stringA and @p stringB. This uses an ASCII sort for everything
538 * up to the digits on the end but a numerical sort for the digits on the end.
539 * @param stringA The first string to compare.
540 * @param stringB The second string to compare.
541 * @return The same as strcmp() - <0 if A<B, 0 if A=B, >0 if A>B.
542 * @note This function only does a numerical sort on the @e last set of numbers. If
543 * there are any in the middle those will be sorted ASCIIbetically.
544 */
545int strcmp_inc_numbers(char *stringA, char *stringB)
546{
547    /*@ int ********************************************************* */
548    int i;
549    int start_of_numbers_in_A;
550    int start_of_numbers_in_B;
551    int res;
552
553    /*@ long ******************************************************* */
554    long numA;
555    long numB;
556
557    /*@ end vars *************************************************** */
558    assert(stringA != NULL);
559    assert(stringB != NULL);
560
561    if (strlen(stringA) == strlen(stringB)) {
562        return (strcmp(stringA, stringB));
563    }
564    for (i = (int) strlen(stringA); i > 0 && isdigit(stringA[i - 1]); i--);
565    if (i == (int) strlen(stringA)) {
566        return (strcmp(stringA, stringB));
567    }
568    start_of_numbers_in_A = i;
569    for (i = (int) strlen(stringB); i > 0 && isdigit(stringB[i - 1]); i--);
570    if (i == (int) strlen(stringB)) {
571        return (strcmp(stringA, stringB));
572    }
573    start_of_numbers_in_B = i;
574    if (start_of_numbers_in_A != start_of_numbers_in_B) {
575        return (strcmp(stringA, stringB));
576    }
577    res = strncmp(stringA, stringB, (size_t) i);
578    if (res) {
579        return (res);
580    }
581    numA = atol(stringA + start_of_numbers_in_A);
582    numB = atol(stringB + start_of_numbers_in_B);
583    return ((int) (numA - numB));
584}
585
586
587
588/**
589 * Strip excess baggage from @p input, which should be a line from afio.
590 * For now this copies the whole line unless it finds a set of quotes, in which case
591 * it copies their contents only.
592 * @param input The input line (presumably from afio).
593 * @return The stripped line.
594 * @note The returned string points to static storage that will be overwritten with each call.
595 */
596char *strip_afio_output_line(char *input)
597{
598    /*@ buffer ****************************************************** */
599    static char output[MAX_STR_LEN];
600
601    /*@ pointers **************************************************** */
602    char *p;
603    char *q;
604    /*@ end vars *************************************************** */
605
606    assert(input != NULL);
607    strcpy(output, input);
608    p = strchr(input, '\"');
609    if (p) {
610        q = strchr(++p, '\"');
611        if (q) {
612            strcpy(output, p);
613            *(strchr(output, '\"')) = '\0';
614        }
615    }
616    return (output);
617}
618
619
620/**
621 * If there are double quotes "" around @p incoming then remove them.
622 * This does not affect other quotes that may be embedded within the string.
623 * @param incoming The string to trim quotes from (modified).
624 * @return @p incoming.
625 */
626char *trim_empty_quotes(char *incoming)
627{
628    /*@ buffer ****************************************************** */
629    static char outgoing[MAX_STR_LEN];
630
631    /*@ end vars *************************************************** */
632    assert(incoming != NULL);
633
634    if (incoming[0] == '\"' && incoming[strlen(incoming) - 1] == '\"') {
635        strcpy(outgoing, incoming + 1);
636        outgoing[strlen(outgoing) - 1] = '\0';
637    } else {
638        strcpy(outgoing, incoming);
639    }
640    return (outgoing);
641}
642
643
644
645
646/**
647 * Remove any partition info from @p partition, leaving just the drive name.
648 * @param partition The partition name soon-to-become drive name. (modified)
649 * @return @p partition.
650 */
651char *truncate_to_drive_name(char *partition)
652{
653    int i = strlen(partition) - 1;
654    char *c = NULL;
655
656#ifdef __FreeBSD__
657
658    if (islower(partition[i]))  // BSD subpartition
659        i--;
660    if (partition[i - 1] == 's') {
661        while (isdigit(partition[i]))
662            i--;
663        i--;
664    }
665    partition[i + 1] = '\0';
666
667#else
668
669    assert_string_is_neither_NULL_nor_zerolength(partition);
670    /* first see if it's a devfs style device */
671    c = strrchr(partition, '/');
672    if (c && strncmp(c, "/part", 5) == 0) {
673        /* yup it's devfs, return the "disc" path */
674        strncpy(c + 1, "disc", (size_t)5);
675        return partition;
676    }
677
678    for (i = strlen(partition); isdigit(partition[i - 1]); i--)
679        continue;
680    if (partition[i - 1] == 'p' && isdigit(partition[i - 2])) {
681        i--;
682    }
683    partition[i] = '\0';
684
685#endif
686
687    return partition;
688}
689
690
691/**
692 * Turn a RAID level number (-1 to 5) into a friendly string. The string
693 * is either "Linear RAID" for -1, or " RAID %-2d " (%d = @p raid_level)
694 * for anything else.
695 * @param raid_level The RAID level to stringify.
696 * @return The string form of @p raid_level.
697 * @note The returned value points to static storage that will be overwritten with each call.
698 */
699char *turn_raid_level_number_to_string(int raid_level)
700{
701
702    /*@ buffer ********************************************************** */
703    static char output[MAX_STR_LEN];
704
705
706
707    if (raid_level >= 0) {
708        sprintf(output, " RAID %-2d ", raid_level);
709    } else {
710        sprintf(output, "Linear RAID");
711    }
712    return (output);
713}
714
715
716/**
717 * Determine the severity (1-3, 1 being low) of the fact that
718 * @p fn changed in the live filesystem (verify/compare).
719 * @param fn The filename that changed.
720 * @param out_reason If non-NULL, a descriptive reason for the difference will be copied here.
721 * @return The severity (1-3).
722 */
723int severity_of_difference(char *fn, char *out_reason)
724{
725    int sev = 0;
726    char *reason = NULL;
727    char *filename = NULL;
728
729    // out_reason might be null on purpose, so don't bomb if it is :) OK?
730    assert_string_is_neither_NULL_nor_zerolength(fn);
731    if (!strncmp(fn, MNT_RESTORING, strlen(MNT_RESTORING))) {
732        mr_asprintf(&filename, fn + strlen(MNT_RESTORING));
733    } else if (fn[0] != '/') {
734        mr_asprintf(&filename, "/%s", fn);
735    } else {
736        mr_asprintf(&filename, fn);
737    }
738
739    if (!strncmp(filename, "/var/", 5)) {
740        sev = 2;
741        mr_asprintf(&reason,
742                 _("/var's contents will change regularly, inevitably."));
743    }
744    if (!strncmp(filename, "/home", 5)) {
745        sev = 2;
746        mr_asprintf(&reason,
747                 _("It's in your /home directory. Therefore, it is important."));
748    }
749    if (!strncmp(filename, "/usr/", 5)) {
750        sev = 3;
751        mr_asprintf(&reason,
752                 _("You may have installed/removed software during the backup."));
753    }
754    if (!strncmp(filename, "/etc/", 5)) {
755        sev = 3;
756        mr_asprintf(&reason,
757                 _("Do not edit config files while backing up your PC."));
758    }
759    if (!strcmp(filename, "/etc/adjtime")
760        || !strcmp(filename, "/etc/mtab")) {
761        sev = 1;
762        mr_asprintf(&reason, _("This file changes all the time. It's OK."));
763    }
764    if (!strncmp(filename, "/root/", 6)) {
765        sev = 3;
766        mr_asprintf(&reason,
767                 _("Were you compiling/editing something in /root?"));
768    }
769    if (!strncmp(filename, "/root/.", 7)) {
770        sev = 2;
771        mr_asprintf(&reason, _("Temp or 'dot' files changed in /root."));
772    }
773    if (!strncmp(filename, "/var/lib/", 9)) {
774        sev = 2;
775        mr_asprintf(&reason, _("Did you add/remove software during backing?"));
776    }
777    if (!strncmp(filename, "/var/lib/rpm", 12)) {
778        sev = 3;
779        mr_asprintf(&reason, _("Did you add/remove software during backing?"));
780    }
781    if (!strncmp(filename, "/var/lib/slocate", 16)) {
782        sev = 1;
783        mr_asprintf(&reason,
784                 _("The 'update' daemon ran during backup. This does not affect the integrity of your backup."));
785    }
786    if (!strncmp(filename, "/var/log/", 9)
787        || strstr(filename, "/.xsession")
788        || !strcmp(filename + strlen(filename) - 4, ".log")) {
789        sev = 1;
790        mr_asprintf(&reason,
791                 _("Log files change frequently as the computer runs. Fret not."));
792    }
793    if (!strncmp(filename, "/var/spool", 10)) {
794        sev = 1;
795        mr_asprintf(&reason,
796                 _("Background processes or printers were active. This does not affect the integrity of your backup."));
797    }
798    if (!strncmp(filename, "/var/spool/mail", 10)) {
799        sev = 2;
800        mr_asprintf(&reason, _("Mail was sent/received during backup."));
801    }
802    if (filename[strlen(filename) - 1] == '~') {
803        sev = 1;
804        mr_asprintf(&reason,
805                 _("Backup copy of another file which was modified recently."));
806    }
807    if (strstr(filename, "cache")) {
808        sev = 1;
809        mr_asprintf(&reason,
810                 _("Part of a cache of data. Caches change from time to time. Don't worry."));
811    }
812    if (!strncmp(filename, "/var/run/", 9)
813        || !strncmp(filename, "/var/lock", 8)
814        || strstr(filename, "/.DCOPserver") || strstr(filename, "/.MCOP")
815        || strstr(filename, "/.Xauthority")) {
816        sev = 1;
817        mr_asprintf(&reason,
818                _("Temporary file (a lockfile, perhaps) used by software such as X or KDE to register its presence."));
819    }
820    mr_free(filename);
821
822    if (sev == 0) {
823        sev = 3;
824        mr_asprintf(&reason,
825                 _("Changed since backup. Consider running a differential backup in a day or two."));
826    }
827    if (out_reason) {
828        strcpy(out_reason, reason);
829    }
830
831    mr_free(reason);
832    return (sev);
833}
834
835
836/**
837 * Compare the filenames in two filelist entries (s_filelist_entry*) casted
838 * to void*.
839 * @param va The first filelist entry, cast as a @c void pointer.
840 * @param vb The second filelist entry, cast as a @c void pointer.
841 * @return The return value of strcmp().
842 */
843int compare_two_filelist_entries(void *va, void *vb)
844{
845    static int res;
846    struct s_filelist_entry *fa, *fb;
847
848    assert(va != NULL);
849    assert(vb != NULL);
850    fa = (struct s_filelist_entry *) va;
851    fb = (struct s_filelist_entry *) vb;
852    res = strcmp(fa->filename, fb->filename);
853    return (res);
854}
855
856
857/**
858 * Generate a line intended to be passed to update_evalcall_form(), indicating
859 * the current media fill percentage (or number of kilobytes if size is not known).
860 * @param bkpinfo The backup media structure. Fields used:
861 * - @c bkpinfo->backup_media_type
862 * - @c bkpinfo->media_size
863 * - @c bkpinfo->scratchdir
864 * @return The string indicating media fill.
865 * @note The returned string points to static storage that will be overwritten with each call.
866 */
867char *percent_media_full_comment(struct s_bkpinfo *bkpinfo)
868{
869    /*@ int *********************************************** */
870    int percentage = 0;
871    int j = 0;
872
873    /*@ buffers ******************************************* */
874    static char outstr[MAX_STR_LEN];
875
876    assert(bkpinfo != NULL);
877
878    if (bkpinfo->media_size <= 0L) {
879        sprintf(outstr, _("Volume %d: %'lld kilobytes archived so far"),
880                g_current_media_number, g_tape_posK);
881        return (outstr);
882    }
883
884    /* update screen */
885    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
886        percentage =
887            (int) (g_tape_posK / 10 /
888                   bkpinfo->media_size);
889        if (percentage > 100) {
890            percentage = 100;
891        }
892        sprintf(outstr, _("Volume %d: ["), g_current_media_number);
893    } else {
894        percentage =
895            (int) (space_occupied_by_cd(bkpinfo->scratchdir) * 100 / 1024 /
896                   bkpinfo->media_size);
897        sprintf(outstr, "%s %d: [",
898                bkpinfo->backup_media_string,
899                g_current_media_number);
900    }
901    for (j = 0; j < percentage; j += 5) {
902        strcat(outstr, "*");
903    }
904    for (; j < 100; j += 5) {
905        strcat(outstr, ".");
906    }
907    j = (int) strlen(outstr);
908    sprintf(outstr + j, "] %d%% used", percentage);
909    return (outstr);
910}
911
912
913
914/**
915 * Get a string form of @p type_of_bkp.
916 * @param type_of_bkp The backup type to stringify.
917 * @return The stringification of @p type_of_bkp.
918 * @note The returned string points to static storage that will be overwritten with each call.
919 */
920char *media_descriptor_string(t_bkptype type_of_bkp)
921{
922       static char *type_of_backup = NULL;
923
924       if (!type_of_backup) {
925               malloc_string(type_of_backup);
926       }
927
928       switch (type_of_bkp) {
929       case dvd:
930               strcpy(type_of_backup, "DVD");
931               break;
932       case cdr:
933               strcpy(type_of_backup, "CDR");
934               break;
935       case cdrw:
936               strcpy(type_of_backup, "CDRW");
937               break;
938       case tape:
939               strcpy(type_of_backup, "tape");
940               break;
941       case cdstream:
942               strcpy(type_of_backup, "CDR");
943               break;
944       case udev:
945               strcpy(type_of_backup, "udev");
946               break;
947       case iso:
948               strcpy(type_of_backup, "ISO");
949               break;
950       case nfs:
951               strcpy(type_of_backup, "nfs");
952               break;
953       case usb:
954               strcpy(type_of_backup, "USB");
955               break;
956       default:
957               strcpy(type_of_backup, "ISO");
958       }
959       return (type_of_backup);
960}
961
Note: See TracBrowser for help on using the repository browser.