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 namespace boost::filesystem;
00065 using namespace zypp;
00066 using namespace zypp::filesystem;
00067
00069 namespace zypp
00070 {
00071 namespace storage
00072 {
00073
00074
00076
00077
00078
00080 class XMLFilesBackend::Private
00081 {
00082 public:
00083 Private()
00084 { }
00085 bool randomFileName;
00086 std::set<Resolvable::Kind> kinds;
00087 std::set<Resolvable::Kind> kinds_flags;
00088 Pathname root;
00089 };
00090
00092
00093
00094
00096
00098
00099
00100
00101
00102 XMLFilesBackend::XMLFilesBackend(const Pathname &root) : Backend(root)
00103 {
00104 d = new Private;
00105 d->randomFileName = false;
00106 d->root = root;
00107
00108
00109 d->kinds.insert(ResTraits<zypp::Patch>::kind);
00110
00111
00112 d->kinds.insert(ResTraits<zypp::Selection>::kind);
00113 d->kinds.insert(ResTraits<zypp::Product>::kind);
00114 d->kinds.insert(ResTraits<zypp::Pattern>::kind);
00115 d->kinds.insert(ResTraits<zypp::Language>::kind);
00116
00117
00118 d->kinds_flags.insert(ResTraits<zypp::Package>::kind);
00119 d->kinds_flags.insert(ResTraits<zypp::Patch>::kind);
00120
00121
00122 d->kinds_flags.insert(ResTraits<zypp::Selection>::kind);
00123 d->kinds_flags.insert(ResTraits<zypp::Product>::kind);
00124 d->kinds_flags.insert(ResTraits<zypp::Pattern>::kind);
00125 d->kinds_flags.insert(ResTraits<zypp::Language>::kind);
00126
00127
00128
00129 if (!isBackendInitialized())
00130 {
00131 DBG << "Database not initialized" << std::endl;
00132 initBackend();
00133
00134 if (!isBackendInitialized())
00135 DBG << "Error, cant init database" << std::endl;
00136 else
00137 DBG << "Database initialized" << std::endl;
00138 }
00139 else
00140 {
00141 DBG << "Database already initialized" << std::endl;
00142 }
00143 }
00144
00145
00146 int XMLFilesBackend::random() const
00147 {
00148 static bool init = false;
00149 if (!init)
00150 {
00151 unsigned int seed;
00152 init = true;
00153 int fd = open("/dev/urandom", O_RDONLY);
00154 if (fd < 0 || ::read(fd, &seed, sizeof(seed)) != sizeof(seed))
00155 {
00156
00157 srand(getpid());
00158 seed = rand()+time(0);
00159 }
00160 if (fd >= 0) close(fd);
00161 srand(seed);
00162 }
00163 return rand();
00164 }
00165
00166
00167 std::string XMLFilesBackend::randomString(int length) const
00168 {
00169 if (length <=0 ) return std::string();
00170
00171 std::string str; str.resize( length );
00172 int i = 0;
00173 while (length--)
00174 {
00175 int r=random() % 62;
00176 r+=48;
00177 if (r>57) r+=7;
00178 if (r>90) r+=6;
00179 str[i++] = char(r);
00180
00181 }
00182 return str;
00183 }
00184
00185 bool
00186 XMLFilesBackend::isBackendInitialized() const
00187 {
00188 bool ok = true;
00189 Pathname dbdir = d->root + ZYPP_DB_DIR;
00190 ok = ok && PathInfo(dbdir).isExist();
00191
00192 bool fixperms = false;
00193
00194
00195
00196 if ( ok && PathInfo(dbdir).perm() == 0700 )
00197 {
00198 if ( geteuid() == 0 )
00199 {
00200 fixperms = true;
00201 WAR << "Wrong permissions for /var/lib/zypp, will fix" << std::endl;
00202
00203 const char* argv[] =
00204 {
00205 "chmod",
00206 "-R",
00207 "0755",
00208 "/var/lib/zypp",
00209 NULL
00210 };
00211
00212 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
00213 prog.close();
00214 }
00215 else
00216 {
00217 WAR << "Wrong permissions for /var/lib/zypp, but can't fix unless you run as root." << std::endl;
00218 }
00219
00220 }
00221
00222
00223 std::set<Resolvable::Kind>::const_iterator it_kinds;
00224 for ( it_kinds = d->kinds.begin() ; it_kinds != d->kinds.end(); ++it_kinds )
00225 {
00226 Resolvable::Kind kind = (*it_kinds);
00227 bool isthere = exists(dirForResolvableKind(kind));
00228 ok = ok && isthere;
00229 }
00230
00231
00232 for ( it_kinds = d->kinds_flags.begin() ; it_kinds != d->kinds_flags.end(); ++it_kinds )
00233 {
00234 Resolvable::Kind kind = (*it_kinds);
00235 bool isthere = exists(dirForResolvableKindFlags(kind));
00236 ok = ok && isthere;
00237 }
00238
00239
00240 bool nmthere = exists(dirForNamedFlags());
00241 ok = ok && nmthere;
00242
00243 Pathname sourcesdir = d->root + ZYPP_DB_DIR + "/sources";
00244 bool srcthere = PathInfo(sourcesdir).isExist();
00245 ok = ok && srcthere;
00246
00247 if (srcthere && fixperms)
00248 {
00249 MIL << "Making " << sourcesdir << " not readable by others (0700)" << std::endl;
00250 filesystem::chmod( sourcesdir, 0700);
00251 }
00252
00253 return ok;
00254 }
00255
00256 void
00257 XMLFilesBackend::initBackend()
00258 {
00259
00260
00261
00262 Pathname topdir = d->root + Pathname(ZYPP_DB_DIR);
00263 DBG << "Creating directory structure " << topdir << std::endl;
00264
00265 if (0 != assert_dir(topdir, 0755))
00266 ZYPP_THROW(Exception("Cannot create XMLBackend db directory " + topdir.asString()));
00267
00268
00269 std::set<Resolvable::Kind>::const_iterator it_kinds;
00270 for ( it_kinds = d->kinds.begin() ; it_kinds != d->kinds.end(); ++it_kinds )
00271 {
00272 Resolvable::Kind kind = (*it_kinds);
00273 Pathname p(dirForResolvableKind(kind));
00274 if (0 != assert_dir(p, 0755))
00275 ZYPP_THROW(Exception("Cannot create directory " + p.asString()));
00276 else
00277 MIL << "Created " << p.asString() << std::endl;
00278 }
00279
00280
00281 for ( it_kinds = d->kinds_flags.begin() ; it_kinds != d->kinds_flags.end(); ++it_kinds )
00282 {
00283 Resolvable::Kind kind = (*it_kinds);
00284 Pathname p(dirForResolvableKindFlags(kind));
00285 if (0 != assert_dir(p, 0755))
00286 ZYPP_THROW(Exception("Cannot create directory " + p.asString()));
00287 else
00288 MIL << "Created " << p.asString() << std::endl;
00289 }
00290
00291
00292 Pathname namedflags(dirForNamedFlags());
00293 if (0 != assert_dir(namedflags, 0755))
00294 ZYPP_THROW(Exception("Cannot create directory " + namedflags.asString()));
00295 else
00296 MIL << "Created " << namedflags.asString() << std::endl;
00297
00298
00299 Pathname source_p = d->root + Pathname(ZYPP_DB_DIR) + Pathname("/sources/");
00300 if (0 != assert_dir(source_p, 0700))
00301 ZYPP_THROW(Exception("Cannot create directory " + source_p.asString()));
00302 else
00303 MIL << "Created " << source_p.asString() << std::endl;
00304 }
00305
00306 void XMLFilesBackend::setRandomFileNameEnabled( bool enabled )
00307 {
00308 d->randomFileName = enabled;
00309 }
00310
00311 std::string
00312 XMLFilesBackend::dirForResolvableKind( Resolvable::Kind kind ) const
00313 {
00314 std::string dir;
00315 dir += Pathname( d->root + Pathname(ZYPP_DB_DIR) + Pathname(resolvableKindToString(kind, true)) ).asString();
00316 return dir;
00317 }
00318
00319 std::string
00320 XMLFilesBackend::dirForResolvableKindFlags( Resolvable::Kind kind ) const
00321 {
00322 std::string dir;
00323 dir += Pathname( d->root + Pathname(ZYPP_DB_DIR) + Pathname("flags") + Pathname(resolvableKindToString(kind, true)) ).asString();
00324 return dir;
00325 }
00326
00327 std::string
00328 XMLFilesBackend::dirForNamedFlags() const
00329 {
00330 std::string dir;
00331 dir += Pathname( d->root + Pathname(ZYPP_DB_DIR) + Pathname("named-flags")).asString();
00332 return dir;
00333 }
00334
00335 std::string
00336 XMLFilesBackend::dirForResolvable( ResObject::constPtr resolvable ) const
00337 {
00338 return dirForResolvableKind(resolvable->kind());
00339 }
00340
00341 std::string
00342 XMLFilesBackend::dirForResolvableFlags( ResObject::constPtr resolvable ) const
00343 {
00344 return dirForResolvableKindFlags(resolvable->kind());
00345 }
00346
00347 std::string
00348 XMLFilesBackend::fileNameForResolvable( ResObject::constPtr resolvable ) const
00349 {
00350 std::string filename;
00351
00352 filename = resolvable->name();
00353 if (resolvable->edition() != Edition::noedition )
00354 {
00355 filename += "-" + resolvable->edition().asString();
00356 }
00357
00358 std::stringstream filename_stream(filename);
00359 std::string filename_encoded = Digest::digest("MD5", filename_stream);
00360 return filename_encoded;
00361 }
00362
00363 std::string
00364 XMLFilesBackend::fullPathForResolvable( ResObject::constPtr resolvable ) const
00365 {
00366 return path( path(dirForResolvable(resolvable)) / path(fileNameForResolvable(resolvable))).string();
00367 }
00368
00369 std::string
00370 XMLFilesBackend::fullPathForNamedFlags( const std::string &key ) const
00371 {
00372 std::stringstream key_stream(key);
00373 std::string key_encoded = Digest::digest("MD5", key_stream);
00374 return path( path(dirForNamedFlags()) / path(key_encoded)).string();
00375 }
00376
00377 std::string
00378 XMLFilesBackend::fullPathForResolvableFlags( ResObject::constPtr resolvable ) const
00379 {
00380
00381 return path( path(dirForResolvableFlags(resolvable)) / path(fileNameForResolvable(resolvable))).string();
00382 }
00383
00384 void
00385 XMLFilesBackend::setObjectFlag( ResObject::constPtr resolvable, const std::string &flag )
00386 {
00387 std::set<std::string> flags = objectFlags(resolvable);
00388 flags.insert(flag);
00389 writeObjectFlags(resolvable, flags);
00390 }
00391
00392 void
00393 XMLFilesBackend::removeObjectFlag( ResObject::constPtr resolvable, const std::string &flag )
00394 {
00395 std::set<std::string> flags = objectFlags(resolvable);
00396 flags.erase(flag);
00397 writeObjectFlags(resolvable, flags);
00398 }
00399
00400 void
00401 XMLFilesBackend::writeObjectFlags( ResObject::constPtr resolvable, const std::set<std::string> &flags )
00402 {
00403 std::string filename = fullPathForResolvableFlags(resolvable);
00404 writeFlagsInFile( filename, flags );
00405 MIL << "Wrote " << flags.size() << " flags for " << resolvable->name() << " " << resolvable->edition() << std::endl;
00406 }
00407
00408 std::set<std::string>
00409 XMLFilesBackend::objectFlags( ResObject::constPtr resolvable ) const
00410 {
00411 std::string filename = fullPathForResolvableFlags(resolvable);
00412 return flagsFromFile(filename);
00413 }
00414
00415 bool
00416 XMLFilesBackend::doesObjectHasFlag( ResObject::constPtr resolvable, const std::string &flag ) const
00417 {
00418 std::set<std::string> flags = objectFlags(resolvable);
00419 return (find(flags.begin(), flags.end(), flag) != flags.end());
00420 }
00421
00423
00425
00426 void
00427 XMLFilesBackend::setFlag( const std::string &key, const std::string &flag )
00428 {
00429 std::set<std::string> _flags = flags(key);
00430 _flags.insert(flag);
00431 writeFlags(key, _flags);
00432 }
00433
00434 void
00435 XMLFilesBackend::removeFlag( const std::string &key, const std::string &flag )
00436 {
00437 std::set<std::string> _flags = flags(key);
00438 _flags.erase(flag);
00439 writeFlags(key, _flags);
00440 }
00441
00442 std::set<std::string>
00443 XMLFilesBackend::flags( const std::string &key ) const
00444 {
00445 std::string filename = fullPathForNamedFlags(key);
00446 return flagsFromFile(filename);
00447 }
00448
00449 bool
00450 XMLFilesBackend::hasFlag( const std::string &key, const std::string &flag ) const
00451 {
00452 std::set<std::string> _flags = flags(key);
00453 return (find(_flags.begin(), _flags.end(), flag) != _flags.end());
00454 }
00455
00456 void
00457 XMLFilesBackend::writeFlags( const std::string &key, const std::set<std::string> &pflags )
00458 {
00459 std::string filename = fullPathForNamedFlags(key);
00460 writeFlagsInFile( filename, pflags );
00461 MIL << "Wrote " << pflags.size() << " flags for " << key << std::endl;
00462 }
00463
00465
00467
00468 void
00469 XMLFilesBackend::writeFlagsInFile( const std::string &filename, const std::set<std::string> &pflags )
00470 {
00471 std::ofstream file(filename.c_str());
00472 if (!file) {
00473 ZYPP_THROW (Exception( "Can't open " + filename ) );
00474 }
00475
00476 try
00477 {
00478 for ( std::set<std::string>::const_iterator it = pflags.begin(); it != pflags.end(); it++)
00479 {
00480
00481 if ( *it == std::string() )
00482 continue;
00483 else
00484 file << *it << std::endl;
00485 }
00486 file << std::endl;
00487 MIL << "Wrote " << pflags.size() << " flags in " << filename << std::endl;
00488 }
00489 catch( std::exception &e )
00490 {
00491
00492 }
00493 }
00494
00495 std::set<std::string>
00496 XMLFilesBackend::flagsFromFile( const std::string &filename ) const
00497 {
00498 std::set<std::string> _flags;
00499
00500 if (!exists(path(filename)))
00501 return _flags;
00502
00503 std::ifstream file(filename.c_str());
00504 if (!file) {
00505 ZYPP_THROW (Exception( "Can't open " + filename ) );
00506 }
00507
00508 std::string buffer;
00509 while(file && !file.eof())
00510 {
00511 getline(file, buffer);
00512 if (buffer == std::string())
00513 continue;
00514
00515 _flags.insert(buffer);
00516 }
00517
00518 return _flags;
00519 }
00520
00522
00524
00525 void
00526 XMLFilesBackend::storeObject( ResObject::constPtr resolvable )
00527 {
00528
00529 std::set<Resolvable::Kind>::const_iterator it;
00530 it = find(d->kinds.begin(), d->kinds.end(), resolvable->kind() );
00531 if (it == d->kinds.end())
00532 {
00533 ERR << "This backend was not designed to store resolvable of kind " << resolvableKindToString(resolvable->kind()) << ", ignoring..." << std::endl;
00534 return;
00535 }
00536
00537 std::string xml = castedToXML(resolvable);
00538 std::string filename = fullPathForResolvable(resolvable);
00539
00540 std::ofstream file;
00541
00542 try
00543 {
00544 file.open(filename.c_str());
00545 file << xml;
00546 file.close();
00547 }
00548 catch(std::exception &e)
00549 {
00550 ERR << "Error saving resolvable " << resolvable << std::endl;
00551 ZYPP_THROW(Exception(e.what()));
00552 }
00553 }
00554
00555 void
00556 XMLFilesBackend::deleteObject( ResObject::constPtr resolvable )
00557 {
00558
00559 std::string filename = fullPathForResolvable(resolvable);
00560 try
00561 {
00562 int ret = filesystem::unlink(Pathname(filename));
00563 if ( ret != 0 )
00564 {
00565 ERR << "Error removing resolvable " << resolvable << std::endl;
00566 ZYPP_THROW(Exception("Error deleting " + filename));
00567 }
00568 }
00569 catch(std::exception &e)
00570 {
00571 ERR << "Error removing resolvable " << resolvable << std::endl;
00572 ZYPP_THROW(Exception(e.what()));
00573 }
00574 }
00575
00576 std::list<ResObject::Ptr> XMLFilesBackend::resolvablesFromFile( std::string file_path, Resolvable::Kind kind ) const
00577 {
00578 MIL << "[" << resolvableKindToString( kind, false ) << "] - " << file_path << std::endl;
00579 std::list<ResObject::Ptr> resolvables;
00580 std::ifstream res_file(file_path.c_str());
00581 if ( kind == ResTraits<zypp::Patch>::kind )
00582 {
00583
00584
00585
00586 try {
00587 XMLPatchParser iter(res_file,"");
00588 for (; !iter.atEnd(); ++iter)
00589 {
00590 Patch::Ptr patch = createPatch(**iter);
00591 resolvables.push_back(patch);
00592 Patch::AtomList atoms = patch->atoms();
00593 for (Patch::AtomList::iterator at = atoms.begin(); at != atoms.end(); at++)
00594 resolvables.push_back(*at);
00595
00596 break;
00597 }
00598 }
00599 catch (const Exception & excpt_r) {
00600 ZYPP_CAUGHT( excpt_r );
00601 WAR << "Skipping invalid patch file " << file_path << endl;
00602 }
00603 }
00604 else if ( kind == ResTraits<zypp::Product>::kind )
00605 {
00606 XMLProductParser iter(res_file,"");
00607 for (; !iter.atEnd(); ++iter)
00608 {
00609 resolvables.push_back(createProduct(**iter));
00610 break;
00611 }
00612 }
00613 else if ( kind == ResTraits<zypp::Selection>::kind )
00614 {
00615 XMLPatternParser iter(res_file,"");
00616 for (; !iter.atEnd(); ++iter)
00617 {
00618 resolvables.push_back(createSelection(**iter));
00619 break;
00620 }
00621 }
00622 else if ( kind == ResTraits<zypp::Pattern>::kind )
00623 {
00624 XMLPatternParser iter(res_file,"");
00625 for (; !iter.atEnd(); ++iter)
00626 {
00627 resolvables.push_back(createPattern(**iter));
00628 break;
00629 }
00630 }
00631 else if ( kind == ResTraits<zypp::Language>::kind )
00632 {
00633 XMLLanguageParser iter(res_file,"");
00634 for (; !iter.atEnd(); ++iter)
00635 {
00636 resolvables.push_back(createLanguage(**iter));
00637 break;
00638 }
00639 }
00640 else
00641 {
00642
00643 }
00644 return resolvables;
00645 }
00646
00647 std::list<ResObject::Ptr>
00648 XMLFilesBackend::storedObjects() const
00649 {
00650 DBG << std::endl;
00651 std::list<ResObject::Ptr> objects;
00652
00653 std::set<Resolvable::Kind>::const_iterator it_kinds;
00654 for ( it_kinds = d->kinds.begin() ; it_kinds != d->kinds.end(); ++it_kinds )
00655 {
00656 Resolvable::Kind kind = (*it_kinds);
00657 std::list<ResObject::Ptr> objects_for_kind = storedObjects(kind);
00658 std::list<ResObject::Ptr>::iterator it;
00659 for( it = objects_for_kind.begin(); it != objects_for_kind.end(); ++it)
00660 {
00661
00662 objects.push_back(*it);
00663 }
00664 }
00665 return objects;
00666 }
00667
00668 std::list<ResObject::Ptr>
00669 XMLFilesBackend::storedObjects(const Resolvable::Kind kind) const
00670 {
00671 std::list<ResObject::Ptr> objects;
00672 std::string dir_path = dirForResolvableKind(kind);
00673 DBG << "Reading objects of kind " << resolvableKindToString(kind) << " in " << dir_path << std::endl;
00674 directory_iterator end_iter;
00675
00676 if ( !exists( dir_path ) )
00677 {
00678 ERR << "path " << dir_path << " does not exists. Required to read objects of kind " << resolvableKindToString(kind) << std::endl;
00679 return std::list<ResObject::Ptr>();
00680 }
00681
00682 for ( directory_iterator dir_itr( dir_path ); dir_itr != end_iter; ++dir_itr )
00683 {
00684 DBG << "[" << resolvableKindToString( kind, false ) << "] - " << dir_itr->leaf() << std::endl;
00685 std::list<ResObject::Ptr> objects_for_file;
00686 objects_for_file = resolvablesFromFile( dir_path + "/" + dir_itr->leaf(), kind);
00687 for ( std::list<ResObject::Ptr>::iterator it = objects_for_file.begin(); it != objects_for_file.end(); ++it)
00688 objects.push_back(*it);
00689 }
00690 MIL << "done reading " << objects.size() << " stored objects for file of kind " << resolvableKindToString(kind) << std::endl;
00691 return objects;
00692 }
00693
00694 std::list<ResObject::Ptr>
00695 XMLFilesBackend::storedObjects(const Resolvable::Kind kind, const std::string & name, bool partial_match) const
00696 {
00697 std::list<ResObject::Ptr> result;
00698 std::list<ResObject::Ptr> all;
00699 all = storedObjects(kind);
00700 std::list<ResObject::Ptr>::const_iterator it;
00701 for( it = all.begin(); it != all.end(); ++it)
00702 {
00703 ResObject::Ptr item = *it;
00704 if (item->name() == name )
00705 result.push_back(item);
00706 }
00707 MIL << "done reading stored objects of kind " << resolvableKindToString(kind) << " and keyword [" << name <<"]" << std::endl;
00708 return result;
00709 }
00710
00711 Patch::Ptr
00712 XMLFilesBackend::createPatch( const zypp::parser::xmlstore::XMLPatchData & parsed ) const
00713 {
00714 try
00715 {
00716 detail::ResImplTraits<XMLPatchImpl>::Ptr impl(new XMLPatchImpl());
00717 impl->_patch_id = parsed.patchId;
00718 impl->_timestamp = str::strtonum<time_t>(parsed.timestamp);
00719 impl->_category = parsed.category;
00720 impl->_reboot_needed = parsed.rebootNeeded;
00721 impl->_affects_pkg_manager = parsed.packageManager;
00722
00723
00724 impl->_summary = parsed.summary;
00725 impl->_description = parsed.summary;
00726
00727 impl->_install_notify = parsed.install_notify;
00728 impl->_delete_notify = parsed.delete_notify;
00729 impl->_license_to_confirm = parsed.license_to_confirm;
00730 impl->_size = parsed.size;
00731 impl->_archive_size = parsed.archive_size;
00732 impl->_install_only = parsed.install_only;
00733 impl->_build_time = parsed.build_time;
00734 impl->_install_time = parsed.install_time;
00735
00736 Arch arch;
00737 if (!parsed.arch.empty())
00738 arch = Arch(parsed.arch);
00739
00740
00741 NVRAD dataCollect( parsed.name,
00742 Edition( parsed.ver, parsed.rel, parsed.epoch ), arch,
00743 createDependencies(parsed, ResTraits<Patch>::kind) );
00744 Patch::Ptr patch = detail::makeResolvableFromImpl( dataCollect, impl );
00745 CapFactory _f;
00746
00747
00748
00749
00750 ResObject::Ptr atom;
00751 for (std::list<XMLPatchAtomData_Ptr >::const_iterator it = parsed.atoms.begin(); it != parsed.atoms.end(); it++)
00752 {
00753 switch ((*it)->atomType())
00754 {
00755 case XMLPatchAtomData::Atom:
00756 {
00757
00758
00759
00760
00761
00762
00763
00764 XMLPatchAtomData_Ptr atom_data = dynamic_pointer_cast<XMLPatchAtomData>(*it);
00765 atom = createAtom(*atom_data);
00766 impl->_atoms.push_back(atom);
00767 break;
00768 }
00769 case XMLPatchAtomData::Message:
00770 {
00771 XMLPatchMessageData_Ptr message_data = dynamic_pointer_cast<XMLPatchMessageData>(*it);
00772 atom = createMessage(*message_data);
00773 impl->_atoms.push_back(atom);
00774 break;
00775 }
00776 case XMLPatchAtomData::Script:
00777 {
00778 XMLPatchScriptData_Ptr script_data = dynamic_pointer_cast<XMLPatchScriptData>(*it);
00779 atom = createScript(*script_data);
00780 impl->_atoms.push_back(atom);
00781 break;
00782 }
00783 default:
00784 ERR << "Unknown type of atom" << endl;
00785 }
00786
00787 Capability cap( _f.parse(atom->kind(), atom->name(), Rel::EQ, atom->edition() ));
00788 patch->injectRequires(cap);
00789 }
00790 return patch;
00791 }
00792 catch (const Exception & excpt_r)
00793 {
00794 ZYPP_CAUGHT(excpt_r);
00795 ZYPP_THROW(Exception("Cannot create patch object"));
00796 }
00797 return 0L;
00798 }
00799
00800 Atom::Ptr
00801 XMLFilesBackend::createAtom( const zypp::parser::xmlstore::XMLPatchAtomData & parsed ) const
00802 {
00803 try
00804 {
00805 detail::ResImplTraits<XMLAtomImpl>::Ptr impl(new XMLAtomImpl());
00806
00807 Arch arch;
00808 if (!parsed.arch.empty())
00809 arch = Arch(parsed.arch);
00810
00811
00812 NVRAD dataCollect( parsed.name, Edition( parsed.ver, parsed.rel, parsed.epoch ), arch, createDependencies(parsed, ResTraits<Atom>::kind) );
00813
00814 impl->_summary = parsed.summary;
00815 impl->_description = parsed.summary;
00816
00817 impl->_install_notify = parsed.install_notify;
00818 impl->_delete_notify = parsed.delete_notify;
00819 impl->_license_to_confirm = parsed.license_to_confirm;
00820 impl->_size = parsed.size;
00821 impl->_archive_size = parsed.archive_size;
00822 impl->_install_only = parsed.install_only;
00823 impl->_build_time = parsed.build_time;
00824 impl->_install_time = parsed.install_time;
00825
00826 Atom::Ptr atom = detail::makeResolvableFromImpl( dataCollect, impl);
00827 return atom;
00828 }
00829 catch (const Exception & excpt_r)
00830 {
00831 ZYPP_CAUGHT(excpt_r);
00832 ZYPP_THROW(Exception("Cannot create atom object"));
00833 }
00834 return 0L;
00835 }
00836
00837 Message::Ptr
00838 XMLFilesBackend::createMessage( const zypp::parser::xmlstore::XMLPatchMessageData & parsed ) const
00839 {
00840 try
00841 {
00842 detail::ResImplTraits<XMLMessageImpl>::Ptr impl(new XMLMessageImpl());
00843 impl->_text = parsed.text;
00844
00845 Arch arch;
00846 if (!parsed.arch.empty())
00847 arch = Arch(parsed.arch);
00848
00849 impl->_summary = parsed.summary;
00850 impl->_description = parsed.summary;
00851
00852 impl->_install_notify = parsed.install_notify;
00853 impl->_delete_notify = parsed.delete_notify;
00854 impl->_license_to_confirm = parsed.license_to_confirm;
00855 impl->_size = parsed.size;
00856 impl->_archive_size = parsed.archive_size;
00857 impl->_install_only = parsed.install_only;
00858 impl->_build_time = parsed.build_time;
00859 impl->_install_time = parsed.install_time;
00860
00861
00862 NVRAD dataCollect( parsed.name, Edition( parsed.ver, parsed.rel, parsed.epoch ), arch, createDependencies(parsed, ResTraits<Message>::kind) );
00863 Message::Ptr message = detail::makeResolvableFromImpl( dataCollect, impl);
00864 return message;
00865 }
00866 catch (const Exception & excpt_r)
00867 {
00868 ZYPP_CAUGHT(excpt_r);
00869 ZYPP_THROW(Exception("Cannot create message object"));
00870 }
00871 return 0L;
00872 }
00873
00874 Script::Ptr
00875 XMLFilesBackend::createScript(const zypp::parser::xmlstore::XMLPatchScriptData & parsed ) const
00876 {
00877 try
00878 {
00879 detail::ResImplTraits<XMLScriptImpl>::Ptr impl(new XMLScriptImpl());
00880
00881 ofstream file;
00882 file.open(impl->_do_script.path().asString().c_str());
00883 file << parsed.do_script;;
00884 file.close();
00885
00886 file.open(impl->_undo_script.path().asString().c_str());
00887 file << parsed.undo_script;;
00888 file.close();
00889
00890 Arch arch;
00891 if (!parsed.arch.empty())
00892 arch = Arch(parsed.arch);
00893
00894 impl->_summary = parsed.summary;
00895 impl->_description = parsed.summary;
00896
00897 impl->_install_notify = parsed.install_notify;
00898 impl->_delete_notify = parsed.delete_notify;
00899 impl->_license_to_confirm = parsed.license_to_confirm;
00900 impl->_size = parsed.size;
00901 impl->_archive_size = parsed.archive_size;
00902 impl->_install_only = parsed.install_only;
00903 impl->_build_time = parsed.build_time;
00904 impl->_install_time = parsed.install_time;
00905
00906
00907 NVRAD dataCollect( parsed.name, Edition( parsed.ver, parsed.rel, parsed.epoch ), arch, createDependencies(parsed, ResTraits<Script>::kind));
00908 Script::Ptr script = detail::makeResolvableFromImpl( dataCollect, impl );
00909 return script;
00910 }
00911 catch (const Exception & excpt_r)
00912 {
00913 ZYPP_CAUGHT(excpt_r);
00914 ZYPP_THROW(Exception("Cannot create script object"));
00915 }
00916 catch (const std::exception & excpt_r)
00917 {
00918 ERR << excpt_r.what() << endl;
00919 ZYPP_THROW(Exception("Cannot create script object"));
00920 }
00921 return 0L;
00922 }
00923
00924 Language::Ptr
00925 XMLFilesBackend::createLanguage( const zypp::parser::xmlstore::XMLLanguageData & parsed ) const
00926 {
00927 try
00928 {
00929 return Language::installedInstance( Locale(parsed.name) );
00930 }
00931 catch (const Exception & excpt_r)
00932 {
00933 ZYPP_CAUGHT(excpt_r);
00934 ZYPP_THROW(Exception("Cannot create language object"));
00935 }
00936 return 0L;
00937 }
00938
00939
00940 Product::Ptr
00941 XMLFilesBackend::createProduct( const zypp::parser::xmlstore::XMLProductData & parsed ) const
00942 {
00943 try
00944 {
00945 detail::ResImplTraits<XMLProductImpl>::Ptr impl(new XMLProductImpl());
00946
00947 impl->_summary = parsed.summary;
00948 impl->_description = parsed.summary;
00949
00950 impl->_install_notify = parsed.install_notify;
00951 impl->_delete_notify = parsed.delete_notify;
00952 impl->_license_to_confirm = parsed.license_to_confirm;
00953 impl->_size = parsed.size;
00954 impl->_archive_size = parsed.archive_size;
00955 impl->_install_only = parsed.install_only;
00956 impl->_build_time = parsed.build_time;
00957 impl->_install_time = parsed.install_time;
00958
00959 impl->_category = parsed.type;
00960 impl->_short_name = parsed.short_name;
00961
00962 if ( parsed.releasenotesurl.size() > 0 )
00963 impl->_release_notes_url = parsed.releasenotesurl;
00964 else
00965 impl->_release_notes_url = Url();
00966
00967
00968 std::list<std::string>::const_iterator
00969 b = parsed.update_urls.begin(),
00970 e = parsed.update_urls.end(),
00971 i;
00972 for (i = b; i != e; ++i) {
00973 Url u;
00974 try {
00975 u = *i;
00976 }
00977 catch (...) {
00978 }
00979 impl->_update_urls.push_back (u);
00980 }
00981
00982 impl->_flags = parsed.flags;
00983
00984 Arch arch;
00985 if (!parsed.arch.empty())
00986 arch = Arch(parsed.arch);
00987
00988
00989 NVRAD dataCollect( parsed.name, Edition( parsed.ver, parsed.rel, parsed.epoch ), arch, createDependencies(parsed, ResTraits<Product>::kind) );
00990 Product::Ptr product = detail::makeResolvableFromImpl( dataCollect, impl );
00991 return product;
00992 }
00993 catch (const Exception & excpt_r)
00994 {
00995 ZYPP_CAUGHT(excpt_r);
00996 ZYPP_THROW(Exception("Cannot create product object"));
00997 }
00998 return 0L;
00999 }
01000
01001 Pattern::Ptr
01002 XMLFilesBackend::createPattern( const zypp::parser::xmlstore::XMLPatternData & parsed ) const
01003 {
01004 try
01005 {
01006 detail::ResImplTraits<XMLPatternImpl>::Ptr impl(new XMLPatternImpl());
01007
01008 impl->_summary = parsed.summary;
01009 impl->_description = parsed.summary;
01010
01011 impl->_install_notify = parsed.install_notify;
01012 impl->_delete_notify = parsed.delete_notify;
01013 impl->_license_to_confirm = parsed.license_to_confirm;
01014 impl->_size = parsed.size;
01015 impl->_archive_size = parsed.archive_size;
01016 impl->_install_only = parsed.install_only;
01017 impl->_build_time = parsed.build_time;
01018 impl->_install_time = parsed.install_time;
01019
01020 impl->_user_visible = parsed.userVisible;
01021 impl->_default = ((parsed.default_ == "false" ) ? false : true );
01022 impl->_category = parsed.category;
01023 impl->_icon = parsed.icon;
01024 impl->_script = parsed.script;
01025
01026 Arch arch;
01027 if (!parsed.arch.empty())
01028 arch = Arch(parsed.arch);
01029
01030
01031 NVRAD dataCollect( parsed.name, Edition( parsed.ver, parsed.rel, parsed.epoch ), arch, createDependencies( parsed, ResTraits<Pattern>::kind));
01032 Pattern::Ptr pattern = detail::makeResolvableFromImpl( dataCollect, impl );
01033 return pattern;
01034 }
01035 catch (const Exception & excpt_r)
01036 {
01037 ZYPP_CAUGHT(excpt_r);
01038 ZYPP_THROW(Exception("Cannot create installation pattern object"));
01039 }
01040 return 0L;
01041 }
01042
01043 Selection::Ptr
01044 XMLFilesBackend::createSelection( const zypp::parser::xmlstore::XMLPatternData & parsed ) const
01045 {
01046 try
01047 {
01048 detail::ResImplTraits<XMLSelectionImpl>::Ptr impl(new XMLSelectionImpl());
01049
01050 impl->_summary = parsed.summary;
01051 impl->_description = parsed.summary;
01052
01053 impl->_install_notify = parsed.install_notify;
01054 impl->_delete_notify = parsed.delete_notify;
01055 impl->_license_to_confirm = parsed.license_to_confirm;
01056 impl->_size = parsed.size;
01057 impl->_archive_size = parsed.archive_size;
01058 impl->_install_only = parsed.install_only;
01059 impl->_build_time = parsed.build_time;
01060 impl->_install_time = parsed.install_time;
01061
01062 impl->_visible = parsed.userVisible;
01063 impl->_name = parsed.name;
01064
01065 impl->_category = parsed.category;
01066
01067 Arch arch;
01068 if (!parsed.arch.empty())
01069 arch = Arch(parsed.arch);
01070
01071
01072 NVRAD dataCollect( parsed.name, Edition( parsed.ver, parsed.rel, parsed.epoch ), arch, createDependencies( parsed, ResTraits<Pattern>::kind));
01073 Selection::Ptr selection = detail::makeResolvableFromImpl( dataCollect, impl );
01074 return selection;
01075 }
01076 catch (const Exception & excpt_r)
01077 {
01078 ZYPP_CAUGHT(excpt_r);
01079 ZYPP_THROW(Exception("Cannot create installation selection object"));
01080 }
01081 return 0L;
01082 }
01083
01084 Dependencies
01085 XMLFilesBackend::createDependencies( const zypp::parser::xmlstore::XMLResObjectData & parsed, const Resolvable::Kind my_kind ) const
01086 {
01087 Dependencies _deps;
01088 for (std::list<XMLDependency>::const_iterator it = parsed.provides.begin(); it != parsed.provides.end(); it++)
01089 {
01090 _deps[Dep::PROVIDES].insert(createCapability(*it, my_kind));
01091 }
01092 for (std::list<XMLDependency>::const_iterator it = parsed.conflicts.begin(); it != parsed.conflicts.end(); it++)
01093 {
01094 _deps[Dep::CONFLICTS].insert(createCapability(*it, my_kind));
01095 }
01096
01097 for (std::list<XMLDependency>::const_iterator it = parsed.obsoletes.begin(); it != parsed.obsoletes.end(); it++)
01098 {
01099 _deps[Dep::OBSOLETES].insert(createCapability(*it, my_kind));
01100 }
01101
01102 for (std::list<XMLDependency>::const_iterator it = parsed.freshens.begin(); it != parsed.freshens.end(); it++)
01103 {
01104 _deps[Dep::FRESHENS].insert(createCapability(*it, my_kind));
01105 }
01106
01107 for (std::list<XMLDependency>::const_iterator it = parsed.recommends.begin(); it != parsed.recommends.end(); it++)
01108 {
01109 _deps[Dep::RECOMMENDS].insert(createCapability(*it, my_kind));
01110 }
01111
01112 for (std::list<XMLDependency>::const_iterator it = parsed.suggests.begin(); it != parsed.suggests.end(); it++)
01113 {
01114 _deps[Dep::SUGGESTS].insert(createCapability(*it, my_kind));
01115 }
01116
01117 for (std::list<XMLDependency>::const_iterator it = parsed.enhances.begin(); it != parsed.enhances.end(); it++)
01118 {
01119 _deps[Dep::ENHANCES].insert(createCapability(*it, my_kind));
01120 }
01121
01122 for (std::list<XMLDependency>::const_iterator it = parsed.requires.begin(); it != parsed.requires.end(); it++)
01123 {
01124 _deps[Dep::REQUIRES].insert(createCapability(*it, my_kind));
01125 }
01126
01127 for (std::list<XMLDependency>::const_iterator it = parsed.prerequires.begin(); it != parsed.prerequires.end(); it++)
01128 {
01129 _deps[Dep::PREREQUIRES].insert(createCapability(*it, my_kind));
01130 }
01131 return _deps;
01132 }
01133
01134 Capability
01135 XMLFilesBackend::createCapability(const XMLDependency & dep, const Resolvable::Kind & my_kind) const
01136 {
01137 CapFactory _f;
01138 Resolvable::Kind _kind = dep.kind == "" ? my_kind : Resolvable::Kind(dep.kind);
01139 Capability cap;
01140 cap = _f.parse( _kind, dep.encoded );
01141 return cap;
01142 }
01143
01145
01146
01147
01148
01149 XMLFilesBackend::~XMLFilesBackend()
01150 {
01151 delete d;
01152 }
01153
01155
01156
01157
01158
01159 void XMLFilesBackend::doTest()
01160 {}
01161
01162
01163
01164
01165
01166
01167 std::ostream & operator<<( std::ostream & str, const XMLFilesBackend & obj )
01168 {
01169 return str;
01170 }
01171
01173
01175
01176 std::list<PersistentStorage::SourceData>
01177 XMLFilesBackend::storedSources() const
01178 {
01179 path source_p = path(d->root.asString()) / path(ZYPP_DB_DIR) / path ("sources");
01180 std::list<PersistentStorage::SourceData> sources;
01181 DBG << "Reading source cache in " << source_p.string() << std::endl;
01182 directory_iterator end_iter;
01183
01184 if ( !exists( source_p ) )
01185 {
01186 ERR << "path " << source_p.string() << " does not exists. Required to read source cache " << std::endl;
01187 return std::list<PersistentStorage::SourceData>();
01188 }
01189
01190 for ( directory_iterator dir_itr( source_p ); dir_itr != end_iter; ++dir_itr )
01191 {
01192 DBG << "[source-list] - " << dir_itr->leaf() << std::endl;
01193
01194 std::string full_path = (source_p / dir_itr->leaf()).string();
01195 std::ifstream anIstream(full_path.c_str());
01196 zypp::parser::xmlstore::XMLSourceCacheParser iter(anIstream, "");
01197 for (; ! iter.atEnd(); ++iter) {
01198 PersistentStorage::SourceData data = **iter;
01199 sources.push_back(data);
01200 }
01201 }
01202 MIL << "done reading source cache" << std::endl;
01203 return sources;
01204
01205 }
01206
01207 void
01208 XMLFilesBackend::storeSource(const PersistentStorage::SourceData &data)
01209 {
01210
01211 std::string xml = toXML(data);
01212 path source_p = path(d->root.asString()) / path(ZYPP_DB_DIR) / path ("sources");
01213
01214
01215 if (data.alias.size() == 0)
01216 {
01217 ZYPP_THROW(Exception("Cant save source with empty alias"));
01218 }
01219
01220
01221 std::ofstream file;
01222
01223 try
01224 {
01225 std::stringstream message_stream(data.alias);
01226 std::string full_path = (source_p / Digest::digest("MD5", message_stream)).string();
01227
01228 file.open(full_path.c_str());
01229 file << xml;
01230 file.close();
01231 }
01232 catch ( std::exception &e )
01233 {
01234 ERR << "Error saving source " << data.alias << " in the cache" << std::endl;
01235 ZYPP_THROW(Exception(e.what()));
01236 }
01237 }
01238
01239 void
01240 XMLFilesBackend::deleteSource(const std::string &alias)
01241 {
01242
01243 path source_p = path(d->root.asString()) / path(ZYPP_DB_DIR) / path ("sources");
01244 try
01245 {
01246 std::stringstream message_stream(alias);
01247 std::string full_path = (source_p / Digest::digest("MD5", message_stream)).string();
01248 remove(full_path);
01249 }
01250 catch ( std::exception &e )
01251 {
01252 ERR << "Error deleting source " << alias << " in the cache" << std::endl;
01253 ZYPP_THROW(Exception(e.what()));
01254 }
01255 }
01256
01258 }
01261 }