]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - time/getdate.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / time / getdate.c
index 626fb49d7a22c498ae4c3bdbcfcbba1a9cd58e0a..aee96f7163403f313801dfec63f75127b89b8564 100644 (file)
@@ -1,29 +1,33 @@
 /* Convert a string representation of time to a time value.
-   Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997-2019 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
 
    The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
 
    The GNU C Library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
+   Lesser General Public License for more details.
 
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If not,
-   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
 #include <limits.h>
 #include <stdio.h>
+#include <stdio_ext.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <string.h>
 #include <time.h>
+#include <unistd.h>
 #include <sys/stat.h>
+#include <ctype.h>
+#include <alloca.h>
 
 #define TM_YEAR_BASE 1900
 
@@ -42,7 +46,7 @@ static int check_mday (int year, int mon, int mday);
      6  memory allication failed (not enough memory available),
      7  there is no line in the template that matches the input,
      8  invalid input specification Example: February 31 or a time is
-        specified that can not be represented in a time_t (representing
+       specified that can not be represented in a time_t (representing
        the time in seconds since 00:00:00 UTC, January 1, 1970) */
 int getdate_err;
 
@@ -110,24 +114,68 @@ __getdate_r (const char *string, struct tm *tp)
   char *result = NULL;
   time_t timer;
   struct tm tm;
-  struct stat st;
+  struct stat64 st;
   int mday_ok = 0;
 
   datemsk = getenv ("DATEMSK");
   if (datemsk == NULL || *datemsk == '\0')
     return 1;
 
-  if (stat (datemsk, &st) < 0)
+  if (stat64 (datemsk, &st) < 0)
     return 3;
 
   if (!S_ISREG (st.st_mode))
     return 4;
 
+  if (__access (datemsk, R_OK) < 0)
+    return 2;
+
   /* Open the template file.  */
-  fp = fopen (datemsk, "r");
+  fp = fopen (datemsk, "rce");
   if (fp == NULL)
     return 2;
 
+  /* No threads reading this stream.  */
+  __fsetlocking (fp, FSETLOCKING_BYCALLER);
+
+  /* Skip leading whitespace.  */
+  while (isspace (*string))
+    string++;
+
+  size_t inlen, oldlen;
+
+  oldlen = inlen = strlen (string);
+
+  /* Skip trailing whitespace.  */
+  while (inlen > 0 && isspace (string[inlen - 1]))
+    inlen--;
+
+  char *instr = NULL;
+
+  if (inlen < oldlen)
+    {
+      bool using_malloc = false;
+
+      if (__libc_use_alloca (inlen + 1))
+       instr = alloca (inlen + 1);
+      else
+       {
+         instr = malloc (inlen + 1);
+         if (instr == NULL)
+           {
+             fclose (fp);
+             return 6;
+           }
+         using_malloc = true;
+       }
+      memcpy (instr, string, inlen);
+      instr[inlen] = '\0';
+      string = instr;
+
+      if (!using_malloc)
+       instr = NULL;
+    }
+
   line = NULL;
   len = 0;
   do
@@ -143,17 +191,22 @@ __getdate_r (const char *string, struct tm *tp)
       /* Do the conversion.  */
       tp->tm_year = tp->tm_mon = tp->tm_mday = tp->tm_wday = INT_MIN;
       tp->tm_hour = tp->tm_sec = tp->tm_min = INT_MIN;
+      tp->tm_isdst = -1;
+      tp->tm_gmtoff = 0;
+      tp->tm_zone = NULL;
       result = strptime (string, line, tp);
       if (result && *result == '\0')
        break;
     }
-  while (!feof_unlocked (fp));
+  while (!__feof_unlocked (fp));
+
+  free (instr);
 
   /* Free the buffer.  */
   free (line);
 
   /* Check for errors. */
-  if (ferror_unlocked (fp))
+  if (__ferror_unlocked (fp))
     {
       fclose (fp);
       return 5;
@@ -201,28 +254,31 @@ __getdate_r (const char *string, struct tm *tp)
       tp->tm_sec = tm.tm_sec;
     }
 
+  /* Fill in the gaps.  */
+  if (tp->tm_hour == INT_MIN)
+    tp->tm_hour = 0;
+  if (tp->tm_min == INT_MIN)
+    tp->tm_min = 0;
+  if (tp->tm_sec == INT_MIN)
+    tp->tm_sec = 0;
+
   /* If no date is given, today is assumed if the given hour is
      greater than the current hour and tomorrow is assumed if
      it is less.  */
   if (tp->tm_hour >= 0 && tp->tm_hour <= 23
-      && tp->tm_year == INT_MIN && tp->tm_mon == INT_MIN
+      && tp->tm_mon == INT_MIN
       && tp->tm_mday == INT_MIN && tp->tm_wday == INT_MIN)
     {
-      tp->tm_year = tm.tm_year;
       tp->tm_mon = tm.tm_mon;
       tp->tm_mday = tm.tm_mday + ((tp->tm_hour - tm.tm_hour) < 0 ? 1 : 0);
       mday_ok = 1;
     }
 
-  /* Fill in the gaps.  */
+  /* More fillers.  */
   if (tp->tm_year == INT_MIN)
     tp->tm_year = tm.tm_year;
-  if (tp->tm_hour == INT_MIN)
-    tp->tm_hour = 0;
-  if (tp->tm_min == INT_MIN)
-    tp->tm_min = 0;
-  if (tp->tm_sec == INT_MIN)
-    tp->tm_sec = 0;
+  if (tp->tm_mon == INT_MIN)
+    tp->tm_mon = tm.tm_mon;
 
   /* Check if the day of month is within range, and if the time can be
      represented in a time_t.  We make use of the fact that the mktime