|
libzypp
9.1.2
|
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 std::string mtype(matchMountFs ? e->type : ref.mediaSource->type); 00556 if( ref.mediaSource->bdir.empty()) 00557 { 00558 MediaSource media(mtype, e->src); 00559 00560 if( ref.mediaSource->equals( media) && 00561 ref.attachPoint->path == Pathname(e->dir)) 00562 { 00563 DBG << "Found media name " 00564 << ref.mediaSource->asString() 00565 << " in the mount table as " << e->src << std::endl; 00566 _isAttached = true; 00567 break; 00568 } 00569 } 00570 else 00571 { 00572 if(ref.mediaSource->bdir == e->src && 00573 ref.attachPoint->path == Pathname(e->dir)) 00574 { 00575 DBG << "Found bound media " 00576 << ref.mediaSource->asString() 00577 << " in the mount table as " << e->src << std::endl; 00578 _isAttached = true; 00579 break; 00580 } 00581 } 00582 // differs 00583 } 00584 } 00585 00586 if( !_isAttached) 00587 { 00588 MIL << "Looking for " << ref << endl; 00589 if( entries.empty() ) 00590 { 00591 ERR << "Unable to find any entry in the /etc/mtab file" << std::endl; 00592 } 00593 else 00594 { 00595 dumpRange( DBG << "MountEntries: ", entries.begin(), entries.end() ) << endl; 00596 } 00597 if( old_mtime > 0 ) 00598 { 00599 ERR << "Attached media not in mount table any more - forcing reset!" 00600 << std::endl; 00601 00602 _mediaSource.reset(); 00603 } 00604 else 00605 { 00606 WAR << "Attached media not in mount table ..." << std::endl; 00607 } 00608 00609 // reset the mtime and force a new check to make sure, 00610 // that we've found the media at least once in the mtab. 00611 _attach_mtime = 0; 00612 } 00613 } 00614 } 00615 return _isAttached; 00616 } 00617 00619 // 00620 // 00621 // METHOD NAME : MediaHandler::attach 00622 // METHOD TYPE : PMError 00623 // 00624 // DESCRIPTION : 00625 // 00626 void MediaHandler::attach( bool next ) 00627 { 00628 if ( isAttached() ) 00629 return; 00630 00631 // reset it in case of overloaded isAttached() 00632 // that checks the media against /etc/mtab ... 00633 setMediaSource(MediaSourceRef()); 00634 00635 AttachPoint ap( attachPointHint()); 00636 setAttachPoint(ap.path, ap.temp); 00637 00638 try 00639 { 00640 attachTo( next ); // pass to concrete handler 00641 } 00642 catch(const MediaException &e) 00643 { 00644 removeAttachPoint(); 00645 ZYPP_RETHROW(e); 00646 } 00647 MIL << "Attached: " << *this << endl; 00648 } 00649 00650 00652 // 00653 // 00654 // METHOD NAME : MediaHandler::localPath 00655 // METHOD TYPE : Pathname 00656 // 00657 Pathname MediaHandler::localPath( const Pathname & pathname ) const 00658 { 00659 Pathname _localRoot( localRoot()); 00660 if ( _localRoot.empty() ) 00661 return _localRoot; 00662 00663 // we must check maximum file name length 00664 // this is important for fetching the suseservers, the 00665 // url with all parameters can get too long (bug #42021) 00666 00667 return _localRoot + pathname.absolutename(); 00668 } 00669 00670 00671 00672 00673 00675 // 00676 // 00677 // METHOD NAME : MediaHandler::disconnect 00678 // METHOD TYPE : PMError 00679 // 00680 void MediaHandler::disconnect() 00681 { 00682 if ( !isAttached() ) 00683 return; 00684 00685 disconnectFrom(); // pass to concrete handler 00686 MIL << "Disconnected: " << *this << endl; 00687 } 00688 00690 // 00691 // 00692 // METHOD NAME : MediaHandler::release 00693 // METHOD TYPE : PMError 00694 // 00695 // DESCRIPTION : 00696 // 00697 void MediaHandler::release( const std::string & ejectDev ) 00698 { 00699 if ( !isAttached() ) { 00700 DBG << "Request to release media - not attached; eject '" << ejectDev << "'" 00701 << std::endl; 00702 if ( !ejectDev.empty() ) 00703 forceEject(ejectDev); 00704 return; 00705 } 00706 00707 DBG << "Request to release attached media " 00708 << _mediaSource->asString() 00709 << ", use count=" << _mediaSource.use_count() 00710 << std::endl; 00711 00712 if( _mediaSource.unique()) 00713 { 00714 DBG << "Releasing media " << _mediaSource->asString() << std::endl; 00715 try { 00716 releaseFrom( ejectDev ); // pass to concrete handler 00717 } 00718 catch(const MediaNotEjectedException &e) 00719 { 00720 // not ejected because the media 00721 // is mounted by somebody else 00722 // (if our attach point is busy, 00723 // we get an umount exception) 00724 _mediaSource.reset(NULL); 00725 removeAttachPoint(); 00726 // OK, retrow now 00727 ZYPP_RETHROW(e); 00728 } 00729 _mediaSource.reset(NULL); 00730 removeAttachPoint(); 00731 } 00732 else if( !ejectDev.empty() ) { 00733 // 00734 // Can't eject a shared media 00735 // 00736 //ZYPP_THROW(MediaIsSharedException(_mediaSource->asString())); 00737 00738 MediaSourceRef media( new MediaSource(*_mediaSource)); 00739 _mediaSource.reset(NULL); 00740 00741 MediaManager manager; 00742 manager.forceReleaseShared(media); 00743 00744 setMediaSource(media); 00745 DBG << "Releasing media (forced) " << _mediaSource->asString() << std::endl; 00746 try { 00747 releaseFrom( ejectDev ); // pass to concrete handler 00748 } 00749 catch(const MediaNotEjectedException &e) 00750 { 00751 // not ejected because the media 00752 // is mounted by somebody else 00753 // (if our attach point is busy, 00754 // we get an umount exception) 00755 _mediaSource.reset(NULL); 00756 removeAttachPoint(); 00757 // OK, retrow now 00758 ZYPP_RETHROW(e); 00759 } 00760 _mediaSource.reset(NULL); 00761 removeAttachPoint(); 00762 } 00763 else { 00764 DBG << "Releasing shared media reference only" << std::endl; 00765 _mediaSource.reset(NULL); 00766 setAttachPoint("", true); 00767 } 00768 MIL << "Released: " << *this << endl; 00769 } 00770 00771 void MediaHandler::forceRelaseAllMedia(bool matchMountFs) 00772 { 00773 forceRelaseAllMedia( attachedMedia().mediaSource, matchMountFs); 00774 } 00775 00776 void MediaHandler::forceRelaseAllMedia(const MediaSourceRef &ref, 00777 bool matchMountFs) 00778 { 00779 if( !ref) 00780 return; 00781 00782 MountEntries entries( MediaManager::getMountEntries()); 00783 MountEntries::const_iterator e; 00784 for( e = entries.begin(); e != entries.end(); ++e) 00785 { 00786 bool is_device = false; 00787 PathInfo dev_info; 00788 00789 if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) && 00790 dev_info(e->src) && dev_info.isBlk()) 00791 { 00792 is_device = true; 00793 } 00794 00795 if( is_device && ref->maj_nr) 00796 { 00797 std::string mtype(matchMountFs ? e->type : ref->type); 00798 MediaSource media(mtype, e->src, dev_info.major(), dev_info.minor()); 00799 00800 if( ref->equals( media) && e->type != "subfs") 00801 { 00802 DBG << "Forcing release of media device " 00803 << ref->asString() 00804 << " in the mount table as " 00805 << e->src << std::endl; 00806 try { 00807 Mount mount; 00808 mount.umount(e->dir); 00809 } 00810 catch (const Exception &e) 00811 { 00812 ZYPP_CAUGHT(e); 00813 } 00814 } 00815 } 00816 else 00817 if(!is_device && !ref->maj_nr) 00818 { 00819 std::string mtype(matchMountFs ? e->type : ref->type); 00820 MediaSource media(mtype, e->src); 00821 if( ref->equals( media)) 00822 { 00823 DBG << "Forcing release of media name " 00824 << ref->asString() 00825 << " in the mount table as " 00826 << e->src << std::endl; 00827 try { 00828 Mount mount; 00829 mount.umount(e->dir); 00830 } 00831 catch (const Exception &e) 00832 { 00833 ZYPP_CAUGHT(e); 00834 } 00835 } 00836 } 00837 } 00838 } 00839 00840 bool 00841 MediaHandler::checkAttachPoint(const Pathname &apoint) const 00842 { 00843 return MediaHandler::checkAttachPoint( apoint, true, false); 00844 } 00845 00846 // STATIC 00847 bool 00848 MediaHandler::checkAttachPoint(const Pathname &apoint, 00849 bool emptydir, 00850 bool writeable) 00851 { 00852 if( apoint.empty() || !apoint.absolute()) 00853 { 00854 ERR << "Attach point '" << apoint << "' is not absolute" 00855 << std::endl; 00856 return false; 00857 } 00858 if( apoint == "/") 00859 { 00860 ERR << "Attach point '" << apoint << "' is not allowed" 00861 << std::endl; 00862 return false; 00863 } 00864 00865 PathInfo ainfo(apoint); 00866 if( !ainfo.isDir()) 00867 { 00868 ERR << "Attach point '" << apoint << "' is not a directory" 00869 << std::endl; 00870 return false; 00871 } 00872 00873 if( emptydir) 00874 { 00875 if( 0 != zypp::filesystem::is_empty_dir(apoint)) 00876 { 00877 ERR << "Attach point '" << apoint << "' is not a empty directory" 00878 << std::endl; 00879 return false; 00880 } 00881 } 00882 00883 if( writeable) 00884 { 00885 Pathname apath(apoint + "XXXXXX"); 00886 char *atemp = ::strdup( apath.asString().c_str()); 00887 char *atest = NULL; 00888 if( !ainfo.userMayRWX() || atemp == NULL || 00889 (atest=::mkdtemp(atemp)) == NULL) 00890 { 00891 if( atemp != NULL) 00892 ::free(atemp); 00893 00894 ERR << "Attach point '" << ainfo.path() 00895 << "' is not a writeable directory" << std::endl; 00896 return false; 00897 } 00898 else if( atest != NULL) 00899 ::rmdir(atest); 00900 00901 if( atemp != NULL) 00902 ::free(atemp); 00903 } 00904 return true; 00905 } 00906 00908 // 00909 // METHOD NAME : MediaHandler::dependsOnParent 00910 // METHOD TYPE : bool 00911 // 00912 // DESCRIPTION : 00913 // 00914 bool 00915 MediaHandler::dependsOnParent() 00916 { 00917 return _parentId != 0; 00918 } 00919 00920 bool 00921 MediaHandler::dependsOnParent(MediaAccessId parentId, bool exactIdMatch) 00922 { 00923 if( _parentId != 0) 00924 { 00925 if(parentId == _parentId) 00926 return true; 00927 00928 if( !exactIdMatch) 00929 { 00930 MediaManager mm; 00931 AttachedMedia am1 = mm.getAttachedMedia(_parentId); 00932 AttachedMedia am2 = mm.getAttachedMedia(parentId); 00933 if( am1.mediaSource && am2.mediaSource) 00934 { 00935 return am1.mediaSource->equals( *(am2.mediaSource)); 00936 } 00937 } 00938 } 00939 return false; 00940 } 00941 00943 // 00944 // 00945 // METHOD NAME : MediaHandler::provideFile 00946 // METHOD TYPE : PMError 00947 // 00948 // DESCRIPTION : 00949 // 00950 void MediaHandler::provideFileCopy( Pathname srcFilename, 00951 Pathname targetFilename ) const 00952 { 00953 if ( !isAttached() ) { 00954 INT << "Media not_attached on provideFileCopy(" << srcFilename 00955 << "," << targetFilename << ")" << endl; 00956 ZYPP_THROW(MediaNotAttachedException(url())); 00957 } 00958 00959 getFileCopy( srcFilename, targetFilename ); // pass to concrete handler 00960 DBG << "provideFileCopy(" << srcFilename << "," << targetFilename << ")" << endl; 00961 } 00962 00963 void MediaHandler::provideFile( Pathname filename ) const 00964 { 00965 if ( !isAttached() ) { 00966 INT << "Error: Not attached on provideFile(" << filename << ")" << endl; 00967 ZYPP_THROW(MediaNotAttachedException(url())); 00968 } 00969 00970 getFile( filename ); // pass to concrete handler 00971 DBG << "provideFile(" << filename << ")" << endl; 00972 } 00973 00974 00976 // 00977 // 00978 // METHOD NAME : MediaHandler::provideDir 00979 // METHOD TYPE : PMError 00980 // 00981 // DESCRIPTION : 00982 // 00983 void MediaHandler::provideDir( Pathname dirname ) const 00984 { 00985 if ( !isAttached() ) { 00986 INT << "Error: Not attached on provideDir(" << dirname << ")" << endl; 00987 ZYPP_THROW(MediaNotAttachedException(url())); 00988 } 00989 00990 getDir( dirname, /*recursive*/false ); // pass to concrete handler 00991 MIL << "provideDir(" << dirname << ")" << endl; 00992 } 00993 00995 // 00996 // 00997 // METHOD NAME : MediaHandler::provideDirTree 00998 // METHOD TYPE : PMError 00999 // 01000 // DESCRIPTION : 01001 // 01002 void MediaHandler::provideDirTree( Pathname dirname ) const 01003 { 01004 if ( !isAttached() ) { 01005 INT << "Error Not attached on provideDirTree(" << dirname << ")" << endl; 01006 ZYPP_THROW(MediaNotAttachedException(url())); 01007 } 01008 01009 getDir( dirname, /*recursive*/true ); // pass to concrete handler 01010 MIL << "provideDirTree(" << dirname << ")" << endl; 01011 } 01012 01014 // 01015 // 01016 // METHOD NAME : MediaHandler::releasePath 01017 // METHOD TYPE : PMError 01018 // 01019 // DESCRIPTION : 01020 // 01021 void MediaHandler::releasePath( Pathname pathname ) const 01022 { 01023 if ( ! _does_download || _attachPoint->empty() ) 01024 return; 01025 01026 PathInfo info( localPath( pathname ) ); 01027 01028 if ( info.isFile() ) { 01029 unlink( info.path() ); 01030 } else if ( info.isDir() ) { 01031 if ( info.path() != localRoot() ) { 01032 recursive_rmdir( info.path() ); 01033 } else { 01034 clean_dir( info.path() ); 01035 } 01036 } 01037 } 01038 01040 // 01041 // 01042 // METHOD NAME : MediaHandler::dirInfo 01043 // METHOD TYPE : PMError 01044 // 01045 // DESCRIPTION : 01046 // 01047 void MediaHandler::dirInfo( std::list<std::string> & retlist, 01048 const Pathname & dirname, bool dots ) const 01049 { 01050 retlist.clear(); 01051 01052 if ( !isAttached() ) { 01053 INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl; 01054 ZYPP_THROW(MediaNotAttachedException(url())); 01055 } 01056 01057 getDirInfo( retlist, dirname, dots ); // pass to concrete handler 01058 MIL << "dirInfo(" << dirname << ")" << endl; 01059 } 01060 01062 // 01063 // 01064 // METHOD NAME : MediaHandler::dirInfo 01065 // METHOD TYPE : PMError 01066 // 01067 // DESCRIPTION : 01068 // 01069 void MediaHandler::dirInfo( filesystem::DirContent & retlist, 01070 const Pathname & dirname, bool dots ) const 01071 { 01072 retlist.clear(); 01073 01074 if ( !isAttached() ) { 01075 INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl; 01076 ZYPP_THROW(MediaNotAttachedException(url())); 01077 } 01078 01079 getDirInfo( retlist, dirname, dots ); // pass to concrete handler 01080 MIL << "dirInfo(" << dirname << ")" << endl; 01081 } 01082 01084 // 01085 // 01086 // METHOD NAME : MediaHandler::doesFileExist 01087 // METHOD TYPE : PMError 01088 // 01089 // DESCRIPTION : 01090 // 01091 bool MediaHandler::doesFileExist( const Pathname & filename ) const 01092 { 01093 // TODO do some logging 01094 if ( !isAttached() ) { 01095 INT << "Error Not attached on doesFileExist(" << filename << ")" << endl; 01096 ZYPP_THROW(MediaNotAttachedException(url())); 01097 } 01098 return getDoesFileExist( filename ); 01099 MIL << "doesFileExist(" << filename << ")" << endl; 01100 } 01101 01103 // 01104 // 01105 // METHOD NAME : MediaHandler::getDirectoryYast 01106 // METHOD TYPE : PMError 01107 // 01108 void MediaHandler::getDirectoryYast( std::list<std::string> & retlist, 01109 const Pathname & dirname, bool dots ) const 01110 { 01111 retlist.clear(); 01112 01113 filesystem::DirContent content; 01114 getDirectoryYast( content, dirname, dots ); 01115 01116 // convert to std::list<std::string> 01117 for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) { 01118 retlist.push_back( it->name ); 01119 } 01120 } 01121 01123 // 01124 // 01125 // METHOD NAME : MediaHandler::getDirectoryYast 01126 // METHOD TYPE : PMError 01127 // 01128 void MediaHandler::getDirectoryYast( filesystem::DirContent & retlist, 01129 const Pathname & dirname, bool dots ) const 01130 { 01131 retlist.clear(); 01132 01133 // look for directory.yast 01134 Pathname dirFile = dirname + "directory.yast"; 01135 getFile( dirFile ); 01136 DBG << "provideFile(" << dirFile << "): " << "OK" << endl; 01137 01138 // using directory.yast 01139 ifstream dir( localPath( dirFile ).asString().c_str() ); 01140 if ( dir.fail() ) { 01141 ERR << "Unable to load '" << localPath( dirFile ) << "'" << endl; 01142 ZYPP_THROW(MediaSystemException(url(), 01143 "Unable to load '" + localPath( dirFile ).asString() + "'")); 01144 } 01145 01146 string line; 01147 while( getline( dir, line ) ) { 01148 if ( line.empty() ) continue; 01149 if ( line == "directory.yast" ) continue; 01150 01151 // Newer directory.yast append '/' to directory names 01152 // Remaining entries are unspecified, although most probabely files. 01153 filesystem::FileType type = filesystem::FT_NOT_AVAIL; 01154 if ( *line.rbegin() == '/' ) { 01155 line.erase( line.end()-1 ); 01156 type = filesystem::FT_DIR; 01157 } 01158 01159 if ( dots ) { 01160 if ( line == "." || line == ".." ) continue; 01161 } else { 01162 if ( *line.begin() == '.' ) continue; 01163 } 01164 01165 retlist.push_back( filesystem::DirEntry( line, type ) ); 01166 } 01167 } 01168 01169 /****************************************************************** 01170 ** 01171 ** 01172 ** FUNCTION NAME : operator<< 01173 ** FUNCTION TYPE : ostream & 01174 */ 01175 ostream & operator<<( ostream & str, const MediaHandler & obj ) 01176 { 01177 str << obj.url() << ( obj.isAttached() ? "" : " not" ) 01178 << " attached; localRoot \"" << obj.localRoot() << "\""; 01179 return str; 01180 } 01181 01183 // 01184 // 01185 // METHOD NAME : MediaHandler::getFile 01186 // METHOD TYPE : PMError 01187 // 01188 // DESCRIPTION : Asserted that media is attached. 01189 // Default implementation of pure virtual. 01190 // 01191 void MediaHandler::getFile( const Pathname & filename ) const 01192 { 01193 PathInfo info( localPath( filename ) ); 01194 if( info.isFile() ) { 01195 return; 01196 } 01197 01198 if (info.isExist()) 01199 ZYPP_THROW(MediaNotAFileException(url(), localPath(filename))); 01200 else 01201 ZYPP_THROW(MediaFileNotFoundException(url(), filename)); 01202 } 01203 01204 01205 void MediaHandler::getFileCopy ( const Pathname & srcFilename, const Pathname & targetFilename ) const 01206 { 01207 getFile(srcFilename); 01208 01209 if ( copy( localPath( srcFilename ), targetFilename ) != 0 ) { 01210 ZYPP_THROW(MediaWriteException(targetFilename)); 01211 } 01212 } 01213 01214 01215 01217 // 01218 // 01219 // METHOD NAME : MediaHandler::getDir 01220 // METHOD TYPE : PMError 01221 // 01222 // DESCRIPTION : Asserted that media is attached. 01223 // Default implementation of pure virtual. 01224 // 01225 void MediaHandler::getDir( const Pathname & dirname, bool recurse_r ) const 01226 { 01227 PathInfo info( localPath( dirname ) ); 01228 if( info.isDir() ) { 01229 return; 01230 } 01231 01232 if (info.isExist()) 01233 ZYPP_THROW(MediaNotADirException(url(), localPath(dirname))); 01234 else 01235 ZYPP_THROW(MediaFileNotFoundException(url(), dirname)); 01236 } 01237 01239 // 01240 // 01241 // METHOD NAME : MediaHandler::getDirInfo 01242 // METHOD TYPE : PMError 01243 // 01244 // DESCRIPTION : Asserted that media is attached and retlist is empty. 01245 // Default implementation of pure virtual. 01246 // 01247 void MediaHandler::getDirInfo( std::list<std::string> & retlist, 01248 const Pathname & dirname, bool dots ) const 01249 { 01250 PathInfo info( localPath( dirname ) ); 01251 if( ! info.isDir() ) { 01252 ZYPP_THROW(MediaNotADirException(url(), localPath(dirname))); 01253 } 01254 01255 #if NONREMOTE_DIRECTORY_YAST 01256 // use directory.yast if available 01257 try { 01258 getDirectoryYast( retlist, dirname, dots ); 01259 } 01260 catch (const MediaException & excpt_r) 01261 { 01262 #endif 01263 01264 // readdir 01265 int res = readdir( retlist, info.path(), dots ); 01266 if ( res ) 01267 { 01268 MediaSystemException nexcpt(url(), "readdir failed"); 01269 #if NONREMOTE_DIRECTORY_YAST 01270 nexcpt.remember(excpt_r); 01271 #endif 01272 ZYPP_THROW(nexcpt); 01273 } 01274 01275 #if NONREMOTE_DIRECTORY_YAST 01276 } 01277 #endif 01278 01279 return; 01280 } 01281 01283 // 01284 // 01285 // METHOD NAME : MediaHandler::getDirInfo 01286 // METHOD TYPE : PMError 01287 // 01288 // DESCRIPTION : Asserted that media is attached and retlist is empty. 01289 // Default implementation of pure virtual. 01290 // 01291 void MediaHandler::getDirInfo( filesystem::DirContent & retlist, 01292 const Pathname & dirname, bool dots ) const 01293 { 01294 PathInfo info( localPath( dirname ) ); 01295 if( ! info.isDir() ) { 01296 ZYPP_THROW(MediaNotADirException(url(), localPath(dirname))); 01297 } 01298 01299 #if NONREMOTE_DIRECTORY_YAST 01300 // use directory.yast if available 01301 try { 01302 getDirectoryYast( retlist, dirname, dots ); 01303 } 01304 catch (const MediaException & excpt_r) 01305 { 01306 #endif 01307 01308 // readdir 01309 int res = readdir( retlist, info.path(), dots ); 01310 if ( res ) 01311 { 01312 MediaSystemException nexcpt(url(), "readdir failed"); 01313 #if NONREMOTE_DIRECTORY_YAST 01314 nexcpt.remember(excpt_r); 01315 #endif 01316 ZYPP_THROW(nexcpt); 01317 } 01318 #if NONREMOTE_DIRECTORY_YAST 01319 } 01320 #endif 01321 } 01322 01324 // 01325 // 01326 // METHOD NAME : MediaHandler::getDoesFileExist 01327 // METHOD TYPE : PMError 01328 // 01329 // DESCRIPTION : Asserted that file is not a directory 01330 // Default implementation of pure virtual. 01331 // 01332 bool MediaHandler::getDoesFileExist( const Pathname & filename ) const 01333 { 01334 PathInfo info( localPath( filename ) ); 01335 if( info.isDir() ) { 01336 ZYPP_THROW(MediaNotAFileException(url(), localPath(filename))); 01337 } 01338 return info.isExist(); 01339 } 01340 01341 bool MediaHandler::hasMoreDevices() 01342 { 01343 return false; 01344 } 01345 01346 void MediaHandler::getDetectedDevices(std::vector<std::string> & devices, 01347 unsigned int & index) const 01348 { 01349 // clear the vector by default 01350 if (!devices.empty()) 01351 devices.clear(); 01352 index = 0; 01353 01354 DBG << "No devices for this medium" << endl; 01355 } 01356 01357 void MediaHandler::setDeltafile( const Pathname & filename ) const 01358 { 01359 _deltafile = filename; 01360 } 01361 01362 Pathname MediaHandler::deltafile() const { 01363 return _deltafile; 01364 } 01365 01366 } // namespace media 01367 } // namespace zypp 01368 // vim: set ts=8 sts=2 sw=2 ai noet:
1.7.6.1