Annotation of embedaddon/istgt/src/istgt_misc.c, revision 1.1.1.2
1.1 misho 1: /*
1.1.1.2 ! misho 2: * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
1.1 misho 3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17: * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24: * SUCH DAMAGE.
25: *
26: */
27:
28: #ifdef HAVE_CONFIG_H
29: #include "config.h"
30: #endif
31:
32: #include <inttypes.h>
33: #include <stdint.h>
34:
35: #include <ctype.h>
36: #include <stdarg.h>
37: #include <stdio.h>
38: #include <stdlib.h>
39: #include <string.h>
40: #include <syslog.h>
41:
42: #include <unistd.h>
43:
44: #ifdef HAVE_LIBPTHREAD
45: #include <pthread.h>
46: #endif
47: #ifdef HAVE_SCHED
48: #include <sched.h>
49: #endif
50:
51: #include "istgt.h"
52: #include "istgt_misc.h"
53:
1.1.1.2 ! misho 54: #if !defined(__GNUC__)
! 55: #undef __attribute__
! 56: #define __attribute__(x)
! 57: #endif
! 58:
! 59: static void fatal(const char *format, ...) __attribute__((__noreturn__, __format__(__printf__, 1, 2)));
! 60:
1.1 misho 61: static void
62: fatal(const char *format, ...)
63: {
64: char buf[MAX_TMPBUF];
65: va_list ap;
66:
67: va_start(ap, format);
68: vsnprintf(buf, sizeof buf, format, ap);
69: fprintf(stderr, "%s", buf);
70: syslog(LOG_ERR, "%s", buf);
71: va_end(ap);
72: exit(EXIT_FAILURE);
73: }
74:
75: void *
76: xmalloc(size_t size)
77: {
78: void *p;
79:
80: if (size < 1)
81: size = 1;
82: p = malloc(size);
83: if (p == NULL)
84: fatal("no memory\n");
85: return p;
86: }
87:
88: void *
89: xrealloc(void *p, size_t size)
90: {
91: if (size < 1)
92: size = 1;
93: if (p == NULL) {
94: p = malloc(size);
95: } else {
96: p = realloc(p, size);
97: }
98: if (p == NULL)
99: fatal("no memory\n");
100: return p;
101: }
102:
103: void
104: xfree(void *p)
105: {
106: if (p == NULL)
107: return;
108: free(p);
109: }
110:
111: char *
112: xstrdup(const char *s)
113: {
114: char *p;
115: size_t size;
116:
117: if (s == NULL)
118: return NULL;
119: size = strlen(s) + 1;
120: p = xmalloc(size);
121: memcpy(p, s, size - 1);
122: p[size - 1] = '\0';
123: return p;
124: }
125:
126: char *
127: strlwr(char *s)
128: {
129: char *p;
130:
131: if (s == NULL)
132: return NULL;
133:
134: p = s;
135: while (*p != '\0') {
136: *p = tolower((int) *p);
137: p++;
138: }
139: return s;
140: }
141:
142: char *
143: strupr(char *s)
144: {
145: char *p;
146:
147: if (s == NULL)
148: return NULL;
149:
150: p = s;
151: while (*p != '\0') {
152: *p = toupper((int) *p);
153: p++;
154: }
155: return s;
156: }
157:
158: char *
159: strsepq(char **stringp, const char *delim)
160: {
161: char *p, *q, *r;
162: int quoted = 0, bslash = 0;
163:
164: p = *stringp;
165: if (p == NULL)
166: return NULL;
167:
168: r = q = p;
169: while (*q != '\0' && *q != '\n') {
170: /* eat quoted characters */
171: if (bslash) {
172: bslash = 0;
173: *r++ = *q++;
174: continue;
175: } else if (quoted) {
176: if (quoted == '"' && *q == '\\') {
177: bslash = 1;
178: q++;
179: continue;
180: } else if (*q == quoted) {
181: quoted = 0;
182: q++;
183: continue;
184: }
185: *r++ = *q++;
186: continue;
187: } else if (*q == '\\') {
188: bslash = 1;
189: q++;
190: continue;
191: } else if (*q == '"' || *q == '\'') {
192: quoted = *q;
193: q++;
194: continue;
195: }
196:
197: /* separator? */
198: if (strchr(delim, (int) *q) == NULL) {
199: *r++ = *q++;
200: continue;
201: }
202:
203: /* new string */
204: q++;
205: break;
206: }
207: *r = '\0';
208:
209: /* skip tailer */
210: while (*q != '\0' && strchr(delim, (int) *q) != NULL) {
211: q++;
212: }
213: if (*q != '\0') {
214: *stringp = q;
215: } else {
216: *stringp = NULL;
217: }
218:
219: return p;
220: }
221:
222: char *
223: trim_string(char *s)
224: {
225: char *p, *q;
226:
227: if (s == NULL)
228: return NULL;
229:
230: /* remove header */
231: p = s;
232: while (*p != '\0' && isspace((int) *p)) {
233: p++;
234: }
235: /* remove tailer */
236: q = p + strlen(p);
237: while (q - 1 >= p && isspace((int) *(q - 1))) {
238: q--;
239: *q = '\0';
240: }
241: /* if remove header, move */
242: if (p != s) {
243: q = s;
244: while (*p != '\0') {
245: *q++ = *p++;
246: }
247: }
248: return s;
249: }
250:
251: char *
252: escape_string(const char *s)
253: {
254: const char *p;
255: char *q, *r;
256: size_t size;
257:
258: if (s == NULL)
259: return NULL;
260:
261: p = s;
262: size = 0;
263: while (*p != '\0') {
264: if (*p == '"' || *p == '\\' || *p == '\'') {
265: size += 2;
266: } else {
267: size++;
268: }
269: p++;
270: }
271:
272: p = s;
273: r = q = xmalloc(size + 1);
274: while (*p != '\0') {
275: if (*p == '"' || *p == '\\' || *p == '\'') {
276: *q++ = '\\';
277: *q++ = *p++;
278: } else {
279: *q++ = *p++;
280: }
281: }
282: *q++ = '\0';
283: return r;
284: }
285:
286: /* LBA = (M * 60 + S) * 75 + F - 150 */
287: uint32_t
288: istgt_msf2lba(uint32_t msf)
289: {
290: uint32_t lba;
291:
292: lba = ((msf >> 16) & 0xff) * 60 * 75;
293: lba += ((msf >> 8) & 0xff) * 75;
294: lba += msf & 0xff;
295: lba -= 150;
296: return lba;
297: }
298:
299: uint32_t
300: istgt_lba2msf(uint32_t lba)
301: {
302: uint32_t m, s, f;
303:
304: lba += 150;
305: m = (lba / 75) / 60;
306: s = (lba / 75) % 60;
307: f = lba % 75;
308:
309: return ((m << 16) | (s << 8) | f);
310: }
311:
312: uint8_t
313: istgt_dget8(const uint8_t *data)
314: {
315: uint8_t value;
316:
317: value = (data[0] & 0xffU) << 0;
318: return value;
319: }
320:
321: void
322: istgt_dset8(uint8_t *data, uint32_t value)
323: {
324: data[0] = (value >> 0) & 0xffU;
325: }
326:
327: uint16_t
328: istgt_dget16(const uint8_t *data)
329: {
330: uint16_t value;
331:
332: value = (data[0] & 0xffU) << 8;
333: value |= (data[1] & 0xffU) << 0;
334: return value;
335: }
336:
337: void
338: istgt_dset16(uint8_t *data, uint32_t value)
339: {
340: data[0] = (value >> 8) & 0xffU;
341: data[1] = (value >> 0) & 0xffU;
342: }
343:
344: uint32_t
345: istgt_dget24(const uint8_t *data)
346: {
347: uint32_t value;
348:
349: value = (data[0] & 0xffU) << 16;
350: value |= (data[1] & 0xffU) << 8;
351: value |= (data[2] & 0xffU) << 0;
352: return value;
353: }
354:
355: void
356: istgt_dset24(uint8_t *data, uint32_t value)
357: {
358: data[0] = (value >> 16) & 0xffU;
359: data[1] = (value >> 8) & 0xffU;
360: data[2] = (value >> 0) & 0xffU;
361: }
362:
363: uint32_t
364: istgt_dget32(const uint8_t *data)
365: {
366: uint32_t value;
367:
368: value = (data[0] & 0xffU) << 24;
369: value |= (data[1] & 0xffU) << 16;
370: value |= (data[2] & 0xffU) << 8;
371: value |= (data[3] & 0xffU) << 0;
372: return value;
373: }
374:
375: void
376: istgt_dset32(uint8_t *data, uint32_t value)
377: {
378: data[0] = (value >> 24) & 0xffU;
379: data[1] = (value >> 16) & 0xffU;
380: data[2] = (value >> 8) & 0xffU;
381: data[3] = (value >> 0) & 0xffU;
382: }
383:
384: uint64_t
385: istgt_dget48(const uint8_t *data)
386: {
387: uint64_t value;
388:
389: value = (data[0] & 0xffULL) << 40;
390: value |= (data[1] & 0xffULL) << 32;
391: value |= (data[2] & 0xffULL) << 24;
392: value |= (data[3] & 0xffULL) << 16;
393: value |= (data[4] & 0xffULL) << 8;
394: value |= (data[5] & 0xffULL) << 0;
395: return value;
396: }
397:
398: void
399: istgt_dset48(uint8_t *data, uint64_t value)
400: {
401: data[0] = (value >> 40) & 0xffULL;
402: data[1] = (value >> 32) & 0xffULL;
403: data[2] = (value >> 24) & 0xffULL;
404: data[3] = (value >> 16) & 0xffULL;
405: data[4] = (value >> 8) & 0xffULL;
406: data[5] = (value >> 0) & 0xffULL;
407: }
408:
409: uint64_t
410: istgt_dget64(const uint8_t *data)
411: {
412: uint64_t value;
413:
414: value = (data[0] & 0xffULL) << 56;
415: value |= (data[1] & 0xffULL) << 48;
416: value |= (data[2] & 0xffULL) << 40;
417: value |= (data[3] & 0xffULL) << 32;
418: value |= (data[4] & 0xffULL) << 24;
419: value |= (data[5] & 0xffULL) << 16;
420: value |= (data[6] & 0xffULL) << 8;
421: value |= (data[7] & 0xffULL) << 0;
422: return value;
423: }
424:
425: void
426: istgt_dset64(uint8_t *data, uint64_t value)
427: {
428: data[0] = (value >> 56) & 0xffULL;
429: data[1] = (value >> 48) & 0xffULL;
430: data[2] = (value >> 40) & 0xffULL;
431: data[3] = (value >> 32) & 0xffULL;
432: data[4] = (value >> 24) & 0xffULL;
433: data[5] = (value >> 16) & 0xffULL;
434: data[6] = (value >> 8) & 0xffULL;
435: data[7] = (value >> 0) & 0xffULL;
436: }
437:
438: void
439: istgt_dump(const char *label, const uint8_t *buf, size_t len)
440: {
441: istgt_fdump(stdout, label, buf, len);
442: }
443:
444: void
445: istgt_fdump(FILE *fp, const char *label, const uint8_t *buf, size_t len)
446: {
447: char tmpbuf[MAX_TMPBUF];
448: char buf8[8+1];
1.1.1.2 ! misho 449: size_t total;
! 450: size_t idx;
1.1 misho 451:
452: fprintf(fp, "%s\n", label);
453:
454: memset(buf8, 0, sizeof buf8);
455: total = 0;
1.1.1.2 ! misho 456: for (idx = 0; idx < len; idx++) {
! 457: if (idx != 0 && idx % 8 == 0) {
1.1 misho 458: total += snprintf(tmpbuf + total, sizeof tmpbuf - total,
1.1.1.2 ! misho 459: "%s", buf8);
1.1 misho 460: fprintf(fp, "%s\n", tmpbuf);
461: total = 0;
462: }
463: total += snprintf(tmpbuf + total, sizeof tmpbuf - total,
1.1.1.2 ! misho 464: "%2.2x ", buf[idx] & 0xff);
! 465: buf8[idx % 8] = isprint(buf[idx]) ? buf[idx] : '.';
1.1 misho 466: }
1.1.1.2 ! misho 467: for ( ; idx % 8 != 0; idx++) {
1.1 misho 468: total += snprintf(tmpbuf + total, sizeof tmpbuf - total, " ");
1.1.1.2 ! misho 469: buf8[idx % 8] = ' ';
1.1 misho 470: }
471: total += snprintf(tmpbuf + total, sizeof tmpbuf - total, "%s", buf8);
472: fprintf(fp, "%s\n", tmpbuf);
473: fflush(fp);
474: }
475:
476: #ifndef HAVE_SRANDOMDEV
477: #include <time.h>
478: void
479: srandomdev(void)
480: {
481: unsigned long seed;
482: time_t now;
483: pid_t pid;
484:
485: pid = getpid();
486: now = time(NULL);
487: seed = pid ^ now;
488: srandom(seed);
489: }
490: #endif /* HAVE_SRANDOMDEV */
491:
492: #ifndef HAVE_ARC4RANDOM
493: static int istgt_arc4random_initialized = 0;
494:
495: uint32_t
496: arc4random(void)
497: {
498: uint32_t r;
499: uint32_t r1, r2;
500:
501: if (!istgt_arc4random_initialized) {
502: srandomdev();
503: istgt_arc4random_initialized = 1;
504: }
505: r1 = (uint32_t) (random() & 0xffff);
506: r2 = (uint32_t) (random() & 0xffff);
507: r = (r1 << 16) | r2;
508: return r;
509: }
510: #endif /* HAVE_ARC4RANDOM */
511:
512: void
513: istgt_gen_random(uint8_t *buf, size_t len)
514: {
515: #ifdef USE_RANDOM
516: long l;
1.1.1.2 ! misho 517: size_t idx;
1.1 misho 518:
519: srandomdev();
1.1.1.2 ! misho 520: for (idx = 0; idx < len; idx++) {
1.1 misho 521: l = random();
1.1.1.2 ! misho 522: buf[idx] = (uint8_t) l;
1.1 misho 523: }
524: #else
525: uint32_t r;
1.1.1.2 ! misho 526: size_t idx;
1.1 misho 527:
1.1.1.2 ! misho 528: for (idx = 0; idx < len; idx++) {
1.1 misho 529: r = arc4random();
1.1.1.2 ! misho 530: buf[idx] = (uint8_t) r;
1.1 misho 531: }
532: #endif /* USE_RANDOM */
533: }
534:
535: int
536: istgt_bin2hex(char *buf, size_t len, const uint8_t *data, size_t data_len)
537: {
538: const char *digits = "0123456789ABCDEF";
1.1.1.2 ! misho 539: size_t total = 0;
! 540: size_t idx;
1.1 misho 541:
542: if (len < 3)
543: return -1;
544: buf[total] = '0';
545: total++;
546: buf[total] = 'x';
547: total++;
548: buf[total] = '\0';
549:
1.1.1.2 ! misho 550: for (idx = 0; idx < data_len; idx++) {
1.1 misho 551: if (total + 3 > len) {
552: buf[total] = '\0';
553: return - 1;
554: }
1.1.1.2 ! misho 555: buf[total] = digits[(data[idx] >> 4) & 0x0fU];
1.1 misho 556: total++;
1.1.1.2 ! misho 557: buf[total] = digits[data[idx] & 0x0fU];
1.1 misho 558: total++;
559: }
560: buf[total] = '\0';
561: return total;
562: }
563:
564: int
565: istgt_hex2bin(uint8_t *data, size_t data_len, const char *str)
566: {
567: const char *digits = "0123456789ABCDEF";
568: const char *dp;
569: const char *p;
1.1.1.2 ! misho 570: size_t total = 0;
1.1 misho 571: int n0, n1;
572:
573: p = str;
574: if (p[0] != '0' && (p[1] != 'x' && p[1] != 'X'))
575: return -1;
576: p += 2;
577:
578: while (p[0] != '\0' && p[1] != '\0') {
579: if (total >= data_len) {
580: return -1;
581: }
582: dp = strchr(digits, toupper((int) p[0]));
583: if (dp == NULL) {
584: return -1;
585: }
586: n0 = (int) (dp - digits);
587: dp = strchr(digits, toupper((int) p[1]));
588: if (dp == NULL) {
589: return -1;
590: }
591: n1 = (int) (dp - digits);
592:
593: data[total] = (uint8_t) (((n0 & 0x0fU) << 4) | (n1 & 0x0fU));
594: total++;
595: p += 2;
596: }
597: return total;
598: }
599:
600: void
601: istgt_yield(void)
602: {
603: #if defined (HAVE_PTHREAD_YIELD)
604: pthread_yield();
605: #elif defined (HAVE_SCHED_YIELD)
606: sched_yield();
607: #else
608: usleep(0);
609: #endif
610: }
611:
612: #ifndef HAVE_STRLCPY
613: size_t
614: strlcpy(char *dst, const char *src, size_t size)
615: {
616: size_t len;
617:
618: if (dst == NULL)
619: return 0;
620: if (size < 1) {
621: return 0;
622: }
623: len = strlen(src);
624: if (len > size - 1) {
625: len = size - 1;
626: }
627: memcpy(dst, src, len);
628: dst[len] = '\0';
629: return len;
630: }
631: #endif /* HAVE_STRLCPY */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>