This is an automated email from the git hooks/post-receive script.

guillem pushed a commit to branch main
in repository dpkg.

View the commit online:
https://git.dpkg.org/cgit/dpkg/dpkg.git/commit/?id=042ea3b92bcae6517135e22ffd574fdd0d1ba55d

commit 042ea3b92bcae6517135e22ffd574fdd0d1ba55d
Author: Guillem Jover <[email protected]>
AuthorDate: Wed Nov 30 04:26:16 2022 +0100

    libdpkg: Automatically initialize fsys and db dirs on demand
    
    Change the dpkg_fsys_* and dpkg_db_* functions to initialize the
    directories when needed, so that it guarantees the users can always
    use these functions safely, and they respect the expected initialization
    order.
    
    Refactor the set_instdir() and set_admindir() functions so that we can
    set their values correctly in a single place.
    
    Fixes: commit b8f9e1c3ce86818d14ccad403e6ad2e6b52e6b12
    Reported-by: stackomatiker (on stackoverflow)
    Ref: https://stackoverflow.com/questions/73529576
---
 dselect/main.cc         | 17 ++------------
 lib/dpkg/dbdir.c        | 62 +++++++++++++++++++++++++++++++++++--------------
 lib/dpkg/fsys-dir.c     | 58 +++++++++++++++++++++++++++++++--------------
 lib/dpkg/options-dirs.c | 28 ++++++++++++++++++++++
 lib/dpkg/options.h      |  4 ++++
 src/divert/main.c       | 21 +----------------
 src/main/main.c         | 20 +---------------
 src/query/main.c        | 15 +-----------
 src/split/main.c        |  2 --
 src/statoverride/main.c | 21 +----------------
 src/trigger/main.c      | 14 +----------
 11 files changed, 125 insertions(+), 137 deletions(-)

