1 /*
2  * Copyright (C) 2011 Andrea Mazzoleni
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "portable.h"
19 
20 #include "support.h"
21 
22 /****************************************************************************/
23 /* lock */
24 
25 /**
26  * Locks used externally.
27  */
28 #if HAVE_THREAD
29 static thread_mutex_t msg_lock;
30 static thread_mutex_t memory_lock;
31 #endif
32 
lock_msg(void)33 void lock_msg(void)
34 {
35 #if HAVE_THREAD
36 	thread_mutex_lock(&msg_lock);
37 #endif
38 }
39 
unlock_msg(void)40 void unlock_msg(void)
41 {
42 #if HAVE_THREAD
43 	thread_mutex_unlock(&msg_lock);
44 #endif
45 }
46 
lock_memory(void)47 void lock_memory(void)
48 {
49 #if HAVE_THREAD
50 	thread_mutex_lock(&memory_lock);
51 #endif
52 }
53 
unlock_memory(void)54 void unlock_memory(void)
55 {
56 #if HAVE_THREAD
57 	thread_mutex_unlock(&memory_lock);
58 #endif
59 }
60 
lock_init(void)61 void lock_init(void)
62 {
63 #if HAVE_THREAD
64 	/* initialize the locks as first operation as log_fatal depends on them */
65 	thread_mutex_init(&msg_lock);
66 	thread_mutex_init(&memory_lock);
67 #endif
68 }
69 
lock_done(void)70 void lock_done(void)
71 {
72 #if HAVE_THREAD
73 	thread_mutex_destroy(&msg_lock);
74 	thread_mutex_destroy(&memory_lock);
75 #endif
76 }
77 
78 /****************************************************************************/
79 /* print */
80 
81 int msg_level = 0;
82 FILE* stdlog = 0;
83 
84 /*
85  * Note that in the following functions we always flush both
86  * stdout and stderr, because we want to ensure that they mixes
87  * well when redirected to files
88  *
89  * The buffering is similar at the "line buffered" one, that
90  * is not available on Windows, so we emulate it in this way.
91  *
92  * For stdlog flushing is limited. To ensure flushing the
93  * caller should use log_flush().
94  */
95 
log_fatal(const char * format,...)96 void log_fatal(const char* format, ...)
97 {
98 	va_list ap;
99 
100 	lock_msg();
101 
102 	if (stdlog) {
103 		va_start(ap, format);
104 		fprintf(stdlog, "msg:fatal: ");
105 		vfprintf(stdlog, format, ap);
106 		fflush(stdlog);
107 		va_end(ap);
108 	}
109 
110 	va_start(ap, format);
111 	vfprintf(stderr, format, ap);
112 	fflush(stderr);
113 	va_end(ap);
114 
115 	unlock_msg();
116 }
117 
log_error(const char * format,...)118 void log_error(const char* format, ...)
119 {
120 	va_list ap;
121 
122 	lock_msg();
123 
124 	if (stdlog) {
125 		va_start(ap, format);
126 		fprintf(stdlog, "msg:error: ");
127 		vfprintf(stdlog, format, ap);
128 		fflush(stdlog);
129 		va_end(ap);
130 	} else {
131 		va_start(ap, format);
132 		vfprintf(stderr, format, ap);
133 		fflush(stderr);
134 		va_end(ap);
135 	}
136 
137 	unlock_msg();
138 }
139 
log_expected(const char * format,...)140 void log_expected(const char* format, ...)
141 {
142 	va_list ap;
143 
144 	lock_msg();
145 
146 	if (stdlog) {
147 		va_start(ap, format);
148 		fprintf(stdlog, "msg:expected: ");
149 		vfprintf(stdlog, format, ap);
150 		fflush(stdlog);
151 		va_end(ap);
152 	}
153 
154 	unlock_msg();
155 }
156 
log_tag(const char * format,...)157 void log_tag(const char* format, ...)
158 {
159 	va_list ap;
160 
161 	lock_msg();
162 
163 	if (stdlog) {
164 		va_start(ap, format);
165 		vfprintf(stdlog, format, ap);
166 		/* here we intentionally don't flush */
167 		/* to make the output faster */
168 		va_end(ap);
169 	}
170 
171 	unlock_msg();
172 }
173 
log_flush(void)174 void log_flush(void)
175 {
176 	lock_msg();
177 
178 	if (stdlog)
179 		fflush(stdlog);
180 	fflush(stdout);
181 	fflush(stderr);
182 
183 	unlock_msg();
184 }
185 
msg_status(const char * format,...)186 void msg_status(const char* format, ...)
187 {
188 	va_list ap;
189 
190 	lock_msg();
191 
192 	if (stdlog) {
193 		va_start(ap, format);
194 		fprintf(stdlog, "msg:status: ");
195 		vfprintf(stdlog, format, ap);
196 		fflush(stdlog);
197 		va_end(ap);
198 	}
199 
200 	if (msg_level >= MSG_STATUS) {
201 		va_start(ap, format);
202 		vfprintf(stdout, format, ap);
203 		fflush(stdout);
204 		va_end(ap);
205 	}
206 
207 	unlock_msg();
208 }
209 
msg_info(const char * format,...)210 void msg_info(const char* format, ...)
211 {
212 	va_list ap;
213 
214 	lock_msg();
215 
216 	/* don't output in stdlog as these messages */
217 	/* are always paired with a msg_tag() call */
218 
219 	if (msg_level >= MSG_INFO) {
220 		va_start(ap, format);
221 		vfprintf(stdout, format, ap);
222 		fflush(stdout);
223 		va_end(ap);
224 	}
225 
226 	unlock_msg();
227 }
228 
msg_progress(const char * format,...)229 void msg_progress(const char* format, ...)
230 {
231 	va_list ap;
232 
233 	lock_msg();
234 
235 	if (stdlog) {
236 		va_start(ap, format);
237 		fprintf(stdlog, "msg:progress: ");
238 		vfprintf(stdlog, format, ap);
239 		fflush(stdlog);
240 		va_end(ap);
241 	}
242 
243 	if (msg_level >= MSG_PROGRESS) {
244 		va_start(ap, format);
245 		vfprintf(stdout, format, ap);
246 		fflush(stdout);
247 		va_end(ap);
248 	}
249 
250 	unlock_msg();
251 }
252 
msg_bar(const char * format,...)253 void msg_bar(const char* format, ...)
254 {
255 	va_list ap;
256 
257 	lock_msg();
258 
259 	/* don't output in stdlog as these messages */
260 	/* are intended for screen only */
261 	/* also don't flush stdout as they are intended to be partial messages */
262 
263 	if (msg_level >= MSG_BAR) {
264 		va_start(ap, format);
265 		vfprintf(stdout, format, ap);
266 		va_end(ap);
267 	}
268 
269 	unlock_msg();
270 }
271 
msg_verbose(const char * format,...)272 void msg_verbose(const char* format, ...)
273 {
274 	va_list ap;
275 
276 	lock_msg();
277 
278 	if (stdlog) {
279 		va_start(ap, format);
280 		fprintf(stdlog, "msg:verbose: ");
281 		vfprintf(stdlog, format, ap);
282 		fflush(stdlog);
283 		va_end(ap);
284 	}
285 
286 	if (msg_level >= MSG_VERBOSE) {
287 		va_start(ap, format);
288 		vfprintf(stdout, format, ap);
289 		fflush(stdout);
290 		va_end(ap);
291 	}
292 
293 	unlock_msg();
294 }
295 
msg_flush(void)296 void msg_flush(void)
297 {
298 	lock_msg();
299 
300 	fflush(stdout);
301 	fflush(stderr);
302 
303 	unlock_msg();
304 }
305 
printc(char c,size_t pad)306 void printc(char c, size_t pad)
307 {
308 	while (pad) {
309 		/* group writes in long pieces */
310 		char buf[128];
311 		size_t len = pad;
312 
313 		if (len >= sizeof(buf))
314 			len = sizeof(buf) - 1;
315 
316 		memset(buf, c, len);
317 		buf[len] = 0;
318 
319 		fputs(buf, stdout);
320 
321 		pad -= len;
322 	}
323 }
324 
printr(const char * str,size_t pad)325 void printr(const char* str, size_t pad)
326 {
327 	size_t len;
328 
329 	len = strlen(str);
330 
331 	if (len < pad)
332 		printc(' ', pad - len);
333 
334 	fputs(str, stdout);
335 }
336 
printl(const char * str,size_t pad)337 void printl(const char* str, size_t pad)
338 {
339 	size_t len;
340 
341 	fputs(str, stdout);
342 
343 	len = strlen(str);
344 
345 	if (len < pad)
346 		printc(' ', pad - len);
347 }
348 
printp(double v,size_t pad)349 void printp(double v, size_t pad)
350 {
351 	char buf[64];
352 	const char* s = "%";
353 
354 	if (v > 0.1)
355 		snprintf(buf, sizeof(buf), "%5.2f%s", v, s);
356 	else if (v > 0.01)
357 		snprintf(buf, sizeof(buf), "%6.3f%s", v, s);
358 	else if (v > 0.001)
359 		snprintf(buf, sizeof(buf), "%7.4f%s", v, s);
360 	else if (v > 0.0001)
361 		snprintf(buf, sizeof(buf), "%8.5f%s", v, s);
362 	else if (v > 0.00001)
363 		snprintf(buf, sizeof(buf), "%9.6f%s", v, s);
364 	else if (v > 0.000001)
365 		snprintf(buf, sizeof(buf), "%10.7f%s", v, s);
366 	else if (v > 0.0000001)
367 		snprintf(buf, sizeof(buf), "%11.8f%s", v, s);
368 	else if (v > 0.00000001)
369 		snprintf(buf, sizeof(buf), "%12.9f%s", v, s);
370 	else if (v > 0.000000001)
371 		snprintf(buf, sizeof(buf), "%13.10f%s", v, s);
372 	else if (v > 0.0000000001)
373 		snprintf(buf, sizeof(buf), "%14.11f%s", v, s);
374 	else if (v > 0.00000000001)
375 		snprintf(buf, sizeof(buf), "%15.12f%s", v, s);
376 	else if (v > 0.000000000001)
377 		snprintf(buf, sizeof(buf), "%16.13f%s", v, s);
378 	else
379 		snprintf(buf, sizeof(buf), "%17.14f%s", v, s);
380 	printl(buf, pad);
381 }
382 
383 #define ESCAPE(from,escape,to) \
384 	case from : \
385 		if (p == end) \
386 			goto bail; \
387 		*p++ = escape; \
388 		if (p == end) \
389 			goto bail; \
390 		*p++ = to; \
391 		break
392 
esc_tag(const char * str,char * buffer)393 const char* esc_tag(const char* str, char* buffer)
394 {
395 	char* begin = buffer;
396 	char* end = begin + ESC_MAX;
397 	char* p = begin;
398 
399 	/* copy string with escaping */
400 	while (*str) {
401 		char c = *str;
402 
403 		switch (c) {
404 
405 		ESCAPE('\n', '\\', 'n');
406 		ESCAPE('\r', '\\', 'r');
407 		ESCAPE(':', '\\', 'd');
408 		ESCAPE('\\', '\\', '\\');
409 
410 		default:
411 			if (p == end)
412 				goto bail;
413 			*p++ = c;
414 			break;
415 		}
416 
417 		++str;
418 	}
419 
420 	/* put final 0 */
421 	if (p == end)
422 		goto bail;
423 	*p = 0;
424 
425 	return begin;
426 
427 bail:
428 	/* LCOV_EXCL_START */
429 	log_fatal("Escape for log too long\n");
430 	exit(EXIT_FAILURE);
431 	/* LCOV_EXCL_STOP */
432 }
433 
esc_shell_multi(const char ** str_map,unsigned str_max,char * buffer)434 const char* esc_shell_multi(const char** str_map, unsigned str_max, char* buffer)
435 {
436 	char* begin = buffer;
437 	char* end = begin + ESC_MAX;
438 	char* p = begin;
439 	unsigned str_mac;
440 	const char* str;
441 
442 #ifdef _WIN32
443 	int has_quote = 0;
444 
445 	for (str_mac = 0; str_mac < str_max; ++str_mac) {
446 		str = str_map[str_mac];
447 		if (strchr(str, ' ') != 0)
448 			has_quote = 1;
449 	}
450 
451 	if (has_quote) {
452 		if (p == end)
453 			goto bail;
454 		*p++ = '"';
455 	}
456 #endif
457 
458 	/* copy string with escaping */
459 	str_mac = 0;
460 	str = str_map[str_mac];
461 	while (1) {
462 		/* get the next char */
463 		char c = *str;
464 
465 		/* if one string is finished, go to the next */
466 		while (c == 0 && str_mac + 1 < str_max) {
467 			++str_mac;
468 			str = str_map[str_mac];
469 			c = *str;
470 		}
471 
472 		/* if we read all the strings, stop */
473 		if (!c)
474 			break;
475 
476 		switch (c) {
477 #ifdef _WIN32
478 		/*
479 		 * Windows shell escape
480 		 *
481 		 * The Windows NT Command Shell
482 		 * https://technet.microsoft.com/en-us/library/cc723564.aspx
483 		 */
484 		case '"' :
485 			/* double quote, it needs to be quoted with \ */
486 			if (has_quote) {
487 				/* " -> "\"" -> (close quote)(quoted with \ ")(reopen quote) */
488 				if (p == end)
489 					goto bail;
490 				*p++ = '"';
491 				if (p == end)
492 					goto bail;
493 				*p++ = '\\';
494 				if (p == end)
495 					goto bail;
496 				*p++ = '"';
497 				if (p == end)
498 					goto bail;
499 				*p++ = '"';
500 			} else {
501 				/* " -> \" */
502 				if (p == end)
503 					goto bail;
504 				*p++ = '\\';
505 				if (p == end)
506 					goto bail;
507 				*p++ = '"';
508 			}
509 			break;
510 		case '&' :
511 		case '|' :
512 		case '(' :
513 		case ')' :
514 		case '<' :
515 		case '>' :
516 		case '^' :
517 			/* reserved chars, they need to be quoted with ^ */
518 			if (has_quote) {
519 				if (p == end)
520 					goto bail;
521 				*p++ = c;
522 			} else {
523 				if (p == end)
524 					goto bail;
525 				*p++ = '^';
526 				if (p == end)
527 					goto bail;
528 				*p++ = c;
529 			}
530 			break;
531 #else
532 		/* special chars that need to be quoted */
533 		case ' ' : /* space */
534 		case '~' : /* home */
535 		case '`' : /* command */
536 		case '#' : /* comment */
537 		case '$' : /* variable */
538 		case '&' : /* background job */
539 		case '*' : /* wildcard */
540 		case '(' : /* shell */
541 		case ')' : /* shell */
542 		case '\\': /* quote */
543 		case '|' : /* pipe */
544 		case '[' : /* wildcard */
545 		case ']' : /* wildcard */
546 		case '{' : /* code */
547 		case '}' : /* code */
548 		case ';' : /* separator */
549 		case '\'': /* quote */
550 		case '"' : /* quote */
551 		case '<' : /* redirect */
552 		case '>' : /* redirect */
553 		case '?' : /* wildcard */
554 			if (p == end)
555 				goto bail;
556 			*p++ = '\\';
557 			if (p == end)
558 				goto bail;
559 			*p++ = c;
560 			break;
561 #endif
562 		default :
563 			/* unquoted */
564 			if (p == end)
565 				goto bail;
566 			*p++ = c;
567 			break;
568 		}
569 
570 		++str;
571 	}
572 
573 #ifdef _WIN32
574 	if (has_quote) {
575 		if (p == end)
576 			goto bail;
577 		*p++ = '"';
578 	}
579 #endif
580 
581 	/* put final 0 */
582 	if (p == end)
583 		goto bail;
584 	*p = 0;
585 
586 	return begin;
587 
588 bail:
589 	/* LCOV_EXCL_START */
590 	log_fatal("Escape for shell too long\n");
591 	exit(EXIT_FAILURE);
592 	/* LCOV_EXCL_STOP */
593 }
594 
strpolish(char * s)595 char* strpolish(char* s)
596 {
597 	char* i = s;
598 
599 	while (*i) {
600 		if (isspace(*i) || !isprint(*i))
601 			*i = ' ';
602 		++i;
603 	}
604 
605 	return s;
606 }
607 
strsplit(char ** split_map,unsigned split_max,char * str,const char * delimiters)608 unsigned strsplit(char** split_map, unsigned split_max, char* str, const char* delimiters)
609 {
610 	unsigned mac = 0;
611 
612 	/* skip initial delimiters */
613 	str += strspn(str, delimiters);
614 
615 	while (*str != 0 || mac == split_max) {
616 		/* start of the token */
617 		split_map[mac] = str;
618 		++mac;
619 
620 		/* find the first delimiter or the end of the string */
621 		str += strcspn(str, delimiters);
622 
623 		/* put the final terminator if missing */
624 		if (*str != 0)
625 			*str++ = 0;
626 
627 		/* skip trailing delimiters */
628 		str += strspn(str, delimiters);
629 	}
630 
631 	return mac;
632 }
633 
634 /****************************************************************************/
635 /* path */
636 
pathcpy(char * dst,size_t size,const char * src)637 void pathcpy(char* dst, size_t size, const char* src)
638 {
639 	size_t len = strlen(src);
640 
641 	if (len + 1 > size) {
642 		/* LCOV_EXCL_START */
643 		log_fatal("Path too long '%s'\n", src);
644 		os_abort();
645 		/* LCOV_EXCL_STOP */
646 	}
647 
648 	memcpy(dst, src, len + 1);
649 }
650 
pathcat(char * dst,size_t size,const char * src)651 void pathcat(char* dst, size_t size, const char* src)
652 {
653 	size_t dst_len = strlen(dst);
654 	size_t src_len = strlen(src);
655 
656 	if (dst_len + src_len + 1 > size) {
657 		/* LCOV_EXCL_START */
658 		log_fatal("Path too long '%s%s'\n", dst, src);
659 		os_abort();
660 		/* LCOV_EXCL_STOP */
661 	}
662 
663 	memcpy(dst + dst_len, src, src_len + 1);
664 }
665 
pathcatl(char * dst,size_t dst_len,size_t size,const char * src)666 void pathcatl(char* dst, size_t dst_len, size_t size, const char* src)
667 {
668 	size_t src_len = strlen(src);
669 
670 	if (dst_len + src_len + 1 > size) {
671 		/* LCOV_EXCL_START */
672 		log_fatal("Path too long '%s%s'\n", dst, src);
673 		os_abort();
674 		/* LCOV_EXCL_STOP */
675 	}
676 
677 	memcpy(dst + dst_len, src, src_len + 1);
678 }
679 
pathcatc(char * dst,size_t size,char c)680 void pathcatc(char* dst, size_t size, char c)
681 {
682 	size_t dst_len = strlen(dst);
683 
684 	if (dst_len + 2 > size) {
685 		/* LCOV_EXCL_START */
686 		log_fatal("Path too long '%s%c'\n", dst, c);
687 		os_abort();
688 		/* LCOV_EXCL_STOP */
689 	}
690 
691 	dst[dst_len] = c;
692 	dst[dst_len + 1] = 0;
693 }
694 
pathimport(char * dst,size_t size,const char * src)695 void pathimport(char* dst, size_t size, const char* src)
696 {
697 	pathcpy(dst, size, src);
698 
699 #ifdef _WIN32
700 	/* convert the  Windows dir separator '\' to C '/', */
701 	/* and the Windows escaping  char '^' to the fnmatch '\' */
702 	while (*dst) {
703 		switch (*dst) {
704 		case '\\' :
705 			*dst = '/';
706 			break;
707 		case '^' :
708 			*dst = '\\';
709 			break;
710 		}
711 		++dst;
712 	}
713 #endif
714 }
715 
pathexport(char * dst,size_t size,const char * src)716 void pathexport(char* dst, size_t size, const char* src)
717 {
718 	pathcpy(dst, size, src);
719 
720 #ifdef _WIN32
721 	/* invert the import */
722 	while (*dst) {
723 		switch (*dst) {
724 		case '/' :
725 			*dst = '\\';
726 			break;
727 		case '\\' :
728 			*dst = '^';
729 			break;
730 		}
731 		++dst;
732 	}
733 #endif
734 }
735 
pathprint(char * dst,size_t size,const char * format,...)736 void pathprint(char* dst, size_t size, const char* format, ...)
737 {
738 	size_t len;
739 	va_list ap;
740 
741 	va_start(ap, format);
742 	len = vsnprintf(dst, size, format, ap);
743 	va_end(ap);
744 
745 	if (len >= size) {
746 		/* LCOV_EXCL_START */
747 		if (size > 0) {
748 			dst[size - 1] = 0;
749 			log_fatal("Path too long '%s...'\n", dst);
750 		} else {
751 			log_fatal("Path too long for empty size'\n");
752 		}
753 		os_abort();
754 		/* LCOV_EXCL_STOP */
755 	}
756 }
757 
pathslash(char * dst,size_t size)758 void pathslash(char* dst, size_t size)
759 {
760 	size_t len = strlen(dst);
761 
762 	if (len > 0 && dst[len - 1] != '/') {
763 		if (len + 2 >= size) {
764 			/* LCOV_EXCL_START */
765 			log_fatal("Path too long '%s/'\n", dst);
766 			os_abort();
767 			/* LCOV_EXCL_STOP */
768 		}
769 
770 		dst[len] = '/';
771 		dst[len + 1] = 0;
772 	}
773 }
774 
pathcut(char * dst)775 void pathcut(char* dst)
776 {
777 	char* slash = strrchr(dst, '/');
778 
779 	if (slash)
780 		slash[1] = 0;
781 	else
782 		dst[0] = 0;
783 }
784 
pathcmp(const char * a,const char * b)785 int pathcmp(const char* a, const char* b)
786 {
787 #ifdef _WIN32
788 	char ai[PATH_MAX];
789 	char bi[PATH_MAX];
790 
791 	/* import to convert \ to / */
792 	pathimport(ai, sizeof(ai), a);
793 	pathimport(bi, sizeof(bi), b);
794 
795 	/* case insensitive compare in Windows */
796 	return stricmp(ai, bi);
797 #else
798 	return strcmp(a, b);
799 #endif
800 }
801 
802 /****************************************************************************/
803 /* file-system */
804 
mkancestor(const char * file)805 int mkancestor(const char* file)
806 {
807 	char dir[PATH_MAX];
808 	struct stat st;
809 	char* c;
810 
811 	pathcpy(dir, sizeof(dir), file);
812 
813 	c = strrchr(dir, '/');
814 	if (!c) {
815 		/* no ancestor */
816 		return 0;
817 	}
818 
819 	/* clear the file */
820 	*c = 0;
821 
822 	/* if it's the root dir */
823 	if (*dir == 0) {
824 		/* nothing more to do */
825 		return 0;
826 	}
827 
828 #ifdef _WIN32
829 	/* if it's a drive specification like "C:" */
830 	if (isalpha(dir[0]) && dir[1] == ':' && dir[2] == 0) {
831 		/* nothing more to do */
832 		return 0;
833 	}
834 #endif
835 
836 	/*
837 	 * Check if the dir already exists using lstat().
838 	 *
839 	 * Note that in Windows when dealing with read-only media
840 	 * you cannot try to create the directory, and expecting
841 	 * the EEXIST error because the call will fail with ERROR_WRITE_PROTECTED.
842 	 *
843 	 * Also in Windows it's better to use lstat() than stat() because it
844 	 * doesn't need to open the dir with CreateFile().
845 	 */
846 	if (lstat(dir, &st) == 0) {
847 		/* it already exists */
848 		return 0;
849 	}
850 
851 	/* recursively create them all */
852 	if (mkancestor(dir) != 0) {
853 		/* LCOV_EXCL_START */
854 		return -1;
855 		/* LCOV_EXCL_STOP */
856 	}
857 
858 	/* create it */
859 	if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
860 		/* LCOV_EXCL_START */
861 		log_fatal("Error creating directory '%s'. %s.\n", dir, strerror(errno));
862 		return -1;
863 		/* LCOV_EXCL_STOP */
864 	}
865 
866 	return 0;
867 }
868 
fmtime(int f,int64_t mtime_sec,int mtime_nsec)869 int fmtime(int f, int64_t mtime_sec, int mtime_nsec)
870 {
871 #if HAVE_FUTIMENS
872 	struct timespec tv[2];
873 #else
874 	struct timeval tv[2];
875 #endif
876 	int ret;
877 
878 #if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */
879 	tv[0].tv_sec = mtime_sec;
880 	if (mtime_nsec != STAT_NSEC_INVALID)
881 		tv[0].tv_nsec = mtime_nsec;
882 	else
883 		tv[0].tv_nsec = 0;
884 	tv[1].tv_sec = tv[0].tv_sec;
885 	tv[1].tv_nsec = tv[0].tv_nsec;
886 
887 	ret = futimens(f, tv);
888 #elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */
889 	tv[0].tv_sec = mtime_sec;
890 	if (mtime_nsec != STAT_NSEC_INVALID)
891 		tv[0].tv_usec = mtime_nsec / 1000;
892 	else
893 		tv[0].tv_usec = 0;
894 	tv[1].tv_sec = tv[0].tv_sec;
895 	tv[1].tv_usec = tv[0].tv_usec;
896 
897 	ret = futimes(f, tv);
898 #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */
899 	tv[0].tv_sec = mtime_sec;
900 	if (mtime_nsec != STAT_NSEC_INVALID)
901 		tv[0].tv_usec = mtime_nsec / 1000;
902 	else
903 		tv[0].tv_usec = 0;
904 	tv[1].tv_sec = tv[0].tv_sec;
905 	tv[1].tv_usec = tv[0].tv_usec;
906 
907 	ret = futimesat(f, 0, tv);
908 #else
909 #error No function available to set file timestamps with sub-second precision
910 #endif
911 
912 	return ret;
913 }
914 
lmtime(const char * path,int64_t mtime_sec,int mtime_nsec)915 int lmtime(const char* path, int64_t mtime_sec, int mtime_nsec)
916 {
917 #if HAVE_UTIMENSAT
918 	struct timespec tv[2];
919 #else
920 	struct timeval tv[2];
921 #endif
922 	int ret;
923 
924 #if HAVE_UTIMENSAT /* utimensat() is preferred because it gives nanosecond precision */
925 	tv[0].tv_sec = mtime_sec;
926 	if (mtime_nsec != STAT_NSEC_INVALID)
927 		tv[0].tv_nsec = mtime_nsec;
928 	else
929 		tv[0].tv_nsec = 0;
930 	tv[1].tv_sec = tv[0].tv_sec;
931 	tv[1].tv_nsec = tv[0].tv_nsec;
932 
933 	ret = utimensat(AT_FDCWD, path, tv, AT_SYMLINK_NOFOLLOW);
934 #elif HAVE_LUTIMES /* fallback to lutimes() if nanosecond precision is not available */
935 	tv[0].tv_sec = mtime_sec;
936 	if (mtime_nsec != STAT_NSEC_INVALID)
937 		tv[0].tv_usec = mtime_nsec / 1000;
938 	else
939 		tv[0].tv_usec = 0;
940 	tv[1].tv_sec = tv[0].tv_sec;
941 	tv[1].tv_usec = tv[0].tv_usec;
942 
943 	ret = lutimes(path, tv);
944 #elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */
945 	tv[0].tv_sec = mtime_sec;
946 	if (mtime_nsec != STAT_NSEC_INVALID)
947 		tv[0].tv_usec = mtime_nsec / 1000;
948 	else
949 		tv[0].tv_usec = 0;
950 	tv[1].tv_sec = tv[0].tv_sec;
951 	tv[1].tv_usec = tv[0].tv_usec;
952 
953 	ret = futimesat(AT_FDCWD, path, tv);
954 #else
955 #error No function available to set file timestamps with sub-second precision
956 #endif
957 
958 	return ret;
959 }
960 
961 /****************************************************************************/
962 /* advise */
963 
advise_init(struct advise_struct * advise,int mode)964 void advise_init(struct advise_struct* advise, int mode)
965 {
966 	advise->mode = mode;
967 	advise->dirty_begin = 0;
968 	advise->dirty_end = 0;
969 }
970 
advise_flags(struct advise_struct * advise)971 int advise_flags(struct advise_struct* advise)
972 {
973 	int flags = 0;
974 
975 	if (advise->mode == ADVISE_SEQUENTIAL
976 		|| advise->mode == ADVISE_FLUSH
977 		|| advise->mode == ADVISE_FLUSH_WINDOW
978 		|| advise->mode == ADVISE_DISCARD
979 		|| advise->mode == ADVISE_DISCARD_WINDOW
980 	)
981 		flags |= O_SEQUENTIAL;
982 
983 #if HAVE_DIRECT_IO
984 	if (advise->mode == ADVISE_DIRECT)
985 		flags |= O_DIRECT;
986 #endif
987 
988 	return flags;
989 }
990 
advise_open(struct advise_struct * advise,int f)991 int advise_open(struct advise_struct* advise, int f)
992 {
993 	(void)advise;
994 	(void)f;
995 
996 #if HAVE_POSIX_FADVISE
997 	if (advise->mode == ADVISE_SEQUENTIAL
998 		|| advise->mode == ADVISE_FLUSH
999 		|| advise->mode == ADVISE_FLUSH_WINDOW
1000 		|| advise->mode == ADVISE_DISCARD
1001 		|| advise->mode == ADVISE_DISCARD_WINDOW
1002 	) {
1003 		int ret;
1004 
1005 		/* advise sequential access */
1006 		ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL);
1007 		if (ret == ENOSYS) {
1008 			/* call is not supported, like in armhf, see posix_fadvise manpage */
1009 			ret = 0;
1010 		}
1011 		if (ret != 0) {
1012 			/* LCOV_EXCL_START */
1013 			errno = ret; /* posix_fadvise return the error code */
1014 			return -1;
1015 			/* LCOV_EXCL_STOP */
1016 		}
1017 	}
1018 #endif
1019 
1020 	return 0;
1021 }
1022 
advise_write(struct advise_struct * advise,int f,data_off_t offset,data_off_t size)1023 int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_off_t size)
1024 {
1025 	data_off_t flush_offset;
1026 	data_off_t flush_size;
1027 	data_off_t discard_offset;
1028 	data_off_t discard_size;
1029 
1030 	(void)f;
1031 	(void)flush_offset;
1032 	(void)flush_size;
1033 	(void)discard_offset;
1034 	(void)discard_size;
1035 
1036 	flush_offset = 0;
1037 	flush_size = 0;
1038 	discard_offset = 0;
1039 	discard_size = 0;
1040 
1041 	/*
1042 	 * Follow Linus recommendations about fast writes.
1043 	 *
1044 	 * Linus "Unexpected splice "always copy" behavior observed"
1045 	 * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988070
1046 	 * ---
1047 	 * I have had _very_ good experiences with even a rather trivial
1048 	 * file writer that basically used (iirc) 8MB windows, and the logic was very
1049 	 * trivial:
1050 	 *
1051 	 *  - before writing a new 8M window, do "start writeback"
1052 	 *    (SYNC_FILE_RANGE_WRITE) on the previous window, and do
1053 	 *    a wait (SYNC_FILE_RANGE_WAIT_AFTER) on the window before that.
1054 	 *
1055 	 * in fact, in its simplest form, you can do it like this (this is from my
1056 	 * "overwrite disk images" program that I use on old disks):
1057 	 *
1058 	 * for (index = 0; index < max_index ;index++) {
1059 	 *   if (write(fd, buffer, BUFSIZE) != BUFSIZE)
1060 	 *     break;
1061 	 *   // This won't block, but will start writeout asynchronously
1062 	 *   sync_file_range(fd, index*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WRITE);
1063 	 *   // This does a blocking write-and-wait on any old ranges
1064 	 *   if (index)
1065 	 *     sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER);
1066 	 * }
1067 	 *
1068 	 * and even if you don't actually do a discard (maybe we should add a
1069 	 * SYNC_FILE_RANGE_DISCARD bit, right now you'd need to do a separate
1070 	 * fadvise(FADV_DONTNEED) to throw it out) the system behavior is pretty
1071 	 * nice, because the heavy writer gets good IO performance _and_ leaves only
1072 	 * easy-to-free pages around after itself.
1073 	 * ---
1074 	 *
1075 	 * Linus "Unexpected splice "always copy" behavior observed"
1076 	 * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988176
1077 	 * ---
1078 	 * The behavior for dirty page writeback is _not_ well defined, and
1079 	 * if you do POSIX_FADV_DONTNEED, I would suggest you do it as part of that
1080 	 * writeback logic, ie you do it only on ranges that you have just waited on.
1081 	 *
1082 	 * IOW, in my example, you'd couple the
1083 	 *
1084 	 *   sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER);
1085 	 *
1086 	 * with a
1087 	 *
1088 	 *   posix_fadvise(fd, (index-1)*BUFSIZE, BUFSIZE, POSIX_FADV_DONTNEED);
1089 	 *
1090 	 * afterwards to throw out the pages that you just waited for.
1091 	 * ---
1092 	 */
1093 
1094 	switch (advise->mode) {
1095 	case ADVISE_FLUSH :
1096 		flush_offset = offset;
1097 		flush_size = size;
1098 		break;
1099 	case ADVISE_DISCARD :
1100 		discard_offset = offset;
1101 		discard_size = size;
1102 		break;
1103 	case ADVISE_FLUSH_WINDOW :
1104 		/* if the dirty range can be extended */
1105 		if (advise->dirty_end == offset) {
1106 			/* extent the dirty range */
1107 			advise->dirty_end += size;
1108 
1109 			/* if we reached the window size */
1110 			if (advise->dirty_end - advise->dirty_begin >= ADVISE_WINDOW_SIZE) {
1111 				/* flush the window  */
1112 				flush_offset = advise->dirty_begin;
1113 				flush_size = ADVISE_WINDOW_SIZE;
1114 
1115 				/* remove it from the dirty range */
1116 				advise->dirty_begin += ADVISE_WINDOW_SIZE;
1117 			}
1118 		} else {
1119 			/* otherwise flush the existing dirty */
1120 			flush_offset = advise->dirty_begin;
1121 			flush_size = advise->dirty_end - advise->dirty_begin;
1122 
1123 			/* and set the new range as dirty */
1124 			advise->dirty_begin = offset;
1125 			advise->dirty_end = offset + size;
1126 		}
1127 		break;
1128 	case ADVISE_DISCARD_WINDOW :
1129 		/* if the dirty range can be extended */
1130 		if (advise->dirty_end == offset) {
1131 			/* extent the dirty range */
1132 			advise->dirty_end += size;
1133 
1134 			/* if we reached the double window size */
1135 			if (advise->dirty_end - advise->dirty_begin >= 2 * ADVISE_WINDOW_SIZE) {
1136 				/* discard the first window */
1137 				discard_offset = advise->dirty_begin;
1138 				discard_size = ADVISE_WINDOW_SIZE;
1139 
1140 				/* remove it from the dirty range */
1141 				advise->dirty_begin += ADVISE_WINDOW_SIZE;
1142 
1143 				/* flush the second window */
1144 				flush_offset = advise->dirty_begin;
1145 				flush_size = ADVISE_WINDOW_SIZE;
1146 			}
1147 		} else {
1148 			/* otherwise discard the existing dirty */
1149 			discard_offset = advise->dirty_begin;
1150 			discard_size = advise->dirty_end - advise->dirty_begin;
1151 
1152 			/* and set the new range as dirty */
1153 			advise->dirty_begin = offset;
1154 			advise->dirty_end = offset + size;
1155 		}
1156 		break;
1157 	}
1158 
1159 #if HAVE_SYNC_FILE_RANGE
1160 	if (flush_size != 0) {
1161 		int ret;
1162 
1163 		/* start writing immediately */
1164 		ret = sync_file_range(f, flush_offset, flush_size, SYNC_FILE_RANGE_WRITE);
1165 		if (ret != 0) {
1166 			/* LCOV_EXCL_START */
1167 			return -1;
1168 			/* LCOV_EXCL_STOP */
1169 		}
1170 	}
1171 #endif
1172 
1173 #if HAVE_SYNC_FILE_RANGE && HAVE_POSIX_FADVISE
1174 	if (discard_size != 0) {
1175 		int ret;
1176 
1177 		/* send the data to the disk and wait until it's written */
1178 		ret = sync_file_range(f, discard_offset, discard_size, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER);
1179 		if (ret != 0) {
1180 			/* LCOV_EXCL_START */
1181 			return -1;
1182 			/* LCOV_EXCL_STOP */
1183 		}
1184 
1185 		/* flush the data from the cache */
1186 		ret = posix_fadvise(f, discard_offset, discard_size, POSIX_FADV_DONTNEED);
1187 		/* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */
1188 		if (ret != 0) {
1189 			/* LCOV_EXCL_START */
1190 			errno = ret; /* posix_fadvise return the error code */
1191 			return -1;
1192 			/* LCOV_EXCL_STOP */
1193 		}
1194 	}
1195 #endif
1196 
1197 	return 0;
1198 }
1199 
advise_read(struct advise_struct * advise,int f,data_off_t offset,data_off_t size)1200 int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off_t size)
1201 {
1202 	(void)advise;
1203 	(void)f;
1204 	(void)offset;
1205 	(void)size;
1206 
1207 #if HAVE_POSIX_FADVISE
1208 	if (advise->mode == ADVISE_DISCARD
1209 		|| advise->mode == ADVISE_DISCARD_WINDOW
1210 	) {
1211 		int ret;
1212 
1213 		/* flush the data from the cache */
1214 		ret = posix_fadvise(f, offset, size, POSIX_FADV_DONTNEED);
1215 		/* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */
1216 		if (ret != 0) {
1217 			/* LCOV_EXCL_START */
1218 			errno = ret; /* posix_fadvise return the error code */
1219 			return -1;
1220 			/* LCOV_EXCL_STOP */
1221 		}
1222 	}
1223 #endif
1224 
1225 	/*
1226 	 * Here we cannot call posix_fadvise(..., POSIX_FADV_WILLNEED) for the next block
1227 	 * because it may be blocking.
1228 	 *
1229 	 * Ted Ts'o "posix_fadvise(POSIX_FADV_WILLNEED) waits before returning?"
1230 	 * https://lkml.org/lkml/2010/12/6/122
1231 	 * ---
1232 	 * readahead and posix_fadvise(POSIX_FADV_WILLNEED) work exactly the same
1233 	 * way, and in fact share mostly the same code path (see
1234 	 * force_page_cache_readahead() in mm/readahead.c).
1235 	 *
1236 	 * They are asynchronous in that there is no guarantee the pages will be
1237 	 * in the page cache by the time they return.  But at the same time, they
1238 	 * are not guaranteed to be non-blocking.  That is, the work of doing the
1239 	 * readahead does not take place in a kernel thread.  So if you try to
1240 	 * request I/O than will fit in the request queue, the system call will
1241 	 * block until some I/O is completed so that more I/O requested cam be
1242 	 * loaded onto the request queue.
1243 	 *
1244 	 * The only way to fix this would be to either put the work on a kernel
1245 	 * thread (i.e., some kind of workqueue) or in a userspace thread.  For
1246 	 * ion programmer wondering what to do today, I'd suggest the
1247 	 * latter since it will be more portable across various kernel versions.
1248 	 *
1249 	 * This does leave the question about whether we should change the kernel
1250 	 * to allow readahead() and posix_fadvise(POSIX_FADV_WILLNEED) to be
1251 	 * non-blocking and do this work in a workqueue (or via some kind of
1252 	 * callback/continuation scheme).  My worry is just doing this if a user
1253 	 * application does something crazy, like request gigabytes and gigabytes
1254 	 * of readahead, and then repented of their craziness, there should be a
1255 	 * way of cancelling the readahead request.  Today, the user can just
1256 	 * kill the application.  But if we simply shove the work to a kernel
1257 	 * thread, it becomes a lot harder to cancel the readahead request.  We'd
1258 	 * have to invent a new API, and then have a way to know whether the user
1259 	 * has access to kill a particular readahead request, etc.
1260 	 * ---
1261 	 */
1262 
1263 	return 0;
1264 }
1265 
1266 /****************************************************************************/
1267 /* memory */
1268 
1269 /**
1270  * Total amount of memory allocated.
1271  */
1272 static size_t mcounter;
1273 
malloc_counter_get(void)1274 size_t malloc_counter_get(void)
1275 {
1276 	size_t ret;
1277 
1278 	lock_memory();
1279 
1280 	ret = mcounter;
1281 
1282 	unlock_memory();
1283 
1284 	return ret;
1285 }
1286 
malloc_counter_inc(size_t inc)1287 void malloc_counter_inc(size_t inc)
1288 {
1289 	lock_memory();
1290 
1291 	mcounter += inc;
1292 
1293 	unlock_memory();
1294 }
1295 
1296 /* LCOV_EXCL_START */
malloc_print(int f,const char * str)1297 static ssize_t malloc_print(int f, const char* str)
1298 {
1299 	ssize_t len = 0;
1300 
1301 	while (str[len])
1302 		++len;
1303 	return write(f, str, len);
1304 }
1305 /* LCOV_EXCL_STOP */
1306 
1307 /* LCOV_EXCL_START */
malloc_printn(int f,size_t value)1308 static ssize_t malloc_printn(int f, size_t value)
1309 {
1310 	char buf[32];
1311 	int i;
1312 
1313 	if (!value)
1314 		return write(f, "0", 1);
1315 
1316 	i = sizeof(buf);
1317 	while (value) {
1318 		buf[--i] = (value % 10) + '0';
1319 		value /= 10;
1320 	}
1321 
1322 	return write(f, buf + i, sizeof(buf) - i);
1323 }
1324 /* LCOV_EXCL_STOP */
1325 
1326 /* LCOV_EXCL_START */
malloc_fail(size_t size)1327 void malloc_fail(size_t size)
1328 {
1329 	/* don't use printf to avoid any possible extra allocation */
1330 	int f = 2; /* stderr */
1331 
1332 	malloc_print(f, "Failed for Low Memory!\n");
1333 	malloc_print(f, "Allocating ");
1334 	malloc_printn(f, size);
1335 	malloc_print(f, " bytes.\n");
1336 	malloc_print(f, "Already allocated ");
1337 	malloc_printn(f, malloc_counter_get());
1338 	malloc_print(f, " bytes.\n");
1339 	if (sizeof(void*) == 4) {
1340 		malloc_print(f, "You are currently using a 32 bits executable.\n");
1341 		malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n");
1342 	}
1343 }
1344 /* LCOV_EXCL_STOP */
1345 
malloc_nofail(size_t size)1346 void* malloc_nofail(size_t size)
1347 {
1348 	void* ptr = malloc(size);
1349 
1350 	if (!ptr) {
1351 		/* LCOV_EXCL_START */
1352 		malloc_fail(size);
1353 		exit(EXIT_FAILURE);
1354 		/* LCOV_EXCL_STOP */
1355 	}
1356 
1357 #ifndef CHECKER /* Don't preinitialize when running for valgrind */
1358 	/* Here we preinitialize the memory to ensure that the OS is really allocating it */
1359 	/* and not only reserving the addressable space. */
1360 	/* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process. */
1361 	/* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to */
1362 	/* get a real error from malloc() instead than a process killed. */
1363 	/* Note that calloc() doesn't have the same effect. */
1364 	memset(ptr, 0xA5, size);
1365 #endif
1366 
1367 	malloc_counter_inc(size);
1368 
1369 	return ptr;
1370 }
1371 
calloc_nofail(size_t count,size_t size)1372 void* calloc_nofail(size_t count, size_t size)
1373 {
1374 	void* ptr;
1375 
1376 	size *= count;
1377 
1378 	/* see the note in malloc_nofail() of why we don't use calloc() */
1379 	ptr = malloc(size);
1380 
1381 	if (!ptr) {
1382 		/* LCOV_EXCL_START */
1383 		malloc_fail(size);
1384 		exit(EXIT_FAILURE);
1385 		/* LCOV_EXCL_STOP */
1386 	}
1387 
1388 	memset(ptr, 0, size);
1389 
1390 	malloc_counter_inc(size);
1391 
1392 	return ptr;
1393 }
1394 
strdup_nofail(const char * str)1395 char* strdup_nofail(const char* str)
1396 {
1397 	size_t size;
1398 	char* ptr;
1399 
1400 	size = strlen(str) + 1;
1401 
1402 	ptr = malloc(size);
1403 
1404 	if (!ptr) {
1405 		/* LCOV_EXCL_START */
1406 		malloc_fail(size);
1407 		exit(EXIT_FAILURE);
1408 		/* LCOV_EXCL_STOP */
1409 	}
1410 
1411 	memcpy(ptr, str, size);
1412 
1413 	malloc_counter_inc(size);
1414 
1415 	return ptr;
1416 }
1417 
1418 /****************************************************************************/
1419 /* smartctl */
1420 
1421 /**
1422  * Match a string with the specified pattern.
1423  * Like sscanf() a space match any sequence of spaces.
1424  * Return 0 if it matches.
1425  */
smatch(const char * str,const char * pattern)1426 static int smatch(const char* str, const char* pattern)
1427 {
1428 	while (*pattern) {
1429 		if (isspace(*pattern)) {
1430 			++pattern;
1431 			while (isspace(*str))
1432 				++str;
1433 		} else if (*pattern == *str) {
1434 			++pattern;
1435 			++str;
1436 		} else
1437 			return -1;
1438 	}
1439 
1440 	return 0;
1441 }
1442 
smartctl_attribute(FILE * f,const char * file,const char * name,uint64_t * smart,char * serial,char * vendor,char * model)1443 int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial, char* vendor, char* model)
1444 {
1445 	unsigned i;
1446 	int inside;
1447 
1448 	/* preclear attribute */
1449 	*serial = 0;
1450 	for (i = 0; i < SMART_COUNT; ++i)
1451 		smart[i] = SMART_UNASSIGNED;
1452 
1453 	/* read the file */
1454 	inside = 0;
1455 	while (1) {
1456 		char buf[256];
1457 		unsigned id;
1458 		uint64_t raw;
1459 		char* s;
1460 
1461 		s = fgets(buf, sizeof(buf), f);
1462 		if (s == 0)
1463 			break;
1464 
1465 		/* remove extraneous chars */
1466 		s = strpolish(buf);
1467 
1468 		log_tag("smartctl:%s:%s:out: %s\n", file, name, s);
1469 
1470 		/* skip initial spaces */
1471 		while (isspace(*s))
1472 			++s;
1473 
1474 		if (*s == 0) {
1475 			inside = 0;
1476 		/* common */
1477 		} else if (smatch(s, "Rotation Rate: Solid State") == 0) {
1478 			smart[SMART_ROTATION_RATE] = 0;
1479 		} else if (sscanf(s, "Rotation Rate: %" SCNu64, &smart[SMART_ROTATION_RATE]) == 1) {
1480 		} else if (smatch(s, "User Capacity:") == 0) {
1481 			char* begin = strchr(s, ':');
1482 			char* end = strstr(s, "bytes");
1483 			if (begin != 0 && end != 0 && begin < end) {
1484 				char* p;
1485 				smart[SMART_SIZE] = 0;
1486 				for (p = begin; p != end; ++p) {
1487 					if (isdigit(*p)) {
1488 						smart[SMART_SIZE] *= 10;
1489 						smart[SMART_SIZE] += *p - '0';
1490 					}
1491 				}
1492 			}
1493 		} else if (sscanf(s, "Device Model: %63s %63s", vendor, model) == 2) {
1494 		} else if (sscanf(s, "Device Model: %63s", model) == 1) {
1495 		/* SCSI */
1496 		} else if (sscanf(s, "Serial number: %63s", serial) == 1) { /* note "n" of "number" lower case */
1497 		} else if (sscanf(s, "Elements in grown defect list: %" SCNu64, &smart[SMART_REALLOCATED_SECTOR_COUNT]) == 1) {
1498 		} else if (sscanf(s, "Current Drive Temperature: %" SCNu64, &smart[SMART_TEMPERATURE_CELSIUS]) == 1) {
1499 		} else if (sscanf(s, "Drive Trip Temperature: %" SCNu64, &smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS]) == 1) {
1500 		} else if (sscanf(s, "Accumulated start-stop cycles: %" SCNu64, &smart[SMART_START_STOP_COUNT]) == 1) {
1501 		} else if (sscanf(s, "Accumulated load-unload cycles: %" SCNu64, &smart[SMART_LOAD_CYCLE_COUNT]) == 1) {
1502 		} else if (sscanf(s, "  number of hours powered up = %" SCNu64, &smart[SMART_POWER_ON_HOURS]) == 1) {
1503 		/* ATA */
1504 		} else if (sscanf(s, "Serial Number: %63s", serial) == 1) {
1505 		} else if (smatch(s, "ID#") == 0) {
1506 			inside = 1;
1507 		} else if (smatch(s, "No Errors Logged") == 0) {
1508 			smart[SMART_ERROR] = 0;
1509 		} else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) {
1510 			smart[SMART_ERROR] = raw;
1511 		} else if (inside) {
1512 			if (sscanf(s, "%u %*s %*s %*s %*s %*s %*s %*s %*s %" SCNu64, &id, &raw) != 2) {
1513 				/* LCOV_EXCL_START */
1514 				log_fatal("Invalid smartctl line '%s'.\n", s);
1515 				return -1;
1516 				/* LCOV_EXCL_STOP */
1517 			}
1518 
1519 			if (id >= 256) {
1520 				/* LCOV_EXCL_START */
1521 				log_fatal("Invalid SMART id '%u'.\n", id);
1522 				return -1;
1523 				/* LCOV_EXCL_STOP */
1524 			}
1525 
1526 			smart[id] = raw;
1527 		}
1528 	}
1529 
1530 	return 0;
1531 }
1532 
smartctl_flush(FILE * f,const char * file,const char * name)1533 int smartctl_flush(FILE* f, const char* file, const char* name)
1534 {
1535 	/* read the file */
1536 	while (1) {
1537 		char buf[256];
1538 		char* s;
1539 
1540 		s = fgets(buf, sizeof(buf), f);
1541 		if (s == 0)
1542 			break;
1543 
1544 		/* remove extraneous chars */
1545 		s = strpolish(buf);
1546 
1547 		log_tag("smartctl:%s:%s:out: %s\n", file, name, s);
1548 	}
1549 
1550 	return 0;
1551 }
1552 
1553 /****************************************************************************/
1554 /* thread */
1555 
1556 #if HAVE_THREAD
thread_mutex_init(thread_mutex_t * mutex)1557 void thread_mutex_init(thread_mutex_t* mutex)
1558 {
1559 	if (pthread_mutex_init(mutex, 0) != 0) {
1560 		/* LCOV_EXCL_START */
1561 		log_fatal("Failed call to pthread_mutex_init().\n");
1562 		os_abort();
1563 		/* LCOV_EXCL_STOP */
1564 	}
1565 }
1566 
thread_mutex_destroy(thread_mutex_t * mutex)1567 void thread_mutex_destroy(thread_mutex_t* mutex)
1568 {
1569 	if (pthread_mutex_destroy(mutex) != 0) {
1570 		/* LCOV_EXCL_START */
1571 		log_fatal("Failed call to pthread_mutex_destroy().\n");
1572 		os_abort();
1573 		/* LCOV_EXCL_STOP */
1574 	}
1575 }
1576 
thread_mutex_lock(thread_mutex_t * mutex)1577 void thread_mutex_lock(thread_mutex_t* mutex)
1578 {
1579 	if (pthread_mutex_lock(mutex) != 0) {
1580 		/* LCOV_EXCL_START */
1581 		log_fatal("Failed call to pthread_mutex_lock().\n");
1582 		os_abort();
1583 		/* LCOV_EXCL_STOP */
1584 	}
1585 }
1586 
thread_mutex_unlock(thread_mutex_t * mutex)1587 void thread_mutex_unlock(thread_mutex_t* mutex)
1588 {
1589 	if (pthread_mutex_unlock(mutex) != 0) {
1590 		/* LCOV_EXCL_START */
1591 		log_fatal("Failed call to pthread_mutex_unlock().\n");
1592 		os_abort();
1593 		/* LCOV_EXCL_STOP */
1594 	}
1595 }
1596 
thread_cond_init(thread_cond_t * cond)1597 void thread_cond_init(thread_cond_t* cond)
1598 {
1599 	if (pthread_cond_init(cond, 0) != 0) {
1600 		/* LCOV_EXCL_START */
1601 		log_fatal("Failed call to pthread_cond_init().\n");
1602 		os_abort();
1603 		/* LCOV_EXCL_STOP */
1604 	}
1605 }
1606 
thread_cond_destroy(thread_cond_t * cond)1607 void thread_cond_destroy(thread_cond_t* cond)
1608 {
1609 	if (pthread_cond_destroy(cond) != 0) {
1610 		/* LCOV_EXCL_START */
1611 		log_fatal("Failed call to pthread_cond_destroy().\n");
1612 		os_abort();
1613 		/* LCOV_EXCL_STOP */
1614 	}
1615 }
1616 
thread_cond_signal(thread_cond_t * cond)1617 void thread_cond_signal(thread_cond_t* cond)
1618 {
1619 	if (pthread_cond_signal(cond) != 0) {
1620 		/* LCOV_EXCL_START */
1621 		log_fatal("Failed call to pthread_cond_signal().\n");
1622 		os_abort();
1623 		/* LCOV_EXCL_STOP */
1624 	}
1625 }
1626 
thread_cond_broadcast(thread_cond_t * cond)1627 void thread_cond_broadcast(thread_cond_t* cond)
1628 {
1629 	if (pthread_cond_broadcast(cond) != 0) {
1630 		/* LCOV_EXCL_START */
1631 		log_fatal("Failed call to pthread_cond_broadcast().\n");
1632 		os_abort();
1633 		/* LCOV_EXCL_STOP */
1634 	}
1635 }
1636 
thread_cond_wait(thread_cond_t * cond,thread_mutex_t * mutex)1637 void thread_cond_wait(thread_cond_t* cond, thread_mutex_t* mutex)
1638 {
1639 	if (pthread_cond_wait(cond, mutex) != 0) {
1640 		/* LCOV_EXCL_START */
1641 		log_fatal("Failed call to pthread_cond_wait().\n");
1642 		os_abort();
1643 		/* LCOV_EXCL_STOP */
1644 	}
1645 }
1646 
1647 /**
1648  * Implementation note about conditional variables.
1649  *
1650  * The conditional variables can be signaled inside or outside the mutex,
1651  * what is better it's debatable but in general doing that outside the mutex,
1652  * reduces the number of context switches.
1653  *
1654  * But when testing with helgrind and drd, this disallows such tools to
1655  * to see the dependency between the signal and the wait.
1656  *
1657  * To avoid it we signal everything inside the mutex. And we do this in both
1658  * test mode (with CHECKER defined) and release mode (CHECKER not defined),
1659  * to be on the safe side and avoid any difference in behaviour between test and
1660  * release.
1661  *
1662  * Here some interesting discussion:
1663  *
1664  * Condvars: signal with mutex locked or not?
1665  * http://www.domaigne.com/blog/computing/condvars-signal-with-mutex-locked-or-not/
1666  *
1667  * Calling pthread_cond_signal without locking mutex
1668  * http://stackoverflow.com/questions/4544234/calling-pthread-cond-signal-without-locking-mutex/4544494#4544494
1669  */
1670 
1671 /**
1672  * Control when to signal the condition variables.
1673  */
1674 int thread_cond_signal_outside = 0;
1675 
thread_cond_signal_and_unlock(thread_cond_t * cond,thread_mutex_t * mutex)1676 void thread_cond_signal_and_unlock(thread_cond_t* cond, thread_mutex_t* mutex)
1677 {
1678 	if (thread_cond_signal_outside) {
1679 		/* without the thread checker unlock before signaling, */
1680 		/* this reduces the number of context switches */
1681 		thread_mutex_unlock(mutex);
1682 	}
1683 
1684 	thread_cond_signal(cond);
1685 
1686 	if (!thread_cond_signal_outside) {
1687 		/* with the thread checker unlock after signaling */
1688 		/* to make explicit the condition and mutex relation */
1689 		thread_mutex_unlock(mutex);
1690 	}
1691 }
1692 
thread_cond_broadcast_and_unlock(thread_cond_t * cond,thread_mutex_t * mutex)1693 void thread_cond_broadcast_and_unlock(thread_cond_t* cond, thread_mutex_t* mutex)
1694 {
1695 	if (thread_cond_signal_outside) {
1696 		/* without the thread checker unlock before signaling, */
1697 		/* this reduces the number of context switches */
1698 		thread_mutex_unlock(mutex);
1699 	}
1700 
1701 	thread_cond_broadcast(cond);
1702 
1703 	if (!thread_cond_signal_outside) {
1704 		/* with the thread checker unlock after signaling */
1705 		/* to make explicit the condition and mutex relation */
1706 		thread_mutex_unlock(mutex);
1707 	}
1708 }
1709 
thread_create(thread_id_t * thread,void * (* func)(void *),void * arg)1710 void thread_create(thread_id_t* thread, void* (* func)(void *), void *arg)
1711 {
1712 	if (pthread_create(thread, 0, func, arg) != 0) {
1713 		/* LCOV_EXCL_START */
1714 		log_fatal("Failed call to pthread_create().\n");
1715 		os_abort();
1716 		/* LCOV_EXCL_STOP */
1717 	}
1718 }
1719 
thread_join(thread_id_t thread,void ** retval)1720 void thread_join(thread_id_t thread, void** retval)
1721 {
1722 	if (pthread_join(thread, retval) != 0) {
1723 		/* LCOV_EXCL_START */
1724 		log_fatal("Failed call to pthread_join().\n");
1725 		os_abort();
1726 		/* LCOV_EXCL_STOP */
1727 	}
1728 }
1729 
1730 #endif
1731 
1732