Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/ldns/duration.c
39475 views
1
/*
2
* $Id: duration.c 4518 2011-02-24 15:39:09Z matthijs $
3
*
4
* Copyright (c) 2009 NLNet Labs. All rights reserved.
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
*
27
*/
28
29
/**
30
*
31
* This file is copied from the OpenDNSSEC source repository
32
* and only slightly adapted to make it fit.
33
*/
34
35
/**
36
*
37
* Durations.
38
*/
39
40
#include <ldns/config.h>
41
#include <ldns/duration.h>
42
43
#include <stdio.h>
44
#include <stdlib.h>
45
#include <string.h>
46
#include <time.h>
47
48
49
/**
50
* Create a new 'instant' duration.
51
*
52
*/
53
ldns_duration_type*
54
ldns_duration_create(void)
55
{
56
ldns_duration_type* duration;
57
58
duration = malloc(sizeof(ldns_duration_type));
59
if (!duration) {
60
return NULL;
61
}
62
duration->years = 0;
63
duration->months = 0;
64
duration->weeks = 0;
65
duration->days = 0;
66
duration->hours = 0;
67
duration->minutes = 0;
68
duration->seconds = 0;
69
return duration;
70
}
71
72
73
/**
74
* Compare durations.
75
*
76
*/
77
int
78
ldns_duration_compare(const ldns_duration_type* d1, const ldns_duration_type* d2)
79
{
80
if (!d1 && !d2) {
81
return 0;
82
}
83
if (!d1 || !d2) {
84
return d1?-1:1;
85
}
86
87
if (d1->years != d2->years) {
88
return (int) (d1->years - d2->years);
89
}
90
if (d1->months != d2->months) {
91
return (int) (d1->months - d2->months);
92
}
93
if (d1->weeks != d2->weeks) {
94
return (int) (d1->weeks - d2->weeks);
95
}
96
if (d1->days != d2->days) {
97
return (int) (d1->days - d2->days);
98
}
99
if (d1->hours != d2->hours) {
100
return (int) (d1->hours - d2->hours);
101
}
102
if (d1->minutes != d2->minutes) {
103
return (int) (d1->minutes - d2->minutes);
104
}
105
if (d1->seconds != d2->seconds) {
106
return (int) (d1->seconds - d2->seconds);
107
}
108
109
return 0;
110
}
111
112
113
/**
114
* Create a duration from string.
115
*
116
*/
117
ldns_duration_type*
118
ldns_duration_create_from_string(const char* str)
119
{
120
ldns_duration_type* duration = ldns_duration_create();
121
char* P, *X, *T, *W;
122
int not_weeks = 0;
123
124
if (!duration) {
125
return NULL;
126
}
127
if (!str) {
128
return duration;
129
}
130
131
P = strchr(str, 'P');
132
if (!P) {
133
ldns_duration_cleanup(duration);
134
return NULL;
135
}
136
137
T = strchr(str, 'T');
138
X = strchr(str, 'Y');
139
if (X) {
140
duration->years = (time_t) atoi(str+1);
141
str = X;
142
not_weeks = 1;
143
}
144
X = strchr(str, 'M');
145
if (X && (!T || (size_t) (X-P) < (size_t) (T-P))) {
146
duration->months = (time_t) atoi(str+1);
147
str = X;
148
not_weeks = 1;
149
}
150
X = strchr(str, 'D');
151
if (X) {
152
duration->days = (time_t) atoi(str+1);
153
str = X;
154
not_weeks = 1;
155
}
156
if (T) {
157
str = T;
158
not_weeks = 1;
159
}
160
X = strchr(str, 'H');
161
if (X && T) {
162
duration->hours = (time_t) atoi(str+1);
163
str = X;
164
not_weeks = 1;
165
}
166
X = strrchr(str, 'M');
167
if (X && T && (size_t) (X-P) > (size_t) (T-P)) {
168
duration->minutes = (time_t) atoi(str+1);
169
str = X;
170
not_weeks = 1;
171
}
172
X = strchr(str, 'S');
173
if (X && T) {
174
duration->seconds = (time_t) atoi(str+1);
175
str = X;
176
not_weeks = 1;
177
}
178
179
W = strchr(str, 'W');
180
if (W) {
181
if (not_weeks) {
182
ldns_duration_cleanup(duration);
183
return NULL;
184
} else {
185
duration->weeks = (time_t) atoi(str+1);
186
}
187
}
188
return duration;
189
}
190
191
192
/**
193
* Helper func for ldns_duration2string below. If t > 0,
194
* scan print t and c on buf, forwarding buf. Return 0 on success.
195
*/
196
static inline int dur_scan_print(char **buf, char *eob, char c, time_t t)
197
{
198
if (t > 0) {
199
int r = snprintf(*buf, eob - *buf, "%u%c", (unsigned)t, c);
200
if (r < 0 || (*buf += r) >= eob)
201
return -1;
202
}
203
return 0;
204
}
205
206
/**
207
* Convert a duration to a string.
208
*
209
*/
210
char*
211
ldns_duration2string(const ldns_duration_type* d)
212
{
213
/* Max string size should be 7 * 40 + 3 on a 127 bits machine
214
* So 300 (< 273) is more than enough.
215
*/
216
char buf[300] = "P0D", *eob = buf + sizeof(buf), *p = buf + 1;
217
218
if (!d)
219
return NULL;
220
221
if (dur_scan_print(&p, eob, 'Y', d->years)
222
|| dur_scan_print(&p, eob, 'M', d->months)
223
|| dur_scan_print(&p, eob, 'W', d->weeks)
224
|| dur_scan_print(&p, eob, 'D', d->days))
225
return NULL;
226
227
if (d->hours || d->minutes || d->seconds) {
228
if (p > (eob - 2))
229
return NULL; /* Error; no space left on buf for 'T' */
230
231
*p++ = 'T'; *p = 0;
232
if (dur_scan_print(&p, eob, 'H', d->hours)
233
|| dur_scan_print(&p, eob, 'M', d->minutes)
234
|| dur_scan_print(&p, eob, 'S', d->seconds))
235
return NULL;
236
}
237
return strdup(buf);
238
}
239
240
241
/**
242
* Convert a duration to a time.
243
*
244
*/
245
time_t
246
ldns_duration2time(const ldns_duration_type* duration)
247
{
248
time_t period = 0;
249
250
if (duration) {
251
period += (duration->seconds);
252
period += (duration->minutes)*60;
253
period += (duration->hours)*3600;
254
period += (duration->days)*86400;
255
period += (duration->weeks)*86400*7;
256
period += (duration->months)*86400*31;
257
period += (duration->years)*86400*365;
258
259
/* [TODO] calculate correct number of days in this month/year */
260
/*
261
if (duration->months || duration->years) {
262
}
263
*/
264
}
265
return period;
266
}
267
268
269
/**
270
* Clean up duration.
271
*
272
*/
273
void
274
ldns_duration_cleanup(ldns_duration_type* duration)
275
{
276
if (!duration) {
277
return;
278
}
279
free(duration);
280
return;
281
}
282
283