Print this page
3141 strptime() doesn't support %t
   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 }