~henrix/ubuntu/precise/open-vm-dkms/lp-1416003

« back to all changes in this revision

Viewing changes to lib/misc/timeutil.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2008-10-23 15:32:00 UTC
  • mfrom: (1.1.2 upstream) (2.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20081023153200-gc1bfx89hj35c799
Tags: 2008.10.10-123053-2
* Correcting typo in dh_installinit call.
* Downgrading depends on module-assistant to recommends.

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
#else
34
34
#  include <sys/time.h>
35
35
#endif
 
36
#include <ctype.h>
36
37
 
37
38
#include "vmware.h"
38
39
/* For HARD_EXPIRE --hpreg */
45
46
#include "win32u.h"
46
47
#endif
47
48
 
 
49
 
48
50
/*
49
51
 * NT time of the Unix epoch:
50
52
 * midnight January 1, 1970 UTC
58
60
#define UNIX_S32_MAX (UNIX_EPOCH + (uint64)0x80000000 * 10000000)
59
61
 
60
62
/*
 
63
 * Days in month defines. The month is 1 - 12.
 
64
 * Notice that there are 28 days in february. It will updated for leap year
 
65
 * as necessary by the function using this defines.
 
66
 */
 
67
#define DAYS_IN_MONTH { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
 
68
 
 
69
 
 
70
/*
 
71
 * Local Definitions
 
72
 */
 
73
 
 
74
static void TimeUtilInit(TimeUtil_Date *d);
 
75
static Bool TimeUtilLoadDate(TimeUtil_Date *d, const char *date);
 
76
static Bool TimeUtilIsLeapYear(unsigned int year);
 
77
static Bool TimeUtilIsValidDate(unsigned int year, unsigned int month, unsigned int day);
 
78
 
 
79
 
 
80
/*
61
81
 * Function to guess Windows TZ Index by using time offset in
62
82
 * a lookup table
63
83
 */
70
90
static int Win32TimeUtilLookupZoneIndex(const char* targetName);
71
91
#endif
72
92
 
 
93
 
73
94
/*
74
95
 * Local substitution for localtime_r() for those platforms
75
96
 * that don't have one.
76
 
*/
 
97
 */
77
98
#ifdef SOL9
78
99
#include <synch.h>
79
100
static mutex_t LT_MUTEX = DEFAULTMUTEX;
93
114
/*
94
115
 *----------------------------------------------------------------------
95
116
 *
 
117
 * TimeUtil_MakeTime --
 
118
 *
 
119
 *    Converts a TimeUtil_Date to a time_t.
 
120
 *
 
121
 * Results:
 
122
 *    A time_t.
 
123
 *
 
124
 * Side effects:
 
125
 *    None.
 
126
 *
 
127
 *----------------------------------------------------------------------
 
128
 */
 
129
 
 
130
time_t
 
131
TimeUtil_MakeTime(const TimeUtil_Date *d) // IN
 
132
{
 
133
   struct tm t;
 
134
 
 
135
   ASSERT(d != NULL);
 
136
 
 
137
   memset(&t, 0, sizeof t);
 
138
 
 
139
   t.tm_mday = d->day;
 
140
   t.tm_mon = d->month - 1;
 
141
   t.tm_year = d->year - 1900;
 
142
 
 
143
   t.tm_sec = d->second;
 
144
   t.tm_min = d->minute;
 
145
   t.tm_hour = d->hour;
 
146
   t.tm_isdst = -1; /* Unknown. */
 
147
 
 
148
   return mktime(&t);
 
149
}
 
150
 
 
151
 
 
152
/*
 
153
 *----------------------------------------------------------------------
 
154
 *
 
155
 * TimeUtil_StringToDate --
 
156
 *
 
157
 *    Initialize the date object with value from the string argument,
 
158
 *    while the time will be left unmodified.
 
159
 *    The string 'date' needs to be in the format of 'YYYYMMDD' or
 
160
 *    'YYYY/MM/DD' or 'YYYY-MM-DD'.
 
161
 *    Unsuccesful initialization will leave the 'd' argument unmodified.
 
162
 *
 
163
 * Results:
 
164
 *    TRUE or FALSE.
 
165
 *
 
166
 * Side effects:
 
167
 *    None.
 
168
 *
 
169
 *----------------------------------------------------------------------
 
170
 */
 
171
 
 
172
Bool
 
173
TimeUtil_StringToDate(TimeUtil_Date *d,  // IN/OUT
 
174
                      char const *date)  // IN
 
175
{
 
176
   /*
 
177
    * Reduce the string to a known and handled format: YYYYMMDD.
 
178
    * Then, passed to internal function TimeUtilLoadDate.
 
179
    */
 
180
   if (strlen(date) == 8) {
 
181
      /* 'YYYYMMDD' */
 
182
      return TimeUtilLoadDate(d, date);
 
183
   } else if (strlen(date) == 10) {
 
184
      /* 'YYYY/MM/DD' */
 
185
      char temp[16] = { 0 };
 
186
 
 
187
      if (!(((date[4] != '/') || (date[7] != '/')) ||
 
188
           ((date[4] != '-') || (date[7] != '-')))) {
 
189
         return FALSE;
 
190
      }
 
191
 
 
192
      Str_Strcpy(temp, date, sizeof(temp));
 
193
      temp[4] = date[5];
 
194
      temp[5] = date[6];
 
195
      temp[6] = date[8];
 
196
      temp[7] = date[9];
 
197
      temp[8] = '\0';
 
198
 
 
199
      return TimeUtilLoadDate(d, temp);
 
200
   } else {
 
201
      return FALSE;
 
202
   }
 
203
}
 
204
 
 
205
 
 
206
/*
 
207
 *----------------------------------------------------------------------
 
208
 *
 
209
 * TimeUtil_DeltaDays --
 
210
 *
 
211
 *    Calculate the number of days between the two date arguments.
 
212
 *    This function ignores the time. It will be as if the time
 
213
 *    is midnight (00:00:00).
 
214
 *
 
215
 * Results:
 
216
 *    number of days:
 
217
 *    - 0 (if 'left' and 'right' are of the same date (ignoring the time).
 
218
 *    - negative, if 'left' is of a later date than 'right'
 
219
 *    - positive, if 'right' is of a later date than 'left'
 
220
 *
 
221
 * Side effects:
 
222
 *    None.
 
223
 *
 
224
 *----------------------------------------------------------------------
 
225
 */
 
226
 
 
227
int
 
228
TimeUtil_DeltaDays(TimeUtil_Date const *left,  // IN
 
229
                   TimeUtil_Date const *right) // IN
 
230
{
 
231
   TimeUtil_Date temp1;
 
232
   TimeUtil_Date temp2;
 
233
   TimeUtil_Date temp;
 
234
 
 
235
   int days = 0;
 
236
   Bool inverted = FALSE;
 
237
 
 
238
   ASSERT(left);
 
239
   ASSERT(right);
 
240
   ASSERT(TimeUtilIsValidDate(left->year, left->month, left->day));
 
241
   ASSERT(TimeUtilIsValidDate(right->year, right->month, right->day));
 
242
 
 
243
   TimeUtilInit(&temp1);
 
244
   TimeUtilInit(&temp2);
 
245
   TimeUtilInit(&temp);
 
246
 
 
247
   temp1.year = left->year;
 
248
   temp1.month = left->month;
 
249
   temp1.day = left->day;
 
250
   temp2.year = right->year;
 
251
   temp2.month = right->month;
 
252
   temp2.day = right->day;
 
253
 
 
254
   if (!TimeUtil_DateLowerThan(&temp1, &temp2) &&
 
255
       !TimeUtil_DateLowerThan(&temp2, &temp1)) {
 
256
      return 0;
 
257
   } else if (TimeUtil_DateLowerThan(&temp1, &temp2)) {
 
258
      inverted = FALSE;
 
259
   } else if (TimeUtil_DateLowerThan(&temp2, &temp1)) {
 
260
      inverted = TRUE;
 
261
      temp = temp1;
 
262
      temp1 = temp2;
 
263
      temp2 = temp;
 
264
   }
 
265
 
 
266
   days = 1;
 
267
   TimeUtil_DaysAdd(&temp1, 1);
 
268
   while (TimeUtil_DateLowerThan(&temp1, &temp2)) {
 
269
      days++;
 
270
      TimeUtil_DaysAdd(&temp1, 1);
 
271
   }
 
272
 
 
273
   if (inverted) {
 
274
      return -days;
 
275
   } else {
 
276
      return days;
 
277
   }
 
278
}
 
279
 
 
280
 
 
281
/*
 
282
 *----------------------------------------------------------------------
 
283
 *
 
284
 * TimeUtil_DaysSubtract --
 
285
 *
 
286
 *    Subtracts 'nr' days from 'd'.
 
287
 *
 
288
 *    Simple algorithm - which can be improved as necessary:
 
289
 *    - get rough days estimation, also guarantee that the estimation is
 
290
 *      lower than the actual result.
 
291
 *    - 'add' a day-by-day to arrive at actual result.
 
292
 *    'd' will be unchanged if the function failed.
 
293
 *
 
294
 * TODO:
 
295
 *    This function can be combined with DaysAdd(), where it
 
296
 *    accepts integer (positive for addition, negative for subtraction).
 
297
 *    But, that cannot be done without changing the DaysAdd function
 
298
 *    signature.
 
299
 *    When this utility get rewritten, this can be updated.
 
300
 *
 
301
 * Results:
 
302
 *    TRUE or FALSE.
 
303
 *
 
304
 * Side effects:
 
305
 *    None.
 
306
 *
 
307
 *----------------------------------------------------------------------
 
308
 */
 
309
 
 
310
Bool
 
311
TimeUtil_DaysSubtract(TimeUtil_Date *d,   // IN/OUT
 
312
                      unsigned int nr)    // IN
 
313
{
 
314
   TimeUtil_Date temp;
 
315
   int subYear = 0;
 
316
   int subMonth = 0;
 
317
   int subDay = 0;
 
318
 
 
319
   TimeUtil_Date estRes;
 
320
   int estYear = 0;
 
321
   int estMonth = 0;
 
322
   int estDay = 0;
 
323
 
 
324
   unsigned int dayCount = nr;
 
325
 
 
326
   ASSERT(d);
 
327
 
 
328
   TimeUtilInit(&temp);
 
329
   TimeUtilInit(&estRes);
 
330
 
 
331
   /*
 
332
    * Use lower bound for the following conversion:
 
333
    * 365 (instead of 366) days in a year
 
334
    * 30 (instead of 31) days in a month.
 
335
    *
 
336
    *   To account for February having fewer than 30 days, we will
 
337
    *   intentionally subtract an additional 2 days for each year
 
338
    *   and an additional 3 days.
 
339
    */
 
340
   dayCount = dayCount + 3 + 2 * (dayCount / 365);
 
341
 
 
342
   subYear = dayCount / 365;
 
343
   dayCount = dayCount % 365;
 
344
   subMonth = dayCount / 30;
 
345
   subDay = dayCount % 30;
 
346
 
 
347
   estDay = d->day - subDay;
 
348
   while (estDay <= 0) {
 
349
      estDay = estDay + 30;
 
350
      subMonth++;
 
351
   }
 
352
   estMonth = d->month - subMonth;
 
353
   while (estMonth <= 0) {
 
354
      estMonth = estMonth + 12;
 
355
      subYear++;
 
356
   }
 
357
   estYear = d->year - subYear;
 
358
   if (estYear <= 0) {
 
359
      return FALSE;
 
360
   }
 
361
 
 
362
   /*
 
363
    * making sure on the valid range, without checking
 
364
    * for leap year, etc.
 
365
    */
 
366
   if ((estDay > 28) && (estMonth == 2)) {
 
367
      estDay = 28;
 
368
   }
 
369
 
 
370
   estRes.year = estYear;
 
371
   estRes.month = estMonth;
 
372
   estRes.day = estDay;
 
373
 
 
374
   /*
 
375
    * we also copy the time from the original argument in making
 
376
    * sure that it does not play role in the comparison.
 
377
    */
 
378
   estRes.hour = d->hour;
 
379
   estRes.minute = d->minute;
 
380
   estRes.second = d->second;
 
381
 
 
382
   /*
 
383
    * At this point, we should have an estimated result which
 
384
    * guaranteed to be lower than the actual result. Otherwise,
 
385
    * infinite loop will happen.
 
386
    */
 
387
   ASSERT(TimeUtil_DateLowerThan(&estRes, d));
 
388
 
 
389
   /*
 
390
    * Perform the actual precise adjustment
 
391
    * Done by moving up (moving forward) the estimated a day at a time
 
392
    *    until they are the correct one (i.e. estDate + arg #day = arg date)
 
393
    */
 
394
   temp = estRes;
 
395
   TimeUtil_DaysAdd(&temp, nr);
 
396
   while (TimeUtil_DateLowerThan(&temp, d)) {
 
397
      TimeUtil_DaysAdd(&temp, 1);
 
398
      TimeUtil_DaysAdd(&estRes, 1);
 
399
   }
 
400
 
 
401
   d->year = estRes.year;
 
402
   d->month = estRes.month;
 
403
   d->day = estRes.day;
 
404
 
 
405
   return TRUE;
 
406
}
 
407
 
 
408
 
 
409
/*
 
410
 *----------------------------------------------------------------------
 
411
 *
96
412
 * TimeUtil_DaysAdd --
97
413
 *
98
414
 *    Add 'nr' days to a date.
111
427
TimeUtil_DaysAdd(TimeUtil_Date *d, // IN/OUT
112
428
                 unsigned int nr)  // IN
113
429
{
114
 
   static unsigned int monthdays[13] = { 0,
115
 
      31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
 
430
   static unsigned int monthdays[13] = DAYS_IN_MONTH;
116
431
   unsigned int i;
117
432
 
118
433
   /*
119
434
    * Initialize the table
120
435
    */
121
436
 
122
 
   if (   (d->year % 4) == 0
123
 
       && (   (d->year % 100) != 0
124
 
           || (d->year % 400) == 0)) {
125
 
      /* Leap year */
 
437
   if (TimeUtilIsLeapYear(d->year)) {
126
438
      monthdays[2] = 29;
127
439
   } else {
128
440
      monthdays[2] = 28;
145
457
             * Update the table
146
458
             */
147
459
 
148
 
            if (   (d->year % 4) == 0
149
 
                && (   (d->year % 100) != 0
150
 
                    || (d->year % 400) == 0)) {
151
 
               /* Leap year */
 
460
            if (TimeUtilIsLeapYear(d->year)) {
152
461
               monthdays[2] = 29;
153
462
            } else {
154
463
               monthdays[2] = 28;
751
1060
 
752
1061
 
753
1062
/*
 
1063
 ***********************************************************************
 
1064
 *
 
1065
 * Local Functions
 
1066
 *
 
1067
 ***********************************************************************
 
1068
 */
 
1069
 
 
1070
/*
 
1071
 *----------------------------------------------------------------------
 
1072
 *
 
1073
 * TimeUtilInit --
 
1074
 *
 
1075
 *    Initialize everything to zero
 
1076
 *
 
1077
 * Results:
 
1078
 *    None
 
1079
 *
 
1080
 * Side effects:
 
1081
 *    None.
 
1082
 *
 
1083
 *----------------------------------------------------------------------
 
1084
 */
 
1085
 
 
1086
static void
 
1087
TimeUtilInit(TimeUtil_Date *d)
 
1088
{
 
1089
   ASSERT(d);
 
1090
 
 
1091
   d->year = 0;
 
1092
   d->month = 0;
 
1093
   d->day = 0;
 
1094
   d->hour = 0;
 
1095
   d->minute = 0;
 
1096
   d->second = 0;
 
1097
 
 
1098
   return;
 
1099
}
 
1100
 
 
1101
 
 
1102
/*
 
1103
 *----------------------------------------------------------------------
 
1104
 *
 
1105
 * TimeUtilIsValidDate --
 
1106
 *
 
1107
 *    Check whether the args represent a valid date.
 
1108
 *
 
1109
 * Results:
 
1110
 *    TRUE or FALSE.
 
1111
 *
 
1112
 * Side effects:
 
1113
 *    None.
 
1114
 *
 
1115
 *----------------------------------------------------------------------
 
1116
 */
 
1117
 
 
1118
static Bool
 
1119
TimeUtilIsValidDate(unsigned int year,   // IN
 
1120
                    unsigned int month,  // IN
 
1121
                    unsigned int day)    // IN
 
1122
{
 
1123
   static unsigned int monthdays[13] = DAYS_IN_MONTH;
 
1124
 
 
1125
   /*
 
1126
    * Initialize the table
 
1127
    */
 
1128
   if (TimeUtilIsLeapYear(year)) {
 
1129
      monthdays[2] = 29;
 
1130
   } else {
 
1131
      monthdays[2] = 28;
 
1132
   }
 
1133
 
 
1134
   if ((year >= 1) &&
 
1135
       (month >= 1) && (month <= 12) &&
 
1136
       (day >= 1) && (day <= monthdays[month])) {
 
1137
      return TRUE;
 
1138
   }
 
1139
 
 
1140
   return FALSE;
 
1141
}
 
1142
 
 
1143
 
 
1144
/*
 
1145
 *----------------------------------------------------------------------
 
1146
 *
 
1147
 * TimeUtilIsLeapYear --
 
1148
 *
 
1149
 *    Check whether the argument represents a leap year.
 
1150
 *
 
1151
 * Results:
 
1152
 *    TRUE or FALSE.
 
1153
 *
 
1154
 * Side effects:
 
1155
 *    None.
 
1156
 *
 
1157
 *----------------------------------------------------------------------
 
1158
 */
 
1159
 
 
1160
static Bool
 
1161
TimeUtilIsLeapYear(unsigned int year)  // IN
 
1162
{
 
1163
   if ((year % 4) == 0 &&
 
1164
       ((year % 100) != 0 ||
 
1165
        (year % 400) == 0)) {
 
1166
      return TRUE;
 
1167
   }
 
1168
 
 
1169
   return FALSE;
 
1170
}
 
1171
 
 
1172
 
 
1173
/*
 
1174
 *----------------------------------------------------------------------
 
1175
 *
 
1176
 * TimeUtilLoadDate --
 
1177
 *
 
1178
 *    Initialize the date object with value from the string argument,
 
1179
 *    while the time will be left unmodified.
 
1180
 *    The string 'date' needs to be in the format of 'YYYYMMDD'.
 
1181
 *    Unsuccesful initialization will leave the 'd' argument unmodified.
 
1182
 *
 
1183
 * Results:
 
1184
 *    TRUE or FALSE.
 
1185
 *
 
1186
 * Side effects:
 
1187
 *    None.
 
1188
 *
 
1189
 *----------------------------------------------------------------------
 
1190
 */
 
1191
 
 
1192
static Bool
 
1193
TimeUtilLoadDate(TimeUtil_Date *d,  // IN/OUT
 
1194
                 const char *date)  // IN
 
1195
{
 
1196
   char temp[16] = { 0 };
 
1197
   int i = 0;
 
1198
   char *end = NULL;
 
1199
 
 
1200
   int32 year = 0;
 
1201
   int32 month = 0;
 
1202
   int32 day = 0;
 
1203
 
 
1204
   ASSERT(d);
 
1205
   ASSERT(date);
 
1206
 
 
1207
   if (strlen(date) != 8) {
 
1208
      return FALSE;
 
1209
   }
 
1210
   for (i = 0; i < strlen(date); i++) {
 
1211
      if (isdigit((int) date[i]) == 0) {
 
1212
         return FALSE;
 
1213
      }
 
1214
   }
 
1215
 
 
1216
   temp[0] = date[0];
 
1217
   temp[1] = date[1];
 
1218
   temp[2] = date[2];
 
1219
   temp[3] = date[3];
 
1220
   temp[4] = '\0';
 
1221
   year = strtol(temp, &end, 10);
 
1222
   if (*end != '\0') {
 
1223
      return FALSE;
 
1224
   }
 
1225
 
 
1226
   temp[0] = date[4];
 
1227
   temp[1] = date[5];
 
1228
   temp[2] = '\0';
 
1229
   month = strtol(temp, &end, 10);
 
1230
   if (*end != '\0') {
 
1231
      return FALSE;
 
1232
   }
 
1233
 
 
1234
   temp[0] = date[6];
 
1235
   temp[1] = date[7];
 
1236
   temp[2] = '\0';
 
1237
   day = strtol(temp, &end, 10);
 
1238
   if (*end != '\0') {
 
1239
      return FALSE;
 
1240
   }
 
1241
 
 
1242
   if (!TimeUtilIsValidDate((unsigned int) year, (unsigned int) month, (unsigned int) day)) {
 
1243
      return FALSE;
 
1244
   }
 
1245
 
 
1246
   d->year = (unsigned int) year;
 
1247
   d->month = (unsigned int) month;
 
1248
   d->day = (unsigned int) day;
 
1249
 
 
1250
   return TRUE;
 
1251
}
 
1252
 
 
1253
 
 
1254
/*
754
1255
 *----------------------------------------------------------------------
755
1256
 *
756
1257
 * TimeUtilFindIndexByUTCOffset --