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