1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2000-2011 Free Software Foundation Europe e.V.
5    Copyright (C) 2015-2015 Bareos GmbH & Co. KG
6 
7    This program is Free Software; you can redistribute it and/or
8    modify it under the terms of version three of the GNU Affero General Public
9    License as published by the Free Software Foundation and included
10    in the file LICENSE.
11 
12    This program is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15    Affero General Public License for more details.
16 
17    You should have received a copy of the GNU Affero General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20    02110-1301, USA.
21 */
22 /*
23  * BAREOS floating point time and date routines -- John Walker
24  *
25  * Later double precision integer time/date routines -- Kern Sibbald
26  *
27  */
28 
29 /* Concerning times. There are a number of differnt time standards
30  * in BAREOS (fdate_t, ftime_t, time_t (Unix standard), btime_t, and
31  * utime_t).  fdate_t and ftime_t are deprecated and should no longer
32  * be used, and in general, Unix time time_t should no longer be used,
33  * it is being phased out.
34  *
35  * Epoch is the base of Unix time in seconds (time_t, ...)
36  *    and is 1 Jan 1970 at 0:0 UTC
37  *
38  * The major two times that should be left are:
39  *    btime_t  (64 bit integer in microseconds base Epoch)
40  *    utime_t  (64 bit integer in seconds base Epoch)
41  */
42 
43 #include "include/bareos.h"
44 #include <math.h>
45 
Blocaltime(const time_t * time,struct tm * tm)46 void Blocaltime(const time_t* time, struct tm* tm)
47 {
48   /* ***FIXME**** localtime_r() should be user configurable */
49   (void)localtime_r(time, tm);
50 }
51 
52 /*
53  * Formatted time for user display: dd-Mon-yyyy hh:mm
54  */
bstrftime(char * dt,int maxlen,utime_t utime,const char * fmt)55 char* bstrftime(char* dt, int maxlen, utime_t utime, const char* fmt)
56 {
57   time_t time = (time_t)utime;
58   struct tm tm;
59 
60   Blocaltime(&time, &tm);
61   if (fmt) {
62     strftime(dt, maxlen, fmt, &tm);
63   } else {
64     strftime(dt, maxlen, "%d-%b-%Y %H:%M", &tm);
65   }
66 
67   return dt;
68 }
69 
70 /*
71  * Formatted time for user display: dd-Mon-yyyy hh:mm:ss
72  */
bstrftimes(char * dt,int maxlen,utime_t utime)73 char* bstrftimes(char* dt, int maxlen, utime_t utime)
74 {
75   return bstrftime(dt, maxlen, utime, "%d-%b-%Y %H:%M:%S");
76 }
77 
78 /*
79  * Formatted time for user display: dd-Mon hh:mm
80  */
bstrftime_ny(char * dt,int maxlen,utime_t utime)81 char* bstrftime_ny(char* dt, int maxlen, utime_t utime)
82 {
83   return bstrftime(dt, maxlen, utime, "%d-%b %H:%M");
84 }
85 
86 /*
87  * Formatted time for user display with weekday: weekday dd-Mon hh:mm
88  */
bstrftime_wd(char * dt,int maxlen,utime_t utime)89 char* bstrftime_wd(char* dt, int maxlen, utime_t utime)
90 {
91   return bstrftime(dt, maxlen, utime, "%a %d-%b-%Y %H:%M");
92 }
93 
94 /*
95  * Formatted time for user display: dd-Mon-yy hh:mm (no century)
96  */
bstrftime_nc(char * dt,int maxlen,utime_t utime)97 char* bstrftime_nc(char* dt, int maxlen, utime_t utime)
98 {
99   char *p, *q;
100 
101   /*
102    * NOTE! since the compiler complains about %y, I use %Y and cut the century
103    */
104   bstrftime(dt, maxlen, utime, "%d-%b-%Y %H:%M");
105 
106   /*
107    * Overlay the century
108    */
109   p = dt + 7;
110   q = dt + 9;
111   while (*q) { *p++ = *q++; }
112   *p = 0;
113   return dt;
114 }
115 
116 /*
117  * Unix time to standard time string yyyy-mm-dd hh:mm:ss
118  */
bstrutime(char * dt,int maxlen,utime_t utime)119 char* bstrutime(char* dt, int maxlen, utime_t utime)
120 {
121   return bstrftime(dt, maxlen, utime, "%Y-%m-%d %H:%M:%S");
122 }
123 
124 /*
125  * Convert standard time string yyyy-mm-dd hh:mm:ss to Unix time
126  */
StrToUtime(const char * str)127 utime_t StrToUtime(const char* str)
128 {
129   struct tm tm;
130   time_t time;
131 
132   /*
133    * Check for bad argument
134    */
135   if (!str || *str == 0) { return 0; }
136 
137   if (sscanf(str, "%d-%d-%d %d:%d:%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
138              &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
139     return 0;
140   }
141   if (tm.tm_mon > 0) {
142     tm.tm_mon--;
143   } else {
144     return 0;
145   }
146   if (tm.tm_year >= 1900) {
147     tm.tm_year -= 1900;
148   } else {
149     return 0;
150   }
151   tm.tm_wday = tm.tm_yday = 0;
152   tm.tm_isdst = -1;
153   time = mktime(&tm);
154   if (time == -1) { time = 0; }
155   return (utime_t)time;
156 }
157 
158 
159 /*
160  * BAREOS's time (btime_t) is an unsigned 64 bit integer that contains
161  * the number of microseconds since Epoch Time (1 Jan 1970) UTC.
162  */
163 
GetCurrentBtime()164 btime_t GetCurrentBtime()
165 {
166   struct timeval tv;
167   if (gettimeofday(&tv, NULL) != 0) {
168     tv.tv_sec = (long)time(NULL); /* fall back to old method */
169     tv.tv_usec = 0;
170   }
171   return ((btime_t)tv.tv_sec) * 1000000 + (btime_t)tv.tv_usec;
172 }
173 
174 /*
175  * Convert btime to Unix time
176  */
BtimeToUnix(btime_t bt)177 time_t BtimeToUnix(btime_t bt) { return (time_t)(bt / 1000000); }
178 
179 /*
180  * Convert btime to utime
181  */
BtimeToUtime(btime_t bt)182 utime_t BtimeToUtime(btime_t bt) { return (utime_t)(bt / 1000000); }
183 
184 /*
185  * Return the week of the month, base 0 (wom)
186  * given tm_mday and tm_wday. Value returned
187  * can be from 0 to 4 => week1, ... week5
188  */
tm_wom(int mday,int wday)189 int tm_wom(int mday, int wday)
190 {
191   int fs; /* first sunday */
192   int wom;
193 
194   fs = (mday % 7) - wday;
195   if (fs <= 0) { fs += 7; }
196   if (mday <= fs) { return 0; }
197   wom = 1 + (mday - fs - 1) / 7;
198 
199   return wom;
200 }
201 
202 /*
203  * Given a Unix date return the week of the year.
204  * The returned value can be 0-53.  Officially
205  * the weeks are numbered from 1 to 53 where week1
206  * is the week in which the first Thursday of the
207  * year occurs (alternatively, the week which contains
208  * the 4th of January).  We return 0, if the week of the
209  * year does not fall in the current year.
210  */
TmWoy(time_t stime)211 int TmWoy(time_t stime)
212 {
213   int woy, fty, tm_yday;
214   time_t time4;
215   struct tm tm;
216 
217   memset(&tm, 0, sizeof(struct tm));
218   Blocaltime(&stime, &tm);
219   tm_yday = tm.tm_yday;
220   tm.tm_mon = 0;
221   tm.tm_mday = 4;
222   tm.tm_isdst = 0; /* 4 Jan is not DST */
223   time4 = mktime(&tm);
224   Blocaltime(&time4, &tm);
225   fty = 1 - tm.tm_wday;
226   if (fty <= 0) { fty += 7; }
227   woy = tm_yday - fty + 4;
228   if (woy < 0) { return 0; }
229   return 1 + woy / 7;
230 }
231 
232 /*
233  * Deprecated. Do not use.
234  */
get_current_time(struct date_time * dt)235 void get_current_time(struct date_time* dt)
236 {
237   struct tm tm;
238   time_t now;
239 
240   now = time(NULL);
241   (void)gmtime_r(&now, &tm);
242   Dmsg6(200, "m=%d d=%d y=%d h=%d m=%d s=%d\n", tm.tm_mon + 1, tm.tm_mday,
243         tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
244   TmEncode(dt, &tm);
245   Dmsg2(200, "jday=%f jmin=%f\n", dt->julian_day_number,
246         dt->julian_day_fraction);
247   TmDecode(dt, &tm);
248   Dmsg6(200, "m=%d d=%d y=%d h=%d m=%d s=%d\n", tm.tm_mon + 1, tm.tm_mday,
249         tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
250 }
251 
252 
253 /*  DateEncode  --  Encode civil date as a Julian day number.  */
254 
255 /* Deprecated. Do not use. */
DateEncode(uint32_t year,uint8_t month,uint8_t day)256 fdate_t DateEncode(uint32_t year, uint8_t month, uint8_t day)
257 {
258   /* Algorithm as given in Meeus, Astronomical Algorithms, Chapter 7, page 61 */
259 
260   int32_t a, b, m;
261   uint32_t y;
262 
263   ASSERT(month < 13);
264   ASSERT(day > 0 && day < 32);
265 
266   m = month;
267   y = year;
268 
269   if (m <= 2) {
270     y--;
271     m += 12;
272   }
273 
274   /* Determine whether date is in Julian or Gregorian calendar based on
275      canonical date of calendar reform. */
276 
277   if ((year < 1582) ||
278       ((year == 1582) && ((month < 9) || (month == 9 && day < 5)))) {
279     b = 0;
280   } else {
281     a = ((int)(y / 100));
282     b = 2 - a + (a / 4);
283   }
284 
285   return (((int32_t)(365.25 * (y + 4716))) + ((int)(30.6001 * (m + 1))) + day +
286           b - 1524.5);
287 }
288 
289 /*  TimeEncode  --  Encode time from hours, minutes, and seconds
290                      into a fraction of a day.  */
291 
292 /* Deprecated. Do not use. */
TimeEncode(uint8_t hour,uint8_t minute,uint8_t second,float32_t second_fraction)293 ftime_t TimeEncode(uint8_t hour,
294                    uint8_t minute,
295                    uint8_t second,
296                    float32_t second_fraction)
297 {
298   ASSERT((second_fraction >= 0.0) || (second_fraction < 1.0));
299   return (ftime_t)(((second + 60L * (minute + 60L * hour)) / 86400.0)) +
300          second_fraction;
301 }
302 
303 /*  date_time_encode  --  Set day number and fraction from date
304                           and time.  */
305 
306 /* Deprecated. Do not use. */
date_time_encode(struct date_time * dt,uint32_t year,uint8_t month,uint8_t day,uint8_t hour,uint8_t minute,uint8_t second,float32_t second_fraction)307 void date_time_encode(struct date_time* dt,
308                       uint32_t year,
309                       uint8_t month,
310                       uint8_t day,
311                       uint8_t hour,
312                       uint8_t minute,
313                       uint8_t second,
314                       float32_t second_fraction)
315 {
316   dt->julian_day_number = DateEncode(year, month, day);
317   dt->julian_day_fraction = TimeEncode(hour, minute, second, second_fraction);
318 }
319 
320 /*  DateDecode  --  Decode a Julian day number into civil date.  */
321 
322 /* Deprecated. Do not use. */
DateDecode(fdate_t date,uint32_t * year,uint8_t * month,uint8_t * day)323 void DateDecode(fdate_t date, uint32_t* year, uint8_t* month, uint8_t* day)
324 {
325   fdate_t z, f, a, alpha, b, c, d, e;
326 
327   date += 0.5;
328   z = floor(date);
329   f = date - z;
330 
331   if (z < 2299161.0) {
332     a = z;
333   } else {
334     alpha = floor((z - 1867216.25) / 36524.25);
335     a = z + 1 + alpha - floor(alpha / 4);
336   }
337 
338   b = a + 1524;
339   c = floor((b - 122.1) / 365.25);
340   d = floor(365.25 * c);
341   e = floor((b - d) / 30.6001);
342 
343   *day = (uint8_t)(b - d - floor(30.6001 * e) + f);
344   *month = (uint8_t)((e < 14) ? (e - 1) : (e - 13));
345   *year = (uint32_t)((*month > 2) ? (c - 4716) : (c - 4715));
346 }
347 
348 /*  TimeDecode  --  Decode a day fraction into civil time.  */
349 
350 /* Deprecated. Do not use. */
TimeDecode(ftime_t time,uint8_t * hour,uint8_t * minute,uint8_t * second,float32_t * second_fraction)351 void TimeDecode(ftime_t time,
352                 uint8_t* hour,
353                 uint8_t* minute,
354                 uint8_t* second,
355                 float32_t* second_fraction)
356 {
357   uint32_t ij;
358 
359   ij = (uint32_t)((time - floor(time)) * 86400.0);
360   *hour = (uint8_t)(ij / 3600L);
361   *minute = (uint8_t)((ij / 60L) % 60L);
362   *second = (uint8_t)(ij % 60L);
363   if (second_fraction != NULL) {
364     *second_fraction = (float32_t)(time - floor(time));
365   }
366 }
367 
368 /*  date_time_decode  --  Decode a Julian day and day fraction
369                           into civil date and time.  */
370 
371 /* Deprecated. Do not use. */
date_time_decode(struct date_time * dt,uint32_t * year,uint8_t * month,uint8_t * day,uint8_t * hour,uint8_t * minute,uint8_t * second,float32_t * second_fraction)372 void date_time_decode(struct date_time* dt,
373                       uint32_t* year,
374                       uint8_t* month,
375                       uint8_t* day,
376                       uint8_t* hour,
377                       uint8_t* minute,
378                       uint8_t* second,
379                       float32_t* second_fraction)
380 {
381   DateDecode(dt->julian_day_number, year, month, day);
382   TimeDecode(dt->julian_day_fraction, hour, minute, second, second_fraction);
383 }
384 
385 /*  TmEncode  --  Encode a civil date and time from a tm structure
386  *                 to a Julian day and day fraction.
387  */
388 
389 /* Deprecated. Do not use. */
TmEncode(struct date_time * dt,struct tm * tm)390 void TmEncode(struct date_time* dt, struct tm* tm)
391 {
392   uint32_t year;
393   uint8_t month, day, hour, minute, second;
394 
395   year = tm->tm_year + 1900;
396   month = tm->tm_mon + 1;
397   day = tm->tm_mday;
398   hour = tm->tm_hour;
399   minute = tm->tm_min;
400   second = tm->tm_sec;
401   dt->julian_day_number = DateEncode(year, month, day);
402   dt->julian_day_fraction = TimeEncode(hour, minute, second, 0.0);
403 }
404 
405 
406 /*  TmDecode  --  Decode a Julian day and day fraction
407                    into civil date and time in tm structure */
408 
409 /* Deprecated. Do not use. */
TmDecode(struct date_time * dt,struct tm * tm)410 void TmDecode(struct date_time* dt, struct tm* tm)
411 {
412   uint32_t year;
413   uint8_t month, day, hour, minute, second;
414 
415   DateDecode(dt->julian_day_number, &year, &month, &day);
416   TimeDecode(dt->julian_day_fraction, &hour, &minute, &second, NULL);
417   tm->tm_year = year - 1900;
418   tm->tm_mon = month - 1;
419   tm->tm_mday = day;
420   tm->tm_hour = hour;
421   tm->tm_min = minute;
422   tm->tm_sec = second;
423 }
424 
425 
426 /*  DateTimeCompare  --  Compare two dates and times and return
427                            the relationship as follows:
428 
429                                     -1    dt1 < dt2
430                                      0    dt1 = dt2
431                                      1    dt1 > dt2
432 */
433 
434 /* Deprecated. Do not use. */
DateTimeCompare(struct date_time * dt1,struct date_time * dt2)435 int DateTimeCompare(struct date_time* dt1, struct date_time* dt2)
436 {
437   if (dt1->julian_day_number == dt2->julian_day_number) {
438     if (dt1->julian_day_fraction == dt2->julian_day_fraction) { return 0; }
439     return (dt1->julian_day_fraction < dt2->julian_day_fraction) ? -1 : 1;
440   }
441   return (dt1->julian_day_number - dt2->julian_day_number) ? -1 : 1;
442 }
443