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

Last change on this file since 1195 was 1195, checked in by Bruno Cornec, 13 years ago

Removed 2 asserts which were generating invalid errors (chains were not empty or null so the function is probably wrong !!)

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