1 /*
2 * Copyright (c) 2013-2022 Douglas Gilbert.
3 * All rights reserved.
4 * Use of this source code is governed by a BSD-style
5 * license that can be found in the BSD_LICENSE file.
6 *
7 * SPDX-License-Identifier: BSD-2-Clause
8 */
9
10 #include <unistd.h>
11 #include <fcntl.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <stdarg.h>
15 #include <string.h>
16 #include <getopt.h>
17 #include <ctype.h>
18 #include <errno.h>
19 #define __STDC_FORMAT_MACROS 1
20 #include <inttypes.h>
21
22 #include <time.h>
23
24 #if defined(__GNUC__) && ! defined(SG_LIB_FREEBSD)
25 #include <byteswap.h>
26 #endif
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h" /* need this to see if HAVE_BYTESWAP_H */
30 #endif
31
32 #include "sg_lib.h"
33 #include "sg_pr2serr.h"
34
35 /* Uncomment the next two undefs to force use of the generic (i.e. shifting)
36 * unaligned functions (i.e. sg_get_* and sg_put_*). Use "-b 16|32|64
37 * -n 100m" to see the differences in timing. */
38 /* #undef HAVE_CONFIG_H */
39 /* #undef HAVE_BYTESWAP_H */
40 #include "sg_unaligned.h"
41
42 /*
43 * A utility program to test sg_libs string handling, specifically
44 * related to snprintf().
45 */
46
47 static const char * version_str = "1.17 20220717";
48
49
50 #define MY_NAME "tst_sg_lib"
51
52 #define MAX_LINE_LEN 1024
53
54
55 static struct option long_options[] = {
56 {"byteswap", required_argument, 0, 'b'},
57 {"exit", no_argument, 0, 'e'},
58 {"help", no_argument, 0, 'h'},
59 {"hex2", no_argument, 0, 'H'},
60 {"json", optional_argument, 0, 'j'},
61 {"leadin", required_argument, 0, 'l'},
62 {"num", required_argument, 0, 'n'},
63 {"printf", no_argument, 0, 'p'},
64 {"sense", no_argument, 0, 's'},
65 {"unaligned", no_argument, 0, 'u'},
66 {"verbose", no_argument, 0, 'v'},
67 {"version", no_argument, 0, 'V'},
68 {0, 0, 0, 0}, /* sentinel */
69 };
70
71 static const uint8_t desc_sense_data1[] = {
72 /* unrec_err, excessive_writes, sdat_ovfl, additional_len=? */
73 0x72, 0x1, 0x3, 0x2, 0x80, 0x0, 0x0, 12+12+8+4+8+4+28,
74 /* Information: 0x11223344556677bb */
75 0x0, 0xa, 0x80, 0x0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0xbb,
76 /* command specific: 0x3344556677bbccff */
77 0x1, 0xa, 0x0, 0x0, 0x33, 0x44, 0x55, 0x66, 0x77, 0xbb, 0xcc, 0xff,
78 /* sense key specific: SKSV=1, actual_count=257 (hex: 0x101) */
79 0x2, 0x6, 0x0, 0x0, 0x80, 0x1, 0x1, 0x0,
80 /* field replaceable code=0x45 */
81 0x3, 0x2, 0x0, 0x45,
82 /* another progress report indicator */
83 0xa, 0x6, 0x2, 0x1, 0x2, 0x0, 0x32, 0x01,
84 /* incorrect length indicator (ILI) */
85 0x5, 0x2, 0x0, 0x20,
86 /* user data segment referral */
87 0xb, 26, 0x1, 0x0,
88 0,0,0,1, 0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,
89 0x1,0x2,0x3,0x4,0x55,0x6,0x7,0x8,
90 2,0,0x12,0x34,
91 };
92
93 static const uint8_t desc_sense_data2[] = {
94 /* ill_req, inv fld in para list, additional_len=? */
95 0x72, 0x5, 0x26, 0x0, 0x0, 0x0, 0x0, 8+4,
96 /* sense key specific: SKSV=1, C/D*=0, bitp=7 bytep=34 */
97 0x2, 0x6, 0x0, 0x0, 0x8f, 0x0, 0x34, 0x0,
98 /* field replaceable code=0x45 */
99 0x3, 0x2, 0x0, 0x45,
100 };
101
102 static const uint8_t desc_sense_data3[] = {
103 /* medium err, vibration induced ..., additional_len=? */
104 0x72, 0x3, 0x9, 0x5, 0x0, 0x0, 0x0, 32+16,
105 /* 0xd: block dev: sense key specific: SKSV=1, retry_count=257, fru=0x45
106 * info=0x1122334455, command_specific=0x1 */
107 0xd, 0x1e, 0xa0, 0x0, 0x80, 0x1, 0x1, 0x45,
108 0x0, 0x0, 0x0, 0x11, 0x22, 0x33, 0x44, 0x55,
109 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
110 /* following sbc3 (standard) and sbc4r10 inconsistency; add padding */
111 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
112 /* 0xe: reason: send_to_given+henceforth, lu, naa-5, 0x5333333000001f40 */
113 0xe, 0xe, 0x0, 0x1, 0x1, 0x3, 0x0, 0x8,
114 0x53, 0x33, 0x33, 0x30, 0x0, 0x0, 0x1f, 0x40,
115 };
116
117 static const uint8_t desc_sense_data4[] = {
118 /* ill_req, inv fld in para list, additional_len=? */
119 0x72, 0x5, 0x26, 0x0, 0x0, 0x0, 0x0, 24,
120 /* Forwarded sense data, FSDT=0, sd_src=7, f_status=2 */
121 0xc, 22, 0x7, 0x2,
122 /* ill_req, inv fld in para list, additional_len=? */
123 0x72, 0x5, 0x26, 0x0, 0x0, 0x0, 0x0, 8+4,
124 /* sense key specific: SKSV=1, C/D*=0, bitp=7 bytep=34 */
125 0x2, 0x6, 0x0, 0x0, 0x8f, 0x0, 0x34, 0x0,
126 /* field replaceable code=0x45 */
127 0x3, 0x2, 0x0, 0x45,
128 };
129
130 static const uint8_t desc_sense_data5[] = {
131 /* no_sense, ATA info available */
132 0x72, 0x0, 0x0, 0x1d, 0x0, 0x0, 0x0, 14+14,
133 /* ATA descriptor extend=1 */
134 0x9, 0xc, 0x1, 0x0, 0x34, 0x12, 0x44, 0x11,
135 0x55, 0x22, 0x66, 0x33, 0x1, 0x0,
136 /* ATA descriptor extend=0 */
137 0x9, 0xc, 0x0, 0x0, 0x34, 0x12, 0x44, 0x11,
138 0x55, 0x22, 0x66, 0x33, 0x1, 0x0,
139 };
140
141 static const uint8_t desc_sense_data6[] = {
142 /* UA, req, subsidiary binding */
143 0x72, 0x6, 0x3f, 0x1a, 0x0, 0x0, 0x0, 26+12+12,
144 /* 0xe: designator, reason: preferred admin lu, uuid */
145 0xe, 0x18, 0x0, 0x4, 0x1, 0xa, 0x0, 0x12,
146 0x10, 0x0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
147 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
148 0xfe, 0xdc,
149 /* 0x0: Information(valid): lun */
150 0x0, 0xa, 0x80, 0x0,
151 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
152 /* 0x1: Command specific: 0x1 */
153 0x1, 0xa, 0x0, 0x0,
154 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
155 };
156
157 static const char * leadin = NULL;
158
159
160 static void
usage()161 usage()
162 {
163 fprintf(stderr,
164 "Usage: tst_sg_lib [--exit] [--help] [--hex2] [--leadin=STR] "
165 "[--printf]\n"
166 " [--sense] [--unaligned] [--verbose] "
167 "[--version]\n"
168 " where:\n"
169 #if defined(__GNUC__) && ! defined(SG_LIB_FREEBSD)
170 " --byteswap=B|-b B B is 16, 32 or 64; tests NUM "
171 "byteswaps\n"
172 " compared to sg_unaligned "
173 "equivalent\n"
174 " --exit|-e test exit status strings\n"
175 #else
176 " --exit|-e test exit status strings\n"
177 #endif
178 " --help|-h print out usage message\n"
179 " --hex2|-H test hex2* variants\n"
180 " --leadin=STR|-l STR every line output by --sense "
181 "should\n"
182 " be prefixed by STR\n"
183 " --num=NUM|-n NUM number of iterations (def=1)\n"
184 " --printf|-p test library printf variants\n"
185 " --sense|-s test sense data handling\n"
186 " --unaligned|-u test unaligned data handling\n"
187 " --verbose|-v increase verbosity\n"
188 " --version|-V print version string and exit\n\n"
189 "Test various parts of sg_lib, see options. Sense data tests "
190 "overlap\nsomewhat with examples/sg_sense_test .\n"
191 );
192
193 }
194
195 static char *
get_exit_status_str(int exit_status,bool longer,int b_len,char * b)196 get_exit_status_str(int exit_status, bool longer, int b_len, char * b)
197 {
198 int n;
199
200 n = sg_scnpr(b, b_len, " ES=%d: ", exit_status);
201 if (n >= (b_len - 1))
202 return b;
203 if (sg_exit2str(exit_status, longer, b_len - n, b + n)) {
204 n = (int)strlen(b);
205 if (n < (b_len - 1))
206 sg_scnpr(b + n, b_len - n, " [ok=true]");
207 return b;
208 } else
209 snprintf(b, b_len, " No ES string for %d%s", exit_status,
210 (longer ? " [ok=false]" : ""));
211 return b;
212 }
213
214 static uint8_t arr[64];
215
216 #define OFF 7 /* in byteswap mode, can test different alignments (def: 8) */
217
218 int
main(int argc,char * argv[])219 main(int argc, char * argv[])
220 {
221 bool as_json = false;
222 bool do_exit_status = false;
223 bool ok;
224 int k, c, n, len;
225 int byteswap_sz = 0;
226 int do_hex2 = 0;
227 int do_num = 1;
228 int do_printf = 0;
229 int do_sense = 0;
230 int do_unaligned = 0;
231 int did_something = 0;
232 int vb = 0;
233 int ret = 0;
234 sgj_opaque_p jop = NULL;
235 sgj_opaque_p jo2p;
236 sgj_state json_st SG_C_CPP_ZERO_INIT;
237 sgj_state * jsp = &json_st;
238 char b[2048];
239 char bb[256];
240 const int b_len = sizeof(b);
241
242 while (1) {
243 int option_index = 0;
244
245 c = getopt_long(argc, argv, "b:ehHj::l:n:psuvV", long_options,
246 &option_index);
247 if (c == -1)
248 break;
249
250 switch (c) {
251 case 'b':
252 byteswap_sz = sg_get_num(optarg);
253 if (! ((16 == byteswap_sz) || (32 == byteswap_sz) ||
254 (64 == byteswap_sz))) {
255 fprintf(stderr, "--byteswap= requires 16, 32 or 64\n");
256 return 1;
257 }
258 break;
259 case 'e':
260 do_exit_status = true;
261 break;
262 case 'h':
263 case '?':
264 usage();
265 return 0;
266 case 'H':
267 ++do_hex2;
268 break;
269 case 'j':
270 if (! sgj_init_state(&json_st, optarg)) {
271 pr2serr("bad argument to --json= option, unrecognized "
272 "character '%c'\n", json_st.first_bad_char);
273 return SG_LIB_SYNTAX_ERROR;
274 }
275 break;
276
277 case 'l':
278 leadin = optarg;
279 break;
280 case 'n':
281 do_num = sg_get_num(optarg);
282 if (do_num < 0) {
283 fprintf(stderr, "--num= unable decode argument as number\n");
284 return 1;
285 }
286 break;
287 case 'p':
288 ++do_printf;
289 break;
290 case 's':
291 ++do_sense;
292 break;
293 case 'u':
294 ++do_unaligned;
295 break;
296 case 'v':
297 ++vb;
298 break;
299 case 'V':
300 fprintf(stderr, "version: %s\n", version_str);
301 return 0;
302 default:
303 fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
304 usage();
305 return 1;
306 }
307 }
308 if (optind < argc) {
309 if (optind < argc) {
310 for (; optind < argc; ++optind)
311 fprintf(stderr, "Unexpected extra argument: %s\n",
312 argv[optind]);
313 usage();
314 return 1;
315 }
316 }
317
318 as_json = json_st.pr_as_json;
319 if (as_json)
320 jop = sgj_start_r(MY_NAME, version_str, argc, argv, jsp);
321
322 if (do_exit_status) {
323 ++did_something;
324
325 printf("Test Exit Status strings (add -v for long version):\n");
326 printf(" No error (es=0): %s\n",
327 sg_get_category_sense_str(0, b_len, b, vb));
328 ok = sg_exit2str(0, true, b_len, b);
329 printf(" No error (force verbose): %s\n", b);
330 if (vb)
331 printf(" for previous line sg_exit2str() returned: %s\n",
332 (ok ? "true" : "false"));
333 printf("%s\n", get_exit_status_str(1, (vb > 0), b_len, b));
334 printf("%s\n", get_exit_status_str(2, (vb > 0), b_len, b));
335 printf("%s\n", get_exit_status_str(3, (vb > 0), b_len, b));
336 printf("%s\n", get_exit_status_str(4, (vb > 0), b_len, b));
337 printf("%s\n", get_exit_status_str(5, (vb > 0), b_len, b));
338 printf("%s\n", get_exit_status_str(6, (vb > 0), b_len, b));
339 printf("%s\n", get_exit_status_str(7, (vb > 0), b_len, b));
340 printf("%s\n", get_exit_status_str(8, (vb > 0), b_len, b));
341 printf("%s\n", get_exit_status_str(25, (vb > 0), b_len, b));
342 printf("%s\n", get_exit_status_str(33, (vb > 0), b_len, b));
343 printf("%s\n", get_exit_status_str(36, (vb > 0), b_len, b));
344 printf("%s\n", get_exit_status_str(48, (vb > 0), b_len, b));
345 printf("%s\n", get_exit_status_str(50, (vb > 0), b_len, b));
346 printf("%s\n", get_exit_status_str(51, (vb > 0), b_len, b));
347 printf("%s\n", get_exit_status_str(96, (vb > 0), b_len, b));
348 printf("%s\n", get_exit_status_str(97, (vb > 0), b_len, b));
349 printf("%s\n", get_exit_status_str(97, (vb > 0), b_len, b));
350 printf("%s\n", get_exit_status_str(255, (vb > 0), b_len, b));
351 printf("%s\n", get_exit_status_str(-1, (vb > 0), b_len, b));
352
353 printf("\n");
354 }
355
356 if (do_sense ) {
357 ++did_something;
358 if (as_json) {
359 jo2p = sgj_named_subobject_r(jsp, jop, "desc_sense_data__test1");
360 sgj_js_sense(jsp, jo2p, desc_sense_data1,
361 (int)sizeof(desc_sense_data1));
362 } else {
363 printf("desc_sense_data test1:\n");
364 sg_print_sense(leadin, desc_sense_data1,
365 (int)sizeof(desc_sense_data1), vb);
366 printf("\n");
367 }
368 #if 1
369 if (as_json) {
370 sgj_js_str_out(jsp, "sg_get_sense_str(ds_data1)", 999);
371 sg_get_sense_str(leadin, desc_sense_data1,
372 sizeof(desc_sense_data1), vb, b_len, b);
373 sgj_js_str_out(jsp, b, strlen(b));
374
375 } else {
376 printf("sg_get_sense_str(ds_data1):\n");
377 sg_get_sense_str(leadin, desc_sense_data1,
378 sizeof(desc_sense_data1), vb, b_len, b);
379 printf("sg_get_sense_str: strlen(b)->%u\n", (uint32_t)strlen(b));
380 printf("%s", b);
381 printf("\n");
382 }
383 #endif
384 if (as_json) {
385 jo2p = sgj_named_subobject_r(jsp, jop, "desc_sense_data__test2");
386 sgj_js_sense(jsp, jo2p, desc_sense_data2,
387 (int)sizeof(desc_sense_data2));
388 } else {
389 printf("desc_sense_data test2\n");
390 sg_print_sense(leadin, desc_sense_data2,
391 (int)sizeof(desc_sense_data2), vb);
392 printf("\n");
393 }
394 if (as_json) {
395 jo2p = sgj_named_subobject_r(jsp, jop,
396 "desc_sense_block_combo_test3");
397 sgj_js_sense(jsp, jo2p, desc_sense_data3,
398 (int)sizeof(desc_sense_data3));
399 } else {
400 printf("desc_sense block dev combo plus designator test3\n");
401 sg_print_sense(leadin, desc_sense_data3,
402 (int)sizeof(desc_sense_data3), vb);
403 printf("\n");
404 }
405 if (as_json) {
406 jo2p = sgj_named_subobject_r(jsp, jop,
407 "desc_sense_forwarded_sense_test4");
408 sgj_js_sense(jsp, jo2p, desc_sense_data4,
409 (int)sizeof(desc_sense_data4));
410 } else {
411 printf("desc_sense forwarded sense test4\n");
412 sg_print_sense(leadin, desc_sense_data4,
413 (int)sizeof(desc_sense_data4), vb);
414 printf("\n");
415 }
416 if (as_json) {
417 jo2p = sgj_named_subobject_r(jsp, jop,
418 "desc_sense_ata_info_test5");
419 sgj_js_sense(jsp, jo2p, desc_sense_data5,
420 (int)sizeof(desc_sense_data5));
421 } else {
422 printf("desc_sense ATA Info test5\n");
423 sg_print_sense(leadin, desc_sense_data5,
424 (int)sizeof(desc_sense_data5), vb);
425 printf("\n");
426 }
427 if (as_json) {
428 jo2p = sgj_named_subobject_r(jsp, jop,
429 "desc_sense_ua_binding_test6");
430 sgj_js_sense(jsp, jo2p, desc_sense_data6,
431 (int)sizeof(desc_sense_data6));
432 } else {
433 printf("desc_sense UA subsidiary binding changed test6\n");
434 sg_print_sense(leadin, desc_sense_data6,
435 (int)sizeof(desc_sense_data6), vb);
436 printf("\n");
437 printf("\n");
438 }
439 }
440
441 if (do_printf) {
442 ++did_something;
443 printf("Testing sg_scnpr():\n");
444 b[0] = '\0';
445 len = b_len;
446 n = sg_scnpr(b, len, "%s", "test");
447 printf("sg_scnpr(,%d,,\"test\") -> %d; strlen(b) -> %u\n",
448 len, n, (uint32_t)strlen(b));
449 if (strlen(b) > 0)
450 printf("Resulting string: %s\n", b);
451
452 b[0] = '\0';
453 len = -1;
454 n = sg_scnpr(b, len, "%s", "test");
455 printf("sg_scnpr(,%d,,\"test\") -> %d; strlen(b) -> %u\n",
456 len, n, (uint32_t)strlen(b));
457 if (strlen(b) > 0)
458 printf("Resulting string: %s\n", b);
459
460 b[0] = '\0';
461 len = 0;
462 n = sg_scnpr(b, len, "%s", "test");
463 printf("sg_scnpr(,%d,,\"test\") -> %d; strlen(b) -> %u\n",
464 len, n, (uint32_t)strlen(b));
465 if (strlen(b) > 0)
466 printf("Resulting string: %s\n", b);
467
468 b[0] = '\0';
469 len = 1;
470 n = sg_scnpr(b, len, "%s", "test");
471 printf("sg_scnpr(,%d,,\"test\") -> %d; strlen(b) -> %u\n",
472 len, n, (uint32_t)strlen(b));
473 if (strlen(b) > 0)
474 printf("Resulting string: %s\n", b);
475
476 b[0] = '\0';
477 len = 2;
478 n = sg_scnpr(b, len, "%s", "test");
479 printf("sg_scnpr(,%d,,\"test\") -> %d; strlen(b) -> %u\n",
480 len, n, (uint32_t)strlen(b));
481 if (strlen(b) > 0)
482 printf("Resulting string: %s\n", b);
483
484 b[0] = '\0';
485 len = 3;
486 n = sg_scnpr(b, len, "%s", "test");
487 printf("sg_scnpr(,%d,,\"test\") -> %d; strlen(b) -> %u\n",
488 len, n, (uint32_t)strlen(b));
489 if (strlen(b) > 0)
490 printf("Resulting string: %s\n", b);
491
492 b[0] = '\0';
493 len = 4;
494 n = sg_scnpr(b, len, "%s", "test");
495 printf("sg_scnpr(,%d,,\"test\") -> %d; strlen(b) -> %u\n",
496 len, n, (uint32_t)strlen(b));
497 if (strlen(b) > 0)
498 printf("Resulting string: %s\n", b);
499
500 b[0] = '\0';
501 len = 5;
502 n = sg_scnpr(b, len, "%s", "test");
503 printf("sg_scnpr(,%d,,\"test\") -> %d; strlen(b) -> %u\n",
504 len, n, (uint32_t)strlen(b));
505 if (strlen(b) > 0)
506 printf("Resulting string: %s\n", b);
507
508 b[0] = '\0';
509 len = 6;
510 n = sg_scnpr(b, len, "%s", "test");
511 printf("sg_scnpr(,%d,,\"test\") -> %d; strlen(b) -> %u\n",
512 len, n, (uint32_t)strlen(b));
513 if (strlen(b) > 0)
514 printf("Resulting string: %s\n", b);
515
516 b[0] = '\0';
517 len = 7;
518 n = sg_scnpr(b, len, "%s", "test");
519 printf("sg_scnpr(,%d,,\"test\") -> %d; strlen(b) -> %u\n",
520 len, n, (uint32_t)strlen(b));
521 if (strlen(b) > 0)
522 printf("Resulting string: %s\n", b);
523 }
524 if (do_hex2) {
525 uint8_t b[] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
526 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
527 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58};
528
529 ++did_something;
530 for (k = 0; k < 19; ++k) {
531 printf("k=%d:\n", k);
532 hex2stdout(b, k, 0);
533 hex2str(b, k, "h2str0: ", 0, sizeof(bb), bb);
534 printf("%s", bb);
535 hex2stdout(b, k, 1);
536 hex2str(b, k, "h2str1: ", 1, sizeof(bb), bb);
537 printf("%s", bb);
538 hex2str(b, k, "h2str2: ", 2, sizeof(bb), bb);
539 printf("%s\n", bb);
540 hex2stdout(b, k, -1);
541 printf("\n");
542 }
543 }
544 if (do_unaligned) {
545 uint16_t u16 = 0x55aa;
546 uint16_t u16r;
547 uint32_t u24 = 0x224488;
548 uint32_t u24r;
549 uint32_t u32 = 0x224488aa;
550 uint32_t u32r;
551 uint64_t u48 = 0x112233445566ULL;
552 uint64_t u48r;
553 uint64_t u64 = 0x1122334455667788ULL;
554 uint64_t u64r;
555 uint8_t u8[64];
556
557 ++did_something;
558 if (vb)
559 memset(u8, 0, sizeof(u8));
560 printf("u16=0x%" PRIx16 "\n", u16);
561 sg_put_unaligned_le16(u16, u8);
562 printf(" le16:\n");
563 hex2stdout(u8, vb ? 10 : 2, -1);
564 u16r = sg_get_unaligned_le16(u8);
565 printf(" u16r=0x%" PRIx16 "\n", u16r);
566 sg_put_unaligned_be16(u16, u8);
567 printf(" be16:\n");
568 hex2stdout(u8, vb ? 10 : 2, -1);
569 u16r = sg_get_unaligned_be16(u8);
570 printf(" u16r=0x%" PRIx16 "\n\n", u16r);
571
572 printf("u24=0x%" PRIx32 "\n", u24);
573 sg_put_unaligned_le24(u24, u8);
574 printf(" le24:\n");
575 hex2stdout(u8, vb ? 10 : 3, -1);
576 u24r = sg_get_unaligned_le24(u8);
577 printf(" u24r=0x%" PRIx32 "\n", u24r);
578 sg_put_unaligned_be24(u24, u8);
579 printf(" be24:\n");
580 hex2stdout(u8, vb ? 10 : 3, -1);
581 u24r = sg_get_unaligned_be24(u8);
582 printf(" u24r=0x%" PRIx32 "\n\n", u24r);
583
584 printf("u32=0x%" PRIx32 "\n", u32);
585 sg_put_unaligned_le32(u32, u8);
586 printf(" le32:\n");
587 hex2stdout(u8, vb ? 10 : 4, -1);
588 u32r = sg_get_unaligned_le32(u8);
589 printf(" u32r=0x%" PRIx32 "\n", u32r);
590 sg_put_unaligned_be32(u32, u8);
591 printf(" be32:\n");
592 hex2stdout(u8, vb ? 10 : 4, -1);
593 u32r = sg_get_unaligned_be32(u8);
594 printf(" u32r=0x%" PRIx32 "\n\n", u32r);
595
596 printf("u48=0x%" PRIx64 "\n", u48);
597 sg_put_unaligned_le48(u48, u8);
598 printf(" le48:\n");
599 hex2stdout(u8, vb ? 10 : 6, -1);
600 u48r = sg_get_unaligned_le48(u8);
601 printf(" u48r=0x%" PRIx64 "\n", u48r);
602 sg_put_unaligned_be48(u48, u8);
603 printf(" be48:\n");
604 hex2stdout(u8, vb ? 10 : 6, -1);
605 u48r = sg_get_unaligned_be48(u8);
606 printf(" u48r=0x%" PRIx64 "\n\n", u48r);
607
608 printf("u64=0x%" PRIx64 "\n", u64);
609 sg_put_unaligned_le64(u64, u8);
610 printf(" le64:\n");
611 hex2stdout(u8, vb ? 10 : 8, -1);
612 u64r = sg_get_unaligned_le64(u8);
613 printf(" u64r=0x%" PRIx64 "\n", u64r);
614 sg_put_unaligned_be64(u64, u8);
615 printf(" be64:\n");
616 hex2stdout(u8, vb ? 10 : 8, -1);
617 u64r = sg_get_unaligned_be64(u8);
618 printf(" u64r=0x%" PRIx64 "\n\n", u64r);
619
620 printf(" be[v=8 bytes]:\n");
621 hex2stdout(u8, vb ? 10 : 8, -1);
622 u64r = sg_get_unaligned_be(8, u8);
623 printf(" u64r[v=8 bytes]=0x%" PRIx64 "\n", u64r);
624 printf(" le[v=8 bytes]:\n");
625 hex2stdout(u8, vb ? 10 : 8, -1);
626 u64r = sg_get_unaligned_le(8, u8);
627 printf(" u64r[v=8 bytes]=0x%" PRIx64 "\n\n", u64r);
628 }
629
630 #if defined(__GNUC__) && ! defined(SG_LIB_FREEBSD)
631 if (byteswap_sz > 0) {
632 uint32_t elapsed_msecs;
633 uint16_t count16 = 0;
634 uint32_t count32 = 0;
635 uint64_t count64 = 0;
636 struct timespec start_tm, end_tm;
637
638 ++did_something;
639 if (0 != clock_gettime(CLOCK_MONOTONIC, &start_tm)) {
640 perror("clock_gettime(CLOCK_MONOTONIC)\n");
641 return 1;
642 }
643 for (k = 0; k < do_num; ++k) {
644 switch (byteswap_sz) {
645 case 16:
646 sg_put_unaligned_be16(count16 + 1, arr + OFF);
647 count16 = sg_get_unaligned_be16(arr + OFF);
648 break;
649 case 32:
650 sg_put_unaligned_be32(count32 + 1, arr + OFF);
651 count32 = sg_get_unaligned_be32(arr + OFF);
652 break;
653 case 64:
654 sg_put_unaligned_be64(count64 + 1, arr + OFF);
655 count64 = sg_get_unaligned_be64(arr + OFF);
656 break;
657 default:
658 break;
659 }
660 }
661 if (0 != clock_gettime(CLOCK_MONOTONIC, &end_tm)) {
662 perror("clock_gettime(CLOCK_MONOTONIC)\n");
663 return 1;
664 }
665 elapsed_msecs = (end_tm.tv_sec - start_tm.tv_sec) * 1000;
666 elapsed_msecs += (end_tm.tv_nsec - start_tm.tv_nsec) / 1000000;
667 if (16 == byteswap_sz)
668 printf(" last k=%d, last count16=%u\n", k, count16);
669 else if (32 == byteswap_sz)
670 printf(" last k=%d, last count32=%u\n", k, count32);
671 else
672 printf(" last k=%d, last count64=%" PRIu64 "\n", k, count64);
673 printf("Unaligned elapsed milliseconds: %u\n", elapsed_msecs);
674 count16 = 0;
675 count32 = 0;
676 count64 = 0;
677
678 if (0 != clock_gettime(CLOCK_MONOTONIC, &start_tm)) {
679 perror("clock_gettime(CLOCK_MONOTONIC)\n");
680 return 1;
681 }
682 for (k = 0; k < do_num; ++k) {
683 switch (byteswap_sz) {
684 case 16:
685 count16 = bswap_16(count16 + 1);
686 memcpy(arr + OFF, &count16, 2);
687 memcpy(&count16, arr + OFF, 2);
688 count16 = bswap_16(count16);
689 break;
690 case 32:
691 count32 = bswap_32(count32 + 1);
692 memcpy(arr + OFF, &count32, 4);
693 memcpy(&count32, arr + OFF, 4);
694 count32 = bswap_32(count32);
695 break;
696 case 64:
697 count64 = bswap_64(count64 + 1);
698 memcpy(arr + OFF, &count64, 8);
699 memcpy(&count64, arr + OFF, 8);
700 count64 = bswap_64(count64);
701 break;
702 default:
703 break;
704 }
705 }
706 if (0 != clock_gettime(CLOCK_MONOTONIC, &end_tm)) {
707 perror("clock_gettime(CLOCK_MONOTONIC)\n");
708 return 1;
709 }
710 elapsed_msecs = (end_tm.tv_sec - start_tm.tv_sec) * 1000;
711 elapsed_msecs += (end_tm.tv_nsec - start_tm.tv_nsec) / 1000000;
712 if (16 == byteswap_sz)
713 printf(" last k=%d, last count16=%u\n", k, count16);
714 else if (32 == byteswap_sz)
715 printf(" last k=%d, last count32=%u\n", k, count32);
716 else
717 printf(" last k=%d, last count64=%" PRIu64 "\n", k, count64);
718 printf("Byteswap/memcpy elapsed milliseconds: %u\n", elapsed_msecs);
719 count16 = 0;
720 count32 = 0;
721 count64 = 0;
722 }
723 #endif
724
725 if (0 == did_something)
726 printf("Looks like no tests done, check usage with '-h'\n");
727 ret = (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
728 if (as_json) {
729 if (0 == do_hex2)
730 sgj_js2file(jsp, NULL, ret, stdout);
731 sgj_finish(jsp);
732 }
733 return ret;
734 }
735