source: MondoRescue/branches/2.2.2/mondo/src/common/libmondo-string.c@ 1229

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

Fixed display problem in newt mode where old strings weren't fully
overwritten which led to garbled display by improving function
center_string(). (This is also the fix for Debian bug #320152.)

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