--- /dev/null
+#include <iostream>
+
+#include <zypp/base/LogControl.h>
+#include <zypp/base/LogTools.h>
+#include <zypp/ExternalProgram.h>
+
+#include <zypp/MediaSetAccess.h>
+#include <zypp/KeyRing.h>
+#include <zypp/Fetcher.h>
+#include <zypp/TmpPath.h>
+
+
+using std::endl;
+
+int main ( int argc, const char * argv[] )
+try {
+ --argc;
+ ++argv;
+ //zypp::base::LogControl::instance().logToStdErr();
+ INT << "===[START]==========================================" << endl;
+ ///////////////////////////////////////////////////////////////////
+
+ zypp::Url oRemoteUrl( argv[0] ); //"http://download.opensuse.org/distribution/openSUSE-current/repo/oss" );
+ std::string oRemoteDir( argv[1] ); //"/suse/setup/slide" );
+ const bool oRecursive( true );
+ zypp::Pathname oLocalDir( "" );
+
+ zypp::scoped_ptr<zypp::filesystem::TmpDir> tmpdir;
+ if ( oLocalDir.empty() )
+ {
+ tmpdir.reset( new zypp::filesystem::TmpDir );
+ oLocalDir = tmpdir->path();
+ }
+
+ zypp::Fetcher fetcher;
+ fetcher.setOptions( zypp::Fetcher::AutoAddIndexes );
+ fetcher.enqueueDir( zypp::OnMediaLocation( oRemoteDir ), oRecursive );
+
+ zypp::KeyRing::setDefaultAccept( zypp::KeyRing::TRUST_KEY_TEMPORARILY );
+ zypp::MediaSetAccess media( oRemoteUrl, "/" );
+ fetcher.start( oLocalDir, media );
+
+ zypp::ExternalProgram( "find "+(oLocalDir/oRemoteDir).asString()+" -ls" ) >> std::cout;
+
+ ///////////////////////////////////////////////////////////////////
+ INT << "===[END]============================================" << endl << endl;
+ zypp::base::LogControl::instance().logNothing();
+ return 0;
+}
+catch ( const zypp::Exception & exp )
+{
+ INT << exp << endl << exp.historyAsString();
+}
+catch (...)
+{}
*/
void readIndex( const Pathname &index, const Pathname &basedir );
- /** specific version of \ref readIndex for SHA1SUMS file */
- void readSha1sumsIndex( const Pathname &index, const Pathname &basedir );
+ /** specific version of \ref readIndex for CHECKSUMS file */
+ void readChecksumsIndex( const Pathname &index, const Pathname &basedir );
- /** specific version of \ref readIndex for SHA1SUMS file */
+ /** specific version of \ref readIndex for content file */
void readContentFileIndex( const Pathname &index, const Pathname &basedir );
/** reads the content of a directory but keeps a cache **/
const OnMediaLocation &resource,
const Pathname &dest_dir )
{
- if ( _options & AutoAddSha1sumsIndexes )
+ auto fnc_addIfInContent( [&]( const std::string & index_r ) -> bool
{
- // only try to add an index if it exists
- filesystem::DirEntry shafile;
- shafile.name = "SHA1SUMS"; shafile.type = filesystem::FT_FILE;
- if ( find( content.begin(), content.end(), shafile ) != content.end() )
- {
- // add the index of this directory
- OnMediaLocation indexloc(resource);
- indexloc.changeFilename(resource.filename() + "SHA1SUMS");
- addIndex(indexloc);
- // we need to read it now
- downloadAndReadIndexList(media, dest_dir);
- }
+ if ( find( content.begin(), content.end(), filesystem::DirEntry(index_r,filesystem::FT_FILE) ) == content.end() )
+ return false;
+ // add the index of this directory
+ OnMediaLocation indexloc( resource );
+ indexloc.changeFilename( resource.filename() + index_r );
+ addIndex( indexloc );
+ // we need to read it now
+ downloadAndReadIndexList( media, dest_dir );
+ return true;
+ } );
+
+ if ( _options & AutoAddChecksumsIndexes )
+ {
+ fnc_addIfInContent( "CHECKSUMS" ) || fnc_addIfInContent( "SHA1SUMS" );
}
if ( _options & AutoAddContentFileIndexes )
{
- // only try to add an index if it exists
- filesystem::DirEntry contentfile;
- contentfile.name = "content"; contentfile.type = filesystem::FT_FILE;
- if ( find( content.begin(), content.end(), contentfile ) != content.end() )
- {
- // add the index of this directory
- OnMediaLocation indexloc(resource);
- indexloc.changeFilename(resource.filename() + "content");
- addIndex(indexloc);
- // we need to read it now
- downloadAndReadIndexList(media, dest_dir);
- }
+ fnc_addIfInContent( "content" );
}
}
// individual transfer jobs
MIL << "Adding directory " << resource.filename() << endl;
filesystem::DirContent content;
- getDirectoryContent(media, resource, content);
+ try {
+ getDirectoryContent(media, resource, content);
+ }
+ catch ( media::MediaFileNotFoundException & exception )
+ {
+ ZYPP_CAUGHT( exception );
+ WAR << "Skiping subtree hidden at " << resource.filename() << endl;
+ return;
+ }
// this method test for the option flags so indexes are added
// only if the options are enabled
it != content.end();
++it )
{
- // skip SHA1SUMS* as they were already retrieved
- if ( str::hasPrefix(it->name, "SHA1SUMS") )
+ // skip CHECKSUMS* as they were already retrieved
+ if ( str::hasPrefix(it->name, "CHECKSUMS") || str::hasPrefix(it->name, "SHA1SUMS") )
continue;
Pathname filename = resource.filename() + it->name;
// generic function for reading indexes
void Fetcher::Impl::readIndex( const Pathname &index, const Pathname &basedir )
{
- if ( index.basename() == "SHA1SUMS" )
- readSha1sumsIndex(index, basedir);
+ if ( index.basename() == "CHECKSUMS" || index.basename() == "SHA1SUMS" )
+ readChecksumsIndex(index, basedir);
else if ( index.basename() == "content" )
readContentFileIndex(index, basedir);
else
}
}
- // reads a SHA1SUMS file index
- void Fetcher::Impl::readSha1sumsIndex( const Pathname &index, const Pathname &basedir )
+ // reads a CHECKSUMS (old SHA1SUMS) file index
+ void Fetcher::Impl::readChecksumsIndex( const Pathname &index, const Pathname &basedir )
{
std::ifstream in( index.c_str() );
- string buffer;
if ( ! in.fail() )
{
- while ( getline(in, buffer) )
+ std::string buffer;
+ while ( getline( in, buffer ) )
{
- vector<string> words;
- str::split( buffer, back_inserter(words) );
- if ( words.size() != 2 )
- ZYPP_THROW(Exception("Wrong format for SHA1SUMS file"));
- //MIL << "check: '" << words[0] << "' | '" << words[1] << "'" << endl;
- if ( ! words[1].empty() )
- _checksums[(basedir + words[1]).asString()] = CheckSum::sha1(words[0]);
+
+ if ( buffer[0] == '#' )
+ continue; // simple comment
+
+ CheckSum checksum( str::stripFirstWord( buffer, /*ltrim before strip*/true ) );
+ if ( checksum.empty() )
+ continue; // empty line | unknown cheksum format
+
+ if ( buffer.empty() )
+ {
+ WAR << "Missing filename in CHECKSUMS file: " << index.asString() << " (" << checksum << ")" << endl;
+ continue;
+ }
+
+ _checksums[(basedir/buffer).asString()] = checksum;
}
}
else
- ZYPP_THROW(Exception("Can't open SHA1SUMS file: " + index.asString()));
+ ZYPP_THROW(Exception("Can't open CHECKSUMS file: " + index.asString()));
}
void Fetcher::Impl::downloadIndex( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir)
// may be this code can be factored out
// together with the autodiscovery of indexes
// of addDirJobs
- if ( ( _options & AutoAddSha1sumsIndexes ) ||
+ if ( ( _options & AutoAddChecksumsIndexes ) ||
( _options & AutoAddContentFileIndexes ) )
{
// if auto indexing is enabled, then we need to read the
* fetcher.reset();
* \endcode
*
- * Indexes are supported in SHA1SUMS format (simple text file)
- * with sha1sums and file name, or content file, whith
+ * Indexes are supported in CHECKSUMS format (simple text file)
+ * with checksum and file name, or content file, whith
* HASH SHA1 line entries.
- *
+ *
* \note The indexes file names are relative to the directory
* where the index is.
+ *
+ * \note libzypp-11.x: Introduction of sha256 lead to the insight
+ * that using SHA1SUMS as filename was a bad choice. New media store
+ * the checksums in a CHECKSUMS file. If a CHECKSUMS file is not
+ * present, we fall back looking for a SHA1SUMS file. The checksum
+ * type (md5,sha1,sha256) is auto detected by looking at the cheksums
+ * length. No need to somehow encode it in the filename.
*/
class Fetcher
{
*/
AutoAddContentFileIndexes = 0x0001,
/**
- * If a SHA1SUMS file is found, it is
+ * If a CHECKSUMS file is found, it is
* downloaded and read.
*/
- AutoAddSha1sumsIndexes = 0x0002,
+ AutoAddChecksumsIndexes = 0x0002,
/**
- * If a content or SHA1SUMS file is found,
+ * If a content or CHECKSUMS file is found,
* it is downloaded and read.
*/
- AutoAddIndexes = 0x0001 | 0x0002,
+ AutoAddIndexes = AutoAddContentFileIndexes | AutoAddChecksumsIndexes,
};
ZYPP_DECLARE_FLAGS(Options, Option);
*
*/
void addIndex( const OnMediaLocation &resource );
-
+
/**
* Enqueue a object for transferal, they will not
* be transfered until \ref start() is called
*/
void enqueue( const OnMediaLocation &resource,
const FileChecker &checker = FileChecker() );
-
+
/**
* Enqueue a object for transferal, they will not
* be transfered until \ref start() is called
* using \ref AutoAddIndexes flag.
*
* Files are checked by providing a
- * SHA1SUMS or content file listing
+ * CHECKSUMS or content file listing
* <checksum> filename
- * and a respective SHA1SUMS.asc/content.asc which has
+ * and a respective CHECKSUMS.asc/content.asc which has
* the signature for the checksums.
*
* If you expect the user to not have the key of
* the signature either in the trusted or untrusted
- * keyring, you can offer it as SHA1SUMS.key (or content.key)
+ * keyring, you can offer it as CHECKSUMS.key (or content.key)
*
* \param recursive True if the complete tree should
* be enqueued.
* so make sure you don't add another one or
* the user could be asked twice.
*
- * \note The format of the file SHA1SUMS is the output of:
- * ls | grep -v SHA1SUMS | xargs sha1sum > SHA1SUMS
+ * \note The format of the file CHECKSUMS is the output of:
+ * ls | grep -v CHECKSUMS | xargs sha256sum > CHECKSUMS
* in each subdirectory.
*
- * \note Every file SHA1SUMS.* except of SHA1SUMS.(asc|key|(void)) will
+ * \note Every file CHECKSUMS.* except of CHECKSUMS.(asc|key|(void)) will
* not be transfered and will be ignored.
*
*/
* using \ref AutoAddIndexes flag.
*
* Files are checked by providing a
- * SHA1SUMS or content file listing
+ * CHECKSUMS or content file listing
* <checksum> filename
- * and a respective SHA1SUMS.asc/content.asc which has
+ * and a respective CHECKSUMS.asc/content.asc which has
* the signature for the checksums.
*
* If you expect the user to not have the key of
* the signature either in the trusted or untrusted
- * keyring, you can offer it as SHA1SUMS.key (or content.key)
+ * keyring, you can offer it as CHECKSUMS.key (or content.key)
*
* \param recursive True if the complete tree should
* be enqueued.
* transfer job, so make sure you don't add another one or
* the user could be asked twice.
*
- * \note The format of the file SHA1SUMS is the output of:
- * ls | grep -v SHA1SUMS | xargs sha1sum > SHA1SUMS
+ * \note The format of the file CHECKSUMS is the output of:
+ * ls | grep -v CHECKSUMS | xargs sha256sum > CHECKSUMS
* in each subdirectory.
*
- * \note Every file SHA1SUMS.* except of SHA1SUMS.(asc|key|(void)) will
+ * \note Every file CHECKSUMS.* except of CHECKSUMS.(asc|key|(void)) will
* not be transfered and will be ignored.
*
*/
void enqueueDigestedDir( const OnMediaLocation &resource,
bool recursive = false,
const FileChecker &checker = FileChecker() );
-
+
/**
* adds a directory to the list of directories
* where to look for cached files
*/
void addCachePath( const Pathname &cache_dir );
-
+
/**
* Reset the transfer (jobs) list
* \note It does not reset the cache directory list
*/
void reset();
-
+
/**
* start the transfer to a destination directory
* \a dest_dir