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