MediaCIFS.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00013 #include <iostream>
00014 #include <fstream>
00015
00016 #include "zypp/base/Logger.h"
00017 #include "zypp/base/Gettext.h"
00018 #include "zypp/TmpPath.h"
00019 #include "zypp/KVMap.h"
00020 #include "zypp/media/Mount.h"
00021 #include "zypp/media/MediaUserAuth.h"
00022 #include "zypp/media/CredentialManager.h"
00023 #include "zypp/ZYppCallbacks.h"
00024
00025 #warning FIXME: get rid of this dependency on Target
00026 #include "zypp/ZYppFactory.h"
00027 #include "zypp/Target.h"
00028
00029 #include "zypp/media/MediaCIFS.h"
00030
00031 #include <sys/types.h>
00032 #include <sys/mount.h>
00033 #include <errno.h>
00034 #include <dirent.h>
00035
00036 using namespace std;
00037
00038 namespace zypp {
00039 namespace media {
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 inline string getShare( Pathname spath_r )
00050 {
00051 if ( spath_r.empty() )
00052 return string();
00053
00054 string share( spath_r.absolutename().asString() );
00055 string::size_type sep = share.find( "/", 1 );
00056 if ( sep == string::npos )
00057 share = share.erase( 0, 1 );
00058 else
00059 share = share.substr( 1, sep-1 );
00060
00061
00062 while ( (sep = share.find( "%2f" )) != string::npos ) {
00063 share.replace( sep, 3, "/" );
00064 }
00065
00066 return share;
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 inline Pathname stripShare( Pathname spath_r )
00078 {
00079 if ( spath_r.empty() )
00080 return Pathname();
00081
00082 string striped( spath_r.absolutename().asString() );
00083 string::size_type sep = striped.find( "/", 1 );
00084 if ( sep == string::npos )
00085 return "/";
00086
00087 return striped.substr( sep );
00088 }
00089
00091
00092
00093
00095
00097
00098
00099
00100
00101
00102
00103
00104 MediaCIFS::MediaCIFS( const Url & url_r,
00105 const Pathname & attach_point_hint_r )
00106 : MediaHandler( url_r, attach_point_hint_r,
00107 stripShare( url_r.getPathName() ),
00108 false )
00109 {
00110 MIL << "MediaCIFS::MediaCIFS(" << url_r << ", " << attach_point_hint_r << ")" << endl;
00111 }
00112
00114
00115
00116
00117
00132 void MediaCIFS::attachTo(bool next)
00133 {
00134 if(_url.getHost().empty())
00135 ZYPP_THROW(MediaBadUrlEmptyHostException(_url));
00136 if(next)
00137 ZYPP_THROW(MediaNotSupportedException(_url));
00138
00139 string path = "//";
00140 path += _url.getHost() + "/" + getShare( _url.getPathName() );
00141
00142 MediaSourceRef media( new MediaSource( "cifs", path));
00143 AttachedMedia ret( findAttachedMedia( media));
00144
00145 if( ret.mediaSource &&
00146 ret.attachPoint &&
00147 !ret.attachPoint->empty())
00148 {
00149 DBG << "Using a shared media "
00150 << ret.mediaSource->name
00151 << " attached on "
00152 << ret.attachPoint->path
00153 << endl;
00154
00155 removeAttachPoint();
00156 setAttachPoint(ret.attachPoint);
00157 setMediaSource(ret.mediaSource);
00158 return;
00159 }
00160
00161 std::string mountpoint = attachPoint().asString();
00162 if( !isUseableAttachPoint(attachPoint()))
00163 {
00164 mountpoint = createAttachPoint().asString();
00165 if( mountpoint.empty())
00166 ZYPP_THROW( MediaBadAttachPointException(url()));
00167 setAttachPoint( mountpoint, true);
00168 }
00169
00170 Mount mount;
00171 CredentialManager cm;
00172
00173 Mount::Options options( _url.getQueryParam("mountoptions") );
00174 string username = _url.getUsername();
00175 string password = _url.getPassword();
00176
00177 if ( ! options.has( "rw" ) ) {
00178 options["ro"];
00179 }
00180
00181
00182 string workgroup = _url.getQueryParam("workgroup");
00183 if ( workgroup.empty() )
00184 workgroup = _url.getQueryParam("domain");
00185 if ( !workgroup.empty() )
00186 options["domain"] = workgroup;
00187
00188
00189
00190 Mount::Options::iterator toEnv;
00191 toEnv = options.find("username");
00192 if ( toEnv != options.end() ) {
00193 if ( username.empty() )
00194 username = toEnv->second;
00195 options.erase( toEnv );
00196 }
00197
00198 toEnv = options.find("user");
00199 if ( toEnv != options.end() ) {
00200 if ( username.empty() )
00201 username = toEnv->second;
00202 options.erase( toEnv );
00203 }
00204
00205
00206
00207 toEnv = options.find("password");
00208 if ( toEnv != options.end() ) {
00209 if ( password.empty() )
00210 password = toEnv->second;
00211 options.erase( toEnv );
00212 }
00213
00214 toEnv = options.find("pass");
00215 if ( toEnv != options.end() ) {
00216 if ( password.empty() )
00217 password = toEnv->second;
00218 options.erase( toEnv );
00219 }
00220
00221 if ( username.empty() || password.empty() )
00222 {
00223 AuthData_Ptr c = cm.getCred(_url);
00224 if (c)
00225 {
00226 username = c->username();
00227 password = c->password();
00228 }
00229 }
00230
00231 bool firstTry = true;
00232 bool authRequired = false;
00233 AuthData authdata;
00234 do
00235 {
00236
00237 if ( !firstTry )
00238 {
00239 username = authdata.username();
00240 password = authdata.password();
00241 }
00242
00243
00244 Mount::Environment environment;
00245 if ( !username.empty() )
00246 environment["USER"] = username;
00247 if ( !password.empty() )
00248 environment["PASSWD"] = password;
00249
00251
00252
00253 filesystem::TmpPath credentials;
00254 if ( !username.empty() || !password.empty() )
00255 {
00256 filesystem::TmpFile tmp;
00257 ofstream outs( tmp.path().asString().c_str() );
00258 outs << "username=" << username << endl;
00259 outs << "password=" << password << endl;
00260 outs.close();
00261
00262 credentials = tmp;
00263 options["credentials"] = credentials.path().asString();
00264 }
00265 else
00266 {
00267
00268 if ( options.has( "noguest" ) )
00269 options.erase( "noguest" );
00270 else
00271
00272
00273 options["guest"];
00274 }
00275
00276
00278
00279 try
00280 {
00281 mount.mount( path, mountpoint, "cifs",
00282 options.asString(), environment );
00283 setMediaSource(media);
00284 break;
00285 }
00286 catch (const MediaMountException & e)
00287 {
00288 ZYPP_CAUGHT( e );
00289
00290 if ( e.mountError() == "Permission denied" )
00291 authRequired = authenticate( authdata, firstTry );
00292 else
00293 ZYPP_RETHROW( e );
00294 }
00295
00296 firstTry = false;
00297 }
00298 while ( authRequired );
00299
00300
00301
00302 int limit = 3;
00303 bool mountsucceeded;
00304 while( !(mountsucceeded=isAttached()) && --limit)
00305 sleep(1);
00306
00307 if ( !mountsucceeded )
00308 {
00309 setMediaSource(MediaSourceRef());
00310 try
00311 {
00312 mount.umount(attachPoint().asString());
00313 }
00314 catch (const MediaException & excpt_r)
00315 {
00316 ZYPP_CAUGHT(excpt_r);
00317 }
00318 ZYPP_THROW(MediaMountException(
00319 "Unable to verify that the media was mounted",
00320 path, mountpoint
00321 ));
00322 }
00323 }
00324
00326
00327
00328
00329
00330
00331
00332 bool
00333 MediaCIFS::isAttached() const
00334 {
00335 return checkAttached(true);
00336 }
00337
00339
00340
00341
00342
00343
00344
00345
00346 void MediaCIFS::releaseFrom( const std::string & ejectDev )
00347 {
00348 Mount mount;
00349 mount.umount(attachPoint().asString());
00350 }
00351
00353
00354
00355
00356
00357
00358
00359 void MediaCIFS::getFile (const Pathname & filename) const
00360 {
00361 MediaHandler::getFile( filename );
00362 }
00363
00365
00366
00367
00368
00369
00370
00371 void MediaCIFS::getDir( const Pathname & dirname, bool recurse_r ) const
00372 {
00373 MediaHandler::getDir( dirname, recurse_r );
00374 }
00375
00377
00378
00379
00380
00381
00382
00383
00384 void MediaCIFS::getDirInfo( std::list<std::string> & retlist,
00385 const Pathname & dirname, bool dots ) const
00386 {
00387 MediaHandler::getDirInfo( retlist, dirname, dots );
00388 }
00389
00391
00392
00393
00394
00395
00396
00397
00398 void MediaCIFS::getDirInfo( filesystem::DirContent & retlist,
00399 const Pathname & dirname, bool dots ) const
00400 {
00401 MediaHandler::getDirInfo( retlist, dirname, dots );
00402 }
00403
00404 bool MediaCIFS::getDoesFileExist( const Pathname & filename ) const
00405 {
00406 return MediaHandler::getDoesFileExist( filename );
00407 }
00408
00409 bool MediaCIFS::authenticate(AuthData & authdata, bool firstTry) const
00410 {
00412 Target_Ptr target = zypp::getZYpp()->getTarget();
00413 CredentialManager cm(CredManagerOptions(target ? target->root() : ""));
00414
00415
00416 AuthData_Ptr cmcred = cm.getCred(_url);
00417
00418 AuthData_Ptr smbcred;
00419 smbcred.reset(new AuthData());
00420 callback::SendReport<AuthenticationReport> auth_report;
00421
00422
00423 if (!_url.getUsername().empty() && firstTry)
00424 smbcred->setUsername(_url.getUsername());
00425
00426 else if (cmcred)
00427 smbcred->setUsername(cmcred->username());
00428
00429
00430 cmcred.reset();
00431
00432 string prompt_msg = str::form(
00434 _("Authentication required for '%s'"), _url.asString().c_str());
00435
00436
00437 if (auth_report->prompt(_url, prompt_msg, *smbcred))
00438 {
00439 DBG << "callback answer: retry" << endl
00440 << "AuthData: " << *smbcred << endl;
00441
00442 if (smbcred->valid())
00443 {
00444 cmcred = smbcred;
00445
00446
00454 }
00455 }
00456 else
00457 DBG << "callback answer: cancel" << endl;
00458
00459
00460 if (cmcred)
00461 {
00462 authdata.setUsername(cmcred->username());
00463 authdata.setPassword(cmcred->password());
00464
00465
00466 cmcred->setUrl(_url);
00467 cm.addCred(*cmcred);
00468 cm.save();
00469
00470 return true;
00471 }
00472
00473 return false;
00474 }
00475
00476
00477 }
00478 }