support for ubifs overlay
[project/fstools.git] / libubi / ubiutils-common.c
1 /*
2  * Copyright (C) 2007, 2008 Nokia Corporation
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12  * the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 /*
20  * This file contains various common stuff used by UBI utilities.
21  *
22  * Authors: Artem Bityutskiy
23  *          Adrian Hunter
24  */
25
26 #define PROGRAM_NAME "ubiutils"
27
28 #include <sys/time.h>
29 #include <sys/types.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include "libubi.h"
36
37 /**
38  * get_multiplier - convert size specifier to an integer multiplier.
39  * @str: the size specifier string
40  *
41  * This function parses the @str size specifier, which may be one of
42  * 'KiB', 'MiB', or 'GiB' into an integer multiplier. Returns positive
43  * size multiplier in case of success and %-1 in case of failure.
44  */
45 static int get_multiplier(const char *str)
46 {
47         if (!str)
48                 return 1;
49
50         /* Remove spaces before the specifier */
51         while (*str == ' ' || *str == '\t')
52                 str += 1;
53
54         if (!strcmp(str, "KiB"))
55                 return 1024;
56         if (!strcmp(str, "MiB"))
57                 return 1024 * 1024;
58         if (!strcmp(str, "GiB"))
59                 return 1024 * 1024 * 1024;
60
61         return -1;
62 }
63
64 /**
65  * ubiutils_get_bytes - convert a string containing amount of bytes into an
66  * integer
67  * @str: string to convert
68  *
69  * This function parses @str which may have one of 'KiB', 'MiB', or 'GiB'
70  * size specifiers. Returns positive amount of bytes in case of success and %-1
71  * in case of failure.
72  */
73 long long ubiutils_get_bytes(const char *str)
74 {
75         char *endp;
76         long long bytes = strtoull(str, &endp, 0);
77
78         if (endp == str || bytes < 0) {
79                 fprintf(stderr, "incorrect amount of bytes: \"%s\"\n", str);
80                 return -1;
81         }
82
83         if (*endp != '\0') {
84                 int mult = get_multiplier(endp);
85
86                 if (mult == -1) {
87                         fprintf(stderr, "bad size specifier: \"%s\" - "
88                                 "should be 'KiB', 'MiB' or 'GiB'\n", endp);
89                         return -1;
90                 }
91                 bytes *= mult;
92         }
93
94         return bytes;
95 }
96
97 /**
98  * ubiutils_print_bytes - print bytes.
99  * @bytes: variable to print
100  * @bracket: whether brackets have to be put or not
101  *
102  * This is a helper function which prints amount of bytes in a human-readable
103  * form, i.e., it prints the exact amount of bytes following by the approximate
104  * amount of Kilobytes, Megabytes, or Gigabytes, depending on how big @bytes
105  * is.
106  */
107 void ubiutils_print_bytes(long long bytes, int bracket)
108 {
109         const char *p;
110
111         if (bracket)
112                 p = " (";
113         else
114                 p = ", ";
115
116         printf("%lld bytes", bytes);
117
118         if (bytes > 1024 * 1024 * 1024)
119                 printf("%s%.1f GiB", p, (double)bytes / (1024 * 1024 * 1024));
120         else if (bytes > 1024 * 1024)
121                 printf("%s%.1f MiB", p, (double)bytes / (1024 * 1024));
122         else if (bytes > 1024 && bytes != 0)
123                 printf("%s%.1f KiB", p, (double)bytes / 1024);
124         else
125                 return;
126
127         if (bracket)
128                 printf(")");
129 }
130
131 /**
132  * ubiutils_print_text - print text and fold it.
133  * @stream: file stream to print to
134  * @text: text to print
135  * @width: maximum allowed text width
136  *
137  * Print text and fold it so that each line would not have more then @width
138  * characters.
139  */
140 void ubiutils_print_text(FILE *stream, const char *text, int width)
141 {
142         int pos, bpos = 0;
143         const char *p;
144         char line[1024];
145
146         if (width > 1023) {
147                 fprintf(stream, "%s\n", text);
148                 return;
149         }
150         p = text;
151         pos = 0;
152         while (p[pos]) {
153                 while (!isspace(p[pos])) {
154                         line[pos] = p[pos];
155                         if (!p[pos])
156                                 break;
157                         ++pos;
158                         if (pos == width) {
159                                 line[pos] = '\0';
160                                 fprintf(stream, "%s\n", line);
161                                 p += pos;
162                                 pos = 0;
163                         }
164                 }
165                 while (pos < width) {
166                         line[pos] = p[pos];
167                         if (!p[pos]) {
168                                 bpos = pos;
169                                 break;
170                         }
171                         if (isspace(p[pos]))
172                                 bpos = pos;
173                         ++pos;
174                 }
175                 line[bpos] = '\0';
176                 fprintf(stream, "%s\n", line);
177                 p += bpos;
178                 pos = 0;
179                 while (p[pos] && isspace(p[pos]))
180                         ++p;
181         }
182 }
183
184 /**
185  * ubiutils_srand - randomly seed the standard pseudo-random generator.
186  *
187  * This helper function seeds the standard libc pseudo-random generator with a
188  * more or less random value to make sure the 'rand()' call does not return the
189  * same sequence every time UBI utilities run. Returns zero in case of success
190  * and a %-1 in case of error.
191  */
192 int ubiutils_srand(void)
193 {
194         struct timeval tv;
195         struct timezone tz;
196         unsigned int seed;
197
198         /*
199          * Just assume that a combination of the PID + current time is a
200          * reasonably random number.
201          */
202         if (gettimeofday(&tv, &tz))
203                 return -1;
204
205         seed = (unsigned int)tv.tv_sec;
206         seed += (unsigned int)tv.tv_usec;
207         seed *= getpid();
208         seed %= RAND_MAX;
209         srand(seed);
210         return 0;
211 }