00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <iostream>
00011 #include <fstream>
00012
00013 #include "zypp/base/LogTools.h"
00014 #include "zypp/base/Regex.h"
00015 #include "zypp/base/UserRequestException.h"
00016 #include "zypp/ZYppCallbacks.h"
00017 #include "zypp/MediaSetAccess.h"
00018 #include "zypp/PathInfo.h"
00019
00020
00021 using namespace std;
00022
00024 namespace zypp
00025 {
00026
00027 IMPL_PTR_TYPE(MediaSetAccess);
00028
00030
00031 MediaSetAccess::MediaSetAccess(const Url &url,
00032 const Pathname & prefered_attach_point)
00033 : _url(url),
00034 _prefAttachPoint(prefered_attach_point)
00035 {
00036 MIL << "initializing.." << std::endl;
00037
00038
00039
00040 }
00041
00042
00043 MediaSetAccess::~MediaSetAccess()
00044 {
00045 release();
00046 }
00047
00048
00049 void MediaSetAccess::setVerifier( unsigned media_nr, media::MediaVerifierRef verifier )
00050 {
00051 if (_medias.find(media_nr) != _medias.end())
00052 {
00053
00054 media::MediaAccessId id = _medias[media_nr];
00055 media::MediaManager media_mgr;
00056 media_mgr.addVerifier( id, verifier );
00057
00058 _verifiers.erase(media_nr);
00059
00060
00061 }
00062 else
00063 {
00064
00065
00066 _verifiers[media_nr] = verifier;
00067 }
00068 }
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 Pathname MediaSetAccess::provideFile( const OnMediaLocation & on_media_file )
00082 {
00083 return provideFile( on_media_file.filename(), on_media_file.medianr() );
00084 }
00085
00086
00087 Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr )
00088 {
00089 return provideFileInternal( file, media_nr, false, false);
00090 }
00091
00092 bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr )
00093 {
00094 callback::SendReport<media::MediaChangeReport> report;
00095 media::MediaManager media_mgr;
00096
00097 bool exists = false;
00098
00099 do
00100 {
00101
00102 media::MediaAccessId media = getMediaAccessId( media_nr);
00103
00104 try
00105 {
00106 DBG << "Cheking if file " << file
00107 << " from media number " << media_nr << " exists." << endl;
00108
00109 if ( ! media_mgr.isAttached(media) )
00110 media_mgr.attachDesiredMedia(media);
00111 exists = media_mgr.doesFileExist(media, file);
00112 break;
00113 }
00114 catch ( media::MediaException & excp )
00115 {
00116 ZYPP_CAUGHT(excp);
00117 media::MediaChangeReport::Action user;
00118 do
00119 {
00120 DBG << "Media couldn't provide file " << file << " , releasing." << endl;
00121 try
00122 {
00123 media_mgr.release (media, false);
00124 }
00125 catch (const Exception & excpt_r)
00126 {
00127 ZYPP_CAUGHT(excpt_r);
00128 MIL << "Failed to release media " << media << endl;
00129 }
00130
00131
00132 media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
00133
00134 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
00135 typeid(excp) == typeid( media::MediaNotAFileException ) )
00136 {
00137 reason = media::MediaChangeReport::NOT_FOUND;
00138 }
00139 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
00140 typeid(excp) == typeid( media::MediaNotAttachedException) )
00141 {
00142 reason = media::MediaChangeReport::WRONG;
00143 }
00144
00145 user = report->requestMedia (
00146 _url,
00147 media_nr,
00148 reason,
00149 excp.asUserString()
00150 );
00151
00152 DBG << "doesFileExist exception caught, callback answer: " << user << endl;
00153
00154 if( user == media::MediaChangeReport::ABORT )
00155 {
00156 DBG << "Aborting" << endl;
00157 ZYPP_RETHROW ( excp );
00158 }
00159 else if ( user == media::MediaChangeReport::IGNORE )
00160 {
00161 DBG << "Skipping" << endl;
00162 SkipRequestException nexcp("User-requested skipping of a file");
00163 nexcp.remember(excp);
00164 ZYPP_THROW(nexcp);
00165 }
00166 else if ( user == media::MediaChangeReport::EJECT )
00167 {
00168 DBG << "Eject: try to release" << endl;
00169 media_mgr.releaseAll();
00170 media_mgr.release (media, true);
00171 }
00172 else if ( user == media::MediaChangeReport::RETRY ||
00173 user == media::MediaChangeReport::CHANGE_URL )
00174 {
00175
00176 DBG << "Going to try again" << endl;
00177
00178 media_mgr.close(media);
00179 _medias.erase(media_nr);
00180
00181
00182
00183 break;
00184 }
00185 else
00186 {
00187 DBG << "Don't know, let's ABORT" << endl;
00188 ZYPP_RETHROW ( excp );
00189 }
00190 } while( user == media::MediaChangeReport::EJECT );
00191 }
00192
00193
00194 } while( true );
00195
00196 return exists;
00197 }
00198
00199 Pathname MediaSetAccess::provideFileInternal(const Pathname & file, unsigned media_nr, bool cached, bool checkonly )
00200 {
00201 callback::SendReport<media::MediaChangeReport> report;
00202 media::MediaManager media_mgr;
00203
00204 media::MediaAccessId media;
00205
00206 do
00207 {
00208
00209 media = getMediaAccessId( media_nr);
00210
00211 try
00212 {
00213 DBG << "Going to try to provide file " << file
00214 << " from media number " << media_nr << endl;
00215
00216 if ( ! media_mgr.isAttached(media) )
00217 media_mgr.attachDesiredMedia(media);
00218 media_mgr.provideFile (media, file, false, false);
00219 break;
00220 }
00221 catch ( media::MediaException & excp )
00222 {
00223 ZYPP_CAUGHT(excp);
00224 media::MediaChangeReport::Action user;
00225 do
00226 {
00227 DBG << "Media couldn't provide file " << file << " , releasing." << endl;
00228 try
00229 {
00230 media_mgr.release (media, false);
00231 }
00232 catch (const Exception & excpt_r)
00233 {
00234 ZYPP_CAUGHT(excpt_r);
00235 MIL << "Failed to release media " << media << endl;
00236 }
00237
00238
00239 media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
00240
00241 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
00242 typeid(excp) == typeid( media::MediaNotAFileException ) )
00243 {
00244 reason = media::MediaChangeReport::NOT_FOUND;
00245 }
00246 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
00247 typeid(excp) == typeid( media::MediaNotAttachedException) )
00248 {
00249 reason = media::MediaChangeReport::WRONG;
00250 }
00251
00252 user = checkonly ? media::MediaChangeReport::ABORT :
00253 report->requestMedia (
00254 _url,
00255 media_nr,
00256 reason,
00257 excp.asUserString()
00258 );
00259
00260 DBG << "ProvideFile exception caught, callback answer: " << user << endl;
00261
00262 if( user == media::MediaChangeReport::ABORT )
00263 {
00264 DBG << "Aborting" << endl;
00265 ZYPP_RETHROW ( excp );
00266 }
00267 else if ( user == media::MediaChangeReport::IGNORE )
00268 {
00269 DBG << "Skipping" << endl;
00270 SkipRequestException nexcp("User-requested skipping of a file");
00271 nexcp.remember(excp);
00272 ZYPP_THROW(nexcp);
00273 }
00274 else if ( user == media::MediaChangeReport::EJECT )
00275 {
00276 DBG << "Eject: try to release" << endl;
00277 media_mgr.releaseAll();
00278 media_mgr.release (media, true);
00279 }
00280 else if ( user == media::MediaChangeReport::RETRY ||
00281 user == media::MediaChangeReport::CHANGE_URL )
00282 {
00283
00284 DBG << "Going to try again" << endl;
00285
00286 media_mgr.close(media);
00287 _medias.erase(media_nr);
00288
00289
00290
00291 break;
00292 }
00293 else
00294 {
00295 DBG << "Don't know, let's ABORT" << endl;
00296 ZYPP_RETHROW ( excp );
00297 }
00298 } while( user == media::MediaChangeReport::EJECT );
00299 }
00300
00301
00302 } while( true );
00303
00304 return media_mgr.localPath( media, file );
00305 }
00306
00307
00308 Pathname MediaSetAccess::provideDir(const Pathname & dir,
00309 bool recursive,
00310 unsigned media_nr)
00311 {
00312 callback::SendReport<media::MediaChangeReport> report;
00313 media::MediaManager media_mgr;
00314 media::MediaAccessId _media;
00315
00316 do
00317 {
00318
00319 _media = getMediaAccessId(media_nr);
00320
00321 try
00322 {
00323 DBG << "Going to try provide direcotry " << dir
00324 << (recursive ? " (recursively)" : "")
00325 << " from media nr. " << media_nr << endl;
00326
00327
00328 if (!media_mgr.isAttached(_media))
00329 media_mgr.attachDesiredMedia(_media);
00330
00331 _media = getMediaAccessId(media_nr);
00332
00333 if (recursive)
00334 media_mgr.provideDirTree(_media, dir);
00335 else
00336 media_mgr.provideDir(_media, dir);
00337
00338 break;
00339 }
00340 catch (media::MediaException & excp)
00341 {
00342 ZYPP_CAUGHT(excp);
00343 media::MediaChangeReport::Action user;
00344
00345 do
00346 {
00347 DBG << "Media couldn't provide dir " << dir << ", releasing." << endl;
00348 try
00349 {
00350 media_mgr.release (_media, false);
00351 }
00352 catch (const Exception & excpt_r)
00353 {
00354 ZYPP_CAUGHT(excpt_r);
00355 ERR << "Failed to release media " << _media << endl;
00356 }
00357
00358
00359 try
00360 {
00362
00363 }
00364 catch (const zypp::Exception& excpt_r)
00365 {
00366 ZYPP_CAUGHT(excpt_r);
00367 ERR << "Failed to release all sources" << endl;
00368 }
00369
00370
00371 media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
00372
00373 if (typeid(excp) == typeid(media::MediaFileNotFoundException)
00374 || typeid(excp) == typeid(media::MediaNotAFileException))
00375 {
00376 reason = media::MediaChangeReport::NOT_FOUND;
00377 }
00378 else if (typeid(excp) == typeid( media::MediaNotDesiredException)
00379 || typeid(excp) == typeid(media::MediaNotAttachedException))
00380 {
00381 reason = media::MediaChangeReport::WRONG;
00382 }
00383
00384 user = report->requestMedia(_url,
00385 media_nr,
00386 reason,
00387 excp.asUserString());
00388
00389 DBG << "ProvideFile exception caught, callback answer: " << user << endl;
00390
00391 if (user == media::MediaChangeReport::ABORT)
00392 {
00393 DBG << "Aborting" << endl;
00394 ZYPP_RETHROW ( excp );
00395 }
00396 else if (user == media::MediaChangeReport::EJECT)
00397 {
00398 DBG << "Eject: try to release" << endl;
00399 media_mgr.releaseAll();
00400 media_mgr.release (_media, true);
00401 }
00402 else if (user == media::MediaChangeReport::RETRY ||
00403 user == media::MediaChangeReport::CHANGE_URL)
00404 {
00405
00406 DBG << "Going to try again" << endl;
00407
00408 media_mgr.close(_media);
00409 _medias.erase(media_nr);
00410
00411
00412
00413
00414 break;
00415 }
00416 else
00417 {
00418 DBG << "Don't know, let's ABORT" << endl;
00419
00420 ZYPP_RETHROW (excp);
00421 }
00422 }
00423 while (user == media::MediaChangeReport::EJECT);
00424 }
00425
00426 }
00427 while (true);
00428
00429 return media_mgr.localPath(_media, dir);
00430 }
00431
00432 media::MediaAccessId MediaSetAccess::getMediaAccessId (media::MediaNr medianr)
00433 {
00434 media::MediaManager media_mgr;
00435
00436 if (_medias.find(medianr) != _medias.end())
00437 {
00438 media::MediaAccessId id = _medias[medianr];
00439
00440
00441 return id;
00442 }
00443 Url url;
00444 url = rewriteUrl (_url, medianr);
00445 media::MediaAccessId id = media_mgr.open(url, _prefAttachPoint);
00446 _medias[medianr] = id;
00447
00448 try
00449 {
00450 if (_verifiers.find(medianr) != _verifiers.end())
00451 {
00452
00453
00454
00455 media::MediaAccessId id = _medias[medianr];
00456 media::MediaManager media_mgr;
00457 media_mgr.delVerifier(id);
00458 media_mgr.addVerifier( id, _verifiers[medianr] );
00459
00460 _verifiers.erase(medianr);
00461 }
00462 }
00463 catch ( const Exception &e )
00464 {
00465 ZYPP_CAUGHT(e);
00466 WAR << "Verifier not found" << endl;
00467 }
00468
00469 return id;
00470 }
00471
00472
00473 Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
00474 {
00475 std::string scheme = url_r.getScheme();
00476 if (scheme == "cd" || scheme == "dvd")
00477 return url_r;
00478
00479 DBG << "Rewriting url " << url_r << endl;
00480
00481 if( scheme == "iso")
00482 {
00483
00484
00485
00486 std::string isofile = url_r.getQueryParam("iso");
00487 str::regex e("^(.*)(cd|dvd)[0-9]+\\.iso$", str::regex::icase);
00488
00489 str::smatch what;
00490 if(str::regex_match(isofile, what, e))
00491 {
00492 Url url( url_r);
00493 isofile = what[1] + what[2] + str::numstring(medianr) + ".iso";
00494 url.setQueryParam("iso", isofile);
00495 DBG << "Url rewrite result: " << url << endl;
00496 return url;
00497 }
00498 }
00499 else
00500 {
00501 std::string pathname = url_r.getPathName();
00502 str::regex e("^(.*)(cd|dvd)[0-9]+(/)?$", str::regex::icase);
00503 str::smatch what;
00504 if(str::regex_match(pathname, what, e))
00505 {
00506 Url url( url_r);
00507 pathname = what[1] + what[2] + str::numstring(medianr) + what[3];
00508 url.setPathName(pathname);
00509 DBG << "Url rewrite result: " << url << endl;
00510 return url;
00511 }
00512 }
00513 return url_r;
00514 }
00515
00516 void MediaSetAccess::release()
00517 {
00518 DBG << "Releasing all media IDs held by this MediaSetAccess" << endl;
00519 media::MediaManager manager;
00520 for (MediaMap::const_iterator m = _medias.begin(); m != _medias.end(); ++m)
00521 manager.release(m->second);
00522 }
00523
00524 std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
00525 {
00526 str << "MediaSetAccess (URL='" << _url << "', attach_point_hint='" << _prefAttachPoint << "')";
00527 return str;
00528 }
00529
00530
00531
00532
00534 }