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