nis-util  1.0.D108
lib/space/auto_master/functor/check.cc
Go to the documentation of this file.
00001 //
00002 // nis-util - NIS Administration Utilities
00003 // Copyright (C) 2012 Peter Miller
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or (at
00008 // your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License along
00016 // with this program. If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 
00019 #include <lib/ac/string.h>
00020 
00021 #include <lib/sizeof.h>
00022 #include <lib/space/auto_master/functor/check.h>
00023 #include <lib/space/auto_master/row/adapter.h>
00024 #include <lib/space/auto_master/row/direct.h>
00025 #include <lib/space/auto_master/row/hosts.h>
00026 
00027 
00028 space_auto_master_functor_check::~space_auto_master_functor_check()
00029 {
00030 }
00031 
00032 
00033 space_auto_master_functor_check::space_auto_master_functor_check(
00034     const space_auto_master::pointer &a_context,
00035     const space_hosts_slurp::pointer &a_hosts
00036 ) :
00037     context(a_context),
00038     hosts(a_hosts)
00039 {
00040     assert(context);
00041 }
00042 
00043 
00044 static bool
00045 dumb(const rcstring &dir)
00046 {
00047     static const char *const table[] =
00048     {
00049         "/",
00050         "/dev",
00051         "/etc",
00052         "/media",
00053         "/opt",
00054         "/proc",
00055         "/sys",
00056         "/tmp"
00057         "/usr",
00058         "/var",
00059     };
00060 
00061     for (const char *const *cpp = table; cpp < ENDOF(table); ++cpp)
00062     {
00063         if (dir == *cpp)
00064             return true;
00065     }
00066     return false;
00067 }
00068 
00069 
00070 void
00071 space_auto_master_functor_check::check_for_dumb_place(
00072     const space_auto_master_row::pointer &rp)
00073 {
00074     const mount_point &mp = rp->get_mount_point();
00075     rcstring dir = mp.get_mount_point();
00076     if (dumb(dir))
00077     {
00078         context->error
00079         (
00080             mp.get_source_location(),
00081             "directory %s is not a suitable mount point",
00082             dir.quote_c().c_str()
00083         );
00084     }
00085 }
00086 
00087 
00088 static bool
00089 below_dir(const rcstring &s1, const rcstring &s2)
00090 {
00091     return
00092         (
00093             s1.size() < s2.size()
00094         &&
00095             0 == memcmp(s1.c_str(), s2.c_str(), s1.size())
00096         &&
00097             s2[s1.size()] == '/'
00098         );
00099 }
00100 
00101 
00102 void
00103 space_auto_master_functor_check::check_for_overlap(
00104     const space_auto_master_row::pointer &rp)
00105 {
00106     rcstring dir = rp->get_mount_point().get_mount_point();
00107     for
00108     (
00109         overlap_t::const_iterator it = overlap.begin();
00110         it != overlap.end();
00111         ++it
00112     )
00113     {
00114         space_auto_master_row::pointer rp2 = *it;
00115         rcstring dir2 = rp2->get_mount_point().get_mount_point();
00116 
00117         if (dir == dir2)
00118         {
00119             context->error
00120             (
00121                 rp->get_mount_point().get_source_location(),
00122                 "duplicate %s mount point...",
00123                 dir.quote_c().c_str()
00124             );
00125             context->error
00126             (
00127                 rp2->get_mount_point().get_source_location(),
00128                 "... here is the location of the first %s mount point",
00129                 rp2->get_mount_point().get_mount_point().quote_c().c_str()
00130             );
00131             return;
00132         }
00133 
00134         if (below_dir(dir2, dir))
00135         {
00136             context->error
00137             (
00138                 rp->get_mount_point().get_source_location(),
00139                 "mount point %s is beneath...",
00140                 dir.quote_c().c_str()
00141             );
00142             context->error
00143             (
00144                 rp2->get_mount_point().get_source_location(),
00145                 "...existing %s mount point",
00146                 dir2.quote_c().c_str()
00147             );
00148             return;
00149         }
00150         if (below_dir(dir, dir2))
00151         {
00152             context->error
00153             (
00154                 rp->get_mount_point().get_source_location(),
00155                 "mount point %s is above...",
00156                 dir.quote_c().c_str()
00157             );
00158             context->error
00159             (
00160                 rp2->get_mount_point().get_source_location(),
00161                 "...existing %s mount point",
00162                 dir2.quote_c().c_str()
00163             );
00164             return;
00165         }
00166     }
00167     overlap.push_back(rp);
00168 }
00169 
00170 
00171 //
00172 // Many applications (including Arc/Info) require that path names be
00173 // entirely uppercase or entirely lower case.  They have a variety of
00174 // heart-attacks if there is mixed case.  Because most of the existing
00175 // pathnames are lower case, enforce the requirement that they all be
00176 // lower case.
00177 //
00178 
00179 void
00180 space_auto_master_functor_check::check_case(
00181     const space_auto_master_row::pointer &rp)
00182 {
00183     rcstring dir = rp->get_mount_point().get_mount_point();
00184     if (!dir.is_lower_case())
00185     {
00186         rcstring suggest = dir.downcase();
00187         context->error
00188         (
00189             rp->get_mount_point().get_source_location(),
00190             "mount point %s must be lower case, suggest %s instead; "
00191             "some overly stupid applications make this unavoidable",
00192             dir.quote_c().c_str(),
00193             suggest.quote_c().c_str()
00194         );
00195     }
00196 }
00197 
00198 
00199 void
00200 space_auto_master_functor_check::walk(const space_auto_master_row::pointer &rp)
00201 {
00202     check_case(rp);
00203     check_for_dumb_place(rp);
00204     check_for_overlap(rp);
00205 
00206     if (rp->has_associated_file())
00207     {
00208         // load map and check it
00209         rp->load_map(find_file(rp->get_filename()), hosts);
00210     }
00211 
00212     // check that there is only ever one direct map
00213     {
00214         space_auto_master_row_direct::pointer rp2 =
00215             boost::dynamic_pointer_cast<space_auto_master_row_direct>(rp);
00216         if (rp2)
00217         {
00218             if (direct_rp)
00219             {
00220                 context->error
00221                 (
00222                     rp2->get_mount_point().get_source_location(),
00223                     "duplicate direct mount map specified..."
00224                 );
00225                 context->error
00226                 (
00227                     direct_rp->get_mount_point().get_source_location(),
00228                     "...here is the first direct mount map"
00229                 );
00230             }
00231             else
00232             {
00233                 direct_rp = rp2;
00234 
00235                 // Add each of the diretc mount points to the known
00236                 // mount points, so that we can validate against
00237                 // everything we know about.
00238                 space_auto_master_row::keys_t keys = rp2->get_keys();
00239                 for
00240                 (
00241                     space_auto_master_row::keys_t::const_iterator it =
00242                         keys.begin();
00243                     it != keys.end();
00244                     ++it
00245                 )
00246                 {
00247                     const mount_point &key = *it;
00248                     space_auto_master_row::pointer rp3 =
00249                         space_auto_master_row_adapter::create(key);
00250                     check_case(rp3);
00251                     check_for_dumb_place(rp3);
00252                     check_for_overlap(rp3);
00253                 }
00254             }
00255         }
00256     }
00257 
00258     // check that there is only ever one hosts map
00259     {
00260         space_auto_master_row_hosts::pointer rp2 =
00261             boost::dynamic_pointer_cast<space_auto_master_row_hosts>(rp);
00262         if (rp2)
00263         {
00264             if (hosts_rp)
00265             {
00266                 context->error
00267                 (
00268                     rp2->get_mount_point().get_source_location(),
00269                     "duplicate -hosts mount point specified..."
00270                 );
00271                 context->error
00272                 (
00273                     hosts_rp->get_mount_point().get_source_location(),
00274                     "...here is the first -hosts mount point"
00275                 );
00276             }
00277             else
00278             {
00279                 hosts_rp = rp2;
00280             }
00281         }
00282     }
00283 }
00284 
00285 
00286 // vim: set ts=8 sw=4 et :