source: MondoRescue/branches/stable/mondo/mondo/common/libmondo-string.c@ 541

Last change on this file since 541 was 541, checked in by bcornec, 18 years ago

Stable is reverted to r436 (2.0.7) to put it in line with 2.0.8 and start from there over

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