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>
17 #include <sys/types.h>
18 #include <afs/ktime.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
27 #define MAX_YEAR_VALUE 0
28 #define MAX_MONTH_VALUE 11
29 #define MAX_DAY_VALUE 30
31 /* for parsing relative expiration dates */
32 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 */
42 /* Encodings to and from relative dates. The caller is responsible for
43 * enforcing appropriate use of these routines
46 ktimeRelDate_ToLong(kdptr)
47 struct ktime_date *kdptr;
52 (((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 memset(kdptr, 0, sizeof(*kdptr));
68 kdptr->day = longDate % (MAX_DAY_VALUE + 1);
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;
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", kdptr->year, kdptr->month,
111 kdptr->day, kdptr->hour, kdptr->min, kdptr->sec);
116 /* CompactStringTo_ktimeDate
117 * parses the string and places it in the ktime structure
120 * -1 - failed, string format error
123 CompactStringTo_ktimeDate(stptr, kdptr)
125 struct ktime_date *kdptr;
130 sscanf(stptr, "%d:%d:%d:%d:%d:%d", &kdptr->year, &kdptr->month,
131 &kdptr->day, &kdptr->hour, &kdptr->min, &kdptr->sec);
139 kdptr->mask |= KTIMEDATE_YEAR;
142 kdptr->mask |= KTIMEDATE_MONTH;
145 kdptr->mask |= KTIMEDATE_DAY;
148 kdptr->mask |= KTIMEDATE_HOUR;
151 kdptr->mask |= KTIMEDATE_MIN;
154 kdptr->mask |= KTIMEDATE_SEC;
159 /* ktimeDate_FromLong
160 * Converts a time in seconds, to a time (in ktime_date format). Result is
161 * placed in the supplied structure
163 * timeSecs - time in seconds
164 * ktimePtr - ptr to struct for the return value
167 ktimeDate_FromLong(timeSecs, ktimePtr)
169 struct ktime_date *ktimePtr;
173 timePtr = localtime(&timeSecs);
175 /* copy the relevant fields */
176 ktimePtr->sec = timePtr->sec;
177 ktimePtr->min = timePtr->min;
178 ktimePtr->hour = timePtr->hour;
179 ktimePtr->day = timePtr->mday;
180 ktimePtr->month = timePtr->mon;
181 ktimePtr->year = timePtr->year;
184 KTIMEDATE_YEAR | KTIMEDATE_MONTH | KTIMEDATE_DAY | KTIMEDATE_HOUR |
185 KTIMEDATE_MIN | KTIMEDATE_SEC;
192 * Returns current time with a relative time added. Note that the
193 * computation adds in most significant fields first, i.e. year, month
194 * day etc. Addition of least significant fields would produce different
195 * results (depending on the data).
197 * relDatePtr - a ktime_date containing a relative time specification
199 * returns current time with relative time added.
203 AddKtimeToNow(relDatePtr)
204 struct ktime_date *relDatePtr;
206 struct parseseqS typePtr;
209 static struct ktime_date absDate;
211 curTime = time(0); /* get current time */
212 ktimeDate_FromLong(curTime, &absDate); /* convert to ktime */
215 absDate.year += relDatePtr->year;
218 absDate.month += relDatePtr->month;
219 if (absDate.month > 12) {
220 moreYears = absDate.month / 12;
221 absDate.month = absDate.month % 12;
222 absDate.year += moreYears;
225 /* day computations depend upon month size, so do these in seconds */
226 curTime = ktime_InterpretDate(&absDate);
229 curTime + relDatePtr->sec + relDatePtr->min * 60 +
230 relDatePtr->hour * 60 * 60 + relDatePtr->day * 24 * 60 * 60;
236 #define RD_DIGIT_LIMIT 4 /* max. no. digits permitted */
240 * Parses a relative date of the form <n>y<n>m<n>d representing years
241 * months and days. <n> is limited to RD_DIGIT_LIMIT digits in length.
243 * dateStr - ptr to string to parse. Leading white space ingnored.
245 * returns a ptr to a static ktime_date structure containing
246 * appropriately set fields. The mask field is unused.
247 * 0 - error in date specification
251 ParseRelDate(dateStr, relDatePtr)
253 struct ktime_date *relDatePtr;
255 struct parseseqS *psPtr;
256 afs_int32 value, digit_limit;
257 afs_int32 type_index;
259 memset(relDatePtr, 0, sizeof(*relDatePtr));
264 while (isspace(*dateStr)) /* skip leading whitespace */
267 if (isdigit(*dateStr) == 0)
270 digit_limit = RD_DIGIT_LIMIT;
272 while (isdigit(*dateStr)) {
273 value = value * 10 + *dateStr - '0';
275 if (digit_limit-- == 0)
279 psPtr = &parseseq[type_index];
280 /* determine the units. Search for a matching type character */
281 while ((psPtr->ps_keychar != *dateStr)
282 && (psPtr->ps_keychar != 0)
285 psPtr = &parseseq[type_index];
288 /* no matching type found */
289 if (psPtr->ps_keychar == 0)
292 /* check the bounds on the maximum value. Can't be negative
293 * and if a maximum value is specified, check against it
296 || ((psPtr->ps_maxValue > 0) && (value > psPtr->ps_maxValue))
300 /* save computed value in the relevant type field */
301 switch (psPtr->ps_field) {
303 relDatePtr->year = value;
304 relDatePtr->mask |= KTIMEDATE_YEAR;
307 case KTIMEDATE_MONTH:
308 relDatePtr->month = value;
309 relDatePtr->mask |= KTIMEDATE_MONTH;
313 relDatePtr->mask |= KTIMEDATE_DAY;
314 relDatePtr->day = value;
320 dateStr++; /* next digit */
323 /* no more chars to process, return the result */
333 * returns a static string representing the relative date. This is in
334 * a format acceptable to the relative date parser.
336 * datePtr - relative date to be converted.
338 * ptr to static string
342 RelDatetoString(datePtr)
343 struct ktime_date *datePtr;
345 static char dateString[64];
346 char tempstring[64], *sptr;
349 sptr = &dateString[0];
351 if (datePtr->mask & KTIMEDATE_YEAR) {
352 sprintf(tempstring, "%-dy", datePtr->year);
353 strcat(sptr, tempstring);
356 if (datePtr->mask & KTIMEDATE_MONTH) {
358 sprintf(tempstring, "%-dm", datePtr->month);
359 strcat(sptr, tempstring);
362 if (datePtr->mask & KTIMEDATE_DAY) {
364 sprintf(tempstring, "%-dd", datePtr->day);
365 strcat(sptr, tempstring);
376 /* bc_ParseExpiration
379 * dates are specified as absolute or relative, the syntax is:
380 * absolute: at %d/%d/%d [%d:%d] where [..] is optional
381 * relative: in [%dy][%dm][%dd] where at least one component
386 bc_ParseExpiration(paramPtr, expType, expDate)
387 struct cmd_parmdesc *paramPtr;
391 struct cmd_item *itemPtr, *tempPtr;
392 struct ktime_date kt;
394 afs_int32 length = 0;
397 if (paramPtr->items == 0) {
398 /* no expiration specified */
399 *expType = BC_NO_EXPDATE;
404 /* some form of expiration date specified. First validate the prefix */
405 itemPtr = paramPtr->items;
407 if (strcmp(itemPtr->data, "at") == 0) {
408 *expType = BC_ABS_EXPDATE;
409 } else if (strcmp(itemPtr->data, "in") == 0) {
410 *expType = BC_REL_EXPDATE;
414 /* before parsing the date string - concatenate all the pieces */
415 itemPtr = itemPtr->next;
418 /* compute the length of string required */
419 while (tempPtr != 0) {
420 length += strlen(tempPtr->data);
421 tempPtr = tempPtr->next;
422 length++; /* space or null terminator */
424 if (length == 0) /* no actual date string */
427 dateString = (char *)malloc(length);
431 /* now assemble the date string */
433 while (itemPtr != 0) {
434 strcat(dateString, itemPtr->data);
435 itemPtr = itemPtr->next;
437 strcat(dateString, " ");
442 code = ktime_DateToLong(dateString, expDate);
448 code = ParseRelDate(dateString, &kt);
451 *expDate = ktimeRelDate_ToLong(&kt);
466 /* assign default values */
467 *expType = BC_NO_EXPDATE;