From efbbb0578845a702827de9d5dfbd450035bae7e9 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Tue, 18 Feb 2025 14:52:04 +0100 Subject: [PATCH 1/8] lib/getdate.*: Reimplement in pure C This removes all yacc(1) code from this project. Add copyright and license, since there remains nothing of the original code. Signed-off-by: Alejandro Colomar --- .../actions/install-dependencies/action.yml | 2 +- .gitignore | 1 - configure.ac | 1 - lib/Makefile.am | 2 +- lib/getdate.c | 80 ++++++ lib/getdate.y | 248 ------------------ share/ansible/roles/ci_run/tasks/alpine.yml | 1 - share/ansible/roles/ci_run/tasks/opensuse.yml | 1 - 8 files changed, 82 insertions(+), 254 deletions(-) create mode 100644 lib/getdate.c delete mode 100644 lib/getdate.y diff --git a/.github/actions/install-dependencies/action.yml b/.github/actions/install-dependencies/action.yml index 15c0ba352b..7dd52a71c0 100644 --- a/.github/actions/install-dependencies/action.yml +++ b/.github/actions/install-dependencies/action.yml @@ -22,5 +22,5 @@ runs: sudo apt-mark hold grub-efi-amd64-bin grub-efi-amd64-signed sudo apt-get update sudo apt-get -y dist-upgrade - sudo apt-get -y install ubuntu-dev-tools automake autopoint xsltproc gettext expect byacc libtool libbsd-dev libltdl-dev pkgconf + sudo apt-get -y install ubuntu-dev-tools automake autopoint xsltproc gettext expect libtool libbsd-dev libltdl-dev pkgconf sudo apt-get -y build-dep shadow diff --git a/.gitignore b/.gitignore index 3d6d91c80c..56693605a8 100644 --- a/.gitignore +++ b/.gitignore @@ -52,7 +52,6 @@ test-driver /shadow.spec /shadow-*.tar.* -/lib/getdate.c /libsubid/subid.h .venv diff --git a/configure.ac b/configure.ac index 283097fe81..186c1ea9a1 100644 --- a/configure.ac +++ b/configure.ac @@ -30,7 +30,6 @@ AM_MAINTAINER_MODE dnl Checks for programs. AC_PROG_CC AC_PROG_LN_S -AC_PROG_YACC LT_INIT LT_LIB_DLLOAD diff --git a/lib/Makefile.am b/lib/Makefile.am index 279971bdab..e6a2cf2df4 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -104,8 +104,8 @@ libshadow_la_SOURCES = \ fs/readlink/readlinknul.c \ fs/readlink/readlinknul.h \ get_pid.c \ + getdate.c \ getdate.h \ - getdate.y \ getdef.c \ getdef.h \ getgr_nam_gid.c \ diff --git a/lib/getdate.c b/lib/getdate.c new file mode 100644 index 0000000000..3d08bd4d16 --- /dev/null +++ b/lib/getdate.c @@ -0,0 +1,80 @@ +// SPDX-FileCopyrightText: 2025, Alejandro Colomar +// SPDX-License-Identifier: BSD-3-Clause + + +#include + +#include +#include +#include +#include +#include + +#include "atoi/a2i/a2s.h" +#include "getdate.h" +#include "string/strchr/strchrcnt.h" +#include "string/strcmp/streq.h" +#include "string/strcmp/strprefix.h" +#include "string/strcmp/strsuffix.h" +#include "string/strspn/stpspn.h" + + +#define TM_YEAR_ORIGIN 1900 + + +static long yyDay; +static long yyMonth; +static long yyYear; + + +static int parse_date(const char *s); + + +time_t get_date (const char *p, const time_t *now) +{ + struct tm tm; + + if (parse_date(p) == -1) + return -1; + + tm.tm_year = yyYear - TM_YEAR_ORIGIN; + tm.tm_mon = yyMonth - 1; + tm.tm_mday = yyDay; + tm.tm_hour = tm.tm_min = tm.tm_sec = 0; + tm.tm_isdst = 0; + + return timegm(&tm); +} + + +static int +parse_date(const char *s) +{ + long n; + + if (!streq(stpspn(s, "0123456789-"), "") + || strchrcnt(s, '-') != 2 + || strprefix(s, "-") + || strsuffix(s, "-") + || strstr(s, "--")) + { + return -1; + } + + if (a2sl(&yyYear, s, &s, 10, LONG_MIN, LONG_MAX) == -1 && errno != ENOTSUP) + return -1; + + if (!strprefix(s++, "-")) + return -1; + + if (a2sl(&yyMonth, s, &s, 10, LONG_MIN, LONG_MAX) == -1 && errno != ENOTSUP) + return -1; + + if (!strprefix(s++, "-")) + return -1; + + if (a2sl(&yyDay, s, NULL, 10, LONG_MIN, LONG_MAX) == -1) + return -1; + + return 0; +} diff --git a/lib/getdate.y b/lib/getdate.y deleted file mode 100644 index c0df43428d..0000000000 --- a/lib/getdate.y +++ /dev/null @@ -1,248 +0,0 @@ -%{ -/* -** Originally written by Steven M. Bellovin while -** at the University of North Carolina at Chapel Hill. Later tweaked by -** a couple of people on Usenet. Completely overhauled by Rich $alz -** and Jim Berets in August, 1990; -** -** This grammar has 13 shift/reduce conflicts. -** -** This code is in the public domain and has no copyright. -*/ - -#ifdef HAVE_CONFIG_H -# include -#endif - -/* Since the code of getdate.y is not included in the Emacs executable - itself, there is no need to #define static in this file. Even if - the code were included in the Emacs executable, it probably - wouldn't do any harm to #undef it here; this will only cause - problems if we try to write to a static variable, which I don't - think this code needs to do. */ -#ifdef emacs -# undef static -#endif - -#include -#include -#include -#include - -#include "attr.h" -#include "getdate.h" -#include "string/strspn/stpspn.h" - - -/* Some old versions of bison generate parsers that use bcopy. - That loses on systems that don't provide the function, so we have - to redefine it here. */ -#if !defined (HAVE_BCOPY) && !defined (bcopy) -# define bcopy(from, to, len) memcpy ((to), (from), (len)) -#endif - -/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc), - as well as gratuitously global symbol names, so we can have multiple - yacc generated parsers in the same program. Note that these are only - the variables produced by yacc. If other parser generators (bison, - byacc, etc) produce additional global names that conflict at link time, - then those parser generators need to be fixed instead of adding those - names to this list. */ - -#define yymaxdepth gd_maxdepth -#define yyparse gd_parse -#define yylex gd_lex -#define yyerror gd_error -#define yylval gd_lval -#define yychar gd_char -#define yydebug gd_debug -#define yypact gd_pact -#define yyr1 gd_r1 -#define yyr2 gd_r2 -#define yydef gd_def -#define yychk gd_chk -#define yypgo gd_pgo -#define yyact gd_act -#define yyexca gd_exca -#define yyerrflag gd_errflag -#define yynerrs gd_nerrs -#define yyps gd_ps -#define yypv gd_pv -#define yys gd_s -#define yy_yys gd_yys -#define yystate gd_state -#define yytmp gd_tmp -#define yyv gd_v -#define yy_yyv gd_yyv -#define yyval gd_val -#define yylloc gd_lloc -#define yyreds gd_reds /* With YYDEBUG defined */ -#define yytoks gd_toks /* With YYDEBUG defined */ -#define yylhs gd_yylhs -#define yylen gd_yylen -#define yydefred gd_yydefred -#define yydgoto gd_yydgoto -#define yysindex gd_yysindex -#define yyrindex gd_yyrindex -#define yygindex gd_yygindex -#define yytable gd_yytable -#define yycheck gd_yycheck - -static int yylex (void); -static int yyerror (const char *s); - - -#define MAX_BUFF_LEN 128 /* size of buffer to read the date into */ - -/* -** An entry in the lexical lookup table. -*/ -typedef struct _TABLE { - const char *name; - int type; - int value; -} TABLE; - - -/* -** Global variables. We could get rid of most of these by using a good -** union as the yacc stack. (This routine was originally written before -** yacc had the %union construct.) Maybe someday; right now we only use -** the %union very rarely. -*/ -static const char *yyInput; -static int yyDay; -static int yyMonth; -static int yyYear; - -%} - -%union { - int Number; -} - -%token tSNUMBER tUNUMBER - -%type tSNUMBER tUNUMBER - -%% - -spec : /* NULL */ - | spec item - ; - -item : date - ; - -date : tUNUMBER tSNUMBER tSNUMBER { - /* ISO 8601 format. yyyy-mm-dd. */ - yyYear = $1; - yyMonth = -$2; - yyDay = -$3; - } - ; - -%% - - - - -static int yyerror (MAYBE_UNUSED const char *s) -{ - return 0; -} - -static int -yylex (void) -{ - register char c; - register char *p; - char buff[20]; - int Count; - int sign; - - for (;;) - { - yyInput = stpspn(yyInput, " \t"); - - if (isdigit (c = *yyInput) || c == '-' || c == '+') - { - if (c == '-' || c == '+') - { - sign = c == '-' ? -1 : 1; - if (!isdigit (*++yyInput)) - /* skip the '-' sign */ - continue; - } - else - sign = 0; - for (yylval.Number = 0; isdigit (c = *yyInput++);) - yylval.Number = 10 * yylval.Number + c - '0'; - yyInput--; - if (sign < 0) - yylval.Number = -yylval.Number; - return (0 != sign) ? tSNUMBER : tUNUMBER; - } - if (c != '(') - return *yyInput++; - Count = 0; - do - { - c = *yyInput++; - if (c == '\0') - return c; - if (c == '(') - Count++; - else if (c == ')') - Count--; - } - while (Count > 0); - } -} - -#define TM_YEAR_ORIGIN 1900 - -time_t get_date (const char *p, const time_t *now) -{ - struct tm tm; - - yyInput = p; - - if (yyparse()) - return -1; - - tm.tm_year = yyYear - TM_YEAR_ORIGIN; - tm.tm_mon = yyMonth - 1; - tm.tm_mday = yyDay; - tm.tm_hour = tm.tm_min = tm.tm_sec = 0; - tm.tm_isdst = 0; - - return timegm(&tm); -} - -#if defined (TEST) - -int -main(void) -{ - char buff[MAX_BUFF_LEN + 1]; - time_t d; - - (void) printf ("Enter date, or blank line to exit.\n\t> "); - (void) fflush (stdout); - - buff[MAX_BUFF_LEN] = 0; - while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0]) - { - d = get_date(buff, NULL); - if (d == -1) - (void) printf ("Bad format - couldn't convert.\n"); - else - (void) printf ("%s", ctime (&d)); - (void) printf ("\t> "); - (void) fflush (stdout); - } - exit (0); - /* NOTREACHED */ -} -#endif /* defined (TEST) */ diff --git a/share/ansible/roles/ci_run/tasks/alpine.yml b/share/ansible/roles/ci_run/tasks/alpine.yml index b76b639b22..abd0f2502c 100644 --- a/share/ansible/roles/ci_run/tasks/alpine.yml +++ b/share/ansible/roles/ci_run/tasks/alpine.yml @@ -10,7 +10,6 @@ - automake - bash - build-base - - byacc - cmocka-dev - coreutils - expect diff --git a/share/ansible/roles/ci_run/tasks/opensuse.yml b/share/ansible/roles/ci_run/tasks/opensuse.yml index ab16580f82..92a779b984 100644 --- a/share/ansible/roles/ci_run/tasks/opensuse.yml +++ b/share/ansible/roles/ci_run/tasks/opensuse.yml @@ -8,7 +8,6 @@ name: - autoconf - automake - - byacc - diffutils - gawk - gcc From edcc515aec3d2f56046d0d0458aa8664c73977b2 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Tue, 18 Feb 2025 15:08:52 +0100 Subject: [PATCH 2/8] lib/: Fix indentation and alignment Signed-off-by: Alejandro Colomar --- lib/getdate.c | 21 +++++++++++---------- lib/strtoday.c | 3 ++- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/getdate.c b/lib/getdate.c index 3d08bd4d16..7479875e80 100644 --- a/lib/getdate.c +++ b/lib/getdate.c @@ -30,20 +30,21 @@ static long yyYear; static int parse_date(const char *s); -time_t get_date (const char *p, const time_t *now) +time_t +get_date(const char *p, const time_t *now) { - struct tm tm; + struct tm tm; - if (parse_date(p) == -1) - return -1; + if (parse_date(p) == -1) + return -1; - tm.tm_year = yyYear - TM_YEAR_ORIGIN; - tm.tm_mon = yyMonth - 1; - tm.tm_mday = yyDay; - tm.tm_hour = tm.tm_min = tm.tm_sec = 0; - tm.tm_isdst = 0; + tm.tm_year = yyYear - TM_YEAR_ORIGIN; + tm.tm_mon = yyMonth - 1; + tm.tm_mday = yyDay; + tm.tm_hour = tm.tm_min = tm.tm_sec = 0; + tm.tm_isdst = 0; - return timegm(&tm); + return timegm(&tm); } diff --git a/lib/strtoday.c b/lib/strtoday.c index c37c90abed..3d9410181f 100644 --- a/lib/strtoday.c +++ b/lib/strtoday.c @@ -21,7 +21,8 @@ // string parse-to day-since-Epoch -long strtoday (const char *str) +long +strtoday(const char *str) { time_t t; const char *s = str; From 61a5fff53967c5fedcbeb1263017f051199ae7d7 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Tue, 18 Feb 2025 15:19:38 +0100 Subject: [PATCH 3/8] lib/: get_date(): Remove unused parameter And rename the remaining parameter. Signed-off-by: Alejandro Colomar --- lib/getdate.c | 4 ++-- lib/getdate.h | 2 +- lib/strtoday.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/getdate.c b/lib/getdate.c index 7479875e80..f9a3f837ab 100644 --- a/lib/getdate.c +++ b/lib/getdate.c @@ -31,11 +31,11 @@ static int parse_date(const char *s); time_t -get_date(const char *p, const time_t *now) +get_date(const char *s) { struct tm tm; - if (parse_date(p) == -1) + if (parse_date(s) == -1) return -1; tm.tm_year = yyYear - TM_YEAR_ORIGIN; diff --git a/lib/getdate.h b/lib/getdate.h index eae56f647f..7348559214 100644 --- a/lib/getdate.h +++ b/lib/getdate.h @@ -12,5 +12,5 @@ #include #include "defines.h" -time_t get_date (const char *p, /*@null@*/const time_t *now); +time_t get_date(const char *s); #endif diff --git a/lib/strtoday.c b/lib/strtoday.c index 3d9410181f..c0b159337b 100644 --- a/lib/strtoday.c +++ b/lib/strtoday.c @@ -49,7 +49,7 @@ strtoday(const char *str) return retdate; } - t = get_date(str, NULL); + t = get_date(str); if ((time_t) - 1 == t) { return -2; } From 98005517dd55779ebb2acca843f6cef38a81ce51 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Tue, 18 Feb 2025 23:25:29 +0100 Subject: [PATCH 4/8] lib/getdate.c: Use strptime(3) to simplify The following trick: t = 0; gmtime_r(&t, &tm); is a clever way to clear the tm(3type) structure, and set it to use UTC. We need to set it to set UTC with this trick, because strptime(3) doesn't set the timezone. I (Alex) tried previously using bzero(&tm, sizeof(tm)); strptime("UTC", "%Z", &tm); but glibc ignores the timezone, and musl (at least I tried in an Alpine container) seems to report an error. The idea to use gmtime_r(3) was from lanodan. Link: Cc: Iker Pedrosa Cc: Serge Hallyn Cc: Rich Felker Co-authored-by: "Haelwenn (lanodan) Monnier" Signed-off-by: "Haelwenn (lanodan) Monnier" Signed-off-by: Alejandro Colomar --- lib/getdate.c | 68 +++++++-------------------------------------------- 1 file changed, 9 insertions(+), 59 deletions(-) diff --git a/lib/getdate.c b/lib/getdate.c index f9a3f837ab..cc2c3f1559 100644 --- a/lib/getdate.c +++ b/lib/getdate.c @@ -1,81 +1,31 @@ // SPDX-FileCopyrightText: 2025, Alejandro Colomar +// SPDX-FileCopyrightText: 2025, "Haelwenn (lanodan) Monnier" // SPDX-License-Identifier: BSD-3-Clause #include -#include -#include #include -#include #include -#include "atoi/a2i/a2s.h" #include "getdate.h" -#include "string/strchr/strchrcnt.h" #include "string/strcmp/streq.h" -#include "string/strcmp/strprefix.h" -#include "string/strcmp/strsuffix.h" -#include "string/strspn/stpspn.h" - - -#define TM_YEAR_ORIGIN 1900 - - -static long yyDay; -static long yyMonth; -static long yyYear; - - -static int parse_date(const char *s); time_t get_date(const char *s) { - struct tm tm; - - if (parse_date(s) == -1) - return -1; - - tm.tm_year = yyYear - TM_YEAR_ORIGIN; - tm.tm_mon = yyMonth - 1; - tm.tm_mday = yyDay; - tm.tm_hour = tm.tm_min = tm.tm_sec = 0; - tm.tm_isdst = 0; - - return timegm(&tm); -} - - -static int -parse_date(const char *s) -{ - long n; - - if (!streq(stpspn(s, "0123456789-"), "") - || strchrcnt(s, '-') != 2 - || strprefix(s, "-") - || strsuffix(s, "-") - || strstr(s, "--")) - { - return -1; - } - - if (a2sl(&yyYear, s, &s, 10, LONG_MIN, LONG_MAX) == -1 && errno != ENOTSUP) - return -1; - - if (!strprefix(s++, "-")) - return -1; + time_t t; + struct tm tm; + const char *p; - if (a2sl(&yyMonth, s, &s, 10, LONG_MIN, LONG_MAX) == -1 && errno != ENOTSUP) + t = 0; + if (gmtime_r(&t, &tm) == NULL) return -1; - if (!strprefix(s++, "-")) + p = strptime(s, "%Y-%m-%d", &tm); + if (p == NULL || !streq(p, "")) return -1; - if (a2sl(&yyDay, s, NULL, 10, LONG_MIN, LONG_MAX) == -1) - return -1; - - return 0; + return timegm(&tm); } From 1bf48bda43a4dc2b876d0fa286f0814df20ad866 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Tue, 18 Feb 2025 15:24:34 +0100 Subject: [PATCH 5/8] lib/strtoday.c: strtoday(): Attempt parsing with str2sl() directly If it fails, let's fall back to get_date(). Signed-off-by: Alejandro Colomar --- lib/strtoday.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/lib/strtoday.c b/lib/strtoday.c index c0b159337b..cf77ca6fa3 100644 --- a/lib/strtoday.c +++ b/lib/strtoday.c @@ -14,18 +14,15 @@ #include "atoi/str2i.h" #include "getdate.h" #include "prototypes.h" -#include "string/ctype/strisascii/strisdigit.h" #include "string/strcmp/streq.h" -#include "string/strcmp/strprefix.h" -#include "string/strspn/stpspn.h" // string parse-to day-since-Epoch long strtoday(const char *str) { + long d; time_t t; - const char *s = str; /* * get_date() interprets an empty string as the current date, @@ -39,15 +36,8 @@ strtoday(const char *str) /* If a numerical value is provided, this is already a number of * days since EPOCH. */ - s = strprefix(s, "-") ?: s; - s = stpspn(s, " "); - if (strisdigit(s)) { - long retdate; - - if (str2sl(&retdate, str) == -1) - return -2; - return retdate; - } + if (str2sl(&d, str) == 0) + return d; t = get_date(str); if ((time_t) - 1 == t) { From bfaa21233d61fb02563487d3a2c84b99cac56d34 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Tue, 18 Feb 2025 15:43:29 +0100 Subject: [PATCH 6/8] lib/strtoday.c: strtoday(): Remove obsolete comment get_date() doesn't treat "" as a date anymore, so the comment is obsolete. We still need the code, though, as for example usermod(8) uses an empty string as a synonym for -1. Link: Reported-by: Chris Hofstaedtler Signed-off-by: Alejandro Colomar --- lib/strtoday.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/strtoday.c b/lib/strtoday.c index cf77ca6fa3..6e0e55c704 100644 --- a/lib/strtoday.c +++ b/lib/strtoday.c @@ -24,14 +24,8 @@ strtoday(const char *str) long d; time_t t; - /* - * get_date() interprets an empty string as the current date, - * which is not what we expect, unless you're a BOFH :-). - * (useradd sets sp_expire = current date for new lusers) - */ - if ((NULL == str) || streq(str, "")) { + if (NULL == str || streq(str, "")) return -1; - } /* If a numerical value is provided, this is already a number of * days since EPOCH. From cea1ff50c97753b6d9e47b5b862e8fbad219db7f Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Tue, 18 Feb 2025 15:38:35 +0100 Subject: [PATCH 7/8] lib/: Move get_date() to lib/strtoday.c Signed-off-by: Alejandro Colomar --- lib/Makefile.am | 2 -- lib/getdate.c | 31 ------------------------------- lib/getdate.h | 16 ---------------- lib/strtoday.c | 43 +++++++++++++++++++++++++++++++++---------- 4 files changed, 33 insertions(+), 59 deletions(-) delete mode 100644 lib/getdate.c delete mode 100644 lib/getdate.h diff --git a/lib/Makefile.am b/lib/Makefile.am index e6a2cf2df4..04e6c251c6 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -104,8 +104,6 @@ libshadow_la_SOURCES = \ fs/readlink/readlinknul.c \ fs/readlink/readlinknul.h \ get_pid.c \ - getdate.c \ - getdate.h \ getdef.c \ getdef.h \ getgr_nam_gid.c \ diff --git a/lib/getdate.c b/lib/getdate.c deleted file mode 100644 index cc2c3f1559..0000000000 --- a/lib/getdate.c +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-FileCopyrightText: 2025, Alejandro Colomar -// SPDX-FileCopyrightText: 2025, "Haelwenn (lanodan) Monnier" -// SPDX-License-Identifier: BSD-3-Clause - - -#include - -#include -#include - -#include "getdate.h" -#include "string/strcmp/streq.h" - - -time_t -get_date(const char *s) -{ - time_t t; - struct tm tm; - const char *p; - - t = 0; - if (gmtime_r(&t, &tm) == NULL) - return -1; - - p = strptime(s, "%Y-%m-%d", &tm); - if (p == NULL || !streq(p, "")) - return -1; - - return timegm(&tm); -} diff --git a/lib/getdate.h b/lib/getdate.h deleted file mode 100644 index 7348559214..0000000000 --- a/lib/getdate.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * SPDX-FileCopyrightText: 1990 - 1994, Julianne Frances Haugh - * SPDX-FileCopyrightText: 1997 - 2000, Marek Michałkiewicz - * SPDX-FileCopyrightText: 2005 , Tomasz Kłoczko - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef _GETDATE_H_ -#define _GETDATE_H_ - -#include -#include "defines.h" - -time_t get_date(const char *s); -#endif diff --git a/lib/strtoday.c b/lib/strtoday.c index 6e0e55c704..ea327faeee 100644 --- a/lib/strtoday.c +++ b/lib/strtoday.c @@ -1,22 +1,26 @@ -/* - * SPDX-FileCopyrightText: 1991 - 1994, Julianne Frances Haugh - * SPDX-FileCopyrightText: 1996 - 1999, Marek Michałkiewicz - * SPDX-FileCopyrightText: 2003 - 2005, Tomasz Kłoczko - * SPDX-FileCopyrightText: 2008 , Nicolas François - * - * SPDX-License-Identifier: BSD-3-Clause - */ +// SPDX-FileCopyrightText: 1991-1994, Julianne Frances Haugh +// SPDX-FileCopyrightText: 1996-1999, Marek Michałkiewicz +// SPDX-FileCopyrightText: 2003-2005, Tomasz Kłoczko +// SPDX-FileCopyrightText: 2008, Nicolas François +// SPDX-FileCopyrightText: 2025, Alejandro Colomar +// SPDX-FileCopyrightText: 2025, "Haelwenn (lanodan) Monnier" +// SPDX-License-Identifier: BSD-3-Clause + #include -#include +#include +#include #include "atoi/str2i.h" -#include "getdate.h" +#include "defines.h" #include "prototypes.h" #include "string/strcmp/streq.h" +static time_t get_date(const char *s); + + // string parse-to day-since-Epoch long strtoday(const char *str) @@ -39,3 +43,22 @@ strtoday(const char *str) } return t / DAY; } + + +static time_t +get_date(const char *s) +{ + time_t t; + struct tm tm; + const char *p; + + t = 0; + if (gmtime_r(&t, &tm) == NULL) + return -1; + + p = strptime(s, "%Y-%m-%d", &tm); + if (p == NULL || !streq(p, "")) + return -1; + + return timegm(&tm); +} From 727c0bb45c24f396bad33189d9171f8ad870f1f5 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Tue, 18 Feb 2025 23:37:17 +0100 Subject: [PATCH 8/8] lib/strtoday.c: Actually return a date from get_date() Signed-off-by: Alejandro Colomar --- lib/strtoday.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/lib/strtoday.c b/lib/strtoday.c index ea327faeee..ac3be80006 100644 --- a/lib/strtoday.c +++ b/lib/strtoday.c @@ -18,7 +18,8 @@ #include "string/strcmp/streq.h" -static time_t get_date(const char *s); +static long get_date(const char *s); +static long dategm(struct tm *tm); // string parse-to day-since-Epoch @@ -26,7 +27,6 @@ long strtoday(const char *str) { long d; - time_t t; if (NULL == str || streq(str, "")) return -1; @@ -37,15 +37,15 @@ strtoday(const char *str) if (str2sl(&d, str) == 0) return d; - t = get_date(str); - if ((time_t) - 1 == t) { + d = get_date(str); + if (d == -1) return -2; - } - return t / DAY; + + return d; } -static time_t +static long get_date(const char *s) { time_t t; @@ -60,5 +60,18 @@ get_date(const char *s) if (p == NULL || !streq(p, "")) return -1; - return timegm(&tm); + return dategm(&tm); +} + + +static long +dategm(struct tm *tm) +{ + time_t t; + + t = timegm(tm); + if (t == (time_t) -1) + return -1; + + return t / DAY; }