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>
18 #include <afs/ktime.h>
23 #define MAX_YEAR_VALUE 0
24 #define MAX_MONTH_VALUE 11
25 #define MAX_DAY_VALUE 30
27 /* for parsing relative expiration dates */
28 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 */
38 /* Encodings to and from relative dates. The caller is responsible for
39 * enforcing appropriate use of these routines
42 ktimeRelDate_ToLong(kdptr)
43 struct ktime_date *kdptr;
48 (((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 memset(kdptr, 0, sizeof(*kdptr));
64 kdptr->day = longDate % (MAX_DAY_VALUE + 1);
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;
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", kdptr->year, kdptr->month,
107 kdptr->day, kdptr->hour, kdptr->min, kdptr->sec);
112 /* CompactStringTo_ktimeDate
113 * parses the string and places it in the ktime structure
116 * -1 - failed, string format error
119 CompactStringTo_ktimeDate(stptr, kdptr)
121 struct ktime_date *kdptr;
126 sscanf(stptr, "%d:%d:%d:%d:%d:%d", &kdptr->year, &kdptr->month,
127 &kdptr->day, &kdptr->hour, &kdptr->min, &kdptr->sec);
135 kdptr->mask |= KTIMEDATE_YEAR;
138 kdptr->mask |= KTIMEDATE_MONTH;
141 kdptr->mask |= KTIMEDATE_DAY;
144 kdptr->mask |= KTIMEDATE_HOUR;
147 kdptr->mask |= KTIMEDATE_MIN;
150 kdptr->mask |= KTIMEDATE_SEC;
155 /* ktimeDate_FromLong
156 * Converts a time in seconds, to a time (in ktime_date format). Result is
157 * placed in the supplied structure
159 * timeSecs - time in seconds
160 * ktimePtr - ptr to struct for the return value
163 ktimeDate_FromLong(timeSecs, ktimePtr)
165 struct ktime_date *ktimePtr;
169 timePtr = localtime(&timeSecs);
171 /* copy the relevant fields */
172 ktimePtr->sec = timePtr->sec;
173 ktimePtr->min = timePtr->min;
174 ktimePtr->hour = timePtr->hour;
175 ktimePtr->day = timePtr->mday;
176 ktimePtr->month = timePtr->mon;
177 ktimePtr->year = timePtr->year;
180 KTIMEDATE_YEAR | KTIMEDATE_MONTH | KTIMEDATE_DAY | KTIMEDATE_HOUR |
181 KTIMEDATE_MIN | KTIMEDATE_SEC;
188 * Returns current time with a relative time added. Note that the
189 * computation adds in most significant fields first, i.e. year, month
190 * day etc. Addition of least significant fields would produce different
191 * results (depending on the data).
193 * relDatePtr - a ktime_date containing a relative time specification
195 * returns current time with relative time added.
199 AddKtimeToNow(relDatePtr)
200 struct ktime_date *relDatePtr;
202 struct parseseqS typePtr;
205 static struct ktime_date absDate;
207 curTime = time(0); /* get current time */
208 ktimeDate_FromLong(curTime, &absDate); /* convert to ktime */
211 absDate.year += relDatePtr->year;
214 absDate.month += relDatePtr->month;
215 if (absDate.month > 12) {
216 moreYears = absDate.month / 12;
217 absDate.month = absDate.month % 12;
218 absDate.year += moreYears;
221 /* day computations depend upon month size, so do these in seconds */
222 curTime = ktime_InterpretDate(&absDate);
225 curTime + relDatePtr->sec + relDatePtr->min * 60 +
226 relDatePtr->hour * 60 * 60 + relDatePtr->day * 24 * 60 * 60;
232 #define RD_DIGIT_LIMIT 4 /* max. no. digits permitted */
236 * Parses a relative date of the form <n>y<n>m<n>d representing years
237 * months and days. <n> is limited to RD_DIGIT_LIMIT digits in length.
239 * dateStr - ptr to string to parse. Leading white space ingnored.
241 * returns a ptr to a static ktime_date structure containing
242 * appropriately set fields. The mask field is unused.
243 * 0 - error in date specification
247 ParseRelDate(dateStr, relDatePtr)
249 struct ktime_date *relDatePtr;
251 struct parseseqS *psPtr;
252 afs_int32 value, digit_limit;
253 afs_int32 type_index;
255 memset(relDatePtr, 0, sizeof(*relDatePtr));
260 while (isspace(*dateStr)) /* skip leading whitespace */
263 if (isdigit(*dateStr) == 0)
266 digit_limit = RD_DIGIT_LIMIT;
268 while (isdigit(*dateStr)) {
269 value = value * 10 + *dateStr - '0';
271 if (digit_limit-- == 0)
275 psPtr = &parseseq[type_index];
276 /* determine the units. Search for a matching type character */
277 while ((psPtr->ps_keychar != *dateStr)
278 && (psPtr->ps_keychar != 0)
281 psPtr = &parseseq[type_index];
284 /* no matching type found */
285 if (psPtr->ps_keychar == 0)
288 /* check the bounds on the maximum value. Can't be negative
289 * and if a maximum value is specified, check against it
292 || ((psPtr->ps_maxValue > 0) && (value > psPtr->ps_maxValue))
296 /* save computed value in the relevant type field */
297 switch (psPtr->ps_field) {
299 relDatePtr->year = value;
300 relDatePtr->mask |= KTIMEDATE_YEAR;
303 case KTIMEDATE_MONTH:
304 relDatePtr->month = value;
305 relDatePtr->mask |= KTIMEDATE_MONTH;
309 relDatePtr->mask |= KTIMEDATE_DAY;
310 relDatePtr->day = value;
316 dateStr++; /* next digit */
319 /* no more chars to process, return the result */
329 * returns a static string representing the relative date. This is in
330 * a format acceptable to the relative date parser.
332 * datePtr - relative date to be converted.
334 * ptr to static string
338 RelDatetoString(datePtr)
339 struct ktime_date *datePtr;
341 static char dateString[64];
342 char tempstring[64], *sptr;
345 sptr = &dateString[0];
347 if (datePtr->mask & KTIMEDATE_YEAR) {
348 sprintf(tempstring, "%-dy", datePtr->year);
349 strcat(sptr, tempstring);
352 if (datePtr->mask & KTIMEDATE_MONTH) {
354 sprintf(tempstring, "%-dm", datePtr->month);
355 strcat(sptr, tempstring);
358 if (datePtr->mask & KTIMEDATE_DAY) {
360 sprintf(tempstring, "%-dd", datePtr->day);
361 strcat(sptr, tempstring);
372 /* bc_ParseExpiration
375 * dates are specified as absolute or relative, the syntax is:
376 * absolute: at %d/%d/%d [%d:%d] where [..] is optional
377 * relative: in [%dy][%dm][%dd] where at least one component
382 bc_ParseExpiration(struct cmd_parmdesc *paramPtr, afs_int32 *expType,
385 struct cmd_item *itemPtr, *tempPtr;
386 struct ktime_date kt;
388 afs_int32 length = 0;
391 if (paramPtr->items == 0) {
392 /* no expiration specified */
393 *expType = BC_NO_EXPDATE;
398 /* some form of expiration date specified. First validate the prefix */
399 itemPtr = paramPtr->items;
401 if (strcmp(itemPtr->data, "at") == 0) {
402 *expType = BC_ABS_EXPDATE;
403 } else if (strcmp(itemPtr->data, "in") == 0) {
404 *expType = BC_REL_EXPDATE;
408 /* before parsing the date string - concatenate all the pieces */
409 itemPtr = itemPtr->next;
412 /* compute the length of string required */
413 while (tempPtr != 0) {
414 length += strlen(tempPtr->data);
415 tempPtr = tempPtr->next;
416 length++; /* space or null terminator */
418 if (length == 0) /* no actual date string */
421 dateString = malloc(length);
425 /* now assemble the date string */
427 while (itemPtr != 0) {
428 strcat(dateString, itemPtr->data);
429 itemPtr = itemPtr->next;
431 strcat(dateString, " ");
436 code = ktime_DateToLong(dateString, expDate);
442 code = ParseRelDate(dateString, &kt);
445 *expDate = ktimeRelDate_ToLong(&kt);
460 /* assign default values */
461 *expType = BC_NO_EXPDATE;