ubiutils-common.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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. * This file contains various common stuff used by UBI utilities.
  20. *
  21. * Authors: Artem Bityutskiy
  22. * Adrian Hunter
  23. */
  24. #define PROGRAM_NAME "ubiutils"
  25. #include <sys/time.h>
  26. #include <sys/types.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <ctype.h>
  30. #include <stdlib.h>
  31. #include <unistd.h>
  32. #include "libubi.h"
  33. /**
  34. * get_multiplier - convert size specifier to an integer multiplier.
  35. * @str: the size specifier string
  36. *
  37. * This function parses the @str size specifier, which may be one of
  38. * 'KiB', 'MiB', or 'GiB' into an integer multiplier. Returns positive
  39. * size multiplier in case of success and %-1 in case of failure.
  40. */
  41. static int get_multiplier(const char *str)
  42. {
  43. if (!str)
  44. return 1;
  45. /* Remove spaces before the specifier */
  46. while (*str == ' ' || *str == '\t')
  47. str += 1;
  48. if (!strcmp(str, "KiB"))
  49. return 1024;
  50. if (!strcmp(str, "MiB"))
  51. return 1024 * 1024;
  52. if (!strcmp(str, "GiB"))
  53. return 1024 * 1024 * 1024;
  54. return -1;
  55. }
  56. /**
  57. * ubiutils_get_bytes - convert a string containing amount of bytes into an
  58. * integer
  59. * @str: string to convert
  60. *
  61. * This function parses @str which may have one of 'KiB', 'MiB', or 'GiB'
  62. * size specifiers. Returns positive amount of bytes in case of success and %-1
  63. * in case of failure.
  64. */
  65. long long ubiutils_get_bytes(const char *str)
  66. {
  67. char *endp;
  68. long long bytes = strtoull(str, &endp, 0);
  69. if (endp == str || bytes < 0) {
  70. fprintf(stderr, "incorrect amount of bytes: \"%s\"\n", str);
  71. return -1;
  72. }
  73. if (*endp != '\0') {
  74. int mult = get_multiplier(endp);
  75. if (mult == -1) {
  76. fprintf(stderr, "bad size specifier: \"%s\" - "
  77. "should be 'KiB', 'MiB' or 'GiB'\n", endp);
  78. return -1;
  79. }
  80. bytes *= mult;
  81. }
  82. return bytes;
  83. }
  84. /**
  85. * ubiutils_print_bytes - print bytes.
  86. * @bytes: variable to print
  87. * @bracket: whether brackets have to be put or not
  88. *
  89. * This is a helper function which prints amount of bytes in a human-readable
  90. * form, i.e., it prints the exact amount of bytes following by the approximate
  91. * amount of Kilobytes, Megabytes, or Gigabytes, depending on how big @bytes
  92. * is.
  93. */
  94. void ubiutils_print_bytes(long long bytes, int bracket)
  95. {
  96. const char *p;
  97. if (bracket)
  98. p = " (";
  99. else
  100. p = ", ";
  101. printf("%lld bytes", bytes);
  102. if (bytes > 1024 * 1024 * 1024)
  103. printf("%s%.1f GiB", p, (double)bytes / (1024 * 1024 * 1024));
  104. else if (bytes > 1024 * 1024)
  105. printf("%s%.1f MiB", p, (double)bytes / (1024 * 1024));
  106. else if (bytes > 1024 && bytes != 0)
  107. printf("%s%.1f KiB", p, (double)bytes / 1024);
  108. else
  109. return;
  110. if (bracket)
  111. printf(")");
  112. }
  113. /**
  114. * ubiutils_print_text - print text and fold it.
  115. * @stream: file stream to print to
  116. * @text: text to print
  117. * @width: maximum allowed text width
  118. *
  119. * Print text and fold it so that each line would not have more then @width
  120. * characters.
  121. */
  122. void ubiutils_print_text(FILE *stream, const char *text, int width)
  123. {
  124. int pos, bpos = 0;
  125. const char *p;
  126. char line[1024];
  127. if (width > 1023) {
  128. fprintf(stream, "%s\n", text);
  129. return;
  130. }
  131. p = text;
  132. pos = 0;
  133. while (p[pos]) {
  134. while (!isspace(p[pos])) {
  135. line[pos] = p[pos];
  136. if (!p[pos])
  137. break;
  138. ++pos;
  139. if (pos == width) {
  140. line[pos] = '\0';
  141. fprintf(stream, "%s\n", line);
  142. p += pos;
  143. pos = 0;
  144. }
  145. }
  146. while (pos < width) {
  147. line[pos] = p[pos];
  148. if (!p[pos]) {
  149. bpos = pos;
  150. break;
  151. }
  152. if (isspace(p[pos]))
  153. bpos = pos;
  154. ++pos;
  155. }
  156. line[bpos] = '\0';
  157. fprintf(stream, "%s\n", line);
  158. p += bpos;
  159. pos = 0;
  160. while (p[pos] && isspace(p[pos]))
  161. ++p;
  162. }
  163. }
  164. /**
  165. * ubiutils_srand - randomly seed the standard pseudo-random generator.
  166. *
  167. * This helper function seeds the standard libc pseudo-random generator with a
  168. * more or less random value to make sure the 'rand()' call does not return the
  169. * same sequence every time UBI utilities run. Returns zero in case of success
  170. * and a %-1 in case of error.
  171. */
  172. int ubiutils_srand(void)
  173. {
  174. struct timeval tv;
  175. struct timezone tz;
  176. unsigned int seed;
  177. /*
  178. * Just assume that a combination of the PID + current time is a
  179. * reasonably random number.
  180. */
  181. if (gettimeofday(&tv, &tz))
  182. return -1;
  183. seed = (unsigned int)tv.tv_sec;
  184. seed += (unsigned int)tv.tv_usec;
  185. seed *= getpid();
  186. seed %= RAND_MAX;
  187. srand(seed);
  188. return 0;
  189. }