Bug Summary

File:util/ktime.c
Location:line 528, column 9
Description:Assigned value is always the same as the existing value

Annotated Source Code

1/*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10#include <afsconfig.h>
11#include <afs/param.h>
12
13#include <roken.h>
14
15#include <ctype.h>
16
17#include "afsutil.h"
18#include "ktime.h"
19
20/* some date parsing routines */
21
22struct token {
23 struct token *next;
24 char *key;
25};
26
27static char *day[] = {
28 "sun",
29 "mon",
30 "tue",
31 "wed",
32 "thu",
33 "fri",
34 "sat"
35};
36
37/* free token list returned by parseLine */
38#ifdef undef
39static
40LocalFreeTokens(alist)
41 struct token *alist;
42{
43 struct token *nlist;
44 for (; alist; alist = nlist) {
45 nlist = alist->next;
46 free(alist->key);
47 free(alist);
48 }
49 return 0;
50}
51#endif
52
53static int
54space(int x)
55{
56 if (x == 0 || x == ' ' || x == '\t' || x == '\n')
57 return 1;
58 else
59 return 0;
60}
61
62static int
63LocalParseLine(char *aline, struct token **alist)
64{
65 char tbuffer[256];
66 char *tptr = NULL((void *)0);
67 int inToken;
68 struct token *first, *last;
69 struct token *ttok;
70 int tc;
71
72 inToken = 0; /* not copying token chars at start */
73 first = NULL((void *)0);
74 last = NULL((void *)0);
75 while (1) {
76 tc = *aline++;
77 if (tc == 0 || space(tc)) { /* terminating null gets us in here, too */
78 if (inToken) {
79 inToken = 0; /* end of this token */
80 *tptr++ = 0;
81 ttok = (struct token *)malloc(sizeof(struct token));
82 ttok->next = NULL((void *)0);
83 ttok->key = (char *)malloc(strlen(tbuffer) + 1);
84 strcpy(ttok->key, tbuffer);
85 if (last) {
86 last->next = ttok;
87 last = ttok;
88 } else
89 last = ttok;
90 if (!first)
91 first = ttok;
92 }
93 } else {
94 /* an alpha character */
95 if (!inToken) {
96 tptr = tbuffer;
97 inToken = 1;
98 }
99 if (tptr - tbuffer >= sizeof(tbuffer))
100 return -1; /* token too long */
101 *tptr++ = tc;
102 }
103 if (tc == 0) {
104 /* last token flushed 'cause space(0) --> true */
105 if (last)
106 last->next = NULL((void *)0);
107 *alist = first;
108 return 0;
109 }
110 }
111}
112
113/* keyword database for periodic date parsing */
114static struct ptemp {
115 char *key;
116 afs_int32 value;
117} ptkeys[] = {
118 {
119 "sun", 0x10000,}, {
120 "mon", 0x10001,}, {
121 "tue", 0x10002,}, {
122 "wed", 0x10003,}, {
123 "thu", 0x10004,}, {
124 "fri", 0x10005,}, {
125 "sat", 0x10006,}, {
126 "sunday", 0x10000,}, {
127 "monday", 0x10001,}, {
128 "tuesday", 0x10002,}, {
129 "wednesday", 0x10003,}, {
130 "thursday", 0x10004,}, {
131 "thur", 0x10004,}, {
132 "friday", 0x10005,}, {
133 "saturday", 0x10006,}, {
134 "am", 0x20000,}, {
135 "pm", 0x20001,}, {
136 "a.m.", 0x20000,}, {
137 "p.m.", 0x20001,}, {
138 0, 0,}
139};
140
141/* ktime_DateOf
142 * entry:
143 * atime - time in seconds (Unix std)
144 * exit:
145 * return value - ptr to time in text form. Ptr is to a static string.
146 */
147
148char *
149ktime_DateOf(afs_int32 atime)
150{
151 static char tbuffer[30];
152 char *tp;
153 time_t t = atime;
154 tp = ctime(&t);
155 if (tp) {
156 strcpy(tbuffer, tp);
157 tbuffer[24] = 0; /* get rid of new line */
158 } else
159 strcpy(tbuffer, "BAD TIME");
160 return tbuffer;
161}
162
163/* ParseTime
164 * parse 12:33:12 or 12:33 or 12 into ktime structure
165 * entry:
166 * astr - ptr to string to be parsed
167 * ak - ptr to struct for return value.
168 * exit:
169 * 0 - ak holds parsed time.
170 * -1 - error in format
171 */
172
173static int
174ParseTime(struct ktime *ak, char *astr)
175{
176 int field;
177 afs_int32 temp;
178 char *tp;
179 int tc;
180
181 field = 0; /* 0=hour, 1=min, 2=sec */
182 temp = 0;
183
184 ak->mask |= (KTIME_HOUR1 | KTIME_MIN2 | KTIME_SEC4);
185 for (tp = astr;;) {
186 tc = *tp++;
187 if (tc == 0 || tc == ':') {
188 if (field == 0)
189 ak->hour = temp;
190 else if (field == 1)
191 ak->min = temp;
192 else if (field == 2)
193 ak->sec = temp;
194 temp = 0;
195 field++;
196 if (tc == 0)
197 break;
198 continue;
199 } else if (!isdigit(tc)__isctype((tc), 0x00000400L))
200 return -1; /* syntax error */
201 else {
202 /* digit */
203 temp *= 10;
204 temp += tc - '0';
205 }
206 }
207 if (ak->hour >= 24 || ak->min >= 60 || ak->sec >= 60)
208 return -1;
209 return 0;
210}
211
212afs_int32
213ktime_Str2int32(char *astr)
214{
215 struct ktime tk;
216
217 memset(&tk, 0, sizeof(tk));
218 if (ParseTime(&tk, astr))
219 return (-1); /* syntax error */
220
221 return ((tk.hour * 60 + tk.min) * 60 + tk.sec);
222}
223
224/* ktime_ParsePeriodic
225 * Parses periodic date of form
226 * now | never | at [time spec] | every [time spec]
227 * where [time spec] is a ktime string.
228 * entry:
229 * adate - string to be parsed
230 * ak - ptr to structure for returned ktime
231 * exit:
232 * 0 - parsed ktime in ak
233 * -1 - specification error
234 */
235
236/* -1 means error, 0 means now, otherwise returns time of next event */
237int
238ktime_ParsePeriodic(char *adate, struct ktime *ak)
239{
240 struct token *tt;
241 afs_int32 code;
242 struct ptemp *tp;
243
244 memset(ak, 0, sizeof(*ak));
245 code = LocalParseLine(adate, &tt);
246 if (code)
247 return -1;
248 for (; tt; tt = tt->next) {
249 /* look at each token */
250 if (strcmp(tt->key, "now") == 0) {
251 ak->mask |= KTIME_NOW0x20;
252 return 0;
253 }
254 if (strcmp(tt->key, "never") == 0) {
255 ak->mask |= KTIME_NEVER0x10;
256 return 0;
257 }
258 if (strcmp(tt->key, "at") == 0)
259 continue;
260 if (strcmp(tt->key, "every") == 0)
261 continue;
262 if (isdigit(tt->key[0])__isctype((tt->key[0]), 0x00000400L)) {
263 /* parse a time */
264 code = ParseTime(ak, tt->key);
265 if (code)
266 return -1;
267 continue;
268 }
269 /* otherwise use keyword table */
270 for (tp = ptkeys;; tp++) {
271 if (tp->key == NULL((void *)0)) {
272 return -1;
273 }
274 if (strcmp(tp->key, tt->key) == 0)
275 break;
276 }
277 /* now look at tp->value to see what we've got */
278 if ((tp->value >> 16) == 1) {
279 /* a day */
280 ak->mask |= KTIME_DAY8;
281 ak->day = tp->value & 0xff;
282 }
283 if ((tp->value >> 16) == 2) {
284 /* am or pm token */
285 if ((tp->value & 0xff) == 1) {
286 /* pm */
287 if (!(ak->mask & KTIME_HOUR1))
288 return -1;
289 if (ak->hour < 12)
290 ak->hour += 12;
291 /* 12 is 12 PM */
292 else if (ak->hour != 12)
293 return -1;
294 } else {
295 /* am is almost a noop, except that we map 12:01 am to 0:01 */
296 if (ak->hour > 12)
297 return -1;
298 if (ak->hour == 12)
299 ak->hour = 0;
300 }
301 }
302 }
303 return 0;
304}
305
306/* ktime_DisplayString
307 * Display ktime structure as English that could go into the ktime parser
308 * entry:
309 * aparm - ktime to be converted to string
310 * astring - ptr to string, for the result
311 * exit:
312 * 0 - astring contains ktime string.
313 */
314int
315ktime_DisplayString(struct ktime *aparm, char *astring)
316{
317 char tempString[50];
318
319 if (aparm->mask & KTIME_NEVER0x10) {
320 strcpy(astring, "never");
321 return 0;
322 } else if (aparm->mask & KTIME_NOW0x20) {
323 strcpy(astring, "now");
324 return 0;
325 } else {
326 strcpy(astring, "at");
327 if (aparm->mask & KTIME_DAY8) {
328 strcat(astring, " ");
329 strcat(astring, day[aparm->day]);
330 }
331 if (aparm->mask & KTIME_HOUR1) {
332 if (aparm->hour > 12)
333 sprintf(tempString, " %d", aparm->hour - 12);
334 else if (aparm->hour == 0)
335 strcpy(tempString, " 12");
336 else
337 sprintf(tempString, " %d", aparm->hour);
338 strcat(astring, tempString);
339 }
340 if (aparm->mask & KTIME_MIN2) {
341 sprintf(tempString, ":%02d", aparm->min);
342 strcat(astring, tempString);
343 }
344 if ((aparm->mask & KTIME_SEC4) && aparm->sec != 0) {
345 sprintf(tempString, ":%02d", aparm->sec);
346 strcat(astring, tempString);
347 }
348 if (aparm->mask & KTIME_HOUR1) {
349 if (aparm->hour >= 12)
350 strcat(astring, " pm");
351 else
352 strcat(astring, " am");
353 }
354 }
355 return 0;
356}
357
358/* get next time that matches ktime structure after time afrom */
359afs_int32
360ktime_next(struct ktime * aktime, afs_int32 afrom)
361{
362 /* try by guessing from now */
363 struct tm *tsp;
364 time_t start; /* time to start looking */
365 time_t probe; /* a placeholder to use for advancing day to day */
366 time_t time_next; /* actual UTC time of probe, with time of day set */
367 afs_int32 tmask;
368 struct ktime_date tdate;
369
370 start = afrom + time(0); /* time to start search */
371 tmask = aktime->mask;
372
373 /* handle some special cases */
374 if (tmask & KTIME_NEVER0x10)
375 return 0x7fffffff;
376 if (tmask & KTIME_NOW0x20)
377 return 0;
378
379 /* Use probe to fill in members of *tsp. Add 23 hours each iteration until
380 * time_next is correct. Only add 23 hrs to avoid skipping spring
381 * daylight savings time day */
382 for (probe = start;; probe += (23 * 3600)) {
383 tsp = localtime(&probe); /* find out what UTC time "probe" is */
384
385 tdate.year = tsp->tm_year;
386 tdate.month = tsp->tm_mon + 1;
387 tdate.day = tsp->tm_mday;
388 tdate.mask =
389 KTIMEDATE_YEAR1 | KTIMEDATE_MONTH2 | KTIMEDATE_DAY4 | KTIMEDATE_HOUR8
390 | KTIMEDATE_MIN0x10 | KTIMEDATE_SEC0x20;
391 tdate.hour = aktime->hour; /* edit in our changes */
392 tdate.min = aktime->min;
393 tdate.sec = aktime->sec;
394 time_next = ktime_InterpretDate(&tdate); /* Convert back to UTC time */
395 if (time_next < start)
396 continue; /* "probe" time is already past */
397 if ((tmask & KTIME_DAY8) == 0) /* don't care about day, we're done */
398 break;
399 tsp = localtime(&time_next);
400 if (tsp->tm_wday == aktime->day)
401 break; /* day matches, we're done */
402 }
403 return time_next;
404}
405
406
407/* compare date in both formats, and return as in strcmp */
408#ifdef undef
409static int
410KTimeCmp(struct ktime *aktime, struct tm *atm)
411{
412 afs_int32 tmask;
413
414 /* don't compare day of the week, since we can't tell the
415 * order in a cyclical set. Caller must check for equality, if
416 * she cares */
417 tmask = aktime->mask;
418 if (tmask & KTIME_HOUR1) {
419 if (aktime->hour > atm->tm_hour)
420 return 1;
421 if (aktime->hour < atm->tm_hour)
422 return -1;
423 }
424 if (tmask & KTIME_MIN2) {
425 if (aktime->min > atm->tm_min)
426 return 1;
427 if (aktime->min < atm->tm_min)
428 return -1;
429 }
430 if (tmask & KTIME_SEC4) {
431 if (aktime->sec > atm->tm_sec)
432 return 1;
433 if (aktime->sec < atm->tm_sec)
434 return -1;
435 }
436 return 0;
437}
438#endif
439
440/* compare date in both formats, and return as in strcmp */
441static int
442KDateCmp(struct ktime_date *akdate, struct tm *atm)
443{
444 if (akdate->year > atm->tm_year)
445 return 1;
446 if (akdate->year < atm->tm_year)
447 return -1;
448 if (akdate->month > atm->tm_mon)
449 return 1;
450 if (akdate->month < atm->tm_mon)
451 return -1;
452 if (akdate->day > atm->tm_mday)
453 return 1;
454 if (akdate->day < atm->tm_mday)
455 return -1;
456 if (akdate->mask & KTIMEDATE_HOUR8) {
457 if (akdate->hour > atm->tm_hour)
458 return 1;
459 if (akdate->hour < atm->tm_hour)
460 return -1;
461 }
462 if (akdate->mask & KTIMEDATE_MIN0x10) {
463 if (akdate->min > atm->tm_min)
464 return 1;
465 if (akdate->min < atm->tm_min)
466 return -1;
467 }
468 if (akdate->mask & KTIMEDATE_SEC0x20) {
469 if (akdate->sec > atm->tm_sec)
470 return 1;
471 if (akdate->sec < atm->tm_sec)
472 return -1;
473 }
474 return 0;
475}
476
477/* ktime_ParseDate
478 * parse date string into ktime_date structure
479 * entry:
480 * adate - string to be parsed
481 * akdate - ptr to ktime_date for result
482 * exit:
483 * 0 - akdate contains converted date
484 * -1 - parsing failure
485 */
486
487static afs_int32
488ktime_ParseDate(char *adate, struct ktime_date *akdate)
489{
490 int code;
491 afs_int32 month, day2, year, hour, min, sec;
492 char never[7];
493 char c[2];
494
495 lcstring(never, adate, sizeof(never));
496 if (strcmp(never, "never") == 0)
1
Taking false branch
497 akdate->mask = KTIMEDATE_NEVER0x1000;
498 else if (strcmp(never, "now") == 0)
2
Taking false branch
499 akdate->mask = KTIMEDATE_NOW0x2000;
500 else
501 akdate->mask = 0;
502 if (akdate->mask)
3
Taking false branch
503 return 0;
504
505 /* Old ambiguous mm/dd/yy hh:mm:ss format */
506
507 code =
508 sscanf(adate, "%d / %d / %d %d : %d : %d%1s", &month, &day2, &year,
509 &hour, &min, &sec, &c[0]);
510 if (code != 6) {
4
Taking true branch
511 sec = 0;
5
The value 0 is assigned to 'sec'
512 code =
513 sscanf(adate, "%d / %d / %d %d : %d%1s", &month, &day2, &year,
514 &hour, &min, &c[0]);
515 if (code != 5) {
6
Taking true branch
516 hour = min = 0;
517 code =
518 sscanf(adate, "%d / %d / %d%1s", &month, &day2, &year, &c[0]);
519 if (code != 3) {
7
Taking true branch
520 code = -1;
521 }
522 }
523 }
524
525 /* New ISO 8601 (subset) format */
526
527 if (code < 0) {
8
Taking true branch
528 hour = min = sec = 0;
9
Assigned value is always the same as the existing value
529 code =
530 sscanf(adate, "%d-%d-%d %d:%d:%d%1s", &year, &month, &day2,
531 &hour, &min, &sec, c);
532 if (code != 3 && code != 5 && code != 6)
533 code = -1;
534 }
535
536 if (code < 0)
537 return code;
538
539 if ((year < 0) || (month < 1) || (month > 12) || (day2 < 1) || (day2 > 31) || /* more or less */
540 (hour < 0) || (hour > 23) || (min < 0) || (min > 59) || (sec < 0)
541 || (sec > 59))
542 return -2;
543
544 if (year < 69)
545 year += 100; /* make 1/1/1 => Jan 1, 2001 */
546 else if (year >= 1900)
547 year -= 1900; /* allow 1/1/2001 to work */
548 else if (year > 99)
549 return -2; /* only allow 2 or 4 digit years */
550
551 akdate->mask =
552 KTIMEDATE_YEAR1 | KTIMEDATE_MONTH2 | KTIMEDATE_DAY4 | KTIMEDATE_HOUR8 |
553 KTIMEDATE_MIN0x10 | KTIMEDATE_SEC0x20;
554
555 akdate->year = year;
556 akdate->month = month;
557 akdate->day = day2;
558 akdate->hour = hour;
559 akdate->min = min;
560 akdate->sec = sec;
561
562 /* done successfully */
563 return 0;
564}
565
566/* ktime_DateToInt32
567 * Converts a ktime date string into an afs_int32
568 * entry:
569 * adate - ktime date string
570 * aint32 - ptr to afs_int32
571 * exit:
572 * 0 - aint32 contains converted date.
573 */
574
575afs_int32
576ktime_DateToInt32(char *adate, afs_int32 * aint32)
577{
578 struct ktime_date tdate;
579 afs_int32 code;
580 unsigned long l;
581 char c[2];
582
583 if (sscanf(adate, "%lu%1s", &l, c) == 1 && l > 200000000)
584 *aint32 = l;
585 else {
586 /* parse the date into a ktime_date structure */
587 code = ktime_ParseDate(adate, &tdate);
588 if (code)
589 return code; /* failed to parse */
590 *aint32 = ktime_InterpretDate(&tdate); /* interpret as seconds since 1970 */
591 }
592
593 return 0;
594}
595
596/* get useful error message to print about date input format */
597char *
598ktime_GetDateUsage(void)
599{
600 return "date format is '(yyyy-mm-dd | mm/dd/yy) [hh:mm]', using a 24 hour clock";
601}
602
603
604/* ktime_InterpretDate
605 * Converts ktime_date to an afs_int32
606 * entry:
607 * akdate - date to be converted/interpreted
608 * exit:
609 * returns KTIMEDATE_NEVERDATE - if never flag was set, or
610 * date converted to afs_int32.
611 */
612
613afs_int32
614ktime_InterpretDate(struct ktime_date * akdate)
615{
616 afs_uint32 tresult;
617 afs_uint32 tbit;
618 time_t temp;
619 struct tm *tsp;
620
621 if (akdate->mask & KTIMEDATE_NOW0x2000)
622 return time(0);
623 if (akdate->mask & KTIMEDATE_NEVER0x1000)
624 return KTIMEDATE_NEVERDATE0xffffffff;
625
626 tbit = 1 << 30; /* start off at max signed result */
627 tresult = 0; /* result to return */
628 while (tbit > 0) {
629 temp = tresult + tbit; /* see if adding this bit keeps us < akdate */
630 tsp = localtime(&temp);
631 tsp->tm_mon++;
632#ifdef notdef
633 if (tsp->tm_mon == 0) {
634 tsp->tm_mon = 12;
635 tsp->tm_year--;
636 }
637#endif
638 if (KDateCmp(akdate, tsp) >= 0) {
639 /* if temp still represents earlier than date than we're searching
640 * for, add in bit as increment, otherwise use old value and look
641 * for smaller increment */
642 tresult = temp;
643 }
644 tbit = tbit >> 1; /* try next bit */
645 }
646
647 return tresult;
648}