libzypp  15.28.6
RepoMirrorList.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include <iostream>
14 #include <vector>
15 #include <time.h>
18 #include "zypp/MediaSetAccess.h"
19 #include "zypp/base/LogTools.h"
20 #include "zypp/ZConfig.h"
21 #include "zypp/PathInfo.h"
22 
23 using namespace std;
24 
26 namespace zypp
27 {
28  namespace repo
30  {
31 
33  namespace
34  {
42  struct RepoMirrorListTempProvider
43  {
44  RepoMirrorListTempProvider()
45  {}
46  RepoMirrorListTempProvider( const Pathname & localfile_r )
47  : _localfile( localfile_r )
48  {}
49  RepoMirrorListTempProvider( const Url & url_r )
50  {
51  Url abs_url( url_r );
52  abs_url.setPathName( "/" );
53  abs_url.setQueryParam( "mediahandler", "curl" );
54  _access.reset( new MediaSetAccess( abs_url ) );
55  _localfile = _access->provideFile( url_r.getPathName() );
56  }
57 
58  const Pathname & localfile() const
59  { return _localfile; }
60 
61  private:
62  shared_ptr<MediaSetAccess> _access;
63  Pathname _localfile;
64  };
66 
67  inline std::vector<Url> RepoMirrorListParseXML( const Pathname &tmpfile )
68  {
69  InputStream tmpfstream (tmpfile);
70  media::MetaLinkParser metalink;
71  metalink.parse(tmpfstream);
72  return metalink.getUrls();
73  }
74 
75  inline std::vector<Url> RepoMirrorListParseTXT( const Pathname &tmpfile )
76  {
77  InputStream tmpfstream (tmpfile);
78  std::vector<Url> my_urls;
79  string tmpurl;
80  while (getline(tmpfstream.stream(), tmpurl))
81  {
82  if ( tmpurl[0] == '#' )
83  continue;
84  try {
85  my_urls.push_back(Url(tmpurl));
86  }
87  catch (...)
88  {;} // ignore malformed urls
89  }
90  return my_urls;
91  }
92 
94  inline std::vector<Url> RepoMirrorListParse( const Url & url_r, const Pathname & listfile_r, bool mirrorListForceMetalink_r )
95  {
96  USR << url_r << " " << listfile_r << endl;
97 
98  std::vector<Url> mirrorurls;
99  if ( mirrorListForceMetalink_r || url_r.asString().find( "/metalink" ) != string::npos )
100  mirrorurls = RepoMirrorListParseXML( listfile_r );
101  else
102  mirrorurls = RepoMirrorListParseTXT( listfile_r );
103 
104 
105  std::vector<Url> ret;
106  for ( auto & murl : mirrorurls )
107  {
108  if ( murl.getScheme() != "rsync" )
109  {
110  size_t delpos = murl.getPathName().find("repodata/repomd.xml");
111  if( delpos != string::npos )
112  {
113  murl.setPathName( murl.getPathName().erase(delpos) );
114  }
115  ret.push_back( murl );
116 
117  if ( ret.size() >= 4 ) // why 4?
118  break;
119  }
120  }
121  return ret;
122  }
123 
124  } // namespace
126 
127  RepoMirrorList::RepoMirrorList( const Url & url_r, const Pathname & metadatapath_r, bool mirrorListForceMetalink_r )
128  {
129  if ( url_r.getScheme() == "file" )
130  {
131  // never cache for local mirrorlist
132  _urls = RepoMirrorListParse( url_r, url_r.getPathName(), mirrorListForceMetalink_r );
133  }
134  else if ( ! PathInfo( metadatapath_r).isDir() )
135  {
136  // no cachedir
137  RepoMirrorListTempProvider provider( url_r ); // RAII: lifetime of any downloaded files
138  _urls = RepoMirrorListParse( url_r, provider.localfile(), mirrorListForceMetalink_r );
139  }
140  else
141  {
142  // have cachedir
143  Pathname cachefile( metadatapath_r );
144  if ( mirrorListForceMetalink_r || url_r.asString().find( "/metalink" ) != string::npos )
145  cachefile /= "mirrorlist.xml";
146  else
147  cachefile /= "mirrorlist.txt";
148 
149  zypp::filesystem::PathInfo cacheinfo( cachefile );
150  if ( !cacheinfo.isFile() || cacheinfo.mtime() < time(NULL) - (long) ZConfig::instance().repo_refresh_delay() * 60 )
151  {
152  DBG << "Getting MirrorList from URL: " << url_r << endl;
153  RepoMirrorListTempProvider provider( url_r ); // RAII: lifetime of downloaded file
154 
155  // Create directory, if not existing
156  DBG << "Copy MirrorList file to " << cachefile << endl;
157  zypp::filesystem::assert_dir( metadatapath_r );
158  zypp::filesystem::hardlinkCopy( provider.localfile(), cachefile );
159  }
160 
161  _urls = RepoMirrorListParse( url_r, cachefile, mirrorListForceMetalink_r );
162  if( _urls.empty() )
163  {
164  DBG << "Removing Cachefile as it contains no URLs" << endl;
165  zypp::filesystem::unlink( cachefile );
166  }
167  }
168  }
169 
171  } // namespace repo
174 } // namespace zypp
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition: PathInfo.cc:320
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition: Url.cc:598
Pathname _localfile
std::string asString() const
Returns a default string representation of the Url object.
Definition: Url.cc:491
std::string getline(std::istream &str)
Read one line from stream.
Definition: IOStream.cc:33
time_t mtime() const
Definition: PathInfo.h:376
int unlink(const Pathname &path)
Like 'unlink'.
Definition: PathInfo.cc:662
#define USR
Definition: Logger.h:69
int hardlinkCopy(const Pathname &oldpath, const Pathname &newpath)
Create newpath as hardlink or copy of oldpath.
Definition: PathInfo.cc:817
bool isFile() const
Definition: PathInfo.h:289
shared_ptr< MediaSetAccess > _access
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:220
std::string getScheme() const
Returns the scheme name of the URL.
Definition: Url.cc:527
Url manipulation class.
Definition: Url.h:87
#define DBG
Definition: Logger.h:63