diff --git a/dselect/main.cc b/dselect/main.cc
index 7985bb74f..32010235b 100644
--- a/dselect/main.cc
+++ b/dselect/main.cc
@@ -64,9 +64,6 @@ static const char printforhelp[] = N_("Type dselect --help 
for help.");
 
 bool expertmode = false;
 
-static const char *admindir;
-static const char *instdir;
-
 static keybindings 
packagelistbindings(packagelist_kinterps,packagelist_korgbindings);
 
 struct table_t {
@@ -227,13 +224,6 @@ usage(const struct cmdinfo *ci, const char *value)
 /* These are called by C code, so need to have C calling convention */
 extern "C" {
 
-  static void
-  set_root(const struct cmdinfo*, const char *v)
-  {
-    instdir = dpkg_fsys_set_dir(v);
-    admindir = dpkg_fsys_get_path(ADMINDIR);
-  }
-
   static void
   set_debug(const struct cmdinfo*, const char *v)
   {
@@ -322,8 +312,8 @@ extern "C" {
 } /* End of extern "C" */
 
 static const struct cmdinfo cmdinfos[]= {
-  { "admindir",     0,  1, nullptr,  &admindir, nullptr      },
-  { "instdir",      0,  1, nullptr,  &instdir,  nullptr      },
+  { "admindir",     0,  1, nullptr,  nullptr,   set_admindir, 1 },
+  { "instdir",      0,  1, nullptr,  nullptr,   set_instdir, 1 },
   { "root",         0,  1, nullptr,  nullptr,   set_root, 1  },
   { "debug",       'D', 1, nullptr,  nullptr,   set_debug    },
   { "expert",      'E', 0, nullptr,  nullptr,   set_expert   },
@@ -549,9 +539,6 @@ main(int, const char *const *argv)
   dpkg_options_load(DSELECT, cmdinfos);
   dpkg_options_parse(&argv, cmdinfos, printforhelp);
 
-  instdir = dpkg_fsys_set_dir(instdir);
-  admindir = dpkg_db_set_dir(admindir);
-
   if (*argv) {
     const char *a;
     while ((a = *argv++) != nullptr) {
diff --git a/lib/dpkg/dbdir.c b/lib/dpkg/dbdir.c
index fecd4842f..e86affa91 100644
--- a/lib/dpkg/dbdir.c
+++ b/lib/dpkg/dbdir.c
@@ -29,15 +29,39 @@
 #include <dpkg/dpkg-db.h>
 #include <dpkg/fsys.h>
 
-static const char *db_dir = ADMINDIR;
+static char *db_dir;
+
+/**
+ * Allocate the default on-disk database directory.
+ *
+ * The directory defaults to the value from environment variable
+ * DPKG_ADMINDIR, and if not set the built-in default ADMINDIR.
+ *
+ * @return The database directory.
+ */
+static char *
+dpkg_db_new_dir(void)
+{
+       const char *env;
+       char *dir;
+
+       /* Make sure the filesystem root directory is initialized. */
+       dpkg_fsys_get_dir();
+
+       env = getenv("DPKG_ADMINDIR");
+       if (env)
+               dir = m_strdup(env);
+       else
+               dir = dpkg_fsys_get_path(ADMINDIR);
+
+       return dir;
+}
 
 /**
  * Set current on-disk database directory.
  *
- * The directory is initially set to ADMINDIR, this function can be used to
- * set the directory to a new value, or to set it to a default value if dir
- * is NULL. For the latter the order is, value from environment variable
- * DPKG_ADMINDIR, and then the built-in default ADMINDIR,
+ * This function can be used to set the directory to a new value, or to
+ * reset it to a default value if dir is NULL.
  *
  * @param dir The new database directory, or NULL to set to default.
  *
@@ -46,17 +70,15 @@ static const char *db_dir = ADMINDIR;
 const char *
 dpkg_db_set_dir(const char *dir)
 {
-       if (dir == NULL) {
-               const char *env;
-
-               env = getenv("DPKG_ADMINDIR");
-               if (env)
-                       db_dir = env;
-               else
-                       db_dir = dpkg_fsys_get_path(ADMINDIR);
-       } else {
-               db_dir = dir;
-       }
+       char *dir_new;
+
+       if (dir == NULL)
+               dir_new = dpkg_db_new_dir();
+       else
+               dir_new = m_strdup(dir);
+
+       free(db_dir);
+       db_dir = dir_new;
 
        return db_dir;
 }
@@ -64,11 +86,17 @@ dpkg_db_set_dir(const char *dir)
 /**
  * Get current on-disk database directory.
  *
+ * This function will take care of initializing the directory if it has not
+ * been initialized before.
+ *
  * @return The current database directory.
  */
 const char *
 dpkg_db_get_dir(void)
 {
+       if (db_dir == NULL)
+               db_dir = dpkg_db_new_dir();
+
        return db_dir;
 }
 
@@ -85,5 +113,5 @@ dpkg_db_get_dir(void)
 char *
 dpkg_db_get_path(const char *pathpart)
 {
-       return str_fmt("%s/%s", db_dir, pathpart);
+       return str_fmt("%s/%s", dpkg_db_get_dir(), pathpart);
 }
diff --git a/lib/dpkg/fsys-dir.c b/lib/dpkg/fsys-dir.c
index 016b265e1..76d5f39de 100644
--- a/lib/dpkg/fsys-dir.c
+++ b/lib/dpkg/fsys-dir.c
@@ -28,16 +28,38 @@
 #include <dpkg/path.h>
 #include <dpkg/fsys.h>
 
-static const char *fsys_dir = "";
-static char *fsys_dir_alloc;
+static char *fsys_dir;
+
+/**
+ * Allocate the default on-disk filesystem root directory.
+ *
+ * The directory defaults to the value from environment variable
+ * DPKG_ROOT, and if not set the built-in default "".
+ *
+ * @return The filesystem root directory.
+ */
+static char *
+dpkg_fsys_new_dir(void)
+{
+       const char *env;
+       char *dir;
+
+       env = getenv("DPKG_ROOT");
+       if (env == NULL) {
+               dir = m_strdup("");
+       } else {
+               dir = m_strdup(env);
+               path_trim_slash_slashdot(dir);
+       }
+
+       return dir;
+}
 
 /**
  * Set current on-disk filesystem root directory.
  *
- * The directory is initially set to "", this function can be used to
- * set the directory to a new value, or to set it to a default value if dir
- * is NULL. For the latter the order is, value from environment variable
- * DPKG_ROOT, and then the built-in default "",
+ * This function can be used to set the directory to a new value, or to
+ * reset it to a default value if dir is NULL.
  *
  * @param dir The new filesystem root directory, or NULL to set to default.
  *
@@ -46,21 +68,17 @@ static char *fsys_dir_alloc;
 const char *
 dpkg_fsys_set_dir(const char *dir)
 {
-       char *fsys_dir_new;
-
-       if (dir == NULL)
-               dir = getenv("DPKG_ROOT");
+       char *dir_new;
 
        if (dir == NULL) {
-               fsys_dir = "";
-               fsys_dir_new = NULL;
+               dir_new = dpkg_fsys_new_dir();
        } else {
-               fsys_dir = fsys_dir_new = m_strdup(dir);
-               path_trim_slash_slashdot(fsys_dir_new);
+               dir_new = m_strdup(dir);
+               path_trim_slash_slashdot(dir_new);
        }
 
-       free(fsys_dir_alloc);
-       fsys_dir_alloc = fsys_dir_new;
+       free(fsys_dir);
+       fsys_dir = dir_new;
 
        return fsys_dir;
 }
@@ -68,11 +86,17 @@ dpkg_fsys_set_dir(const char *dir)
 /**
  * Get current on-disk filesystem root directory.
  *
+ * This function will take care of initializing the directory if it has not
+ * been initialized before.
+ *
  * @return The current filesystem root directory.
  */
 const char *
 dpkg_fsys_get_dir(void)
 {
+       if (fsys_dir == NULL)
+               fsys_dir = dpkg_fsys_new_dir();
+
        return fsys_dir;
 }
 
@@ -91,5 +115,5 @@ dpkg_fsys_get_path(const char *pathpart)
 {
        pathpart = path_skip_slash_dotslash(pathpart);
 
-       return str_fmt("%s/%s", fsys_dir, pathpart);
+       return str_fmt("%s/%s", dpkg_fsys_get_dir(), pathpart);
 }
diff --git a/lib/dpkg/options-dirs.c b/lib/dpkg/options-dirs.c
index 0147c0f19..9b7a122fe 100644
--- a/lib/dpkg/options-dirs.c
+++ b/lib/dpkg/options-dirs.c
@@ -21,13 +21,41 @@
 #include <config.h>
 #include <compat.h>
 
+#include <stdlib.h>
+
 #include <dpkg/macros.h>
 #include <dpkg/dpkg.h>
 #include <dpkg/dpkg-db.h>
+#include <dpkg/fsys.h>
 #include <dpkg/options.h>
 
+void
+set_instdir(const struct cmdinfo *cip, const char *value)
+{
+       /* Make sure the database is initialized before the root directory,
+        * otherwise, on first use it would get initialized based on the
+        * newly set root directory. */
+       dpkg_db_get_dir();
+
+       dpkg_fsys_set_dir(value);
+}
+
 void
 set_admindir(const struct cmdinfo *cip, const char *value)
 {
        dpkg_db_set_dir(value);
 }
+
+void
+set_root(const struct cmdinfo *cip, const char *value)
+{
+       char *db_dir;
+
+       /* Initialize the root directory. */
+       dpkg_fsys_set_dir(value);
+
+       /* Set the database directory based on the new root directory. */
+       db_dir = dpkg_fsys_get_path(ADMINDIR);
+       dpkg_db_set_dir(db_dir);
+       free(db_dir);
+}
diff --git a/lib/dpkg/options.h b/lib/dpkg/options.h
index 5c07d1a89..c08f28623 100644
--- a/lib/dpkg/options.h
+++ b/lib/dpkg/options.h
@@ -84,8 +84,12 @@ void setobsolete(const struct cmdinfo *cip, const char 
*value);
 #define OBSOLETE(longopt, shortopt) \
  { longopt, shortopt, 0, NULL, NULL, setobsolete, 0, NULL, NULL }
 
+void
+set_instdir(const struct cmdinfo *cip, const char *value);
 void
 set_admindir(const struct cmdinfo *cip, const char *value);
+void
+set_root(const struct cmdinfo *cip, const char *value);
 
 /** @} */
 
diff --git a/src/divert/main.c b/src/divert/main.c
index baaa2758a..ddfd18d28 100644
--- a/src/divert/main.c
+++ b/src/divert/main.c
@@ -51,9 +51,6 @@
 static const char printforhelp[] = N_(
 "Use --help for help about diverting files.");
 
-static const char *admindir;
-static const char *instdir;
-
 static bool opt_pkgname_match_any = true;
 static const char *opt_pkgname = NULL;
 static const char *opt_divertto = NULL;
@@ -833,19 +830,6 @@ set_divertto(const struct cmdinfo *cip, const char *value)
                badusage(_("divert-to may not contain newlines"));
 }
 
-static void
-set_instdir(const struct cmdinfo *cip, const char *value)
-{
-       instdir = dpkg_fsys_set_dir(value);
-}
-
-static void
-set_root(const struct cmdinfo *cip, const char *value)
-{
-       instdir = dpkg_fsys_set_dir(value);
-       admindir = dpkg_fsys_get_path(ADMINDIR);
-}
-
 static const struct cmdinfo cmdinfo_add =
        ACTION("add",         0, 0, diversion_add);
 
@@ -858,7 +842,7 @@ static const struct cmdinfo cmdinfos[] = {
        ACTION("help",        '?', 0, usage),
        ACTION("version",     0,   0, printversion),
 
-       { "admindir",   0,   1,  NULL,         &admindir, NULL          },
+       { "admindir",   0,   1,  NULL,         NULL,      set_admindir, 0 },
        { "instdir",    0,   1,  NULL,         NULL,      set_instdir,  0 },
        { "root",       0,   1,  NULL,         NULL,      set_root,     0 },
        { "divert",     0,   1,  NULL,         NULL,      set_divertto  },
@@ -881,9 +865,6 @@ main(int argc, const char * const *argv)
        dpkg_program_init("dpkg-divert");
        dpkg_options_parse(&argv, cmdinfos, printforhelp);
 
-       instdir = dpkg_fsys_set_dir(instdir);
-       admindir = dpkg_db_set_dir(admindir);
-
        env_pkgname = getenv("DPKG_MAINTSCRIPT_PACKAGE");
        if (opt_pkgname_match_any && env_pkgname)
                set_package(NULL, env_pkgname);
diff --git a/src/main/main.c b/src/main/main.c
index f25763054..c3f9e50c5 100644
--- a/src/main/main.c
+++ b/src/main/main.c
@@ -199,8 +199,6 @@ int f_autodeconf=0, f_nodebsig=0;
 int f_triggers = 0;
 
 int errabort = 50;
-static const char *admindir;
-static const char *instdir;
 struct pkg_list *ignoredependss = NULL;
 
 #define DBG_DEF(n, d) \
@@ -276,19 +274,6 @@ set_verify_format(const struct cmdinfo *cip, const char 
*value)
     badusage(_("unknown verify output format '%s'"), value);
 }
 
-static void
-set_instdir(const struct cmdinfo *cip, const char *value)
-{
-  instdir = dpkg_fsys_set_dir(value);
-}
-
-static void
-set_root(const struct cmdinfo *cip, const char *value)
-{
-  instdir = dpkg_fsys_set_dir(value);
-  admindir = dpkg_fsys_get_path(ADMINDIR);
-}
-
 static void
 set_ignore_depends(const struct cmdinfo *cip, const char *value)
 {
@@ -597,7 +582,7 @@ static const struct cmdinfo cmdinfos[]= {
   { "robot",             0,   0, &f_robot,      NULL,      NULL,    1 },
   { "root",              0,   1, NULL,          NULL,      set_root,      0 },
   { "abort-after",       0,   1, &errabort,     NULL,      set_integer,   0 },
-  { "admindir",          0,   1, NULL,          &admindir, NULL,          0 },
+  { "admindir",          0,   1, NULL,          NULL,      set_admindir,  0 },
   { "instdir",           0,   1, NULL,          NULL,      set_instdir,   0 },
   { "ignore-depends",    0,   1, NULL,          NULL,      set_ignore_depends, 
0 },
   { "force",             0,   2, NULL,          NULL,      set_force_option,   
1 },
@@ -759,9 +744,6 @@ int main(int argc, const char *const *argv) {
 
   if (!cipaction) badusage(_("need an action option"));
 
-  instdir = dpkg_fsys_set_dir(instdir);
-  admindir = dpkg_db_set_dir(admindir);
-
   /* Always set environment, to avoid possible security risks. */
   if (setenv("DPKG_ADMINDIR", dpkg_db_get_dir(), 1) < 0)
     ohshite(_("unable to setenv for subprocesses"));
diff --git a/src/query/main.c b/src/query/main.c
index a531cc17d..8c34518a2 100644
--- a/src/query/main.c
+++ b/src/query/main.c
@@ -58,9 +58,6 @@
 
 #include "actions.h"
 
-static const char *admindir;
-static const char *instdir;
-
 static const char *showformat = "${binary:Package}\t${Version}\n";
 
 static int opt_loadavail = 0;
@@ -765,13 +762,6 @@ control_show(const char *const *argv)
   return 0;
 }
 
-static void
-set_root(const struct cmdinfo *cip, const char *value)
-{
-  instdir = dpkg_fsys_set_dir(value);
-  admindir = dpkg_fsys_get_path(ADMINDIR);
-}
-
 static void
 set_no_pager(const struct cmdinfo *ci, const char *value)
 {
@@ -861,7 +851,7 @@ static const struct cmdinfo cmdinfos[]= {
   ACTION( "help",                           '?', act_help,          usage      
     ),
   ACTION( "version",                         0,  act_version,       
printversion    ),
 
-  { "admindir",   0,   1, NULL, &admindir,   NULL          },
+  { "admindir",   0,   1, NULL, NULL,        set_admindir, 0 },
   { "root",       0,   1, NULL, NULL,        set_root, 0   },
   { "load-avail", 0,   0, &opt_loadavail, NULL, NULL, 1    },
   { "showformat", 'f', 1, NULL, &showformat, NULL          },
@@ -877,9 +867,6 @@ int main(int argc, const char *const *argv) {
   dpkg_program_init("dpkg-query");
   dpkg_options_parse(&argv, cmdinfos, printforhelp);
 
-  instdir = dpkg_fsys_set_dir(instdir);
-  admindir = dpkg_db_set_dir(admindir);
-
   if (!cipaction) badusage(_("need an action option"));
 
   ret = cipaction->action(argv);
diff --git a/src/split/main.c b/src/split/main.c
index 7b80b60f9..fb8fa4361 100644
--- a/src/split/main.c
+++ b/src/split/main.c
@@ -103,7 +103,6 @@ usage(const char *const *argv)
 static const char printforhelp[] = N_("Type dpkg-split --help for help.");
 
 off_t opt_maxpartsize = SPLITPARTDEFMAX;
-static const char *admindir;
 const char *opt_depotdir;
 const char *opt_outputfile = NULL;
 int opt_npquiet = 0;
@@ -162,7 +161,6 @@ int main(int argc, const char *const *argv) {
   dpkg_program_init(SPLITTER);
   dpkg_options_parse(&argv, cmdinfos, printforhelp);
 
-  admindir = dpkg_db_set_dir(admindir);
   if (opt_depotdir == NULL)
     opt_depotdir = dpkg_db_get_path(PARTSDIR);
 
diff --git a/src/statoverride/main.c b/src/statoverride/main.c
index ddb8d75ff..801da2064 100644
--- a/src/statoverride/main.c
+++ b/src/statoverride/main.c
@@ -108,25 +108,9 @@ usage(const char *const *argv)
        FORCE_NON_ROOT | \
        FORCE_SECURITY_MAC | FORCE_STATOVERRIDE_ADD | FORCE_STATOVERRIDE_DEL
 
-static const char *admindir;
-static const char *instdir;
-
 static int opt_verbose = 1;
 static int opt_update = 0;
 
-static void
-set_instdir(const struct cmdinfo *cip, const char *value)
-{
-       instdir = dpkg_fsys_set_dir(value);
-}
-
-static void
-set_root(const struct cmdinfo *cip, const char *value)
-{
-       instdir = dpkg_fsys_set_dir(value);
-       admindir = dpkg_fsys_get_path(ADMINDIR);
-}
-
 static char *
 path_cleanup(const char *path)
 {
@@ -400,7 +384,7 @@ static const struct cmdinfo cmdinfos[] = {
        ACTION("help",   '?', act_help,    usage),
        ACTION("version", 0,  act_version, printversion),
 
-       { "admindir",   0,   1,  NULL,         &admindir, NULL          },
+       { "admindir",   0,   1,  NULL,         NULL,      set_admindir, 0 },
        { "instdir",    0,   1,  NULL,         NULL,      set_instdir,  0 },
        { "root",       0,   1,  NULL,         NULL,      set_root,     0 },
        { "quiet",      0,   0,  &opt_verbose, NULL,      NULL, 0       },
@@ -422,9 +406,6 @@ main(int argc, const char *const *argv)
        set_force_default(FORCE_STATCMD_MASK);
        dpkg_options_parse(&argv, cmdinfos, printforhelp);
 
-       instdir = dpkg_fsys_set_dir(instdir);
-       admindir = dpkg_db_set_dir(admindir);
-
        if (!cipaction)
                badusage(_("need an action option"));
 
diff --git a/src/trigger/main.c b/src/trigger/main.c
index 541c8239c..3321b7040 100644
--- a/src/trigger/main.c
+++ b/src/trigger/main.c
@@ -93,21 +93,12 @@ usage(const char *const *argv)
        return 0;
 }
 
-static const char *admindir;
-static const char *instdir;
 static int f_noact;
 static int f_await = 1;
 
 static const char *bypackage, *activate;
 static bool done_trig, ctrig;
 
-static void
-set_root(const struct cmdinfo *cip, const char *value)
-{
-       instdir = dpkg_fsys_set_dir(value);
-       admindir = dpkg_fsys_get_path(ADMINDIR);
-}
-
 static void
 yespackage(const char *awname)
 {
@@ -246,7 +237,7 @@ static const struct cmdinfo cmdinfos[] = {
        ACTION("help",            '?', 0, usage),
        ACTION("version",          0,  0, printversion),
 
-       { "admindir",        0,   1, NULL,     &admindir },
+       { "admindir",        0,   1, NULL,     NULL,       set_admindir, 0 },
        { "root",            0,   1, NULL,     NULL,       set_root, 0 },
        { "by-package",      'f', 1, NULL,     &bypackage },
        { "await",           0,   0, &f_await, NULL,       NULL, 1 },
@@ -264,9 +255,6 @@ main(int argc, const char *const *argv)
        dpkg_program_init("dpkg-trigger");
        dpkg_options_parse(&argv, cmdinfos, printforhelp);
 
-       instdir = dpkg_fsys_set_dir(instdir);
-       admindir = dpkg_db_set_dir(admindir);
-
        if (!cipaction)
                setaction(&cmdinfo_trigger, NULL);
 

-- 
Dpkg.Org's dpkg

Reply via email to