You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
7.3 KiB

  1. #if !defined(TOKUDB_COMMON_FUNCS_H)
  2. #define TOKUDB_COMMON_FUNCS_H
  3. /* -*- mode: C; c-basic-offset: 4 -*- */
  4. #ident "Copyright (c) 2007 Tokutek Inc. All rights reserved."
  5. #include "tokudb_common.h"
  6. //DB_ENV->err disabled since it does not use db_strerror
  7. #define ERROR(retval, ...) \
  8. if (0) g.dbenv->err(g.dbenv, retval, __VA_ARGS__); \
  9. else { \
  10. fprintf(stderr, "%s: %s:", g.progname, db_strerror(retval)); \
  11. fprintf(stderr, __VA_ARGS__); \
  12. fprintf(stderr, "\n"); \
  13. }
  14. //DB_ENV->err disabled since it does not use db_strerror, errx does not exist.
  15. #define ERRORX(...) \
  16. if (0) g.dbenv->err(g.dbenv, 0, __VA_ARGS__); \
  17. else { \
  18. fprintf(stderr, "%s: ", g.progname); \
  19. fprintf(stderr, __VA_ARGS__); \
  20. fprintf(stderr, "\n"); \
  21. }
  22. int strtoint32 (char* str, int32_t* num, int32_t min, int32_t max, int base);
  23. int strtouint32 (char* str, u_int32_t* num, u_int32_t min, u_int32_t max, int base);
  24. int strtoint64 (char* str, int64_t* num, int64_t min, int64_t max, int base);
  25. int strtouint64 (char* str, u_int64_t* num, u_int64_t min, u_int64_t max, int base);
  26. /*
  27. * Convert a string to an integer of type "type".
  28. *
  29. *
  30. * Sets errno and returns:
  31. * EINVAL: str == NULL, num == NULL, or string not of the form [ \t]*[+-]?[0-9]+
  32. * ERANGE: value out of range specified. (Range of [min, max])
  33. *
  34. * *num is unchanged on error.
  35. * Returns:
  36. *
  37. */
  38. #define DEF_STR_TO(name, type, bigtype, strtofunc, frmt) \
  39. int name(char* str, type* num, type min, type max, int base) \
  40. { \
  41. char* test; \
  42. bigtype value; \
  43. \
  44. assert(str); \
  45. assert(num); \
  46. assert(min <= max); \
  47. assert(g.dbenv || g.progname); \
  48. assert(base == 0 || (base >= 2 && base <= 36)); \
  49. \
  50. errno = 0; \
  51. while (isspace(*str)) str++; \
  52. value = strtofunc(str, &test, base); \
  53. if ((*test != '\0' && *test != '\n') || test == str) { \
  54. ERRORX("%s: Invalid numeric argument\n", str); \
  55. errno = EINVAL; \
  56. goto error; \
  57. } \
  58. if (errno != 0) { \
  59. ERROR(errno, "%s\n", str); \
  60. } \
  61. if (value < min) { \
  62. ERRORX("%s: Less than minimum value (%" frmt ")\n", str, min); \
  63. goto error; \
  64. } \
  65. if (value > max) { \
  66. ERRORX("%s: Greater than maximum value (%" frmt ")\n", str, max); \
  67. goto error; \
  68. } \
  69. *num = value; \
  70. return EXIT_SUCCESS; \
  71. error: \
  72. return errno; \
  73. }
  74. DEF_STR_TO(strtoint32, int32_t, int64_t, strtoll, PRId32);
  75. DEF_STR_TO(strtouint32, u_int32_t, u_int64_t, strtoull, PRIu32);
  76. DEF_STR_TO(strtoint64, int64_t, int64_t, strtoll, PRId64);
  77. DEF_STR_TO(strtouint64, u_int64_t, u_int64_t, strtoull, PRIu64);
  78. void outputbyte(u_int8_t ch)
  79. {
  80. if (g.plaintext) {
  81. if (ch == '\\') printf("\\\\");
  82. else if (isprint(ch)) printf("%c", ch);
  83. else printf("\\%02x", ch);
  84. }
  85. else printf("%02x", ch);
  86. }
  87. void outputstring(char* str)
  88. {
  89. char* p;
  90. for (p = str; *p != '\0'; p++) {
  91. outputbyte((u_int8_t)*p);
  92. }
  93. }
  94. void outputplaintextstring(char* str)
  95. {
  96. bool old_plaintext = g.plaintext;
  97. g.plaintext = true;
  98. outputstring(str);
  99. g.plaintext = old_plaintext;
  100. }
  101. int hextoint(int ch)
  102. {
  103. if (ch >= '0' && ch <= '9') {
  104. return ch - '0';
  105. }
  106. if (ch >= 'a' && ch <= 'z') {
  107. return ch - 'a' + 10;
  108. }
  109. if (ch >= 'A' && ch <= 'Z') {
  110. return ch - 'A' + 10;
  111. }
  112. return EOF;
  113. }
  114. int printabletocstring(char* inputstr, char** poutputstr)
  115. {
  116. char highch;
  117. char lowch;
  118. char nextch;
  119. char* cstring;
  120. assert(inputstr);
  121. assert(poutputstr);
  122. assert(*poutputstr == NULL);
  123. cstring = (char*)malloc((strlen(inputstr) + 1) * sizeof(char));
  124. if (cstring == NULL) {
  125. ERROR(errno, "printabletocstring");
  126. goto error;
  127. }
  128. for (*poutputstr = cstring; *inputstr != '\0'; inputstr++) {
  129. if (*inputstr == '\\') {
  130. if ((highch = *++inputstr) == '\\') {
  131. *cstring++ = '\\';
  132. continue;
  133. }
  134. if (highch == '\0' || (lowch = *++inputstr) == '\0') {
  135. ERROR(0, "unexpected end of input data or key/data pair");
  136. goto error;
  137. }
  138. if (!isxdigit(highch)) {
  139. ERROR(0, "Unexpected '%c' (non-hex) input.\n", highch);
  140. goto error;
  141. }
  142. if (!isxdigit(lowch)) {
  143. ERROR(0, "Unexpected '%c' (non-hex) input.\n", lowch);
  144. goto error;
  145. }
  146. nextch = (hextoint(highch) << 4) | hextoint(lowch);
  147. if (nextch == '\0') {
  148. /* Database names are c strings, and cannot have extra NULL terminators. */
  149. ERROR(0, "Unexpected '\\00' in input.\n");
  150. goto error;
  151. }
  152. *cstring++ = nextch;
  153. }
  154. else *cstring++ = *inputstr;
  155. }
  156. /* Terminate the string. */
  157. *cstring = '\0';
  158. return EXIT_SUCCESS;
  159. error:
  160. ERROR(0, "Quitting out due to errors.\n");
  161. return EXIT_FAILURE;
  162. }
  163. int verify_library_version()
  164. {
  165. int major;
  166. int minor;
  167. db_version(&major, &minor, NULL);
  168. if (major != DB_VERSION_MAJOR || minor != DB_VERSION_MINOR) {
  169. ERRORX("version %d.%d doesn't match library version %d.%d\n",
  170. DB_VERSION_MAJOR, DB_VERSION_MINOR, major, minor);
  171. return EXIT_FAILURE;
  172. }
  173. return EXIT_SUCCESS;
  174. }
  175. static int last_caught = 0;
  176. static void catch_signal(int signal) {
  177. last_caught = signal;
  178. if (last_caught == 0) last_caught = SIGINT;
  179. }
  180. void init_catch_signals(void) {
  181. signal(SIGHUP, catch_signal);
  182. signal(SIGINT, catch_signal);
  183. signal(SIGPIPE, catch_signal);
  184. signal(SIGTERM, catch_signal);
  185. }
  186. int caught_any_signals(void) {
  187. return last_caught != 0;
  188. }
  189. void resend_signals(void) {
  190. if (last_caught) {
  191. signal(last_caught, SIG_DFL);
  192. raise(last_caught);
  193. }
  194. }
  195. #endif /* #if !defined(TOKUDB_COMMON_H) */