1 /***
2 This file is part of eudev, forked from systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdbool.h>
24 #include <time.h>
25
26 #include "time-util.h"
27 #include "macro.h"
28
now(clockid_t clock_id)29 usec_t now(clockid_t clock_id) {
30 struct timespec ts;
31
32 assert_se(clock_gettime(clock_id, &ts) == 0);
33
34 return timespec_load(&ts);
35 }
36
timespec_load(const struct timespec * ts)37 usec_t timespec_load(const struct timespec *ts) {
38 assert(ts);
39
40 if (ts->tv_sec == (time_t) -1 &&
41 ts->tv_nsec == (long) -1)
42 return USEC_INFINITY;
43
44 if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC)
45 return USEC_INFINITY;
46
47 return
48 (usec_t) ts->tv_sec * USEC_PER_SEC +
49 (usec_t) ts->tv_nsec / NSEC_PER_USEC;
50 }
51
timespec_store(struct timespec * ts,usec_t u)52 struct timespec *timespec_store(struct timespec *ts, usec_t u) {
53 assert(ts);
54
55 if (u == USEC_INFINITY) {
56 ts->tv_sec = (time_t) -1;
57 ts->tv_nsec = (long) -1;
58 return ts;
59 }
60
61 ts->tv_sec = (time_t) (u / USEC_PER_SEC);
62 ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC);
63
64 return ts;
65 }
timeval_store(struct timeval * tv,usec_t u)66 struct timeval *timeval_store(struct timeval *tv, usec_t u) {
67 assert(tv);
68
69 if (u == USEC_INFINITY) {
70 tv->tv_sec = (time_t) -1;
71 tv->tv_usec = (suseconds_t) -1;
72 } else {
73 tv->tv_sec = (time_t) (u / USEC_PER_SEC);
74 tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC);
75 }
76
77 return tv;
78 }
79
format_timespan(char * buf,size_t l,usec_t t,usec_t accuracy)80 char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
81 static const struct {
82 const char *suffix;
83 usec_t usec;
84 } table[] = {
85 { "y", USEC_PER_YEAR },
86 { "month", USEC_PER_MONTH },
87 { "w", USEC_PER_WEEK },
88 { "d", USEC_PER_DAY },
89 { "h", USEC_PER_HOUR },
90 { "min", USEC_PER_MINUTE },
91 { "s", USEC_PER_SEC },
92 { "ms", USEC_PER_MSEC },
93 { "us", 1 },
94 };
95
96 unsigned i;
97 char *p = buf;
98 bool something = false;
99
100 assert(buf);
101 assert(l > 0);
102
103 if (t == USEC_INFINITY) {
104 strncpy(p, "infinity", l-1);
105 p[l-1] = 0;
106 return p;
107 }
108
109 if (t <= 0) {
110 strncpy(p, "0", l-1);
111 p[l-1] = 0;
112 return p;
113 }
114
115 /* The result of this function can be parsed with parse_sec */
116
117 for (i = 0; i < ELEMENTSOF(table); i++) {
118 int k = 0;
119 size_t n;
120 bool done = false;
121 usec_t a, b;
122
123 if (t <= 0)
124 break;
125
126 if (t < accuracy && something)
127 break;
128
129 if (t < table[i].usec)
130 continue;
131
132 if (l <= 1)
133 break;
134
135 a = t / table[i].usec;
136 b = t % table[i].usec;
137
138 /* Let's see if we should shows this in dot notation */
139 if (t < USEC_PER_MINUTE && b > 0) {
140 usec_t cc;
141 int j;
142
143 j = 0;
144 for (cc = table[i].usec; cc > 1; cc /= 10)
145 j++;
146
147 for (cc = accuracy; cc > 1; cc /= 10) {
148 b /= 10;
149 j--;
150 }
151
152 if (j > 0) {
153 k = snprintf(p, l,
154 "%s"USEC_FMT".%0*llu%s",
155 p > buf ? " " : "",
156 a,
157 j,
158 (unsigned long long) b,
159 table[i].suffix);
160
161 t = 0;
162 done = true;
163 }
164 }
165
166 /* No? Then let's show it normally */
167 if (!done) {
168 k = snprintf(p, l,
169 "%s"USEC_FMT"%s",
170 p > buf ? " " : "",
171 a,
172 table[i].suffix);
173
174 t = b;
175 }
176
177 n = MIN((size_t) k, l);
178
179 l -= n;
180 p += n;
181
182 something = true;
183 }
184
185 *p = 0;
186
187 return buf;
188 }
189
190