• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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