1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2000-2011 Free Software Foundation Europe e.V.
5    Copyright (C) 2015-2019 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)
139       != 6) {
140     return 0;
141   }
142   if (tm.tm_mon > 0) {
143     tm.tm_mon--;
144   } else {
145     return 0;
146   }
147   if (tm.tm_year >= 1900) {
148     tm.tm_year -= 1900;
149   } else {
150     return 0;
151   }
152   tm.tm_wday = tm.tm_yday = 0;
153   tm.tm_isdst = -1;
154   time = mktime(&tm);
155   if (time == -1) { time = 0; }
156   return (utime_t)time;
157 }
158 
159 
160 /*
161  * BAREOS's time (btime_t) is an unsigned 64 bit integer that contains
162  * the number of microseconds since Epoch Time (1 Jan 1970) UTC.
163  */
164 
GetCurrentBtime()165 btime_t GetCurrentBtime()
166 {
167   struct timeval tv;
168   if (gettimeofday(&tv, NULL) != 0) {
169     tv.tv_sec = (long)time(NULL); /* fall back to old method */
170     tv.tv_usec = 0;
171   }
172   return ((btime_t)tv.tv_sec) * 1000000 + (btime_t)tv.tv_usec;
173 }
174 
175 /*
176  * Convert btime to Unix time
177  */
BtimeToUnix(btime_t bt)178 time_t BtimeToUnix(btime_t bt) { return (time_t)(bt / 1000000); }
179 
180 /*
181  * Convert btime to utime
182  */
BtimeToUtime(btime_t bt)183 utime_t BtimeToUtime(btime_t bt) { return (utime_t)(bt / 1000000); }
184 
185 /*
186  * Return the week of the month, base 0 (wom)
187  * given tm_mday and tm_wday. Value returned
188  * can be from 0 to 4 => week1, ... week5
189  */
tm_wom(int mday,int wday)190 int tm_wom(int mday, int wday)
191 {
192   int fs; /* first sunday */
193   int wom;
194 
195   fs = (mday % 7) - wday;
196   if (fs <= 0) { fs += 7; }
197   if (mday <= fs) { return 0; }
198   wom = 1 + (mday - fs - 1) / 7;
199 
200   return wom;
201 }
202 
203 /*
204  * Given a Unix date return the week of the year.
205  * The returned value can be 0-53.  Officially
206  * the weeks are numbered from 1 to 53 where week1
207  * is the week in which the first Thursday of the
208  * year occurs (alternatively, the week which contains
209  * the 4th of January).  We return 0, if the week of the
210  * year does not fall in the current year.
211  */
TmWoy(time_t stime)212 int TmWoy(time_t stime)
213 {
214   int woy, fty, tm_yday;
215   time_t time4;
216   struct tm tm;
217 
218   memset(&tm, 0, sizeof(struct tm));
219   Blocaltime(&stime, &tm);
220   tm_yday = tm.tm_yday;
221   tm.tm_mon = 0;
222   tm.tm_mday = 4;
223   tm.tm_isdst = 0; /* 4 Jan is not DST */
224   time4 = mktime(&tm);
225   Blocaltime(&time4, &tm);
226   fty = 1 - tm.tm_wday;
227   if (fty <= 0) { fty += 7; }
228   woy = tm_yday - fty + 4;
229   if (woy < 0) { return 0; }
230   return 1 + woy / 7;
231 }
232 
233 /*
234  * Deprecated. Do not use.
235  */
get_current_time(struct date_time * dt)236 void get_current_time(struct date_time* dt)
237 {
238   struct tm tm;
239   time_t now;
240 
241   now = time(NULL);
242   (void)gmtime_r(&now, &tm);
243   Dmsg6(200, "m=%d d=%d y=%d h=%d m=%d s=%d\n", tm.tm_mon + 1, tm.tm_mday,
244         tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
245   TmEncode(dt, &tm);
246   Dmsg2(200, "jday=%f jmin=%f\n", dt->julian_day_number,
247         dt->julian_day_fraction);
248   TmDecode(dt, &tm);
249   Dmsg6(200, "m=%d d=%d y=%d h=%d m=%d s=%d\n", tm.tm_mon + 1, tm.tm_mday,
250         tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
251 }
252 
253 
254 /*  DateEncode  --  Encode civil date as a Julian day number.  */
255 
256 /* Deprecated. Do not use. */
DateEncode(uint32_t year,uint8_t month,uint8_t day)257 fdate_t DateEncode(uint32_t year, uint8_t month, uint8_t day)
258 {
259   /* Algorithm as given in Meeus, Astronomical Algorithms, Chapter 7, page 61 */
260 
261   int32_t a, b, m;
262   uint32_t y;
263 
264   ASSERT(month < 13);
265   ASSERT(day > 0 && day < 32);
266 
267   m = month;
268   y = year;
269 
270   if (m <= 2) {
271     y--;
272     m += 12;
273   }
274 
275   /* Determine whether date is in Julian or Gregorian calendar based on
276      canonical date of calendar reform. */
277 
278   if ((year < 1582)
279       || ((year == 1582) && ((month < 9) || (month == 9 && day < 5)))) {
280     b = 0;
281   } else {
282     a = ((int)(y / 100));
283     b = 2 - a + (a / 4);
284   }
285 
286   return (((int32_t)(365.25 * (y + 4716))) + ((int)(30.6001 * (m + 1))) + day
287           + b - 1524.5);
288 }
289 
290 /*  TimeEncode  --  Encode time from hours, minutes, and seconds
291                      into a fraction of a day.  */
292 
293 /* Deprecated. Do not use. */
TimeEncode(uint8_t hour,uint8_t minute,uint8_t second,float32_t second_fraction)294 ftime_t TimeEncode(uint8_t hour,
295                    uint8_t minute,
296                    uint8_t second,
297                    float32_t second_fraction)
298 {
299   ASSERT((second_fraction >= 0.0) || (second_fraction < 1.0));
300   return (ftime_t)(((second + 60L * (minute + 60L * hour)) / 86400.0))
301          + second_fraction;
302 }
303 
304 /*  date_time_encode  --  Set day number and fraction from date
305                           and time.  */
306 
307 /* 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)308 void date_time_encode(struct date_time* dt,
309                       uint32_t year,
310                       uint8_t month,
311                       uint8_t day,
312                       uint8_t hour,
313                       uint8_t minute,
314                       uint8_t second,
315                       float32_t second_fraction)
316 {
317   dt->julian_day_number = DateEncode(year, month, day);
318   dt->julian_day_fraction = TimeEncode(hour, minute, second, second_fraction);
319 }
320 
321 /*  DateDecode  --  Decode a Julian day number into civil date.  */
322 
323 /* Deprecated. Do not use. */
DateDecode(fdate_t date,uint32_t * year,uint8_t * month,uint8_t * day)324 void DateDecode(fdate_t date, uint32_t* year, uint8_t* month, uint8_t* day)
325 {
326   fdate_t z, f, a, alpha, b, c, d, e;
327 
328   date += 0.5;
329   z = floor(date);
330   f = date - z;
331 
332   if (z < 2299161.0) {
333     a = z;
334   } else {
335     alpha = floor((z - 1867216.25) / 36524.25);
336     a = z + 1 + alpha - floor(alpha / 4);
337   }
338 
339   b = a + 1524;
340   c = floor((b - 122.1) / 365.25);
341   d = floor(365.25 * c);
342   e = floor((b - d) / 30.6001);
343 
344   *day = (uint8_t)(b - d - floor(30.6001 * e) + f);
345   *month = (uint8_t)((e < 14) ? (e - 1) : (e - 13));
346   *year = (uint32_t)((*month > 2) ? (c - 4716) : (c - 4715));
347 }
348 
349 /*  TimeDecode  --  Decode a day fraction into civil time.  */
350 
351 /* Deprecated. Do not use. */
TimeDecode(ftime_t time,uint8_t * hour,uint8_t * minute,uint8_t * second,float32_t * second_fraction)352 void TimeDecode(ftime_t time,
353                 uint8_t* hour,
354                 uint8_t* minute,
355                 uint8_t* second,
356                 float32_t* second_fraction)
357 {
358   uint32_t ij;
359 
360   ij = (uint32_t)((time - floor(time)) * 86400.0);
361   *hour = (uint8_t)(ij / 3600L);
362   *minute = (uint8_t)((ij / 60L) % 60L);
363   *second = (uint8_t)(ij % 60L);
364   if (second_fraction != NULL) {
365     *second_fraction = (float32_t)(time - floor(time));
366   }
367 }
368 
369 /*  date_time_decode  --  Decode a Julian day and day fraction
370                           into civil date and time.  */
371 
372 /* 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)373 void date_time_decode(struct date_time* dt,
374                       uint32_t* year,
375                       uint8_t* month,
376                       uint8_t* day,
377                       uint8_t* hour,
378                       uint8_t* minute,
379                       uint8_t* second,
380                       float32_t* second_fraction)
381 {
382   DateDecode(dt->julian_day_number, year, month, day);
383   TimeDecode(dt->julian_day_fraction, hour, minute, second, second_fraction);
384 }
385 
386 /*  TmEncode  --  Encode a civil date and time from a tm structure
387  *                 to a Julian day and day fraction.
388  */
389 
390 /* Deprecated. Do not use. */
TmEncode(struct date_time * dt,struct tm * tm)391 void TmEncode(struct date_time* dt, struct tm* tm)
392 {
393   uint32_t year;
394   uint8_t month, day, hour, minute, second;
395 
396   year = tm->tm_year + 1900;
397   month = tm->tm_mon + 1;
398   day = tm->tm_mday;
399   hour = tm->tm_hour;
400   minute = tm->tm_min;
401   second = tm->tm_sec;
402   dt->julian_day_number = DateEncode(year, month, day);
403   dt->julian_day_fraction = TimeEncode(hour, minute, second, 0.0);
404 }
405 
406 
407 /*  TmDecode  --  Decode a Julian day and day fraction
408                    into civil date and time in tm structure */
409 
410 /* Deprecated. Do not use. */
TmDecode(struct date_time * dt,struct tm * tm)411 void TmDecode(struct date_time* dt, struct tm* tm)
412 {
413   uint32_t year;
414   uint8_t month, day, hour, minute, second;
415 
416   DateDecode(dt->julian_day_number, &year, &month, &day);
417   TimeDecode(dt->julian_day_fraction, &hour, &minute, &second, NULL);
418   tm->tm_year = year - 1900;
419   tm->tm_mon = month - 1;
420   tm->tm_mday = day;
421   tm->tm_hour = hour;
422   tm->tm_min = minute;
423   tm->tm_sec = second;
424 }
425 
426 
427 /*  DateTimeCompare  --  Compare two dates and times and return
428                            the relationship as follows:
429 
430                                     -1    dt1 < dt2
431                                      0    dt1 = dt2
432                                      1    dt1 > dt2
433 */
434 
435 /* Deprecated. Do not use. */
DateTimeCompare(struct date_time * dt1,struct date_time * dt2)436 int DateTimeCompare(struct date_time* dt1, struct date_time* dt2)
437 {
438   if (dt1->julian_day_number == dt2->julian_day_number) {
439     if (dt1->julian_day_fraction == dt2->julian_day_fraction) { return 0; }
440     return (dt1->julian_day_fraction < dt2->julian_day_fraction) ? -1 : 1;
441   }
442   return (dt1->julian_day_number - dt2->julian_day_number) ? -1 : 1;
443 }
444