From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from eastern.birch.relay.mailchannels.net (eastern.birch.relay.mailchannels.net [23.83.209.55]) by sourceware.org (Postfix) with ESMTPS id C75AF39BD42C for ; Thu, 10 Jun 2021 11:19:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org C75AF39BD42C X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id 6CE0322CF6; Thu, 10 Jun 2021 11:19:52 +0000 (UTC) Received: from pdx1-sub0-mail-a13.g.dreamhost.com (100-96-133-111.trex.outbound.svc.cluster.local [100.96.133.111]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id E24D022C98; Thu, 10 Jun 2021 11:19:51 +0000 (UTC) X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org Received: from pdx1-sub0-mail-a13.g.dreamhost.com (pop.dreamhost.com [64.90.62.162]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384) by 100.96.133.111 (trex/6.3.1); Thu, 10 Jun 2021 11:19:52 +0000 X-MC-Relay: Neutral X-MailChannels-SenderId: dreamhost|x-authsender|siddhesh@gotplt.org X-MailChannels-Auth-Id: dreamhost X-Abiding-Ruddy: 6ebbecbc258d11a3_1623323992258_86251955 X-MC-Loop-Signature: 1623323992258:4077380334 X-MC-Ingress-Time: 1623323992257 Received: from pdx1-sub0-mail-a13.g.dreamhost.com (localhost [127.0.0.1]) by pdx1-sub0-mail-a13.g.dreamhost.com (Postfix) with ESMTP id 8B3CA800C5; Thu, 10 Jun 2021 11:19:51 +0000 (UTC) Received: from rhbox.intra.reserved-bit.com (unknown [1.186.101.110]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: siddhesh@gotplt.org) by pdx1-sub0-mail-a13.g.dreamhost.com (Postfix) with ESMTPSA id 2387E7FF19; Thu, 10 Jun 2021 11:19:47 +0000 (UTC) X-DH-BACKEND: pdx1-sub0-mail-a13 From: Siddhesh Poyarekar To: libc-alpha@sourceware.org Cc: adhemerval.zanella@linaro.org, dj@redhat.com, schwab@linux-m68k.org Subject: [PATCH 3/6] gconv_conf: Split out configuration file processing Date: Thu, 10 Jun 2021 16:48:50 +0530 Message-Id: <20210610111853.2286873-4-siddhesh@sourceware.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210610111853.2286873-1-siddhesh@sourceware.org> References: <20210610111853.2286873-1-siddhesh@sourceware.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-3494.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, JMQ_SPF_NEUTRAL, KAM_DMARC_NONE, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NEUTRAL, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 10 Jun 2021 11:19:57 -0000 Split configuration file processing into a separate header file and include it. Macroize all calls that need to go through internal interfaces so that iconvconfig can also use them. --- iconv/gconv_conf.c | 129 +---------------------------- iconv/gconv_parseconfdir.h | 161 +++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 126 deletions(-) create mode 100644 iconv/gconv_parseconfdir.h diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c index 6c6625c37a..62bee28769 100644 --- a/iconv/gconv_conf.c +++ b/iconv/gconv_conf.c @@ -19,7 +19,6 @@ =20 #include #include -#include #include #include #include @@ -31,11 +30,10 @@ #include #include #include -#include =20 #include #include - +#include =20 /* This is the default path where we look for module lists. */ static const char default_gconv_path[] =3D GCONV_PATH; @@ -56,11 +54,6 @@ size_t __gconv_max_path_elem_len; /* We use the following struct if we couldn't allocate memory. */ static const struct path_elem empty_path_elem =3D { NULL, 0 }; =20 -/* Name of the file containing the module information in the directories - along the path. */ -static const char gconv_conf_filename[] =3D "gconv-modules"; -static const char gconv_conf_dirname[] =3D "gconv-modules.d"; - /* Filename extension for the modules. */ #ifndef MODULE_EXT # define MODULE_EXT ".so" @@ -99,9 +92,6 @@ static const char builtin_aliases[] =3D #undef BUILTIN_ALIAS }; =20 -#include -#define __getdelim(line, len, c, fp) _IO_getdelim (line, len, c, fp) - =20 /* Value of the GCONV_PATH environment variable. */ const char *__gconv_path_envvar; @@ -361,72 +351,6 @@ add_module (char *rp, const char *directory, size_t = dir_len, int modcounter) } =20 =20 -/* Read the next configuration file. */ -static void -read_conf_file (const char *filename, const char *directory, size_t dir_= len) -{ - /* Note the file is opened with cancellation in the I/O functions - disabled. */ - FILE *fp =3D fopen (filename, "rce"); - char *line =3D NULL; - size_t line_len =3D 0; - static int modcounter; - - /* Don't complain if a file is not present or readable, simply silentl= y - ignore it. */ - if (fp =3D=3D NULL) - return; - - /* No threads reading from this stream. */ - __fsetlocking (fp, FSETLOCKING_BYCALLER); - - /* Process the known entries of the file. Comments start with `#' and - end with the end of the line. Empty lines are ignored. */ - while (!__feof_unlocked (fp)) - { - char *rp, *endp, *word; - ssize_t n =3D __getdelim (&line, &line_len, '\n', fp); - if (n < 0) - /* An error occurred. */ - break; - - rp =3D line; - /* Terminate the line (excluding comments or newline) by an NUL by= te - to simplify the following code. */ - endp =3D strchr (rp, '#'); - if (endp !=3D NULL) - *endp =3D '\0'; - else - if (rp[n - 1] =3D=3D '\n') - rp[n - 1] =3D '\0'; - - while (__isspace_l (*rp, _nl_C_locobj_ptr)) - ++rp; - - /* If this is an empty line go on with the next one. */ - if (rp =3D=3D endp) - continue; - - word =3D rp; - while (*rp !=3D '\0' && !__isspace_l (*rp, _nl_C_locobj_ptr)) - ++rp; - - if (rp - word =3D=3D sizeof ("alias") - 1 - && memcmp (word, "alias", sizeof ("alias") - 1) =3D=3D 0) - add_alias (rp); - else if (rp - word =3D=3D sizeof ("module") - 1 - && memcmp (word, "module", sizeof ("module") - 1) =3D=3D 0) - add_module (rp, directory, dir_len, modcounter++); - /* else */ - /* Otherwise ignore the line. */ - } - - free (line); - - fclose (fp); -} - - /* Determine the directories we are looking for data in. This function = should only be called from __gconv_read_conf. */ static void @@ -554,55 +478,8 @@ __gconv_read_conf (void) __gconv_get_path (); =20 for (cnt =3D 0; __gconv_path_elem[cnt].name !=3D NULL; ++cnt) - { - const char *elem =3D __gconv_path_elem[cnt].name; - size_t elem_len =3D __gconv_path_elem[cnt].len; - - /* No slash needs to be inserted between elem and gconv_conf_filen= ame; - elem already ends in a slash. */ - char *buf =3D malloc (elem_len + sizeof (gconv_conf_dirname)); - if (buf =3D=3D NULL) - continue; - - char *cp =3D __mempcpy (__mempcpy (buf, elem, elem_len), - gconv_conf_filename, sizeof (gconv_conf_filename)); - - /* Read the gconv-modules configuration file first. */ - read_conf_file (buf, elem, elem_len); - - /* Next, see if there is a gconv-modules.d directory containing - configuration files and if it is non-empty. */ - cp--; - cp[0] =3D '.'; - cp[1] =3D 'd'; - cp[2] =3D '\0'; - - DIR *confdir =3D __opendir (buf); - if (confdir !=3D NULL) - { - struct dirent *ent; - while ((ent =3D __readdir (confdir)) !=3D NULL) - { - if (ent->d_type !=3D DT_REG) - continue; - - size_t len =3D strlen (ent->d_name); - const char *suffix =3D ".conf"; - - if (len > strlen (suffix) - && strcmp (ent->d_name + len - strlen (suffix), suffix) =3D=3D 0) - { - char *conf; - if (__asprintf (&conf, "%s/%s", buf, ent->d_name) < 0) - continue; - read_conf_file (conf, elem, elem_len); - free (conf); - } - } - __closedir (confdir); - } - free (buf); - } + gconv_parseconfdir (__gconv_path_elem[cnt].name, + __gconv_path_elem[cnt].len); #endif =20 /* Add the internal modules. */ diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h new file mode 100644 index 0000000000..3d4d58d4be --- /dev/null +++ b/iconv/gconv_parseconfdir.h @@ -0,0 +1,161 @@ +/* Handle configuration data. + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include + +#if IS_IN (libc) +# include +# define __getdelim(line, len, c, fp) _IO_getdelim (line, len, c, fp) + +# undef isspace +# define isspace(__c) __isspace_l ((__c), _nl_C_locobj_ptr) +# define asprintf __asprintf +# define opendir __opendir +# define readdir __readdir +# define closedir __closedir +# define mempcpy __mempcpy +#endif + +/* Name of the file containing the module information in the directories + along the path. */ +static const char gconv_conf_filename[] =3D "gconv-modules"; +static const char gconv_conf_dirname[] =3D "gconv-modules.d"; + +static void add_alias (char *); +static void add_module (char *, const char *, size_t, int); + +/* Read the next configuration file. */ +static bool +read_conf_file (const char *filename, const char *directory, size_t dir_= len) +{ + /* Note the file is opened with cancellation in the I/O functions + disabled. */ + FILE *fp =3D fopen (filename, "rce"); + char *line =3D NULL; + size_t line_len =3D 0; + static int modcounter; + + /* Don't complain if a file is not present or readable, simply silentl= y + ignore it. */ + if (fp =3D=3D NULL) + return false; + + /* No threads reading from this stream. */ + __fsetlocking (fp, FSETLOCKING_BYCALLER); + + /* Process the known entries of the file. Comments start with `#' and + end with the end of the line. Empty lines are ignored. */ + while (!__feof_unlocked (fp)) + { + char *rp, *endp, *word; + ssize_t n =3D __getdelim (&line, &line_len, '\n', fp); + if (n < 0) + /* An error occurred. */ + break; + + rp =3D line; + /* Terminate the line (excluding comments or newline) by an NUL by= te + to simplify the following code. */ + endp =3D strchr (rp, '#'); + if (endp !=3D NULL) + *endp =3D '\0'; + else + if (rp[n - 1] =3D=3D '\n') + rp[n - 1] =3D '\0'; + + while (isspace (*rp)) + ++rp; + + /* If this is an empty line go on with the next one. */ + if (rp =3D=3D endp) + continue; + + word =3D rp; + while (*rp !=3D '\0' && !isspace (*rp)) + ++rp; + + if (rp - word =3D=3D sizeof ("alias") - 1 + && memcmp (word, "alias", sizeof ("alias") - 1) =3D=3D 0) + add_alias (rp); + else if (rp - word =3D=3D sizeof ("module") - 1 + && memcmp (word, "module", sizeof ("module") - 1) =3D=3D 0) + add_module (rp, directory, dir_len, modcounter++); + /* else */ + /* Otherwise ignore the line. */ + } + + free (line); + + fclose (fp); + return true; +} + +static __always_inline bool +gconv_parseconfdir (const char *dir, size_t dir_len) +{ + /* No slash needs to be inserted between dir and gconv_conf_filename; + dir already ends in a slash. */ + char *buf =3D malloc (dir_len + sizeof (gconv_conf_dirname)); + bool found =3D false; + + if (buf =3D=3D NULL) + return false; + + char *cp =3D mempcpy (mempcpy (buf, dir, dir_len), gconv_conf_filename= , + sizeof (gconv_conf_filename)); + + /* Read the gconv-modules configuration file first. */ + found =3D read_conf_file (buf, dir, dir_len); + + /* Next, see if there is a gconv-modules.d directory containing + configuration files and if it is non-empty. */ + cp--; + cp[0] =3D '.'; + cp[1] =3D 'd'; + cp[2] =3D '\0'; + + DIR *confdir =3D opendir (buf); + if (confdir !=3D NULL) + { + struct dirent *ent; + while ((ent =3D readdir (confdir)) !=3D NULL) + { + if (ent->d_type !=3D DT_REG) + continue; + + size_t len =3D strlen (ent->d_name); + const char *suffix =3D ".conf"; + + if (len > strlen (suffix) + && strcmp (ent->d_name + len - strlen (suffix), suffix) =3D=3D 0) + { + char *conf; + if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0) + continue; + found |=3D read_conf_file (conf, dir, dir_len); + free (conf); + } + } + closedir (confdir); + } + free (buf); + return found; +} --=20 2.31.1