PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/epan/to_str.c

https://github.com/labx-technologies-llc/wireshark
C | 1190 lines | 871 code | 165 blank | 154 comment | 140 complexity | 5caf21e6c4bb8765eae6bcc290a337ca MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /* to_str.c
  2. * Routines for utilities to convert various other types to strings.
  3. *
  4. * $Id$
  5. *
  6. * Wireshark - Network traffic analyzer
  7. * By Gerald Combs <gerald@wireshark.org>
  8. * Copyright 1998 Gerald Combs
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version 2
  13. * of the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  23. */
  24. #include "config.h"
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <time.h>
  28. #include <glib.h>
  29. #include "emem.h"
  30. #include "proto.h"
  31. #include "to_str.h"
  32. #include "strutil.h"
  33. /*
  34. * If a user _does_ pass in a too-small buffer, this is probably
  35. * going to be too long to fit. However, even a partial string
  36. * starting with "[Buf" should provide enough of a clue to be
  37. * useful.
  38. */
  39. #define BUF_TOO_SMALL_ERR "[Buffer too small]"
  40. static inline char
  41. low_nibble_of_octet_to_hex(guint8 oct)
  42. {
  43. /* At least one version of Apple's C compiler/linker is buggy, causing
  44. a complaint from the linker about the "literal C string section"
  45. not ending with '\0' if we initialize a 16-element "char" array with
  46. a 16-character string, the fact that initializing such an array with
  47. such a string is perfectly legitimate ANSI C nonwithstanding, the 17th
  48. '\0' byte in the string nonwithstanding. */
  49. static const gchar hex_digits[16] =
  50. { '0', '1', '2', '3', '4', '5', '6', '7',
  51. '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
  52. return hex_digits[oct & 0xF];
  53. }
  54. static inline char *
  55. byte_to_hex(char *out, guint32 dword) {
  56. *out++ = low_nibble_of_octet_to_hex(dword >> 4);
  57. *out++ = low_nibble_of_octet_to_hex(dword);
  58. return out;
  59. }
  60. char *
  61. word_to_hex(char *out, guint16 word) {
  62. out = byte_to_hex(out, word >> 8);
  63. out = byte_to_hex(out, word);
  64. return out;
  65. }
  66. char *
  67. word_to_hex_npad(char *out, guint16 word) {
  68. if (word >= 0x1000)
  69. *out++ = low_nibble_of_octet_to_hex((guint8)(word >> 12));
  70. if (word >= 0x0100)
  71. *out++ = low_nibble_of_octet_to_hex((guint8)(word >> 8));
  72. if (word >= 0x0010)
  73. *out++ = low_nibble_of_octet_to_hex((guint8)(word >> 4));
  74. *out++ = low_nibble_of_octet_to_hex((guint8)(word >> 0));
  75. return out;
  76. }
  77. char *
  78. dword_to_hex(char *out, guint32 dword) {
  79. out = byte_to_hex(out, dword >> 24);
  80. out = byte_to_hex(out, dword >> 16);
  81. out = byte_to_hex(out, dword >> 8);
  82. out = byte_to_hex(out, dword);
  83. return out;
  84. }
  85. char *
  86. dword_to_hex_punct(char *out, guint32 dword, char punct) {
  87. out = byte_to_hex(out, dword >> 24);
  88. *out++ = punct;
  89. out = byte_to_hex(out, dword >> 16);
  90. *out++ = punct;
  91. out = byte_to_hex(out, dword >> 8);
  92. *out++ = punct;
  93. out = byte_to_hex(out, dword);
  94. return out;
  95. }
  96. /*
  97. * This does *not* null-terminate the string. It returns a pointer
  98. * to the position in the string following the last character it
  99. * puts there, so that the caller can either put the null terminator
  100. * in or can append more stuff to the buffer.
  101. *
  102. * There needs to be at least len * 2 bytes left in the buffer.
  103. */
  104. char *
  105. bytes_to_hexstr(char *out, const guint8 *ad, guint32 len) {
  106. guint32 i;
  107. if (!ad)
  108. REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_hexstr()");
  109. for (i = 0; i < len; i++)
  110. out = byte_to_hex(out, ad[i]);
  111. return out;
  112. }
  113. /*
  114. * This does *not* null-terminate the string. It returns a pointer
  115. * to the position in the string following the last character it
  116. * puts there, so that the caller can either put the null terminator
  117. * in or can append more stuff to the buffer.
  118. *
  119. * There needs to be at least len * 3 - 1 bytes left in the buffer.
  120. */
  121. char *
  122. bytes_to_hexstr_punct(char *out, const guint8 *ad, guint32 len, char punct) {
  123. guint32 i;
  124. if (!ad)
  125. REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_hexstr_punct()");
  126. out = byte_to_hex(out, ad[0]);
  127. for (i = 1; i < len; i++) {
  128. *out++ = punct;
  129. out = byte_to_hex(out, ad[i]);
  130. }
  131. return out;
  132. }
  133. /* Routine to convert a sequence of bytes to a hex string, one byte/two hex
  134. * digits at at a time, with a specified punctuation character between
  135. * the bytes.
  136. *
  137. * If punct is '\0', no punctuation is applied (and thus
  138. * the resulting string is (len-1) bytes shorter)
  139. */
  140. const gchar *
  141. bytestring_to_str(const guint8 *ad, const guint32 len, const char punct) {
  142. gchar *buf;
  143. size_t buflen;
  144. if (!ad)
  145. REPORT_DISSECTOR_BUG("Null pointer passed to bytestring_to_str()");
  146. /* XXX, Old code was using int as iterator... Why len is guint32 anyway?! (darkjames) */
  147. if ( ((int) len) < 0)
  148. return "";
  149. if (!len)
  150. return "";
  151. if (punct)
  152. buflen=len*3;
  153. else
  154. buflen=len*2 + 1;
  155. buf=(gchar *)ep_alloc(buflen);
  156. if (punct)
  157. bytes_to_hexstr_punct(buf, ad, len, punct);
  158. else
  159. bytes_to_hexstr(buf, ad, len);
  160. buf[buflen-1] = '\0';
  161. return buf;
  162. }
  163. /* Max string length for displaying byte string. */
  164. #define MAX_BYTE_STR_LEN 48
  165. gchar *
  166. bytes_to_str(const guint8 *bd, int bd_len) {
  167. gchar *cur;
  168. gchar *cur_ptr;
  169. int truncated = 0;
  170. if (!bd)
  171. REPORT_DISSECTOR_BUG("Null pointer passed to bytes_to_str()");
  172. cur=(gchar *)ep_alloc(MAX_BYTE_STR_LEN+3+1);
  173. if (bd_len <= 0) { cur[0] = '\0'; return cur; }
  174. if (bd_len > MAX_BYTE_STR_LEN/2) { /* bd_len > 24 */
  175. truncated = 1;
  176. bd_len = MAX_BYTE_STR_LEN/2;
  177. }
  178. cur_ptr = bytes_to_hexstr(cur, bd, bd_len); /* max MAX_BYTE_STR_LEN bytes */
  179. if (truncated)
  180. cur_ptr = g_stpcpy(cur_ptr, "..."); /* 3 bytes */
  181. *cur_ptr = '\0'; /* 1 byte */
  182. return cur;
  183. }
  184. /* Turn an array of bytes into a string showing the bytes in hex with
  185. * punct as a bytes separator.
  186. */
  187. gchar *
  188. bytes_to_str_punct(const guint8 *bd, int bd_len, gchar punct) {
  189. gchar *cur;
  190. gchar *cur_ptr;
  191. int truncated = 0;
  192. if (!punct)
  193. return bytes_to_str(bd, bd_len);
  194. cur=(gchar *)ep_alloc(MAX_BYTE_STR_LEN+3+1);
  195. if (bd_len <= 0) { cur[0] = '\0'; return cur; }
  196. if (bd_len > MAX_BYTE_STR_LEN/3) { /* bd_len > 16 */
  197. truncated = 1;
  198. bd_len = MAX_BYTE_STR_LEN/3;
  199. }
  200. cur_ptr = bytes_to_hexstr_punct(cur, bd, bd_len, punct); /* max MAX_BYTE_STR_LEN-1 bytes */
  201. if (truncated) {
  202. *cur_ptr++ = punct; /* 1 byte */
  203. cur_ptr = g_stpcpy(cur_ptr, "..."); /* 3 bytes */
  204. }
  205. *cur_ptr = '\0';
  206. return cur;
  207. }
  208. static int
  209. guint32_to_str_buf_len(const guint32 u) {
  210. if (u >= 1000000000)return 10;
  211. if (u >= 100000000) return 9;
  212. if (u >= 10000000) return 8;
  213. if (u >= 1000000) return 7;
  214. if (u >= 100000) return 6;
  215. if (u >= 10000) return 5;
  216. if (u >= 1000) return 4;
  217. if (u >= 100) return 3;
  218. if (u >= 10) return 2;
  219. return 1;
  220. }
  221. static const char fast_strings[][4] = {
  222. "0", "1", "2", "3", "4", "5", "6", "7",
  223. "8", "9", "10", "11", "12", "13", "14", "15",
  224. "16", "17", "18", "19", "20", "21", "22", "23",
  225. "24", "25", "26", "27", "28", "29", "30", "31",
  226. "32", "33", "34", "35", "36", "37", "38", "39",
  227. "40", "41", "42", "43", "44", "45", "46", "47",
  228. "48", "49", "50", "51", "52", "53", "54", "55",
  229. "56", "57", "58", "59", "60", "61", "62", "63",
  230. "64", "65", "66", "67", "68", "69", "70", "71",
  231. "72", "73", "74", "75", "76", "77", "78", "79",
  232. "80", "81", "82", "83", "84", "85", "86", "87",
  233. "88", "89", "90", "91", "92", "93", "94", "95",
  234. "96", "97", "98", "99", "100", "101", "102", "103",
  235. "104", "105", "106", "107", "108", "109", "110", "111",
  236. "112", "113", "114", "115", "116", "117", "118", "119",
  237. "120", "121", "122", "123", "124", "125", "126", "127",
  238. "128", "129", "130", "131", "132", "133", "134", "135",
  239. "136", "137", "138", "139", "140", "141", "142", "143",
  240. "144", "145", "146", "147", "148", "149", "150", "151",
  241. "152", "153", "154", "155", "156", "157", "158", "159",
  242. "160", "161", "162", "163", "164", "165", "166", "167",
  243. "168", "169", "170", "171", "172", "173", "174", "175",
  244. "176", "177", "178", "179", "180", "181", "182", "183",
  245. "184", "185", "186", "187", "188", "189", "190", "191",
  246. "192", "193", "194", "195", "196", "197", "198", "199",
  247. "200", "201", "202", "203", "204", "205", "206", "207",
  248. "208", "209", "210", "211", "212", "213", "214", "215",
  249. "216", "217", "218", "219", "220", "221", "222", "223",
  250. "224", "225", "226", "227", "228", "229", "230", "231",
  251. "232", "233", "234", "235", "236", "237", "238", "239",
  252. "240", "241", "242", "243", "244", "245", "246", "247",
  253. "248", "249", "250", "251", "252", "253", "254", "255"
  254. };
  255. char *uint_to_str_back(char *ptr, guint32 value);
  256. void
  257. guint32_to_str_buf(guint32 u, gchar *buf, int buf_len) {
  258. int str_len = guint32_to_str_buf_len(u)+1;
  259. gchar *bp = &buf[str_len];
  260. if (buf_len < str_len) {
  261. g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
  262. return;
  263. }
  264. *--bp = '\0';
  265. uint_to_str_back(bp, u);
  266. }
  267. gchar *
  268. guint32_to_str(const guint32 u) {
  269. int str_len = 16; /* guint32_to_str_buf_len(u)+1; */
  270. gchar *bp = (gchar *)ep_alloc(str_len);
  271. guint32_to_str_buf(u, bp, str_len);
  272. return bp;
  273. }
  274. #define PLURALIZE(n) (((n) > 1) ? "s" : "")
  275. #define COMMA(do_it) ((do_it) ? ", " : "")
  276. /*
  277. * Maximum length of a string showing days/hours/minutes/seconds.
  278. * (Does not include the terminating '\0'.)
  279. * Includes space for a '-' sign for any negative components.
  280. * -12345 days, 12 hours, 12 minutes, 12.123 seconds
  281. */
  282. #define TIME_SECS_LEN (10+1+4+2+2+5+2+2+7+2+2+7+4)
  283. /*
  284. * Convert a value in seconds and fractions of a second to a string,
  285. * giving time in days, hours, minutes, and seconds, and put the result
  286. * into a buffer.
  287. * "is_nsecs" says that "frac" is microseconds if true and milliseconds
  288. * if false.
  289. * If time is negative, add a '-' to all non-null components.
  290. */
  291. static void
  292. time_secs_to_str_buf(gint32 time_val, const guint32 frac, const gboolean is_nsecs,
  293. emem_strbuf_t *buf)
  294. {
  295. int hours, mins, secs;
  296. const gchar *msign = "";
  297. gboolean do_comma = FALSE;
  298. if(time_val == G_MININT32) { /* That Which Shall Not Be Negated */
  299. ep_strbuf_append_printf(buf, "Unable to cope with time value %d", time_val);
  300. return;
  301. }
  302. if(time_val < 0){
  303. time_val = -time_val;
  304. msign = "-";
  305. }
  306. secs = time_val % 60;
  307. time_val /= 60;
  308. mins = time_val % 60;
  309. time_val /= 60;
  310. hours = time_val % 24;
  311. time_val /= 24;
  312. if (time_val != 0) {
  313. ep_strbuf_append_printf(buf, "%s%u day%s", msign, time_val, PLURALIZE(time_val));
  314. do_comma = TRUE;
  315. msign="";
  316. }
  317. if (hours != 0) {
  318. ep_strbuf_append_printf(buf, "%s%s%u hour%s", COMMA(do_comma), msign, hours, PLURALIZE(hours));
  319. do_comma = TRUE;
  320. msign="";
  321. }
  322. if (mins != 0) {
  323. ep_strbuf_append_printf(buf, "%s%s%u minute%s", COMMA(do_comma), msign, mins, PLURALIZE(mins));
  324. do_comma = TRUE;
  325. msign="";
  326. }
  327. if (secs != 0 || frac != 0) {
  328. if (frac != 0) {
  329. if (is_nsecs)
  330. ep_strbuf_append_printf(buf, "%s%s%u.%09u seconds", COMMA(do_comma), msign, secs, frac);
  331. else
  332. ep_strbuf_append_printf(buf, "%s%s%u.%03u seconds", COMMA(do_comma), msign, secs, frac);
  333. } else
  334. ep_strbuf_append_printf(buf, "%s%s%u second%s", COMMA(do_comma), msign, secs, PLURALIZE(secs));
  335. }
  336. }
  337. gchar *
  338. time_secs_to_str(const gint32 time_val)
  339. {
  340. emem_strbuf_t *buf;
  341. buf=ep_strbuf_sized_new(TIME_SECS_LEN+1, TIME_SECS_LEN+1);
  342. if (time_val == 0) {
  343. ep_strbuf_append(buf, "0 seconds");
  344. return buf->str;
  345. }
  346. time_secs_to_str_buf(time_val, 0, FALSE, buf);
  347. return buf->str;
  348. }
  349. static void
  350. time_secs_to_str_buf_unsigned(guint32 time_val, const guint32 frac, const gboolean is_nsecs,
  351. emem_strbuf_t *buf)
  352. {
  353. int hours, mins, secs;
  354. gboolean do_comma = FALSE;
  355. secs = time_val % 60;
  356. time_val /= 60;
  357. mins = time_val % 60;
  358. time_val /= 60;
  359. hours = time_val % 24;
  360. time_val /= 24;
  361. if (time_val != 0) {
  362. ep_strbuf_append_printf(buf, "%u day%s", time_val, PLURALIZE(time_val));
  363. do_comma = TRUE;
  364. }
  365. if (hours != 0) {
  366. ep_strbuf_append_printf(buf, "%s%u hour%s", COMMA(do_comma), hours, PLURALIZE(hours));
  367. do_comma = TRUE;
  368. }
  369. if (mins != 0) {
  370. ep_strbuf_append_printf(buf, "%s%u minute%s", COMMA(do_comma), mins, PLURALIZE(mins));
  371. do_comma = TRUE;
  372. }
  373. if (secs != 0 || frac != 0) {
  374. if (frac != 0) {
  375. if (is_nsecs)
  376. ep_strbuf_append_printf(buf, "%s%u.%09u seconds", COMMA(do_comma), secs, frac);
  377. else
  378. ep_strbuf_append_printf(buf, "%s%u.%03u seconds", COMMA(do_comma), secs, frac);
  379. } else
  380. ep_strbuf_append_printf(buf, "%s%u second%s", COMMA(do_comma), secs, PLURALIZE(secs));
  381. }
  382. }
  383. gchar *
  384. time_secs_to_str_unsigned(const guint32 time_val)
  385. {
  386. emem_strbuf_t *buf;
  387. buf=ep_strbuf_sized_new(TIME_SECS_LEN+1, TIME_SECS_LEN+1);
  388. if (time_val == 0) {
  389. ep_strbuf_append(buf, "0 seconds");
  390. return buf->str;
  391. }
  392. time_secs_to_str_buf_unsigned(time_val, 0, FALSE, buf);
  393. return buf->str;
  394. }
  395. gchar *
  396. time_msecs_to_str(gint32 time_val)
  397. {
  398. emem_strbuf_t *buf;
  399. int msecs;
  400. buf=ep_strbuf_sized_new(TIME_SECS_LEN+1+3+1, TIME_SECS_LEN+1+3+1);
  401. if (time_val == 0) {
  402. ep_strbuf_append(buf, "0 seconds");
  403. return buf->str;
  404. }
  405. if(time_val<0){
  406. /* oops we got passed a negative time */
  407. time_val= -time_val;
  408. msecs = time_val % 1000;
  409. time_val /= 1000;
  410. time_val= -time_val;
  411. } else {
  412. msecs = time_val % 1000;
  413. time_val /= 1000;
  414. }
  415. time_secs_to_str_buf(time_val, msecs, FALSE, buf);
  416. return buf->str;
  417. }
  418. static const char mon_names[12][4] = {
  419. "Jan",
  420. "Feb",
  421. "Mar",
  422. "Apr",
  423. "May",
  424. "Jun",
  425. "Jul",
  426. "Aug",
  427. "Sep",
  428. "Oct",
  429. "Nov",
  430. "Dec"
  431. };
  432. static const gchar *get_zonename(struct tm *tmp) {
  433. #if defined(HAVE_TM_ZONE)
  434. return tmp->tm_zone;
  435. #else
  436. if ((tmp->tm_isdst != 0) && (tmp->tm_isdst != 1)) {
  437. return "???";
  438. }
  439. # if defined(HAVE_TZNAME)
  440. return tzname[tmp->tm_isdst];
  441. # elif defined(_WIN32)
  442. /* Windows C Runtime: */
  443. /* _tzname is encoded using the "system default ansi code page" */
  444. /* ("which is not necessarily the same as the C library locale"). */
  445. /* So: _tzname must be converted to UTF8 before use. */
  446. /* Alternative: use Windows GetTimeZoneInformation() to get the */
  447. /* timezone name in UTF16 and convert same to UTF8. */
  448. /* XXX: the result is that the timezone name will be based upon the */
  449. /* system code page (iow: the charset of the system). */
  450. /* Since Wireshark is not internationalized, it would seem more */
  451. /* correct to show the timezone name in English, no matter what */
  452. /* the system code page, but I don't how to do that (or if it's */
  453. /* really even possible). */
  454. /* In any case converting to UTF8 presumably at least keeps GTK */
  455. /* happy. (A bug was reported wherein Wireshark crashed in GDK */
  456. /* on a "Japanese version of Windows XP" when trying to copy */
  457. /* the date/time string (containing a copy of _tz_name) to the */
  458. /* clipboard). */
  459. {
  460. static char *ws_tzname[2] = {NULL, NULL};
  461. /* The g_malloc'd value returned from g_locale_to_utf8() is */
  462. /* cached for all further use so there's no need to ever */
  463. /* g_free() that value. */
  464. if (ws_tzname[tmp->tm_isdst] == NULL) {
  465. ws_tzname[tmp->tm_isdst] = g_locale_to_utf8(_tzname[tmp->tm_isdst], -1, NULL, NULL, NULL);
  466. if (ws_tzname[tmp->tm_isdst] == NULL) {
  467. ws_tzname[tmp->tm_isdst] = "???";
  468. }
  469. }
  470. return ws_tzname[tmp->tm_isdst];
  471. }
  472. # else
  473. return tmp->tm_isdst ? "?DT" : "?ST";
  474. # endif
  475. #endif
  476. }
  477. gchar *
  478. abs_time_to_str(const nstime_t *abs_time, const absolute_time_display_e fmt,
  479. gboolean show_zone)
  480. {
  481. struct tm *tmp = NULL;
  482. const char *zonename = "???";
  483. gchar *buf = NULL;
  484. #if (defined _WIN32) && (_MSC_VER < 1500)
  485. /* calling localtime() on MSVC 2005 with huge values causes it to crash */
  486. /* XXX - find the exact value that still does work */
  487. /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
  488. if(abs_time->secs > 2000000000) {
  489. tmp = NULL;
  490. } else
  491. #endif
  492. switch (fmt) {
  493. case ABSOLUTE_TIME_UTC:
  494. case ABSOLUTE_TIME_DOY_UTC:
  495. tmp = gmtime(&abs_time->secs);
  496. zonename = "UTC";
  497. break;
  498. case ABSOLUTE_TIME_LOCAL:
  499. tmp = localtime(&abs_time->secs);
  500. if (tmp) {
  501. zonename = get_zonename(tmp);
  502. }
  503. break;
  504. }
  505. if (tmp) {
  506. switch (fmt) {
  507. case ABSOLUTE_TIME_DOY_UTC:
  508. if (show_zone) {
  509. buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d.%09ld %s",
  510. tmp->tm_year + 1900,
  511. tmp->tm_yday + 1,
  512. tmp->tm_hour,
  513. tmp->tm_min,
  514. tmp->tm_sec,
  515. (long)abs_time->nsecs,
  516. zonename);
  517. } else {
  518. buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d.%09ld",
  519. tmp->tm_year + 1900,
  520. tmp->tm_yday + 1,
  521. tmp->tm_hour,
  522. tmp->tm_min,
  523. tmp->tm_sec,
  524. (long)abs_time->nsecs);
  525. }
  526. break;
  527. case ABSOLUTE_TIME_UTC:
  528. case ABSOLUTE_TIME_LOCAL:
  529. if (show_zone) {
  530. buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d.%09ld %s",
  531. mon_names[tmp->tm_mon],
  532. tmp->tm_mday,
  533. tmp->tm_year + 1900,
  534. tmp->tm_hour,
  535. tmp->tm_min,
  536. tmp->tm_sec,
  537. (long)abs_time->nsecs,
  538. zonename);
  539. } else {
  540. buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d.%09ld",
  541. mon_names[tmp->tm_mon],
  542. tmp->tm_mday,
  543. tmp->tm_year + 1900,
  544. tmp->tm_hour,
  545. tmp->tm_min,
  546. tmp->tm_sec,
  547. (long)abs_time->nsecs);
  548. }
  549. break;
  550. }
  551. } else
  552. buf = ep_strdup("Not representable");
  553. return buf;
  554. }
  555. gchar *
  556. abs_time_secs_to_str(const time_t abs_time, const absolute_time_display_e fmt,
  557. gboolean show_zone)
  558. {
  559. struct tm *tmp = NULL;
  560. const char *zonename = "???";
  561. gchar *buf = NULL;
  562. #if (defined _WIN32) && (_MSC_VER < 1500)
  563. /* calling localtime() on MSVC 2005 with huge values causes it to crash */
  564. /* XXX - find the exact value that still does work */
  565. /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
  566. if(abs_time > 2000000000) {
  567. tmp = NULL;
  568. } else
  569. #endif
  570. switch (fmt) {
  571. case ABSOLUTE_TIME_UTC:
  572. case ABSOLUTE_TIME_DOY_UTC:
  573. tmp = gmtime(&abs_time);
  574. zonename = "UTC";
  575. break;
  576. case ABSOLUTE_TIME_LOCAL:
  577. tmp = localtime(&abs_time);
  578. if (tmp) {
  579. zonename = get_zonename(tmp);
  580. }
  581. break;
  582. }
  583. if (tmp) {
  584. switch (fmt) {
  585. case ABSOLUTE_TIME_DOY_UTC:
  586. if (show_zone) {
  587. buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d %s",
  588. tmp->tm_year + 1900,
  589. tmp->tm_yday + 1,
  590. tmp->tm_hour,
  591. tmp->tm_min,
  592. tmp->tm_sec,
  593. zonename);
  594. } else {
  595. buf = ep_strdup_printf("%04d/%03d:%02d:%02d:%02d",
  596. tmp->tm_year + 1900,
  597. tmp->tm_yday + 1,
  598. tmp->tm_hour,
  599. tmp->tm_min,
  600. tmp->tm_sec);
  601. }
  602. break;
  603. case ABSOLUTE_TIME_UTC:
  604. case ABSOLUTE_TIME_LOCAL:
  605. if (show_zone) {
  606. buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d %s",
  607. mon_names[tmp->tm_mon],
  608. tmp->tm_mday,
  609. tmp->tm_year + 1900,
  610. tmp->tm_hour,
  611. tmp->tm_min,
  612. tmp->tm_sec,
  613. zonename);
  614. } else {
  615. buf = ep_strdup_printf("%s %2d, %d %02d:%02d:%02d",
  616. mon_names[tmp->tm_mon],
  617. tmp->tm_mday,
  618. tmp->tm_year + 1900,
  619. tmp->tm_hour,
  620. tmp->tm_min,
  621. tmp->tm_sec);
  622. }
  623. break;
  624. }
  625. } else
  626. buf = ep_strdup("Not representable");
  627. return buf;
  628. }
  629. void
  630. display_signed_time(gchar *buf, int buflen, const gint32 sec, gint32 frac,
  631. const to_str_time_res_t units)
  632. {
  633. /* If the fractional part of the time stamp is negative,
  634. print its absolute value and, if the seconds part isn't
  635. (the seconds part should be zero in that case), stick
  636. a "-" in front of the entire time stamp. */
  637. if (frac < 0) {
  638. frac = -frac;
  639. if (sec >= 0) {
  640. if (buflen < 1) {
  641. return;
  642. }
  643. buf[0] = '-';
  644. buf++;
  645. buflen--;
  646. }
  647. }
  648. switch (units) {
  649. case TO_STR_TIME_RES_T_SECS:
  650. g_snprintf(buf, buflen, "%d", sec);
  651. break;
  652. case TO_STR_TIME_RES_T_DSECS:
  653. g_snprintf(buf, buflen, "%d.%01d", sec, frac);
  654. break;
  655. case TO_STR_TIME_RES_T_CSECS:
  656. g_snprintf(buf, buflen, "%d.%02d", sec, frac);
  657. break;
  658. case TO_STR_TIME_RES_T_MSECS:
  659. g_snprintf(buf, buflen, "%d.%03d", sec, frac);
  660. break;
  661. case TO_STR_TIME_RES_T_USECS:
  662. g_snprintf(buf, buflen, "%d.%06d", sec, frac);
  663. break;
  664. case TO_STR_TIME_RES_T_NSECS:
  665. g_snprintf(buf, buflen, "%d.%09d", sec, frac);
  666. break;
  667. }
  668. }
  669. void
  670. display_epoch_time(gchar *buf, int buflen, const time_t sec, gint32 frac,
  671. const to_str_time_res_t units)
  672. {
  673. double elapsed_secs;
  674. elapsed_secs = difftime(sec,(time_t)0);
  675. /* This code copied from display_signed_time; keep it in case anyone
  676. is looking at captures from before 1970 (???).
  677. If the fractional part of the time stamp is negative,
  678. print its absolute value and, if the seconds part isn't
  679. (the seconds part should be zero in that case), stick
  680. a "-" in front of the entire time stamp. */
  681. if (frac < 0) {
  682. frac = -frac;
  683. if (elapsed_secs >= 0) {
  684. if (buflen < 1) {
  685. return;
  686. }
  687. buf[0] = '-';
  688. buf++;
  689. buflen--;
  690. }
  691. }
  692. switch (units) {
  693. case TO_STR_TIME_RES_T_SECS:
  694. g_snprintf(buf, buflen, "%0.0f", elapsed_secs);
  695. break;
  696. case TO_STR_TIME_RES_T_DSECS:
  697. g_snprintf(buf, buflen, "%0.0f.%01d", elapsed_secs, frac);
  698. break;
  699. case TO_STR_TIME_RES_T_CSECS:
  700. g_snprintf(buf, buflen, "%0.0f.%02d", elapsed_secs, frac);
  701. break;
  702. case TO_STR_TIME_RES_T_MSECS:
  703. g_snprintf(buf, buflen, "%0.0f.%03d", elapsed_secs, frac);
  704. break;
  705. case TO_STR_TIME_RES_T_USECS:
  706. g_snprintf(buf, buflen, "%0.0f.%06d", elapsed_secs, frac);
  707. break;
  708. case TO_STR_TIME_RES_T_NSECS:
  709. g_snprintf(buf, buflen, "%0.0f.%09d", elapsed_secs, frac);
  710. break;
  711. }
  712. }
  713. /*
  714. * Display a relative time as days/hours/minutes/seconds.
  715. */
  716. gchar *
  717. rel_time_to_str(const nstime_t *rel_time)
  718. {
  719. emem_strbuf_t *buf;
  720. gint32 time_val;
  721. gint32 nsec;
  722. buf=ep_strbuf_sized_new(1+TIME_SECS_LEN+1+6+1, 1+TIME_SECS_LEN+1+6+1);
  723. /* If the nanoseconds part of the time stamp is negative,
  724. print its absolute value and, if the seconds part isn't
  725. (the seconds part should be zero in that case), stick
  726. a "-" in front of the entire time stamp. */
  727. time_val = (gint) rel_time->secs;
  728. nsec = rel_time->nsecs;
  729. if (time_val == 0 && nsec == 0) {
  730. ep_strbuf_append(buf, "0.000000000 seconds");
  731. return buf->str;
  732. }
  733. if (nsec < 0) {
  734. nsec = -nsec;
  735. ep_strbuf_append_c(buf, '-');
  736. /*
  737. * We assume here that "rel_time->secs" is negative
  738. * or zero; if it's not, the time stamp is bogus,
  739. * with a positive seconds and negative microseconds.
  740. */
  741. time_val = (gint) -rel_time->secs;
  742. }
  743. time_secs_to_str_buf(time_val, nsec, TRUE, buf);
  744. return buf->str;
  745. }
  746. #define REL_TIME_SECS_LEN (1+10+1+9+1)
  747. /*
  748. * Display a relative time as seconds.
  749. */
  750. gchar *
  751. rel_time_to_secs_str(const nstime_t *rel_time)
  752. {
  753. gchar *buf;
  754. buf=(gchar *)ep_alloc(REL_TIME_SECS_LEN);
  755. display_signed_time(buf, REL_TIME_SECS_LEN, (gint32) rel_time->secs,
  756. rel_time->nsecs, TO_STR_TIME_RES_T_NSECS);
  757. return buf;
  758. }
  759. /*
  760. * Generates a string representing the bits in a bitfield at "bit_offset" from an 8 bit boundary
  761. * with the length in bits of no_of_bits based on value.
  762. * Ex: ..xx x...
  763. */
  764. char *
  765. decode_bits_in_field(const guint bit_offset, const gint no_of_bits, const guint64 value)
  766. {
  767. guint64 mask = 0,tmp;
  768. char *str;
  769. int bit, str_p = 0;
  770. int i;
  771. mask = 1;
  772. mask = mask << (no_of_bits-1);
  773. /* Prepare the string, 256 pos for the bits and zero termination, + 64 for the spaces */
  774. str=(char *)ep_alloc0(256+64);
  775. for(bit=0;bit<((int)(bit_offset&0x07));bit++){
  776. if(bit&&(!(bit%4))){
  777. str[str_p] = ' ';
  778. str_p++;
  779. }
  780. str[str_p] = '.';
  781. str_p++;
  782. }
  783. /* read the bits for the int */
  784. for(i=0;i<no_of_bits;i++){
  785. if(bit&&(!(bit%4))){
  786. str[str_p] = ' ';
  787. str_p++;
  788. }
  789. if(bit&&(!(bit%8))){
  790. str[str_p] = ' ';
  791. str_p++;
  792. }
  793. bit++;
  794. tmp = value & mask;
  795. if(tmp != 0){
  796. str[str_p] = '1';
  797. str_p++;
  798. } else {
  799. str[str_p] = '0';
  800. str_p++;
  801. }
  802. mask = mask>>1;
  803. }
  804. for(;bit%8;bit++){
  805. if(bit&&(!(bit%4))){
  806. str[str_p] = ' ';
  807. str_p++;
  808. }
  809. str[str_p] = '.';
  810. str_p++;
  811. }
  812. return str;
  813. }
  814. /* Generate, into "buf", a string showing the bits of a bitfield.
  815. Return a pointer to the character after that string. */
  816. /*XXX this needs a buf_len check */
  817. char *
  818. other_decode_bitfield_value(char *buf, const guint32 val, const guint32 mask, const int width)
  819. {
  820. int i;
  821. guint32 bit;
  822. char *p;
  823. i = 0;
  824. p = buf;
  825. bit = 1 << (width - 1);
  826. for (;;) {
  827. if (mask & bit) {
  828. /* This bit is part of the field. Show its value. */
  829. if (val & bit)
  830. *p++ = '1';
  831. else
  832. *p++ = '0';
  833. } else {
  834. /* This bit is not part of the field. */
  835. *p++ = '.';
  836. }
  837. bit >>= 1;
  838. i++;
  839. if (i >= width)
  840. break;
  841. if (i % 4 == 0)
  842. *p++ = ' ';
  843. }
  844. *p = '\0';
  845. return p;
  846. }
  847. char *
  848. decode_bitfield_value(char *buf, const guint32 val, const guint32 mask, const int width)
  849. {
  850. char *p;
  851. p = other_decode_bitfield_value(buf, val, mask, width);
  852. p = g_stpcpy(p, " = ");
  853. return p;
  854. }
  855. /* Generate a string describing a Boolean bitfield (a one-bit field that
  856. says something is either true or false). */
  857. const char *
  858. decode_boolean_bitfield(const guint32 val, const guint32 mask, const int width,
  859. const char *truedesc, const char *falsedesc)
  860. {
  861. char *buf;
  862. char *p;
  863. buf=(char *)ep_alloc(1025); /* is this a bit overkill? */
  864. p = decode_bitfield_value(buf, val, mask, width);
  865. if (val & mask)
  866. strcpy(p, truedesc);
  867. else
  868. strcpy(p, falsedesc);
  869. return buf;
  870. }
  871. /* Generate a string describing a numeric bitfield (an N-bit field whose
  872. value is just a number). */
  873. const char *
  874. decode_numeric_bitfield(const guint32 val, const guint32 mask, const int width,
  875. const char *fmt)
  876. {
  877. char *buf;
  878. char *p;
  879. int shift = 0;
  880. buf=(char *)ep_alloc(1025); /* isnt this a bit overkill? */
  881. /* Compute the number of bits we have to shift the bitfield right
  882. to extract its value. */
  883. while ((mask & (1<<shift)) == 0)
  884. shift++;
  885. p = decode_bitfield_value(buf, val, mask, width);
  886. g_snprintf(p, (gulong) (1025-(p-buf)), fmt, (val & mask) >> shift);
  887. return buf;
  888. }
  889. /*
  890. This function is very fast and this function is called a lot.
  891. XXX update the ep_address_to_str stuff to use this function.
  892. */
  893. void
  894. ip_to_str_buf(const guint8 *ad, gchar *buf, const int buf_len)
  895. {
  896. register gchar const *p;
  897. register gchar *b=buf;
  898. if (buf_len < MAX_IP_STR_LEN) {
  899. g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR ); /* Let the unexpected value alert user */
  900. return;
  901. }
  902. p=fast_strings[*ad++];
  903. do {
  904. *b++=*p;
  905. p++;
  906. } while(*p);
  907. *b++='.';
  908. p=fast_strings[*ad++];
  909. do {
  910. *b++=*p;
  911. p++;
  912. } while(*p);
  913. *b++='.';
  914. p=fast_strings[*ad++];
  915. do {
  916. *b++=*p;
  917. p++;
  918. } while(*p);
  919. *b++='.';
  920. p=fast_strings[*ad];
  921. do {
  922. *b++=*p;
  923. p++;
  924. } while(*p);
  925. *b=0;
  926. }
  927. gchar* guid_to_str(const e_guid_t *guid) {
  928. gchar *buf;
  929. buf=(gchar *)ep_alloc(GUID_STR_LEN);
  930. return guid_to_str_buf(guid, buf, GUID_STR_LEN);
  931. }
  932. gchar* guid_to_str_buf(const e_guid_t *guid, gchar *buf, int buf_len) {
  933. char *tempptr = buf;
  934. if (buf_len < GUID_STR_LEN) {
  935. g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len);/* Let the unexpected value alert user */
  936. return buf;
  937. }
  938. /* 37 bytes */
  939. tempptr = dword_to_hex(tempptr, guid->data1); /* 8 bytes */
  940. *tempptr++ = '-'; /* 1 byte */
  941. tempptr = word_to_hex(tempptr, guid->data2); /* 4 bytes */
  942. *tempptr++ = '-'; /* 1 byte */
  943. tempptr = word_to_hex(tempptr, guid->data3); /* 4 bytes */
  944. *tempptr++ = '-'; /* 1 byte */
  945. tempptr = bytes_to_hexstr(tempptr, &guid->data4[0], 2); /* 4 bytes */
  946. *tempptr++ = '-'; /* 1 byte */
  947. tempptr = bytes_to_hexstr(tempptr, &guid->data4[2], 6); /* 12 bytes */
  948. *tempptr = '\0';
  949. return buf;
  950. }
  951. const gchar* port_type_to_str (port_type type) {
  952. switch (type) {
  953. case PT_NONE: return "NONE";
  954. case PT_SCTP: return "SCTP";
  955. case PT_TCP: return "TCP";
  956. case PT_UDP: return "UDP";
  957. case PT_DCCP: return "DCCP";
  958. case PT_IPX: return "IPX";
  959. case PT_NCP: return "NCP";
  960. case PT_EXCHG: return "FC EXCHG";
  961. case PT_DDP: return "DDP";
  962. case PT_SBCCS: return "FICON SBCCS";
  963. case PT_IDP: return "IDP";
  964. case PT_TIPC: return "TIPC";
  965. case PT_USB: return "USB";
  966. case PT_I2C: return "I2C";
  967. case PT_IBQP: return "IBQP";
  968. case PT_BLUETOOTH: return "BLUETOOTH";
  969. default: return "[Unknown]";
  970. }
  971. }
  972. char *
  973. oct_to_str_back(char *ptr, guint32 value)
  974. {
  975. while (value) {
  976. *(--ptr) = '0' + (value & 0x7);
  977. value >>= 3;
  978. }
  979. *(--ptr) = '0';
  980. return ptr;
  981. }
  982. char *
  983. hex_to_str_back(char *ptr, int pad, guint32 value)
  984. {
  985. do {
  986. *(--ptr) = low_nibble_of_octet_to_hex(value);
  987. value >>= 4;
  988. pad--;
  989. } while (value);
  990. /* pad */
  991. while (pad > 0) {
  992. *(--ptr) = '0';
  993. pad--;
  994. }
  995. *(--ptr) = 'x';
  996. *(--ptr) = '0';
  997. return ptr;
  998. }
  999. char *
  1000. uint_to_str_back(char *ptr, guint32 value)
  1001. {
  1002. char const *p;
  1003. /* special case */
  1004. if (value == 0)
  1005. *(--ptr) = '0';
  1006. while (value >= 10) {
  1007. p = fast_strings[100 + (value % 100)];
  1008. value /= 100;
  1009. *(--ptr) = p[2];
  1010. *(--ptr) = p[1];
  1011. }
  1012. if (value)
  1013. *(--ptr) = (value) | '0';
  1014. return ptr;
  1015. }
  1016. char *
  1017. int_to_str_back(char *ptr, gint32 value)
  1018. {
  1019. if (value < 0) {
  1020. ptr = uint_to_str_back(ptr, -value);
  1021. *(--ptr) = '-';
  1022. } else
  1023. ptr = uint_to_str_back(ptr, value);
  1024. return ptr;
  1025. }