00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <ctime>
00014 #include <cstdlib>
00015 #include <cstdio>
00016 #include <fcntl.h>
00017
00018 #include "zypp/base/Logger.h"
00019 #include "zypp/base/Exception.h"
00020
00021 #include "zypp/CapFactory.h"
00022 #include "zypp/Digest.h"
00023 #include "zypp/Source.h"
00024 #include "zypp/SourceManager.h"
00025 #include "zypp/ExternalProgram.h"
00026
00027 #include "zypp/target/store/xml/XMLPatchImpl.h"
00028 #include "zypp/target/store/xml/XMLMessageImpl.h"
00029 #include "zypp/target/store/xml/XMLScriptImpl.h"
00030 #include "zypp/target/store/xml/XMLSelectionImpl.h"
00031 #include "zypp/target/store/xml/XMLProductImpl.h"
00032 #include "zypp/target/store/xml/XMLPatternImpl.h"
00033 #include "zypp/target/store/xml/XMLAtomImpl.h"
00034
00035 #include "zypp/parser/xmlstore/XMLProductParser.h"
00036 #include "zypp/parser/xmlstore/XMLPatternParser.h"
00037 #include "zypp/parser/xmlstore/XMLPatchParser.h"
00038 #include "zypp/parser/xmlstore/XMLLanguageParser.h"
00039
00040 #include <iostream>
00041 #include <fstream>
00042 #include <sstream>
00043 #include <streambuf>
00044
00045 #include <list>
00046
00047 #include <zypp/TmpPath.h>
00048 #include <zypp/ZYppFactory.h>
00049 #include <zypp/ZYpp.h>
00050 #include <zypp/PathInfo.h>
00051
00052 #include "zypp/parser/xmlstore/XMLSourceCacheParser.h"
00053
00054 #include "boost/filesystem/operations.hpp"
00055 #include "boost/filesystem/fstream.hpp"
00056
00057 #include "XMLFilesBackend.h"
00058 #include "serialize.h"
00059
00060
00061 #define ZYPP_DB_DIR ( getZYpp()->homePath().asString()+"/db/" )
00062
00063 using std::endl;
00064 using std::string;
00065 using std::list;
00066 using namespace boost::filesystem;
00067 using namespace zypp;
00068 using namespace zypp::filesystem;
00069
00071 namespace zypp
00072 {
00073 namespace storage
00074 {
00075
00088 typedef struct
00089 {
00090 char * dist_name;
00091 char * dist_version;
00092 char * product_name;
00093 char * product_version;
00094 } PRODUCT_TABLE_ENTRY;
00095
00101 PRODUCT_TABLE_ENTRY* products_table()
00102 {
00103 static PRODUCT_TABLE_ENTRY products[] = {
00104 { "SUSE-Linux-Enterprise-Desktop-i386", "10-0", "SUSE SLED" , "10" },
00105 { "SUSE-Linux-Enterprise-Desktop-x86_64", "10-0", "SUSE SLED", "10" },
00106 { "SUSE-Linux-Enterprise-Server-i386", "10-0", "SUSE SLES", "10" },
00107 { "SUSE-Linux-Enterprise-Server-x86_64", "10-0", "SUSE SLES", "10" },
00108 { "SUSE-Linux-Enterprise-Server-ppc", "10-0", "SUSE SLES", "10" },
00109 { "SUSE-Linux-Enterprise-Server-ia64", "10-0", "SUSE SLES", "10" },
00110 { "SUSE-Linux-Enterprise-Server-s390x", "10-0", "SUSE SLES", "10" },
00111 { "SUSE-Linux-10.1-CD-download-x86", "10.1-0", "SUSE LINUX", "10.1" },
00112 { "SUSE-Linux-10.1-CD-download-ppc", "10.1-0", "SUSE LINUX", "10.1" },
00113 { "SUSE-Linux-10.1-CD-download-x86_64", "10.1-0", "SUSE LINUX", "10.1" },
00114 { "SUSE-Linux-10.1-CD-x86", "10.1-0", "SUSE LINUX", "10.1" },
00115 { "SUSE-Linux-10.1-CD-ppc", "10.1-0", "SUSE LINUX", "10.1" },
00116 { "SUSE-Linux-10.1-CD-x86_64", "10.1-0", "SUSE LINUX", "10.1" },
00117 { "SUSE-Linux-10.1-DVD9-x86-x86_64", "10.1-0", "SUSE LINUX", "10.1" },
00118 { "SUSE-Linux-10.1-OSS-DVD-x86", "10.1-0", "SUSE LINUX", "10.1" },
00119 { "SUSE-Linux-10.1-DVD-OSS-i386", "10.1-0", "SUSE LINUX", "10.1" },
00120 { "SUSE-Linux-10.1-DVD-OSS-ppc", "10.1-0", "SUSE LINUX", "10.1" },
00121 { "SUSE-Linux-10.1-DVD-OSS-x86_64", "10.1-0", "SUSE LINUX", "10.1" },
00122 { "SUSE-Linux-10.1-FTP", "10.1-0", "SUSE LINUX", "10.1" },
00123 { "SUSE-Linux-10.1-DVD-i386", "10.1-0", "SUSE LINUX", "10.1" },
00124 { "SUSE-Linux-10.1-DVD-x86_64", "10.1-0", "SUSE LINUX", "10.1" },
00125 { "SuSE-Linux-10.1-PromoDVD-i386", "10.1-0", "SUSE LINUX", "10.1" },
00126 { "SUSE-Linux-10.1-DVD9-CTMAGAZIN-x86-x86_64", "10.1-0", "SUSE LINUX", "10.1" },
00127 { "SUSE-Linux-Enterprise-SDK-i386", "10-0", "SLE SDK", "10" },
00128 { "SUSE-Linux-Enterprise-SDK-x86_64", "10-0", "SLE SDK", "10" },
00129 { "SUSE-Linux-Enterprise-SDK-ia64", "10-0", "SLE SDK", "10" },
00130 { "SUSE-Linux-Enterprise-SDK-s390x", "10-0", "SLE SDK", "10" },
00131 { "SUSE-Linux-Enterprise-SDK-ppc", "10-0", "SLE SDK", "10" },
00132 { "SUSE-Linux-Enterprise-RT", "10-0", "SLE RT", "10" },
00133 { 0L, 0L, 0L, 0L }
00134 };
00135
00136 return products;
00137 }
00138
00140
00141
00142
00144 class XMLFilesBackend::Private
00145 {
00146 public:
00147 Private()
00148 { }
00149 bool randomFileName;
00150 std::set<Resolvable::Kind> kinds;
00151 std::set<Resolvable::Kind> kinds_flags;
00152 Pathname root;
00153 };
00154
00156
00157
00158
00160
00162
00163
00164
00165
00166 XMLFilesBackend::XMLFilesBackend(const Pathname &root) : Backend(root)
00167 {
00168 d = new Private;
00169 d->randomFileName = false;
00170 d->root = root;
00171
00172
00173 d->kinds.insert(ResTraits<zypp::Patch>::kind);
00174
00175
00176 d->kinds.insert(ResTraits<zypp::Selection>::kind);
00177 d->kinds.insert(ResTraits<zypp::Product>::kind);
00178 d->kinds.insert(ResTraits<zypp::Pattern>::kind);
00179 d->kinds.insert(ResTraits<zypp::Language>::kind);
00180
00181
00182 d->kinds_flags.insert(ResTraits<zypp::Package>::kind);
00183 d->kinds_flags.insert(ResTraits<zypp::Patch>::kind);
00184
00185 d->kinds_flags.insert(ResTraits<zypp::Script>::kind);
00186 d->kinds_flags.insert(ResTraits<zypp::Selection>::kind);
00187 d->kinds_flags.insert(ResTraits<zypp::Product>::kind);
00188 d->kinds_flags.insert(ResTraits<zypp::Pattern>::kind);
00189 d->kinds_flags.insert(ResTraits<zypp::Language>::kind);
00190
00191
00192
00193 if (!isBackendInitialized())
00194 {
00195 DBG << "Database not initialized" << std::endl;
00196 initBackend();
00197
00198 if (!isBackendInitialized())
00199 DBG << "Error, cant init database" << std::endl;
00200 else
00201 DBG << "Database initialized" << std::endl;
00202 }
00203 else
00204 {
00205 DBG << "Database already initialized" << std::endl;
00206 }
00207 }
00208
00209 Date XMLFilesBackend::timestamp() const
00210 {
00211 PathInfo ts_info = PathInfo( d->root + Pathname(ZYPP_DB_DIR) + "timestamp" );
00212 if ( ts_info.isExist() )
00213 {
00214 return Date(ts_info.mtime());
00215 }
00216 else
00217 {
00218 updateTimestamp();
00219 return Date::now();
00220 }
00221 }
00222
00223
00224 int XMLFilesBackend::random() const
00225 {
00226 static bool init = false;
00227 if (!init)
00228 {
00229 unsigned int seed;
00230 init = true;
00231 int fd = open("/dev/urandom", O_RDONLY);
00232 if (fd < 0 || ::read(fd, &seed, sizeof(seed)) != sizeof(seed))
00233 {
00234
00235 srand(getpid());
00236 seed = rand()+time(0);
00237 }
00238 if (fd >= 0) close(fd);
00239 srand(seed);
00240 }
00241 return rand();
00242 }
00243
00244
00245 std::string XMLFilesBackend::randomString(int length) const
00246 {
00247 if (length <=0 ) return std::string();
00248
00249 std::string str; str.resize( length );
00250 int i = 0;
00251 while (length--)
00252 {
00253 int r=random() % 62;
00254 r+=48;
00255 if (r>57) r+=7;
00256 if (r>90) r+=6;
00257 str[i++] = char(r);
00258
00259 }
00260 return str;
00261 }
00262
00263 bool
00264 XMLFilesBackend::isBackendInitialized() const
00265 {
00266 bool ok = true;
00267 Pathname dbdir = d->root + ZYPP_DB_DIR;
00268 ok = ok && PathInfo(dbdir).isExist();
00269
00270 bool fixperms = false;
00271
00272
00273
00274 if ( ok && PathInfo(dbdir).perm() == 0700 )
00275 {
00276 if ( geteuid() == 0 )
00277 {
00278 fixperms = true;
00279 WAR << "Wrong permissions for /var/lib/zypp, will fix" << std::endl;
00280
00281 const char* argv[] =
00282 {
00283 "chmod",
00284 "-R",
00285 "0755",
00286 "/var/lib/zypp",
00287 NULL
00288 };
00289
00290 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
00291 prog.close();
00292 }
00293 else
00294 {
00295 WAR << "Wrong permissions for /var/lib/zypp, but can't fix unless you run as root." << std::endl;
00296 }
00297
00298 }
00299
00300
00301 std::set<Resolvable::Kind>::const_iterator it_kinds;
00302 for ( it_kinds = d->kinds.begin() ; it_kinds != d->kinds.end(); ++it_kinds )
00303 {
00304 Resolvable::Kind kind = (*it_kinds);
00305 bool isthere = exists(dirForResolvableKind(kind));
00306 ok = ok && isthere;
00307 }
00308
00309
00310 for ( it_kinds = d->kinds_flags.begin() ; it_kinds != d->kinds_flags.end(); ++it_kinds )
00311 {
00312 Resolvable::Kind kind = (*it_kinds);
00313 bool isthere = exists(dirForResolvableKindFlags(kind));
00314 ok = ok && isthere;
00315 }
00316
00317
00318 bool nmthere = exists(dirForNamedFlags());
00319 ok = ok && nmthere;
00320
00321 Pathname sourcesdir = d->root + ZYPP_DB_DIR + "/sources";
00322 bool srcthere = PathInfo(sourcesdir).isExist();
00323 ok = ok && srcthere;
00324
00325 if (srcthere && fixperms)
00326 {
00327 MIL << "Making " << sourcesdir << " not readable by others (0700)" << std::endl;
00328 filesystem::chmod( sourcesdir, 0700);
00329 }
00330
00331 return ok;
00332 }
00333
00334 void
00335 XMLFilesBackend::initBackend()
00336 {
00337
00338
00339
00340 Pathname topdir = d->root + Pathname(ZYPP_DB_DIR);
00341 DBG << "Creating directory structure " << topdir << std::endl;
00342
00343 if (0 != assert_dir(topdir, 0755))
00344 ZYPP_THROW(Exception("Cannot create XMLBackend db directory " + topdir.asString()));
00345
00346
00347 std::set<Resolvable::Kind>::const_iterator it_kinds;
00348 for ( it_kinds = d->kinds.begin() ; it_kinds != d->kinds.end(); ++it_kinds )
00349 {
00350 Resolvable::Kind kind = (*it_kinds);
00351 Pathname p(dirForResolvableKind(kind));
00352 if (0 != assert_dir(p, 0755))
00353 ZYPP_THROW(Exception("Cannot create directory " + p.asString()));
00354 else
00355 MIL << "Created " << p.asString() << std::endl;
00356 }
00357
00358
00359 for ( it_kinds = d->kinds_flags.begin() ; it_kinds != d->kinds_flags.end(); ++it_kinds )
00360 {
00361 Resolvable::Kind kind = (*it_kinds);
00362 Pathname p(dirForResolvableKindFlags(kind));
00363 if (0 != assert_dir(p, 0755))
00364 ZYPP_THROW(Exception("Cannot create directory " + p.asString()));
00365 else
00366 MIL << "Created " << p.asString() << std::endl;
00367 }
00368
00369
00370 Pathname namedflags(dirForNamedFlags());
00371 if (0 != assert_dir(namedflags, 0755))
00372 ZYPP_THROW(Exception("Cannot create directory " + namedflags.asString()));
00373 else
00374 MIL << "Created " << namedflags.asString() << std::endl;
00375
00376
00377 Pathname source_p = d->root + Pathname(ZYPP_DB_DIR) + Pathname("/sources/");
00378 if (0 != assert_dir(source_p, 0700))
00379 ZYPP_THROW(Exception("Cannot create directory " + source_p.asString()));
00380 else
00381 MIL << "Created " << source_p.asString() << std::endl;
00382 }
00383
00384 void XMLFilesBackend::setRandomFileNameEnabled( bool enabled )
00385 {
00386 d->randomFileName = enabled;
00387 }
00388
00389 std::string
00390 XMLFilesBackend::dirForResolvableKind( Resolvable::Kind kind ) const
00391 {
00392 std::string dir;
00393 dir += Pathname( d->root + Pathname(ZYPP_DB_DIR) + Pathname(resolvableKindToString(kind, true)) ).asString();
00394 return dir;
00395 }
00396
00397 std::string
00398 XMLFilesBackend::dirForResolvableKindFlags( Resolvable::Kind kind ) const
00399 {
00400 std::string dir;
00401 dir += Pathname( d->root + Pathname(ZYPP_DB_DIR) + Pathname("flags") + Pathname(resolvableKindToString(kind, true)) ).asString();
00402 return dir;
00403 }
00404
00405 std::string
00406 XMLFilesBackend::dirForNamedFlags() const
00407 {
00408 std::string dir;
00409 dir += Pathname( d->root + Pathname(ZYPP_DB_DIR) + Pathname("named-flags")).asString();
00410 return dir;
00411 }
00412
00413 std::string
00414 XMLFilesBackend::dirForResolvable( ResObject::constPtr resolvable ) const
00415 {
00416 return dirForResolvableKind(resolvable->kind());
00417 }
00418
00419 std::string
00420 XMLFilesBackend::dirForResolvableFlags( ResObject::constPtr resolvable ) const
00421 {
00422 return dirForResolvableKindFlags(resolvable->kind());
00423 }
00424
00425 std::string
00426 XMLFilesBackend::fileNameForNVR( const NVR &nvr ) const
00427 {
00428 std::string filename;
00429 filename = nvr.name;
00430 if ( nvr.edition != Edition::noedition )
00431 {
00432 filename += "-" + nvr.edition.asString();
00433 }
00434
00435 std::stringstream filename_stream(filename);
00436 std::string filename_encoded = Digest::digest("MD5", filename_stream);
00437 return filename_encoded;
00438 }
00439
00440 std::string
00441 XMLFilesBackend::fileNameForResolvable( ResObject::constPtr resolvable ) const
00442 {
00443 return fileNameForNVR( NVR( resolvable->name(), resolvable->edition() ) );
00444 }
00445
00446 std::string
00447 XMLFilesBackend::fullPathForResolvable( ResObject::constPtr resolvable ) const
00448 {
00449 return path( path(dirForResolvable(resolvable)) / path(fileNameForResolvable(resolvable))).string();
00450 }
00451
00452 std::string
00453 XMLFilesBackend::fullPathForNamedFlags( const std::string &key ) const
00454 {
00455 std::stringstream key_stream(key);
00456 std::string key_encoded = Digest::digest("MD5", key_stream);
00457 return path( path(dirForNamedFlags()) / path(key_encoded)).string();
00458 }
00459
00460 std::string
00461 XMLFilesBackend::fullPathForResolvableFlags( ResObject::constPtr resolvable ) const
00462 {
00463
00464 return path( path(dirForResolvableFlags(resolvable)) / path(fileNameForResolvable(resolvable))).string();
00465 }
00466
00467 void
00468 XMLFilesBackend::setObjectFlag( ResObject::constPtr resolvable, const std::string &flag )
00469 {
00470 std::set<std::string> flags = objectFlags(resolvable);
00471 flags.insert(flag);
00472 writeObjectFlags(resolvable, flags);
00473 }
00474
00475 void
00476 XMLFilesBackend::removeObjectFlag( ResObject::constPtr resolvable, const std::string &flag )
00477 {
00478 std::set<std::string> flags = objectFlags(resolvable);
00479 flags.erase(flag);
00480 writeObjectFlags(resolvable, flags);
00481 }
00482
00483 void
00484 XMLFilesBackend::writeObjectFlags( ResObject::constPtr resolvable, const std::set<std::string> &flags )
00485 {
00486 std::string filename = fullPathForResolvableFlags(resolvable);
00487 writeFlagsInFile( filename, flags );
00488 MIL << "Wrote " << flags.size() << " flags for " << resolvable->name() << " " << resolvable->edition() << std::endl;
00489 }
00490
00491 std::set<std::string>
00492 XMLFilesBackend::objectFlags( ResObject::constPtr resolvable ) const
00493 {
00494 std::string filename = fullPathForResolvableFlags(resolvable);
00495 return flagsFromFile(filename);
00496 }
00497
00498 bool
00499 XMLFilesBackend::doesObjectHasFlag( ResObject::constPtr resolvable, const std::string &flag ) const
00500 {
00501 std::set<std::string> flags = objectFlags(resolvable);
00502 return (find(flags.begin(), flags.end(), flag) != flags.end());
00503 }
00504
00506
00508
00509 void
00510 XMLFilesBackend::setFlag( const std::string &key, const std::string &flag )
00511 {
00512 std::set<std::string> _flags = flags(key);
00513 _flags.insert(flag);
00514 writeFlags(key, _flags);
00515 }
00516
00517 void
00518 XMLFilesBackend::removeFlag( const std::string &key, const std::string &flag )
00519 {
00520 std::set<std::string> _flags = flags(key);
00521 _flags.erase(flag);
00522 writeFlags(key, _flags);
00523 }
00524
00525 std::set<std::string>
00526 XMLFilesBackend::flags( const std::string &key ) const
00527 {
00528 std::string filename = fullPathForNamedFlags(key);
00529 return flagsFromFile(filename);
00530 }
00531
00532 bool
00533 XMLFilesBackend::hasFlag( const std::string &key, const std::string &flag ) const
00534 {
00535 std::set<std::string> _flags = flags(key);
00536 return (find(_flags.begin(), _flags.end(), flag) != _flags.end());
00537 }
00538
00539 void
00540 XMLFilesBackend::writeFlags( const std::string &key, const std::set<std::string> &pflags )
00541 {
00542 std::string filename = fullPathForNamedFlags(key);
00543 writeFlagsInFile( filename, pflags );
00544 MIL << "Wrote " << pflags.size() << " flags for " << key << std::endl;
00545 }
00546
00548
00550
00551 void
00552 XMLFilesBackend::writeFlagsInFile( const std::string &filename, const std::set<std::string> &pflags )
00553 {
00554 std::ofstream file(filename.c_str());
00555 if (!file) {
00556 ZYPP_THROW (Exception( "Can't open " + filename ) );
00557 }
00558
00559 try
00560 {
00561 for ( std::set<std::string>::const_iterator it = pflags.begin(); it != pflags.end(); it++)
00562 {
00563
00564 if ( *it == std::string() )
00565 continue;
00566 else
00567 file << *it << std::endl;
00568 }
00569 file << std::endl;
00570 MIL << "Wrote " << pflags.size() << " flags in " << filename << std::endl;
00571 }
00572 catch( std::exception &e )
00573 {
00574 ZYPP_THROW (Exception( "Can't write flags to store") );
00575 }
00576 updateTimestamp();
00577 }
00578
00579 std::set<std::string>
00580 XMLFilesBackend::flagsFromFile( const std::string &filename ) const
00581 {
00582 std::set<std::string> _flags;
00583
00584 if (!exists(path(filename)))
00585 return _flags;
00586
00587 std::ifstream file(filename.c_str());
00588 if (!file) {
00589 ZYPP_THROW (Exception( "Can't open " + filename ) );
00590 }
00591
00592 std::string buffer;
00593 while(file && !file.eof())
00594 {
00595 getline(file, buffer);
00596 if (buffer == std::string())
00597 continue;
00598
00599 _flags.insert(buffer);
00600 }
00601
00602 return _flags;
00603 }
00604
00605 void
00606 XMLFilesBackend::updateTimestamp() const
00607 {
00608 Pathname filename = d->root + Pathname(ZYPP_DB_DIR) + "timestamp";
00609 std::ofstream file(filename.asString().c_str(), std::ios::out);
00610 if (!file)
00611 {
00612 ZYPP_THROW (Exception( "Can't open timestamp file " + filename.asString() ) );
00613 }
00614 file.close();
00615 }
00616
00618
00620
00621 void
00622 XMLFilesBackend::storeObject( ResObject::constPtr resolvable )
00623 {
00624
00625 std::set<Resolvable::Kind>::const_iterator it;
00626 it = find(d->kinds.begin(), d->kinds.end(), resolvable->kind() );
00627 if (it == d->kinds.end())
00628 {
00629 ERR << "This backend was not designed to store resolvable of kind " << resolvableKindToString(resolvable->kind()) << ", ignoring..." << std::endl;
00630 return;
00631 }
00632
00633 std::string xml = castedToXML(resolvable);
00634 std::string filename = fullPathForResolvable(resolvable);
00635
00636 std::ofstream file;
00637
00638 try
00639 {
00640 file.open(filename.c_str());
00641 file << xml;
00642 file.close();
00643 }
00644 catch(std::exception &e)
00645 {
00646 ERR << "Error saving resolvable " << resolvable << std::endl;
00647 ZYPP_THROW(Exception(e.what()));
00648 }
00649 updateTimestamp();
00650 }
00651
00652 void
00653 XMLFilesBackend::deleteFileObject( const Pathname &filename ) const
00654 {
00655 try
00656 {
00657 int ret = filesystem::unlink(Pathname(filename));
00658 if ( ret != 0 )
00659 {
00660 ERR << "Error removing resolvable file " << filename << std::endl;
00661 ZYPP_THROW(Exception("Error deleting " + filename.asString()));
00662 }
00663 updateTimestamp();
00664 }
00665 catch(std::exception &e)
00666 {
00667 ERR << "Error removing resolvable file " << filename << std::endl;
00668 ZYPP_THROW(Exception(e.what()));
00669 }
00670 }
00671
00672 void
00673 XMLFilesBackend::deleteObject( ResObject::constPtr resolvable )
00674 {
00675
00676 std::set<Resolvable::Kind>::const_iterator it;
00677 it = find(d->kinds.begin(), d->kinds.end(), resolvable->kind() );
00678 if (it == d->kinds.end())
00679 {
00680 ERR << "This backend was not designed to store resolvable of kind " << resolvableKindToString(resolvable->kind()) << ", ignoring..." << std::endl;
00681 return;
00682 }
00683
00684
00685 try
00686 {
00687 deleteFileObject( fullPathForResolvable(resolvable) );
00688 }
00689 catch ( const Exception &e )
00690 {
00691 ERR << "Error removing resolvable " << resolvable << std::endl;
00692 ZYPP_RETHROW(e);
00693 }
00694 }
00695
00696 std::list<ResObject::Ptr> XMLFilesBackend::resolvablesFromFile( std::string file_path, Resolvable::Kind kind ) const
00697 {
00698 MIL << "[" << resolvableKindToString( kind, false ) << "] - " << file_path << std::endl;
00699 std::list<ResObject::Ptr> resolvables;
00700 std::ifstream res_file(file_path.c_str());
00701 if ( kind == ResTraits<zypp::Patch>::kind )
00702 {
00703
00704
00705
00706 try {
00707 XMLPatchParser iter(res_file,"");
00708 for (; !iter.atEnd(); ++iter)
00709 {
00710 Patch::Ptr patch = createPatch(**iter);
00711 resolvables.push_back(patch);
00712 Patch::AtomList atoms = patch->atoms();
00713 for (Patch::AtomList::iterator at = atoms.begin(); at != atoms.end(); at++)
00714 resolvables.push_back(*at);
00715
00716 break;
00717 }
00718 }
00719 catch (const Exception & excpt_r) {
00720 ZYPP_CAUGHT( excpt_r );
00721 WAR << "Skipping invalid patch file " << file_path << endl;
00722 }
00723 }
00724 else if ( kind == ResTraits<zypp::Product>::kind )
00725 {
00726 XMLProductParser iter(res_file,"");
00727 for (; !iter.atEnd(); ++iter)
00728 {
00729 resolvables.push_back(createProduct(**iter));
00730 break;
00731 }
00732 }
00733 else if ( kind == ResTraits<zypp::Selection>::kind )
00734 {
00735 XMLPatternParser iter(res_file,"");
00736 for (; !iter.atEnd(); ++iter)
00737 {
00738 resolvables.push_back(createSelection(**iter));
00739 break;
00740 }
00741 }
00742 else if ( kind == ResTraits<zypp::Pattern>::kind )
00743 {
00744 XMLPatternParser iter(res_file,"");
00745 for (; !iter.atEnd(); ++iter)
00746 {
00747 resolvables.push_back(createPattern(**iter));
00748 break;
00749 }
00750 }
00751 else if ( kind == ResTraits<zypp::Language>::kind )
00752 {
00753 XMLLanguageParser iter(res_file,"");
00754 for (; !iter.atEnd(); ++iter)
00755 {
00756 resolvables.push_back(createLanguage(**iter));
00757 break;
00758 }
00759 }
00760 else
00761 {
00762
00763 }
00764 return resolvables;
00765 }
00766
00767 std::list<ResObject::Ptr>
00768 XMLFilesBackend::storedObjects() const
00769 {
00770 DBG << std::endl;
00771 std::list<ResObject::Ptr> objects;
00772
00773 std::set<Resolvable::Kind>::const_iterator it_kinds;
00774 for ( it_kinds = d->kinds.begin() ; it_kinds != d->kinds.end(); ++it_kinds )
00775 {
00776 Resolvable::Kind kind = (*it_kinds);
00777 std::list<ResObject::Ptr> objects_for_kind = storedObjects(kind);
00778 std::list<ResObject::Ptr>::iterator it;
00779 for( it = objects_for_kind.begin(); it != objects_for_kind.end(); ++it)
00780 {
00781
00782 objects.push_back(*it);
00783 }
00784 }
00785 return objects;
00786 }
00787
00788 std::list<ResObject::Ptr>
00789 XMLFilesBackend::storedObjects(const Resolvable::Kind kind) const
00790 {
00791 std::list<ResObject::Ptr> objects;
00792 Pathname dir_path(dirForResolvableKind(kind));
00793 DBG << "Reading objects of kind " << resolvableKindToString(kind) << " in " << dir_path << std::endl;
00794
00795 if ( ! PathInfo( dir_path ).isExist() )
00796 {
00797 ERR << "path " << dir_path << " does not exists. Required to read objects of kind " << resolvableKindToString(kind) << std::endl;
00798 return std::list<ResObject::Ptr>();
00799 }
00800
00801 list<string> files;
00802 filesystem::readdir( files, dir_path, false );
00803
00804 for ( list<string>::const_iterator it = files.begin(); it != files.end(); ++it )
00805 {
00806 Pathname curr_file = dir_path + (*it);
00807 DBG << "[" << resolvableKindToString( kind, false ) << "] - " << curr_file << std::endl;
00808 std::list<ResObject::Ptr> objects_for_file;
00809 objects_for_file = resolvablesFromFile( curr_file.asString(), kind);
00810 for ( std::list<ResObject::Ptr>::iterator it = objects_for_file.begin(); it != objects_for_file.end(); ++it)
00811 objects.push_back(*it);
00812 }
00813
00814 MIL << "done reading " << objects.size() << " stored objects for file of kind " << resolvableKindToString(kind) << std::endl;
00815 return objects;
00816 }
00817
00818 std::list<ResObject::Ptr>
00819 XMLFilesBackend::storedObjects(const Resolvable::Kind kind, const std::string & name, bool partial_match) const
00820 {
00821 std::list<ResObject::Ptr> result;
00822 std::list<ResObject::Ptr> all;
00823 all = storedObjects(kind);
00824 std::list<ResObject::Ptr>::const_iterator it;
00825 for( it = all.begin(); it != all.end(); ++it)
00826 {
00827 ResObject::Ptr item = *it;
00828 if (item->name() == name )
00829 result.push_back(item);
00830 }
00831 MIL << "done reading stored objects of kind " << resolvableKindToString(kind) << " and keyword [" << name <<"]" << std::endl;
00832 return result;
00833 }
00834
00835 Patch::Ptr
00836 XMLFilesBackend::createPatch( const zypp::parser::xmlstore::XMLPatchData & parsed ) const
00837 {
00838 try
00839 {
00840 detail::ResImplTraits<XMLPatchImpl>::Ptr impl(new XMLPatchImpl());
00841 impl->_patch_id = parsed.patchId;
00842 impl->_timestamp = str::strtonum<time_t>(parsed.timestamp);
00843 impl->_category = parsed.category;
00844 impl->_reboot_needed = parsed.rebootNeeded;
00845 impl->_affects_pkg_manager = parsed.packageManager;
00846
00847
00848 impl->_summary = parsed.summary;
00849 impl->_description = parsed.summary;
00850
00851 impl->_install_notify = parsed.install_notify;
00852 impl->_delete_notify = parsed.delete_notify;
00853 impl->_license_to_confirm = parsed.license_to_confirm;
00854 impl->_size = parsed.size;
00855 impl->_archive_size = parsed.archive_size;
00856 impl->_install_only = parsed.install_only;
00857 impl->_build_time = parsed.build_time;
00858 impl->_install_time = parsed.install_time;
00859
00860 Arch arch;
00861 if (!parsed.arch.empty())
00862 arch = Arch(parsed.arch);
00863
00864
00865 NVRAD dataCollect( parsed.name,
00866 Edition( parsed.ver, parsed.rel, parsed.epoch ), arch,
00867 createDependencies(parsed, ResTraits<Patch>::kind) );
00868 Patch::Ptr patch = detail::makeResolvableFromImpl( dataCollect, impl );
00869 CapFactory _f;
00870
00871
00872
00873
00874 ResObject::Ptr atom;
00875 for (std::list<XMLPatchAtomData_Ptr >::const_iterator it = parsed.atoms.begin(); it != parsed.atoms.end(); it++)
00876 {
00877 switch ((*it)->atomType())
00878 {
00879 case XMLPatchAtomData::Atom:
00880 {
00881
00882
00883
00884
00885
00886
00887
00888 XMLPatchAtomData_Ptr atom_data = dynamic_pointer_cast<XMLPatchAtomData>(*it);
00889 atom = createAtom(*atom_data);
00890 impl->_atoms.push_back(atom);
00891 break;
00892 }
00893 case XMLPatchAtomData::Message:
00894 {
00895 XMLPatchMessageData_Ptr message_data = dynamic_pointer_cast<XMLPatchMessageData>(*it);
00896 atom = createMessage(*message_data);
00897 impl->_atoms.push_back(atom);
00898 break;
00899 }
00900 case XMLPatchAtomData::Script:
00901 {
00902 XMLPatchScriptData_Ptr script_data = dynamic_pointer_cast<XMLPatchScriptData>(*it);
00903 atom = createScript(*script_data);
00904 if ( doesObjectHasFlag( atom, "SCRIPT_EXEC_FAILED" ) )
00905 {
00906 WAR << "Patch script not yet successfully executed: " << atom << endl;
00907 } else {
00908 impl->_atoms.push_back(atom);
00909 }
00910 break;
00911 }
00912 default:
00913 ERR << "Unknown type of atom" << endl;
00914 }
00915
00916 Capability cap( _f.parse(atom->kind(), atom->name(), Rel::EQ, atom->edition() ));
00917 patch->injectRequires(cap);
00918 }
00919 return patch;
00920 }
00921 catch (const Exception & excpt_r)
00922 {
00923 ZYPP_CAUGHT(excpt_r);
00924 ZYPP_THROW(Exception("Cannot create patch object"));
00925 }
00926 return 0L;
00927 }
00928
00929 Atom::Ptr
00930 XMLFilesBackend::createAtom( const zypp::parser::xmlstore::XMLPatchAtomData & parsed ) const
00931 {
00932 try
00933 {
00934 detail::ResImplTraits<XMLAtomImpl>::Ptr impl(new XMLAtomImpl());
00935
00936 Arch arch;
00937 if (!parsed.arch.empty())
00938 arch = Arch(parsed.arch);
00939
00940
00941 NVRAD dataCollect( parsed.name, Edition( parsed.ver, parsed.rel, parsed.epoch ), arch, createDependencies(parsed, ResTraits<Atom>::kind) );
00942
00943 impl->_summary = parsed.summary;
00944 impl->_description = parsed.summary;
00945
00946 impl->_install_notify = parsed.install_notify;
00947 impl->_delete_notify = parsed.delete_notify;
00948 impl->_license_to_confirm = parsed.license_to_confirm;
00949 impl->_size = parsed.size;
00950 impl->_archive_size = parsed.archive_size;
00951 impl->_install_only = parsed.install_only;
00952 impl->_build_time = parsed.build_time;
00953 impl->_install_time = parsed.install_time;
00954
00955 Atom::Ptr atom = detail::makeResolvableFromImpl( dataCollect, impl);
00956 return atom;
00957 }
00958 catch (const Exception & excpt_r)
00959 {
00960 ZYPP_CAUGHT(excpt_r);
00961 ZYPP_THROW(Exception("Cannot create atom object"));
00962 }
00963 return 0L;
00964 }
00965
00966 Message::Ptr
00967 XMLFilesBackend::createMessage( const zypp::parser::xmlstore::XMLPatchMessageData & parsed ) const
00968 {
00969 try
00970 {
00971 detail::ResImplTraits<XMLMessageImpl>::Ptr impl(new XMLMessageImpl());
00972 impl->_text = parsed.text;
00973
00974 Arch arch;
00975 if (!parsed.arch.empty())
00976 arch = Arch(parsed.arch);
00977
00978 impl->_summary = parsed.summary;
00979 impl->_description = parsed.summary;
00980
00981 impl->_install_notify = parsed.install_notify;
00982 impl->_delete_notify = parsed.delete_notify;
00983 impl->_license_to_confirm = parsed.license_to_confirm;
00984 impl->_size = parsed.size;
00985 impl->_archive_size = parsed.archive_size;
00986 impl->_install_only = parsed.install_only;
00987 impl->_build_time = parsed.build_time;
00988 impl->_install_time = parsed.install_time;
00989
00990
00991 NVRAD dataCollect( parsed.name, Edition( parsed.ver, parsed.rel, parsed.epoch ), arch, createDependencies(parsed, ResTraits<Message>::kind) );
00992 Message::Ptr message = detail::makeResolvableFromImpl( dataCollect, impl);
00993 return message;
00994 }
00995 catch (const Exception & excpt_r)
00996 {
00997 ZYPP_CAUGHT(excpt_r);
00998 ZYPP_THROW(Exception("Cannot create message object"));
00999 }
01000 return 0L;
01001 }
01002
01003 Script::Ptr
01004 XMLFilesBackend::createScript(const zypp::parser::xmlstore::XMLPatchScriptData & parsed ) const
01005 {
01006 try
01007 {
01008 detail::ResImplTraits<XMLScriptImpl>::Ptr impl(new XMLScriptImpl());
01009
01010 ofstream file;
01011 file.open(impl->_do_script->path().asString().c_str());
01012
01013 if ( ! file )
01014 ZYPP_THROW(Exception(N_("Cannot create a file needed to perform update installation.")));
01015
01016 file << parsed.do_script;;
01017 file.close();
01018
01019 file.open(impl->_undo_script->path().asString().c_str());
01020 if ( ! file )
01021 ZYPP_THROW(Exception(N_("Cannot create a file needed to perform update installation.")));
01022
01023 file << parsed.undo_script;;
01024 file.close();
01025
01026 Arch arch;
01027 if (!parsed.arch.empty())
01028 arch = Arch(parsed.arch);
01029
01030 impl->_summary = parsed.summary;
01031 impl->_description = parsed.summary;
01032
01033 impl->_install_notify = parsed.install_notify;
01034 impl->_delete_notify = parsed.delete_notify;
01035 impl->_license_to_confirm = parsed.license_to_confirm;
01036 impl->_size = parsed.size;
01037 impl->_archive_size = parsed.archive_size;
01038 impl->_install_only = parsed.install_only;
01039 impl->_build_time = parsed.build_time;
01040 impl->_install_time = parsed.install_time;
01041
01042
01043 NVRAD dataCollect( parsed.name, Edition( parsed.ver, parsed.rel, parsed.epoch ), arch, createDependencies(parsed, ResTraits<Script>::kind));
01044 Script::Ptr script = detail::makeResolvableFromImpl( dataCollect, impl );
01045 return script;
01046 }
01047 catch (const Exception & excpt_r)
01048 {
01049 ZYPP_CAUGHT(excpt_r);
01050 ZYPP_THROW(Exception("Cannot create script object"));
01051 }
01052 catch (const std::exception & excpt_r)
01053 {
01054 ERR << excpt_r.what() << endl;
01055 ZYPP_THROW(Exception("Cannot create script object"));
01056 }
01057 return 0L;
01058 }
01059
01060 Language::Ptr
01061 XMLFilesBackend::createLanguage( const zypp::parser::xmlstore::XMLLanguageData & parsed ) const
01062 {
01063 try
01064 {
01065 return Language::installedInstance( Locale(parsed.name) );
01066 }
01067 catch (const Exception & excpt_r)
01068 {
01069 ZYPP_CAUGHT(excpt_r);
01070 ZYPP_THROW(Exception("Cannot create language object"));
01071 }
01072 return 0L;
01073 }
01074
01075
01076 Product::Ptr
01077 XMLFilesBackend::createProduct( const zypp::parser::xmlstore::XMLProductData & parsed ) const
01078 {
01079 try
01080 {
01081 detail::ResImplTraits<XMLProductImpl>::Ptr impl(new XMLProductImpl());
01082
01083 Edition parser_edition = ( parsed.parser_version.empty() ? Edition::noedition : Edition(parsed.parser_version) );
01084
01085 impl->_summary = parsed.summary;
01086 impl->_description = parsed.summary;
01087
01088 impl->_install_notify = parsed.install_notify;
01089 impl->_delete_notify = parsed.delete_notify;
01090 impl->_license_to_confirm = parsed.license_to_confirm;
01091 impl->_size = parsed.size;
01092 impl->_archive_size = parsed.archive_size;
01093 impl->_install_only = parsed.install_only;
01094 impl->_build_time = parsed.build_time;
01095 impl->_install_time = parsed.install_time;
01096
01097 impl->_category = parsed.type;
01098 impl->_short_name = parsed.short_name;
01099 impl->_dist_name = parsed.dist_name;
01100 impl->_dist_version = parsed.dist_version;
01101
01102 if ( parsed.releasenotesurl.size() > 0 )
01103 impl->_release_notes_url = parsed.releasenotesurl;
01104 else
01105 impl->_release_notes_url = Url();
01106
01107
01108 list<string> update_urls = parsed.update_urls;
01109 for ( list<string>::const_iterator it = update_urls.begin(); it != update_urls.end(); ++it )
01110 {
01111 try
01112 {
01113 Url u(*it);
01114 impl->_update_urls.push_back (u);
01115 }
01116 catch ( const Exception &e )
01117 {
01118 ZYPP_THROW(Exception("Error parsing update url: " + e.msg()));
01119 }
01120 }
01121
01122
01123 list<string> extra_urls = parsed.extra_urls;
01124 for ( list<string>::const_iterator it = extra_urls.begin(); it != extra_urls.end(); ++it )
01125 {
01126 try
01127 {
01128 Url u(*it);
01129 impl->_extra_urls.push_back (u);
01130 }
01131 catch ( const Exception &e )
01132 {
01133 ZYPP_THROW(Exception("Error parsing extra url: " + e.msg()));
01134 }
01135 }
01136
01137
01138 list<string> optional_urls = parsed.optional_urls;
01139 for ( list<string>::const_iterator it = optional_urls.begin(); it != optional_urls.end(); ++it )
01140 {
01141 try
01142 {
01143 Url u(*it);
01144 impl->_optional_urls.push_back (u);
01145 }
01146 catch ( const Exception &e )
01147 {
01148 ZYPP_THROW(Exception("Error parsing optional url: " + e.msg()));
01149 }
01150 }
01151
01152 impl->_flags = parsed.flags;
01153
01154 Arch arch;
01155 if (!parsed.arch.empty())
01156 arch = Arch(parsed.arch);
01157
01158 Edition prod_edition( parsed.ver, parsed.rel, parsed.epoch );
01159 string prod_name(parsed.name);
01160
01161
01162 bool save_new_product_again_workaround = false;
01163 if ( parser_edition == Edition::noedition )
01164 {
01165 MIL << "Product " << parsed.name << " " << prod_edition << " possibly suffers from bug #205392. checking..." << endl;
01166 PRODUCT_TABLE_ENTRY *all_products = products_table();
01167 while ( all_products->dist_name != 0L )
01168 {
01169
01170 if ( ( parsed.name == all_products->dist_name ) && ( prod_edition.asString() == all_products->dist_version ) )
01171 {
01172 MIL << "[ATTENTION] Detected bug #205392. Product " << parsed.name << " " << prod_edition << " will be changed to " << all_products->product_name << " " << all_products->product_version << std::endl;
01173
01174
01175 Pathname wrong_product = Pathname(dirForResolvableKind(ResTraits<zypp::Product>::kind)) + fileNameForNVR( NVR( parsed.name, prod_edition) );
01176
01177
01178
01179 prod_name = string(all_products->product_name);
01180 prod_edition = Edition(all_products->product_version);
01181
01182
01183 impl->_dist_name = all_products->dist_name;
01184 impl->_dist_version = Edition(all_products->dist_version);
01185
01186
01187 deleteFileObject( wrong_product );
01188 MIL << "Fix for bug #205392 Old product deleted." << std::endl;
01189 save_new_product_again_workaround = true;
01190 break;
01191 }
01192 ++all_products;
01193 }
01194
01195 }
01196
01197
01198 std::replace(prod_name.begin(), prod_name.end(), ' ', '_');
01199
01200
01201 NVRAD dataCollect( prod_name, prod_edition, arch, createDependencies(parsed, ResTraits<Product>::kind) );
01202 Product::Ptr product = detail::makeResolvableFromImpl( dataCollect, impl );
01203
01204 if ( save_new_product_again_workaround )
01205 {
01206 const_cast<XMLFilesBackend *>(this)->storeObject(product);
01207 MIL << "Fixed Product saved. Fix for bug #205392. complete" << std::endl;
01208 }
01209
01210 return product;
01211 }
01212 catch (const Exception & excpt_r)
01213 {
01214 ZYPP_CAUGHT(excpt_r);
01215 ZYPP_THROW(Exception("Cannot create product object"));
01216 }
01217 return 0L;
01218 }
01219
01220 Pattern::Ptr
01221 XMLFilesBackend::createPattern( const zypp::parser::xmlstore::XMLPatternData & parsed ) const
01222 {
01223 try
01224 {
01225 detail::ResImplTraits<XMLPatternImpl>::Ptr impl(new XMLPatternImpl());
01226
01227 impl->_summary = parsed.summary;
01228 impl->_description = parsed.summary;
01229
01230 impl->_install_notify = parsed.install_notify;
01231 impl->_delete_notify = parsed.delete_notify;
01232 impl->_license_to_confirm = parsed.license_to_confirm;
01233 impl->_size = parsed.size;
01234 impl->_archive_size = parsed.archive_size;
01235 impl->_install_only = parsed.install_only;
01236 impl->_build_time = parsed.build_time;
01237 impl->_install_time = parsed.install_time;
01238
01239 impl->_user_visible = parsed.userVisible;
01240 impl->_default = ((parsed.default_ == "false" ) ? false : true );
01241 impl->_category = parsed.category;
01242 impl->_icon = parsed.icon;
01243 impl->_script = parsed.script;
01244
01245 Arch arch;
01246 if (!parsed.arch.empty())
01247 arch = Arch(parsed.arch);
01248
01249
01250 NVRAD dataCollect( parsed.name, Edition( parsed.ver, parsed.rel, parsed.epoch ), arch, createDependencies( parsed, ResTraits<Pattern>::kind));
01251 Pattern::Ptr pattern = detail::makeResolvableFromImpl( dataCollect, impl );
01252 return pattern;
01253 }
01254 catch (const Exception & excpt_r)
01255 {
01256 ZYPP_CAUGHT(excpt_r);
01257 ZYPP_THROW(Exception("Cannot create installation pattern object"));
01258 }
01259 return 0L;
01260 }
01261
01262 Selection::Ptr
01263 XMLFilesBackend::createSelection( const zypp::parser::xmlstore::XMLPatternData & parsed ) const
01264 {
01265 try
01266 {
01267 detail::ResImplTraits<XMLSelectionImpl>::Ptr impl(new XMLSelectionImpl());
01268
01269 impl->_summary = parsed.summary;
01270 impl->_description = parsed.summary;
01271
01272 impl->_install_notify = parsed.install_notify;
01273 impl->_delete_notify = parsed.delete_notify;
01274 impl->_license_to_confirm = parsed.license_to_confirm;
01275 impl->_size = parsed.size;
01276 impl->_archive_size = parsed.archive_size;
01277 impl->_install_only = parsed.install_only;
01278 impl->_build_time = parsed.build_time;
01279 impl->_install_time = parsed.install_time;
01280
01281 impl->_visible = parsed.userVisible;
01282 impl->_name = parsed.name;
01283
01284 impl->_category = parsed.category;
01285
01286 Arch arch;
01287 if (!parsed.arch.empty())
01288 arch = Arch(parsed.arch);
01289
01290
01291 NVRAD dataCollect( parsed.name, Edition( parsed.ver, parsed.rel, parsed.epoch ), arch, createDependencies( parsed, ResTraits<Pattern>::kind));
01292 Selection::Ptr selection = detail::makeResolvableFromImpl( dataCollect, impl );
01293 return selection;
01294 }
01295 catch (const Exception & excpt_r)
01296 {
01297 ZYPP_CAUGHT(excpt_r);
01298 ZYPP_THROW(Exception("Cannot create installation selection object"));
01299 }
01300 return 0L;
01301 }
01302
01303 Dependencies
01304 XMLFilesBackend::createDependencies( const zypp::parser::xmlstore::XMLResObjectData & parsed, const Resolvable::Kind my_kind ) const
01305 {
01306 Dependencies _deps;
01307 for (std::list<XMLDependency>::const_iterator it = parsed.provides.begin(); it != parsed.provides.end(); it++)
01308 {
01309 _deps[Dep::PROVIDES].insert(createCapability(*it, my_kind));
01310 }
01311 for (std::list<XMLDependency>::const_iterator it = parsed.conflicts.begin(); it != parsed.conflicts.end(); it++)
01312 {
01313 _deps[Dep::CONFLICTS].insert(createCapability(*it, my_kind));
01314 }
01315
01316 for (std::list<XMLDependency>::const_iterator it = parsed.obsoletes.begin(); it != parsed.obsoletes.end(); it++)
01317 {
01318 _deps[Dep::OBSOLETES].insert(createCapability(*it, my_kind));
01319 }
01320
01321 for (std::list<XMLDependency>::const_iterator it = parsed.freshens.begin(); it != parsed.freshens.end(); it++)
01322 {
01323 _deps[Dep::FRESHENS].insert(createCapability(*it, my_kind));
01324 }
01325
01326 for (std::list<XMLDependency>::const_iterator it = parsed.recommends.begin(); it != parsed.recommends.end(); it++)
01327 {
01328 _deps[Dep::RECOMMENDS].insert(createCapability(*it, my_kind));
01329 }
01330
01331 for (std::list<XMLDependency>::const_iterator it = parsed.suggests.begin(); it != parsed.suggests.end(); it++)
01332 {
01333 _deps[Dep::SUGGESTS].insert(createCapability(*it, my_kind));
01334 }
01335
01336 for (std::list<XMLDependency>::const_iterator it = parsed.enhances.begin(); it != parsed.enhances.end(); it++)
01337 {
01338 _deps[Dep::ENHANCES].insert(createCapability(*it, my_kind));
01339 }
01340
01341 for (std::list<XMLDependency>::const_iterator it = parsed.requires.begin(); it != parsed.requires.end(); it++)
01342 {
01343 _deps[Dep::REQUIRES].insert(createCapability(*it, my_kind));
01344 }
01345
01346 for (std::list<XMLDependency>::const_iterator it = parsed.prerequires.begin(); it != parsed.prerequires.end(); it++)
01347 {
01348 _deps[Dep::PREREQUIRES].insert(createCapability(*it, my_kind));
01349 }
01350 return _deps;
01351 }
01352
01353 Capability
01354 XMLFilesBackend::createCapability(const XMLDependency & dep, const Resolvable::Kind & my_kind) const
01355 {
01356 CapFactory _f;
01357 Resolvable::Kind _kind = dep.kind == "" ? my_kind : Resolvable::Kind(dep.kind);
01358 Capability cap;
01359 cap = _f.parse( _kind, dep.encoded );
01360 return cap;
01361 }
01362
01364
01365
01366
01367
01368 XMLFilesBackend::~XMLFilesBackend()
01369 {
01370 delete d;
01371 }
01372
01374
01375
01376
01377
01378 void XMLFilesBackend::doTest()
01379 {}
01380
01381
01382
01383
01384
01385
01386 std::ostream & operator<<( std::ostream & str, const XMLFilesBackend & obj )
01387 {
01388 return str;
01389 }
01390
01392
01394
01395 source::SourceInfoList
01396 XMLFilesBackend::storedSources() const
01397 {
01398 path source_p = path(d->root.asString()) / path(ZYPP_DB_DIR) / path ("sources");
01399 source::SourceInfoList sources;
01400 DBG << "Reading source cache in " << source_p.string() << std::endl;
01401 directory_iterator end_iter;
01402
01403 if ( !exists( source_p ) )
01404 {
01405 ERR << "path " << source_p.string() << " does not exists. Required to read source cache " << std::endl;
01406 return source::SourceInfoList();
01407 }
01408
01409 for ( directory_iterator dir_itr( source_p ); dir_itr != end_iter; ++dir_itr )
01410 {
01411 DBG << "[source-list] - " << dir_itr->leaf() << std::endl;
01412
01413 std::string full_path = (source_p / dir_itr->leaf()).string();
01414 std::ifstream anIstream(full_path.c_str());
01415 zypp::parser::xmlstore::XMLSourceCacheParser iter(anIstream, "");
01416 for (; ! iter.atEnd(); ++iter) {
01417 source::SourceInfo data = **iter;
01418 sources.push_back(data);
01419 }
01420 }
01421 MIL << "done reading source cache" << std::endl;
01422 return sources;
01423
01424 }
01425
01426 void
01427 XMLFilesBackend::storeSource(const source::SourceInfo &data)
01428 {
01429
01430 std::string xml = toXML(data);
01431 path source_p = path(d->root.asString()) / path(ZYPP_DB_DIR) / path ("sources");
01432
01433
01434 if (data.alias().size() == 0)
01435 {
01436 ZYPP_THROW(Exception("Cant save source with empty alias"));
01437 }
01438
01439
01440 std::ofstream file;
01441
01442 try
01443 {
01444 std::stringstream message_stream(data.alias());
01445 std::string full_path = (source_p / Digest::digest("MD5", message_stream)).string();
01446
01447 file.open(full_path.c_str());
01448 file << xml;
01449 file.close();
01450 }
01451 catch ( std::exception &e )
01452 {
01453 ERR << "Error saving source " << data.alias() << " in the cache" << std::endl;
01454 ZYPP_THROW(Exception(e.what()));
01455 }
01456 updateTimestamp();
01457 }
01458
01459 void
01460 XMLFilesBackend::deleteSource(const std::string &alias)
01461 {
01462
01463 path source_p = path(d->root.asString()) / path(ZYPP_DB_DIR) / path ("sources");
01464 try
01465 {
01466 std::stringstream message_stream(alias);
01467 std::string full_path = (source_p / Digest::digest("MD5", message_stream)).string();
01468 remove(full_path);
01469 }
01470 catch ( std::exception &e )
01471 {
01472 ERR << "Error deleting source " << alias << " in the cache" << std::endl;
01473 ZYPP_THROW(Exception(e.what()));
01474 }
01475 updateTimestamp();
01476 }
01477
01479 }
01482 }