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