1 /*****
2 *
3 * Copyright (C) 2003-2015 CS-SI. All Rights Reserved.
4 * Author: Nicolas Delon <nicolas.delon@prelude-ids.com>
5 *
6 * This file is part of the Prelude library.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 *****/
23
24 /*
25 * This is required on Solaris so that multiple call to
26 * strptime() won't reset the tm structure.
27 */
28 #define _STRPTIME_DONTZERO
29
30 #include "config.h"
31 #include "libmissing.h"
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <ctype.h>
37 #include <sys/types.h>
38
39 #if defined(__linux__) && ! defined(__USE_XOPEN)
40 # define __USE_XOPEN
41 #endif
42
43 #if TIME_WITH_SYS_TIME
44 # include <sys/time.h>
45 # include <time.h>
46 #else
47 # if HAVE_SYS_TIME_H
48 # include <sys/time.h>
49 # else
50 # include <time.h>
51 # endif
52 #endif
53
54 #include "prelude-inttypes.h"
55 #include "prelude-string.h"
56 #include "prelude-error.h"
57 #include "ntp.h"
58 #include "prelude-log.h"
59 #include "common.h"
60 #include "idmef-time.h"
61
62
parse_time_ymd(struct tm * tm,const char * buf)63 static char *parse_time_ymd(struct tm *tm, const char *buf)
64 {
65 char *ptr;
66
67 ptr = strptime(buf, "%Y-%m-%d", tm);
68 if ( ! ptr )
69 return NULL;
70
71 /*
72 * The IDMEF draft only permits the 'T' variant here
73 */
74 while ( isspace((int) *ptr) )
75 ptr++;
76
77 if ( *ptr == 'T' )
78 ptr++;
79
80 return ptr;
81 }
82
83
84
digit2usec(uint32_t n,int digit_count)85 static int digit2usec(uint32_t n, int digit_count)
86 {
87 int i;
88 const size_t max_digit = 6; /* 999999 */
89
90 if ( digit_count > max_digit )
91 return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "Invalid number of digits for time fraction");
92
93 for ( i = 0; i < (max_digit - digit_count); i++ )
94 n *= 10;
95
96 return n;
97 }
98
99
100
parse_time_hmsu(struct tm * tm,uint32_t * usec,char ** buf)101 static int parse_time_hmsu(struct tm *tm, uint32_t *usec, char **buf)
102 {
103 int fraction;
104 char *eptr = NULL;
105
106 *buf = strptime(*buf, "%H:%M:%S", tm);
107 if ( ! *buf )
108 goto fmterror;
109
110 if ( **buf == '.' || **buf == ',' ) {
111 (*buf)++;
112
113 fraction = strtoul(*buf, &eptr, 10);
114 if ( eptr == *buf )
115 goto fmterror;
116
117 fraction = digit2usec(fraction, eptr - *buf);
118 if ( fraction < 0 )
119 return fraction;
120
121 *buf = eptr;
122 *usec = fraction;
123 }
124
125 return 0;
126
127 fmterror:
128 return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "error parsing time field, format should be: HH:MM:SS(.fraction)");
129 }
130
131
132
parse_time_gmt(struct tm * tm,int32_t * gmtoff,const char * buf)133 static int parse_time_gmt(struct tm *tm, int32_t *gmtoff, const char *buf)
134 {
135 int ret;
136 unsigned int offset_hour, offset_min;
137
138 /*
139 * if UTC, do nothing.
140 */
141 if ( *buf == 'Z' )
142 return 0;
143
144 ret = sscanf(buf + 1, "%2u:%2u", &offset_hour, &offset_min);
145 if ( ret != 2 )
146 return -1;
147
148 if ( *buf == '+' ) {
149 tm->tm_min -= offset_min;
150 tm->tm_hour -= offset_hour;
151 *gmtoff = offset_hour * 3600 + offset_min * 60;
152 }
153
154 else if ( *buf == '-' ) {
155 tm->tm_min += offset_min;
156 tm->tm_hour += offset_hour;
157 *gmtoff = - (offset_hour * 3600 + offset_min * 60);
158 }
159
160 else
161 return -1;
162
163 return 0;
164 }
165
166
167
168 /**
169 * idmef_time_set_from_string:
170 * @time: Pointer to an #idmef_time_t object.
171 * @buf: Pointer to a string describing a time in an IDMEF conforming format.
172 *
173 * Fills @time object with information retrieved from the user provided
174 * @buf, containing a string describing a time in a format conforming
175 * to the IDMEF definition (v. 0.10, section 3.2.6).
176 *
177 * Additionally, the provided time might be separated with white spaces,
178 * instead of the IDMEF defined 'T' character.
179 *
180 * If there is no UTC offset specified, we assume that the provided
181 * time is local, and compute the GMT offset by ourselve.
182 *
183 * Returns: 0 on success, a negative value if an error occured.
184 */
idmef_time_set_from_string(idmef_time_t * time,const char * buf)185 int idmef_time_set_from_string(idmef_time_t *time, const char *buf)
186 {
187 int ret;
188 char *ptr;
189 struct tm tm;
190 prelude_bool_t miss_gmt = FALSE;
191
192 prelude_return_val_if_fail(time, prelude_error(PRELUDE_ERROR_ASSERTION));
193 prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
194
195 memset(&tm, 0, sizeof(tm));
196 tm.tm_isdst = -1;
197
198 ptr = parse_time_ymd(&tm, buf);
199 if ( ! ptr )
200 return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "error parsing date field, format should be: YY-MM-DD");
201
202 time->usec = 0;
203 time->gmt_offset = 0;
204
205 if ( *ptr ) {
206 ret = parse_time_hmsu(&tm, &time->usec, &ptr);
207 if ( ret < 0 )
208 return ret;
209
210 miss_gmt = TRUE;
211 if ( *ptr ) {
212 ret = parse_time_gmt(&tm, &time->gmt_offset, ptr);
213 if ( ret < 0 )
214 return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "error parsing GMT offset field (Z)?(+|-)?HH:MM");
215
216 miss_gmt = FALSE;
217 }
218 }
219
220 if ( miss_gmt ) {
221 long gmtoff;
222 prelude_get_gmt_offset_from_tm(&tm, &gmtoff);
223 time->gmt_offset = (int32_t) gmtoff;
224 }
225
226 time->sec = miss_gmt ? mktime(&tm) : prelude_timegm(&tm);
227 return 0;
228 }
229
230
231
232 /**
233 * idmef_time_new_from_string:
234 * @time: Address where to store the created #idmef_time_t object.
235 * @buf: Pointer to a string describing a time in an IDMEF conforming format.
236 *
237 * Creates an #idmef_time_t object filled with information retrieved
238 * from the user provided @buf, containing a string describing a time in a format
239 * conforming to the IDMEF definition (v. 0.10, section 3.2.6).
240 *
241 * Additionally, the provided time might be separated with white spaces, instead
242 * of the IDMEF define 'T' character. The format might not specify a timezone
243 * (will assume UTC in this case).
244 *
245 * The resulting #idmef_time_t object is stored in @time.
246 *
247 * Returns: 0 on success, a negative value if an error occured.
248 */
idmef_time_new_from_string(idmef_time_t ** time,const char * buf)249 int idmef_time_new_from_string(idmef_time_t **time, const char *buf)
250 {
251 int ret;
252
253 prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
254
255 ret = idmef_time_new(time);
256 if ( ret < 0 )
257 return ret;
258
259 ret = idmef_time_set_from_string(*time, buf);
260 if ( ret < 0 ) {
261 free(*time);
262 return ret;
263 }
264
265 return 0;
266 }
267
268
269
270 /**
271 * idmef_time_set_from_ntpstamp:
272 * @time: Pointer to a #idmef_time_t object.
273 * @buf: Pointer to a string containing an NTP timestamp.
274 *
275 * Fills the @time object with information provided within the @buf NTP timestamp.
276 *
277 * Returns: 0 on success, a negative value if an error occured.
278 */
idmef_time_set_from_ntpstamp(idmef_time_t * time,const char * buf)279 int idmef_time_set_from_ntpstamp(idmef_time_t *time, const char *buf)
280 {
281 l_fp ts;
282 struct timeval tv;
283 unsigned ts_mask = TS_MASK;
284 unsigned ts_roundbit = TS_ROUNDBIT;
285
286 prelude_return_val_if_fail(time, prelude_error(PRELUDE_ERROR_ASSERTION));
287 prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
288
289 if ( sscanf(buf, "%x.%x", &ts.l_ui, &ts.l_uf) < 2 )
290 return -1;
291
292 /*
293 * This transformation is a reverse form of the one found in
294 * idmef_get_ntp_timestamp()
295 */
296 ts.l_ui -= JAN_1970;
297 ts.l_uf -= ts_roundbit;
298 ts.l_uf &= ts_mask;
299 TSTOTV(&ts, &tv);
300
301 time->sec = tv.tv_sec;
302 time->usec = tv.tv_usec;
303 time->gmt_offset = 0;
304
305 return 0;
306 }
307
308
309
310 /**
311 * idmef_time_to_ntpstamp:
312 * @time: Pointer to an IDMEF time structure.
313 * @out: Pointer to a #prelude_string_t output buffer.
314 *
315 * Translates @time to an user readable NTP timestamp string,
316 * conforming to the IDMEF defined time format.
317 *
318 * Returns: number of bytes written on success, a negative value if an error occured.
319 */
idmef_time_to_ntpstamp(const idmef_time_t * time,prelude_string_t * out)320 int idmef_time_to_ntpstamp(const idmef_time_t *time, prelude_string_t *out)
321 {
322 l_fp ts;
323 struct timeval tv;
324 unsigned ts_mask = TS_MASK; /* defaults to 20 bits (us) */
325 unsigned ts_roundbit = TS_ROUNDBIT; /* defaults to 20 bits (us) */
326 int ret;
327
328 prelude_return_val_if_fail(time, prelude_error(PRELUDE_ERROR_ASSERTION));
329 prelude_return_val_if_fail(out, prelude_error(PRELUDE_ERROR_ASSERTION));
330
331 tv.tv_sec = idmef_time_get_sec(time);
332 tv.tv_usec = idmef_time_get_usec(time);
333
334 sTVTOTS(&tv, &ts);
335
336 ts.l_ui += JAN_1970; /* make it time since 1900 */
337 ts.l_uf += ts_roundbit;
338 ts.l_uf &= ts_mask;
339
340 ret = prelude_string_sprintf(out, "0x%08lx.0x%08lx", (unsigned long) ts.l_ui, (unsigned long) ts.l_uf);
341
342 return ret;
343 }
344
345
346
347 /**
348 * idmef_time_to_string:
349 * @time: Pointer to an IDMEF time structure.
350 * @out: Pointer to a #prelude_string_t output buffer.
351 *
352 * Translates @time to an user readable string conforming to the IDMEF
353 * defined time format.
354 *
355 * Returns: number of bytes written on success, a negative value if an error occured.
356 */
idmef_time_to_string(const idmef_time_t * time,prelude_string_t * out)357 int idmef_time_to_string(const idmef_time_t *time, prelude_string_t *out)
358 {
359 time_t t;
360 struct tm utc;
361 uint32_t hour_off, min_off;
362
363 prelude_return_val_if_fail(time, prelude_error(PRELUDE_ERROR_ASSERTION));
364 prelude_return_val_if_fail(out, prelude_error(PRELUDE_ERROR_ASSERTION));
365
366 t = time->sec + time->gmt_offset;
367
368 if ( ! gmtime_r((const time_t *) &t, &utc) )
369 return prelude_error_from_errno(errno);
370
371 hour_off = time->gmt_offset / 3600;
372 min_off = time->gmt_offset % 3600 / 60;
373
374 return prelude_string_sprintf(out, "%d-%.2d-%.2dT%.2d:%.2d:%.2d.%02u%+.2d:%.2d",
375 utc.tm_year + 1900, utc.tm_mon + 1, utc.tm_mday,
376 utc.tm_hour, utc.tm_min, utc.tm_sec, idmef_time_get_usec(time),
377 hour_off, min_off);
378 }
379
380
381
382
383 /**
384 * idmef_time_new_from_ntpstamp:
385 * @time: Address where to store the created #idmef_time_t object.
386 * @buf: Pointer to a string containing an NTP timestamp.
387 *
388 * Creates an #idmef_time_t object filled with information provided
389 * from the @buf NTP timestamp, and stores it in @time.
390 *
391 * Returns: 0 on success, a negative value if an error occured.
392 */
idmef_time_new_from_ntpstamp(idmef_time_t ** time,const char * buf)393 int idmef_time_new_from_ntpstamp(idmef_time_t **time, const char *buf)
394 {
395 int ret;
396
397 prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
398
399 ret = idmef_time_new(time);
400 if ( ret < 0 )
401 return ret;
402
403 ret = idmef_time_set_from_ntpstamp(*time, buf);
404 if ( ret < 0 ) {
405 free(*time);
406 return ret;
407 }
408
409 return 0;
410 }
411
412
413
414 /**
415 * idmef_time_set_from_timeval:
416 * @time: Pointer to an #idmef_time_t object.
417 * @tv: Pointer to a struct timeval (see gettimeofday()).
418 *
419 * Fills @time object filled with information provided within the @tv structure.
420 *
421 * Returns: 0 on success, a negative value if an error occured.
422 */
idmef_time_set_from_timeval(idmef_time_t * time,const struct timeval * tv)423 int idmef_time_set_from_timeval(idmef_time_t *time, const struct timeval *tv)
424 {
425 int ret;
426 long gmtoff;
427
428 prelude_return_val_if_fail(time, prelude_error(PRELUDE_ERROR_ASSERTION));
429 prelude_return_val_if_fail(tv, prelude_error(PRELUDE_ERROR_ASSERTION));
430
431 ret = prelude_get_gmt_offset_from_time((const time_t *) &tv->tv_sec, &gmtoff);
432 if ( ret < 0 )
433 return ret;
434
435 time->sec = tv->tv_sec;
436 time->usec = tv->tv_usec;
437 time->gmt_offset = (int32_t) gmtoff;
438
439 return 0;
440 }
441
442
443
444 /**
445 * idmef_time_new_from_timeval:
446 * @time: Address where to store the created #idmef_time_t object.
447 * @tv: Pointer to a struct timeval (see gettimeofday()).
448 *
449 * Creates an #idmef_time_t object filled with information provided
450 * within the @tv structure.
451 *
452 * Returns: 0 on success, a negative value if an error occured.
453 */
idmef_time_new_from_timeval(idmef_time_t ** time,const struct timeval * tv)454 int idmef_time_new_from_timeval(idmef_time_t **time, const struct timeval *tv)
455 {
456 int ret;
457
458 prelude_return_val_if_fail(tv, prelude_error(PRELUDE_ERROR_ASSERTION));
459
460 ret = idmef_time_new(time);
461 if ( ret < 0 )
462 return ret;
463
464 return idmef_time_set_from_timeval(*time, tv);
465 }
466
467
468
469 /**
470 * idmef_time_set_from_gettimeofday:
471 * @time: Pointer to an #idmef_time_t object.
472 *
473 * Fills @time with information retrieved using gettimeofday().
474 *
475 * Returns: 0 on success, a negative value if an error occured.
476 */
idmef_time_set_from_gettimeofday(idmef_time_t * time)477 int idmef_time_set_from_gettimeofday(idmef_time_t *time)
478 {
479 int ret;
480 struct timeval tv;
481
482 prelude_return_val_if_fail(time, prelude_error(PRELUDE_ERROR_ASSERTION));
483
484 ret = gettimeofday(&tv, NULL);
485 if ( ret < 0 )
486 return prelude_error_from_errno(errno);
487
488 return idmef_time_set_from_timeval(time, &tv);
489 }
490
491
492
493 /**
494 * idmef_time_new_from_gettimeofday:
495 * @time: Address where to store the created #idmef_time_t object.
496 *
497 * Creates an #idmef_time_t object filled with information retrieved
498 * using gettimeofday(), and stores it in @time.
499 *
500 * Returns: 0 on success, a negative value if an error occured.
501 */
idmef_time_new_from_gettimeofday(idmef_time_t ** time)502 int idmef_time_new_from_gettimeofday(idmef_time_t **time)
503 {
504 int ret;
505 struct timeval tv;
506
507 ret = gettimeofday(&tv, NULL);
508 if ( ret < 0 )
509 return prelude_error_from_errno(errno);
510
511 return idmef_time_new_from_timeval(time, &tv);
512 }
513
514
515
516 /**
517 * idmef_time_ref:
518 * @time: Pointer to an #idmef_time_t object.
519 *
520 * Increases @time reference count.
521 * idmef_time_destroy() won't destroy @time until the refcount
522 * reach 0.
523 *
524 * Returns: The @time provided argument.
525 */
idmef_time_ref(idmef_time_t * time)526 idmef_time_t *idmef_time_ref(idmef_time_t *time)
527 {
528 prelude_return_val_if_fail(time, NULL);
529
530 time->refcount++;
531 return time;
532 }
533
534
535
536 /**
537 * idmef_time_new:
538 * @time: Address where to store the created #idmef_time_t object.
539 *
540 * Creates an empty #idmef_time_t object and store it in @time.
541 *
542 * Returns: 0 on success, a negative value if an error occured.
543 */
idmef_time_new(idmef_time_t ** time)544 int idmef_time_new(idmef_time_t **time)
545 {
546 *time = calloc(1, sizeof(**time));
547 if ( ! *time )
548 return prelude_error_from_errno(errno);
549
550 (*time)->refcount = 1;
551
552 return 0;
553 }
554
555
556
557 /**
558 * idmef_time_clone:
559 * @src: Pointer to a #idmef_time_t to clone.
560 * @dst: Address where to store the cloned @src object.
561 *
562 * Clones @src and stores the result in the @dst address.
563 *
564 * Returns: 0 on success, a negative value if an error occured.
565 */
idmef_time_clone(const idmef_time_t * src,idmef_time_t ** dst)566 int idmef_time_clone(const idmef_time_t *src, idmef_time_t **dst)
567 {
568 int ret;
569
570 prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
571
572 ret = idmef_time_new(dst);
573 if ( ret < 0 )
574 return ret;
575
576 return idmef_time_copy(src, *dst);
577 }
578
579
580
581 /**
582 * idmef_time_set_from_time:
583 * @time: Pointer to an #idmef_time_t object.
584 * @t: Pointer to a time_t.
585 *
586 * Fills @time from the information described by @t.
587 * @time won't contain micro seconds information, since theses are not
588 * available within @t.
589 */
idmef_time_set_from_time(idmef_time_t * time,const time_t * t)590 void idmef_time_set_from_time(idmef_time_t *time, const time_t *t)
591 {
592 long gmtoff;
593
594 prelude_return_if_fail(time);
595 prelude_return_if_fail(t);
596
597 prelude_get_gmt_offset_from_time(t, &gmtoff);
598
599 time->gmt_offset = (int32_t) gmtoff;
600 time->sec = *t;
601 }
602
603
604
605 /**
606 * idmef_time_new_from_time:
607 * @time: Address where to store the created #idmef_time_t object.
608 * @t: Pointer to a time_t.
609 *
610 * Creates a new #idmef_time_t object and store it in @time.
611 * This object will be filled with information available in @t. The created
612 * @time won't contain micro seconds information, since theses are not
613 * available within @t.
614 *
615 * Returns: 0 on success, a negative value if an error occured.
616 */
idmef_time_new_from_time(idmef_time_t ** time,const time_t * t)617 int idmef_time_new_from_time(idmef_time_t **time, const time_t *t)
618 {
619 int ret;
620
621 prelude_return_val_if_fail(t, prelude_error(PRELUDE_ERROR_ASSERTION));
622
623 ret = idmef_time_new(time);
624 if ( ret < 0 )
625 return ret;
626
627 idmef_time_set_from_time(*time, t);
628
629 return 0;
630 }
631
632
633
634 /**
635 * idmef_time_set_gmt_offset:
636 * @time: Pointer to a #idmef_time_t.
637 * @gmtoff: GMT offset for @time, in seconds.
638 *
639 * Sets the GMT offset @gmtoff, in seconds, within @time.
640 *
641 * WARNING: this is just an accessor function, and using it to
642 * set @time current time also requires the use of idmef_time_set_sec()
643 * and idmef_time_set_usec().
644 */
idmef_time_set_gmt_offset(idmef_time_t * time,int32_t gmtoff)645 void idmef_time_set_gmt_offset(idmef_time_t *time, int32_t gmtoff)
646 {
647 prelude_return_if_fail(time);
648 time->gmt_offset = gmtoff;
649 }
650
651
652
653 /**
654 * idmef_time_set_sec:
655 * @time: Pointer to a #idmef_time_t.
656 * @sec: Number of seconds since the Epoch.
657 *
658 * Sets the number of second from the Epoch to @sec within @time.
659 *
660 * WARNING: this is just an accessor function, and using it to
661 * set @time current time also requires the use of idmef_time_set_usec()
662 * and idmef_time_set_gmt_offset().
663 */
idmef_time_set_sec(idmef_time_t * time,uint32_t sec)664 void idmef_time_set_sec(idmef_time_t *time, uint32_t sec)
665 {
666 prelude_return_if_fail(time);
667 time->sec = sec;
668 }
669
670
671
672 /**
673 * idmef_time_set_usec:
674 * @time: Pointer to a #idmef_time_t.
675 * @usec: Number of micro seconds to set within @time.
676 *
677 * Sets the number of micro second to @usec within @time.
678 *
679 * WARNING: this is just an accessor function, and using it to
680 * set @time current time also requires the use of idmef_time_set_sec()
681 * and idmef_time_set_gmt_offset().
682 */
idmef_time_set_usec(idmef_time_t * time,uint32_t usec)683 void idmef_time_set_usec(idmef_time_t *time, uint32_t usec)
684 {
685 prelude_return_if_fail(time);
686 time->usec = usec;
687 }
688
689
690 /**
691 * idmef_time_get_gmt_offset:
692 * @time: Pointer to a #idmef_time_t.
693 *
694 * Returns the GMT offset that applies to @time.
695 *
696 * Returns: The GMT offset, in seconds.
697 */
idmef_time_get_gmt_offset(const idmef_time_t * time)698 int32_t idmef_time_get_gmt_offset(const idmef_time_t *time)
699 {
700 prelude_return_val_if_fail(time, 0);
701 return time->gmt_offset;
702 }
703
704
705
706
707 /**
708 * idmef_time_get_sec:
709 * @time: Pointer to a #idmef_time_t.
710 *
711 * Returns the number of second since the Epoch (00:00:00 UTC, January 1, 1970),
712 * previously set within @time.
713 *
714 * Returns: The number of seconds.
715 */
idmef_time_get_sec(const idmef_time_t * time)716 uint32_t idmef_time_get_sec(const idmef_time_t *time)
717 {
718 prelude_return_val_if_fail(time, 0);
719 return time->sec;
720 }
721
722
723
724 /**
725 * idmef_time_get_usec:
726 * @time: Pointer to a #idmef_time_t.
727 *
728 * Returns the u-second member of @time.
729 *
730 * Returns: The number of u-seconds.
731 */
idmef_time_get_usec(const idmef_time_t * time)732 uint32_t idmef_time_get_usec(const idmef_time_t *time)
733 {
734 prelude_return_val_if_fail(time, 0);
735 return time->usec;
736 }
737
738
739
740 /**
741 * idmef_time_copy:
742 * @src: Pointer to a #idmef_time_t to copy data from.
743 * @dst: Pointer to a #idmef_time_t to copy data to.
744 *
745 * Copies @src internal to @dst.
746 *
747 * Returns: 0 on success, a negative value if an error occured.
748 */
idmef_time_copy(const idmef_time_t * src,idmef_time_t * dst)749 int idmef_time_copy(const idmef_time_t *src, idmef_time_t *dst)
750 {
751 prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
752 prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));
753
754 dst->sec = src->sec;
755 dst->usec = src->usec;
756 dst->gmt_offset = src->gmt_offset;
757
758 return 0;
759 }
760
761
762
763
idmef_time_destroy_internal(idmef_time_t * time)764 void idmef_time_destroy_internal(idmef_time_t *time)
765 {
766 /* nop */
767 }
768
769
770
771 /**
772 * idmef_time_destroy:
773 * @time: Pointer to an #idmef_time_t object.
774 *
775 * Destroys @time if refcount reach 0.
776 */
idmef_time_destroy(idmef_time_t * time)777 void idmef_time_destroy(idmef_time_t *time)
778 {
779 prelude_return_if_fail(time);
780
781 if ( --time->refcount )
782 return;
783
784 free(time);
785 }
786
787
788
789 /**
790 * idmef_time_compare:
791 * @time1: Pointer to an #idmef_time_t object to compare with @time2.
792 * @time2: Pointer to an #idmef_time_t object to compare with @time1.
793 *
794 * Returns: 0 if @time1 and @time2 match, 1 if @time1 is greater than
795 * @time2, -1 if @time1 is lesser than @time2.
796 */
idmef_time_compare(const idmef_time_t * time1,const idmef_time_t * time2)797 int idmef_time_compare(const idmef_time_t *time1, const idmef_time_t *time2)
798 {
799 unsigned long t1, t2;
800
801 if ( ! time1 && ! time2 )
802 return 0;
803
804 else if ( ! time1 || ! time2 )
805 return -1;
806
807 t1 = time1->sec + time1->gmt_offset;
808 t2 = time2->sec + time2->gmt_offset;
809
810 if ( t1 == t2 ) {
811 if ( time1->usec == time2->usec )
812 return 0;
813 else
814 return (time1->usec < time2->usec) ? -1 : 1;
815 }
816
817 else return (t1 < t2) ? -1 : 1;
818 }
819