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 <afsconfig.h>
11 #include <afs/param.h>
16 #include <sys/types.h>
17 #include <afs/ktime.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
26 #define MAX_YEAR_VALUE 0
27 #define MAX_MONTH_VALUE 11
28 #define MAX_DAY_VALUE 30
30 /* for parsing relative expiration dates */
31 static struct parseseqS
35 afs_int32 ps_maxValue;
37 KTIMEDATE_YEAR, 'y', MAX_YEAR_VALUE, /* no max. value */
38 KTIMEDATE_MONTH, 'm', MAX_MONTH_VALUE, /* months max. 12 */
39 KTIMEDATE_DAY, 'd', MAX_DAY_VALUE, /* days max. 31 */
43 /* Encodings to and from relative dates. The caller is responsible for
44 * enforcing appropriate use of these routines
47 ktimeRelDate_ToLong(kdptr)
48 struct ktime_date *kdptr;
52 retval = (((kdptr->year*(MAX_MONTH_VALUE+1)) +
53 kdptr->month)*(MAX_DAY_VALUE+1)) + kdptr->day;
57 /* LongTo_ktimeRelDate
58 * Convert a relative date encoded in a long - back into a ktime_date
62 LongTo_ktimeRelDate(longDate, kdptr)
64 struct ktime_date *kdptr;
66 bzero(kdptr, sizeof(*kdptr));
68 kdptr->day = longDate % (MAX_DAY_VALUE + 1);
69 if ( kdptr->day != 0 )
70 kdptr->mask |= KTIMEDATE_DAY;
72 longDate = longDate/(MAX_DAY_VALUE + 1);
74 kdptr->month = longDate % (MAX_MONTH_VALUE + 1);
75 if ( kdptr->month != 0 )
76 kdptr->mask |= KTIMEDATE_MONTH;
78 longDate = longDate/(MAX_MONTH_VALUE + 1);
80 kdptr->year = longDate;
81 if ( kdptr->year != 0 )
82 kdptr->mask |= KTIMEDATE_YEAR;
89 /* First some date storage and retrieval routines.
90 * These routines are for convert ktime date structures into text, and back.
91 * the format is compact and suitable for relative dates. These are used
92 * to store dates into the backup database.
95 /* ktimeDate_ToCompactString
96 * convert the ktime into a compact text form.
98 * pointer to a static string containing the text form of the ktime.
100 * it assumes that non-valid portions of the date are set to 0 and that
101 * all date fields are non-negative.
105 ktimeDate_ToCompactString(kdptr)
106 struct ktime_date *kdptr;
110 sprintf(buffer, "%-d:%-d:%-d:%-d:%-d:%-d",
121 /* CompactStringTo_ktimeDate
122 * parses the string and places it in the ktime structure
125 * -1 - failed, string format error
128 CompactStringTo_ktimeDate(stptr, kdptr)
130 struct ktime_date *kdptr;
134 code = sscanf(stptr, "%d:%d:%d:%d:%d:%d",
148 kdptr->mask |= KTIMEDATE_YEAR;
151 kdptr->mask |= KTIMEDATE_MONTH;
154 kdptr->mask |= KTIMEDATE_DAY;
157 kdptr->mask |= KTIMEDATE_HOUR;
160 kdptr->mask |= KTIMEDATE_MIN;
163 kdptr->mask |= KTIMEDATE_SEC;
168 /* ktimeDate_FromLong
169 * Converts a time in seconds, to a time (in ktime_date format). Result is
170 * placed in the supplied structure
172 * timeSecs - time in seconds
173 * ktimePtr - ptr to struct for the return value
176 ktimeDate_FromLong(timeSecs, ktimePtr)
178 struct ktime_date *ktimePtr;
182 timePtr = localtime(&timeSecs);
184 /* copy the relevant fields */
185 ktimePtr->sec = timePtr->sec;
186 ktimePtr->min = timePtr->min;
187 ktimePtr->hour = timePtr->hour;
188 ktimePtr->day = timePtr->mday;
189 ktimePtr->month = timePtr->mon;
190 ktimePtr->year = timePtr->year;
192 ktimePtr->mask = KTIMEDATE_YEAR | KTIMEDATE_MONTH | KTIMEDATE_DAY |
193 KTIMEDATE_HOUR | KTIMEDATE_MIN | KTIMEDATE_SEC;
200 * Returns current time with a relative time added. Note that the
201 * computation adds in most significant fields first, i.e. year, month
202 * day etc. Addition of least significant fields would produce different
203 * results (depending on the data).
205 * relDatePtr - a ktime_date containing a relative time specification
207 * returns current time with relative time added.
211 AddKtimeToNow( relDatePtr )
212 struct ktime_date *relDatePtr;
214 struct parseseqS typePtr;
217 static struct ktime_date absDate;
219 curTime = time(0); /* get current time */
220 ktimeDate_FromLong(curTime, &absDate); /* convert to ktime */
223 absDate.year += relDatePtr->year;
226 absDate.month += relDatePtr->month;
227 if ( absDate.month > 12 )
229 moreYears = absDate.month / 12;
230 absDate.month = absDate.month % 12;
231 absDate.year += moreYears;
234 /* day computations depend upon month size, so do these in seconds */
235 curTime = ktime_InterpretDate(&absDate);
237 curTime = curTime + relDatePtr->sec + relDatePtr->min*60 +
238 relDatePtr->hour*60*60 + relDatePtr->day*24*60*60;
244 #define RD_DIGIT_LIMIT 4 /* max. no. digits permitted */
248 * Parses a relative date of the form <n>y<n>m<n>d representing years
249 * months and days. <n> is limited to RD_DIGIT_LIMIT digits in length.
251 * dateStr - ptr to string to parse. Leading white space ingnored.
253 * returns a ptr to a static ktime_date structure containing
254 * appropriately set fields. The mask field is unused.
255 * 0 - error in date specification
259 ParseRelDate(dateStr, relDatePtr)
261 struct ktime_date *relDatePtr;
263 struct parseseqS *psPtr;
264 afs_int32 value, digit_limit;
265 afs_int32 type_index;
267 bzero(relDatePtr, sizeof(*relDatePtr));
273 while ( isspace(*dateStr) ) /* skip leading whitespace */
276 if ( isdigit(*dateStr) == 0 )
279 digit_limit = RD_DIGIT_LIMIT;
281 while ( isdigit(*dateStr) )
283 value = value*10 + *dateStr - '0';
285 if ( digit_limit-- == 0 )
289 psPtr = &parseseq[type_index];
290 /* determine the units. Search for a matching type character */
291 while ( (psPtr->ps_keychar != *dateStr)
292 && (psPtr->ps_keychar != 0)
296 psPtr = &parseseq[type_index];
299 /* no matching type found */
300 if ( psPtr->ps_keychar == 0 )
303 /* check the bounds on the maximum value. Can't be negative
304 * and if a maximum value is specified, check against it
307 || ((psPtr->ps_maxValue > 0) && (value > psPtr->ps_maxValue))
311 /* save computed value in the relevant type field */
312 switch ( psPtr->ps_field )
315 relDatePtr->year = value;
316 relDatePtr->mask |= KTIMEDATE_YEAR;
319 case KTIMEDATE_MONTH:
320 relDatePtr->month = value;
321 relDatePtr->mask |= KTIMEDATE_MONTH;
325 relDatePtr->mask |= KTIMEDATE_DAY;
326 relDatePtr->day = value;
332 dateStr++; /* next digit */
336 /* no more chars to process, return the result */
346 * returns a static string representing the relative date. This is in
347 * a format acceptable to the relative date parser.
349 * datePtr - relative date to be converted.
351 * ptr to static string
355 RelDatetoString(datePtr)
356 struct ktime_date *datePtr;
358 static char dateString[64];
359 char tempstring[64], *sptr;
362 sptr = &dateString[0];
364 if ( datePtr->mask & KTIMEDATE_YEAR )
366 sprintf(tempstring, "%-dy", datePtr->year);
367 strcat(sptr, tempstring);
370 if ( datePtr->mask & KTIMEDATE_MONTH )
373 sprintf(tempstring, "%-dm", datePtr->month);
374 strcat(sptr, tempstring);
377 if ( datePtr->mask & KTIMEDATE_DAY )
380 sprintf(tempstring, "%-dd", datePtr->day);
381 strcat(sptr, tempstring);
392 /* bc_ParseExpiration
395 * dates are specified as absolute or relative, the syntax is:
396 * absolute: at %d/%d/%d [%d:%d] where [..] is optional
397 * relative: in [%dy][%dm][%dd] where at least one component
402 bc_ParseExpiration(paramPtr, expType, expDate)
403 struct cmd_parmdesc *paramPtr;
407 struct cmd_item *itemPtr, *tempPtr;
408 struct ktime_date kt;
410 afs_int32 length = 0;
413 if ( paramPtr->items == 0 )
415 /* no expiration specified */
416 *expType = BC_NO_EXPDATE;
421 /* some form of expiration date specified. First validate the prefix */
422 itemPtr = paramPtr->items;
424 if ( strcmp(itemPtr->data, "at") == 0 )
426 *expType = BC_ABS_EXPDATE;
429 if ( strcmp(itemPtr->data, "in") == 0 )
431 *expType = BC_REL_EXPDATE;
436 /* before parsing the date string - concatenate all the pieces */
437 itemPtr = itemPtr->next;
440 /* compute the length of string required */
441 while ( tempPtr != 0 )
443 length += strlen(tempPtr->data);
444 tempPtr = tempPtr->next;
445 length++; /* space or null terminator */
447 if ( length == 0 ) /* no actual date string */
450 dateString = (char *) malloc(length);
451 if ( dateString == 0 )
454 /* now assemble the date string */
456 while ( itemPtr != 0 )
458 strcat(dateString, itemPtr->data);
459 itemPtr = itemPtr->next;
461 strcat(dateString, " ");
467 code = ktime_DateToLong(dateString, expDate);
473 code = ParseRelDate(dateString, &kt);
476 *expDate = ktimeRelDate_ToLong(&kt);
491 /* assign default values */
492 *expType = BC_NO_EXPDATE;