File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bmon / src / utils.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 21 14:58:35 2019 UTC (4 years, 8 months ago) by misho
Branches: bmon, MAIN
CVS tags: v4_0p0, HEAD
bmon ver 4.0

    1: /*
    2:  * utils.c             General purpose utilities
    3:  *
    4:  * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
    5:  * Copyright (c) 2013 Red Hat, Inc.
    6:  *
    7:  * Permission is hereby granted, free of charge, to any person obtaining a
    8:  * copy of this software and associated documentation files (the "Software"),
    9:  * to deal in the Software without restriction, including without limitation
   10:  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   11:  * and/or sell copies of the Software, and to permit persons to whom the
   12:  * Software is furnished to do so, subject to the following conditions:
   13:  *
   14:  * The above copyright notice and this permission notice shall be included
   15:  * in all copies or substantial portions of the Software.
   16:  *
   17:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   18:  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   19:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   20:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   21:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   22:  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   23:  * DEALINGS IN THE SOFTWARE.
   24:  */
   25: 
   26: #include <bmon/bmon.h>
   27: #include <bmon/conf.h>
   28: #include <bmon/utils.h>
   29: 
   30: #ifdef __MACH__
   31: #include <mach/clock.h>
   32: #include <mach/mach.h>
   33: #endif
   34: 
   35: void *xcalloc(size_t n, size_t s)
   36: {
   37: 	void *d = calloc(n, s);
   38: 
   39: 	if (NULL == d) {
   40: 		fprintf(stderr, "xalloc: Out of memory\n");
   41: 		exit(ENOMEM);
   42: 	}
   43: 
   44: 	return d;
   45: }
   46: 
   47: void *xrealloc(void *p, size_t s)
   48: {
   49: 	void *d = realloc(p, s);
   50: 
   51: 	if (NULL == d) {
   52: 		fprintf(stderr, "xrealloc: Out of memory!\n");
   53: 		exit(ENOMEM);
   54: 	}
   55: 
   56: 	return d;
   57: }
   58: 
   59: void xfree(void *d)
   60: {
   61: 	if (d)
   62: 		free(d);
   63: }
   64: 
   65: float timestamp_to_float(timestamp_t *src)
   66: {
   67: 	return (float) src->tv_sec + ((float) src->tv_usec / 1000000.0f);
   68: }
   69: 
   70: int64_t timestamp_to_int(timestamp_t *src)
   71: {
   72: 	return (src->tv_sec * 1000000ULL) + src->tv_usec;
   73: }
   74: 
   75: void float_to_timestamp(timestamp_t *dst, float src)
   76: {
   77: 	dst->tv_sec = (time_t) src;
   78: 	dst->tv_usec = (src - ((float) ((time_t) src))) * 1000000.0f;
   79: }
   80: 
   81: void timestamp_add(timestamp_t *dst, timestamp_t *src1, timestamp_t *src2)
   82: {
   83: 	dst->tv_sec = src1->tv_sec + src2->tv_sec;
   84: 	dst->tv_usec = src1->tv_usec + src2->tv_usec;
   85: 
   86: 	if (dst->tv_usec >= 1000000) {
   87: 		dst->tv_sec++;
   88: 		dst->tv_usec -= 1000000;
   89: 	}
   90: }
   91: 
   92: void timestamp_sub(timestamp_t *dst, timestamp_t *src1, timestamp_t *src2)
   93: {
   94: 	dst->tv_sec = src1->tv_sec - src2->tv_sec;
   95: 	dst->tv_usec = src1->tv_usec - src2->tv_usec;
   96: 	if (dst->tv_usec < 0) {
   97: 		dst->tv_sec--;
   98: 		dst->tv_usec += 1000000;
   99: 	}
  100: }
  101: 
  102: int timestamp_le(timestamp_t *a, timestamp_t *b)
  103: {
  104: 	if (a->tv_sec > b->tv_sec)
  105: 		return 0;
  106: 
  107: 	if (a->tv_sec < b->tv_sec || a->tv_usec <= b->tv_usec)
  108: 		return 1;
  109: 	
  110: 	return 0;
  111: }
  112: 
  113: int timestamp_is_negative(timestamp_t *ts)
  114: {
  115: 	return (ts->tv_sec < 0 || ts->tv_usec < 0);
  116: }
  117: 
  118: void update_timestamp(timestamp_t *dst)
  119: {
  120: #ifdef __MACH__
  121: 	clock_serv_t cclock;
  122: 	mach_timespec_t tp;
  123: 
  124: 	host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
  125: 	clock_get_time(cclock, &tp);
  126: 	mach_port_deallocate(mach_task_self(), cclock);
  127: #else
  128: 	struct timespec tp;
  129: 
  130: 	clock_gettime(CLOCK_MONOTONIC, &tp);
  131: #endif
  132: 
  133: 	dst->tv_sec = tp.tv_sec;
  134: 	dst->tv_usec = tp.tv_nsec / 1000;
  135: }
  136: 
  137: void copy_timestamp(timestamp_t *ts1, timestamp_t *ts2)
  138: {
  139: 	ts1->tv_sec = ts2->tv_sec;
  140: 	ts1->tv_usec = ts2->tv_usec;
  141: }
  142: 
  143: float timestamp_diff(timestamp_t *t1, timestamp_t *t2)
  144: {
  145: 	float diff;
  146: 
  147: 	diff = t2->tv_sec - t1->tv_sec;
  148: 	diff += (((float) t2->tv_usec - (float) t1->tv_usec) / 1000000.0f);
  149: 
  150: 	return diff;
  151: }
  152: 
  153: #if 0
  154: 
  155: 
  156: float diff_now(timestamp_t *t1)
  157: {
  158: 	timestamp_t now;
  159: 	update_ts(&now);
  160: 	return time_diff(t1, &now);
  161: }
  162: 
  163: const char *xinet_ntop(struct sockaddr *src, char *dst, socklen_t cnt)
  164: {
  165: 	void *s;
  166: 	int family;
  167: 
  168: 	if (src->sa_family == AF_INET6) {
  169: 		s = &((struct sockaddr_in6 *) src)->sin6_addr;
  170: 		family = AF_INET6;
  171: 	} else if (src->sa_family == AF_INET) {
  172: 		s = &((struct sockaddr_in *) src)->sin_addr;
  173: 		family = AF_INET;
  174: 	} else
  175: 		return NULL;
  176: 
  177: 	return inet_ntop(family, s, dst, cnt);
  178: }
  179: 
  180: uint64_t parse_size(const char *str)
  181: {
  182: 	char *p;
  183: 	uint64_t l = strtol(str, &p, 0);
  184: 	if (p == str)
  185: 		return -1;
  186: 
  187: 	if (*p) {
  188: 		if (!strcasecmp(p, "kb") || !strcasecmp(p, "k"))
  189: 			l *= 1024;
  190: 		else if (!strcasecmp(p, "gb") || !strcasecmp(p, "g"))
  191: 			l *= 1024*1024*1024;
  192: 		else if (!strcasecmp(p, "gbit"))
  193: 			l *= 1024*1024*1024/8;
  194: 		else if (!strcasecmp(p, "mb") || !strcasecmp(p, "m"))
  195: 			l *= 1024*1024;
  196: 		else if (!strcasecmp(p, "mbit"))
  197: 			l *= 1024*1024/8;
  198: 		else if (!strcasecmp(p, "kbit"))
  199: 			l *= 1024/8;
  200: 		else if (strcasecmp(p, "b") != 0)
  201: 			return -1;
  202: 	}
  203: 
  204: 	return l;
  205: }
  206: 
  207: #ifndef HAVE_STRDUP
  208: char *strdup(const char *s)
  209: {
  210: 	char *t = xcalloc(1, strlen(s) + 1);
  211: 	memcpy(t, s, strlen(s));
  212: 	return s;
  213: }
  214: #endif
  215: 
  216: char *timestamp2str(timestamp_t *ts, char *buf, size_t len)
  217: {
  218: 	int i, split[5];
  219: 	char *units[] = {"d", "h", "m", "s", "usec"};
  220: 	time_t sec = ts->tv_sec;
  221: 
  222: #define _SPLIT(idx, unit) if ((split[idx] = sec / unit) > 0) sec %= unit
  223: 	_SPLIT(0, 86400);	/* days */
  224: 	_SPLIT(1, 3600);	/* hours */
  225: 	_SPLIT(2, 60);		/* minutes */
  226: 	_SPLIT(3, 1);		/* seconds */
  227: #undef  _SPLIT
  228: 	split[4] = ts->tv_usec;
  229: 
  230: 	memset(buf, 0, len);
  231: 
  232: 	for (i = 0; i < ARRAY_SIZE(split); i++) {
  233: 		if (split[i] > 0) {
  234: 			char t[64];
  235: 			snprintf(t, sizeof(t), "%s%d%s",
  236: 				 strlen(buf) ? " " : "", split[i], units[i]);
  237: 			strncat(buf, t, len - strlen(buf) - 1);
  238: 		}
  239: 	}
  240: 
  241: 	return buf;
  242: }
  243: 
  244: int parse_date(const char *str, xdate_t *dst)
  245: {
  246: 	time_t now = time(NULL);
  247: 	struct tm *now_tm = localtime(&now);
  248: 	const char *next;
  249: 	char *p;
  250: 	struct tm backup;
  251: 
  252: 	memset(dst, 0, sizeof(*dst));
  253: 
  254: 	if (strchr(str, '-')) {
  255: 		next = strptime(str, "%Y-%m-%d", &dst->d_tm);
  256: 		if (next == NULL ||
  257: 		    (*next != '\0' && *next != ' '))
  258: 			goto invalid_date;
  259: 	} else {
  260: 		dst->d_tm.tm_mday  = now_tm->tm_mday;
  261: 		dst->d_tm.tm_mon   = now_tm->tm_mon;
  262: 		dst->d_tm.tm_year  = now_tm->tm_year;
  263: 		dst->d_tm.tm_wday  = now_tm->tm_wday;
  264: 		dst->d_tm.tm_yday  = now_tm->tm_yday;
  265: 		dst->d_tm.tm_isdst = now_tm->tm_isdst;
  266: 		next = str;
  267: 	}
  268: 
  269: 	if (*next == '\0')
  270: 		return 0;
  271: 
  272: 	while (*next == ' ')
  273: 		next++;
  274: 
  275: 	if (*next == '.')
  276: 		goto read_us;
  277: 
  278: 	/* Make a backup, we can't rely on strptime to not screw
  279: 	 * up what we've got so far. */
  280: 	memset(&backup, 0, sizeof(backup));
  281: 	memcpy(&backup, &dst->d_tm, sizeof(backup));
  282: 
  283: 	next = strptime(next, "%H:%M:%S", &dst->d_tm);
  284: 	if (next == NULL ||
  285: 	    (*next != '\0' && *next != '.'))
  286: 		goto invalid_date;
  287: 
  288: 	dst->d_tm.tm_mday  = backup.tm_mday;
  289: 	dst->d_tm.tm_mon   = backup.tm_mon;
  290: 	dst->d_tm.tm_year  = backup.tm_year;
  291: 	dst->d_tm.tm_wday  = backup.tm_wday;
  292: 	dst->d_tm.tm_yday  = backup.tm_yday;
  293: 	dst->d_tm.tm_isdst = backup.tm_isdst;
  294: 
  295: 	if (*next == '\0')
  296: 		return 0;
  297: read_us:
  298: 	if (*next == '.')
  299: 		next++;
  300: 	else
  301: 		BUG();
  302: 
  303: 	dst->d_usec = strtoul(next, &p, 10);
  304: 
  305: 	if (*p != '\0')
  306: 		goto invalid_date;
  307: 	
  308: 	return 0;
  309: 
  310: invalid_date:
  311: 	fprintf(stderr, "Invalid date \"%s\"\n", str);
  312: 	return -1;
  313: }
  314: 
  315: static inline void print_token(FILE *fd, struct db_token *tok)
  316: {
  317: 	fprintf(fd, "%s", tok->t_name);
  318: 
  319: 	if (tok->t_flags & DB_T_ATTR)
  320: 		fprintf(fd, "<attr>");
  321: }
  322: 
  323: void db_print_filter(FILE *fd, struct db_filter *filter)
  324: {
  325: 	if (filter->f_node)
  326: 		print_token(fd, filter->f_node);
  327: 
  328: 	if (filter->f_group) {
  329: 		fprintf(fd, ".");
  330: 		print_token(fd, filter->f_group);
  331: 	}
  332: 
  333: 	if (filter->f_item) {
  334: 		fprintf(fd, ".");
  335: 		print_token(fd, filter->f_item);
  336: 	}
  337: 
  338: 	if (filter->f_attr) {
  339: 		fprintf(fd, ".");
  340: 		print_token(fd, filter->f_attr);
  341: 	}
  342: 
  343: 	if (filter->f_field)
  344: 		fprintf(fd, "@%s", filter->f_field);
  345: }
  346: 
  347: void *db_filter__scan_string(const char *);
  348: void db_filter__switch_to_buffer(void *);
  349: int db_filter_parse(void);
  350: 
  351: struct db_filter * parse_db_filter(const char *buf)
  352: {
  353: 	struct db_filter *f;
  354: 	struct db_token *tok, *t;
  355: 
  356: 	void *state = db_filter__scan_string(buf);
  357: 	db_filter__switch_to_buffer(state);
  358: 
  359: 	if (db_filter_parse()) {
  360: 		fprintf(stderr, "Failed to parse filter \"%s\"\n", buf);
  361: 		return NULL;
  362: 	}
  363: 
  364: 	tok = db_filter_out; /* generated by yacc */
  365: 	if (tok == NULL)
  366: 		return NULL;
  367: 	
  368: 	f = xcalloc(1, sizeof(*f));
  369: 
  370: 	f->f_node = tok;
  371: 
  372: 	if (!tok->t_next)
  373: 		goto out;
  374: 	tok = tok->t_next;
  375: 
  376: 	if (tok->t_flags & DB_T_ATTR) {
  377: 		fprintf(stderr, "Node may not contain an attribute field\n");
  378: 		goto errout;
  379: 	}
  380: 
  381: 	f->f_group = tok;
  382: 	if (!tok->t_next)
  383: 		goto out;
  384: 	tok = tok->t_next;
  385: 
  386: 	if (tok->t_flags & DB_T_ATTR) {
  387: 		fprintf(stderr, "Group may not contain an attribute field\n");
  388: 		goto errout;
  389: 	}
  390: 
  391: 	f->f_item = tok;
  392: 
  393: 	if (!tok->t_next)
  394: 		goto out;
  395: 	tok = tok->t_next;
  396: 
  397: 	if (tok->t_flags & DB_T_ATTR) {
  398: 		if (!tok->t_name)
  399: 			BUG();
  400: 		f->f_field = tok->t_name;
  401: 		goto out;
  402: 	} else
  403: 		f->f_attr = tok;
  404: 
  405: 	if (!tok->t_next)
  406: 		goto out;
  407: 	tok = tok->t_next;
  408: 
  409: 	if (tok->t_flags & DB_T_ATTR) {
  410: 		if (!tok->t_name)
  411: 			BUG();
  412: 		f->f_field = tok->t_name;
  413: 	} else {
  414: 		fprintf(stderr, "Unexpected additional token after attribute\n");
  415: 		goto errout;
  416: 	}
  417: 
  418: out:
  419: 	/* free unused tokens */
  420: 	for (tok = tok->t_next ; tok; tok = t) {
  421: 		t = tok->t_next;
  422: 		if (tok->t_name)
  423: 			free(tok->t_name);
  424: 		free(tok);
  425: 	}
  426: 
  427: 	return f;
  428: 
  429: errout:
  430: 	free(f);
  431: 	f = NULL;
  432: 	tok = db_filter_out;
  433: 	goto out;
  434: }
  435: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>