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

