00001
00002
00003
00004
00005
00006
00007
00008
00012 #if 0
00013 #include "librpm.h"
00014 extern "C"
00015 {
00016 #ifdef _RPM_5
00017 typedef rpmuint32_t rpm_count_t;
00018 #define HGEPtr_t void *
00019 #define headerGetEntryMinMemory headerGetEntry
00020 #define headerNVR(h,n,v,r) headerNEVRA(h,n,NULL,v,r,NULL)
00021 #else
00022 #ifdef _RPM_4_4
00023 typedef int32_t rpm_count_t;
00024 #define HGEPtr_t const void *
00025 #endif
00026 #endif
00027 }
00028
00029 #include <iostream>
00030
00031 #include "zypp/base/Logger.h"
00032
00033 #include "zypp/target/rpm/librpmDb.h"
00034 #include "zypp/target/rpm/RpmCallbacks.h"
00035 #include "zypp/ZYppCallbacks.h"
00036
00037 #define xmalloc malloc
00038 #define xstrdup strdup
00039
00040 extern "C"
00041 {
00042 #include <string.h>
00043
00044 #define FA_MAGIC 0x02050920
00045
00046 struct faFileHeader
00047 {
00048 unsigned int magic;
00049 unsigned int firstFree;
00050 };
00051
00052 struct faHeader
00053 {
00054 unsigned int size;
00055 unsigned int freeNext;
00056 unsigned int freePrev;
00057 unsigned int isFree;
00058
00059
00060 };
00061 }
00062
00063 namespace zypp
00064 {
00065 namespace target
00066 {
00067 namespace rpm
00068 {
00069 static int fadFileSize;
00070
00071 static ssize_t Pread(FD_t fd, void * buf, size_t count, off_t offset)
00072 {
00073 if (Fseek(fd, offset, SEEK_SET) < 0)
00074 return -1;
00075 return Fread(buf, sizeof(char), count, fd);
00076 }
00077
00078 static FD_t fadOpen(const char * path)
00079 {
00080 struct faFileHeader newHdr;
00081 FD_t fd;
00082 struct stat stb;
00083
00084 fd = Fopen(path, "r.fdio");
00085 if (!fd || Ferror(fd))
00086 return NULL;
00087
00088 if (fstat(Fileno(fd), &stb))
00089 {
00090 Fclose(fd);
00091 return NULL;
00092 }
00093 fadFileSize = stb.st_size;
00094
00095
00096 if (fadFileSize == 0)
00097 {
00098 Fclose(fd);
00099 return NULL;
00100 }
00101 if (Pread(fd, &newHdr, sizeof(newHdr), 0) != sizeof(newHdr))
00102 {
00103 Fclose(fd);
00104 return NULL;
00105 }
00106 if (newHdr.magic != FA_MAGIC)
00107 {
00108 Fclose(fd);
00109 return NULL;
00110 }
00111 return fd ;
00112 }
00113
00114 static int fadNextOffset(FD_t fd, unsigned int lastOffset)
00115 {
00116 struct faHeader header;
00117 int offset;
00118
00119 offset = (lastOffset)
00120 ? (lastOffset - sizeof(header))
00121 : sizeof(struct faFileHeader);
00122
00123 if (offset >= fadFileSize)
00124 return 0;
00125
00126 if (Pread(fd, &header, sizeof(header), offset) != sizeof(header))
00127 return 0;
00128
00129 if (!lastOffset && !header.isFree)
00130 return (offset + sizeof(header));
00131
00132 do
00133 {
00134 offset += header.size;
00135
00136 if (Pread(fd, &header, sizeof(header), offset) != sizeof(header))
00137 return 0;
00138
00139 if (!header.isFree) break;
00140 }
00141 while (offset < fadFileSize && header.isFree);
00142
00143 if (offset < fadFileSize)
00144 {
00145
00146 offset += sizeof(header);
00147
00148 if (offset < 0 || (unsigned)offset <= lastOffset) return -1;
00149
00150 return offset;
00151 }
00152 else
00153 return 0;
00154 }
00155
00156 static int fadFirstOffset(FD_t fd)
00157 {
00158 return fadNextOffset(fd, 0);
00159 }
00160
00161
00162 static int dncmp(const void * a, const void * b)
00163
00164 {
00165 const char *const * first = (const char *const *)a;
00166 const char *const * second = (const char *const *)b;
00167 return strcmp(*first, *second);
00168 }
00169
00170
00171
00172 #ifndef _RPM_4_X
00173 static void compressFilelist(Header h)
00174
00175 {
00176 char ** fileNames;
00177 const char ** dirNames;
00178 const char ** baseNames;
00179 int_32 * dirIndexes;
00180 rpmTagType fnt;
00181 rpm_count_t count;
00182 int xx;
00183 int dirIndex = -1;
00184
00185
00186
00187
00188
00189
00190
00191 if (headerIsEntry(h, RPMTAG_DIRNAMES))
00192 {
00193 xx = headerRemoveEntry(h, RPMTAG_OLDFILENAMES);
00194 return;
00195 }
00196
00197 HGEPtr_t hgePtr = NULL;
00198 if (!headerGetEntryMinMemory(h, RPMTAG_OLDFILENAMES, hTYP_t(&fnt), &hgePtr, &count))
00199 return;
00200 fileNames = (char **)hgePtr;
00201 if (fileNames == NULL || count <= 0)
00202 return;
00203
00204 dirNames = (const char **)alloca(sizeof(*dirNames) * count);
00205 baseNames = (const char **)alloca(sizeof(*dirNames) * count);
00206 dirIndexes = (int_32 *)alloca(sizeof(*dirIndexes) * count);
00207
00208 if (fileNames[0][0] != '/')
00209 {
00210
00211 dirIndex = 0;
00212 dirNames[dirIndex] = "";
00213 for (rpm_count_t i = 0; i < count; i++)
00214 {
00215 dirIndexes[i] = dirIndex;
00216 baseNames[i] = fileNames[i];
00217 }
00218 goto exit;
00219 }
00220
00221
00222 for (rpm_count_t i = 0; i < count; i++)
00223 {
00224 const char ** needle;
00225 char savechar;
00226 char * baseName;
00227 int len;
00228
00229 if (fileNames[i] == NULL)
00230 continue;
00231 baseName = strrchr(fileNames[i], '/') + 1;
00232 len = baseName - fileNames[i];
00233 needle = dirNames;
00234 savechar = *baseName;
00235 *baseName = '\0';
00236
00237 if (dirIndex < 0 ||
00238 (needle = (const char **)bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL)
00239 {
00240 char *s = (char *)alloca(len + 1);
00241 memcpy(s, fileNames[i], len + 1);
00242 s[len] = '\0';
00243 dirIndexes[i] = ++dirIndex;
00244 dirNames[dirIndex] = s;
00245 }
00246 else
00247 dirIndexes[i] = needle - dirNames;
00248
00249
00250 *baseName = savechar;
00251 baseNames[i] = baseName;
00252 }
00253
00254
00255 exit:
00256 if (count > 0)
00257 {
00258 xx = headerAddEntry(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
00259 xx = headerAddEntry(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
00260 baseNames, count);
00261 xx = headerAddEntry(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
00262 dirNames, dirIndex + 1);
00263 }
00264
00265 fileNames = (char**)headerFreeData(fileNames, fnt);
00266
00267 xx = headerRemoveEntry(h, RPMTAG_OLDFILENAMES);
00268 }
00269
00270
00271
00272
00273
00274
00275 void providePackageNVR(Header h)
00276 {
00277 const char *name, *version, *release;
00278 HGEPtr_t hgePtr = NULL;
00279 int_32 * epoch;
00280 const char *pEVR;
00281 char *p;
00282 int_32 pFlags = RPMSENSE_EQUAL;
00283 const char ** provides = NULL;
00284 const char ** providesEVR = NULL;
00285 rpmTagType pnt, pvt;
00286 int_32 * provideFlags = NULL;
00287 rpm_count_t providesCount;
00288 int xx;
00289 int bingo = 1;
00290
00291
00292 xx = headerNVR(h, &name, &version, &release);
00293 if (!(name && version && release))
00294 return;
00295 pEVR = p = (char *)alloca(21 + strlen(version) + 1 + strlen(release) + 1);
00296 *p = '\0';
00297 if (headerGetEntryMinMemory(h, RPMTAG_EPOCH, NULL, &hgePtr, NULL))
00298 {
00299 epoch = (int_32 *)hgePtr;
00300 sprintf(p, "%d:", *epoch);
00301 while (*p != '\0')
00302 p++;
00303 }
00304 (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
00305
00306
00307
00308
00309
00310 if (!headerGetEntryMinMemory(h, RPMTAG_PROVIDENAME, hTYP_t(&pnt), &hgePtr, &providesCount))
00311 goto exit;
00312 provides = (const char **)hgePtr;
00313
00314
00315
00316
00317 if (!headerGetEntryMinMemory(h, RPMTAG_PROVIDEVERSION, hTYP_t(&pvt), &hgePtr, NULL))
00318 {
00319 providesEVR = (const char **)hgePtr;
00320 for (rpm_count_t i = 0; i < providesCount; i++)
00321 {
00322 const char * vdummy = "";
00323 int_32 fdummy = RPMSENSE_ANY;
00324 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
00325 &vdummy, 1);
00326 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
00327 &fdummy, 1);
00328 }
00329 goto exit;
00330 }
00331
00332 xx = headerGetEntryMinMemory(h, RPMTAG_PROVIDEFLAGS, NULL, &hgePtr, NULL);
00333 provideFlags = (int_32 *)hgePtr;
00334
00335
00336 if (provides && providesEVR && provideFlags)
00337 for (rpm_count_t i = 0; i < providesCount; i++)
00338 {
00339 if (!(provides[i] && providesEVR[i]))
00340 continue;
00341 if (!(provideFlags[i] == RPMSENSE_EQUAL &&
00342 !strcmp(name, provides[i]) && !strcmp(pEVR, providesEVR[i])))
00343 continue;
00344 bingo = 0;
00345 break;
00346 }
00347
00348
00349 exit:
00350 provides = (const char **)headerFreeData(provides, pnt);
00351 providesEVR = (const char **)headerFreeData(providesEVR, pvt);
00352
00353 if (bingo)
00354 {
00355 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE,
00356 &name, 1);
00357 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
00358 &pFlags, 1);
00359 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
00360 &pEVR, 1);
00361 }
00362 }
00363 #else
00364 static void compressFilelist(Header h)
00365 {
00366 struct rpmtd_s fileNames;
00367 char ** dirNames;
00368 const char ** baseNames;
00369 uint32_t * dirIndexes;
00370 rpm_count_t count;
00371 int xx, i;
00372 int dirIndex = -1;
00373
00374
00375
00376
00377
00378
00379
00380 if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
00381 xx = headerDel(h, RPMTAG_OLDFILENAMES);
00382 return;
00383 }
00384
00385 if (!headerGet(h, RPMTAG_OLDFILENAMES, &fileNames, HEADERGET_MINMEM))
00386 return;
00387 count = rpmtdCount(&fileNames);
00388 if (count < 1)
00389 return;
00390
00391 dirNames = (char**)malloc(sizeof(*dirNames) * count);
00392 baseNames = (const char**)malloc(sizeof(*dirNames) * count);
00393 dirIndexes = (uint32_t*)malloc(sizeof(*dirIndexes) * count);
00394
00395
00396 { const char *fn = rpmtdGetString(&fileNames);
00397 if (fn && *fn != '/') {
00398 dirIndex = 0;
00399 dirNames[dirIndex] = xstrdup("");
00400 while ((i = rpmtdNext(&fileNames)) >= 0) {
00401 dirIndexes[i] = dirIndex;
00402 baseNames[i] = rpmtdGetString(&fileNames);
00403 }
00404 goto exit;
00405 }
00406 }
00407
00408 while ((i = rpmtdNext(&fileNames)) >= 0) {
00409 char ** needle;
00410 char savechar;
00411 char * baseName;
00412 size_t len;
00413 const char *filename = rpmtdGetString(&fileNames);
00414
00415 if (filename == NULL)
00416 continue;
00417 baseName = strrchr((char*)filename, '/') + 1;
00418 len = baseName - filename;
00419 needle = dirNames;
00420 savechar = *baseName;
00421 *baseName = '\0';
00422 if (dirIndex < 0 ||
00423 (needle = (char**)bsearch(&filename, dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
00424 char *s = (char*)malloc(len + 1);
00425 rstrlcpy(s, filename, len + 1);
00426 dirIndexes[i] = ++dirIndex;
00427 dirNames[dirIndex] = s;
00428 } else
00429 dirIndexes[i] = needle - dirNames;
00430
00431 *baseName = savechar;
00432 baseNames[i] = baseName;
00433 }
00434
00435 exit:
00436 if (count > 0) {
00437 headerPutUint32(h, RPMTAG_DIRINDEXES, dirIndexes, count);
00438 headerPutStringArray(h, RPMTAG_BASENAMES, baseNames, count);
00439 headerPutStringArray(h, RPMTAG_DIRNAMES,
00440 (const char **) dirNames, dirIndex + 1);
00441 }
00442
00443 rpmtdFreeData(&fileNames);
00444 for (i = 0; i <= dirIndex; i++) {
00445 free(dirNames[i]);
00446 }
00447 free(dirNames);
00448 free(baseNames);
00449 free(dirIndexes);
00450
00451 xx = headerDel(h, RPMTAG_OLDFILENAMES);
00452 }
00453
00454
00455
00456
00457
00458 static void providePackageNVR(Header h)
00459 {
00460 const char *name;
00461 char *pEVR;
00462 rpmsenseFlags pFlags = RPMSENSE_EQUAL;
00463 int bingo = 1;
00464 struct rpmtd_s pnames;
00465 rpmds hds, nvrds;
00466
00467
00468 pEVR = headerGetEVR(h, &name);
00469 if (!(name && pEVR))
00470 return;
00471
00472
00473
00474
00475
00476 if (!headerGet(h, RPMTAG_PROVIDENAME, &pnames, HEADERGET_MINMEM)) {
00477 goto exit;
00478 }
00479
00480
00481
00482
00483 if (!headerIsEntry(h, RPMTAG_PROVIDEVERSION)) {
00484 while (rpmtdNext(&pnames) >= 0) {
00485 uint32_t fdummy = RPMSENSE_ANY;
00486
00487 headerPutString(h, RPMTAG_PROVIDEVERSION, "");
00488 headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &fdummy, 1);
00489 }
00490 goto exit;
00491 }
00492
00493
00494 hds = rpmdsNew(h, RPMTAG_PROVIDENAME, 0);
00495 nvrds = rpmdsSingle(RPMTAG_PROVIDENAME, name, pEVR, pFlags);
00496 if (rpmdsFind(hds, nvrds) >= 0) {
00497 bingo = 0;
00498 }
00499 rpmdsFree(hds);
00500 rpmdsFree(nvrds);
00501
00502 exit:
00503 if (bingo) {
00504 const char *evr = pEVR;
00505 uint32_t fdummy = pFlags;
00506 headerPutString(h, RPMTAG_PROVIDENAME, name);
00507 headerPutString(h, RPMTAG_PROVIDEVERSION, evr);
00508 headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &fdummy, 1);
00509 }
00510 rpmtdFreeData(&pnames);
00511 free(pEVR);
00512 }
00513
00514 #endif
00515
00519
00520 using namespace std;
00521
00522 #undef Y2LOG
00523 #define Y2LOG "librpmDb"
00524
00525
00526
00527
00528
00529
00530
00531 void internal_convertV3toV4( const Pathname & v3db_r, const librpmDb::constPtr & v4db_r,
00532 callback::SendReport<ConvertDBReport> & report )
00533 {
00534
00535 MIL << "Convert rpm3 database to rpm4" << endl;
00536
00537
00538 FD_t fd = fadOpen( v3db_r.asString().c_str() );
00539 if ( fd == 0 )
00540 {
00541 Fclose( fd );
00542 ZYPP_THROW(RpmDbOpenException(Pathname("/"), v3db_r));
00543 }
00544
00545 if ( ! v4db_r )
00546 {
00547 Fclose( fd );
00548 INT << "NULL rpmV4 database passed as argument!" << endl;
00549 ZYPP_THROW(RpmNullDatabaseException());
00550 }
00551
00552 shared_ptr<RpmException> err = v4db_r->error();
00553 if ( err )
00554 {
00555 Fclose( fd );
00556 INT << "Can't access rpmV4 database " << v4db_r << endl;
00557 ZYPP_THROW(*err);
00558 }
00559
00560
00561
00562 rpmdb db = 0;
00563 string rootstr( v4db_r->root().asString() );
00564 const char * root = ( rootstr == "/" ? NULL : rootstr.c_str() );
00565
00566 int res = ::rpmdbOpen( root, &db, O_RDWR, 0644 );
00567 if ( res || ! db )
00568 {
00569 if ( db )
00570 {
00571 ::rpmdbClose( db );
00572 }
00573 Fclose( fd );
00574 ZYPP_THROW(RpmDbOpenException(root, v4db_r->dbPath()));
00575 }
00576
00577
00578 int max = 0;
00579 for ( int offset = fadFirstOffset(fd); offset; offset = fadNextOffset(fd, offset) )
00580 {
00581 ++max;
00582 }
00583 MIL << "Packages in rpmV3 database " << v3db_r << ": " << max << endl;
00584
00585 unsigned failed = 0;
00586 unsigned ignored = 0;
00587 unsigned alreadyInV4 = 0;
00588 report->progress( (100 * (failed + ignored + alreadyInV4) / max), v3db_r );
00589
00590 if ( !max )
00591 {
00592 Fclose( fd );
00593 ::rpmdbClose( db );
00594 return;
00595 }
00596
00597
00598 #warning Add CBSuggest handling if needed, also on lines below
00599
00600 bool proceed = true;
00601 for ( int offset = fadFirstOffset(fd); offset && proceed ;
00602 offset = fadNextOffset(fd, offset),
00603 report->progress( (100 * (failed + ignored + alreadyInV4) / max), v3db_r ) )
00604 {
00605
00606
00607
00608 if ( lseek( Fileno( fd ), (off_t)offset, SEEK_SET ) == -1 )
00609 {
00610 ostream * reportAs = &(ERR);
00611
00612
00613
00614
00615
00616
00617
00618 ++failed;
00619
00620 (*reportAs) << "rpmV3 database entry: Can't seek to offset " << offset << " (errno " << errno << ")" << endl;
00621 continue;
00622 }
00623 Header h = headerRead(fd, HEADER_MAGIC_NO);
00624 if ( ! h )
00625 {
00626 ostream * reportAs = &(ERR);
00627
00628
00629
00630
00631
00632
00633
00634 ++failed;
00635
00636 (*reportAs) << "rpmV3 database entry: No header at offset " << offset << endl;
00637 continue;
00638 }
00639 compressFilelist(h);
00640 providePackageNVR(h);
00641 const char *name = 0;
00642 const char *version = 0;
00643 const char *release = 0;
00644 headerNVR(h, &name, &version, &release);
00645 string nrv( string(name) + "-" + version + "-" + release );
00646 rpmdbMatchIterator mi = rpmdbInitIterator(db, RPMTAG_NAME, name, 0);
00647 rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_DEFAULT, version);
00648 rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_DEFAULT, release);
00649 if (rpmdbNextIterator(mi))
00650 {
00651
00652 WAR << "SKIP: rpmV3 database entry: " << nrv << " is already in rpmV4 database" << endl;
00653 rpmdbFreeIterator(mi);
00654 headerFree(h);
00655 ++alreadyInV4;
00656 continue;
00657 }
00658 rpmdbFreeIterator(mi);
00659 #ifdef _RPM_5
00660 if (rpmdbAdd(db, -1, h, 0))
00661 #else
00662 if (rpmdbAdd(db, -1, h, 0, 0))
00663 #endif
00664 {
00665
00666 proceed = false;
00667 ++failed;
00668 ERR << "rpmV4 database error: could not add " << nrv << " to rpmV4 database" << endl;
00669 headerFree(h);
00670 continue;
00671 }
00672 headerFree(h);
00673 }
00674
00675 Fclose(fd);
00676 ::rpmdbClose(db);
00677
00678 if ( failed )
00679 {
00680 ERR << "Convert rpm3 database to rpm4: Aborted after "
00681 << alreadyInV4 << " package(s) and " << (failed+ignored) << " error(s)."
00682 << endl;
00683 ZYPP_THROW(RpmDbConvertException());
00684 }
00685 else
00686 {
00687 MIL << "Convert rpm3 database to rpm4: " << max << " package(s) processed";
00688 if ( alreadyInV4 )
00689 {
00690 MIL << "; " << alreadyInV4 << " already present in rpmV4 database";
00691 }
00692 if ( ignored )
00693 {
00694 MIL << "; IGNORED: " << ignored << " unconverted due to error";
00695 }
00696 MIL << endl;
00697 }
00698 }
00699 #endif
00700
00701 #include <iostream>
00702
00703 #include "zypp/base/Logger.h"
00704
00705 #include "zypp/target/rpm/librpmDb.h"
00706 #include "zypp/target/rpm/RpmCallbacks.h"
00707 #include "zypp/ZYppCallbacks.h"
00708
00709 using namespace std;
00710
00711 #undef Y2LOG
00712 #define Y2LOG "librpmDb"
00713
00714 namespace zypp
00715 {
00716 namespace target
00717 {
00718 namespace rpm
00719 {
00720
00721
00722
00723
00724
00725
00726
00727
00728 void convertV3toV4( const Pathname & v3db_r, const librpmDb::constPtr & v4db_r )
00729 {
00730
00731 callback::SendReport<ConvertDBReport> report;
00732 report->start(v3db_r);
00733 try
00734 {
00735
00736
00737 INT << "Unsupported: Convert rpm3 database to rpm4" << endl;
00738 ZYPP_THROW(RpmDbOpenException(Pathname("/"), v3db_r));
00739 }
00740 catch (RpmException & excpt_r)
00741 {
00742 report->finish(v3db_r, ConvertDBReport::FAILED,excpt_r.asUserString());
00743 ZYPP_RETHROW(excpt_r);
00744 }
00745 report->finish(v3db_r, ConvertDBReport::NO_ERROR, "");
00746 }
00747
00748 }
00749 }
00750 }