libzypp
10.5.0
|
00001 /*---------------------------------------------------------------------\ 00002 | ____ _ __ __ ___ | 00003 | |__ / \ / / . \ . \ | 00004 | / / \ V /| _/ _/ | 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; /* offset of the next free block, 0 if none */ 00056 unsigned int freePrev; 00057 unsigned int isFree; 00058 00059 /* note that the u16's appear last for alignment/space reasons */ 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 /* is this file brand new? */ 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 /*@-refcounttrans@*/ return fd /*@=refcounttrans@*/ ; 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 /* Sanity check this to make sure we're not going in loops */ 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 /*@-boundsread@*/ 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 /*@=boundsread@*/ 00170 00171 /*@-bounds@*/ 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 * This assumes the file list is already sorted, and begins with a 00187 * single '/'. That assumption isn't critical, but it makes things go 00188 * a bit faster. 00189 */ 00190 00191 if (headerIsEntry(h, RPMTAG_DIRNAMES)) 00192 { 00193 xx = headerRemoveEntry(h, RPMTAG_OLDFILENAMES); 00194 return; /* Already converted. */ 00195 } 00196 00197 HGEPtr_t hgePtr = NULL; 00198 if (!headerGetEntryMinMemory(h, RPMTAG_OLDFILENAMES, hTYP_t(&fnt), &hgePtr, &count)) 00199 return; /* no file list */ 00200 fileNames = (char **)hgePtr; 00201 if (fileNames == NULL || count <= 0) 00202 return; 00203 00204 dirNames = (const char **)alloca(sizeof(*dirNames) * count); /* worst case */ 00205 baseNames = (const char **)alloca(sizeof(*dirNames) * count); 00206 dirIndexes = (int_32 *)alloca(sizeof(*dirIndexes) * count); 00207 00208 if (fileNames[0][0] != '/') 00209 { 00210 /* HACK. Source RPM, so just do things differently */ 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 /*@-branchstate@*/ 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) /* XXX can't happen */ 00230 continue; 00231 baseName = strrchr(fileNames[i], '/') + 1; 00232 len = baseName - fileNames[i]; 00233 needle = dirNames; 00234 savechar = *baseName; 00235 *baseName = '\0'; 00236 /*@-compdef@*/ 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 /*@=compdef@*/ 00249 00250 *baseName = savechar; 00251 baseNames[i] = baseName; 00252 } 00253 /*@=branchstate@*/ 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 /*@=bounds@*/ 00270 00271 /* 00272 * Up to rpm 3.0.4, packages implicitly provided their own name-version-release. 00273 * Retrofit an explicit "Provides: name = epoch:version-release". 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 /* Generate provides for this package name-version-release. */ 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 * Rpm prior to 3.0.3 does not have versioned provides. 00308 * If no provides at all are available, we can just add. 00309 */ 00310 if (!headerGetEntryMinMemory(h, RPMTAG_PROVIDENAME, hTYP_t(&pnt), &hgePtr, &providesCount)) 00311 goto exit; 00312 provides = (const char **)hgePtr; 00313 00314 /* 00315 * Otherwise, fill in entries on legacy packages. 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 /*@-nullderef@*/ /* LCL: providesEVR is not NULL */ 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 /*@=nullderef@*/ 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 * This assumes the file list is already sorted, and begins with a 00376 * single '/'. That assumption isn't critical, but it makes things go 00377 * a bit faster. 00378 */ 00379 00380 if (headerIsEntry(h, RPMTAG_DIRNAMES)) { 00381 xx = headerDel(h, RPMTAG_OLDFILENAMES); 00382 return; /* Already converted. */ 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); /* worst case */ 00392 baseNames = (const char**)malloc(sizeof(*dirNames) * count); 00393 dirIndexes = (uint32_t*)malloc(sizeof(*dirIndexes) * count); 00394 00395 /* HACK. Source RPM, so just do things differently */ 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) /* XXX can't happen */ 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 * Up to rpm 3.0.4, packages implicitly provided their own name-version-release. 00456 * Retrofit an explicit "Provides: name = epoch:version-release. 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 /* Generate provides for this package name-version-release. */ 00468 pEVR = headerGetEVR(h, &name); 00469 if (!(name && pEVR)) 00470 return; 00471 00472 /* 00473 * Rpm prior to 3.0.3 does not have versioned provides. 00474 * If no provides at all are available, we can just add. 00475 */ 00476 if (!headerGet(h, RPMTAG_PROVIDENAME, &pnames, HEADERGET_MINMEM)) { 00477 goto exit; 00478 } 00479 00480 /* 00481 * Otherwise, fill in entries on legacy packages. 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 /* see if we already have this provide */ 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 ** FUNCTION NAME : internal_convertV3toV4 00529 ** FUNCTION TYPE : int 00530 */ 00531 void internal_convertV3toV4( const Pathname & v3db_r, const librpmDb::constPtr & v4db_r, 00532 callback::SendReport<ConvertDBReport> & report ) 00533 { 00534 // Timecount _t( "convert V3 to V4" ); 00535 MIL << "Convert rpm3 database to rpm4" << endl; 00536 00537 // Check arguments 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 // open rpmV4 database for writing. v4db_r is ok so librpm should 00561 // be properly initialized. 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 // Check ammount of packages to process. 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 // Start conversion. 00598 #warning Add CBSuggest handling if needed, also on lines below 00599 // CBSuggest proceed; 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 // have to use lseek instead of Fseek because headerRead 00607 // uses low level IO 00608 if ( lseek( Fileno( fd ), (off_t)offset, SEEK_SET ) == -1 ) 00609 { 00610 ostream * reportAs = &(ERR); 00611 /* proceed = report->dbReadError( offset ); 00612 if ( proceed == CBSuggest::SKIP ) { 00613 // ignore this error 00614 ++ignored; 00615 reportAs = &(WAR << "IGNORED: "); 00616 } else {*/ 00617 // PROCEED will fail after conversion; CANCEL immediately stop loop 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 /* proceed = report->dbReadError( offset ); 00628 if ( proceed == CBSuggest::SKIP ) { 00629 // ignore this error 00630 ++ignored; 00631 reportAs = &(WAR << "IGNORED: "); 00632 } else {*/ 00633 // PROCEED will fail after conversion; CANCEL immediately stop loop 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 // report.dbInV4( nrv ); 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 // report.dbWriteError( nrv ); 00666 proceed = false;//CBSuggest::CANCEL; // immediately stop loop 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 * FUNCTION NAME : convertV3toV4 00724 * 00725 * \throws RpmException 00726 * 00727 */ 00728 void convertV3toV4( const Pathname & v3db_r, const librpmDb::constPtr & v4db_r ) 00729 { 00730 // report 00731 callback::SendReport<ConvertDBReport> report; 00732 report->start(v3db_r); 00733 try 00734 { 00735 // Does no longer work with rpm 4.9. 00736 // internal_convertV3toV4( v3db_r, v4db_r, report ); 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 } // namespace rpm 00749 } // namespace target 00750 } // namespace zypp