File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bmon / src / utils.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jul 30 07:55:27 2014 UTC (9 years, 11 months ago) by misho
Branches: bmon, MAIN
CVS tags: v3_3, HEAD
bmon 3.3

    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: void *xcalloc(size_t n, size_t s)
   31: {
   32: 	void *d = calloc(n, s);
   33: 
   34: 	if (NULL == d) {
   35: 		fprintf(stderr, "xalloc: Out of memory\n");
   36: 		exit(ENOMEM);
   37: 	}
   38: 
   39: 	return d;
   40: }
   41: 
   42: void *xrealloc(void *p, size_t s)
   43: {
   44: 	void *d = realloc(p, s);
   45: 
   46: 	if (NULL == d) {
   47: 		fprintf(stderr, "xrealloc: Out of memory!\n");
   48: 		exit(ENOMEM);
   49: 	}
   50: 
   51: 	return d;
   52: }
   53: 
   54: void xfree(void *d)
   55: {
   56: 	if (d)
   57: 		free(d);
   58: }
   59: 
   60: float timestamp_to_float(timestamp_t *src)
   61: {
   62: 	return (float) src->tv_sec + ((float) src->tv_usec / 1000000.0f);
   63: }
   64: 
   65: int64_t timestamp_to_int(timestamp_t *src)
   66: {
   67: 	return (src->tv_sec * 1000000ULL) + src->tv_usec;
   68: }
   69: 
   70: void float_to_timestamp(timestamp_t *dst, float src)
   71: {
   72: 	dst->tv_sec = (time_t) src;
   73: 	dst->tv_usec = (src - ((float) ((time_t) src))) * 1000000.0f;
   74: }
   75: 
   76: void timestamp_add(timestamp_t *dst, timestamp_t *src1, timestamp_t *src2)
   77: {
   78: 	dst->tv_sec = src1->tv_sec + src2->tv_sec;
   79: 	dst->tv_usec = src1->tv_usec + src2->tv_usec;
   80: 
   81: 	if (dst->tv_usec >= 1000000) {
   82: 		dst->tv_sec++;
   83: 		dst->tv_usec -= 1000000;
   84: 	}
   85: }
   86: 
   87: void timestamp_sub(timestamp_t *dst, timestamp_t *src1, timestamp_t *src2)
   88: {
   89: 	dst->tv_sec = src1->tv_sec - src2->tv_sec;
   90: 	dst->tv_usec = src1->tv_usec - src2->tv_usec;
   91: 	if (dst->tv_usec < 0) {
   92: 		dst->tv_sec--;
   93: 		dst->tv_usec += 1000000;
   94: 	}
   95: }
   96: 
   97: int timestamp_le(timestamp_t *a, timestamp_t *b)
   98: {
   99: 	if (a->tv_sec > b->tv_sec)
  100: 		return 0;
  101: 
  102: 	if (a->tv_sec < b->tv_sec || a->tv_usec <= b->tv_usec)
  103: 		return 1;
  104: 	
  105: 	return 0;
  106: }
  107: 
  108: int timestamp_is_negative(timestamp_t *ts)
  109: {
  110: 	return (ts->tv_sec < 0 || ts->tv_usec < 0);
  111: }
  112: 
  113: void update_timestamp(timestamp_t *dst)
  114: {
  115: 	struct timeval tv;
  116: 
  117: 	gettimeofday(&tv, NULL);
  118: 
  119: 	dst->tv_sec = tv.tv_sec;
  120: 	dst->tv_usec = tv.tv_usec;
  121: }
  122: 
  123: void copy_timestamp(timestamp_t *ts1, timestamp_t *ts2)
  124: {
  125: 	ts1->tv_sec = ts2->tv_sec;
  126: 	ts2->tv_usec = ts2->tv_usec;
  127: }
  128: 
  129: float timestamp_diff(timestamp_t *t1, timestamp_t *t2)
  130: {
  131: 	float diff;
  132: 
  133: 	diff = t2->tv_sec - t1->tv_sec;
  134: 	diff += (((float) t2->tv_usec - (float) t1->tv_usec) / 1000000.0f);
  135: 
  136: 	return diff;
  137: }
  138: 
  139: #if 0
  140: 
  141: 
  142: float diff_now(timestamp_t *t1)
  143: {
  144: 	timestamp_t now;
  145: 	update_ts(&now);
  146: 	return time_diff(t1, &now);
  147: }
  148: 
  149: const char *xinet_ntop(struct sockaddr *src, char *dst, socklen_t cnt)
  150: {
  151: 	void *s;
  152: 	int family;
  153: 
  154: 	if (src->sa_family == AF_INET6) {
  155: 		s = &((struct sockaddr_in6 *) src)->sin6_addr;
  156: 		family = AF_INET6;
  157: 	} else if (src->sa_family == AF_INET) {
  158: 		s = &((struct sockaddr_in *) src)->sin_addr;
  159: 		family = AF_INET;
  160: 	} else
  161: 		return NULL;
  162: 
  163: 	return inet_ntop(family, s, dst, cnt);
  164: }
  165: 
  166: uint64_t parse_size(const char *str)
  167: {
  168: 	char *p;
  169: 	uint64_t l = strtol(str, &p, 0);
  170: 	if (p == str)
  171: 		return -1;
  172: 
  173: 	if (*p) {
  174: 		if (!strcasecmp(p, "kb") || !strcasecmp(p, "k"))
  175: 			l *= 1024;
  176: 		else if (!strcasecmp(p, "gb") || !strcasecmp(p, "g"))
  177: 			l *= 1024*1024*1024;
  178: 		else if (!strcasecmp(p, "gbit"))
  179: 			l *= 1024*1024*1024/8;
  180: 		else if (!strcasecmp(p, "mb") || !strcasecmp(p, "m"))
  181: 			l *= 1024*1024;
  182: 		else if (!strcasecmp(p, "mbit"))
  183: 			l *= 1024*1024/8;
  184: 		else if (!strcasecmp(p, "kbit"))
  185: 			l *= 1024/8;
  186: 		else if (strcasecmp(p, "b") != 0)
  187: 			return -1;
  188: 	}
  189: 
  190: 	return l;
  191: }
  192: 
  193: #ifndef HAVE_STRDUP
  194: char *strdup(const char *s)
  195: {
  196: 	char *t = xcalloc(1, strlen(s) + 1);
  197: 	memcpy(t, s, strlen(s));
  198: 	return s;
  199: }
  200: #endif
  201: 
  202: char *timestamp2str(timestamp_t *ts, char *buf, size_t len)
  203: {
  204: 	int i, split[5];
  205: 	char *units[] = {"d", "h", "m", "s", "usec"};
  206: 	time_t sec = ts->tv_sec;
  207: 
  208: #define _SPLIT(idx, unit) if ((split[idx] = sec / unit) > 0) sec %= unit
  209: 	_SPLIT(0, 86400);	/* days */
  210: 	_SPLIT(1, 3600);	/* hours */
  211: 	_SPLIT(2, 60);		/* minutes */
  212: 	_SPLIT(3, 1);		/* seconds */
  213: #undef  _SPLIT
  214: 	split[4] = ts->tv_usec;
  215: 
  216: 	memset(buf, 0, len);
  217: 
  218: 	for (i = 0; i < ARRAY_SIZE(split); i++) {
  219: 		if (split[i] > 0) {
  220: 			char t[64];
  221: 			snprintf(t, sizeof(t), "%s%d%s",
  222: 				 strlen(buf) ? " " : "", split[i], units[i]);
  223: 			strncat(buf, t, len - strlen(buf) - 1);
  224: 		}
  225: 	}
  226: 
  227: 	return buf;
  228: }
  229: 
  230: int parse_date(const char *str, xdate_t *dst)
  231: {
  232: 	time_t now = time(NULL);
  233: 	struct tm *now_tm = localtime(&now);
  234: 	const char *next;
  235: 	char *p;
  236: 	struct tm backup;
  237: 
  238: 	memset(dst, 0, sizeof(*dst));
  239: 
  240: 	if (strchr(str, '-')) {
  241: 		next = strptime(str, "%Y-%m-%d", &dst->d_tm);
  242: 		if (next == NULL ||
  243: 		    (*next != '\0' && *next != ' '))
  244: 			goto invalid_date;
  245: 	} else {
  246: 		dst->d_tm.tm_mday  = now_tm->tm_mday;
  247: 		dst->d_tm.tm_mon   = now_tm->tm_mon;
  248: 		dst->d_tm.tm_year  = now_tm->tm_year;
  249: 		dst->d_tm.tm_wday  = now_tm->tm_wday;
  250: 		dst->d_tm.tm_yday  = now_tm->tm_yday;
  251: 		dst->d_tm.tm_isdst = now_tm->tm_isdst;
  252: 		next = str;
  253: 	}
  254: 
  255: 	if (*next == '\0')
  256: 		return 0;
  257: 
  258: 	while (*next == ' ')
  259: 		next++;
  260: 
  261: 	if (*next == '.')
  262: 		goto read_us;
  263: 
  264: 	/* Make a backup, we can't rely on strptime to not screw
  265: 	 * up what we've got so far. */
  266: 	memset(&backup, 0, sizeof(backup));
  267: 	memcpy(&backup, &dst->d_tm, sizeof(backup));
  268: 
  269: 	next = strptime(next, "%H:%M:%S", &dst->d_tm);
  270: 	if (next == NULL ||
  271: 	    (*next != '\0' && *next != '.'))
  272: 		goto invalid_date;
  273: 
  274: 	dst->d_tm.tm_mday  = backup.tm_mday;
  275: 	dst->d_tm.tm_mon   = backup.tm_mon;
  276: 	dst->d_tm.tm_year  = backup.tm_year;
  277: 	dst->d_tm.tm_wday  = backup.tm_wday;
  278: 	dst->d_tm.tm_yday  = backup.tm_yday;
  279: 	dst->d_tm.tm_isdst = backup.tm_isdst;
  280: 
  281: 	if (*next == '\0')
  282: 		return 0;
  283: read_us:
  284: 	if (*next == '.')
  285: 		next++;
  286: 	else
  287: 		BUG();
  288: 
  289: 	dst->d_usec = strtoul(next, &p, 10);
  290: 
  291: 	if (*p != '\0')
  292: 		goto invalid_date;
  293: 	
  294: 	return 0;
  295: 
  296: invalid_date:
  297: 	fprintf(stderr, "Invalid date \"%s\"\n", str);
  298: 	return -1;
  299: }
  300: 
  301: static inline void print_token(FILE *fd, struct db_token *tok)
  302: {
  303: 	fprintf(fd, "%s", tok->t_name);
  304: 
  305: 	if (tok->t_flags & DB_T_ATTR)
  306: 		fprintf(fd, "<attr>");
  307: }
  308: 
  309: void db_print_filter(FILE *fd, struct db_filter *filter)
  310: {
  311: 	if (filter->f_node)
  312: 		print_token(fd, filter->f_node);
  313: 
  314: 	if (filter->f_group) {
  315: 		fprintf(fd, ".");
  316: 		print_token(fd, filter->f_group);
  317: 	}
  318: 
  319: 	if (filter->f_item) {
  320: 		fprintf(fd, ".");
  321: 		print_token(fd, filter->f_item);
  322: 	}
  323: 
  324: 	if (filter->f_attr) {
  325: 		fprintf(fd, ".");
  326: 		print_token(fd, filter->f_attr);
  327: 	}
  328: 
  329: 	if (filter->f_field)
  330: 		fprintf(fd, "@%s", filter->f_field);
  331: }
  332: 
  333: void *db_filter__scan_string(const char *);
  334: void db_filter__switch_to_buffer(void *);
  335: int db_filter_parse(void);
  336: 
  337: struct db_filter * parse_db_filter(const char *buf)
  338: {
  339: 	struct db_filter *f;
  340: 	struct db_token *tok, *t;
  341: 
  342: 	void *state = db_filter__scan_string(buf);
  343: 	db_filter__switch_to_buffer(state);
  344: 
  345: 	if (db_filter_parse()) {
  346: 		fprintf(stderr, "Failed to parse filter \"%s\"\n", buf);
  347: 		return NULL;
  348: 	}
  349: 
  350: 	tok = db_filter_out; /* generated by yacc */
  351: 	if (tok == NULL)
  352: 		return NULL;
  353: 	
  354: 	f = xcalloc(1, sizeof(*f));
  355: 
  356: 	f->f_node = tok;
  357: 
  358: 	if (!tok->t_next)
  359: 		goto out;
  360: 	tok = tok->t_next;
  361: 
  362: 	if (tok->t_flags & DB_T_ATTR) {
  363: 		fprintf(stderr, "Node may not contain an attribute field\n");
  364: 		goto errout;
  365: 	}
  366: 
  367: 	f->f_group = tok;
  368: 	if (!tok->t_next)
  369: 		goto out;
  370: 	tok = tok->t_next;
  371: 
  372: 	if (tok->t_flags & DB_T_ATTR) {
  373: 		fprintf(stderr, "Group may not contain an attribute field\n");
  374: 		goto errout;
  375: 	}
  376: 
  377: 	f->f_item = tok;
  378: 
  379: 	if (!tok->t_next)
  380: 		goto out;
  381: 	tok = tok->t_next;
  382: 
  383: 	if (tok->t_flags & DB_T_ATTR) {
  384: 		if (!tok->t_name)
  385: 			BUG();
  386: 		f->f_field = tok->t_name;
  387: 		goto out;
  388: 	} else
  389: 		f->f_attr = tok;
  390: 
  391: 	if (!tok->t_next)
  392: 		goto out;
  393: 	tok = tok->t_next;
  394: 
  395: 	if (tok->t_flags & DB_T_ATTR) {
  396: 		if (!tok->t_name)
  397: 			BUG();
  398: 		f->f_field = tok->t_name;
  399: 	} else {
  400: 		fprintf(stderr, "Unexpected additional token after attribute\n");
  401: 		goto errout;
  402: 	}
  403: 
  404: out:
  405: 	/* free unused tokens */
  406: 	for (tok = tok->t_next ; tok; tok = t) {
  407: 		t = tok->t_next;
  408: 		if (tok->t_name)
  409: 			free(tok->t_name);
  410: 		free(tok);
  411: 	}
  412: 
  413: 	return f;
  414: 
  415: errout:
  416: 	free(f);
  417: 	f = NULL;
  418: 	tok = db_filter_out;
  419: 	goto out;
  420: }
  421: #endif

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