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
00884 if ( ! file )
00885 ZYPP_THROW(Exception(N_("Can't write the patch script to a temporary file.")));
00886
00887 file << parsed.do_script;;
00888 file.close();
00889
00890 file.open(impl->_undo_script->path().asString().c_str());
00891 if ( ! file )
00892 ZYPP_THROW(Exception(N_("Can't write the patch script to a temporary file.")));
00893
00894 file << parsed.undo_script;;
00895 file.close();
00896
00897 Arch arch;
00898 if (!parsed.arch.empty())
00899 arch = Arch(parsed.arch);
00900
00901 impl->_summary = parsed.summary;
00902 impl->_description = parsed.summary;
00903
00904 impl->_install_notify = parsed.install_notify;
00905 impl->_delete_notify = parsed.delete_notify;
00906 impl->_license_to_confirm = parsed.license_to_confirm;
00907 impl->_size = parsed.size;
00908 impl->_archive_size = parsed.archive_size;
00909 impl->_install_only = parsed.install_only;
00910 impl->_build_time = parsed.build_time;
00911 impl->_install_time = parsed.install_time;
00912
00913
00914 NVRAD dataCollect( parsed.name, Edition( parsed.ver, parsed.rel, parsed.epoch ), arch, createDependencies(parsed, ResTraits<Script>::kind));
00915 Script::Ptr script = detail::makeResolvableFromImpl( dataCollect, impl );
00916 return script;
00917 }
00918 catch (const Exception & excpt_r)
00919 {
00920 ZYPP_CAUGHT(excpt_r);
00921 ZYPP_THROW(Exception("Cannot create script object"));
00922 }
00923 catch (const std::exception & excpt_r)
00924 {
00925 ERR << excpt_r.what() << endl;
00926 ZYPP_THROW(Exception("Cannot create script object"));
00927 }
00928 return 0L;
00929 }
00930
00931 Language::Ptr
00932 XMLFilesBackend::createLanguage( const zypp::parser::xmlstore::XMLLanguageData & parsed ) const
00933 {
00934 try
00935 {
00936 return Language::installedInstance( Locale(parsed.name) );
00937 }
00938 catch (const Exception & excpt_r)
00939 {
00940 ZYPP_CAUGHT(excpt_r);
00941 ZYPP_THROW(Exception("Cannot create language object"));
00942 }
00943 return 0L;
00944 }
00945
00946
00947 Product::Ptr
00948 XMLFilesBackend::createProduct( const zypp::parser::xmlstore::XMLProductData & parsed ) const
00949 {
00950 try
00951 {
00952 detail::ResImplTraits<XMLProductImpl>::Ptr impl(new XMLProductImpl());
00953
00954 impl->_summary = parsed.summary;
00955 impl->_description = parsed.summary;
00956
00957 impl->_install_notify = parsed.install_notify;
00958 impl->_delete_notify = parsed.delete_notify;
00959 impl->_license_to_confirm = parsed.license_to_confirm;
00960 impl->_size = parsed.size;
00961 impl->_archive_size = parsed.archive_size;
00962 impl->_install_only = parsed.install_only;
00963 impl->_build_time = parsed.build_time;
00964 impl->_install_time = parsed.install_time;
00965
00966 impl->_category = parsed.type;
00967 impl->_short_name = parsed.short_name;
00968
00969 if ( parsed.releasenotesurl.size() > 0 )
00970 impl->_release_notes_url = parsed.releasenotesurl;
00971 else
00972 impl->_release_notes_url = Url();
00973
00974
00975 std::list<std::string>::const_iterator
00976 b = parsed.update_urls.begin(),
00977 e = parsed.update_urls.end(),
00978 i;
00979 for (i = b; i != e; ++i) {
00980 Url u;
00981 try {
00982 u = *i;
00983 }
00984 catch (...) {
00985 }
00986 impl->_update_urls.push_back (u);
00987 }
00988
00989 impl->_flags = parsed.flags;
00990
00991 Arch arch;
00992 if (!parsed.arch.empty())
00993 arch = Arch(parsed.arch);
00994
00995
00996 NVRAD dataCollect( parsed.name, Edition( parsed.ver, parsed.rel, parsed.epoch ), arch, createDependencies(parsed, ResTraits<Product>::kind) );
00997 Product::Ptr product = detail::makeResolvableFromImpl( dataCollect, impl );
00998 return product;
00999 }
01000 catch (const Exception & excpt_r)
01001 {
01002 ZYPP_CAUGHT(excpt_r);
01003 ZYPP_THROW(Exception("Cannot create product object"));
01004 }
01005 return 0L;
01006 }
01007
01008 Pattern::Ptr
01009 XMLFilesBackend::createPattern( const zypp::parser::xmlstore::XMLPatternData & parsed ) const
01010 {
01011 try
01012 {
01013 detail::ResImplTraits<XMLPatternImpl>::Ptr impl(new XMLPatternImpl());
01014
01015 impl->_summary = parsed.summary;
01016 impl->_description = parsed.summary;
01017
01018 impl->_install_notify = parsed.install_notify;
01019 impl->_delete_notify = parsed.delete_notify;
01020 impl->_license_to_confirm = parsed.license_to_confirm;
01021 impl->_size = parsed.size;
01022 impl->_archive_size = parsed.archive_size;
01023 impl->_install_only = parsed.install_only;
01024 impl->_build_time = parsed.build_time;
01025 impl->_install_time = parsed.install_time;
01026
01027 impl->_user_visible = parsed.userVisible;
01028 impl->_default = ((parsed.default_ == "false" ) ? false : true );
01029 impl->_category = parsed.category;
01030 impl->_icon = parsed.icon;
01031 impl->_script = parsed.script;
01032
01033 Arch arch;
01034 if (!parsed.arch.empty())
01035 arch = Arch(parsed.arch);
01036
01037
01038 NVRAD dataCollect( parsed.name, Edition( parsed.ver, parsed.rel, parsed.epoch ), arch, createDependencies( parsed, ResTraits<Pattern>::kind));
01039 Pattern::Ptr pattern = detail::makeResolvableFromImpl( dataCollect, impl );
01040 return pattern;
01041 }
01042 catch (const Exception & excpt_r)
01043 {
01044 ZYPP_CAUGHT(excpt_r);
01045 ZYPP_THROW(Exception("Cannot create installation pattern object"));
01046 }
01047 return 0L;
01048 }
01049
01050 Selection::Ptr
01051 XMLFilesBackend::createSelection( const zypp::parser::xmlstore::XMLPatternData & parsed ) const
01052 {
01053 try
01054 {
01055 detail::ResImplTraits<XMLSelectionImpl>::Ptr impl(new XMLSelectionImpl());
01056
01057 impl->_summary = parsed.summary;
01058 impl->_description = parsed.summary;
01059
01060 impl->_install_notify = parsed.install_notify;
01061 impl->_delete_notify = parsed.delete_notify;
01062 impl->_license_to_confirm = parsed.license_to_confirm;
01063 impl->_size = parsed.size;
01064 impl->_archive_size = parsed.archive_size;
01065 impl->_install_only = parsed.install_only;
01066 impl->_build_time = parsed.build_time;
01067 impl->_install_time = parsed.install_time;
01068
01069 impl->_visible = parsed.userVisible;
01070 impl->_name = parsed.name;
01071
01072 impl->_category = parsed.category;
01073
01074 Arch arch;
01075 if (!parsed.arch.empty())
01076 arch = Arch(parsed.arch);
01077
01078
01079 NVRAD dataCollect( parsed.name, Edition( parsed.ver, parsed.rel, parsed.epoch ), arch, createDependencies( parsed, ResTraits<Pattern>::kind));
01080 Selection::Ptr selection = detail::makeResolvableFromImpl( dataCollect, impl );
01081 return selection;
01082 }
01083 catch (const Exception & excpt_r)
01084 {
01085 ZYPP_CAUGHT(excpt_r);
01086 ZYPP_THROW(Exception("Cannot create installation selection object"));
01087 }
01088 return 0L;
01089 }
01090
01091 Dependencies
01092 XMLFilesBackend::createDependencies( const zypp::parser::xmlstore::XMLResObjectData & parsed, const Resolvable::Kind my_kind ) const
01093 {
01094 Dependencies _deps;
01095 for (std::list<XMLDependency>::const_iterator it = parsed.provides.begin(); it != parsed.provides.end(); it++)
01096 {
01097 _deps[Dep::PROVIDES].insert(createCapability(*it, my_kind));
01098 }
01099 for (std::list<XMLDependency>::const_iterator it = parsed.conflicts.begin(); it != parsed.conflicts.end(); it++)
01100 {
01101 _deps[Dep::CONFLICTS].insert(createCapability(*it, my_kind));
01102 }
01103
01104 for (std::list<XMLDependency>::const_iterator it = parsed.obsoletes.begin(); it != parsed.obsoletes.end(); it++)
01105 {
01106 _deps[Dep::OBSOLETES].insert(createCapability(*it, my_kind));
01107 }
01108
01109 for (std::list<XMLDependency>::const_iterator it = parsed.freshens.begin(); it != parsed.freshens.end(); it++)
01110 {
01111 _deps[Dep::FRESHENS].insert(createCapability(*it, my_kind));
01112 }
01113
01114 for (std::list<XMLDependency>::const_iterator it = parsed.recommends.begin(); it != parsed.recommends.end(); it++)
01115 {
01116 _deps[Dep::RECOMMENDS].insert(createCapability(*it, my_kind));
01117 }
01118
01119 for (std::list<XMLDependency>::const_iterator it = parsed.suggests.begin(); it != parsed.suggests.end(); it++)
01120 {
01121 _deps[Dep::SUGGESTS].insert(createCapability(*it, my_kind));
01122 }
01123
01124 for (std::list<XMLDependency>::const_iterator it = parsed.enhances.begin(); it != parsed.enhances.end(); it++)
01125 {
01126 _deps[Dep::ENHANCES].insert(createCapability(*it, my_kind));
01127 }
01128
01129 for (std::list<XMLDependency>::const_iterator it = parsed.requires.begin(); it != parsed.requires.end(); it++)
01130 {
01131 _deps[Dep::REQUIRES].insert(createCapability(*it, my_kind));
01132 }
01133
01134 for (std::list<XMLDependency>::const_iterator it = parsed.prerequires.begin(); it != parsed.prerequires.end(); it++)
01135 {
01136 _deps[Dep::PREREQUIRES].insert(createCapability(*it, my_kind));
01137 }
01138 return _deps;
01139 }
01140
01141 Capability
01142 XMLFilesBackend::createCapability(const XMLDependency & dep, const Resolvable::Kind & my_kind) const
01143 {
01144 CapFactory _f;
01145 Resolvable::Kind _kind = dep.kind == "" ? my_kind : Resolvable::Kind(dep.kind);
01146 Capability cap;
01147 cap = _f.parse( _kind, dep.encoded );
01148 return cap;
01149 }
01150
01152
01153
01154
01155
01156 XMLFilesBackend::~XMLFilesBackend()
01157 {
01158 delete d;
01159 }
01160
01162
01163
01164
01165
01166 void XMLFilesBackend::doTest()
01167 {}
01168
01169
01170
01171
01172
01173
01174 std::ostream & operator<<( std::ostream & str, const XMLFilesBackend & obj )
01175 {
01176 return str;
01177 }
01178
01180
01182
01183 std::list<PersistentStorage::SourceData>
01184 XMLFilesBackend::storedSources() const
01185 {
01186 path source_p = path(d->root.asString()) / path(ZYPP_DB_DIR) / path ("sources");
01187 std::list<PersistentStorage::SourceData> sources;
01188 DBG << "Reading source cache in " << source_p.string() << std::endl;
01189 directory_iterator end_iter;
01190
01191 if ( !exists( source_p ) )
01192 {
01193 ERR << "path " << source_p.string() << " does not exists. Required to read source cache " << std::endl;
01194 return std::list<PersistentStorage::SourceData>();
01195 }
01196
01197 for ( directory_iterator dir_itr( source_p ); dir_itr != end_iter; ++dir_itr )
01198 {
01199 DBG << "[source-list] - " << dir_itr->leaf() << std::endl;
01200
01201 std::string full_path = (source_p / dir_itr->leaf()).string();
01202 std::ifstream anIstream(full_path.c_str());
01203 zypp::parser::xmlstore::XMLSourceCacheParser iter(anIstream, "");
01204 for (; ! iter.atEnd(); ++iter) {
01205 PersistentStorage::SourceData data = **iter;
01206 sources.push_back(data);
01207 }
01208 }
01209 MIL << "done reading source cache" << std::endl;
01210 return sources;
01211
01212 }
01213
01214 void
01215 XMLFilesBackend::storeSource(const PersistentStorage::SourceData &data)
01216 {
01217
01218 std::string xml = toXML(data);
01219 path source_p = path(d->root.asString()) / path(ZYPP_DB_DIR) / path ("sources");
01220
01221
01222 if (data.alias.size() == 0)
01223 {
01224 ZYPP_THROW(Exception("Cant save source with empty alias"));
01225 }
01226
01227
01228 std::ofstream file;
01229
01230 try
01231 {
01232 std::stringstream message_stream(data.alias);
01233 std::string full_path = (source_p / Digest::digest("MD5", message_stream)).string();
01234
01235 file.open(full_path.c_str());
01236 file << xml;
01237 file.close();
01238 }
01239 catch ( std::exception &e )
01240 {
01241 ERR << "Error saving source " << data.alias << " in the cache" << std::endl;
01242 ZYPP_THROW(Exception(e.what()));
01243 }
01244 }
01245
01246 void
01247 XMLFilesBackend::deleteSource(const std::string &alias)
01248 {
01249
01250 path source_p = path(d->root.asString()) / path(ZYPP_DB_DIR) / path ("sources");
01251 try
01252 {
01253 std::stringstream message_stream(alias);
01254 std::string full_path = (source_p / Digest::digest("MD5", message_stream)).string();
01255 remove(full_path);
01256 }
01257 catch ( std::exception &e )
01258 {
01259 ERR << "Error deleting source " << alias << " in the cache" << std::endl;
01260 ZYPP_THROW(Exception(e.what()));
01261 }
01262 }
01263
01265 }
01268 }