17 typedef rpmuint32_t rpm_count_t;
18 #define HGEPtr_t void *
19 #define headerGetEntryMinMemory headerGetEntry
20 #define headerNVR(h,n,v,r) headerNEVRA(h,n,NULL,v,r,NULL)
23 typedef int32_t rpm_count_t;
24 #define HGEPtr_t const void *
37 #define xmalloc malloc
38 #define xstrdup strdup
44 #define FA_MAGIC 0x02050920
49 unsigned int firstFree;
55 unsigned int freeNext;
56 unsigned int freePrev;
69 static int fadFileSize;
71 static ssize_t Pread(FD_t fd,
void * buf,
size_t count, off_t offset)
73 if (Fseek(fd, offset, SEEK_SET) < 0)
75 return Fread(buf,
sizeof(
char), count, fd);
78 static FD_t fadOpen(
const char * path)
80 struct faFileHeader newHdr;
84 fd = Fopen(path,
"r.fdio");
85 if (!fd || Ferror(fd))
88 if (fstat(Fileno(fd), &stb))
93 fadFileSize = stb.st_size;
101 if (Pread(fd, &newHdr,
sizeof(newHdr), 0) !=
sizeof(newHdr))
106 if (newHdr.magic != FA_MAGIC)
114 static int fadNextOffset(FD_t fd,
unsigned int lastOffset)
116 struct faHeader header;
119 offset = (lastOffset)
120 ? (lastOffset -
sizeof(header))
121 :
sizeof(
struct faFileHeader);
123 if (offset >= fadFileSize)
126 if (Pread(fd, &header,
sizeof(header), offset) !=
sizeof(header))
129 if (!lastOffset && !header.isFree)
130 return (offset +
sizeof(header));
134 offset += header.size;
136 if (Pread(fd, &header,
sizeof(header), offset) !=
sizeof(header))
139 if (!header.isFree)
break;
141 while (offset < fadFileSize && header.isFree);
143 if (offset < fadFileSize)
146 offset +=
sizeof(header);
148 if (offset < 0 || (
unsigned)offset <= lastOffset)
return -1;
156 static int fadFirstOffset(FD_t fd)
158 return fadNextOffset(fd, 0);
162 static int dncmp(
const void * a,
const void * b)
165 const char *
const * first = (
const char *
const *)a;
166 const char *
const * second = (
const char *
const *)b;
167 return strcmp(*first, *second);
173 static void compressFilelist(Header h)
177 const char ** dirNames;
178 const char ** baseNames;
191 if (headerIsEntry(h, RPMTAG_DIRNAMES))
193 xx = headerRemoveEntry(h, RPMTAG_OLDFILENAMES);
197 HGEPtr_t hgePtr = NULL;
198 if (!headerGetEntryMinMemory(h, RPMTAG_OLDFILENAMES, hTYP_t(&fnt), &hgePtr, &count))
200 fileNames = (
char **)hgePtr;
201 if (fileNames == NULL || count <= 0)
204 dirNames = (
const char **)alloca(
sizeof(*dirNames) * count);
205 baseNames = (
const char **)alloca(
sizeof(*dirNames) * count);
206 dirIndexes = (int_32 *)alloca(
sizeof(*dirIndexes) * count);
208 if (fileNames[0][0] !=
'/')
212 dirNames[dirIndex] =
"";
213 for (rpm_count_t i = 0; i < count; i++)
215 dirIndexes[i] = dirIndex;
216 baseNames[i] = fileNames[i];
222 for (rpm_count_t i = 0; i < count; i++)
224 const char ** needle;
229 if (fileNames[i] == NULL)
231 baseName = strrchr(fileNames[i],
'/') + 1;
232 len = baseName - fileNames[i];
234 savechar = *baseName;
238 (needle = (
const char **)bsearch(&fileNames[i], dirNames, dirIndex + 1,
sizeof(dirNames[0]), dncmp)) == NULL)
240 char *s = (
char *)alloca(len + 1);
241 memcpy(s, fileNames[i], len + 1);
243 dirIndexes[i] = ++dirIndex;
244 dirNames[dirIndex] = s;
247 dirIndexes[i] = needle - dirNames;
250 *baseName = savechar;
251 baseNames[i] = baseName;
258 xx = headerAddEntry(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
259 xx = headerAddEntry(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
261 xx = headerAddEntry(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
262 dirNames, dirIndex + 1);
265 fileNames = (
char**)headerFreeData(fileNames, fnt);
267 xx = headerRemoveEntry(h, RPMTAG_OLDFILENAMES);
275 void providePackageNVR(Header h)
277 const char *name, *version, *release;
278 HGEPtr_t hgePtr = NULL;
282 int_32 pFlags = RPMSENSE_EQUAL;
283 const char ** provides = NULL;
284 const char ** providesEVR = NULL;
286 int_32 * provideFlags = NULL;
287 rpm_count_t providesCount;
292 xx = headerNVR(h, &name, &version, &release);
293 if (!(name && version && release))
295 pEVR = p = (
char *)alloca(21 + strlen(version) + 1 + strlen(release) + 1);
297 if (headerGetEntryMinMemory(h, RPMTAG_EPOCH, NULL, &hgePtr, NULL))
299 epoch = (int_32 *)hgePtr;
300 sprintf(p,
"%d:", *epoch);
304 (void) stpcpy( stpcpy( stpcpy(p, version) ,
"-") , release);
310 if (!headerGetEntryMinMemory(h, RPMTAG_PROVIDENAME, hTYP_t(&pnt), &hgePtr, &providesCount))
312 provides = (
const char **)hgePtr;
317 if (!headerGetEntryMinMemory(h, RPMTAG_PROVIDEVERSION, hTYP_t(&pvt), &hgePtr, NULL))
319 providesEVR = (
const char **)hgePtr;
320 for (rpm_count_t i = 0; i < providesCount; i++)
322 const char * vdummy =
"";
323 int_32 fdummy = RPMSENSE_ANY;
324 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
326 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
332 xx = headerGetEntryMinMemory(h, RPMTAG_PROVIDEFLAGS, NULL, &hgePtr, NULL);
333 provideFlags = (int_32 *)hgePtr;
336 if (provides && providesEVR && provideFlags)
337 for (rpm_count_t i = 0; i < providesCount; i++)
339 if (!(provides[i] && providesEVR[i]))
341 if (!(provideFlags[i] == RPMSENSE_EQUAL &&
342 !strcmp(name, provides[i]) && !strcmp(pEVR, providesEVR[i])))
350 provides = (
const char **)headerFreeData(provides, pnt);
351 providesEVR = (
const char **)headerFreeData(providesEVR, pvt);
355 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE,
357 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
359 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
364 static void compressFilelist(Header h)
366 struct rpmtd_s fileNames;
368 const char ** baseNames;
369 uint32_t * dirIndexes;
380 if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
381 xx = headerDel(h, RPMTAG_OLDFILENAMES);
385 if (!headerGet(h, RPMTAG_OLDFILENAMES, &fileNames, HEADERGET_MINMEM))
387 count = rpmtdCount(&fileNames);
391 dirNames = (
char**)malloc(
sizeof(*dirNames) * count);
392 baseNames = (
const char**)malloc(
sizeof(*dirNames) * count);
393 dirIndexes = (uint32_t*)malloc(
sizeof(*dirIndexes) * count);
396 {
const char *fn = rpmtdGetString(&fileNames);
397 if (fn && *fn !=
'/') {
399 dirNames[dirIndex] = xstrdup(
"");
400 while ((i = rpmtdNext(&fileNames)) >= 0) {
401 dirIndexes[i] = dirIndex;
402 baseNames[i] = rpmtdGetString(&fileNames);
408 while ((i = rpmtdNext(&fileNames)) >= 0) {
413 const char *filename = rpmtdGetString(&fileNames);
415 if (filename == NULL)
417 baseName = strrchr((
char*)filename,
'/') + 1;
418 len = baseName - filename;
420 savechar = *baseName;
423 (needle = (
char**)bsearch(&filename, dirNames, dirIndex + 1,
sizeof(dirNames[0]), dncmp)) == NULL) {
424 char *s = (
char*)malloc(len + 1);
425 rstrlcpy(s, filename, len + 1);
426 dirIndexes[i] = ++dirIndex;
427 dirNames[dirIndex] = s;
429 dirIndexes[i] = needle - dirNames;
431 *baseName = savechar;
432 baseNames[i] = baseName;
437 headerPutUint32(h, RPMTAG_DIRINDEXES, dirIndexes, count);
438 headerPutStringArray(h, RPMTAG_BASENAMES, baseNames, count);
439 headerPutStringArray(h, RPMTAG_DIRNAMES,
440 (
const char **) dirNames, dirIndex + 1);
443 rpmtdFreeData(&fileNames);
444 for (i = 0; i <= dirIndex; i++) {
451 xx = headerDel(h, RPMTAG_OLDFILENAMES);
458 static void providePackageNVR(Header h)
462 rpmsenseFlags pFlags = RPMSENSE_EQUAL;
464 struct rpmtd_s pnames;
468 pEVR = headerGetEVR(h, &name);
476 if (!headerGet(h, RPMTAG_PROVIDENAME, &pnames, HEADERGET_MINMEM)) {
483 if (!headerIsEntry(h, RPMTAG_PROVIDEVERSION)) {
484 while (rpmtdNext(&pnames) >= 0) {
485 uint32_t fdummy = RPMSENSE_ANY;
487 headerPutString(h, RPMTAG_PROVIDEVERSION,
"");
488 headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &fdummy, 1);
494 hds = rpmdsNew(h, RPMTAG_PROVIDENAME, 0);
495 nvrds = rpmdsSingle(RPMTAG_PROVIDENAME, name, pEVR, pFlags);
496 if (rpmdsFind(hds, nvrds) >= 0) {
504 const char *evr = pEVR;
505 uint32_t fdummy = pFlags;
506 headerPutString(h, RPMTAG_PROVIDENAME, name);
507 headerPutString(h, RPMTAG_PROVIDEVERSION, evr);
508 headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &fdummy, 1);
510 rpmtdFreeData(&pnames);
523 #define Y2LOG "librpmDb"
531 void internal_convertV3toV4(
const Pathname & v3db_r,
const librpmDb::constPtr & v4db_r,
532 callback::SendReport<ConvertDBReport> &
report )
535 MIL <<
"Convert rpm3 database to rpm4" << endl;
538 FD_t fd = fadOpen( v3db_r.asString().c_str() );
542 ZYPP_THROW(RpmDbOpenException(Pathname(
"/"), v3db_r));
548 INT <<
"NULL rpmV4 database passed as argument!" << endl;
552 shared_ptr<RpmException> err = v4db_r->error();
556 INT <<
"Can't access rpmV4 database " << v4db_r << endl;
563 string rootstr( v4db_r->root().asString() );
564 const char * root = ( rootstr ==
"/" ? NULL : rootstr.c_str() );
566 int res = ::rpmdbOpen( root, &db, O_RDWR, 0644 );
574 ZYPP_THROW(RpmDbOpenException(root, v4db_r->dbPath()));
579 for (
int offset = fadFirstOffset(fd); offset; offset = fadNextOffset(fd, offset) )
583 MIL <<
"Packages in rpmV3 database " << v3db_r <<
": " << max << endl;
586 unsigned ignored = 0;
587 unsigned alreadyInV4 = 0;
588 report->progress( (100 * (failed + ignored + alreadyInV4) / max), v3db_r );
598 #warning Add CBSuggest handling if needed, also on lines below
601 for (
int offset = fadFirstOffset(fd); offset && proceed ;
602 offset = fadNextOffset(fd, offset),
603 report->progress( (100 * (failed + ignored + alreadyInV4) / max), v3db_r ) )
608 if ( lseek( Fileno( fd ), (off_t)offset, SEEK_SET ) == -1 )
610 ostream * reportAs = &(
ERR);
620 (*reportAs) <<
"rpmV3 database entry: Can't seek to offset " << offset <<
" (errno " << errno <<
")" << endl;
623 Header h = headerRead(fd, HEADER_MAGIC_NO);
626 ostream * reportAs = &(
ERR);
636 (*reportAs) <<
"rpmV3 database entry: No header at offset " << offset << endl;
640 providePackageNVR(h);
641 const char *name = 0;
642 const char *version = 0;
643 const char *release = 0;
644 headerNVR(h, &name, &version, &release);
645 string nrv(
string(name) +
"-" + version +
"-" + release );
646 rpmdbMatchIterator mi = rpmdbInitIterator(db, RPMTAG_NAME, name, 0);
647 rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_DEFAULT, version);
648 rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_DEFAULT, release);
649 if (rpmdbNextIterator(mi))
652 WAR <<
"SKIP: rpmV3 database entry: " << nrv <<
" is already in rpmV4 database" << endl;
653 rpmdbFreeIterator(mi);
658 rpmdbFreeIterator(mi);
660 if (rpmdbAdd(db, -1, h, 0))
662 if (rpmdbAdd(db, -1, h, 0, 0))
668 ERR <<
"rpmV4 database error: could not add " << nrv <<
" to rpmV4 database" << endl;
680 ERR <<
"Convert rpm3 database to rpm4: Aborted after "
681 << alreadyInV4 <<
" package(s) and " << (failed+ignored) <<
" error(s)."
687 MIL <<
"Convert rpm3 database to rpm4: " << max <<
" package(s) processed";
690 MIL <<
"; " << alreadyInV4 <<
" already present in rpmV4 database";
694 MIL <<
"; IGNORED: " << ignored <<
" unconverted due to error";
712 #define Y2LOG "librpmDb"
732 report->start(v3db_r);
737 INT <<
"Unsupported: Convert rpm3 database to rpm4" << endl;
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Just inherits Exception to separate media exceptions.
void convertV3toV4(const Pathname &v3db_r, const librpmDb::constPtr &v4db_r)
intrusive_ptr< const librpmDb > constPtr
std::string asUserString() const
Translated error message as string suitable for the user.