libzypp
10.5.0
|
00001 /*---------------------------------------------------------------------\ 00002 | ____ _ __ __ ___ | 00003 | |__ / \ / / . \ . \ | 00004 | / / \ V /| _/ _/ | 00005 | / /__ | | | | | | | 00006 | /_____||_| |_| |_| | 00007 | | 00008 \---------------------------------------------------------------------*/ 00013 #include <iostream> 00014 #include <fstream> 00015 #include <sstream> 00016 00017 #include "zypp/TmpPath.h" 00018 #include "zypp/Date.h" 00019 #include "zypp/base/LogTools.h" 00020 #include "zypp/base/String.h" 00021 #include "zypp/media/MediaHandler.h" 00022 #include "zypp/media/MediaManager.h" 00023 #include "zypp/media/Mount.h" 00024 #include <limits.h> 00025 #include <stdlib.h> 00026 #include <errno.h> 00027 00028 00029 using namespace std; 00030 00031 // use directory.yast on every media (not just via ftp/http) 00032 #define NONREMOTE_DIRECTORY_YAST 1 00033 00034 namespace zypp { 00035 namespace media { 00036 00037 Pathname MediaHandler::_attachPrefix(""); 00038 00040 // 00041 // CLASS NAME : MediaHandler 00042 // 00044 00046 // 00047 // 00048 // METHOD NAME : MediaHandler::MediaHandler 00049 // METHOD TYPE : Constructor 00050 // 00051 // DESCRIPTION : 00052 // 00053 MediaHandler::MediaHandler ( const Url & url_r, 00054 const Pathname & attach_point_r, 00055 const Pathname & urlpath_below_attachpoint_r, 00056 const bool does_download_r ) 00057 : _mediaSource() 00058 , _attachPoint( new AttachPoint()) 00059 , _AttachPointHint() 00060 , _relativeRoot( urlpath_below_attachpoint_r) 00061 , _does_download( does_download_r ) 00062 , _attach_mtime(0) 00063 , _url( url_r ) 00064 , _parentId(0) 00065 { 00066 Pathname real_attach_point( getRealPath(attach_point_r.asString())); 00067 00068 if ( !real_attach_point.empty() ) { 00070 // check if provided attachpoint is usable. 00072 00073 PathInfo adir( real_attach_point ); 00074 // 00075 // The verify if attach_point_r isn't a mountpoint of another 00076 // device is done in the particular media handler (if needed). 00077 // 00078 // We just verify, if attach_point_r is a directory and for 00079 // schemes other than "file" and "dir", if it is absolute. 00080 // 00081 if ( !adir.isDir() 00082 || (_url.getScheme() != "file" 00083 && _url.getScheme() != "dir" 00084 && !real_attach_point.absolute()) ) 00085 { 00086 ERR << "Provided attach point is not a absolute directory: " 00087 << adir << endl; 00088 } 00089 else { 00090 attachPointHint( real_attach_point, false); 00091 setAttachPoint( real_attach_point, false); 00092 } 00093 } 00094 } 00095 00097 // 00098 // 00099 // METHOD NAME : MediaHandler::~MediaHandler 00100 // METHOD TYPE : Destructor 00101 // 00102 // DESCRIPTION : 00103 // 00104 MediaHandler::~MediaHandler() 00105 { 00106 try 00107 { 00108 removeAttachPoint(); 00109 } 00110 catch(...) {} 00111 } 00112 00113 void 00114 MediaHandler::resetParentId() 00115 { 00116 _parentId = 0; 00117 } 00118 00119 std::string 00120 MediaHandler::getRealPath(const std::string &path) 00121 { 00122 std::string real; 00123 if( !path.empty()) 00124 { 00125 #if __GNUC__ > 2 00126 00127 char *ptr = ::realpath(path.c_str(), NULL); 00128 if( ptr != NULL) 00129 { 00130 real = ptr; 00131 free( ptr); 00132 } 00133 else 00135 if( EINVAL == errno) 00136 { 00137 char buff[PATH_MAX + 2]; 00138 memset(buff, '\0', sizeof(buff)); 00139 if( ::realpath(path.c_str(), buff) != NULL) 00140 { 00141 real = buff; 00142 } 00143 } 00144 #else 00145 char buff[PATH_MAX + 2]; 00146 memset(buff, '\0', sizeof(buff)); 00147 if( ::realpath(path.c_str(), buff) != NULL) 00148 { 00149 real = buff; 00150 } 00151 #endif 00152 } 00153 return real; 00154 } 00155 00156 zypp::Pathname 00157 MediaHandler::getRealPath(const Pathname &path) 00158 { 00159 return zypp::Pathname(getRealPath(path.asString())); 00160 } 00161 00162 00164 // 00165 // 00166 // METHOD NAME : MediaHandler::removeAttachPoint 00167 // METHOD TYPE : void 00168 // 00169 // DESCRIPTION : 00170 // 00171 void 00172 MediaHandler::removeAttachPoint() 00173 { 00174 if ( _mediaSource ) { 00175 INT << "MediaHandler deleted with media attached." << endl; 00176 return; // no cleanup if media still mounted! 00177 } 00178 00179 DBG << "MediaHandler - checking if to remove attach point" << endl; 00180 if ( _attachPoint.unique() && 00181 _attachPoint->temp && 00182 !_attachPoint->path.empty() && 00183 PathInfo(_attachPoint->path).isDir()) 00184 { 00185 Pathname path(_attachPoint->path); 00186 00187 setAttachPoint("", true); 00188 00189 int res = recursive_rmdir( path ); 00190 if ( res == 0 ) { 00191 MIL << "Deleted default attach point " << path << endl; 00192 } else { 00193 ERR << "Failed to Delete default attach point " << path 00194 << " errno(" << res << ")" << endl; 00195 } 00196 } 00197 else 00198 { 00199 if( !_attachPoint->path.empty() && !_attachPoint->temp) 00200 DBG << "MediaHandler - attachpoint is not temporary" << endl; 00201 } 00202 } 00203 00204 00206 // 00207 // 00208 // METHOD NAME : MediaHandler::attachPoint 00209 // METHOD TYPE : Pathname 00210 // 00211 // DESCRIPTION : 00212 // 00213 Pathname 00214 MediaHandler::attachPoint() const 00215 { 00216 return _attachPoint->path; 00217 } 00218 00219 00221 // 00222 // 00223 // METHOD NAME : MediaHandler::attachPoint 00224 // METHOD TYPE : 00225 // 00226 // DESCRIPTION : 00227 // 00228 void 00229 MediaHandler::setAttachPoint(const Pathname &path, bool temporary) 00230 { 00231 _attachPoint.reset( new AttachPoint(path, temporary)); 00232 } 00233 00234 Pathname 00235 MediaHandler::localRoot() const 00236 { 00237 if( _attachPoint->path.empty()) 00238 return Pathname(); 00239 else 00240 return _attachPoint->path + _relativeRoot; 00241 } 00242 00244 // 00245 // 00246 // METHOD NAME : MediaHandler::attachPoint 00247 // METHOD TYPE : 00248 // 00249 // DESCRIPTION : 00250 // 00251 void 00252 MediaHandler::setAttachPoint(const AttachPointRef &ref) 00253 { 00254 if( ref) 00255 AttachPointRef(ref).swap(_attachPoint); 00256 else 00257 _attachPoint.reset( new AttachPoint()); 00258 } 00259 00261 // 00262 // 00263 // METHOD NAME : MediaHandler::attachPointHint 00264 // METHOD TYPE : void 00265 // 00266 // DESCRIPTION : 00267 // 00268 void 00269 MediaHandler::attachPointHint(const Pathname &path, bool temporary) 00270 { 00271 _AttachPointHint.path = path; 00272 _AttachPointHint.temp = temporary; 00273 } 00274 00276 // 00277 // 00278 // METHOD NAME : MediaHandler::attachPointHint 00279 // METHOD TYPE : AttachPoint 00280 // 00281 // DESCRIPTION : 00282 // 00283 AttachPoint 00284 MediaHandler::attachPointHint() const 00285 { 00286 return _AttachPointHint; 00287 } 00288 00290 // 00291 // 00292 // METHOD NAME : MediaHandler::findAttachedMedia 00293 // METHOD TYPE : AttachedMedia 00294 // 00295 // DESCRIPTION : 00296 // 00297 AttachedMedia 00298 MediaHandler::findAttachedMedia(const MediaSourceRef &media) const 00299 { 00300 return MediaManager().findAttachedMedia(media); 00301 } 00302 00304 // 00305 // 00306 // METHOD NAME : MediaHandler::setAttachPrefix 00307 // METHOD TYPE : void 00308 // 00309 // DESCRIPTION : 00310 // 00311 bool 00312 MediaHandler::setAttachPrefix(const Pathname &attach_prefix) 00313 { 00314 if( attach_prefix.empty()) 00315 { 00316 MIL << "Reseting to built-in attach point prefixes." 00317 << std::endl; 00318 MediaHandler::_attachPrefix = attach_prefix; 00319 return true; 00320 } 00321 else 00322 if( MediaHandler::checkAttachPoint(attach_prefix, false, true)) 00323 { 00324 MIL << "Setting user defined attach point prefix: " 00325 << attach_prefix << std::endl; 00326 MediaHandler::_attachPrefix = attach_prefix; 00327 return true; 00328 } 00329 return false; 00330 } 00331 00333 // 00334 // 00335 // METHOD NAME : MediaHandler::attach 00336 // METHOD TYPE : Pathname 00337 // 00338 // DESCRIPTION : 00339 // 00340 Pathname 00341 MediaHandler::createAttachPoint() const 00342 { 00344 // provide a default (temporary) attachpoint 00346 const char * defmounts[] = { 00347 "/var/adm/mount", filesystem::TmpPath::defaultLocation().c_str(), NULL 00348 }; 00349 00350 Pathname apoint; 00351 Pathname aroot( MediaHandler::_attachPrefix); 00352 00353 if( !aroot.empty()) 00354 { 00355 apoint = createAttachPoint(aroot); 00356 } 00357 for ( const char ** def = defmounts; *def && apoint.empty(); ++def ) { 00358 aroot = *def; 00359 if( aroot.empty()) 00360 continue; 00361 00362 apoint = createAttachPoint(aroot); 00363 } 00364 00365 if ( aroot.empty() ) { 00366 ERR << "Create attach point: Can't find a writable directory to create an attach point" << std::endl; 00367 return aroot; 00368 } 00369 00370 if ( !apoint.empty() ) { 00371 MIL << "Created default attach point " << apoint << std::endl; 00372 } 00373 return apoint; 00374 } 00375 00376 Pathname 00377 MediaHandler::createAttachPoint(const Pathname &attach_root) const 00378 { 00379 Pathname apoint; 00380 00381 if( attach_root.empty() || !attach_root.absolute()) { 00382 ERR << "Create attach point: invalid attach root: '" 00383 << attach_root << "'" << std::endl; 00384 return apoint; 00385 } 00386 00387 PathInfo adir( attach_root ); 00388 if( !adir.isDir() || (getuid() != 0 && !adir.userMayRWX())) { 00389 DBG << "Create attach point: attach root is not a writable directory: '" 00390 << attach_root << "'" << std::endl; 00391 return apoint; 00392 } 00393 00394 static bool cleanup_once( true ); 00395 if ( cleanup_once ) 00396 { 00397 cleanup_once = false; 00398 DBG << "Look for orphaned attach points in " << adir << std::endl; 00399 std::list<std::string> entries; 00400 filesystem::readdir( entries, attach_root, false ); 00401 for_each_( it, entries ) 00402 { 00403 const std::string & entry( *it ); 00404 00405 if ( ! str::hasPrefix( entry, "AP_0x" ) ) 00406 continue; 00407 PathInfo sdir( attach_root + entry ); 00408 if ( sdir.isDir() 00409 && sdir.dev() == adir.dev() 00410 && ( Date::now()-sdir.mtime() > Date::month ) ) 00411 { 00412 DBG << "Remove orphaned attach point " << sdir << std::endl; 00413 filesystem::recursive_rmdir( sdir.path() ); 00414 } 00415 } 00416 } 00417 00418 filesystem::TmpDir tmpdir( attach_root, "AP_0x" ); 00419 if ( tmpdir ) 00420 { 00421 apoint = getRealPath( tmpdir.path().asString() ); 00422 if ( ! apoint.empty() ) 00423 { 00424 tmpdir.autoCleanup( false ); // Take responsibility for cleanup. 00425 } 00426 else 00427 { 00428 ERR << "Unable to resolve real path for attach point " << tmpdir << std::endl; 00429 } 00430 } 00431 else 00432 { 00433 ERR << "Unable to create attach point below " << attach_root << std::endl; 00434 } 00435 return apoint; 00436 } 00437 00439 // 00440 // 00441 // METHOD NAME : MediaHandler::isUseableAttachPoint 00442 // METHOD TYPE : bool 00443 // 00444 // DESCRIPTION : 00445 // 00446 bool 00447 MediaHandler::isUseableAttachPoint(const Pathname &path, bool mtab) const 00448 { 00449 MediaManager manager; 00450 return manager.isUseableAttachPoint(path, mtab); 00451 } 00452 00453 00455 // 00456 // 00457 // METHOD NAME : MediaHandler::setMediaSource 00458 // METHOD TYPE : void 00459 // 00460 // DESCRIPTION : 00461 // 00462 void 00463 MediaHandler::setMediaSource(const MediaSourceRef &ref) 00464 { 00465 _mediaSource.reset(); 00466 if( ref && !ref->type.empty() && !ref->name.empty()) 00467 _mediaSource = ref; 00468 } 00469 00471 // 00472 // 00473 // METHOD NAME : MediaHandler::attachedMedia 00474 // METHOD TYPE : AttachedMedia 00475 // 00476 // DESCRIPTION : 00477 // 00478 AttachedMedia 00479 MediaHandler::attachedMedia() const 00480 { 00481 if ( _mediaSource && _attachPoint) 00482 return AttachedMedia(_mediaSource, _attachPoint); 00483 else 00484 return AttachedMedia(); 00485 } 00486 00488 // 00489 // 00490 // METHOD NAME : MediaHandler::isSharedMedia 00491 // METHOD TYPE : bool 00492 // 00493 // DESCRIPTION : 00494 // 00495 bool 00496 MediaHandler::isSharedMedia() const 00497 { 00498 return !_mediaSource.unique(); 00499 } 00500 00502 // 00503 // 00504 // METHOD NAME : MediaHandler::checkAttached 00505 // METHOD TYPE : bool 00506 // 00507 // DESCRIPTION : 00508 // 00509 bool 00510 MediaHandler::checkAttached(bool matchMountFs) const 00511 { 00512 bool _isAttached = false; 00513 00514 AttachedMedia ref( attachedMedia()); 00515 if( ref.mediaSource ) 00516 { 00517 time_t old_mtime = _attach_mtime; 00518 _attach_mtime = MediaManager::getMountTableMTime(); 00519 if( !(old_mtime <= 0 || _attach_mtime != old_mtime) ) 00520 { 00521 // OK, skip the check (we've seen it at least once) 00522 _isAttached = true; 00523 } 00524 else 00525 { 00526 if( old_mtime > 0) 00527 DBG << "Mount table changed - rereading it" << std::endl; 00528 else 00529 DBG << "Forced check of the mount table" << std::endl; 00530 00531 MountEntries entries( MediaManager::getMountEntries()); 00532 for_( e, entries.begin(), entries.end() ) 00533 { 00534 bool is_device = false; 00535 PathInfo dev_info; 00536 00537 if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) && 00538 dev_info(e->src) && dev_info.isBlk()) 00539 { 00540 is_device = true; 00541 } 00542 00543 if( is_device && (ref.mediaSource->maj_nr && 00544 ref.mediaSource->bdir.empty())) 00545 { 00546 std::string mtype(matchMountFs ? e->type : ref.mediaSource->type); 00547 MediaSource media(mtype, e->src, dev_info.major(), dev_info.minor()); 00548 00549 if( ref.mediaSource->equals( media) && 00550 ref.attachPoint->path == Pathname(e->dir)) 00551 { 00552 DBG << "Found media device " 00553 << ref.mediaSource->asString() 00554 << " in the mount table as " << e->src << std::endl; 00555 _isAttached = true; 00556 break; 00557 } 00558 // differs 00559 } 00560 else 00561 if(!is_device && (!ref.mediaSource->maj_nr || 00562 !ref.mediaSource->bdir.empty())) 00563 { 00564 if( ref.mediaSource->bdir.empty()) 00565 { 00566 // bnc#710269: Type nfs may appear as nfs4 in in the mount table 00567 // and maybe vice versa. Similar cifs/smb. Need to unify these types: 00568 if ( matchMountFs && e->type != ref.mediaSource->type ) 00569 { 00570 if ( str::hasPrefix( e->type, "nfs" ) && str::hasPrefix( ref.mediaSource->type, "nfs" ) ) 00571 matchMountFs = false; 00572 else if ( ( e->type == "cifs" || e->type == "smb" ) && ( ref.mediaSource->type == "cifs" || ref.mediaSource->type == "smb" ) ) 00573 matchMountFs = false; 00574 } 00575 std::string mtype(matchMountFs ? e->type : ref.mediaSource->type); 00576 MediaSource media(mtype, e->src); 00577 00578 if( ref.mediaSource->equals( media) && 00579 ref.attachPoint->path == Pathname(e->dir)) 00580 { 00581 DBG << "Found media name " 00582 << ref.mediaSource->asString() 00583 << " in the mount table as " << e->src << std::endl; 00584 _isAttached = true; 00585 break; 00586 } 00587 } 00588 else 00589 { 00590 if(ref.mediaSource->bdir == e->src && 00591 ref.attachPoint->path == Pathname(e->dir)) 00592 { 00593 DBG << "Found bound media " 00594 << ref.mediaSource->asString() 00595 << " in the mount table as " << e->src << std::endl; 00596 _isAttached = true; 00597 break; 00598 } 00599 } 00600 // differs 00601 } 00602 } 00603 00604 if( !_isAttached) 00605 { 00606 MIL << "Looking for " << ref << endl; 00607 if( entries.empty() ) 00608 { 00609 ERR << "Unable to find any entry in the /etc/mtab file" << std::endl; 00610 } 00611 else 00612 { 00613 dumpRange( DBG << "MountEntries: ", entries.begin(), entries.end() ) << endl; 00614 } 00615 if( old_mtime > 0 ) 00616 { 00617 ERR << "Attached media not in mount table any more - forcing reset!" 00618 << std::endl; 00619 00620 _mediaSource.reset(); 00621 } 00622 else 00623 { 00624 WAR << "Attached media not in mount table ..." << std::endl; 00625 } 00626 00627 // reset the mtime and force a new check to make sure, 00628 // that we've found the media at least once in the mtab. 00629 _attach_mtime = 0; 00630 } 00631 } 00632 } 00633 return _isAttached; 00634 } 00635 00637 // 00638 // 00639 // METHOD NAME : MediaHandler::attach 00640 // METHOD TYPE : PMError 00641 // 00642 // DESCRIPTION : 00643 // 00644 void MediaHandler::attach( bool next ) 00645 { 00646 if ( isAttached() ) 00647 return; 00648 00649 // reset it in case of overloaded isAttached() 00650 // that checks the media against /etc/mtab ... 00651 setMediaSource(MediaSourceRef()); 00652 00653 AttachPoint ap( attachPointHint()); 00654 setAttachPoint(ap.path, ap.temp); 00655 00656 try 00657 { 00658 attachTo( next ); // pass to concrete handler 00659 } 00660 catch(const MediaException &e) 00661 { 00662 removeAttachPoint(); 00663 ZYPP_RETHROW(e); 00664 } 00665 MIL << "Attached: " << *this << endl; 00666 } 00667 00668 00670 // 00671 // 00672 // METHOD NAME : MediaHandler::localPath 00673 // METHOD TYPE : Pathname 00674 // 00675 Pathname MediaHandler::localPath( const Pathname & pathname ) const 00676 { 00677 Pathname _localRoot( localRoot()); 00678 if ( _localRoot.empty() ) 00679 return _localRoot; 00680 00681 // we must check maximum file name length 00682 // this is important for fetching the suseservers, the 00683 // url with all parameters can get too long (bug #42021) 00684 00685 return _localRoot + pathname.absolutename(); 00686 } 00687 00688 00689 00690 00691 00693 // 00694 // 00695 // METHOD NAME : MediaHandler::disconnect 00696 // METHOD TYPE : PMError 00697 // 00698 void MediaHandler::disconnect() 00699 { 00700 if ( !isAttached() ) 00701 return; 00702 00703 disconnectFrom(); // pass to concrete handler 00704 MIL << "Disconnected: " << *this << endl; 00705 } 00706 00708 // 00709 // 00710 // METHOD NAME : MediaHandler::release 00711 // METHOD TYPE : PMError 00712 // 00713 // DESCRIPTION : 00714 // 00715 void MediaHandler::release( const std::string & ejectDev ) 00716 { 00717 if ( !isAttached() ) { 00718 DBG << "Request to release media - not attached; eject '" << ejectDev << "'" 00719 << std::endl; 00720 if ( !ejectDev.empty() ) 00721 forceEject(ejectDev); 00722 return; 00723 } 00724 00725 DBG << "Request to release attached media " 00726 << _mediaSource->asString() 00727 << ", use count=" << _mediaSource.use_count() 00728 << std::endl; 00729 00730 if( _mediaSource.unique()) 00731 { 00732 DBG << "Releasing media " << _mediaSource->asString() << std::endl; 00733 try { 00734 releaseFrom( ejectDev ); // pass to concrete handler 00735 } 00736 catch(const MediaNotEjectedException &e) 00737 { 00738 // not ejected because the media 00739 // is mounted by somebody else 00740 // (if our attach point is busy, 00741 // we get an umount exception) 00742 _mediaSource.reset(NULL); 00743 removeAttachPoint(); 00744 // OK, retrow now 00745 ZYPP_RETHROW(e); 00746 } 00747 _mediaSource.reset(NULL); 00748 removeAttachPoint(); 00749 } 00750 else if( !ejectDev.empty() ) { 00751 // 00752 // Can't eject a shared media 00753 // 00754 //ZYPP_THROW(MediaIsSharedException(_mediaSource->asString())); 00755 00756 MediaSourceRef media( new MediaSource(*_mediaSource)); 00757 _mediaSource.reset(NULL); 00758 00759 MediaManager manager; 00760 manager.forceReleaseShared(media); 00761 00762 setMediaSource(media); 00763 DBG << "Releasing media (forced) " << _mediaSource->asString() << std::endl; 00764 try { 00765 releaseFrom( ejectDev ); // pass to concrete handler 00766 } 00767 catch(const MediaNotEjectedException &e) 00768 { 00769 // not ejected because the media 00770 // is mounted by somebody else 00771 // (if our attach point is busy, 00772 // we get an umount exception) 00773 _mediaSource.reset(NULL); 00774 removeAttachPoint(); 00775 // OK, retrow now 00776 ZYPP_RETHROW(e); 00777 } 00778 _mediaSource.reset(NULL); 00779 removeAttachPoint(); 00780 } 00781 else { 00782 DBG << "Releasing shared media reference only" << std::endl; 00783 _mediaSource.reset(NULL); 00784 setAttachPoint("", true); 00785 } 00786 MIL << "Released: " << *this << endl; 00787 } 00788 00789 void MediaHandler::forceRelaseAllMedia(bool matchMountFs) 00790 { 00791 forceRelaseAllMedia( attachedMedia().mediaSource, matchMountFs); 00792 } 00793 00794 void MediaHandler::forceRelaseAllMedia(const MediaSourceRef &ref, 00795 bool matchMountFs) 00796 { 00797 if( !ref) 00798 return; 00799 00800 MountEntries entries( MediaManager::getMountEntries()); 00801 MountEntries::const_iterator e; 00802 for( e = entries.begin(); e != entries.end(); ++e) 00803 { 00804 bool is_device = false; 00805 PathInfo dev_info; 00806 00807 if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) && 00808 dev_info(e->src) && dev_info.isBlk()) 00809 { 00810 is_device = true; 00811 } 00812 00813 if( is_device && ref->maj_nr) 00814 { 00815 std::string mtype(matchMountFs ? e->type : ref->type); 00816 MediaSource media(mtype, e->src, dev_info.major(), dev_info.minor()); 00817 00818 if( ref->equals( media) && e->type != "subfs") 00819 { 00820 DBG << "Forcing release of media device " 00821 << ref->asString() 00822 << " in the mount table as " 00823 << e->src << std::endl; 00824 try { 00825 Mount mount; 00826 mount.umount(e->dir); 00827 } 00828 catch (const Exception &e) 00829 { 00830 ZYPP_CAUGHT(e); 00831 } 00832 } 00833 } 00834 else 00835 if(!is_device && !ref->maj_nr) 00836 { 00837 std::string mtype(matchMountFs ? e->type : ref->type); 00838 MediaSource media(mtype, e->src); 00839 if( ref->equals( media)) 00840 { 00841 DBG << "Forcing release of media name " 00842 << ref->asString() 00843 << " in the mount table as " 00844 << e->src << std::endl; 00845 try { 00846 Mount mount; 00847 mount.umount(e->dir); 00848 } 00849 catch (const Exception &e) 00850 { 00851 ZYPP_CAUGHT(e); 00852 } 00853 } 00854 } 00855 } 00856 } 00857 00858 bool 00859 MediaHandler::checkAttachPoint(const Pathname &apoint) const 00860 { 00861 return MediaHandler::checkAttachPoint( apoint, true, false); 00862 } 00863 00864 // STATIC 00865 bool 00866 MediaHandler::checkAttachPoint(const Pathname &apoint, 00867 bool emptydir, 00868 bool writeable) 00869 { 00870 if( apoint.empty() || !apoint.absolute()) 00871 { 00872 ERR << "Attach point '" << apoint << "' is not absolute" 00873 << std::endl; 00874 return false; 00875 } 00876 if( apoint == "/") 00877 { 00878 ERR << "Attach point '" << apoint << "' is not allowed" 00879 << std::endl; 00880 return false; 00881 } 00882 00883 PathInfo ainfo(apoint); 00884 if( !ainfo.isDir()) 00885 { 00886 ERR << "Attach point '" << apoint << "' is not a directory" 00887 << std::endl; 00888 return false; 00889 } 00890 00891 if( emptydir) 00892 { 00893 if( 0 != zypp::filesystem::is_empty_dir(apoint)) 00894 { 00895 ERR << "Attach point '" << apoint << "' is not a empty directory" 00896 << std::endl; 00897 return false; 00898 } 00899 } 00900 00901 if( writeable) 00902 { 00903 Pathname apath(apoint + "XXXXXX"); 00904 char *atemp = ::strdup( apath.asString().c_str()); 00905 char *atest = NULL; 00906 if( !ainfo.userMayRWX() || atemp == NULL || 00907 (atest=::mkdtemp(atemp)) == NULL) 00908 { 00909 if( atemp != NULL) 00910 ::free(atemp); 00911 00912 ERR << "Attach point '" << ainfo.path() 00913 << "' is not a writeable directory" << std::endl; 00914 return false; 00915 } 00916 else if( atest != NULL) 00917 ::rmdir(atest); 00918 00919 if( atemp != NULL) 00920 ::free(atemp); 00921 } 00922 return true; 00923 } 00924 00926 // 00927 // METHOD NAME : MediaHandler::dependsOnParent 00928 // METHOD TYPE : bool 00929 // 00930 // DESCRIPTION : 00931 // 00932 bool 00933 MediaHandler::dependsOnParent() 00934 { 00935 return _parentId != 0; 00936 } 00937 00938 bool 00939 MediaHandler::dependsOnParent(MediaAccessId parentId, bool exactIdMatch) 00940 { 00941 if( _parentId != 0) 00942 { 00943 if(parentId == _parentId) 00944 return true; 00945 00946 if( !exactIdMatch) 00947 { 00948 MediaManager mm; 00949 AttachedMedia am1 = mm.getAttachedMedia(_parentId); 00950 AttachedMedia am2 = mm.getAttachedMedia(parentId); 00951 if( am1.mediaSource && am2.mediaSource) 00952 { 00953 return am1.mediaSource->equals( *(am2.mediaSource)); 00954 } 00955 } 00956 } 00957 return false; 00958 } 00959 00961 // 00962 // 00963 // METHOD NAME : MediaHandler::provideFile 00964 // METHOD TYPE : PMError 00965 // 00966 // DESCRIPTION : 00967 // 00968 void MediaHandler::provideFileCopy( Pathname srcFilename, 00969 Pathname targetFilename ) const 00970 { 00971 if ( !isAttached() ) { 00972 INT << "Media not_attached on provideFileCopy(" << srcFilename 00973 << "," << targetFilename << ")" << endl; 00974 ZYPP_THROW(MediaNotAttachedException(url())); 00975 } 00976 00977 getFileCopy( srcFilename, targetFilename ); // pass to concrete handler 00978 DBG << "provideFileCopy(" << srcFilename << "," << targetFilename << ")" << endl; 00979 } 00980 00981 void MediaHandler::provideFile( Pathname filename ) const 00982 { 00983 if ( !isAttached() ) { 00984 INT << "Error: Not attached on provideFile(" << filename << ")" << endl; 00985 ZYPP_THROW(MediaNotAttachedException(url())); 00986 } 00987 00988 getFile( filename ); // pass to concrete handler 00989 DBG << "provideFile(" << filename << ")" << endl; 00990 } 00991 00992 00994 // 00995 // 00996 // METHOD NAME : MediaHandler::provideDir 00997 // METHOD TYPE : PMError 00998 // 00999 // DESCRIPTION : 01000 // 01001 void MediaHandler::provideDir( Pathname dirname ) const 01002 { 01003 if ( !isAttached() ) { 01004 INT << "Error: Not attached on provideDir(" << dirname << ")" << endl; 01005 ZYPP_THROW(MediaNotAttachedException(url())); 01006 } 01007 01008 getDir( dirname, /*recursive*/false ); // pass to concrete handler 01009 MIL << "provideDir(" << dirname << ")" << endl; 01010 } 01011 01013 // 01014 // 01015 // METHOD NAME : MediaHandler::provideDirTree 01016 // METHOD TYPE : PMError 01017 // 01018 // DESCRIPTION : 01019 // 01020 void MediaHandler::provideDirTree( Pathname dirname ) const 01021 { 01022 if ( !isAttached() ) { 01023 INT << "Error Not attached on provideDirTree(" << dirname << ")" << endl; 01024 ZYPP_THROW(MediaNotAttachedException(url())); 01025 } 01026 01027 getDir( dirname, /*recursive*/true ); // pass to concrete handler 01028 MIL << "provideDirTree(" << dirname << ")" << endl; 01029 } 01030 01032 // 01033 // 01034 // METHOD NAME : MediaHandler::releasePath 01035 // METHOD TYPE : PMError 01036 // 01037 // DESCRIPTION : 01038 // 01039 void MediaHandler::releasePath( Pathname pathname ) const 01040 { 01041 if ( ! _does_download || _attachPoint->empty() ) 01042 return; 01043 01044 PathInfo info( localPath( pathname ) ); 01045 01046 if ( info.isFile() ) { 01047 unlink( info.path() ); 01048 } else if ( info.isDir() ) { 01049 if ( info.path() != localRoot() ) { 01050 recursive_rmdir( info.path() ); 01051 } else { 01052 clean_dir( info.path() ); 01053 } 01054 } 01055 } 01056 01058 // 01059 // 01060 // METHOD NAME : MediaHandler::dirInfo 01061 // METHOD TYPE : PMError 01062 // 01063 // DESCRIPTION : 01064 // 01065 void MediaHandler::dirInfo( std::list<std::string> & retlist, 01066 const Pathname & dirname, bool dots ) const 01067 { 01068 retlist.clear(); 01069 01070 if ( !isAttached() ) { 01071 INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl; 01072 ZYPP_THROW(MediaNotAttachedException(url())); 01073 } 01074 01075 getDirInfo( retlist, dirname, dots ); // pass to concrete handler 01076 MIL << "dirInfo(" << dirname << ")" << endl; 01077 } 01078 01080 // 01081 // 01082 // METHOD NAME : MediaHandler::dirInfo 01083 // METHOD TYPE : PMError 01084 // 01085 // DESCRIPTION : 01086 // 01087 void MediaHandler::dirInfo( filesystem::DirContent & retlist, 01088 const Pathname & dirname, bool dots ) const 01089 { 01090 retlist.clear(); 01091 01092 if ( !isAttached() ) { 01093 INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl; 01094 ZYPP_THROW(MediaNotAttachedException(url())); 01095 } 01096 01097 getDirInfo( retlist, dirname, dots ); // pass to concrete handler 01098 MIL << "dirInfo(" << dirname << ")" << endl; 01099 } 01100 01102 // 01103 // 01104 // METHOD NAME : MediaHandler::doesFileExist 01105 // METHOD TYPE : PMError 01106 // 01107 // DESCRIPTION : 01108 // 01109 bool MediaHandler::doesFileExist( const Pathname & filename ) const 01110 { 01111 // TODO do some logging 01112 if ( !isAttached() ) { 01113 INT << "Error Not attached on doesFileExist(" << filename << ")" << endl; 01114 ZYPP_THROW(MediaNotAttachedException(url())); 01115 } 01116 return getDoesFileExist( filename ); 01117 MIL << "doesFileExist(" << filename << ")" << endl; 01118 } 01119 01121 // 01122 // 01123 // METHOD NAME : MediaHandler::getDirectoryYast 01124 // METHOD TYPE : PMError 01125 // 01126 void MediaHandler::getDirectoryYast( std::list<std::string> & retlist, 01127 const Pathname & dirname, bool dots ) const 01128 { 01129 retlist.clear(); 01130 01131 filesystem::DirContent content; 01132 getDirectoryYast( content, dirname, dots ); 01133 01134 // convert to std::list<std::string> 01135 for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) { 01136 retlist.push_back( it->name ); 01137 } 01138 } 01139 01141 // 01142 // 01143 // METHOD NAME : MediaHandler::getDirectoryYast 01144 // METHOD TYPE : PMError 01145 // 01146 void MediaHandler::getDirectoryYast( filesystem::DirContent & retlist, 01147 const Pathname & dirname, bool dots ) const 01148 { 01149 retlist.clear(); 01150 01151 // look for directory.yast 01152 Pathname dirFile = dirname + "directory.yast"; 01153 getFile( dirFile ); 01154 DBG << "provideFile(" << dirFile << "): " << "OK" << endl; 01155 01156 // using directory.yast 01157 ifstream dir( localPath( dirFile ).asString().c_str() ); 01158 if ( dir.fail() ) { 01159 ERR << "Unable to load '" << localPath( dirFile ) << "'" << endl; 01160 ZYPP_THROW(MediaSystemException(url(), 01161 "Unable to load '" + localPath( dirFile ).asString() + "'")); 01162 } 01163 01164 string line; 01165 while( getline( dir, line ) ) { 01166 if ( line.empty() ) continue; 01167 if ( line == "directory.yast" ) continue; 01168 01169 // Newer directory.yast append '/' to directory names 01170 // Remaining entries are unspecified, although most probabely files. 01171 filesystem::FileType type = filesystem::FT_NOT_AVAIL; 01172 if ( *line.rbegin() == '/' ) { 01173 line.erase( line.end()-1 ); 01174 type = filesystem::FT_DIR; 01175 } 01176 01177 if ( dots ) { 01178 if ( line == "." || line == ".." ) continue; 01179 } else { 01180 if ( *line.begin() == '.' ) continue; 01181 } 01182 01183 retlist.push_back( filesystem::DirEntry( line, type ) ); 01184 } 01185 } 01186 01187 /****************************************************************** 01188 ** 01189 ** 01190 ** FUNCTION NAME : operator<< 01191 ** FUNCTION TYPE : ostream & 01192 */ 01193 ostream & operator<<( ostream & str, const MediaHandler & obj ) 01194 { 01195 str << obj.url() << ( obj.isAttached() ? "" : " not" ) 01196 << " attached; localRoot \"" << obj.localRoot() << "\""; 01197 return str; 01198 } 01199 01201 // 01202 // 01203 // METHOD NAME : MediaHandler::getFile 01204 // METHOD TYPE : PMError 01205 // 01206 // DESCRIPTION : Asserted that media is attached. 01207 // Default implementation of pure virtual. 01208 // 01209 void MediaHandler::getFile( const Pathname & filename ) const 01210 { 01211 PathInfo info( localPath( filename ) ); 01212 if( info.isFile() ) { 01213 return; 01214 } 01215 01216 if (info.isExist()) 01217 ZYPP_THROW(MediaNotAFileException(url(), localPath(filename))); 01218 else 01219 ZYPP_THROW(MediaFileNotFoundException(url(), filename)); 01220 } 01221 01222 01223 void MediaHandler::getFileCopy ( const Pathname & srcFilename, const Pathname & targetFilename ) const 01224 { 01225 getFile(srcFilename); 01226 01227 if ( copy( localPath( srcFilename ), targetFilename ) != 0 ) { 01228 ZYPP_THROW(MediaWriteException(targetFilename)); 01229 } 01230 } 01231 01232 01233 01235 // 01236 // 01237 // METHOD NAME : MediaHandler::getDir 01238 // METHOD TYPE : PMError 01239 // 01240 // DESCRIPTION : Asserted that media is attached. 01241 // Default implementation of pure virtual. 01242 // 01243 void MediaHandler::getDir( const Pathname & dirname, bool recurse_r ) const 01244 { 01245 PathInfo info( localPath( dirname ) ); 01246 if( info.isDir() ) { 01247 return; 01248 } 01249 01250 if (info.isExist()) 01251 ZYPP_THROW(MediaNotADirException(url(), localPath(dirname))); 01252 else 01253 ZYPP_THROW(MediaFileNotFoundException(url(), dirname)); 01254 } 01255 01257 // 01258 // 01259 // METHOD NAME : MediaHandler::getDirInfo 01260 // METHOD TYPE : PMError 01261 // 01262 // DESCRIPTION : Asserted that media is attached and retlist is empty. 01263 // Default implementation of pure virtual. 01264 // 01265 void MediaHandler::getDirInfo( std::list<std::string> & retlist, 01266 const Pathname & dirname, bool dots ) const 01267 { 01268 PathInfo info( localPath( dirname ) ); 01269 if( ! info.isDir() ) { 01270 ZYPP_THROW(MediaNotADirException(url(), localPath(dirname))); 01271 } 01272 01273 #if NONREMOTE_DIRECTORY_YAST 01274 // use directory.yast if available 01275 try { 01276 getDirectoryYast( retlist, dirname, dots ); 01277 } 01278 catch (const MediaException & excpt_r) 01279 { 01280 #endif 01281 01282 // readdir 01283 int res = readdir( retlist, info.path(), dots ); 01284 if ( res ) 01285 { 01286 MediaSystemException nexcpt(url(), "readdir failed"); 01287 #if NONREMOTE_DIRECTORY_YAST 01288 nexcpt.remember(excpt_r); 01289 #endif 01290 ZYPP_THROW(nexcpt); 01291 } 01292 01293 #if NONREMOTE_DIRECTORY_YAST 01294 } 01295 #endif 01296 01297 return; 01298 } 01299 01301 // 01302 // 01303 // METHOD NAME : MediaHandler::getDirInfo 01304 // METHOD TYPE : PMError 01305 // 01306 // DESCRIPTION : Asserted that media is attached and retlist is empty. 01307 // Default implementation of pure virtual. 01308 // 01309 void MediaHandler::getDirInfo( filesystem::DirContent & retlist, 01310 const Pathname & dirname, bool dots ) const 01311 { 01312 PathInfo info( localPath( dirname ) ); 01313 if( ! info.isDir() ) { 01314 ZYPP_THROW(MediaNotADirException(url(), localPath(dirname))); 01315 } 01316 01317 #if NONREMOTE_DIRECTORY_YAST 01318 // use directory.yast if available 01319 try { 01320 getDirectoryYast( retlist, dirname, dots ); 01321 } 01322 catch (const MediaException & excpt_r) 01323 { 01324 #endif 01325 01326 // readdir 01327 int res = readdir( retlist, info.path(), dots ); 01328 if ( res ) 01329 { 01330 MediaSystemException nexcpt(url(), "readdir failed"); 01331 #if NONREMOTE_DIRECTORY_YAST 01332 nexcpt.remember(excpt_r); 01333 #endif 01334 ZYPP_THROW(nexcpt); 01335 } 01336 #if NONREMOTE_DIRECTORY_YAST 01337 } 01338 #endif 01339 } 01340 01342 // 01343 // 01344 // METHOD NAME : MediaHandler::getDoesFileExist 01345 // METHOD TYPE : PMError 01346 // 01347 // DESCRIPTION : Asserted that file is not a directory 01348 // Default implementation of pure virtual. 01349 // 01350 bool MediaHandler::getDoesFileExist( const Pathname & filename ) const 01351 { 01352 PathInfo info( localPath( filename ) ); 01353 if( info.isDir() ) { 01354 ZYPP_THROW(MediaNotAFileException(url(), localPath(filename))); 01355 } 01356 return info.isExist(); 01357 } 01358 01359 bool MediaHandler::hasMoreDevices() 01360 { 01361 return false; 01362 } 01363 01364 void MediaHandler::getDetectedDevices(std::vector<std::string> & devices, 01365 unsigned int & index) const 01366 { 01367 // clear the vector by default 01368 if (!devices.empty()) 01369 devices.clear(); 01370 index = 0; 01371 01372 DBG << "No devices for this medium" << endl; 01373 } 01374 01375 void MediaHandler::setDeltafile( const Pathname & filename ) const 01376 { 01377 _deltafile = filename; 01378 } 01379 01380 Pathname MediaHandler::deltafile() const { 01381 return _deltafile; 01382 } 01383 01384 } // namespace media 01385 } // namespace zypp 01386 // vim: set ts=8 sts=2 sw=2 ai noet: