LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/lib/commands - toolcontext.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 365 640 57.0 %
Date: 2010-04-13 Functions: 27 32 84.4 %
Branches: 153 402 38.1 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
       3                 :            :  * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
       4                 :            :  *
       5                 :            :  * This file is part of LVM2.
       6                 :            :  *
       7                 :            :  * This copyrighted material is made available to anyone wishing to use,
       8                 :            :  * modify, copy, or redistribute it subject to the terms and conditions
       9                 :            :  * of the GNU Lesser General Public License v.2.1.
      10                 :            :  *
      11                 :            :  * You should have received a copy of the GNU Lesser General Public License
      12                 :            :  * along with this program; if not, write to the Free Software Foundation,
      13                 :            :  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "lib.h"
      17                 :            : #include "toolcontext.h"
      18                 :            : #include "metadata.h"
      19                 :            : #include "defaults.h"
      20                 :            : #include "lvm-string.h"
      21                 :            : #include "activate.h"
      22                 :            : #include "filter.h"
      23                 :            : #include "filter-composite.h"
      24                 :            : #include "filter-md.h"
      25                 :            : #include "filter-persistent.h"
      26                 :            : #include "filter-regex.h"
      27                 :            : #include "filter-sysfs.h"
      28                 :            : #include "label.h"
      29                 :            : #include "lvm-file.h"
      30                 :            : #include "format-text.h"
      31                 :            : #include "display.h"
      32                 :            : #include "memlock.h"
      33                 :            : #include "str_list.h"
      34                 :            : #include "segtype.h"
      35                 :            : #include "lvmcache.h"
      36                 :            : #include "dev-cache.h"
      37                 :            : #include "archiver.h"
      38                 :            : 
      39                 :            : #ifdef HAVE_LIBDL
      40                 :            : #include "sharedlib.h"
      41                 :            : #endif
      42                 :            : 
      43                 :            : #ifdef LVM1_INTERNAL
      44                 :            : #include "format1.h"
      45                 :            : #endif
      46                 :            : 
      47                 :            : #ifdef POOL_INTERNAL
      48                 :            : #include "format_pool.h"
      49                 :            : #endif
      50                 :            : 
      51                 :            : #include <locale.h>
      52                 :            : #include <sys/stat.h>
      53                 :            : #include <sys/utsname.h>
      54                 :            : #include <syslog.h>
      55                 :            : #include <time.h>
      56                 :            : 
      57                 :            : #ifdef linux
      58                 :            : #  include <malloc.h>
      59                 :            : #endif
      60                 :            : 
      61                 :          1 : static int _get_env_vars(struct cmd_context *cmd)
      62                 :            : {
      63                 :            :         const char *e;
      64                 :            : 
      65                 :            :         /* Set to "" to avoid using any system directory */
      66         [ -  + ]:          1 :         if ((e = getenv("LVM_SYSTEM_DIR"))) {
      67         [ #  # ]:          0 :                 if (dm_snprintf(cmd->system_dir, sizeof(cmd->system_dir),
      68                 :            :                                  "%s", e) < 0) {
      69                 :          0 :                         log_error("LVM_SYSTEM_DIR environment variable "
      70                 :            :                                   "is too long.");
      71                 :          0 :                         return 0;
      72                 :            :                 }
      73                 :            :         }
      74                 :            : 
      75                 :          1 :         return 1;
      76                 :            : }
      77                 :            : 
      78                 :          3 : static void _get_sysfs_dir(struct cmd_context *cmd)
      79                 :            : {
      80                 :            :         static char proc_mounts[PATH_MAX];
      81                 :            :         static char *split[4], buffer[PATH_MAX + 16];
      82                 :            :         FILE *fp;
      83                 :          3 :         char *sys_mnt = NULL;
      84                 :            : 
      85                 :          3 :         cmd->sysfs_dir[0] = '\0';
      86         [ -  + ]:          3 :         if (!*cmd->proc_dir) {
      87                 :          0 :                 log_debug("No proc filesystem found: skipping sysfs detection");
      88                 :          0 :                 return;
      89                 :            :         }
      90                 :            : 
      91         [ -  + ]:          3 :         if (dm_snprintf(proc_mounts, sizeof(proc_mounts),
      92                 :            :                          "%s/mounts", cmd->proc_dir) < 0) {
      93                 :          0 :                 log_error("Failed to create /proc/mounts string for sysfs detection");
      94                 :          0 :                 return;
      95                 :            :         }
      96                 :            : 
      97         [ -  + ]:          3 :         if (!(fp = fopen(proc_mounts, "r"))) {
      98                 :          0 :                 log_sys_error("_get_sysfs_dir: fopen %s", proc_mounts);
      99                 :          0 :                 return;
     100                 :            :         }
     101                 :            : 
     102         [ +  - ]:         15 :         while (fgets(buffer, sizeof(buffer), fp)) {
     103 [ +  - ][ +  + ]:         15 :                 if (dm_split_words(buffer, 4, 0, split) == 4 &&
     104                 :         15 :                     !strcmp(split[2], "sysfs")) {
     105                 :          3 :                         sys_mnt = split[1];
     106                 :          3 :                         break;
     107                 :            :                 }
     108                 :            :         }
     109                 :            : 
     110         [ -  + ]:          3 :         if (fclose(fp))
     111                 :          0 :                 log_sys_error("fclose", proc_mounts);
     112                 :            : 
     113         [ -  + ]:          3 :         if (!sys_mnt) {
     114                 :          0 :                 log_error("Failed to find sysfs mount point");
     115                 :          0 :                 return;
     116                 :            :         }
     117                 :            : 
     118                 :          3 :         strncpy(cmd->sysfs_dir, sys_mnt, sizeof(cmd->sysfs_dir));
     119                 :            : }
     120                 :            : 
     121                 :          3 : static void _init_logging(struct cmd_context *cmd)
     122                 :            : {
     123                 :          3 :         int append = 1;
     124                 :            :         time_t t;
     125                 :            : 
     126                 :            :         const char *log_file;
     127                 :            :         char timebuf[26];
     128                 :            : 
     129                 :            :         /* Syslog */
     130                 :          3 :         cmd->default_settings.syslog =
     131                 :          3 :             find_config_tree_int(cmd, "log/syslog", DEFAULT_SYSLOG);
     132         [ +  - ]:          3 :         if (cmd->default_settings.syslog != 1)
     133                 :          3 :                 fin_syslog();
     134                 :            : 
     135         [ -  + ]:          3 :         if (cmd->default_settings.syslog > 1)
     136                 :          0 :                 init_syslog(cmd->default_settings.syslog);
     137                 :            : 
     138                 :            :         /* Debug level for log file output */
     139                 :          3 :         cmd->default_settings.debug =
     140                 :          3 :             find_config_tree_int(cmd, "log/level", DEFAULT_LOGLEVEL);
     141                 :          3 :         init_debug(cmd->default_settings.debug);
     142                 :            : 
     143                 :            :         /* Verbose level for tty output */
     144                 :          3 :         cmd->default_settings.verbose =
     145                 :          3 :             find_config_tree_int(cmd, "log/verbose", DEFAULT_VERBOSE);
     146                 :          3 :         init_verbose(cmd->default_settings.verbose + VERBOSE_BASE_LEVEL);
     147                 :            : 
     148                 :            :         /* Log message formatting */
     149                 :          3 :         init_indent(find_config_tree_int(cmd, "log/indent",
     150                 :            :                                          DEFAULT_INDENT));
     151                 :          3 :         init_abort_on_internal_errors(find_config_tree_int(cmd, "global/abort_on_internal_errors",
     152                 :            :                                                            DEFAULT_ABORT_ON_INTERNAL_ERRORS));
     153                 :            : 
     154                 :          3 :         cmd->default_settings.msg_prefix = find_config_tree_str(cmd,
     155                 :            :                                                            "log/prefix",
     156                 :            :                                                            DEFAULT_MSG_PREFIX);
     157                 :          3 :         init_msg_prefix(cmd->default_settings.msg_prefix);
     158                 :            : 
     159                 :          3 :         cmd->default_settings.cmd_name = find_config_tree_int(cmd,
     160                 :            :                                                          "log/command_names",
     161                 :            :                                                          DEFAULT_CMD_NAME);
     162                 :          3 :         init_cmd_name(cmd->default_settings.cmd_name);
     163                 :            : 
     164                 :            :         /* Test mode */
     165                 :          3 :         cmd->default_settings.test =
     166                 :          3 :             find_config_tree_int(cmd, "global/test", 0);
     167                 :          3 :         init_test(cmd->default_settings.test);
     168                 :            : 
     169                 :            :         /* Settings for logging to file */
     170         [ -  + ]:          3 :         if (find_config_tree_int(cmd, "log/overwrite", DEFAULT_OVERWRITE))
     171                 :          0 :                 append = 0;
     172                 :            : 
     173                 :          3 :         log_file = find_config_tree_str(cmd, "log/file", 0);
     174                 :            : 
     175         [ -  + ]:          3 :         if (log_file) {
     176                 :          0 :                 release_log_memory();
     177                 :          0 :                 fin_log();
     178                 :          0 :                 init_log_file(log_file, append);
     179                 :            :         }
     180                 :            : 
     181                 :          3 :         log_file = find_config_tree_str(cmd, "log/activate_file", 0);
     182         [ -  + ]:          3 :         if (log_file)
     183                 :          0 :                 init_log_direct(log_file, append);
     184                 :            : 
     185                 :          3 :         init_log_while_suspended(find_config_tree_int(cmd,
     186                 :            :                                                  "log/activation", 0));
     187                 :            : 
     188                 :          3 :         t = time(NULL);
     189                 :          3 :         ctime_r(&t, &timebuf[0]);
     190                 :          3 :         timebuf[24] = '\0';
     191                 :          3 :         log_verbose("Logging initialised at %s", timebuf);
     192                 :            : 
     193                 :            :         /* Tell device-mapper about our logging */
     194                 :            : #ifdef DEVMAPPER_SUPPORT
     195                 :          3 :         dm_log_with_errno_init(print_log);
     196                 :            : #endif
     197                 :          3 : }
     198                 :            : 
     199                 :          3 : static int _process_config(struct cmd_context *cmd)
     200                 :            : {
     201                 :            :         mode_t old_umask;
     202                 :            :         const char *read_ahead;
     203                 :            :         struct stat st;
     204                 :            :         const struct config_node *cn;
     205                 :            :         struct config_value *cv;
     206                 :            : 
     207                 :            :         /* umask */
     208                 :          3 :         cmd->default_settings.umask = find_config_tree_int(cmd,
     209                 :            :                                                       "global/umask",
     210                 :            :                                                       DEFAULT_UMASK);
     211                 :            : 
     212         [ +  + ]:          3 :         if ((old_umask = umask((mode_t) cmd->default_settings.umask)) !=
     213                 :            :             (mode_t) cmd->default_settings.umask)
     214                 :          1 :                 log_verbose("Set umask to %04o", cmd->default_settings.umask);
     215                 :            : 
     216                 :            :         /* dev dir */
     217         [ -  + ]:          3 :         if (dm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/",
     218                 :            :                          find_config_tree_str(cmd, "devices/dir",
     219                 :            :                                          DEFAULT_DEV_DIR)) < 0) {
     220                 :          0 :                 log_error("Device directory given in config file too long");
     221                 :          0 :                 return 0;
     222                 :            :         }
     223                 :            : #ifdef DEVMAPPER_SUPPORT
     224                 :          3 :         dm_set_dev_dir(cmd->dev_dir);
     225                 :            : #endif
     226                 :            : 
     227                 :            :         /* proc dir */
     228         [ -  + ]:          3 :         if (dm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
     229                 :            :                          find_config_tree_str(cmd, "global/proc",
     230                 :            :                                          DEFAULT_PROC_DIR)) < 0) {
     231                 :          0 :                 log_error("Device directory given in config file too long");
     232                 :          0 :                 return 0;
     233                 :            :         }
     234                 :            : 
     235 [ +  - ][ -  + ]:          3 :         if (*cmd->proc_dir && !dir_exists(cmd->proc_dir)) {
     236                 :          0 :                 log_warn("WARNING: proc dir %s not found - some checks will be bypassed",
     237                 :            :                          cmd->proc_dir);
     238                 :          0 :                 cmd->proc_dir[0] = '\0';
     239                 :            :         }
     240                 :            : 
     241                 :          3 :         _get_sysfs_dir(cmd);
     242                 :            : 
     243                 :            :         /* activation? */
     244                 :          3 :         cmd->default_settings.activation = find_config_tree_int(cmd,
     245                 :            :                                                            "global/activation",
     246                 :            :                                                            DEFAULT_ACTIVATION);
     247                 :          3 :         set_activation(cmd->default_settings.activation);
     248                 :            : 
     249                 :          3 :         cmd->default_settings.suffix = find_config_tree_int(cmd,
     250                 :            :                                                        "global/suffix",
     251                 :            :                                                        DEFAULT_SUFFIX);
     252                 :            : 
     253         [ -  + ]:          3 :         if (!(cmd->default_settings.unit_factor =
     254                 :          3 :               units_to_bytes(find_config_tree_str(cmd,
     255                 :            :                                              "global/units",
     256                 :            :                                              DEFAULT_UNITS),
     257                 :            :                              &cmd->default_settings.unit_type))) {
     258                 :          0 :                 log_error("Invalid units specification");
     259                 :          0 :                 return 0;
     260                 :            :         }
     261                 :            : 
     262                 :          3 :         read_ahead = find_config_tree_str(cmd, "activation/readahead", DEFAULT_READ_AHEAD);
     263         [ +  - ]:          3 :         if (!strcasecmp(read_ahead, "auto"))
     264                 :          3 :                 cmd->default_settings.read_ahead = DM_READ_AHEAD_AUTO;
     265         [ #  # ]:          0 :         else if (!strcasecmp(read_ahead, "none"))
     266                 :          0 :                 cmd->default_settings.read_ahead = DM_READ_AHEAD_NONE;
     267                 :            :         else {
     268                 :          0 :                 log_error("Invalid readahead specification");
     269                 :          0 :                 return 0;
     270                 :            :         }
     271                 :            : 
     272                 :          3 :         cmd->default_settings.udev_rules = find_config_tree_int(cmd,
     273                 :            :                                                                 "activation/udev_rules",
     274                 :            :                                                                 DEFAULT_UDEV_RULES);
     275                 :            : 
     276                 :          3 :         cmd->default_settings.udev_sync = find_config_tree_int(cmd,
     277                 :            :                                                                 "activation/udev_sync",
     278                 :            :                                                                 DEFAULT_UDEV_SYNC);
     279                 :            : 
     280                 :          3 :         cmd->stripe_filler = find_config_tree_str(cmd,
     281                 :            :                                                   "activation/missing_stripe_filler",
     282                 :            :                                                   DEFAULT_STRIPE_FILLER);
     283                 :            : 
     284                 :            :         /* FIXME Missing error code checks from the stats, not log_warn?, notify if setting overridden, delay message/check till it is actually used (eg consider if lvm shell - file could appear later after this check)? */
     285   [ +  -  +  - ]:          6 :         if (!strcmp(cmd->stripe_filler, "/dev/ioerror") &&
     286                 :          3 :             stat(cmd->stripe_filler, &st))
     287                 :          3 :                 cmd->stripe_filler = "error";
     288                 :            : 
     289         [ -  + ]:          3 :         if (strcmp(cmd->stripe_filler, "error")) {
     290         [ #  # ]:          0 :                 if (stat(cmd->stripe_filler, &st)) {
     291                 :          0 :                         log_warn("WARNING: activation/missing_stripe_filler = \"%s\" "
     292                 :            :                                  "is invalid,", cmd->stripe_filler);
     293                 :          0 :                         log_warn("         stat failed: %s", strerror(errno));
     294                 :          0 :                         log_warn("Falling back to \"error\" missing_stripe_filler.");
     295                 :          0 :                         cmd->stripe_filler = "error";
     296         [ #  # ]:          0 :                 } else if (!S_ISBLK(st.st_mode)) {
     297                 :          0 :                         log_warn("WARNING: activation/missing_stripe_filler = \"%s\" "
     298                 :            :                                  "is not a block device.", cmd->stripe_filler);
     299                 :          0 :                         log_warn("Falling back to \"error\" missing_stripe_filler.");
     300                 :          0 :                         cmd->stripe_filler = "error";
     301                 :            :                 }
     302                 :            :         }
     303                 :            : 
     304                 :          3 :         cmd->si_unit_consistency = find_config_tree_int(cmd,
     305                 :            :                                                   "global/si_unit_consistency",
     306                 :            :                                                   DEFAULT_SI_UNIT_CONSISTENCY);
     307                 :            : 
     308         [ -  + ]:          3 :         if ((cn = find_config_tree_node(cmd, "activation/mlock_filter")))
     309         [ #  # ]:          0 :                 for (cv = cn->v; cv; cv = cv->next) 
     310 [ #  # ][ #  # ]:          0 :                         if ((cv->type != CFG_STRING) || !cv->v.str[0]) 
     311                 :          0 :                                 log_error("Ignoring invalid activation/mlock_filter entry in config file");
     312                 :            : 
     313                 :          3 :         return 1;
     314                 :            : }
     315                 :            : 
     316                 :          0 : static int _set_tag(struct cmd_context *cmd, const char *tag)
     317                 :            : {
     318                 :          0 :         log_very_verbose("Setting host tag: %s", dm_pool_strdup(cmd->libmem, tag));
     319                 :            : 
     320         [ #  # ]:          0 :         if (!str_list_add(cmd->libmem, &cmd->tags, tag)) {
     321                 :          0 :                 log_error("_set_tag: str_list_add %s failed", tag);
     322                 :          0 :                 return 0;
     323                 :            :         }
     324                 :            : 
     325                 :          0 :         return 1;
     326                 :            : }
     327                 :            : 
     328                 :          0 : static int _check_host_filters(struct cmd_context *cmd, struct config_node *hn,
     329                 :            :                                int *passes)
     330                 :            : {
     331                 :            :         struct config_node *cn;
     332                 :            :         struct config_value *cv;
     333                 :            : 
     334                 :          0 :         *passes = 1;
     335                 :            : 
     336         [ #  # ]:          0 :         for (cn = hn; cn; cn = cn->sib) {
     337         [ #  # ]:          0 :                 if (!cn->v)
     338                 :          0 :                         continue;
     339         [ #  # ]:          0 :                 if (!strcmp(cn->key, "host_list")) {
     340                 :          0 :                         *passes = 0;
     341         [ #  # ]:          0 :                         if (cn->v->type == CFG_EMPTY_ARRAY)
     342                 :          0 :                                 continue;
     343         [ #  # ]:          0 :                         for (cv = cn->v; cv; cv = cv->next) {
     344         [ #  # ]:          0 :                                 if (cv->type != CFG_STRING) {
     345                 :          0 :                                         log_error("Invalid hostname string "
     346                 :            :                                                   "for tag %s", cn->key);
     347                 :          0 :                                         return 0;
     348                 :            :                                 }
     349         [ #  # ]:          0 :                                 if (!strcmp(cv->v.str, cmd->hostname)) {
     350                 :          0 :                                         *passes = 1;
     351                 :          0 :                                         return 1;
     352                 :            :                                 }
     353                 :            :                         }
     354                 :            :                 }
     355         [ #  # ]:          0 :                 if (!strcmp(cn->key, "host_filter")) {
     356                 :          0 :                         log_error("host_filter not supported yet");
     357                 :          0 :                         return 0;
     358                 :            :                 }
     359                 :            :         }
     360                 :            : 
     361                 :          0 :         return 1;
     362                 :            : }
     363                 :            : 
     364                 :          3 : static int _init_tags(struct cmd_context *cmd, struct config_tree *cft)
     365                 :            : {
     366                 :            :         const struct config_node *tn, *cn;
     367                 :            :         const char *tag;
     368                 :            :         int passes;
     369                 :            : 
     370 [ -  + ][ #  # ]:          3 :         if (!(tn = find_config_node(cft->root, "tags")) || !tn->child)
     371                 :          3 :                 return 1;
     372                 :            : 
     373                 :            :         /* NB hosttags 0 when already 1 intentionally does not delete the tag */
     374   [ #  #  #  # ]:          0 :         if (!cmd->hosttags && find_config_int(cft->root, "tags/hosttags",
     375                 :          0 :                                               DEFAULT_HOSTTAGS)) {
     376                 :            :                 /* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */
     377         [ #  # ]:          0 :                 if (!_set_tag(cmd, cmd->hostname))
     378                 :          0 :                         return_0;
     379                 :          0 :                 cmd->hosttags = 1;
     380                 :            :         }
     381                 :            : 
     382         [ #  # ]:          0 :         for (cn = tn->child; cn; cn = cn->sib) {
     383         [ #  # ]:          0 :                 if (cn->v)
     384                 :          0 :                         continue;
     385                 :          0 :                 tag = cn->key;
     386         [ #  # ]:          0 :                 if (*tag == '@')
     387                 :          0 :                         tag++;
     388         [ #  # ]:          0 :                 if (!validate_name(tag)) {
     389                 :          0 :                         log_error("Invalid tag in config file: %s", cn->key);
     390                 :          0 :                         return 0;
     391                 :            :                 }
     392         [ #  # ]:          0 :                 if (cn->child) {
     393                 :          0 :                         passes = 0;
     394         [ #  # ]:          0 :                         if (!_check_host_filters(cmd, cn->child, &passes))
     395                 :          0 :                                 return_0;
     396         [ #  # ]:          0 :                         if (!passes)
     397                 :          0 :                                 continue;
     398                 :            :                 }
     399         [ #  # ]:          0 :                 if (!_set_tag(cmd, tag))
     400                 :          0 :                         return_0;
     401                 :            :         }
     402                 :            : 
     403                 :          3 :         return 1;
     404                 :            : }
     405                 :            : 
     406                 :          3 : static int _load_config_file(struct cmd_context *cmd, const char *tag)
     407                 :            : {
     408                 :          3 :         char config_file[PATH_MAX] = "";
     409                 :          3 :         const char *filler = "";
     410                 :            :         struct stat info;
     411                 :            :         struct config_tree_list *cfl;
     412                 :            : 
     413         [ -  + ]:          3 :         if (*tag)
     414                 :          0 :                 filler = "_";
     415                 :            : 
     416         [ -  + ]:          3 :         if (dm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
     417                 :            :                          cmd->system_dir, filler, tag) < 0) {
     418                 :          0 :                 log_error("LVM_SYSTEM_DIR or tag was too long");
     419                 :          0 :                 return 0;
     420                 :            :         }
     421                 :            : 
     422         [ -  + ]:          3 :         if (!(cfl = dm_pool_alloc(cmd->libmem, sizeof(*cfl)))) {
     423                 :          0 :                 log_error("config_tree_list allocation failed");
     424                 :          0 :                 return 0;
     425                 :            :         }
     426                 :            : 
     427         [ -  + ]:          3 :         if (!(cfl->cft = create_config_tree(config_file, 0))) {
     428                 :          0 :                 log_error("config_tree allocation failed");
     429                 :          0 :                 return 0;
     430                 :            :         }
     431                 :            : 
     432                 :            :         /* Is there a config file? */
     433         [ -  + ]:          3 :         if (stat(config_file, &info) == -1) {
     434         [ #  # ]:          0 :                 if (errno == ENOENT) {
     435                 :          0 :                         dm_list_add(&cmd->config_files, &cfl->list);
     436                 :          0 :                         goto out;
     437                 :            :                 }
     438                 :          0 :                 log_sys_error("stat", config_file);
     439                 :          0 :                 destroy_config_tree(cfl->cft);
     440                 :          0 :                 return 0;
     441                 :            :         }
     442                 :            : 
     443                 :          3 :         log_very_verbose("Loading config file: %s", config_file);
     444         [ -  + ]:          3 :         if (!read_config_file(cfl->cft)) {
     445                 :          0 :                 log_error("Failed to load config file %s", config_file);
     446                 :          0 :                 destroy_config_tree(cfl->cft);
     447                 :          0 :                 return 0;
     448                 :            :         }
     449                 :            : 
     450                 :          3 :         dm_list_add(&cmd->config_files, &cfl->list);
     451                 :            : 
     452                 :            :       out:
     453         [ -  + ]:          3 :         if (*tag)
     454                 :          0 :                 _init_tags(cmd, cfl->cft);
     455                 :            :         else
     456                 :            :                 /* Use temporary copy of lvm.conf while loading other files */
     457                 :          3 :                 cmd->cft = cfl->cft;
     458                 :            : 
     459                 :          3 :         return 1;
     460                 :            : }
     461                 :            : 
     462                 :            : /* Find and read first config file */
     463                 :          3 : static int _init_lvm_conf(struct cmd_context *cmd)
     464                 :            : {
     465                 :            :         /* No config file if LVM_SYSTEM_DIR is empty */
     466         [ -  + ]:          3 :         if (!*cmd->system_dir) {
     467         [ #  # ]:          0 :                 if (!(cmd->cft = create_config_tree(NULL, 0))) {
     468                 :          0 :                         log_error("Failed to create config tree");
     469                 :          0 :                         return 0;
     470                 :            :                 }
     471                 :          0 :                 return 1;
     472                 :            :         }
     473                 :            : 
     474         [ -  + ]:          3 :         if (!_load_config_file(cmd, ""))
     475                 :          0 :                 return_0;
     476                 :            : 
     477                 :          3 :         return 1;
     478                 :            : }
     479                 :            : 
     480                 :            : /* Read any additional config files */
     481                 :          3 : static int _init_tag_configs(struct cmd_context *cmd)
     482                 :            : {
     483                 :            :         struct str_list *sl;
     484                 :            : 
     485                 :            :         /* Tag list may grow while inside this loop */
     486         [ -  + ]:          3 :         dm_list_iterate_items(sl, &cmd->tags) {
     487         [ #  # ]:          0 :                 if (!_load_config_file(cmd, sl->str))
     488                 :          0 :                         return_0;
     489                 :            :         }
     490                 :            : 
     491                 :          3 :         return 1;
     492                 :            : }
     493                 :            : 
     494                 :          3 : static int _merge_config_files(struct cmd_context *cmd)
     495                 :            : {
     496                 :            :         struct config_tree_list *cfl;
     497                 :            : 
     498                 :            :         /* Replace temporary duplicate copy of lvm.conf */
     499         [ +  - ]:          3 :         if (cmd->cft->root) {
     500         [ -  + ]:          3 :                 if (!(cmd->cft = create_config_tree(NULL, 0))) {
     501                 :          0 :                         log_error("Failed to create config tree");
     502                 :          0 :                         return 0;
     503                 :            :                 }
     504                 :            :         }
     505                 :            : 
     506         [ +  + ]:          6 :         dm_list_iterate_items(cfl, &cmd->config_files) {
     507                 :            :                 /* Merge all config trees into cmd->cft using merge/tag rules */
     508         [ -  + ]:          3 :                 if (!merge_config_tree(cmd, cmd->cft, cfl->cft))
     509                 :          0 :                         return_0;
     510                 :            :         }
     511                 :            : 
     512                 :          3 :         return 1;
     513                 :            : }
     514                 :            : 
     515                 :          3 : static void _destroy_tags(struct cmd_context *cmd)
     516                 :            : {
     517                 :            :         struct dm_list *slh, *slht;
     518                 :            : 
     519         [ -  + ]:          3 :         dm_list_iterate_safe(slh, slht, &cmd->tags) {
     520                 :          0 :                 dm_list_del(slh);
     521                 :            :         }
     522                 :          3 : }
     523                 :            : 
     524                 :          0 : int config_files_changed(struct cmd_context *cmd)
     525                 :            : {
     526                 :            :         struct config_tree_list *cfl;
     527                 :            : 
     528         [ #  # ]:          0 :         dm_list_iterate_items(cfl, &cmd->config_files) {
     529         [ #  # ]:          0 :                 if (config_file_changed(cfl->cft))
     530                 :          0 :                         return 1;
     531                 :            :         }
     532                 :            : 
     533                 :          0 :         return 0;
     534                 :            : }
     535                 :            : 
     536                 :          3 : static void _destroy_tag_configs(struct cmd_context *cmd)
     537                 :            : {
     538                 :            :         struct config_tree_list *cfl;
     539                 :            : 
     540         [ +  + ]:          6 :         dm_list_iterate_items(cfl, &cmd->config_files) {
     541         [ -  + ]:          3 :                 if (cfl->cft == cmd->cft)
     542                 :          0 :                         cmd->cft = NULL;
     543                 :          3 :                 destroy_config_tree(cfl->cft);
     544                 :            :         }
     545                 :            : 
     546         [ +  - ]:          3 :         if (cmd->cft) {
     547                 :          3 :                 destroy_config_tree(cmd->cft);
     548                 :          3 :                 cmd->cft = NULL;
     549                 :            :         }
     550                 :            : 
     551                 :          3 :         dm_list_init(&cmd->config_files);
     552                 :          3 : }
     553                 :            : 
     554                 :          3 : static int _init_dev_cache(struct cmd_context *cmd)
     555                 :            : {
     556                 :            :         const struct config_node *cn;
     557                 :            :         struct config_value *cv;
     558                 :            : 
     559         [ -  + ]:          3 :         if (!dev_cache_init(cmd))
     560                 :          0 :                 return_0;
     561                 :            : 
     562         [ -  + ]:          3 :         if (!(cn = find_config_tree_node(cmd, "devices/scan"))) {
     563         [ #  # ]:          0 :                 if (!dev_cache_add_dir("/dev")) {
     564                 :          0 :                         log_error("Failed to add /dev to internal "
     565                 :            :                                   "device cache");
     566                 :          0 :                         return 0;
     567                 :            :                 }
     568                 :          0 :                 log_verbose("device/scan not in config file: "
     569                 :            :                             "Defaulting to /dev");
     570                 :          0 :                 return 1;
     571                 :            :         }
     572                 :            : 
     573         [ +  + ]:          6 :         for (cv = cn->v; cv; cv = cv->next) {
     574         [ -  + ]:          3 :                 if (cv->type != CFG_STRING) {
     575                 :          0 :                         log_error("Invalid string in config file: "
     576                 :            :                                   "devices/scan");
     577                 :          0 :                         return 0;
     578                 :            :                 }
     579                 :            : 
     580         [ -  + ]:          3 :                 if (!dev_cache_add_dir(cv->v.str)) {
     581                 :          0 :                         log_error("Failed to add %s to internal device cache",
     582                 :            :                                   cv->v.str);
     583                 :          0 :                         return 0;
     584                 :            :                 }
     585                 :            :         }
     586                 :            : 
     587         [ +  - ]:          3 :         if (!(cn = find_config_tree_node(cmd, "devices/loopfiles")))
     588                 :          3 :                 return 1;
     589                 :            : 
     590         [ #  # ]:          0 :         for (cv = cn->v; cv; cv = cv->next) {
     591         [ #  # ]:          0 :                 if (cv->type != CFG_STRING) {
     592                 :          0 :                         log_error("Invalid string in config file: "
     593                 :            :                                   "devices/loopfiles");
     594                 :          0 :                         return 0;
     595                 :            :                 }
     596                 :            : 
     597         [ #  # ]:          0 :                 if (!dev_cache_add_loopfile(cv->v.str)) {
     598                 :          0 :                         log_error("Failed to add loopfile %s to internal "
     599                 :            :                                   "device cache", cv->v.str);
     600                 :          0 :                         return 0;
     601                 :            :                 }
     602                 :            :         }
     603                 :            : 
     604                 :            : 
     605                 :          3 :         return 1;
     606                 :            : }
     607                 :            : 
     608                 :            : #define MAX_FILTERS 4
     609                 :            : 
     610                 :          3 : static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
     611                 :            : {
     612                 :          3 :         unsigned nr_filt = 0;
     613                 :            :         const struct config_node *cn;
     614                 :            :         struct dev_filter *filters[MAX_FILTERS];
     615                 :            : 
     616                 :          3 :         memset(filters, 0, sizeof(filters));
     617                 :            : 
     618                 :            :         /*
     619                 :            :          * Filters listed in order: top one gets applied first.
     620                 :            :          * Failure to initialise some filters is not fatal.
     621                 :            :          * Update MAX_FILTERS definition above when adding new filters.
     622                 :            :          */
     623                 :            : 
     624                 :            :         /*
     625                 :            :          * sysfs filter. Only available on 2.6 kernels.  Non-critical.
     626                 :            :          * Listed first because it's very efficient at eliminating
     627                 :            :          * unavailable devices.
     628                 :            :          */
     629         [ +  - ]:          3 :         if (find_config_tree_bool(cmd, "devices/sysfs_scan",
     630                 :            :                              DEFAULT_SYSFS_SCAN)) {
     631         [ +  - ]:          3 :                 if ((filters[nr_filt] = sysfs_filter_create(cmd->sysfs_dir)))
     632                 :          3 :                         nr_filt++;
     633                 :            :         }
     634                 :            : 
     635                 :            :         /* regex filter. Optional. */
     636         [ -  + ]:          3 :         if (!(cn = find_config_tree_node(cmd, "devices/filter")))
     637                 :          0 :                 log_very_verbose("devices/filter not found in config file: "
     638                 :            :                                  "no regex filter installed");
     639                 :            : 
     640         [ -  + ]:          3 :         else if (!(filters[nr_filt++] = regex_filter_create(cn->v))) {
     641                 :          0 :                 log_error("Failed to create regex device filter");
     642                 :          0 :                 return NULL;
     643                 :            :         }
     644                 :            : 
     645                 :            :         /* device type filter. Required. */
     646                 :          3 :         cn = find_config_tree_node(cmd, "devices/types");
     647         [ -  + ]:          3 :         if (!(filters[nr_filt++] = lvm_type_filter_create(cmd->proc_dir, cn))) {
     648                 :          0 :                 log_error("Failed to create lvm type filter");
     649                 :          0 :                 return NULL;
     650                 :            :         }
     651                 :            : 
     652                 :            :         /* md component filter. Optional, non-critical. */
     653         [ +  - ]:          3 :         if (find_config_tree_bool(cmd, "devices/md_component_detection",
     654                 :            :                              DEFAULT_MD_COMPONENT_DETECTION)) {
     655                 :          3 :                 init_md_filtering(1);
     656         [ +  - ]:          3 :                 if ((filters[nr_filt] = md_filter_create()))
     657                 :          3 :                         nr_filt++;
     658                 :            :         }
     659                 :            : 
     660                 :            :         /* Only build a composite filter if we really need it. */
     661         [ -  + ]:          6 :         return (nr_filt == 1) ?
     662                 :          3 :             filters[0] : composite_filter_create(nr_filt, filters);
     663                 :            : }
     664                 :            : 
     665                 :          3 : static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
     666                 :            : {
     667                 :          3 :         const char *dev_cache = NULL, *cache_dir, *cache_file_prefix;
     668                 :            :         struct dev_filter *f3, *f4;
     669                 :            :         struct stat st;
     670                 :            :         char cache_file[PATH_MAX];
     671                 :            : 
     672                 :          3 :         cmd->dump_filter = 0;
     673                 :            : 
     674         [ -  + ]:          3 :         if (!(f3 = _init_filter_components(cmd)))
     675                 :          0 :                 return 0;
     676                 :            : 
     677                 :          3 :         init_ignore_suspended_devices(find_config_tree_int(cmd,
     678                 :            :             "devices/ignore_suspended_devices", DEFAULT_IGNORE_SUSPENDED_DEVICES));
     679                 :            : 
     680                 :            :         /*
     681                 :            :          * If 'cache_dir' or 'cache_file_prefix' is set, ignore 'cache'.
     682                 :            :          */
     683                 :          3 :         cache_dir = find_config_tree_str(cmd, "devices/cache_dir", NULL);
     684                 :          3 :         cache_file_prefix = find_config_tree_str(cmd, "devices/cache_file_prefix", NULL);
     685                 :            : 
     686   [ -  +  #  # ]:          6 :         if (cache_dir || cache_file_prefix) {
     687 [ -  + ][ +  - ]:          3 :                 if (dm_snprintf(cache_file, sizeof(cache_file),
         [ +  - ][ -  + ]
                 [ -  + ]
     688                 :            :                     "%s%s%s/%s.cache",
     689                 :            :                     cache_dir ? "" : cmd->system_dir,
     690                 :            :                     cache_dir ? "" : "/",
     691                 :          3 :                     cache_dir ? : DEFAULT_CACHE_SUBDIR,
     692                 :          3 :                     cache_file_prefix ? : DEFAULT_CACHE_FILE_PREFIX) < 0) {
     693                 :          0 :                         log_error("Persistent cache filename too long.");
     694                 :          0 :                         return 0;
     695                 :            :                 }
     696   [ #  #  #  # ]:          0 :         } else if (!(dev_cache = find_config_tree_str(cmd, "devices/cache", NULL)) &&
     697                 :          0 :                    (dm_snprintf(cache_file, sizeof(cache_file),
     698                 :            :                                 "%s/%s/%s.cache",
     699                 :            :                                 cmd->system_dir, DEFAULT_CACHE_SUBDIR,
     700                 :            :                                 DEFAULT_CACHE_FILE_PREFIX) < 0)) {
     701                 :          0 :                 log_error("Persistent cache filename too long.");
     702                 :          0 :                 return 0;
     703                 :            :         }
     704                 :            : 
     705         [ +  - ]:          3 :         if (!dev_cache)
     706                 :          3 :                 dev_cache = cache_file;
     707                 :            : 
     708         [ -  + ]:          3 :         if (!(f4 = persistent_filter_create(f3, dev_cache))) {
     709                 :          0 :                 log_error("Failed to create persistent device filter");
     710                 :          0 :                 return 0;
     711                 :            :         }
     712                 :            : 
     713                 :            :         /* Should we ever dump persistent filter state? */
     714         [ +  - ]:          3 :         if (find_config_tree_int(cmd, "devices/write_cache_state", 1))
     715                 :          3 :                 cmd->dump_filter = 1;
     716                 :            : 
     717         [ -  + ]:          3 :         if (!*cmd->system_dir)
     718                 :          0 :                 cmd->dump_filter = 0;
     719                 :            : 
     720                 :            :         /*
     721                 :            :          * Only load persistent filter device cache on startup if it is newer
     722                 :            :          * than the config file and this is not a long-lived process.
     723                 :            :          */
     724 [ +  + ][ +  -  :          6 :         if (load_persistent_cache && !cmd->is_long_lived &&
          +  -  +  -  -  
                      + ]
     725                 :          1 :             !stat(dev_cache, &st) &&
     726                 :          1 :             (st.st_ctime > config_file_timestamp(cmd->cft)) &&
     727                 :          1 :             !persistent_filter_load(f4, NULL))
     728                 :          0 :                 log_verbose("Failed to load existing device cache from %s",
     729                 :            :                             dev_cache);
     730                 :            : 
     731                 :          3 :         cmd->filter = f4;
     732                 :            : 
     733                 :          3 :         return 1;
     734                 :            : }
     735                 :            : 
     736                 :          3 : static int _init_formats(struct cmd_context *cmd)
     737                 :            : {
     738                 :            :         const char *format;
     739                 :            : 
     740                 :            :         struct format_type *fmt;
     741                 :            : 
     742                 :            : #ifdef HAVE_LIBDL
     743                 :            :         const struct config_node *cn;
     744                 :            : #endif
     745                 :            : 
     746                 :          3 :         label_init();
     747                 :            : 
     748                 :            : #ifdef LVM1_INTERNAL
     749         [ -  + ]:          3 :         if (!(fmt = init_lvm1_format(cmd)))
     750                 :          0 :                 return 0;
     751                 :          3 :         fmt->library = NULL;
     752                 :          3 :         dm_list_add(&cmd->formats, &fmt->list);
     753                 :            : #endif
     754                 :            : 
     755                 :            : #ifdef POOL_INTERNAL
     756         [ -  + ]:          3 :         if (!(fmt = init_pool_format(cmd)))
     757                 :          0 :                 return 0;
     758                 :          3 :         fmt->library = NULL;
     759                 :          3 :         dm_list_add(&cmd->formats, &fmt->list);
     760                 :            : #endif
     761                 :            : 
     762                 :            : #ifdef HAVE_LIBDL
     763                 :            :         /* Load any formats in shared libs if not static */
     764   [ +  -  -  + ]:          6 :         if (!is_static() &&
     765                 :          3 :             (cn = find_config_tree_node(cmd, "global/format_libraries"))) {
     766                 :            : 
     767                 :            :                 struct config_value *cv;
     768                 :            :                 struct format_type *(*init_format_fn) (struct cmd_context *);
     769                 :            :                 void *lib;
     770                 :            : 
     771         [ #  # ]:          0 :                 for (cv = cn->v; cv; cv = cv->next) {
     772         [ #  # ]:          0 :                         if (cv->type != CFG_STRING) {
     773                 :          0 :                                 log_error("Invalid string in config file: "
     774                 :            :                                           "global/format_libraries");
     775                 :          0 :                                 return 0;
     776                 :            :                         }
     777         [ #  # ]:          0 :                         if (!(lib = load_shared_library(cmd, cv->v.str,
     778                 :            :                                                         "format", 0)))
     779                 :          0 :                                 return_0;
     780                 :            : 
     781         [ #  # ]:          0 :                         if (!(init_format_fn = dlsym(lib, "init_format"))) {
     782                 :          0 :                                 log_error("Shared library %s does not contain "
     783                 :            :                                           "format functions", cv->v.str);
     784                 :          0 :                                 dlclose(lib);
     785                 :          0 :                                 return 0;
     786                 :            :                         }
     787                 :            : 
     788         [ #  # ]:          0 :                         if (!(fmt = init_format_fn(cmd)))
     789                 :          0 :                                 return 0;
     790                 :          0 :                         fmt->library = lib;
     791                 :          0 :                         dm_list_add(&cmd->formats, &fmt->list);
     792                 :            :                 }
     793                 :            :         }
     794                 :            : #endif
     795                 :            : 
     796         [ -  + ]:          3 :         if (!(fmt = create_text_format(cmd)))
     797                 :          0 :                 return 0;
     798                 :          3 :         fmt->library = NULL;
     799                 :          3 :         dm_list_add(&cmd->formats, &fmt->list);
     800                 :            : 
     801                 :          3 :         cmd->fmt_backup = fmt;
     802                 :            : 
     803                 :          3 :         format = find_config_tree_str(cmd, "global/format",
     804                 :            :                                  DEFAULT_FORMAT);
     805                 :            : 
     806         [ +  - ]:          9 :         dm_list_iterate_items(fmt, &cmd->formats) {
     807 [ +  + ][ -  + ]:          9 :                 if (!strcasecmp(fmt->name, format) ||
                 [ #  # ]
     808                 :          6 :                     (fmt->alias && !strcasecmp(fmt->alias, format))) {
     809                 :          3 :                         cmd->default_settings.fmt = fmt;
     810                 :          3 :                         cmd->fmt = cmd->default_settings.fmt;
     811                 :          3 :                         return 1;
     812                 :            :                 }
     813                 :            :         }
     814                 :            : 
     815                 :          0 :         log_error("_init_formats: Default format (%s) not found", format);
     816                 :          3 :         return 0;
     817                 :            : }
     818                 :            : 
     819                 :          3 : int init_lvmcache_orphans(struct cmd_context *cmd)
     820                 :            : {
     821                 :            :         struct format_type *fmt;
     822                 :            : 
     823         [ +  + ]:         12 :         dm_list_iterate_items(fmt, &cmd->formats)
     824         [ -  + ]:          9 :                 if (!lvmcache_add_orphan_vginfo(fmt->orphan_vg_name, fmt))
     825                 :          0 :                         return_0;
     826                 :            : 
     827                 :          3 :         return 1;
     828                 :            : }
     829                 :            : 
     830                 :            : struct segtype_library {
     831                 :            :         struct cmd_context *cmd;
     832                 :            :         void *lib;
     833                 :            :         const char *libname;
     834                 :            : };
     835                 :            : 
     836                 :          6 : int lvm_register_segtype(struct segtype_library *seglib,
     837                 :            :                          struct segment_type *segtype)
     838                 :            : {
     839                 :            :         struct segment_type *segtype2;
     840                 :            : 
     841                 :          6 :         segtype->library = seglib->lib;
     842                 :          6 :         segtype->cmd = seglib->cmd;
     843                 :            : 
     844         [ +  + ]:         45 :         dm_list_iterate_items(segtype2, &seglib->cmd->segtypes) {
     845         [ +  - ]:         39 :                 if (strcmp(segtype2->name, segtype->name))
     846                 :         39 :                         continue;
     847                 :          0 :                 log_error("Duplicate segment type %s: "
     848                 :            :                           "unloading shared library %s",
     849                 :            :                           segtype->name, seglib->libname);
     850                 :          0 :                 segtype->ops->destroy(segtype);
     851                 :          0 :                 return 0;
     852                 :            :         }
     853                 :            : 
     854                 :          6 :         dm_list_add(&seglib->cmd->segtypes, &segtype->list);
     855                 :            : 
     856                 :          6 :         return 1;
     857                 :            : }
     858                 :            : 
     859                 :          0 : static int _init_single_segtype(struct cmd_context *cmd,
     860                 :            :                                 struct segtype_library *seglib)
     861                 :            : {
     862                 :            :         struct segment_type *(*init_segtype_fn) (struct cmd_context *);
     863                 :            :         struct segment_type *segtype;
     864                 :            : 
     865         [ #  # ]:          0 :         if (!(init_segtype_fn = dlsym(seglib->lib, "init_segtype"))) {
     866                 :          0 :                 log_error("Shared library %s does not contain segment type "
     867                 :            :                           "functions", seglib->libname);
     868                 :          0 :                 return 0;
     869                 :            :         }
     870                 :            : 
     871         [ #  # ]:          0 :         if (!(segtype = init_segtype_fn(seglib->cmd)))
     872                 :          0 :                 return_0;
     873                 :            : 
     874                 :          0 :         return lvm_register_segtype(seglib, segtype);
     875                 :            : }
     876                 :            : 
     877                 :          3 : static int _init_segtypes(struct cmd_context *cmd)
     878                 :            : {
     879                 :            :         struct segment_type *segtype;
     880                 :          3 :         struct segtype_library seglib = { .cmd = cmd };
     881                 :            : 
     882                 :            : #ifdef HAVE_LIBDL
     883                 :            :         const struct config_node *cn;
     884                 :            : #endif
     885                 :            : 
     886         [ -  + ]:          3 :         if (!(segtype = init_striped_segtype(cmd)))
     887                 :          0 :                 return 0;
     888                 :          3 :         segtype->library = NULL;
     889                 :          3 :         dm_list_add(&cmd->segtypes, &segtype->list);
     890                 :            : 
     891         [ -  + ]:          3 :         if (!(segtype = init_zero_segtype(cmd)))
     892                 :          0 :                 return 0;
     893                 :          3 :         segtype->library = NULL;
     894                 :          3 :         dm_list_add(&cmd->segtypes, &segtype->list);
     895                 :            : 
     896         [ -  + ]:          3 :         if (!(segtype = init_error_segtype(cmd)))
     897                 :          0 :                 return 0;
     898                 :          3 :         segtype->library = NULL;
     899                 :          3 :         dm_list_add(&cmd->segtypes, &segtype->list);
     900                 :            : 
     901         [ -  + ]:          3 :         if (!(segtype = init_free_segtype(cmd)))
     902                 :          0 :                 return 0;
     903                 :          3 :         segtype->library = NULL;
     904                 :          3 :         dm_list_add(&cmd->segtypes, &segtype->list);
     905                 :            : 
     906                 :            : #ifdef SNAPSHOT_INTERNAL
     907         [ -  + ]:          3 :         if (!(segtype = init_snapshot_segtype(cmd)))
     908                 :          0 :                 return 0;
     909                 :          3 :         segtype->library = NULL;
     910                 :          3 :         dm_list_add(&cmd->segtypes, &segtype->list);
     911                 :            : #endif
     912                 :            : 
     913                 :            : #ifdef MIRRORED_INTERNAL
     914         [ -  + ]:          3 :         if (!(segtype = init_mirrored_segtype(cmd)))
     915                 :          0 :                 return 0;
     916                 :          3 :         segtype->library = NULL;
     917                 :          3 :         dm_list_add(&cmd->segtypes, &segtype->list);
     918                 :            : #endif
     919                 :            : 
     920                 :            : #ifdef REPLICATOR_INTERNAL
     921         [ -  + ]:          3 :         if (!init_replicator_segtype(&seglib))
     922                 :          0 :                 return 0;
     923                 :            : #endif
     924                 :            : 
     925                 :            : #ifdef HAVE_LIBDL
     926                 :            :         /* Load any formats in shared libs unless static */
     927   [ +  -  -  + ]:          6 :         if (!is_static() &&
     928                 :          3 :             (cn = find_config_tree_node(cmd, "global/segment_libraries"))) {
     929                 :            : 
     930                 :            :                 struct config_value *cv;
     931                 :            :                 int (*init_multiple_segtypes_fn) (struct cmd_context *,
     932                 :            :                                                   struct segtype_library *);
     933                 :            : 
     934         [ #  # ]:          0 :                 for (cv = cn->v; cv; cv = cv->next) {
     935         [ #  # ]:          0 :                         if (cv->type != CFG_STRING) {
     936                 :          0 :                                 log_error("Invalid string in config file: "
     937                 :            :                                           "global/segment_libraries");
     938                 :          0 :                                 return 0;
     939                 :            :                         }
     940                 :          0 :                         seglib.libname = cv->v.str;
     941         [ #  # ]:          0 :                         if (!(seglib.lib = load_shared_library(cmd,
     942                 :            :                                                         seglib.libname,
     943                 :            :                                                         "segment type", 0)))
     944                 :          0 :                                 return_0;
     945                 :            : 
     946         [ #  # ]:          0 :                         if ((init_multiple_segtypes_fn =
     947                 :          0 :                             dlsym(seglib.lib, "init_multiple_segtypes"))) {
     948         [ #  # ]:          0 :                                 if (dlsym(seglib.lib, "init_segtype"))
     949                 :          0 :                                         log_warn("WARNING: Shared lib %s has "
     950                 :            :                                                  "conflicting init fns.  Using"
     951                 :            :                                                  " init_multiple_segtypes().",
     952                 :            :                                                  seglib.libname);
     953                 :            :                         } else
     954                 :          0 :                                 init_multiple_segtypes_fn =
     955                 :            :                                     _init_single_segtype;
     956                 :            :  
     957         [ #  # ]:          0 :                         if (!init_multiple_segtypes_fn(cmd, &seglib)) {
     958                 :            :                                 struct dm_list *sgtl, *tmp;
     959                 :          0 :                                 log_error("init_multiple_segtypes() failed: "
     960                 :            :                                           "Unloading shared library %s",
     961                 :            :                                           seglib.libname);
     962         [ #  # ]:          0 :                                 dm_list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
     963                 :          0 :                                         segtype = dm_list_item(sgtl, struct segment_type);
     964         [ #  # ]:          0 :                                         if (segtype->library == seglib.lib) {
     965                 :          0 :                                                 dm_list_del(&segtype->list);
     966                 :          0 :                                                 segtype->ops->destroy(segtype);
     967                 :            :                                         }
     968                 :            :                                 }
     969                 :          0 :                                 dlclose(seglib.lib);
     970                 :          0 :                                 return_0;
     971                 :            :                         }
     972                 :            :                 }
     973                 :            :         }
     974                 :            : #endif
     975                 :            : 
     976                 :          3 :         return 1;
     977                 :            : }
     978                 :            : 
     979                 :          1 : static int _init_hostname(struct cmd_context *cmd)
     980                 :            : {
     981                 :            :         struct utsname uts;
     982                 :            : 
     983         [ -  + ]:          1 :         if (uname(&uts)) {
     984                 :          0 :                 log_sys_error("uname", "_init_hostname");
     985                 :          0 :                 return 0;
     986                 :            :         }
     987                 :            : 
     988         [ -  + ]:          1 :         if (!(cmd->hostname = dm_pool_strdup(cmd->libmem, uts.nodename))) {
     989                 :          0 :                 log_error("_init_hostname: dm_pool_strdup failed");
     990                 :          0 :                 return 0;
     991                 :            :         }
     992                 :            : 
     993         [ -  + ]:          1 :         if (!(cmd->kernel_vsn = dm_pool_strdup(cmd->libmem, uts.release))) {
     994                 :          0 :                 log_error("_init_hostname: dm_pool_strdup kernel_vsn failed");
     995                 :          0 :                 return 0;
     996                 :            :         }
     997                 :            : 
     998                 :          1 :         return 1;
     999                 :            : }
    1000                 :            : 
    1001                 :          1 : static int _init_backup(struct cmd_context *cmd)
    1002                 :            : {
    1003                 :            :         uint32_t days, min;
    1004                 :            :         char default_dir[PATH_MAX];
    1005                 :            :         const char *dir;
    1006                 :            : 
    1007                 :            :         if (!cmd->system_dir) {
    1008                 :            :                 log_warn("WARNING: Metadata changes will NOT be backed up");
    1009                 :            :                 backup_init(cmd, "", 0);
    1010                 :            :                 archive_init(cmd, "", 0, 0, 0);
    1011                 :            :                 return 1;
    1012                 :            :         }
    1013                 :            : 
    1014                 :            :         /* set up archiving */
    1015                 :          1 :         cmd->default_settings.archive =
    1016                 :          1 :             find_config_tree_bool(cmd, "backup/archive",
    1017                 :            :                              DEFAULT_ARCHIVE_ENABLED);
    1018                 :            : 
    1019                 :          1 :         days = (uint32_t) find_config_tree_int(cmd, "backup/retain_days",
    1020                 :            :                                           DEFAULT_ARCHIVE_DAYS);
    1021                 :            : 
    1022                 :          1 :         min = (uint32_t) find_config_tree_int(cmd, "backup/retain_min",
    1023                 :            :                                          DEFAULT_ARCHIVE_NUMBER);
    1024                 :            : 
    1025         [ -  + ]:          1 :         if (dm_snprintf
    1026                 :            :             (default_dir, sizeof(default_dir), "%s/%s", cmd->system_dir,
    1027                 :            :              DEFAULT_ARCHIVE_SUBDIR) == -1) {
    1028                 :          0 :                 log_error("Couldn't create default archive path '%s/%s'.",
    1029                 :            :                           cmd->system_dir, DEFAULT_ARCHIVE_SUBDIR);
    1030                 :          0 :                 return 0;
    1031                 :            :         }
    1032                 :            : 
    1033                 :          1 :         dir = find_config_tree_str(cmd, "backup/archive_dir",
    1034                 :            :                               default_dir);
    1035                 :            : 
    1036         [ -  + ]:          1 :         if (!archive_init(cmd, dir, days, min,
    1037                 :            :                           cmd->default_settings.archive)) {
    1038                 :          0 :                 log_debug("archive_init failed.");
    1039                 :          0 :                 return 0;
    1040                 :            :         }
    1041                 :            : 
    1042                 :            :         /* set up the backup */
    1043                 :          1 :         cmd->default_settings.backup =
    1044                 :          1 :             find_config_tree_bool(cmd, "backup/backup",
    1045                 :            :                              DEFAULT_BACKUP_ENABLED);
    1046                 :            : 
    1047         [ -  + ]:          1 :         if (dm_snprintf
    1048                 :            :             (default_dir, sizeof(default_dir), "%s/%s", cmd->system_dir,
    1049                 :            :              DEFAULT_BACKUP_SUBDIR) == -1) {
    1050                 :          0 :                 log_error("Couldn't create default backup path '%s/%s'.",
    1051                 :            :                           cmd->system_dir, DEFAULT_BACKUP_SUBDIR);
    1052                 :          0 :                 return 0;
    1053                 :            :         }
    1054                 :            : 
    1055                 :          1 :         dir = find_config_tree_str(cmd, "backup/backup_dir", default_dir);
    1056                 :            : 
    1057         [ -  + ]:          1 :         if (!backup_init(cmd, dir, cmd->default_settings.backup)) {
    1058                 :          0 :                 log_debug("backup_init failed.");
    1059                 :          0 :                 return 0;
    1060                 :            :         }
    1061                 :            : 
    1062                 :          1 :         return 1;
    1063                 :            : }
    1064                 :            : 
    1065                 :          1 : static void _init_rand(struct cmd_context *cmd)
    1066                 :            : {
    1067         [ +  - ]:          1 :         if (read_urandom(&cmd->rand_seed, sizeof(cmd->rand_seed)))
    1068                 :          1 :                 return;
    1069                 :            : 
    1070                 :          1 :         cmd->rand_seed = (unsigned) time(NULL) + (unsigned) getpid();
    1071                 :            : }
    1072                 :            : 
    1073                 :          1 : static void _init_globals(struct cmd_context *cmd)
    1074                 :            : {
    1075                 :          1 :         init_full_scan_done(0);
    1076                 :          1 :         init_mirror_in_sync(0);
    1077                 :            : 
    1078                 :          1 : }
    1079                 :            : 
    1080                 :            : /* Entry point */
    1081                 :          1 : struct cmd_context *create_toolcontext(unsigned is_long_lived,
    1082                 :            :                                        const char *system_dir)
    1083                 :            : {
    1084                 :            :         struct cmd_context *cmd;
    1085                 :            : 
    1086                 :            : #ifdef M_MMAP_MAX
    1087                 :          1 :         mallopt(M_MMAP_MAX, 0);
    1088                 :            : #endif
    1089                 :            : 
    1090         [ -  + ]:          1 :         if (!setlocale(LC_ALL, ""))
    1091                 :          0 :                 log_very_verbose("setlocale failed");
    1092                 :            : 
    1093                 :            : #ifdef INTL_PACKAGE
    1094                 :            :         bindtextdomain(INTL_PACKAGE, LOCALEDIR);
    1095                 :            : #endif
    1096                 :            : 
    1097                 :          1 :         init_syslog(DEFAULT_LOG_FACILITY);
    1098                 :            : 
    1099         [ -  + ]:          1 :         if (!(cmd = dm_malloc(sizeof(*cmd)))) {
    1100                 :          0 :                 log_error("Failed to allocate command context");
    1101                 :          0 :                 return NULL;
    1102                 :            :         }
    1103                 :          1 :         memset(cmd, 0, sizeof(*cmd));
    1104                 :          1 :         cmd->is_long_lived = is_long_lived;
    1105                 :          1 :         cmd->handles_missing_pvs = 0;
    1106                 :          1 :         cmd->handles_unknown_segments = 0;
    1107                 :          1 :         cmd->hosttags = 0;
    1108                 :          1 :         dm_list_init(&cmd->formats);
    1109                 :          1 :         dm_list_init(&cmd->segtypes);
    1110                 :          1 :         dm_list_init(&cmd->tags);
    1111                 :          1 :         dm_list_init(&cmd->config_files);
    1112                 :            : 
    1113                 :            :         /* FIXME Make this configurable? */
    1114                 :          1 :         reset_lvm_errno(1);
    1115                 :            : 
    1116                 :            :         /*
    1117                 :            :          * Environment variable LVM_SYSTEM_DIR overrides this below.
    1118                 :            :          */
    1119         [ -  + ]:          1 :         if (system_dir)
    1120                 :          0 :                 strncpy(cmd->system_dir, system_dir, sizeof(cmd->system_dir) - 1);
    1121                 :            :         else
    1122                 :          1 :                 strcpy(cmd->system_dir, DEFAULT_SYS_DIR);
    1123                 :            : 
    1124         [ -  + ]:          1 :         if (!_get_env_vars(cmd))
    1125                 :          0 :                 goto_out;
    1126                 :            : 
    1127                 :            :         /* Create system directory if it doesn't already exist */
    1128 [ +  - ][ -  + ]:          1 :         if (*cmd->system_dir && !dm_create_dir(cmd->system_dir)) {
    1129                 :          0 :                 log_error("Failed to create LVM2 system dir for metadata backups, config "
    1130                 :            :                           "files and internal cache.");
    1131                 :          0 :                 log_error("Set environment variable LVM_SYSTEM_DIR to alternative location "
    1132                 :            :                           "or empty string.");
    1133                 :          0 :                 goto out;
    1134                 :            :         }
    1135                 :            : 
    1136         [ -  + ]:          1 :         if (!(cmd->libmem = dm_pool_create("library", 4 * 1024))) {
    1137                 :          0 :                 log_error("Library memory pool creation failed");
    1138                 :          0 :                 goto out;
    1139                 :            :         }
    1140                 :            : 
    1141         [ -  + ]:          1 :         if (!_init_lvm_conf(cmd))
    1142                 :          0 :                 goto_out;
    1143                 :            : 
    1144                 :          1 :         _init_logging(cmd);
    1145                 :            : 
    1146         [ -  + ]:          1 :         if (!_init_hostname(cmd))
    1147                 :          0 :                 goto_out;
    1148                 :            : 
    1149         [ -  + ]:          1 :         if (!_init_tags(cmd, cmd->cft))
    1150                 :          0 :                 goto_out;
    1151                 :            : 
    1152         [ -  + ]:          1 :         if (!_init_tag_configs(cmd))
    1153                 :          0 :                 goto_out;
    1154                 :            : 
    1155         [ -  + ]:          1 :         if (!_merge_config_files(cmd))
    1156                 :          0 :                 goto_out;
    1157                 :            : 
    1158         [ -  + ]:          1 :         if (!_process_config(cmd))
    1159                 :          0 :                 goto_out;
    1160                 :            : 
    1161         [ -  + ]:          1 :         if (!_init_dev_cache(cmd))
    1162                 :          0 :                 goto_out;
    1163                 :            : 
    1164         [ -  + ]:          1 :         if (!_init_filters(cmd, 1))
    1165                 :          0 :                 goto_out;
    1166                 :            : 
    1167         [ -  + ]:          1 :         if (!(cmd->mem = dm_pool_create("command", 4 * 1024))) {
    1168                 :          0 :                 log_error("Command memory pool creation failed");
    1169                 :          0 :                 goto out;
    1170                 :            :         }
    1171                 :            : 
    1172                 :          1 :         memlock_init(cmd);
    1173                 :            : 
    1174         [ -  + ]:          1 :         if (!_init_formats(cmd))
    1175                 :          0 :                 goto_out;
    1176                 :            : 
    1177         [ -  + ]:          1 :         if (!init_lvmcache_orphans(cmd))
    1178                 :          0 :                 goto_out;
    1179                 :            : 
    1180         [ -  + ]:          1 :         if (!_init_segtypes(cmd))
    1181                 :          0 :                 goto_out;
    1182                 :            : 
    1183         [ -  + ]:          1 :         if (!_init_backup(cmd))
    1184                 :          0 :                 goto_out;
    1185                 :            : 
    1186                 :          1 :         _init_rand(cmd);
    1187                 :            : 
    1188                 :          1 :         _init_globals(cmd);
    1189                 :            : 
    1190                 :          1 :         cmd->default_settings.cache_vgmetadata = 1;
    1191                 :          1 :         cmd->current_settings = cmd->default_settings;
    1192                 :            : 
    1193                 :          1 :         cmd->config_valid = 1;
    1194                 :            : out:
    1195                 :          1 :         return cmd;
    1196                 :            : }
    1197                 :            : 
    1198                 :          3 : static void _destroy_formats(struct dm_list *formats)
    1199                 :            : {
    1200                 :            :         struct dm_list *fmtl, *tmp;
    1201                 :            :         struct format_type *fmt;
    1202                 :            :         void *lib;
    1203                 :            : 
    1204         [ +  + ]:         12 :         dm_list_iterate_safe(fmtl, tmp, formats) {
    1205                 :          9 :                 fmt = dm_list_item(fmtl, struct format_type);
    1206                 :          9 :                 dm_list_del(&fmt->list);
    1207                 :          9 :                 lib = fmt->library;
    1208                 :          9 :                 fmt->ops->destroy(fmt);
    1209                 :            : #ifdef HAVE_LIBDL
    1210         [ -  + ]:          9 :                 if (lib)
    1211                 :          0 :                         dlclose(lib);
    1212                 :            : #endif
    1213                 :            :         }
    1214                 :          3 : }
    1215                 :            : 
    1216                 :          3 : static void _destroy_segtypes(struct dm_list *segtypes)
    1217                 :            : {
    1218                 :            :         struct dm_list *sgtl, *tmp;
    1219                 :            :         struct segment_type *segtype;
    1220                 :            :         void *lib;
    1221                 :            : 
    1222         [ +  + ]:         27 :         dm_list_iterate_safe(sgtl, tmp, segtypes) {
    1223                 :         24 :                 segtype = dm_list_item(sgtl, struct segment_type);
    1224                 :         24 :                 dm_list_del(&segtype->list);
    1225                 :         24 :                 lib = segtype->library;
    1226                 :         24 :                 segtype->ops->destroy(segtype);
    1227                 :            : #ifdef HAVE_LIBDL
    1228                 :            :                 /*
    1229                 :            :                  * If no segtypes remain from this library, close it.
    1230                 :            :                  */
    1231         [ -  + ]:         24 :                 if (lib) {
    1232                 :            :                         struct segment_type *segtype2;
    1233         [ #  # ]:          0 :                         dm_list_iterate_items(segtype2, segtypes)
    1234         [ #  # ]:          0 :                                 if (segtype2->library == lib)
    1235                 :          0 :                                         goto skip_dlclose;
    1236                 :          0 :                         dlclose(lib);
    1237                 :            : skip_dlclose:
    1238                 :            :                         ;
    1239                 :            :                 }
    1240                 :            : #endif
    1241                 :            :         }
    1242                 :          3 : }
    1243                 :            : 
    1244                 :          0 : int refresh_filters(struct cmd_context *cmd)
    1245                 :            : {
    1246                 :          0 :         int r, saved_ignore_suspended_devices = ignore_suspended_devices();
    1247                 :            : 
    1248         [ #  # ]:          0 :         if (cmd->filter) {
    1249                 :          0 :                 cmd->filter->destroy(cmd->filter);
    1250                 :          0 :                 cmd->filter = NULL;
    1251                 :            :         }
    1252                 :            : 
    1253                 :          0 :         r = _init_filters(cmd, 0);
    1254                 :            : 
    1255                 :            :         /*
    1256                 :            :          * During repair code must not reset suspended flag.
    1257                 :            :          */
    1258                 :          0 :         init_ignore_suspended_devices(saved_ignore_suspended_devices);
    1259                 :            : 
    1260                 :          0 :         return r;
    1261                 :            : }
    1262                 :            : 
    1263                 :          2 : int refresh_toolcontext(struct cmd_context *cmd)
    1264                 :            : {
    1265                 :          2 :         log_verbose("Reloading config files");
    1266                 :            : 
    1267                 :            :         /*
    1268                 :            :          * Don't update the persistent filter cache as we will
    1269                 :            :          * perform a full rescan.
    1270                 :            :          */
    1271                 :            : 
    1272                 :          2 :         activation_release();
    1273                 :          2 :         lvmcache_destroy(cmd, 0);
    1274                 :          2 :         label_exit();
    1275                 :          2 :         _destroy_segtypes(&cmd->segtypes);
    1276                 :          2 :         _destroy_formats(&cmd->formats);
    1277         [ +  - ]:          2 :         if (cmd->filter) {
    1278                 :          2 :                 cmd->filter->destroy(cmd->filter);
    1279                 :          2 :                 cmd->filter = NULL;
    1280                 :            :         }
    1281                 :          2 :         dev_cache_exit();
    1282                 :          2 :         _destroy_tags(cmd);
    1283                 :          2 :         _destroy_tag_configs(cmd);
    1284                 :            : 
    1285                 :          2 :         cmd->config_valid = 0;
    1286                 :            : 
    1287                 :          2 :         cmd->hosttags = 0;
    1288                 :            : 
    1289         [ -  + ]:          2 :         if (!_init_lvm_conf(cmd))
    1290                 :          0 :                 return 0;
    1291                 :            : 
    1292                 :          2 :         _init_logging(cmd);
    1293                 :            : 
    1294         [ -  + ]:          2 :         if (!_init_tags(cmd, cmd->cft))
    1295                 :          0 :                 return 0;
    1296                 :            : 
    1297         [ -  + ]:          2 :         if (!_init_tag_configs(cmd))
    1298                 :          0 :                 return 0;
    1299                 :            : 
    1300         [ -  + ]:          2 :         if (!_merge_config_files(cmd))
    1301                 :          0 :                 return 0;
    1302                 :            : 
    1303         [ -  + ]:          2 :         if (!_process_config(cmd))
    1304                 :          0 :                 return 0;
    1305                 :            : 
    1306         [ -  + ]:          2 :         if (!_init_dev_cache(cmd))
    1307                 :          0 :                 return 0;
    1308                 :            : 
    1309         [ -  + ]:          2 :         if (!_init_filters(cmd, 0))
    1310                 :          0 :                 return 0;
    1311                 :            : 
    1312         [ -  + ]:          2 :         if (!_init_formats(cmd))
    1313                 :          0 :                 return 0;
    1314                 :            : 
    1315         [ -  + ]:          2 :         if (!init_lvmcache_orphans(cmd))
    1316                 :          0 :                 return 0;
    1317                 :            : 
    1318         [ -  + ]:          2 :         if (!_init_segtypes(cmd))
    1319                 :          0 :                 return 0;
    1320                 :            : 
    1321                 :          2 :         cmd->config_valid = 1;
    1322                 :            : 
    1323                 :          2 :         reset_lvm_errno(1);
    1324                 :          2 :         return 1;
    1325                 :            : }
    1326                 :            : 
    1327                 :          1 : void destroy_toolcontext(struct cmd_context *cmd)
    1328                 :            : {
    1329         [ +  - ]:          1 :         if (cmd->dump_filter)
    1330                 :          1 :                 persistent_filter_dump(cmd->filter);
    1331                 :            : 
    1332                 :          1 :         archive_exit(cmd);
    1333                 :          1 :         backup_exit(cmd);
    1334                 :          1 :         lvmcache_destroy(cmd, 0);
    1335                 :          1 :         label_exit();
    1336                 :          1 :         _destroy_segtypes(&cmd->segtypes);
    1337                 :          1 :         _destroy_formats(&cmd->formats);
    1338         [ +  - ]:          1 :         if (cmd->filter)
    1339                 :          1 :                 cmd->filter->destroy(cmd->filter);
    1340         [ +  - ]:          1 :         if (cmd->mem)
    1341                 :          1 :                 dm_pool_destroy(cmd->mem);
    1342                 :          1 :         dev_cache_exit();
    1343                 :          1 :         _destroy_tags(cmd);
    1344                 :          1 :         _destroy_tag_configs(cmd);
    1345         [ +  - ]:          1 :         if (cmd->libmem)
    1346                 :          1 :                 dm_pool_destroy(cmd->libmem);
    1347                 :          1 :         dm_free(cmd);
    1348                 :            : 
    1349                 :          1 :         release_log_memory();
    1350                 :          1 :         activation_exit();
    1351                 :          1 :         fin_log();
    1352                 :          1 :         fin_syslog();
    1353                 :          1 :         reset_lvm_errno(0);
    1354                 :          1 : }

Generated by: LCOV version 1.8