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>
15 #include <sys/types.h>
16 #include <afs/ktime.h>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
24 #define MAX_YEAR_VALUE 0
25 #define MAX_MONTH_VALUE 11
26 #define MAX_DAY_VALUE 30
28 /* for parsing relative expiration dates */
29 static struct parseseqS {
32 afs_int32 ps_maxValue;
34 KTIMEDATE_YEAR, 'y', MAX_YEAR_VALUE, /* no max. value */
35 KTIMEDATE_MONTH, 'm', MAX_MONTH_VALUE, /* months max. 12 */
36 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;
49 (((kdptr->year * (MAX_MONTH_VALUE + 1)) +
50 kdptr->month) * (MAX_DAY_VALUE + 1)) + kdptr->day;
54 /* LongTo_ktimeRelDate
55 * Convert a relative date encoded in a long - back into a ktime_date
59 LongTo_ktimeRelDate(longDate, kdptr)
61 struct ktime_date *kdptr;
63 memset(kdptr, 0, sizeof(*kdptr));
65 kdptr->day = longDate % (MAX_DAY_VALUE + 1);
67 kdptr->mask |= KTIMEDATE_DAY;
69 longDate = longDate / (MAX_DAY_VALUE + 1);
71 kdptr->month = longDate % (MAX_MONTH_VALUE + 1);
72 if (kdptr->month != 0)
73 kdptr->mask |= KTIMEDATE_MONTH;
75 longDate = longDate / (MAX_MONTH_VALUE + 1);
77 kdptr->year = longDate;
79 kdptr->mask |= KTIMEDATE_YEAR;
86 /* First some date storage and retrieval routines.
87 * These routines are for convert ktime date structures into text, and back.
88 * the format is compact and suitable for relative dates. These are used
89 * to store dates into the backup database.
92 /* ktimeDate_ToCompactString
93 * convert the ktime into a compact text form.
95 * pointer to a static string containing the text form of the ktime.
97 * it assumes that non-valid portions of the date are set to 0 and that
98 * all date fields are non-negative.
102 ktimeDate_ToCompactString(kdptr)
103 struct ktime_date *kdptr;
107 sprintf(buffer, "%-d:%-d:%-d:%-d:%-d:%-d", kdptr->year, kdptr->month,
108 kdptr->day, kdptr->hour, kdptr->min, kdptr->sec);
113 /* CompactStringTo_ktimeDate
114 * parses the string and places it in the ktime structure
117 * -1 - failed, string format error
120 CompactStringTo_ktimeDate(stptr, kdptr)
122 struct ktime_date *kdptr;
127 sscanf(stptr, "%d:%d:%d:%d:%d:%d", &kdptr->year, &kdptr->month,
128 &kdptr->day, &kdptr->hour, &kdptr->min, &kdptr->sec);
136 kdptr->mask |= KTIMEDATE_YEAR;
139 kdptr->mask |= KTIMEDATE_MONTH;
142 kdptr->mask |= KTIMEDATE_DAY;
145 kdptr->mask |= KTIMEDATE_HOUR;
148 kdptr->mask |= KTIMEDATE_MIN;
151 kdptr->mask |= KTIMEDATE_SEC;
156 /* ktimeDate_FromLong
157 * Converts a time in seconds, to a time (in ktime_date format). Result is
158 * placed in the supplied structure
160 * timeSecs - time in seconds
161 * ktimePtr - ptr to struct for the return value
164 ktimeDate_FromLong(timeSecs, ktimePtr)
166 struct ktime_date *ktimePtr;
170 timePtr = localtime(&timeSecs);
172 /* copy the relevant fields */
173 ktimePtr->sec = timePtr->sec;
174 ktimePtr->min = timePtr->min;
175 ktimePtr->hour = timePtr->hour;
176 ktimePtr->day = timePtr->mday;
177 ktimePtr->month = timePtr->mon;
178 ktimePtr->year = timePtr->year;
181 KTIMEDATE_YEAR | KTIMEDATE_MONTH | KTIMEDATE_DAY | KTIMEDATE_HOUR |
182 KTIMEDATE_MIN | KTIMEDATE_SEC;
189 * Returns current time with a relative time added. Note that the
190 * computation adds in most significant fields first, i.e. year, month
191 * day etc. Addition of least significant fields would produce different
192 * results (depending on the data).
194 * relDatePtr - a ktime_date containing a relative time specification
196 * returns current time with relative time added.
200 AddKtimeToNow(relDatePtr)
201 struct ktime_date *relDatePtr;
203 struct parseseqS typePtr;
206 static struct ktime_date absDate;
208 curTime = time(0); /* get current time */
209 ktimeDate_FromLong(curTime, &absDate); /* convert to ktime */
212 absDate.year += relDatePtr->year;
215 absDate.month += relDatePtr->month;
216 if (absDate.month > 12) {
217 moreYears = absDate.month / 12;
218 absDate.month = absDate.month % 12;
219 absDate.year += moreYears;
222 /* day computations depend upon month size, so do these in seconds */
223 curTime = ktime_InterpretDate(&absDate);
226 curTime + relDatePtr->sec + relDatePtr->min * 60 +
227 relDatePtr->hour * 60 * 60 + relDatePtr->day * 24 * 60 * 60;
233 #define RD_DIGIT_LIMIT 4 /* max. no. digits permitted */
237 * Parses a relative date of the form <n>y<n>m<n>d representing years
238 * months and days. <n> is limited to RD_DIGIT_LIMIT digits in length.
240 * dateStr - ptr to string to parse. Leading white space ingnored.
242 * returns a ptr to a static ktime_date structure containing
243 * appropriately set fields. The mask field is unused.
244 * 0 - error in date specification
248 ParseRelDate(dateStr, relDatePtr)
250 struct ktime_date *relDatePtr;
252 struct parseseqS *psPtr;
253 afs_int32 value, digit_limit;
254 afs_int32 type_index;
256 memset(relDatePtr, 0, sizeof(*relDatePtr));
261 while (isspace(*dateStr)) /* skip leading whitespace */
264 if (isdigit(*dateStr) == 0)
267 digit_limit = RD_DIGIT_LIMIT;
269 while (isdigit(*dateStr)) {
270 value = value * 10 + *dateStr - '0';
272 if (digit_limit-- == 0)
276 psPtr = &parseseq[type_index];
277 /* determine the units. Search for a matching type character */
278 while ((psPtr->ps_keychar != *dateStr)
279 && (psPtr->ps_keychar != 0)
282 psPtr = &parseseq[type_index];
285 /* no matching type found */
286 if (psPtr->ps_keychar == 0)
289 /* check the bounds on the maximum value. Can't be negative
290 * and if a maximum value is specified, check against it
293 || ((psPtr->ps_maxValue > 0) && (value > psPtr->ps_maxValue))
297 /* save computed value in the relevant type field */
298 switch (psPtr->ps_field) {
300 relDatePtr->year = value;
301 relDatePtr->mask |= KTIMEDATE_YEAR;
304 case KTIMEDATE_MONTH:
305 relDatePtr->month = value;
306 relDatePtr->mask |= KTIMEDATE_MONTH;
310 relDatePtr->mask |= KTIMEDATE_DAY;
311 relDatePtr->day = value;
317 dateStr++; /* next digit */
320 /* no more chars to process, return the result */
330 * returns a static string representing the relative date. This is in
331 * a format acceptable to the relative date parser.
333 * datePtr - relative date to be converted.
335 * ptr to static string
339 RelDatetoString(datePtr)
340 struct ktime_date *datePtr;
342 static char dateString[64];
343 char tempstring[64], *sptr;
346 sptr = &dateString[0];
348 if (datePtr->mask & KTIMEDATE_YEAR) {
349 sprintf(tempstring, "%-dy", datePtr->year);
350 strcat(sptr, tempstring);
353 if (datePtr->mask & KTIMEDATE_MONTH) {
355 sprintf(tempstring, "%-dm", datePtr->month);
356 strcat(sptr, tempstring);
359 if (datePtr->mask & KTIMEDATE_DAY) {
361 sprintf(tempstring, "%-dd", datePtr->day);
362 strcat(sptr, tempstring);
373 /* bc_ParseExpiration
376 * dates are specified as absolute or relative, the syntax is:
377 * absolute: at %d/%d/%d [%d:%d] where [..] is optional
378 * relative: in [%dy][%dm][%dd] where at least one component
383 bc_ParseExpiration(struct cmd_parmdesc *paramPtr, afs_int32 *expType,
386 struct cmd_item *itemPtr, *tempPtr;
387 struct ktime_date kt;
389 afs_int32 length = 0;
392 if (paramPtr->items == 0) {
393 /* no expiration specified */
394 *expType = BC_NO_EXPDATE;
399 /* some form of expiration date specified. First validate the prefix */
400 itemPtr = paramPtr->items;
402 if (strcmp(itemPtr->data, "at") == 0) {
403 *expType = BC_ABS_EXPDATE;
404 } else if (strcmp(itemPtr->data, "in") == 0) {
405 *expType = BC_REL_EXPDATE;
409 /* before parsing the date string - concatenate all the pieces */
410 itemPtr = itemPtr->next;
413 /* compute the length of string required */
414 while (tempPtr != 0) {
415 length += strlen(tempPtr->data);
416 tempPtr = tempPtr->next;
417 length++; /* space or null terminator */
419 if (length == 0) /* no actual date string */
422 dateString = (char *)malloc(length);
426 /* now assemble the date string */
428 while (itemPtr != 0) {
429 strcat(dateString, itemPtr->data);
430 itemPtr = itemPtr->next;
432 strcat(dateString, " ");
437 code = ktime_DateToLong(dateString, expDate);
443 code = ParseRelDate(dateString, &kt);
446 *expDate = ktimeRelDate_ToLong(&kt);
461 /* assign default values */
462 *expType = BC_NO_EXPDATE;