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/ZYppCallbacks.h"
00015 #include "zypp/MediaSetAccess.h"
00016 #include "zypp/PathInfo.h"
00017
00018
00019 using namespace std;
00020
00022 namespace zypp
00023 {
00024
00025
00026 ChecksumFileChecker::ChecksumFileChecker( const CheckSum &checksum )
00027 : _checksum(checksum)
00028 {
00029 }
00030
00031 bool ChecksumFileChecker::operator()( const Pathname &file )
00032 {
00033
00034 CheckSum real_checksum( _checksum.type(), filesystem::checksum( file, _checksum.type() ));
00035 if ( real_checksum == _checksum )
00036 {
00037 return true;
00038 }
00039 else
00040 {
00041 ERR << "Got " << real_checksum << ", expected " << _checksum << std::endl;
00042 return false;
00043 }
00044 }
00045
00046 bool NullFileChecker::operator()(const Pathname &file )
00047 {
00048 return true;
00049 }
00050
00051 MediaSetAccess::MediaSetAccess( const Url &url, const Pathname &path )
00052 : _url(url),
00053 _path(path)
00054 {
00055 MIL << "initializing.." << std::endl;
00056
00057
00058
00059 }
00060
00061 MediaSetAccess::~MediaSetAccess()
00062 {
00063 }
00064
00065 void MediaSetAccess::setVerifiers( const std::vector<media::MediaVerifierRef> &verifiers )
00066 {
00067 _verifiers = verifiers;
00068 }
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 void MediaSetAccess::providePossiblyCachedMetadataFile( const Pathname &file_to_download, unsigned medianr, const Pathname &destination, const Pathname &cached_file, const CheckSum &checksum )
00082 {
00083 Url file_url( _url.asString() + file_to_download.asString() );
00084
00085 if ( PathInfo(cached_file).isExist() && (! checksum.empty()) && is_checksum( cached_file, checksum ) )
00086 {
00087 MIL << "file " << file_url << " found in previous cache. Using cached copy." << std::endl;
00088
00089
00090 if ( filesystem::copy(cached_file, destination) != 0 )
00091 ZYPP_THROW(Exception("Can't copy " + cached_file.asString() + " to " + destination.asString()));
00092 }
00093 else
00094 {
00095
00096 Pathname downloaded_file = provideFile( file_to_download, medianr, ChecksumFileChecker(checksum) );
00097
00098 if ( filesystem::copy(downloaded_file, destination) != 0 )
00099 ZYPP_THROW(Exception("Can't copy " + downloaded_file.asString() + " to " + destination.asString()));
00100 }
00101 }
00102
00103 Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr )
00104 {
00105 return provideFileInternal( file, media_nr, false, false);
00106 }
00107
00108 Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr, FileChecker checker )
00109 {
00110 Pathname p = provideFileInternal( file, media_nr, false, false);
00111
00112 if ( ! checker(p) )
00113 {
00114 ZYPP_THROW(Exception("Error checker"));
00115 }
00116 return p;
00117 }
00118
00119 Pathname MediaSetAccess::provideFileInternal(const Pathname & file, unsigned media_nr, bool cached, bool checkonly )
00120 {
00121 callback::SendReport<media::MediaChangeReport> report;
00122 media::MediaManager media_mgr;
00123
00124 media::MediaAccessId media = getMediaAccessId( media_nr);
00125
00126 do
00127 {
00128 try
00129 {
00130 DBG << "Going to try provide file " << file << " from " << media_nr << endl;
00131
00132 if ( ! media_mgr.isAttached(media) )
00133 media_mgr.attach(media);
00134 media_mgr.provideFile (media, file, false, false);
00135 break;
00136 }
00137 catch ( Exception & excp )
00138 {
00139 ZYPP_CAUGHT(excp);
00140 media::MediaChangeReport::Action user;
00141 do
00142 {
00143 DBG << "Media couldn't provide file " << file << " , releasing." << endl;
00144 try
00145 {
00146 media_mgr.release (media, false);
00147 }
00148 catch (const Exception & excpt_r)
00149 {
00150 ZYPP_CAUGHT(excpt_r);
00151 MIL << "Failed to release media " << media << endl;
00152 }
00153
00154 MIL << "Releasing all medias of all sources" << endl;
00155 try
00156 {
00157
00158 }
00159 catch (const zypp::Exception& excpt_r)
00160 {
00161 ZYPP_CAUGHT(excpt_r);
00162 ERR << "Failed to release all sources" << endl;
00163 }
00164
00165
00166 media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
00167
00168 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
00169 typeid(excp) == typeid( media::MediaNotAFileException ) )
00170 {
00171 reason = media::MediaChangeReport::NOT_FOUND;
00172 }
00173 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
00174 typeid(excp) == typeid( media::MediaNotAttachedException) )
00175 {
00176 reason = media::MediaChangeReport::WRONG;
00177 }
00178
00179 user = checkonly ? media::MediaChangeReport::ABORT :
00180 report->requestMedia (
00181 Source_Ref::noSource,
00182 media_nr,
00183 reason,
00184 excp.asUserString()
00185 );
00186
00187 DBG << "ProvideFile exception caught, callback answer: " << user << endl;
00188
00189 if( user == media::MediaChangeReport::ABORT )
00190 {
00191 DBG << "Aborting" << endl;
00192 ZYPP_RETHROW ( excp );
00193 }
00194 else if ( user == media::MediaChangeReport::IGNORE )
00195 {
00196 DBG << "Skipping" << endl;
00197 ZYPP_THROW ( source::SkipRequestedException("User-requested skipping of a file") );
00198 }
00199 else if ( user == media::MediaChangeReport::EJECT )
00200 {
00201 DBG << "Eject: try to release" << endl;
00202 try
00203 {
00204
00205 }
00206 catch (const zypp::Exception& excpt_r)
00207 {
00208 ZYPP_CAUGHT(excpt_r);
00209 ERR << "Failed to release all sources" << endl;
00210 }
00211 media_mgr.release (media, true);
00212
00213 }
00214 else if ( user == media::MediaChangeReport::RETRY ||
00215 user == media::MediaChangeReport::CHANGE_URL )
00216 {
00217
00218 DBG << "Going to try again" << endl;
00219
00220
00221
00222 break;
00223 }
00224 else
00225 {
00226 DBG << "Don't know, let's ABORT" << endl;
00227 ZYPP_RETHROW ( excp );
00228 }
00229 } while( user == media::MediaChangeReport::EJECT );
00230 }
00231
00232
00233 } while( true );
00234
00235 return media_mgr.localPath( media, file );
00236 }
00237
00238 media::MediaAccessId MediaSetAccess::getMediaAccessId (media::MediaNr medianr)
00239 {
00240 media::MediaManager media_mgr;
00241
00242 if (medias.find(medianr) != medias.end())
00243 {
00244 media::MediaAccessId id = medias[medianr];
00245
00246
00247 return id;
00248 }
00249 Url url;
00250 url = rewriteUrl (_url, medianr);
00251 media::MediaAccessId id = media_mgr.open(url, _path);
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 medias[medianr] = id;
00263
00264
00265
00266
00267 return id;
00268 }
00269
00270 Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
00271 {
00272 std::string scheme = url_r.getScheme();
00273 if (scheme == "cd" || scheme == "dvd")
00274 return url_r;
00275
00276 DBG << "Rewriting url " << url_r << endl;
00277
00278 if( scheme == "iso")
00279 {
00280 std::string isofile = url_r.getQueryParam("iso");
00281 boost::regex e("^(.*(cd|dvd))([0-9]+)(\\.iso)$", boost::regex::icase);
00282 boost::smatch what;
00283 if(boost::regex_match(isofile, what, e, boost::match_extra))
00284 {
00285 Url url( url_r);
00286 isofile = what[1] + str::numstring(medianr) + what[4];
00287 url.setQueryParam("iso", isofile);
00288 DBG << "Url rewrite result: " << url << endl;
00289 return url;
00290 }
00291 }
00292 else
00293 {
00294 std::string pathname = url_r.getPathName();
00295 boost::regex e("^(.*(cd|dvd))([0-9]+)(/?)$", boost::regex::icase);
00296 boost::smatch what;
00297 if(boost::regex_match(pathname, what, e, boost::match_extra))
00298 {
00299 Url url( url_r);
00300 pathname = what[1] + str::numstring(medianr) + what[4];
00301 url.setPathName(pathname);
00302 DBG << "Url rewrite result: " << url << endl;
00303 return url;
00304 }
00305 }
00306 return url_r;
00307 }
00308
00309 std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
00310 {
00311 return str;
00312 }
00313
00314
00315
00316
00317 MediaVerifier::MediaVerifier(const std::string & vendor_r, const std::string & id_r, const media::MediaNr media_nr)
00318 : _media_vendor(vendor_r)
00319 , _media_id(id_r)
00320 , _media_nr(media_nr)
00321 {}
00322
00323 bool MediaVerifier::isDesiredMedia(const media::MediaAccessRef &ref)
00324 {
00325 if (_media_vendor.empty() || _media_id.empty())
00326 return true;
00327
00328 Pathname media_file = "/media." + str::numstring(_media_nr) + "/media";
00329 ref->provideFile (media_file);
00330 media_file = ref->localPath(media_file);
00331 std::ifstream str(media_file.asString().c_str());
00332 std::string vendor;
00333 std::string id;
00334
00335 #warning check the stream status
00336 getline(str, vendor);
00337 getline(str, id);
00338
00339 return (vendor == _media_vendor && id == _media_id );
00340 }
00341
00342
00344 }