Annotation of embedaddon/bmon/src/utils.c, revision 1.1.1.2
1.1 misho 1: /*
2: * utils.c General purpose utilities
3: *
1.1.1.2 ! misho 4: * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
! 5: * Copyright (c) 2013 Red Hat, Inc.
1.1 misho 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:
1.1.1.2 ! misho 30: void *xcalloc(size_t n, size_t s)
1.1 misho 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:
1.1.1.2 ! misho 42: void *xrealloc(void *p, size_t s)
1.1 misho 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:
1.1.1.2 ! misho 60: float timestamp_to_float(timestamp_t *src)
1.1 misho 61: {
62: return (float) src->tv_sec + ((float) src->tv_usec / 1000000.0f);
63: }
64:
1.1.1.2 ! misho 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)
1.1 misho 71: {
72: dst->tv_sec = (time_t) src;
73: dst->tv_usec = (src - ((float) ((time_t) src))) * 1000000.0f;
74: }
75:
1.1.1.2 ! misho 76: void timestamp_add(timestamp_t *dst, timestamp_t *src1, timestamp_t *src2)
1.1 misho 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:
1.1.1.2 ! misho 87: void timestamp_sub(timestamp_t *dst, timestamp_t *src1, timestamp_t *src2)
1.1 misho 88: {
89: dst->tv_sec = src1->tv_sec - src2->tv_sec;
90: dst->tv_usec = src1->tv_usec - src2->tv_usec;
1.1.1.2 ! misho 91: if (dst->tv_usec < 0) {
1.1 misho 92: dst->tv_sec--;
93: dst->tv_usec += 1000000;
94: }
95: }
96:
1.1.1.2 ! misho 97: int timestamp_le(timestamp_t *a, timestamp_t *b)
1.1 misho 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:
1.1.1.2 ! misho 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)
1.1 misho 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:
1.1.1.2 ! misho 123: void copy_timestamp(timestamp_t *ts1, timestamp_t *ts2)
1.1 misho 124: {
1.1.1.2 ! misho 125: ts1->tv_sec = ts2->tv_sec;
! 126: ts2->tv_usec = ts2->tv_usec;
1.1 misho 127: }
128:
1.1.1.2 ! misho 129: float timestamp_diff(timestamp_t *t1, timestamp_t *t2)
1.1 misho 130: {
1.1.1.2 ! misho 131: float diff;
1.1 misho 132:
1.1.1.2 ! misho 133: diff = t2->tv_sec - t1->tv_sec;
! 134: diff += (((float) t2->tv_usec - (float) t1->tv_usec) / 1000000.0f);
1.1 misho 135:
1.1.1.2 ! misho 136: return diff;
1.1 misho 137: }
138:
1.1.1.2 ! misho 139: #if 0
1.1 misho 140:
141:
1.1.1.2 ! misho 142: float diff_now(timestamp_t *t1)
1.1 misho 143: {
1.1.1.2 ! misho 144: timestamp_t now;
! 145: update_ts(&now);
! 146: return time_diff(t1, &now);
1.1 misho 147: }
148:
1.1.1.2 ! misho 149: const char *xinet_ntop(struct sockaddr *src, char *dst, socklen_t cnt)
1.1 misho 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:
1.1.1.2 ! misho 166: uint64_t parse_size(const char *str)
1.1 misho 167: {
168: char *p;
1.1.1.2 ! misho 169: uint64_t l = strtol(str, &p, 0);
1.1 misho 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
1.1.1.2 ! misho 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>