LCOV - code coverage report
Current view: top level - src/tools/kdb - mount.cpp (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 68 136 50.0 %
Date: 2019-09-12 12:28:41 Functions: 7 10 70.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief source file of mount command
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  *
       8             :  */
       9             : 
      10             : 
      11             : #include <backend.hpp>
      12             : #include <backendbuilder.hpp>
      13             : #include <backends.hpp>
      14             : #include <cmdline.hpp>
      15             : #include <mount.hpp>
      16             : 
      17             : #include <keysetio.hpp>
      18             : 
      19             : #include <fstream>
      20             : #include <iostream>
      21             : #include <iterator>
      22             : #include <string>
      23             : #include <vector>
      24             : 
      25             : #include <kdbmodule.h>
      26             : #include <kdbprivate.h>
      27             : 
      28             : using namespace std;
      29             : using namespace kdb;
      30             : using namespace kdb::tools;
      31             : 
      32         385 : MountCommand::MountCommand ()
      33             : {
      34         385 : }
      35             : 
      36             : 
      37             : /**
      38             :  * @brief Output what currently is mounted
      39             :  */
      40          74 : void MountCommand::outputMtab (Cmdline const & cl)
      41             : {
      42         296 :         Backends::BackendInfoVector mtab = Backends::getBackendInfo (mountConf);
      43          74 :         bool all = cl.first && cl.second && cl.third;
      44          74 :         char delim = '\n';
      45          74 :         if (cl.null)
      46             :         {
      47           0 :                 delim = '\0';
      48             :         }
      49         354 :         for (Backends::BackendInfoVector::const_iterator it = mtab.begin (); it != mtab.end (); ++it)
      50             :         {
      51          29 :                 if (cl.first)
      52             :                 {
      53          58 :                         std::cout << it->path;
      54          29 :                         if (all)
      55          29 :                                 std::cout << " on ";
      56             :                         else
      57           0 :                                 std::cout << delim << std::flush;
      58             :                 }
      59             : 
      60          29 :                 if (cl.second)
      61             :                 {
      62          58 :                         std::cout << it->mountpoint;
      63          29 :                         if (all)
      64          29 :                                 std::cout << " with name ";
      65             :                         else
      66           0 :                                 std::cout << delim << std::flush;
      67             :                 }
      68             : 
      69             :                 // TODO: remove next version
      70          29 :                 if (cl.third)
      71             :                 {
      72          58 :                         std::cout << it->name;
      73          58 :                         std::cout << delim << std::flush;
      74             :                 }
      75             :         }
      76          74 : }
      77             : 
      78         233 : void MountCommand::processArguments (Cmdline const & cl)
      79             : {
      80         466 :         if (!cl.interactive && cl.arguments.size () == 1)
      81             :         {
      82           0 :                 throw invalid_argument ("wrong number of arguments, 0 or more than 1 needed");
      83             :         }
      84             : 
      85         233 :         if (cl.interactive)
      86             :         {
      87           0 :                 cout << "Welcome to interactive mounting" << endl;
      88           0 :                 cout << "Note that nothing will be made persistent" << endl;
      89           0 :                 cout << "until you say y at the very end of the mounting process" << endl;
      90           0 :                 cout << endl;
      91           0 :                 cout << "Please provide a unique name." << endl;
      92             :         }
      93         233 : }
      94             : 
      95         233 : void MountCommand::buildBackend (Cmdline const & cl)
      96             : {
      97         466 :         MountBackendBuilder backend;
      98             : 
      99         932 :         Key mpk (mp, KEY_CASCADING_NAME, KEY_END);
     100             : 
     101         233 :         if (!mpk.isValid ())
     102             :         {
     103           0 :                 throw invalid_argument (mp + " is not a valid mountpoint");
     104             :         }
     105             : 
     106         932 :         KeySet dupMountConf = mountConf.dup ();
     107             : 
     108         466 :         if (cl.force || cl.strategy != "preserve")
     109             :         {
     110           0 :                 Key cutKey (Backends::mountpointsPath, KEY_END);
     111           0 :                 cutKey.addBaseName (mpk.getName ());
     112           0 :                 mountConf.cut (cutKey);
     113             :         }
     114             : 
     115        1165 :         backend.setMountpoint (mpk, mountConf);
     116             : 
     117        1145 :         backend.setBackendConfig (cl.getPluginsConfig ("system/"));
     118             : 
     119        1145 :         PluginSpec resolver (cl.resolver);
     120         229 :         if (cl.debug)
     121             :         {
     122           0 :                 cout << "Trying to load the resolver plugin " << resolver.getName () << endl;
     123             :         }
     124             : 
     125         458 :         backend.addPlugin (PluginSpec (resolver));
     126             : 
     127         229 :         if (cl.interactive)
     128             :         {
     129           0 :                 cout << endl;
     130           0 :                 cout << "Enter a path to a file in the filesystem." << endl;
     131           0 :                 cout << "The path must either not exist or be a file." << endl;
     132           0 :                 cout << "For user or cascading mountpoints it must be a relative path." << endl;
     133           0 :                 cout << "Then, the path will be resolved dynamically." << endl;
     134           0 :                 cout << "Path: ";
     135           0 :                 cin >> path;
     136             :         }
     137             :         else
     138             :         {
     139         229 :                 path = cl.arguments[0];
     140             :         }
     141             : 
     142         687 :         backend.useConfigFile (path);
     143             : 
     144         582 :         if (!cl.quiet && path[0] == '/' && !(mpk.isSystem () || mpk.isSpec () || mpk.isCascading ()))
     145             :         {
     146          30 :                 std::cout << "Note that absolute paths are still relative to their namespace (see `kdb info resolver`)." << std::endl;
     147          30 :                 std::cout << "Only system+spec mountpoints are actually absolute." << std::endl;
     148          75 :                 std::cout << "Use `kdb file " << mp << "` to determine where the file(s) are." << std::endl;
     149          15 :                 std::cout << "Use `-q` or use `kdb set /sw/elektra/kdb/#0/current/quiet 1` to suppress infos." << std::endl;
     150             :         }
     151             : 
     152         229 :         if (cl.debug)
     153             :         {
     154           0 :                 cout << "Trying to add default plugins " << cl.plugins << endl;
     155             :         }
     156             : 
     157         916 :         backend.needPlugin ("storage");
     158         916 :         backend.needPlugin ("sync");
     159         458 :         backend.addPlugins (parseArguments (cl.plugins));
     160             : 
     161         229 :         if (cl.interactive)
     162             :         {
     163           0 :                 cout << "Now enter a sequence of plugins you want in the backend" << endl;
     164           0 :                 appendPlugins (backend);
     165             :         }
     166             :         else
     167             :         {
     168         229 :                 const size_t nonPlugins = 2;
     169        1145 :                 backend.addPlugins (parseArguments (cl.arguments.begin () + nonPlugins, cl.arguments.end ()));
     170             :         }
     171             : 
     172             :         // Call it a day
     173         229 :         outputMissingRecommends (backend.resolveNeeds (cl.withRecommends));
     174         229 :         backend.serialize (mountConf);
     175             : 
     176         456 :         if (cl.strategy == "unchanged" && cl.debug)
     177             :         {
     178           0 :                 cout << "The new configuration is:" << endl;
     179           0 :                 std::cout << mountConf;
     180           0 :                 std::cout << "------------------------" << std::endl;
     181           0 :                 cout << "The configuration originally was:" << endl;
     182           0 :                 std::cout << dupMountConf;
     183             :         }
     184             : 
     185         456 :         if (!cl.force && (cl.strategy == "unchanged" && mountConf != dupMountConf))
     186             :         {
     187             :                 // throw error because it is not unchanged
     188             :                 try
     189             :                 {
     190           0 :                         backend.setMountpoint (mpk, dupMountConf);
     191             :                 }
     192           0 :                 catch (MountpointAlreadyInUseException const & e)
     193             :                 {
     194             :                         throw MountpointAlreadyInUseException (
     195           0 :                                 std::string ("Requested unchanged mountpoint but mount would lead to changes\n") + e.what ());
     196             :                 }
     197             :         }
     198         228 : }
     199             : 
     200           0 : void MountCommand::readPluginConfig (KeySet & pluginConfig)
     201             : {
     202           0 :         string keyName;
     203           0 :         string value;
     204             : 
     205           0 :         cout << "Enter the plugin configuration" << endl;
     206           0 :         cout << "Use '.' as Key name to finish" << endl;
     207             : 
     208             :         while (true)
     209             :         {
     210           0 :                 cout << "Enter the Key name: ";
     211           0 :                 cin >> keyName;
     212             : 
     213           0 :                 if (keyName == ".") break;
     214             : 
     215           0 :                 cout << "Enter the Key value: ";
     216           0 :                 cin >> value;
     217             : 
     218           0 :                 pluginConfig.append (Key ("user/" + keyName, KEY_VALUE, value.c_str (), KEY_END));
     219             :         }
     220           0 : }
     221             : 
     222           0 : void MountCommand::appendPlugins (MountBackendInterface & backend)
     223             : {
     224           0 :         std::string pname;
     225           0 :         KeySet pluginConfig;
     226           0 :         cout << "First Plugin: ";
     227           0 :         cin >> pname;
     228           0 :         readPluginConfig (pluginConfig);
     229             : 
     230           0 :         while (pname != "." || !backend.validated ())
     231             :         {
     232             :                 try
     233             :                 {
     234           0 :                         backend.addPlugin (PluginSpec (pname, pluginConfig));
     235             :                         pluginConfig.clear ();
     236             :                 }
     237           0 :                 catch (PluginCheckException const & e)
     238             :                 {
     239           0 :                         cerr << "Could not add that plugin" << endl;
     240           0 :                         cerr << e.what () << endl;
     241             :                 }
     242           0 :                 if (!backend.validated ())
     243           0 :                         cout << "Not validated, try to add another plugin (. to abort)" << endl;
     244             :                 else
     245           0 :                         cout << "Enter . to finish entering plugins" << endl;
     246             : 
     247           0 :                 cout << endl;
     248           0 :                 cout << "Next Plugin: ";
     249           0 :                 cin >> pname;
     250             : 
     251           0 :                 if (pname != ".")
     252             :                 {
     253           0 :                         readPluginConfig (pluginConfig);
     254             :                 }
     255             : 
     256           0 :                 if (pname == "." && !backend.validated ())
     257             :                 {
     258           0 :                         std::ostringstream os;
     259           0 :                         backend.status (os);
     260           0 :                         throw CommandAbortException (os.str ());
     261             :                 }
     262             :         }
     263           0 : }
     264             : 
     265             : 
     266             : /**
     267             :  * @brief Its quite linear whats going on, but there are many steps involved
     268             :  *
     269             :  * @param cl the commandline
     270             :  *
     271             :  * @retval 0 on success (otherwise exception)
     272             :  */
     273         307 : int MountCommand::execute (Cmdline const & cl)
     274             : {
     275         307 :         readMountConf (cl);
     276             : 
     277         614 :         if (!cl.interactive && cl.arguments.empty ())
     278             :         {
     279             :                 // no interactive mode, so lets output the mtab
     280          74 :                 outputMtab (cl);
     281          74 :                 return 0;
     282             :         }
     283             : 
     284         233 :         processArguments (cl);
     285         233 :         getMountpoint (cl);
     286         233 :         buildBackend (cl);
     287         228 :         askForConfirmation (cl);
     288         228 :         doIt ();
     289             : 
     290         228 :         return 0;
     291             : }
     292             : 
     293         385 : MountCommand::~MountCommand ()
     294             : {
     295        7549 : }

Generated by: LCOV version 1.13