1 /*
2 * Copyright 2011, Nexenta Systems, Inc. All rights reserved.
3 * Copyright (c) 1994 Powerdog Industries. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
198 if (!isdigit(*buf))
199 return (NULL);
200
201 len = 2;
202 for (i = 0; len && isdigit(*buf); buf++) {
203 i *= 10;
204 i += *buf - '0';
205 len--;
206 }
207
208 if (c == 'M') {
209 if (i > 59)
210 return (NULL);
211 tm->tm_min = i;
212 } else {
213 if (i > 60)
214 return (NULL);
215 tm->tm_sec = i;
216 }
217
218 if (isspace(*buf))
219 while (*ptr != 0 && !isspace(*ptr))
220 ptr++;
221 break;
222
223 case 'H':
224 case 'I':
225 case 'k':
226 case 'l':
227 /*
228 * Of these, %l is the only specifier explicitly
229 * documented as not being zero-padded. However,
230 * there is no harm in allowing zero-padding.
231 *
232 * XXX The %l specifier may gobble one too many
233 * digits if used incorrectly.
234 */
235 if (!isdigit(*buf))
236 return (NULL);
237
238 len = 2;
239 for (i = 0; len && isdigit(*buf); buf++) {
240 i *= 10;
241 i += *buf - '0';
242 len--;
243 }
244 if (c == 'H' || c == 'k') {
245 if (i > 23)
246 return (NULL);
247 } else if (i > 12)
248 return (NULL);
249
250 tm->tm_hour = i;
251
252 if (isspace(*buf))
253 while (*ptr != 0 && !isspace(*ptr))
254 ptr++;
255 break;
256
257 case 'p':
258 /*
259 * XXX This is bogus if parsed before hour-related
260 * specifiers.
261 */
262 len = strlen(tptr->am);
263 if (strncasecmp(buf, tptr->am, len) == 0) {
264 if (tm->tm_hour > 12)
265 return (NULL);
266 if (tm->tm_hour == 12)
267 tm->tm_hour = 0;
268 buf += len;
269 break;
270 }
271
272 len = strlen(tptr->pm);
273 if (strncasecmp(buf, tptr->pm, len) == 0) {
274 if (tm->tm_hour > 12)
302 case 'U':
303 case 'W':
304 /*
305 * XXX This is bogus, as we can not assume any valid
306 * information present in the tm structure at this
307 * point to calculate a real value, so just check the
308 * range for now.
309 */
310 if (!isdigit(*buf))
311 return (NULL);
312
313 len = 2;
314 for (i = 0; len && isdigit(*buf); buf++) {
315 i *= 10;
316 i += *buf - '0';
317 len--;
318 }
319 if (i > 53)
320 return (NULL);
321
322 if (isspace(*buf))
323 while (*ptr != 0 && !isspace(*ptr))
324 ptr++;
325 break;
326
327 case 'w':
328 if (!isdigit(*buf))
329 return (NULL);
330
331 i = *buf - '0';
332 if (i > 6)
333 return (NULL);
334
335 tm->tm_wday = i;
336
337 if (isspace(*buf))
338 while (*ptr != 0 && !isspace(*ptr))
339 ptr++;
340 break;
341
342 case 'e':
343 /*
344 * The %e format has a space before single digits
345 * which we need to skip.
346 */
347 if (isspace(*buf))
348 buf++;
349 /* FALLTHROUGH */
350 case 'd':
351 /*
352 * The %e specifier is explicitly documented as not
353 * being zero-padded but there is no harm in allowing
354 * such padding.
355 *
356 * XXX The %e specifier may gobble one too many
357 * digits if used incorrectly.
358 */
359 if (!isdigit(*buf))
360 return (NULL);
361
362 len = 2;
363 for (i = 0; len && isdigit(*buf); buf++) {
364 i *= 10;
365 i += *buf - '0';
366 len--;
367 }
368 if (i > 31)
369 return (NULL);
370
371 tm->tm_mday = i;
372
373 if (isspace(*buf))
374 while (*ptr != 0 && !isspace(*ptr))
375 ptr++;
376 break;
377
378 case 'B':
379 case 'b':
380 case 'h':
381 for (i = 0; i < asizeof(tptr->month); i++) {
382 len = strlen(tptr->month[i]);
383 if (strncasecmp(buf, tptr->month[i], len) == 0)
384 break;
385 }
386 /*
387 * Try the abbreviated month name if the full name
388 * wasn't found.
389 */
390 if (i == asizeof(tptr->month)) {
391 for (i = 0; i < asizeof(tptr->month); i++) {
392 len = strlen(tptr->mon[i]);
393 if (strncasecmp(buf, tptr->mon[i],
394 len) == 0)
395 break;
400
401 tm->tm_mon = i;
402 buf += len;
403 break;
404
405 case 'm':
406 if (!isdigit(*buf))
407 return (NULL);
408
409 len = 2;
410 for (i = 0; len && isdigit(*buf); buf++) {
411 i *= 10;
412 i += *buf - '0';
413 len--;
414 }
415 if (i < 1 || i > 12)
416 return (NULL);
417
418 tm->tm_mon = i - 1;
419
420 if (isspace(*buf))
421 while (*ptr != NULL && !isspace(*ptr))
422 ptr++;
423 break;
424
425 case 's':
426 {
427 char *cp;
428 int sverrno;
429 time_t t;
430
431 sverrno = errno;
432 errno = 0;
433 t = strtol(buf, &cp, 10);
434 if (errno == ERANGE) {
435 errno = sverrno;
436 return (NULL);
437 }
438 errno = sverrno;
439 buf = cp;
440 (void) gmtime_r(&t, tm);
441 *flagsp |= F_GMT;
442 }
448 break;
449
450 if (!isdigit(*buf))
451 return (NULL);
452
453 len = (c == 'Y') ? 4 : 2;
454 for (i = 0; len && isdigit(*buf); buf++) {
455 i *= 10;
456 i += *buf - '0';
457 len--;
458 }
459 if (c == 'Y')
460 i -= 1900;
461 if (c == 'y' && i < 69)
462 i += 100;
463 if (i < 0)
464 return (NULL);
465
466 tm->tm_year = i;
467
468 if (isspace(*buf))
469 while (*ptr != 0 && !isspace(*ptr))
470 ptr++;
471 break;
472
473 case 'Z':
474 {
475 const char *cp = buf;
476 char *zonestr;
477
478 while (isupper(*cp))
479 ++cp;
480 if (cp - buf) {
481 zonestr = alloca(cp - buf + 1);
482 (void) strncpy(zonestr, buf, cp - buf);
483 zonestr[cp - buf] = '\0';
484 tzset();
485 if (strcmp(zonestr, "GMT") == 0) {
486 *flagsp |= F_GMT;
487 } else if (0 == strcmp(zonestr, tzname[0])) {
488 tm->tm_isdst = 0;
489 } else if (0 == strcmp(zonestr, tzname[1])) {
490 tm->tm_isdst = 1;
504 if (*buf == '-')
505 sign = -1;
506 else
507 return (NULL);
508 }
509 buf++;
510 i = 0;
511 for (len = 4; len > 0; len--) {
512 if (!isdigit(*buf))
513 return (NULL);
514 i *= 10;
515 i += *buf - '0';
516 buf++;
517 }
518
519 tm->tm_hour -= sign * (i / 100);
520 tm->tm_min -= sign * (i % 100);
521 *flagsp |= F_GMT;
522 }
523 break;
524 }
525 }
526
527 if (!recurse) {
528 if (buf && (*flagsp & F_GMT)) {
529 time_t t = timegm(tm);
530 (void) localtime_r(&t, tm);
531 }
532 }
533
534 return ((char *)buf);
535 }
536
537 char *
538 strptime(const char *buf, const char *fmt, struct tm *tm)
539 {
540 int flags = F_ZERO;
541
542 return (__strptime(buf, fmt, tm, &flags));
543 }
|
1 /*
2 * Copyright (c) 2014 Gary Mills
3 * Copyright 2011, Nexenta Systems, Inc. All rights reserved.
4 * Copyright (c) 1994 Powerdog Industries. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer
15 * in the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
199 if (!isdigit(*buf))
200 return (NULL);
201
202 len = 2;
203 for (i = 0; len && isdigit(*buf); buf++) {
204 i *= 10;
205 i += *buf - '0';
206 len--;
207 }
208
209 if (c == 'M') {
210 if (i > 59)
211 return (NULL);
212 tm->tm_min = i;
213 } else {
214 if (i > 60)
215 return (NULL);
216 tm->tm_sec = i;
217 }
218
219 break;
220
221 case 'H':
222 case 'I':
223 case 'k':
224 case 'l':
225 /*
226 * Of these, %l is the only specifier explicitly
227 * documented as not being zero-padded. However,
228 * there is no harm in allowing zero-padding.
229 *
230 * XXX The %l specifier may gobble one too many
231 * digits if used incorrectly.
232 */
233 if (!isdigit(*buf))
234 return (NULL);
235
236 len = 2;
237 for (i = 0; len && isdigit(*buf); buf++) {
238 i *= 10;
239 i += *buf - '0';
240 len--;
241 }
242 if (c == 'H' || c == 'k') {
243 if (i > 23)
244 return (NULL);
245 } else if (i > 12)
246 return (NULL);
247
248 tm->tm_hour = i;
249
250 break;
251
252 case 'p':
253 /*
254 * XXX This is bogus if parsed before hour-related
255 * specifiers.
256 */
257 len = strlen(tptr->am);
258 if (strncasecmp(buf, tptr->am, len) == 0) {
259 if (tm->tm_hour > 12)
260 return (NULL);
261 if (tm->tm_hour == 12)
262 tm->tm_hour = 0;
263 buf += len;
264 break;
265 }
266
267 len = strlen(tptr->pm);
268 if (strncasecmp(buf, tptr->pm, len) == 0) {
269 if (tm->tm_hour > 12)
297 case 'U':
298 case 'W':
299 /*
300 * XXX This is bogus, as we can not assume any valid
301 * information present in the tm structure at this
302 * point to calculate a real value, so just check the
303 * range for now.
304 */
305 if (!isdigit(*buf))
306 return (NULL);
307
308 len = 2;
309 for (i = 0; len && isdigit(*buf); buf++) {
310 i *= 10;
311 i += *buf - '0';
312 len--;
313 }
314 if (i > 53)
315 return (NULL);
316
317 break;
318
319 case 'w':
320 if (!isdigit(*buf))
321 return (NULL);
322
323 i = *buf - '0';
324 if (i > 6)
325 return (NULL);
326
327 tm->tm_wday = i;
328
329 break;
330
331 case 'd':
332 case 'e':
333 /*
334 * The %e format has a space before single digits
335 * which we need to skip.
336 */
337 if (isspace(*buf))
338 buf++;
339 /*
340 * The %e specifier is explicitly documented as not
341 * being zero-padded but there is no harm in allowing
342 * such padding.
343 *
344 * XXX The %e specifier may gobble one too many
345 * digits if used incorrectly.
346 */
347 if (!isdigit(*buf))
348 return (NULL);
349
350 len = 2;
351 for (i = 0; len && isdigit(*buf); buf++) {
352 i *= 10;
353 i += *buf - '0';
354 len--;
355 }
356 if (i > 31)
357 return (NULL);
358
359 tm->tm_mday = i;
360
361 break;
362
363 case 'B':
364 case 'b':
365 case 'h':
366 for (i = 0; i < asizeof(tptr->month); i++) {
367 len = strlen(tptr->month[i]);
368 if (strncasecmp(buf, tptr->month[i], len) == 0)
369 break;
370 }
371 /*
372 * Try the abbreviated month name if the full name
373 * wasn't found.
374 */
375 if (i == asizeof(tptr->month)) {
376 for (i = 0; i < asizeof(tptr->month); i++) {
377 len = strlen(tptr->mon[i]);
378 if (strncasecmp(buf, tptr->mon[i],
379 len) == 0)
380 break;
385
386 tm->tm_mon = i;
387 buf += len;
388 break;
389
390 case 'm':
391 if (!isdigit(*buf))
392 return (NULL);
393
394 len = 2;
395 for (i = 0; len && isdigit(*buf); buf++) {
396 i *= 10;
397 i += *buf - '0';
398 len--;
399 }
400 if (i < 1 || i > 12)
401 return (NULL);
402
403 tm->tm_mon = i - 1;
404
405 break;
406
407 case 's':
408 {
409 char *cp;
410 int sverrno;
411 time_t t;
412
413 sverrno = errno;
414 errno = 0;
415 t = strtol(buf, &cp, 10);
416 if (errno == ERANGE) {
417 errno = sverrno;
418 return (NULL);
419 }
420 errno = sverrno;
421 buf = cp;
422 (void) gmtime_r(&t, tm);
423 *flagsp |= F_GMT;
424 }
430 break;
431
432 if (!isdigit(*buf))
433 return (NULL);
434
435 len = (c == 'Y') ? 4 : 2;
436 for (i = 0; len && isdigit(*buf); buf++) {
437 i *= 10;
438 i += *buf - '0';
439 len--;
440 }
441 if (c == 'Y')
442 i -= 1900;
443 if (c == 'y' && i < 69)
444 i += 100;
445 if (i < 0)
446 return (NULL);
447
448 tm->tm_year = i;
449
450 break;
451
452 case 'Z':
453 {
454 const char *cp = buf;
455 char *zonestr;
456
457 while (isupper(*cp))
458 ++cp;
459 if (cp - buf) {
460 zonestr = alloca(cp - buf + 1);
461 (void) strncpy(zonestr, buf, cp - buf);
462 zonestr[cp - buf] = '\0';
463 tzset();
464 if (strcmp(zonestr, "GMT") == 0) {
465 *flagsp |= F_GMT;
466 } else if (0 == strcmp(zonestr, tzname[0])) {
467 tm->tm_isdst = 0;
468 } else if (0 == strcmp(zonestr, tzname[1])) {
469 tm->tm_isdst = 1;
483 if (*buf == '-')
484 sign = -1;
485 else
486 return (NULL);
487 }
488 buf++;
489 i = 0;
490 for (len = 4; len > 0; len--) {
491 if (!isdigit(*buf))
492 return (NULL);
493 i *= 10;
494 i += *buf - '0';
495 buf++;
496 }
497
498 tm->tm_hour -= sign * (i / 100);
499 tm->tm_min -= sign * (i % 100);
500 *flagsp |= F_GMT;
501 }
502 break;
503 case 'n':
504 case 't':
505 while (isspace(*buf))
506 buf++;
507 break;
508 }
509 }
510
511 if (!recurse) {
512 if (buf && (*flagsp & F_GMT)) {
513 time_t t = timegm(tm);
514 (void) localtime_r(&t, tm);
515 }
516 }
517
518 return ((char *)buf);
519 }
520
521 char *
522 strptime(const char *buf, const char *fmt, struct tm *tm)
523 {
524 int flags = F_ZERO;
525
526 return (__strptime(buf, fmt, tm, &flags));
527 }
|