199ca880aSopenharmony_ci/*** 299ca880aSopenharmony_ci This file is part of eudev, forked from systemd. 399ca880aSopenharmony_ci 499ca880aSopenharmony_ci Copyright 2010 Lennart Poettering 599ca880aSopenharmony_ci 699ca880aSopenharmony_ci systemd is free software; you can redistribute it and/or modify it 799ca880aSopenharmony_ci under the terms of the GNU Lesser General Public License as published by 899ca880aSopenharmony_ci the Free Software Foundation; either version 2.1 of the License, or 999ca880aSopenharmony_ci (at your option) any later version. 1099ca880aSopenharmony_ci 1199ca880aSopenharmony_ci systemd is distributed in the hope that it will be useful, but 1299ca880aSopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1399ca880aSopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1499ca880aSopenharmony_ci Lesser General Public License for more details. 1599ca880aSopenharmony_ci 1699ca880aSopenharmony_ci You should have received a copy of the GNU Lesser General Public License 1799ca880aSopenharmony_ci along with systemd; If not, see <http://www.gnu.org/licenses/>. 1899ca880aSopenharmony_ci***/ 1999ca880aSopenharmony_ci 2099ca880aSopenharmony_ci#include <stdlib.h> 2199ca880aSopenharmony_ci#include <stdio.h> 2299ca880aSopenharmony_ci#include <string.h> 2399ca880aSopenharmony_ci#include <stdbool.h> 2499ca880aSopenharmony_ci#include <time.h> 2599ca880aSopenharmony_ci 2699ca880aSopenharmony_ci#include "time-util.h" 2799ca880aSopenharmony_ci#include "macro.h" 2899ca880aSopenharmony_ci 2999ca880aSopenharmony_ciusec_t now(clockid_t clock_id) { 3099ca880aSopenharmony_ci struct timespec ts; 3199ca880aSopenharmony_ci 3299ca880aSopenharmony_ci assert_se(clock_gettime(clock_id, &ts) == 0); 3399ca880aSopenharmony_ci 3499ca880aSopenharmony_ci return timespec_load(&ts); 3599ca880aSopenharmony_ci} 3699ca880aSopenharmony_ci 3799ca880aSopenharmony_ciusec_t timespec_load(const struct timespec *ts) { 3899ca880aSopenharmony_ci assert(ts); 3999ca880aSopenharmony_ci 4099ca880aSopenharmony_ci if (ts->tv_sec == (time_t) -1 && 4199ca880aSopenharmony_ci ts->tv_nsec == (long) -1) 4299ca880aSopenharmony_ci return USEC_INFINITY; 4399ca880aSopenharmony_ci 4499ca880aSopenharmony_ci if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC) 4599ca880aSopenharmony_ci return USEC_INFINITY; 4699ca880aSopenharmony_ci 4799ca880aSopenharmony_ci return 4899ca880aSopenharmony_ci (usec_t) ts->tv_sec * USEC_PER_SEC + 4999ca880aSopenharmony_ci (usec_t) ts->tv_nsec / NSEC_PER_USEC; 5099ca880aSopenharmony_ci} 5199ca880aSopenharmony_ci 5299ca880aSopenharmony_cistruct timespec *timespec_store(struct timespec *ts, usec_t u) { 5399ca880aSopenharmony_ci assert(ts); 5499ca880aSopenharmony_ci 5599ca880aSopenharmony_ci if (u == USEC_INFINITY) { 5699ca880aSopenharmony_ci ts->tv_sec = (time_t) -1; 5799ca880aSopenharmony_ci ts->tv_nsec = (long) -1; 5899ca880aSopenharmony_ci return ts; 5999ca880aSopenharmony_ci } 6099ca880aSopenharmony_ci 6199ca880aSopenharmony_ci ts->tv_sec = (time_t) (u / USEC_PER_SEC); 6299ca880aSopenharmony_ci ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC); 6399ca880aSopenharmony_ci 6499ca880aSopenharmony_ci return ts; 6599ca880aSopenharmony_ci} 6699ca880aSopenharmony_cistruct timeval *timeval_store(struct timeval *tv, usec_t u) { 6799ca880aSopenharmony_ci assert(tv); 6899ca880aSopenharmony_ci 6999ca880aSopenharmony_ci if (u == USEC_INFINITY) { 7099ca880aSopenharmony_ci tv->tv_sec = (time_t) -1; 7199ca880aSopenharmony_ci tv->tv_usec = (suseconds_t) -1; 7299ca880aSopenharmony_ci } else { 7399ca880aSopenharmony_ci tv->tv_sec = (time_t) (u / USEC_PER_SEC); 7499ca880aSopenharmony_ci tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC); 7599ca880aSopenharmony_ci } 7699ca880aSopenharmony_ci 7799ca880aSopenharmony_ci return tv; 7899ca880aSopenharmony_ci} 7999ca880aSopenharmony_ci 8099ca880aSopenharmony_cichar *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) { 8199ca880aSopenharmony_ci static const struct { 8299ca880aSopenharmony_ci const char *suffix; 8399ca880aSopenharmony_ci usec_t usec; 8499ca880aSopenharmony_ci } table[] = { 8599ca880aSopenharmony_ci { "y", USEC_PER_YEAR }, 8699ca880aSopenharmony_ci { "month", USEC_PER_MONTH }, 8799ca880aSopenharmony_ci { "w", USEC_PER_WEEK }, 8899ca880aSopenharmony_ci { "d", USEC_PER_DAY }, 8999ca880aSopenharmony_ci { "h", USEC_PER_HOUR }, 9099ca880aSopenharmony_ci { "min", USEC_PER_MINUTE }, 9199ca880aSopenharmony_ci { "s", USEC_PER_SEC }, 9299ca880aSopenharmony_ci { "ms", USEC_PER_MSEC }, 9399ca880aSopenharmony_ci { "us", 1 }, 9499ca880aSopenharmony_ci }; 9599ca880aSopenharmony_ci 9699ca880aSopenharmony_ci unsigned i; 9799ca880aSopenharmony_ci char *p = buf; 9899ca880aSopenharmony_ci bool something = false; 9999ca880aSopenharmony_ci 10099ca880aSopenharmony_ci assert(buf); 10199ca880aSopenharmony_ci assert(l > 0); 10299ca880aSopenharmony_ci 10399ca880aSopenharmony_ci if (t == USEC_INFINITY) { 10499ca880aSopenharmony_ci strncpy(p, "infinity", l-1); 10599ca880aSopenharmony_ci p[l-1] = 0; 10699ca880aSopenharmony_ci return p; 10799ca880aSopenharmony_ci } 10899ca880aSopenharmony_ci 10999ca880aSopenharmony_ci if (t <= 0) { 11099ca880aSopenharmony_ci strncpy(p, "0", l-1); 11199ca880aSopenharmony_ci p[l-1] = 0; 11299ca880aSopenharmony_ci return p; 11399ca880aSopenharmony_ci } 11499ca880aSopenharmony_ci 11599ca880aSopenharmony_ci /* The result of this function can be parsed with parse_sec */ 11699ca880aSopenharmony_ci 11799ca880aSopenharmony_ci for (i = 0; i < ELEMENTSOF(table); i++) { 11899ca880aSopenharmony_ci int k = 0; 11999ca880aSopenharmony_ci size_t n; 12099ca880aSopenharmony_ci bool done = false; 12199ca880aSopenharmony_ci usec_t a, b; 12299ca880aSopenharmony_ci 12399ca880aSopenharmony_ci if (t <= 0) 12499ca880aSopenharmony_ci break; 12599ca880aSopenharmony_ci 12699ca880aSopenharmony_ci if (t < accuracy && something) 12799ca880aSopenharmony_ci break; 12899ca880aSopenharmony_ci 12999ca880aSopenharmony_ci if (t < table[i].usec) 13099ca880aSopenharmony_ci continue; 13199ca880aSopenharmony_ci 13299ca880aSopenharmony_ci if (l <= 1) 13399ca880aSopenharmony_ci break; 13499ca880aSopenharmony_ci 13599ca880aSopenharmony_ci a = t / table[i].usec; 13699ca880aSopenharmony_ci b = t % table[i].usec; 13799ca880aSopenharmony_ci 13899ca880aSopenharmony_ci /* Let's see if we should shows this in dot notation */ 13999ca880aSopenharmony_ci if (t < USEC_PER_MINUTE && b > 0) { 14099ca880aSopenharmony_ci usec_t cc; 14199ca880aSopenharmony_ci int j; 14299ca880aSopenharmony_ci 14399ca880aSopenharmony_ci j = 0; 14499ca880aSopenharmony_ci for (cc = table[i].usec; cc > 1; cc /= 10) 14599ca880aSopenharmony_ci j++; 14699ca880aSopenharmony_ci 14799ca880aSopenharmony_ci for (cc = accuracy; cc > 1; cc /= 10) { 14899ca880aSopenharmony_ci b /= 10; 14999ca880aSopenharmony_ci j--; 15099ca880aSopenharmony_ci } 15199ca880aSopenharmony_ci 15299ca880aSopenharmony_ci if (j > 0) { 15399ca880aSopenharmony_ci k = snprintf(p, l, 15499ca880aSopenharmony_ci "%s"USEC_FMT".%0*llu%s", 15599ca880aSopenharmony_ci p > buf ? " " : "", 15699ca880aSopenharmony_ci a, 15799ca880aSopenharmony_ci j, 15899ca880aSopenharmony_ci (unsigned long long) b, 15999ca880aSopenharmony_ci table[i].suffix); 16099ca880aSopenharmony_ci 16199ca880aSopenharmony_ci t = 0; 16299ca880aSopenharmony_ci done = true; 16399ca880aSopenharmony_ci } 16499ca880aSopenharmony_ci } 16599ca880aSopenharmony_ci 16699ca880aSopenharmony_ci /* No? Then let's show it normally */ 16799ca880aSopenharmony_ci if (!done) { 16899ca880aSopenharmony_ci k = snprintf(p, l, 16999ca880aSopenharmony_ci "%s"USEC_FMT"%s", 17099ca880aSopenharmony_ci p > buf ? " " : "", 17199ca880aSopenharmony_ci a, 17299ca880aSopenharmony_ci table[i].suffix); 17399ca880aSopenharmony_ci 17499ca880aSopenharmony_ci t = b; 17599ca880aSopenharmony_ci } 17699ca880aSopenharmony_ci 17799ca880aSopenharmony_ci n = MIN((size_t) k, l); 17899ca880aSopenharmony_ci 17999ca880aSopenharmony_ci l -= n; 18099ca880aSopenharmony_ci p += n; 18199ca880aSopenharmony_ci 18299ca880aSopenharmony_ci something = true; 18399ca880aSopenharmony_ci } 18499ca880aSopenharmony_ci 18599ca880aSopenharmony_ci *p = 0; 18699ca880aSopenharmony_ci 18799ca880aSopenharmony_ci return buf; 18899ca880aSopenharmony_ci} 18999ca880aSopenharmony_ci 190