nis-util
1.0.D108
|
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 :