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