2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afs/param.h>
12 #include <sys/types.h>
13 #include <afs/ktime.h>
14 #include <sys/socket.h>
15 #include <netinet/in.h>
22 #define MAX_YEAR_VALUE 0
23 #define MAX_MONTH_VALUE 11
24 #define MAX_DAY_VALUE 30
26 /* for parsing relative expiration dates */
27 static struct parseseqS
31 afs_int32 ps_maxValue;
33 KTIMEDATE_YEAR, 'y', MAX_YEAR_VALUE, /* no max. value */
34 KTIMEDATE_MONTH, 'm', MAX_MONTH_VALUE, /* months max. 12 */
35 KTIMEDATE_DAY, 'd', MAX_DAY_VALUE, /* days max. 31 */
39 /* Encodings to and from relative dates. The caller is responsible for
40 * enforcing appropriate use of these routines
43 ktimeRelDate_ToLong(kdptr)
44 struct ktime_date *kdptr;
48 retval = (((kdptr->year*(MAX_MONTH_VALUE+1)) +
49 kdptr->month)*(MAX_DAY_VALUE+1)) + kdptr->day;
53 /* LongTo_ktimeRelDate
54 * Convert a relative date encoded in a long - back into a ktime_date
58 LongTo_ktimeRelDate(longDate, kdptr)
60 struct ktime_date *kdptr;
62 bzero(kdptr, sizeof(*kdptr));
64 kdptr->day = longDate % (MAX_DAY_VALUE + 1);
65 if ( kdptr->day != 0 )
66 kdptr->mask |= KTIMEDATE_DAY;
68 longDate = longDate/(MAX_DAY_VALUE + 1);
70 kdptr->month = longDate % (MAX_MONTH_VALUE + 1);
71 if ( kdptr->month != 0 )
72 kdptr->mask |= KTIMEDATE_MONTH;
74 longDate = longDate/(MAX_MONTH_VALUE + 1);
76 kdptr->year = longDate;
77 if ( kdptr->year != 0 )
78 kdptr->mask |= KTIMEDATE_YEAR;
85 /* First some date storage and retrieval routines.
86 * These routines are for convert ktime date structures into text, and back.
87 * the format is compact and suitable for relative dates. These are used
88 * to store dates into the backup database.
91 /* ktimeDate_ToCompactString
92 * convert the ktime into a compact text form.
94 * pointer to a static string containing the text form of the ktime.
96 * it assumes that non-valid portions of the date are set to 0 and that
97 * all date fields are non-negative.
101 ktimeDate_ToCompactString(kdptr)
102 struct ktime_date *kdptr;
106 sprintf(buffer, "%-d:%-d:%-d:%-d:%-d:%-d",
117 /* CompactStringTo_ktimeDate
118 * parses the string and places it in the ktime structure
121 * -1 - failed, string format error
124 CompactStringTo_ktimeDate(stptr, kdptr)
126 struct ktime_date *kdptr;
130 code = sscanf(stptr, "%d:%d:%d:%d:%d:%d",
144 kdptr->mask |= KTIMEDATE_YEAR;
147 kdptr->mask |= KTIMEDATE_MONTH;
150 kdptr->mask |= KTIMEDATE_DAY;
153 kdptr->mask |= KTIMEDATE_HOUR;
156 kdptr->mask |= KTIMEDATE_MIN;
159 kdptr->mask |= KTIMEDATE_SEC;
164 /* ktimeDate_FromLong
165 * Converts a time in seconds, to a time (in ktime_date format). Result is
166 * placed in the supplied structure
168 * timeSecs - time in seconds
169 * ktimePtr - ptr to struct for the return value
172 ktimeDate_FromLong(timeSecs, ktimePtr)
174 struct ktime_date *ktimePtr;
178 timePtr = localtime(&timeSecs);
180 /* copy the relevant fields */
181 ktimePtr->sec = timePtr->sec;
182 ktimePtr->min = timePtr->min;
183 ktimePtr->hour = timePtr->hour;
184 ktimePtr->day = timePtr->mday;
185 ktimePtr->month = timePtr->mon;
186 ktimePtr->year = timePtr->year;
188 ktimePtr->mask = KTIMEDATE_YEAR | KTIMEDATE_MONTH | KTIMEDATE_DAY |
189 KTIMEDATE_HOUR | KTIMEDATE_MIN | KTIMEDATE_SEC;
196 * Returns current time with a relative time added. Note that the
197 * computation adds in most significant fields first, i.e. year, month
198 * day etc. Addition of least significant fields would produce different
199 * results (depending on the data).
201 * relDatePtr - a ktime_date containing a relative time specification
203 * returns current time with relative time added.
207 AddKtimeToNow( relDatePtr )
208 struct ktime_date *relDatePtr;
210 struct parseseqS typePtr;
213 static struct ktime_date absDate;
215 curTime = time(0); /* get current time */
216 ktimeDate_FromLong(curTime, &absDate); /* convert to ktime */
219 absDate.year += relDatePtr->year;
222 absDate.month += relDatePtr->month;
223 if ( absDate.month > 12 )
225 moreYears = absDate.month / 12;
226 absDate.month = absDate.month % 12;
227 absDate.year += moreYears;
230 /* day computations depend upon month size, so do these in seconds */
231 curTime = ktime_InterpretDate(&absDate);
233 curTime = curTime + relDatePtr->sec + relDatePtr->min*60 +
234 relDatePtr->hour*60*60 + relDatePtr->day*24*60*60;
240 #define RD_DIGIT_LIMIT 4 /* max. no. digits permitted */
244 * Parses a relative date of the form <n>y<n>m<n>d representing years
245 * months and days. <n> is limited to RD_DIGIT_LIMIT digits in length.
247 * dateStr - ptr to string to parse. Leading white space ingnored.
249 * returns a ptr to a static ktime_date structure containing
250 * appropriately set fields. The mask field is unused.
251 * 0 - error in date specification
255 ParseRelDate(dateStr, relDatePtr)
257 struct ktime_date *relDatePtr;
259 struct parseseqS *psPtr;
260 afs_int32 value, digit_limit;
261 afs_int32 type_index;
263 bzero(relDatePtr, sizeof(*relDatePtr));
269 while ( isspace(*dateStr) ) /* skip leading whitespace */
272 if ( isdigit(*dateStr) == 0 )
275 digit_limit = RD_DIGIT_LIMIT;
277 while ( isdigit(*dateStr) )
279 value = value*10 + *dateStr - '0';
281 if ( digit_limit-- == 0 )
285 psPtr = &parseseq[type_index];
286 /* determine the units. Search for a matching type character */
287 while ( (psPtr->ps_keychar != *dateStr)
288 && (psPtr->ps_keychar != 0)
292 psPtr = &parseseq[type_index];
295 /* no matching type found */
296 if ( psPtr->ps_keychar == 0 )
299 /* check the bounds on the maximum value. Can't be negative
300 * and if a maximum value is specified, check against it
303 || ((psPtr->ps_maxValue > 0) && (value > psPtr->ps_maxValue))
307 /* save computed value in the relevant type field */
308 switch ( psPtr->ps_field )
311 relDatePtr->year = value;
312 relDatePtr->mask |= KTIMEDATE_YEAR;
315 case KTIMEDATE_MONTH:
316 relDatePtr->month = value;
317 relDatePtr->mask |= KTIMEDATE_MONTH;
321 relDatePtr->mask |= KTIMEDATE_DAY;
322 relDatePtr->day = value;
328 dateStr++; /* next digit */
332 /* no more chars to process, return the result */
342 * returns a static string representing the relative date. This is in
343 * a format acceptable to the relative date parser.
345 * datePtr - relative date to be converted.
347 * ptr to static string
351 RelDatetoString(datePtr)
352 struct ktime_date *datePtr;
354 static char dateString[64];
355 char tempstring[64], *sptr;
358 sptr = &dateString[0];
360 if ( datePtr->mask & KTIMEDATE_YEAR )
362 sprintf(tempstring, "%-dy", datePtr->year);
363 strcat(sptr, tempstring);
366 if ( datePtr->mask & KTIMEDATE_MONTH )
369 sprintf(tempstring, "%-dm", datePtr->month);
370 strcat(sptr, tempstring);
373 if ( datePtr->mask & KTIMEDATE_DAY )
376 sprintf(tempstring, "%-dd", datePtr->day);
377 strcat(sptr, tempstring);
388 /* bc_ParseExpiration
391 * dates are specified as absolute or relative, the syntax is:
392 * absolute: at %d/%d/%d [%d:%d] where [..] is optional
393 * relative: in [%dy][%dm][%dd] where at least one component
398 bc_ParseExpiration(paramPtr, expType, expDate)
399 struct cmd_parmdesc *paramPtr;
403 struct cmd_item *itemPtr, *tempPtr;
404 struct ktime_date kt;
406 afs_int32 length = 0;
409 if ( paramPtr->items == 0 )
411 /* no expiration specified */
412 *expType = BC_NO_EXPDATE;
417 /* some form of expiration date specified. First validate the prefix */
418 itemPtr = paramPtr->items;
420 if ( strcmp(itemPtr->data, "at") == 0 )
422 *expType = BC_ABS_EXPDATE;
425 if ( strcmp(itemPtr->data, "in") == 0 )
427 *expType = BC_REL_EXPDATE;
432 /* before parsing the date string - concatenate all the pieces */
433 itemPtr = itemPtr->next;
436 /* compute the length of string required */
437 while ( tempPtr != 0 )
439 length += strlen(tempPtr->data);
440 tempPtr = tempPtr->next;
441 length++; /* space or null terminator */
443 if ( length == 0 ) /* no actual date string */
446 dateString = (char *) malloc(length);
447 if ( dateString == 0 )
450 /* now assemble the date string */
452 while ( itemPtr != 0 )
454 strcat(dateString, itemPtr->data);
455 itemPtr = itemPtr->next;
457 strcat(dateString, " ");
463 code = ktime_DateToLong(dateString, expDate);
469 code = ParseRelDate(dateString, &kt);
472 *expDate = ktimeRelDate_ToLong(&kt);
487 /* assign default values */
488 *expType = BC_NO_EXPDATE;