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