1 /*
2  * Copyright (c) 2002-2018 Balabit
3  * Copyright (c) 1998-2018 Balázs Scheidler
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  * As an additional exemption you are allowed to compile & link against the
20  * OpenSSL libraries as published by the OpenSSL project. See the file
21  * COPYING for details.
22  *
23  */
24 
25 #ifndef WALLCLOCKTIME_H_INCLUDED
26 #define WALLCLOCKTIME_H_INCLUDED
27 
28 #include "syslog-ng.h"
29 
30 /*
31  * This is a simple wrapper over "struct tm" with fields that are not
32  * portable across all platforms or are not present at all, but which we
33  * would use.
34  *
35  * For instance, wct_gmtoff is not present on a number of platforms but would
36  * be very useful internally, so we _always_ have the capability to
37  * represent a broken-down time with all the properties needed for proper
38  * timezone reference.
39  *
40  * Another example is wct_usec, which represents the number of microseconds
41  * so we can carry fractions of a second information.
42  *
43  * The design of the class is so that we don't need to copy the contents of
44  * "struct tm" around for conversions, rather we contain one instance and
45  * provide wrapper macros so that fields that are present in struct tm are
46  * used from there, those that aren't will be part of the wrapper structure.
47  *
48  * NOTE on thread safety: the wct_zone field is a pointer to a dynamically
49  * allocated string, that is managed in a thread-specific location (in
50  * cache.c), the pointer could become stale across a syslog-ng reload.  In
51  * general it is not a good idea to pass WallClockTime instances between
52  * threads, if the wct_zone field was initialized by cached_localtime() and
53  * friends, unless you ensure this field does not become stale.
54  */
55 typedef struct _WallClockTime WallClockTime;
56 struct _WallClockTime
57 {
58 #define wct_year  tm.tm_year
59 #define wct_mon   tm.tm_mon
60 #define wct_mday  tm.tm_mday
61 #define wct_wday  tm.tm_wday
62 #define wct_yday  tm.tm_yday
63 #define wct_hour  tm.tm_hour
64 #define wct_min   tm.tm_min
65 #define wct_sec   tm.tm_sec
66 #define wct_isdst tm.tm_isdst
67   struct tm tm;
68 
69 
70   /* We might need to separate tm_zone to a different conditional/autoconf
71    * check.  At least on Linux/FreeBSD they were introduced the same time.
72    * Some platforms may lack tm_zone, even though they have tm_gmtoff */
73 
74 #ifndef SYSLOG_NG_HAVE_STRUCT_TM_TM_GMTOFF
75   long wct_gmtoff;
76   const char *wct_zone;
77 #else
78 #define wct_gmtoff tm.tm_gmtoff
79 #define wct_zone tm.tm_zone
80 #endif
81   int wct_usec;
82 };
83 
84 #ifdef SYSLOG_NG_HAVE_STRUCT_TM_TM_GMTOFF
85 
86 #define WALL_CLOCK_TIME_INIT \
87   {                                     \
88     .tm =                               \
89       {                                 \
90         .tm_year = -1,                  \
91         .tm_mon = -1,                   \
92         .tm_mday = -1,                  \
93         .tm_wday = -1,                  \
94         .tm_yday = -1,                  \
95         .tm_hour = -1,                  \
96         .tm_min = -1,                   \
97         .tm_sec = -1,                   \
98         .tm_isdst = -1,                 \
99         .tm_gmtoff = -1,                \
100         .tm_zone = NULL,                \
101       },                                \
102       .wct_usec = 0,                    \
103   }
104 #else
105 
106 #define WALL_CLOCK_TIME_INIT \
107   {                                     \
108     .tm =                               \
109       {                                 \
110         .tm_year = -1,                  \
111         .tm_mon = -1,                   \
112         .tm_mday = -1,                  \
113         .tm_wday = -1,                  \
114         .tm_yday = -1,                  \
115         .tm_hour = -1,                  \
116         .tm_min = -1,                   \
117         .tm_sec = -1,                   \
118         .tm_isdst = -1,                 \
119       },                                \
120       .wct_gmtoff = -1,                 \
121       .wct_zone = NULL,                 \
122       .wct_usec = 0,                    \
123   }
124 
125 #endif
126 
127 guint32 wall_clock_time_iso_week_number(WallClockTime *wct);
128 
129 static inline gboolean
wall_clock_time_is_set(WallClockTime * wct)130 wall_clock_time_is_set(WallClockTime *wct)
131 {
132   return wct->wct_hour != -1;
133 }
134 
135 void wall_clock_time_unset(WallClockTime *wct);
136 gchar *wall_clock_time_strptime(WallClockTime *wct, const gchar *format, const gchar *input);
137 void wall_clock_time_guess_missing_year(WallClockTime *self);
138 void wall_clock_time_guess_missing_fields(WallClockTime *self);
139 
140 #endif
141