00001
00005 #include "system.h"
00006
00007 #include <rpmlib.h>
00008 #include <rpmmacro.h>
00009
00010 #include "depends.h"
00011 #include "fprint.h"
00012 #include "hash.h"
00013 #include "install.h"
00014 #include "md5.h"
00015 #include "misc.h"
00016 #include "rpmdb.h"
00017
00018
00019
00020 #if STATFS_IN_SYS_STATVFS
00021 # include <sys/statvfs.h>
00022 #else
00023 # if STATFS_IN_SYS_VFS
00024 # include <sys/vfs.h>
00025 # else
00026 # if STATFS_IN_SYS_MOUNT
00027 # include <sys/mount.h>
00028 # else
00029 # if STATFS_IN_SYS_STATFS
00030 # include <sys/statfs.h>
00031 # endif
00032 # endif
00033 # endif
00034 #endif
00035
00036 #include "debug.h"
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 typedef struct transactionFileInfo {
00047
00048 enum rpmTransactionType type;
00049 enum fileActions * actions;
00050 fingerPrint * fps;
00051 uint_32 * fflags;
00052 uint_32 * fsizes;
00053 const char ** bnl;
00054 const char ** dnl;
00055 const int * dil;
00056 const char ** fmd5s;
00057 uint_16 * fmodes;
00058 Header h;
00059 int fc;
00060 int dc;
00061 char * fstates;
00062
00063 const char ** flinks;
00064 struct availablePackage * ap;
00065 struct sharedFileInfo * replaced;
00066 uint_32 * replacedSizes;
00067
00068 unsigned int record;
00069 } TFI_t;
00070
00071 struct diskspaceInfo {
00072 dev_t dev;
00073 signed long bneeded;
00074 signed long ineeded;
00075 int bsize;
00076 signed long bavail;
00077 signed long iavail;
00078 };
00079
00080
00081 #define adj_fs_blocks(_nb) (((_nb) * 21) / 20)
00082
00083
00084
00085 #define BLOCK_ROUND(size, block) (((size) + (block) - 1) / (block))
00086
00087 #define XSTRCMP(a, b) ((!(a) && !(b)) || ((a) && (b) && !strcmp((a), (b))))
00088
00089 #define XFA_SKIPPING(_a) \
00090 ((_a) == FA_SKIP || (_a) == FA_SKIPNSTATE || (_a) == FA_SKIPNETSHARED || (_a) == FA_SKIPMULTILIB)
00091
00092 static void freeFi(TFI_t *fi)
00093 {
00094 if (fi->h) {
00095 headerFree(fi->h); fi->h = NULL;
00096 }
00097 if (fi->actions) {
00098 free(fi->actions); fi->actions = NULL;
00099 }
00100 if (fi->replacedSizes) {
00101 free(fi->replacedSizes); fi->replacedSizes = NULL;
00102 }
00103 if (fi->replaced) {
00104 free(fi->replaced); fi->replaced = NULL;
00105 }
00106 if (fi->bnl) {
00107 free(fi->bnl); fi->bnl = NULL;
00108 free(fi->dnl); fi->dnl = NULL;
00109 }
00110 if (fi->flinks) {
00111 free(fi->flinks); fi->flinks = NULL;
00112 }
00113 if (fi->fmd5s) {
00114 free(fi->fmd5s); fi->fmd5s = NULL;
00115 }
00116
00117 switch (fi->type) {
00118 case TR_REMOVED:
00119 if (fi->fsizes) {
00120 free(fi->fsizes); fi->fsizes = NULL;
00121 }
00122 if (fi->fflags) {
00123 free(fi->fflags); fi->fflags = NULL;
00124 }
00125 if (fi->fmodes) {
00126 free(fi->fmodes); fi->fmodes = NULL;
00127 }
00128 if (fi->fstates) {
00129 free(fi->fstates); fi->fstates = NULL;
00130 }
00131 if (fi->dil) {
00132 free((void *)fi->dil); fi->dil = NULL;
00133 }
00134 break;
00135 case TR_ADDED:
00136 break;
00137 }
00138 }
00139
00140 static void freeFl(rpmTransactionSet ts, TFI_t *flList)
00141 {
00142 TFI_t *fi;
00143 int oc;
00144
00145 for (oc = 0, fi = flList; oc < ts->orderCount; oc++, fi++) {
00146 freeFi(fi);
00147 }
00148 }
00149
00150 void rpmtransSetScriptFd(rpmTransactionSet ts, FD_t fd)
00151 {
00152 ts->scriptFd = (fd ? fdLink(fd, "rpmtransSetScriptFd") : NULL);
00153 }
00154
00155 int rpmtransGetKeys(const rpmTransactionSet ts, const void *** ep, int * nep)
00156 {
00157 int rc = 0;
00158
00159 if (nep) *nep = ts->orderCount;
00160 if (ep) {
00161 const void ** e;
00162 int oc;
00163
00164 *ep = e = xmalloc(ts->orderCount * sizeof(*e));
00165 for (oc = 0; oc < ts->orderCount; oc++, e++) {
00166 struct availablePackage * alp;
00167 switch (ts->order[oc].type) {
00168 case TR_ADDED:
00169 alp = ts->addedPackages.list + ts->order[oc].u.addedIndex;
00170 *e = alp->key;
00171 break;
00172 case TR_REMOVED:
00173 *e = NULL;
00174 break;
00175 }
00176 }
00177 }
00178 return rc;
00179 }
00180
00181 static rpmProblemSet psCreate(void)
00182 {
00183 rpmProblemSet probs;
00184
00185 probs = xmalloc(sizeof(*probs));
00186 probs->numProblems = probs->numProblemsAlloced = 0;
00187 probs->probs = NULL;
00188
00189 return probs;
00190 }
00191
00192 static void psAppend(rpmProblemSet probs, rpmProblemType type,
00193 const void * key, Header h,
00194 const char * dn, const char *bn,
00195 Header altH, unsigned long ulong1)
00196 {
00197 const char *n, *v, *r;
00198 char *t;
00199 rpmProblem p;
00200
00201 if (probs->numProblems == probs->numProblemsAlloced) {
00202 if (probs->numProblemsAlloced)
00203 probs->numProblemsAlloced *= 2;
00204 else
00205 probs->numProblemsAlloced = 2;
00206 probs->probs = xrealloc(probs->probs,
00207 probs->numProblemsAlloced * sizeof(*probs->probs));
00208 }
00209
00210 p = probs->probs + probs->numProblems++;
00211 p->type = type;
00212 p->key = key;
00213 p->ulong1 = ulong1;
00214 p->ignoreProblem = 0;
00215
00216 if (dn || bn) {
00217 p->str1 =
00218 t = xmalloc((dn ? strlen(dn) : 0) + (bn ? strlen(bn) : 0) + 1);
00219 if (dn) t = stpcpy(t, dn);
00220 if (bn) t = stpcpy(t, bn);
00221 } else
00222 p->str1 = NULL;
00223
00224 if (h) {
00225 p->h = headerLink(h);
00226 headerNVR(h, &n, &v, &r);
00227 p->pkgNEVR =
00228 t = xmalloc(strlen(n) + strlen(v) + strlen(r) + sizeof("--"));
00229 t = stpcpy(t, n);
00230 t = stpcpy(t, "-");
00231 t = stpcpy(t, v);
00232 t = stpcpy(t, "-");
00233 t = stpcpy(t, r);
00234 } else {
00235 p->pkgNEVR = NULL;
00236 p->h = NULL;
00237 }
00238
00239 if (altH) {
00240 headerNVR(altH, &n, &v, &r);
00241 p->altNEVR =
00242 t = xmalloc(strlen(n) + strlen(v) + strlen(r) + sizeof("--"));
00243 t = stpcpy(t, n);
00244 t = stpcpy(t, "-");
00245 t = stpcpy(t, v);
00246 t = stpcpy(t, "-");
00247 t = stpcpy(t, r);
00248 } else
00249 p->altNEVR = NULL;
00250 }
00251
00252 static int archOkay(Header h)
00253 {
00254 void * pkgArch;
00255 int type, count;
00256
00257
00258 headerGetEntry(h, RPMTAG_ARCH, &type, (void **) &pkgArch, &count);
00259 #ifndef DYING
00260 if (type == RPM_INT8_TYPE) {
00261 int_8 * pkgArchNum;
00262 int archNum;
00263
00264
00265 rpmGetArchInfo(NULL, &archNum);
00266 pkgArchNum = pkgArch;
00267 if (archNum != *pkgArchNum) {
00268 return 0;
00269 }
00270 } else
00271 #endif
00272 {
00273
00274 if (!rpmMachineScore(RPM_MACHTABLE_INSTARCH, pkgArch)) {
00275 return 0;
00276 }
00277 }
00278
00279 return 1;
00280 }
00281
00282 static int osOkay(Header h)
00283 {
00284 void * pkgOs;
00285 int type, count;
00286
00287
00288 headerGetEntry(h, RPMTAG_OS, &type, (void **) &pkgOs, &count);
00289 #ifndef DYING
00290 if (type == RPM_INT8_TYPE) {
00291
00292
00293 return 1;
00294 } else
00295 #endif
00296 {
00297
00298 if (!rpmMachineScore(RPM_MACHTABLE_INSTOS, pkgOs)) {
00299 return 0;
00300 }
00301 }
00302
00303 return 1;
00304 }
00305
00306 void rpmProblemSetFree(rpmProblemSet probs)
00307 {
00308 int i;
00309
00310 for (i = 0; i < probs->numProblems; i++) {
00311 rpmProblem p = probs->probs + i;
00312 if (p->h) headerFree(p->h);
00313 if (p->pkgNEVR) free((void *)p->pkgNEVR);
00314 if (p->altNEVR) free((void *)p->altNEVR);
00315 if (p->str1) free((void *)p->str1);
00316 }
00317 free(probs);
00318 }
00319
00320 static const char *const ftstring (enum fileTypes ft)
00321 {
00322 switch (ft) {
00323 case XDIR: return "directory";
00324 case CDEV: return "char dev";
00325 case BDEV: return "block dev";
00326 case LINK: return "link";
00327 case SOCK: return "sock";
00328 case PIPE: return "fifo/pipe";
00329 case REG: return "file";
00330 }
00331 return "unknown file type";
00332 }
00333
00334 static enum fileTypes whatis(uint_16 mode)
00335 {
00336 if (S_ISDIR(mode)) return XDIR;
00337 if (S_ISCHR(mode)) return CDEV;
00338 if (S_ISBLK(mode)) return BDEV;
00339 if (S_ISLNK(mode)) return LINK;
00340 if (S_ISSOCK(mode)) return SOCK;
00341 if (S_ISFIFO(mode)) return PIPE;
00342 return REG;
00343 }
00344
00345 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
00346
00356 static Header relocateFileList(const rpmTransactionSet ts,
00357 struct availablePackage * alp,
00358 Header origH, enum fileActions * actions)
00359 {
00360 static int _printed = 0;
00361 rpmProblemSet probs = ts->probs;
00362 int allowBadRelocate = (ts->ignoreSet & RPMPROB_FILTER_FORCERELOCATE);
00363 rpmRelocation * rawRelocations = alp->relocs;
00364 rpmRelocation * relocations = NULL;
00365 int numRelocations;
00366 const char ** validRelocations;
00367 int_32 validType;
00368 int numValid;
00369 const char ** baseNames;
00370 const char ** dirNames;
00371 int_32 * dirIndexes;
00372 int_32 * newDirIndexes;
00373 int_32 fileCount;
00374 int_32 dirCount;
00375 uint_32 * fFlags = NULL;
00376 uint_16 * fModes = NULL;
00377 char * skipDirList;
00378 Header h;
00379 int nrelocated = 0;
00380 int fileAlloced = 0;
00381 char * fn = NULL;
00382 int haveRelocatedFile = 0;
00383 int len;
00384 int i, j;
00385
00386 if (!headerGetEntry(origH, RPMTAG_PREFIXES, &validType,
00387 (void **) &validRelocations, &numValid))
00388 numValid = 0;
00389
00390 numRelocations = 0;
00391 if (rawRelocations)
00392 while (rawRelocations[numRelocations].newPath ||
00393 rawRelocations[numRelocations].oldPath)
00394 numRelocations++;
00395
00396
00397
00398
00399
00400
00401
00402 if (numRelocations == 0) {
00403 if (numValid) {
00404 if (!headerIsEntry(origH, RPMTAG_INSTPREFIXES))
00405 headerAddEntry(origH, RPMTAG_INSTPREFIXES,
00406 validType, validRelocations, numValid);
00407 headerFreeData(validRelocations, validType);
00408 }
00409
00410 return headerLink(origH);
00411 }
00412
00413 #ifdef DYING
00414 h = headerCopy(origH);
00415 #else
00416 h = headerLink(origH);
00417 #endif
00418
00419 relocations = alloca(sizeof(*relocations) * numRelocations);
00420
00421
00422 for (i = 0; i < numRelocations; i++) {
00423
00424
00425
00426
00427
00428 relocations[i].oldPath =
00429 stripTrailingChar(alloca_strdup(rawRelocations[i].oldPath), '/');
00430
00431
00432 if (rawRelocations[i].newPath) {
00433 relocations[i].newPath =
00434 stripTrailingChar(alloca_strdup(rawRelocations[i].newPath), '/');
00435
00436
00437 for (j = 0; j < numValid; j++)
00438 if (!strcmp(validRelocations[j], relocations[i].oldPath)) break;
00439
00440 if (j == numValid && !allowBadRelocate && actions)
00441 psAppend(probs, RPMPROB_BADRELOCATE, alp->key, alp->h,
00442 relocations[i].oldPath, NULL, NULL, 0);
00443 } else {
00444 relocations[i].newPath = NULL;
00445 }
00446 }
00447
00448
00449 for (i = 0; i < numRelocations; i++) {
00450 int madeSwap;
00451 madeSwap = 0;
00452 for (j = 1; j < numRelocations; j++) {
00453 rpmRelocation tmpReloc;
00454 if (strcmp(relocations[j - 1].oldPath, relocations[j].oldPath) <= 0)
00455 continue;
00456 tmpReloc = relocations[j - 1];
00457 relocations[j - 1] = relocations[j];
00458 relocations[j] = tmpReloc;
00459 madeSwap = 1;
00460 }
00461 if (!madeSwap) break;
00462 }
00463
00464 if (!_printed) {
00465 _printed = 1;
00466 rpmMessage(RPMMESS_DEBUG, _("========== relocations\n"));
00467 for (i = 0; i < numRelocations; i++) {
00468 if (relocations[i].newPath == NULL)
00469 rpmMessage(RPMMESS_DEBUG, _("%5d exclude %s\n"),
00470 i, relocations[i].oldPath);
00471 else
00472 rpmMessage(RPMMESS_DEBUG, _("%5d relocate %s -> %s\n"),
00473 i, relocations[i].oldPath, relocations[i].newPath);
00474 }
00475 }
00476
00477
00478 if (numValid) {
00479 const char ** actualRelocations;
00480 int numActual;
00481
00482 actualRelocations = xmalloc(sizeof(*actualRelocations) * numValid);
00483 numActual = 0;
00484 for (i = 0; i < numValid; i++) {
00485 for (j = 0; j < numRelocations; j++) {
00486 if (strcmp(validRelocations[i], relocations[j].oldPath))
00487 continue;
00488
00489 if (relocations[j].newPath) {
00490 actualRelocations[numActual] = relocations[j].newPath;
00491 numActual++;
00492 }
00493 break;
00494 }
00495 if (j == numRelocations) {
00496 actualRelocations[numActual] = validRelocations[i];
00497 numActual++;
00498 }
00499 }
00500
00501 if (numActual)
00502 headerAddEntry(h, RPMTAG_INSTPREFIXES, RPM_STRING_ARRAY_TYPE,
00503 (void **) actualRelocations, numActual);
00504
00505 free((void *)actualRelocations);
00506 headerFreeData(validRelocations, validType);
00507 }
00508
00509 headerGetEntry(h, RPMTAG_BASENAMES, NULL, (void **) &baseNames,
00510 &fileCount);
00511 headerGetEntry(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL);
00512 headerGetEntry(h, RPMTAG_DIRNAMES, NULL, (void **) &dirNames,
00513 &dirCount);
00514 headerGetEntry(h, RPMTAG_FILEFLAGS, NULL, (void **) &fFlags, NULL);
00515 headerGetEntry(h, RPMTAG_FILEMODES, NULL, (void **) &fModes, NULL);
00516
00517 skipDirList = alloca(dirCount * sizeof(*skipDirList));
00518 memset(skipDirList, 0, dirCount * sizeof(*skipDirList));
00519
00520 newDirIndexes = alloca(sizeof(*newDirIndexes) * fileCount);
00521 memcpy(newDirIndexes, dirIndexes, sizeof(*newDirIndexes) * fileCount);
00522 dirIndexes = newDirIndexes;
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532 for (i = fileCount - 1; i >= 0; i--) {
00533 char * te;
00534 int fslen;
00535
00536
00537
00538
00539
00540 if (alp->multiLib && !isFileMULTILIB((fFlags[i]))) {
00541 if (actions) {
00542 actions[i] = FA_SKIPMULTILIB;
00543 rpmMessage(RPMMESS_DEBUG, _("excluding multilib path %s%s\n"),
00544 dirNames[dirIndexes[i]], baseNames[i]);
00545 }
00546 continue;
00547 }
00548
00549 len = strlen(dirNames[dirIndexes[i]]) + strlen(baseNames[i]) + 1;
00550 if (len >= fileAlloced) {
00551 fileAlloced = len * 2;
00552 fn = xrealloc(fn, fileAlloced);
00553 }
00554 te = stpcpy( stpcpy(fn, dirNames[dirIndexes[i]]), baseNames[i]);
00555 fslen = (te - fn);
00556
00557
00558
00559
00560
00561
00562
00563
00564 for (j = numRelocations - 1; j >= 0; j--) {
00565 len = strlen(relocations[j].oldPath);
00566 if (fslen < len)
00567 continue;
00568 if (strncmp(relocations[j].oldPath, fn, len))
00569 continue;
00570 break;
00571 }
00572 if (j < 0) continue;
00573
00574
00575 if (relocations[j].newPath == NULL) {
00576 enum fileTypes ft = whatis(fModes[i]);
00577 int k;
00578 if (ft == XDIR) {
00579
00580 for (k = dirIndexes[i]; k < dirCount; k++) {
00581 len = strlen(dirNames[k]) - 1;
00582 while (len > 0 && dirNames[k][len-1] == '/') len--;
00583 if (len == fslen && !strncmp(dirNames[k], fn, len))
00584 break;
00585 }
00586 if (k >= dirCount)
00587 continue;
00588 skipDirList[k] = 1;
00589 }
00590 if (actions) {
00591 actions[i] = FA_SKIPNSTATE;
00592 rpmMessage(RPMMESS_DEBUG, _("excluding %s %s\n"),
00593 ftstring(ft), fn);
00594 }
00595 continue;
00596 }
00597
00598 if (actions)
00599 rpmMessage(RPMMESS_DEBUG, _("relocating %s to %s\n"),
00600 fn, relocations[j].newPath);
00601 nrelocated++;
00602
00603 len = strlen(relocations[j].newPath);
00604 if (len >= fileAlloced) {
00605 fileAlloced = len * 2;
00606 fn = xrealloc(fn, fileAlloced);
00607 }
00608 strcpy(fn, relocations[j].newPath);
00609
00610 { char * s = strrchr(fn, '/');
00611 *s++ = '\0';
00612
00613
00614 if (strcmp(baseNames[i], s))
00615 baseNames[i] = alloca_strdup(s);
00616 }
00617
00618
00619 for (j = 0; j < dirCount; j++)
00620 if (!strcmp(fn, dirNames[j])) break;
00621
00622 if (j < dirCount) {
00623 dirIndexes[i] = j;
00624 continue;
00625 }
00626
00627
00628 if (!haveRelocatedFile) {
00629 const char ** newDirList;
00630 int k;
00631
00632 haveRelocatedFile = 1;
00633 newDirList = xmalloc(sizeof(*newDirList) * (dirCount + 1));
00634 for (k = 0; k < dirCount; k++)
00635 newDirList[k] = alloca_strdup(dirNames[k]);
00636 headerFreeData(dirNames, RPM_STRING_ARRAY_TYPE);
00637 dirNames = newDirList;
00638 } else {
00639 dirNames = xrealloc(dirNames,
00640 sizeof(*dirNames) * (dirCount + 1));
00641 }
00642
00643 dirNames[dirCount] = alloca_strdup(fn);
00644 dirIndexes[i] = dirCount;
00645 dirCount++;
00646 }
00647
00648
00649 for (i = dirCount - 1; i >= 0; i--) {
00650 for (j = numRelocations - 1; j >= 0; j--) {
00651 int oplen;
00652
00653 oplen = strlen(relocations[j].oldPath);
00654 if (strncmp(relocations[j].oldPath, dirNames[i], oplen))
00655 continue;
00656
00657
00658
00659
00660
00661 if (!(dirNames[i][oplen] == '/'))
00662 continue;
00663
00664 if (relocations[j].newPath) {
00665 const char *s = relocations[j].newPath;
00666 char *t = alloca(strlen(s) + strlen(dirNames[i]) - oplen + 1);
00667
00668 (void) stpcpy( stpcpy(t, s) , dirNames[i] + oplen);
00669 if (actions)
00670 rpmMessage(RPMMESS_DEBUG,
00671 _("relocating directory %s to %s\n"), dirNames[i], t);
00672 dirNames[i] = t;
00673 nrelocated++;
00674 } else {
00675 if (actions && !skipDirList[i]) {
00676 rpmMessage(RPMMESS_DEBUG, _("excluding directory %s\n"),
00677 dirNames[dirIndexes[i]]);
00678 actions[i] = FA_SKIPNSTATE;
00679 }
00680 }
00681 break;
00682 }
00683 }
00684
00685
00686 if (nrelocated) {
00687 int c;
00688 void * p;
00689 int t;
00690
00691 p = NULL;
00692 headerGetEntry(h, RPMTAG_BASENAMES, &t, &p, &c);
00693 headerAddEntry(h, RPMTAG_ORIGBASENAMES, t, p, c);
00694 headerFreeData(p, t);
00695
00696 p = NULL;
00697 headerGetEntry(h, RPMTAG_DIRNAMES, &t, &p, &c);
00698 headerAddEntry(h, RPMTAG_ORIGDIRNAMES, t, p, c);
00699 headerFreeData(p, t);
00700
00701 p = NULL;
00702 headerGetEntry(h, RPMTAG_DIRINDEXES, &t, &p, &c);
00703 headerAddEntry(h, RPMTAG_ORIGDIRINDEXES, t, p, c);
00704 headerFreeData(p, t);
00705
00706 headerModifyEntry(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
00707 baseNames, fileCount);
00708 headerModifyEntry(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
00709 dirNames, dirCount);
00710 headerModifyEntry(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE,
00711 dirIndexes, fileCount);
00712 }
00713
00714 headerFreeData(baseNames, RPM_STRING_ARRAY_TYPE);
00715 headerFreeData(dirNames, RPM_STRING_ARRAY_TYPE);
00716 if (fn) free(fn);
00717
00718 return h;
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730 static int psTrim(rpmProblemSet filter, rpmProblemSet target)
00731 {
00732 rpmProblem f = filter->probs;
00733 rpmProblem t = target->probs;
00734 int gotProblems = 0;
00735
00736 while ((f - filter->probs) < filter->numProblems) {
00737 if (!f->ignoreProblem) {
00738 f++;
00739 continue;
00740 }
00741 while ((t - target->probs) < target->numProblems) {
00742 if (f->h == t->h && f->type == t->type && t->key == f->key &&
00743 XSTRCMP(f->str1, t->str1))
00744 break;
00745 t++;
00746 gotProblems = 1;
00747 }
00748
00749 if ((t - target->probs) == target->numProblems) {
00750
00751 break;
00752 }
00753
00754 t->ignoreProblem = f->ignoreProblem;
00755 t++, f++;
00756 }
00757
00758 if ((t - target->probs) < target->numProblems)
00759 gotProblems = 1;
00760
00761 return gotProblems;
00762 }
00763
00764 static int sharedCmp(const void * one, const void * two)
00765 {
00766 const struct sharedFileInfo * a = one;
00767 const struct sharedFileInfo * b = two;
00768
00769 if (a->otherPkg < b->otherPkg)
00770 return -1;
00771 else if (a->otherPkg > b->otherPkg)
00772 return 1;
00773
00774 return 0;
00775 }
00776
00777 static enum fileActions decideFileFate(const char * dirName,
00778 const char * baseName, short dbMode,
00779 const char * dbMd5, const char * dbLink, short newMode,
00780 const char * newMd5, const char * newLink, int newFlags,
00781 int brokenMd5, rpmtransFlags transFlags)
00782 {
00783 char buffer[1024];
00784 const char * dbAttr, * newAttr;
00785 enum fileTypes dbWhat, newWhat, diskWhat;
00786 struct stat sb;
00787 int i, rc;
00788 int save = (newFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SAVE;
00789 char * filespec = alloca(strlen(dirName) + strlen(baseName) + 1);
00790
00791 (void) stpcpy( stpcpy(filespec, dirName), baseName);
00792
00793 if (lstat(filespec, &sb)) {
00794
00795
00796
00797
00798 if (!(transFlags & RPMTRANS_FLAG_ALLFILES) &&
00799 (newFlags & RPMFILE_MISSINGOK)) {
00800 rpmMessage(RPMMESS_DEBUG, _("%s skipped due to missingok flag\n"),
00801 filespec);
00802 return FA_SKIP;
00803 } else {
00804 return FA_CREATE;
00805 }
00806 }
00807
00808 diskWhat = whatis(sb.st_mode);
00809 dbWhat = whatis(dbMode);
00810 newWhat = whatis(newMode);
00811
00812
00813
00814 if (newWhat == XDIR) {
00815 return FA_CREATE;
00816 }
00817
00818 if (diskWhat != newWhat) {
00819 return save;
00820 } else if (newWhat != dbWhat && diskWhat != dbWhat) {
00821 return save;
00822 } else if (dbWhat != newWhat) {
00823 return FA_CREATE;
00824 } else if (dbWhat != LINK && dbWhat != REG) {
00825 return FA_CREATE;
00826 }
00827
00828 if (dbWhat == REG) {
00829 if (brokenMd5)
00830 rc = mdfileBroken(filespec, buffer);
00831 else
00832 rc = mdfile(filespec, buffer);
00833
00834 if (rc) {
00835
00836 return FA_CREATE;
00837 }
00838 dbAttr = dbMd5;
00839 newAttr = newMd5;
00840 } else {
00841 memset(buffer, 0, sizeof(buffer));
00842 i = readlink(filespec, buffer, sizeof(buffer) - 1);
00843 if (i == -1) {
00844
00845 return FA_CREATE;
00846 }
00847 dbAttr = dbLink;
00848 newAttr = newLink;
00849 }
00850
00851
00852
00853
00854 if (!strcmp(dbAttr, buffer)) {
00855
00856 return FA_CREATE;
00857 }
00858
00859 if (!strcmp(dbAttr, newAttr)) {
00860
00861 return FA_SKIP;
00862 }
00863
00864
00865
00866
00867
00868
00869
00870 return save;
00871 }
00872
00873 static int filecmp(short mode1, const char * md51, const char * link1,
00874 short mode2, const char * md52, const char * link2)
00875 {
00876 enum fileTypes what1 = whatis(mode1);
00877 enum fileTypes what2 = whatis(mode2);
00878
00879 if (what1 != what2) return 1;
00880
00881 if (what1 == LINK)
00882 return strcmp(link1, link2);
00883 else if (what1 == REG)
00884 return strcmp(md51, md52);
00885
00886 return 0;
00887 }
00888
00889 static int handleInstInstalledFiles(TFI_t * fi, rpmdb db,
00890 struct sharedFileInfo * shared,
00891 int sharedCount, int reportConflicts,
00892 rpmProblemSet probs,
00893 rpmtransFlags transFlags)
00894 {
00895 Header h;
00896 int i;
00897 const char ** otherMd5s;
00898 const char ** otherLinks;
00899 const char * otherStates;
00900 uint_32 * otherFlags;
00901 uint_32 * otherSizes;
00902 uint_16 * otherModes;
00903 int numReplaced = 0;
00904
00905 rpmdbMatchIterator mi;
00906
00907 mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, &shared->otherPkg, sizeof(shared->otherPkg));
00908 h = rpmdbNextIterator(mi);
00909 if (h == NULL) {
00910 rpmdbFreeIterator(mi);
00911 return 1;
00912 }
00913
00914 headerGetEntryMinMemory(h, RPMTAG_FILEMD5S, NULL,
00915 (const void **) &otherMd5s, NULL);
00916 headerGetEntryMinMemory(h, RPMTAG_FILELINKTOS, NULL,
00917 (const void **) &otherLinks, NULL);
00918 headerGetEntryMinMemory(h, RPMTAG_FILESTATES, NULL,
00919 (const void **) &otherStates, NULL);
00920 headerGetEntryMinMemory(h, RPMTAG_FILEMODES, NULL,
00921 (const void **) &otherModes, NULL);
00922 headerGetEntryMinMemory(h, RPMTAG_FILEFLAGS, NULL,
00923 (const void **) &otherFlags, NULL);
00924 headerGetEntryMinMemory(h, RPMTAG_FILESIZES, NULL,
00925 (const void **) &otherSizes, NULL);
00926
00927 fi->replaced = xmalloc(sizeof(*fi->replaced) * sharedCount);
00928
00929 for (i = 0; i < sharedCount; i++, shared++) {
00930 int otherFileNum, fileNum;
00931 otherFileNum = shared->otherFileNum;
00932 fileNum = shared->pkgFileNum;
00933
00934
00935 if (otherStates && otherStates[otherFileNum] != RPMFILE_STATE_NORMAL)
00936 continue;
00937
00938 if (XFA_SKIPPING(fi->actions[fileNum]))
00939 continue;
00940
00941 if (filecmp(otherModes[otherFileNum],
00942 otherMd5s[otherFileNum],
00943 otherLinks[otherFileNum],
00944 fi->fmodes[fileNum],
00945 fi->fmd5s[fileNum],
00946 fi->flinks[fileNum])) {
00947 if (reportConflicts)
00948 psAppend(probs, RPMPROB_FILE_CONFLICT, fi->ap->key, fi->ap->h,
00949 fi->dnl[fi->dil[fileNum]], fi->bnl[fileNum], h, 0);
00950 if (!(otherFlags[otherFileNum] | fi->fflags[fileNum])
00951 & RPMFILE_CONFIG) {
00952 if (!shared->isRemoved)
00953 fi->replaced[numReplaced++] = *shared;
00954 }
00955 }
00956
00957 if ((otherFlags[otherFileNum] | fi->fflags[fileNum]) & RPMFILE_CONFIG) {
00958 fi->actions[fileNum] = decideFileFate(
00959 fi->dnl[fi->dil[fileNum]],
00960 fi->bnl[fileNum],
00961 otherModes[otherFileNum],
00962 otherMd5s[otherFileNum],
00963 otherLinks[otherFileNum],
00964 fi->fmodes[fileNum],
00965 fi->fmd5s[fileNum],
00966 fi->flinks[fileNum],
00967 fi->fflags[fileNum],
00968 !headerIsEntry(h, RPMTAG_RPMVERSION),
00969 transFlags);
00970 }
00971
00972 fi->replacedSizes[fileNum] = otherSizes[otherFileNum];
00973 }
00974
00975 free(otherMd5s);
00976 free(otherLinks);
00977 rpmdbFreeIterator(mi);
00978
00979 fi->replaced = xrealloc(fi->replaced,
00980 sizeof(*fi->replaced) * (numReplaced + 1));
00981 fi->replaced[numReplaced].otherPkg = 0;
00982
00983 return 0;
00984 }
00985
00986 static int handleRmvdInstalledFiles(TFI_t * fi, rpmdb db,
00987 struct sharedFileInfo * shared,
00988 int sharedCount)
00989 {
00990 Header h;
00991 const char * otherStates;
00992 int i;
00993
00994 rpmdbMatchIterator mi;
00995
00996 mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, &shared->otherPkg, sizeof(shared->otherPkg));
00997 h = rpmdbNextIterator(mi);
00998 if (h == NULL) {
00999 rpmdbFreeIterator(mi);
01000 return 1;
01001 }
01002
01003 headerGetEntryMinMemory(h, RPMTAG_FILESTATES, NULL,
01004 (const void **) &otherStates, NULL);
01005
01006 for (i = 0; i < sharedCount; i++, shared++) {
01007 int otherFileNum, fileNum;
01008 otherFileNum = shared->otherFileNum;
01009 fileNum = shared->pkgFileNum;
01010
01011 if (otherStates[otherFileNum] != RPMFILE_STATE_NORMAL)
01012 continue;
01013
01014 fi->actions[fileNum] = FA_SKIP;
01015 }
01016
01017 rpmdbFreeIterator(mi);
01018
01019 return 0;
01020 }
01021
01025 static void handleOverlappedFiles(TFI_t * fi, hashTable ht,
01026 rpmProblemSet probs, struct diskspaceInfo * dsl)
01027 {
01028 int i, j;
01029 struct diskspaceInfo * ds = NULL;
01030 uint_32 fixupSize = 0;
01031 char * filespec = NULL;
01032 int fileSpecAlloced = 0;
01033
01034 for (i = 0; i < fi->fc; i++) {
01035 int otherPkgNum, otherFileNum;
01036 const TFI_t ** recs;
01037 int numRecs;
01038
01039 if (XFA_SKIPPING(fi->actions[i]))
01040 continue;
01041
01042 j = strlen(fi->dnl[fi->dil[i]]) + strlen(fi->bnl[i]) + 1;
01043 if (j > fileSpecAlloced) {
01044 fileSpecAlloced = j * 2;
01045 filespec = xrealloc(filespec, fileSpecAlloced);
01046 }
01047
01048 (void) stpcpy( stpcpy( filespec, fi->dnl[fi->dil[i]]), fi->bnl[i]);
01049
01050 if (dsl) {
01051 ds = dsl;
01052 while (ds->bsize && ds->dev != fi->fps[i].entry->dev) ds++;
01053 if (!ds->bsize) ds = NULL;
01054 fixupSize = 0;
01055 }
01056
01057
01058
01059
01060
01061
01062
01063 htGetEntry(ht, &fi->fps[i], (const void ***) &recs, &numRecs, NULL);
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086 for (j = 0; j < numRecs && recs[j] != fi; j++)
01087 ;
01088
01089
01090 otherFileNum = -1;
01091 for (otherPkgNum = j - 1; otherPkgNum >= 0; otherPkgNum--) {
01092
01093 if (fi->type == TR_ADDED && recs[otherPkgNum]->type != TR_ADDED)
01094 continue;
01095
01096
01097 for (otherFileNum = 0; otherFileNum < recs[otherPkgNum]->fc;
01098 otherFileNum++) {
01099
01100
01101 if ((fi->fps + i) == (recs[otherPkgNum]->fps + otherFileNum))
01102 break;
01103
01104
01105 if (FP_EQUAL(fi->fps[i], recs[otherPkgNum]->fps[otherFileNum]))
01106 break;
01107
01108 }
01109
01110 if (recs[otherPkgNum]->actions[otherFileNum] != FA_UNKNOWN)
01111 break;
01112 }
01113
01114 switch (fi->type) {
01115 struct stat sb;
01116 case TR_ADDED:
01117 if (otherPkgNum < 0) {
01118
01119 if (fi->actions[i] != FA_UNKNOWN)
01120 break;
01121 if ((fi->fflags[i] & RPMFILE_CONFIG) &&
01122 !lstat(filespec, &sb)) {
01123
01124 fi->actions[i] = (fi->fflags[i] & RPMFILE_NOREPLACE)
01125 ? FA_ALTNAME : FA_BACKUP;
01126 } else {
01127 fi->actions[i] = FA_CREATE;
01128 }
01129 break;
01130 }
01131
01132
01133 if (probs && filecmp(recs[otherPkgNum]->fmodes[otherFileNum],
01134 recs[otherPkgNum]->fmd5s[otherFileNum],
01135 recs[otherPkgNum]->flinks[otherFileNum],
01136 fi->fmodes[i],
01137 fi->fmd5s[i],
01138 fi->flinks[i])) {
01139 psAppend(probs, RPMPROB_NEW_FILE_CONFLICT, fi->ap->key,
01140 fi->ap->h, filespec, NULL, recs[otherPkgNum]->ap->h, 0);
01141 }
01142
01143
01144 fixupSize = recs[otherPkgNum]->fsizes[otherFileNum];
01145
01146 if ((fi->fflags[i] & RPMFILE_CONFIG) && !lstat(filespec, &sb)) {
01147
01148 fi->actions[i] = (fi->fflags[i] & RPMFILE_NOREPLACE)
01149 ? FA_ALTNAME : FA_SKIP;
01150 } else {
01151 fi->actions[i] = FA_CREATE;
01152 }
01153 break;
01154 case TR_REMOVED:
01155 if (otherPkgNum >= 0) {
01156
01157 if (recs[otherPkgNum]->actions[otherFileNum] != FA_REMOVE) {
01158
01159 fi->actions[i] = FA_SKIP;
01160 break;
01161 }
01162
01163 recs[otherPkgNum]->actions[otherFileNum] = FA_SKIP;
01164 }
01165 if (XFA_SKIPPING(fi->actions[i]))
01166 break;
01167 if (fi->fstates[i] != RPMFILE_STATE_NORMAL)
01168 break;
01169 if (!(S_ISREG(fi->fmodes[i]) && (fi->fflags[i] & RPMFILE_CONFIG))) {
01170 fi->actions[i] = FA_REMOVE;
01171 break;
01172 }
01173
01174
01175 { char mdsum[50];
01176 if (!mdfile(filespec, mdsum) && strcmp(fi->fmd5s[i], mdsum)) {
01177 fi->actions[i] = FA_BACKUP;
01178 break;
01179 }
01180 }
01181 fi->actions[i] = FA_REMOVE;
01182 break;
01183 }
01184
01185 if (ds) {
01186 uint_32 s = BLOCK_ROUND(fi->fsizes[i], ds->bsize);
01187
01188 switch (fi->actions[i]) {
01189 case FA_BACKUP:
01190 case FA_SAVE:
01191 case FA_ALTNAME:
01192 ds->ineeded++;
01193 ds->bneeded += s;
01194 break;
01195
01196
01197
01198
01199
01200 case FA_CREATE:
01201 ds->ineeded++;
01202 ds->bneeded += s;
01203 ds->bneeded -= BLOCK_ROUND(fi->replacedSizes[i], ds->bsize);
01204 break;
01205
01206 case FA_REMOVE:
01207 ds->ineeded--;
01208 ds->bneeded -= s;
01209 break;
01210
01211 default:
01212 break;
01213 }
01214
01215 ds->bneeded -= BLOCK_ROUND(fixupSize, ds->bsize);
01216 }
01217 }
01218 if (filespec) free(filespec);
01219 }
01220
01221 static int ensureOlder( rpmdb rpmdb, Header new, Header old, rpmProblemSet probs,
01222 const void * key)
01223 {
01224 int result, rc = 0;
01225
01226 if (old == NULL) return 1;
01227
01228 result = rpmVersionCompare(old, new);
01229 if (result <= 0)
01230 rc = 0;
01231 else if (result > 0) {
01232 rc = 1;
01233 psAppend(probs, RPMPROB_OLDPACKAGE, key, new, NULL, NULL, old, 0);
01234 }
01235
01236 return rc;
01237 }
01238
01239 static void skipFiles(TFI_t * fi, int noDocs)
01240 {
01241 int i;
01242 char ** netsharedPaths = NULL;
01243 const char ** fileLangs;
01244 const char ** languages;
01245 const char * s;
01246
01247 if (!noDocs)
01248 noDocs = rpmExpandNumeric("%{_excludedocs}");
01249
01250 { const char *tmpPath = rpmExpand("%{_netsharedpath}", NULL);
01251 if (tmpPath && *tmpPath != '%')
01252 netsharedPaths = splitString(tmpPath, strlen(tmpPath), ':');
01253 free((void *)tmpPath);
01254 }
01255
01256 if (!headerGetEntry(fi->h, RPMTAG_FILELANGS, NULL, (void **) &fileLangs,
01257 NULL))
01258 fileLangs = NULL;
01259
01260 s = rpmExpand("%{_install_langs}", NULL);
01261 if (!(s && *s != '%')) {
01262 if (s) free((void *)s);
01263 s = NULL;
01264 }
01265 if (s) {
01266 languages = (const char **) splitString(s, strlen(s), ':');
01267 free((void *)s);
01268 } else
01269 languages = NULL;
01270
01271 for (i = 0; i < fi->fc; i++) {
01272 char **nsp;
01273
01274
01275 if (XFA_SKIPPING(fi->actions[i]))
01276 continue;
01277
01278
01279
01280
01281
01282
01283 for (nsp = netsharedPaths; nsp && *nsp; nsp++) {
01284 int len;
01285 const char * dir = fi->dnl[fi->dil[i]];
01286
01287 len = strlen(*nsp);
01288 if (strncmp(dir, *nsp, len))
01289 continue;
01290
01291
01292 if (!(dir[len] == '/' || dir[len] == '\0'))
01293 continue;
01294 break;
01295 }
01296
01297 if (nsp && *nsp) {
01298 fi->actions[i] = FA_SKIPNETSHARED;
01299 continue;
01300 }
01301
01302
01303
01304
01305 if (fileLangs && languages && *fileLangs[i]) {
01306 const char **lang, *l, *le;
01307 for (lang = languages; *lang; lang++) {
01308 if (!strcmp(*lang, "all"))
01309 break;
01310 for (l = fileLangs[i]; *l; l = le) {
01311 for (le = l; *le && *le != '|'; le++)
01312 ;
01313 if ((le-l) > 0 && !strncmp(*lang, l, (le-l)))
01314 break;
01315 if (*le == '|') le++;
01316 }
01317 if (*l) break;
01318 }
01319 if (*lang == NULL) {
01320 fi->actions[i] = FA_SKIPNSTATE;
01321 continue;
01322 }
01323 }
01324
01325
01326
01327
01328 if (noDocs && (fi->fflags[i] & RPMFILE_DOC))
01329 fi->actions[i] = FA_SKIPNSTATE;
01330 }
01331
01332 if (netsharedPaths) freeSplitString(netsharedPaths);
01333 if (fileLangs) free(fileLangs);
01334 if (languages) freeSplitString((char **)languages);
01335 }
01336
01337 #define NOTIFY(_ts, _al) if ((_ts)->notify) (void) (_ts)->notify _al
01338
01339 int rpmRunTransactions( rpmTransactionSet ts,
01340 rpmCallbackFunction notify, rpmCallbackData notifyData,
01341 rpmProblemSet okProbs, rpmProblemSet * newProbs,
01342 rpmtransFlags transFlags, rpmprobFilterFlags ignoreSet)
01343 {
01344 int i, j;
01345 int rc, ourrc = 0;
01346 struct availablePackage * alp;
01347 Header * hdrs;
01348 int totalFileCount = 0;
01349 hashTable ht;
01350 TFI_t * flList, * fi;
01351 struct sharedFileInfo * shared, * sharedList;
01352 int numShared;
01353 int flEntries;
01354 int nexti;
01355 int lastFailed;
01356 FD_t fd;
01357 const char ** filesystems;
01358 int filesystemCount;
01359 struct diskspaceInfo * di = NULL;
01360 int oc;
01361 fingerPrintCache fpc;
01362
01363
01364
01365 ts->transFlags = transFlags;
01366 ts->notify = notify;
01367 ts->notifyData = notifyData;
01368 ts->ignoreSet = ignoreSet;
01369 if (ts->currDir)
01370 free((void *)ts->currDir);
01371 ts->currDir = currentDirectory();
01372 ts->chrootDone = 0;
01373 { time_t t;
01374 time(&t);
01375 ts->id = t;
01376 }
01377
01378
01379 if (!(ts->ignoreSet & RPMPROB_FILTER_DISKSPACE) &&
01380 !rpmGetFilesystemList(&filesystems, &filesystemCount)) {
01381 struct stat sb;
01382
01383 di = alloca(sizeof(*di) * (filesystemCount + 1));
01384
01385 for (i = 0; (i < filesystemCount) && di; i++) {
01386 #if STATFS_IN_SYS_STATVFS
01387 struct statvfs sfb;
01388 memset(&sfb, 0, sizeof(sfb));
01389 if (statvfs(filesystems[i], &sfb))
01390 #else
01391 struct statfs sfb;
01392 # if STAT_STATFS4
01393
01394
01395
01396
01397
01398 memset(&sfb, 0, sizeof(sfb));
01399 if (statfs(filesystems[i], &sfb, sizeof(sfb), 0))
01400 # else
01401 memset(&sfb, 0, sizeof(sfb));
01402 if (statfs(filesystems[i], &sfb))
01403 # endif
01404 #endif
01405 {
01406 di = NULL;
01407 } else {
01408 di[i].bsize = sfb.f_bsize;
01409 di[i].bneeded = 0;
01410 di[i].ineeded = 0;
01411 #ifdef STATFS_HAS_F_BAVAIL
01412 di[i].bavail = sfb.f_bavail;
01413 #else
01414
01415
01416
01417
01418 di[i].bavail = sfb.f_blocks - sfb.f_bfree;
01419 #endif
01420
01421 di[i].iavail = (!(sfb.f_ffree == 0 && sfb.f_files == 0))
01422 ? sfb.f_ffree : -1;
01423
01424 stat(filesystems[i], &sb);
01425 di[i].dev = sb.st_dev;
01426 }
01427 }
01428
01429 if (di) di[i].bsize = 0;
01430 }
01431
01432 ts->probs = *newProbs = psCreate();
01433 hdrs = alloca(sizeof(*hdrs) * ts->addedPackages.size);
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444 for (alp = ts->addedPackages.list;
01445 (alp - ts->addedPackages.list) < ts->addedPackages.size;
01446 alp++)
01447 {
01448 if (!archOkay(alp->h) && !(ts->ignoreSet & RPMPROB_FILTER_IGNOREARCH))
01449 psAppend(ts->probs, RPMPROB_BADARCH, alp->key, alp->h,
01450 NULL, NULL, NULL, 0);
01451
01452 if (!osOkay(alp->h) && !(ts->ignoreSet & RPMPROB_FILTER_IGNOREOS))
01453 psAppend(ts->probs, RPMPROB_BADOS, alp->key, alp->h,
01454 NULL, NULL, NULL, 0);
01455
01456 if (!(ts->ignoreSet & RPMPROB_FILTER_OLDPACKAGE)) {
01457 rpmdbMatchIterator mi;
01458 Header oldH;
01459 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, alp->name, 0);
01460 while ((oldH = rpmdbNextIterator(mi)) != NULL)
01461 ensureOlder(ts->rpmdb, alp->h, oldH, ts->probs, alp->key);
01462 rpmdbFreeIterator(mi);
01463 }
01464
01465
01466 if (!(ts->ignoreSet & RPMPROB_FILTER_REPLACEPKG) && !alp->multiLib) {
01467 rpmdbMatchIterator mi;
01468 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, alp->name, 0);
01469 rpmdbSetIteratorVersion(mi, alp->version);
01470 rpmdbSetIteratorRelease(mi, alp->release);
01471 while (rpmdbNextIterator(mi) != NULL) {
01472 psAppend(ts->probs, RPMPROB_PKG_INSTALLED, alp->key, alp->h,
01473 NULL, NULL, NULL, 0);
01474 break;
01475 }
01476 rpmdbFreeIterator(mi);
01477 }
01478
01479 totalFileCount += alp->filesCount;
01480
01481 }
01482
01483
01484
01485 if (ts->numRemovedPackages > 0) {
01486 rpmdbMatchIterator mi;
01487 Header h;
01488 int fileCount;
01489
01490 mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES, NULL, 0);
01491 rpmdbAppendIterator(mi, ts->removedPackages, ts->numRemovedPackages);
01492 while ((h = rpmdbNextIterator(mi)) != NULL) {
01493 if (headerGetEntry(h, RPMTAG_BASENAMES, NULL, NULL, &fileCount))
01494 totalFileCount += fileCount;
01495 }
01496 rpmdbFreeIterator(mi);
01497 }
01498
01499
01500
01501
01502 flEntries = ts->addedPackages.size + ts->numRemovedPackages;
01503 flList = alloca(sizeof(*flList) * (flEntries));
01504
01505
01506
01507
01508
01509
01510 for (fi = flList, oc = 0; oc < ts->orderCount; fi++, oc++) {
01511 const char **preTrans;
01512 int preTransCount;
01513
01514 memset(fi, 0, sizeof(*fi));
01515 preTrans = NULL;
01516 preTransCount = 0;
01517
01518 switch (ts->order[oc].type) {
01519 case TR_ADDED:
01520 i = ts->order[oc].u.addedIndex;
01521 alp = ts->addedPackages.list + ts->order[oc].u.addedIndex;
01522
01523 if (!headerGetEntryMinMemory(alp->h, RPMTAG_BASENAMES, NULL,
01524 NULL, &fi->fc)) {
01525 fi->h = headerLink(alp->h);
01526 hdrs[i] = headerLink(fi->h);
01527 continue;
01528 }
01529
01530
01531 fi->actions = xcalloc(fi->fc, sizeof(*fi->actions));
01532 hdrs[i] = relocateFileList(ts, alp, alp->h, fi->actions);
01533 fi->h = headerLink(hdrs[i]);
01534 fi->ap = alp;
01535 fi->type = TR_ADDED;
01536 break;
01537 case TR_REMOVED:
01538 fi->record = ts->order[oc].u.removed.dboffset;
01539 { rpmdbMatchIterator mi;
01540
01541 mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES,
01542 &fi->record, sizeof(fi->record));
01543 if ((fi->h = rpmdbNextIterator(mi)) != NULL)
01544 fi->h = headerLink(fi->h);
01545 rpmdbFreeIterator(mi);
01546 }
01547 if (fi->h == NULL) {
01548
01549 continue;
01550 }
01551 fi->type = TR_REMOVED;
01552 break;
01553 }
01554 if (!headerGetEntry(fi->h, RPMTAG_BASENAMES, NULL,
01555 (void **) &fi->bnl, &fi->fc)) {
01556
01557 fi->dc = fi->fc = 0;
01558 continue;
01559 }
01560
01561 headerGetEntry(fi->h, RPMTAG_DIRINDEXES, NULL, (void **) &fi->dil,
01562 NULL);
01563 headerGetEntry(fi->h, RPMTAG_DIRNAMES, NULL, (void **) &fi->dnl,
01564 &fi->dc);
01565
01566
01567 if (fi->actions == NULL)
01568 fi->actions = xcalloc(fi->fc, sizeof(*fi->actions));
01569
01570 headerGetEntry(fi->h, RPMTAG_FILEMODES, NULL,
01571 (void **) &fi->fmodes, NULL);
01572 headerGetEntry(fi->h, RPMTAG_FILEFLAGS, NULL,
01573 (void **) &fi->fflags, NULL);
01574 headerGetEntry(fi->h, RPMTAG_FILESIZES, NULL,
01575 (void **) &fi->fsizes, NULL);
01576 headerGetEntry(fi->h, RPMTAG_FILESTATES, NULL,
01577 (void **) &fi->fstates, NULL);
01578
01579 switch (ts->order[oc].type) {
01580 case TR_REMOVED:
01581 headerGetEntry(fi->h, RPMTAG_FILEMD5S, NULL,
01582 (void **) &fi->fmd5s, NULL);
01583 headerGetEntry(fi->h, RPMTAG_FILELINKTOS, NULL,
01584 (void **) &fi->flinks, NULL);
01585 fi->fsizes = memcpy(xmalloc(fi->fc * sizeof(*fi->fsizes)),
01586 fi->fsizes, fi->fc * sizeof(*fi->fsizes));
01587 fi->fflags = memcpy(xmalloc(fi->fc * sizeof(*fi->fflags)),
01588 fi->fflags, fi->fc * sizeof(*fi->fflags));
01589 fi->fmodes = memcpy(xmalloc(fi->fc * sizeof(*fi->fmodes)),
01590 fi->fmodes, fi->fc * sizeof(*fi->fmodes));
01591
01592 if (fi->fstates)
01593 fi->fstates = memcpy(xmalloc(fi->fc * sizeof(*fi->fstates)),
01594 fi->fstates, fi->fc * sizeof(*fi->fstates));
01595 else
01596 fi->fstates = xcalloc(1, fi->fc * sizeof(*fi->fstates));
01597 fi->dil = memcpy(xmalloc(fi->fc * sizeof(*fi->dil)),
01598 fi->dil, fi->fc * sizeof(*fi->dil));
01599 headerFree(fi->h);
01600 fi->h = NULL;
01601 break;
01602 case TR_ADDED:
01603 headerGetEntryMinMemory(fi->h, RPMTAG_FILEMD5S, NULL,
01604 (const void **) &fi->fmd5s, NULL);
01605 headerGetEntryMinMemory(fi->h, RPMTAG_FILELINKTOS, NULL,
01606 (const void **) &fi->flinks, NULL);
01607
01608
01609 fi->replacedSizes = xcalloc(fi->fc, sizeof(*fi->replacedSizes));
01610
01611
01612 skipFiles(fi, ts->transFlags & RPMTRANS_FLAG_NODOCS);
01613 break;
01614 }
01615
01616 fi->fps = xmalloc(sizeof(*fi->fps) * fi->fc);
01617 }
01618
01619
01620 rpmdbOpenAll(ts->rpmdb);
01621
01622 chdir("/");
01623 chroot(ts->rootDir);
01624 ts->chrootDone = 1;
01625
01626 ht = htCreate(totalFileCount * 2, 0, 0, fpHashFunction, fpEqual);
01627 fpc = fpCacheCreate(totalFileCount);
01628
01629
01630
01631
01632 for (fi = flList; (fi - flList) < flEntries; fi++) {
01633 fpLookupList(fpc, fi->dnl, fi->bnl, fi->dil, fi->fc, fi->fps);
01634 for (i = 0; i < fi->fc; i++) {
01635 if (XFA_SKIPPING(fi->actions[i]))
01636 continue;
01637 htAddEntry(ht, fi->fps + i, fi);
01638 }
01639 }
01640
01641 NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_START, 6, flEntries,
01642 NULL, ts->notifyData));
01643
01644
01645
01646
01647 for (fi = flList; (fi - flList) < flEntries; fi++) {
01648 dbiIndexSet * matches;
01649 int knownBad;
01650
01651 NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_PROGRESS, (fi - flList), flEntries,
01652 NULL, ts->notifyData));
01653
01654 if (fi->fc == 0) continue;
01655
01656
01657 matches = xcalloc(sizeof(*matches), fi->fc);
01658 if (rpmdbFindFpList(ts->rpmdb, fi->fps, matches, fi->fc))
01659 return 1;
01660
01661 numShared = 0;
01662 for (i = 0; i < fi->fc; i++)
01663 numShared += dbiIndexSetCount(matches[i]);
01664
01665
01666 shared = sharedList = xmalloc(sizeof(*sharedList) * (numShared + 1));
01667 for (i = 0; i < fi->fc; i++) {
01668
01669
01670
01671
01672 for (j = 0; j < dbiIndexSetCount(matches[i]); j++) {
01673 int k, ro;
01674 ro = dbiIndexRecordOffset(matches[i], j);
01675 knownBad = 0;
01676 for (k = 0; ro != knownBad && k < ts->orderCount; k++) {
01677 switch (ts->order[k].type) {
01678 case TR_REMOVED:
01679 if (ts->order[k].u.removed.dboffset == ro)
01680 knownBad = ro;
01681 break;
01682 case TR_ADDED:
01683 break;
01684 }
01685 }
01686
01687 shared->pkgFileNum = i;
01688 shared->otherPkg = dbiIndexRecordOffset(matches[i], j);
01689 shared->otherFileNum = dbiIndexRecordFileNumber(matches[i], j);
01690 shared->isRemoved = (knownBad == ro);
01691 shared++;
01692 }
01693 if (matches[i]) {
01694 dbiFreeIndexSet(matches[i]);
01695 matches[i] = NULL;
01696 }
01697 }
01698 numShared = shared - sharedList;
01699 shared->otherPkg = -1;
01700 free((void *)matches);
01701
01702
01703 qsort(sharedList, numShared, sizeof(*shared), sharedCmp);
01704
01705
01706 for (i = 0; i < numShared; i = nexti) {
01707 int beingRemoved;
01708
01709 shared = sharedList + i;
01710
01711
01712 for (nexti = i + 1; nexti < numShared; nexti++) {
01713 if (sharedList[nexti].otherPkg != shared->otherPkg)
01714 break;
01715 }
01716
01717
01718 beingRemoved = 0;
01719 for (j = 0; j < ts->numRemovedPackages; j++) {
01720 if (ts->removedPackages[j] != shared->otherPkg)
01721 continue;
01722 beingRemoved = 1;
01723 break;
01724 }
01725
01726
01727 switch (fi->type) {
01728 case TR_ADDED:
01729 handleInstInstalledFiles(fi, ts->rpmdb, shared, nexti - i,
01730 !(beingRemoved || (ts->ignoreSet & RPMPROB_FILTER_REPLACEOLDFILES)),
01731 ts->probs, ts->transFlags);
01732 break;
01733 case TR_REMOVED:
01734 if (!beingRemoved)
01735 handleRmvdInstalledFiles(fi, ts->rpmdb, shared, nexti - i);
01736 break;
01737 }
01738 }
01739
01740 free(sharedList);
01741
01742
01743 handleOverlappedFiles(fi, ht,
01744 ((ts->ignoreSet & RPMPROB_FILTER_REPLACENEWFILES)
01745 ? NULL : ts->probs), di);
01746
01747
01748 switch (fi->type) {
01749 case TR_ADDED:
01750 if (!(di && fi->fc))
01751 break;
01752 for (i = 0; i < filesystemCount; i++) {
01753 struct diskspaceInfo * dip = di + i;
01754
01755
01756 if (dip->iavail <= 0)
01757 continue;
01758
01759 if (adj_fs_blocks(dip->bneeded) > dip->bavail)
01760 psAppend(ts->probs, RPMPROB_DISKSPACE, fi->ap->key,
01761 fi->ap->h, filesystems[i], NULL, NULL,
01762 (adj_fs_blocks(dip->bneeded) - dip->bavail) * dip->bsize);
01763
01764 if (adj_fs_blocks(dip->ineeded) > dip->iavail)
01765 psAppend(ts->probs, RPMPROB_DISKNODES, fi->ap->key,
01766 fi->ap->h, filesystems[i], NULL, NULL,
01767 (adj_fs_blocks(dip->ineeded) - dip->iavail));
01768 }
01769 break;
01770 case TR_REMOVED:
01771 break;
01772 }
01773 }
01774
01775 NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_STOP, 6, flEntries,
01776 NULL, ts->notifyData));
01777
01778 chroot(".");
01779 ts->chrootDone = 0;
01780 chdir(ts->currDir);
01781
01782
01783
01784
01785
01786 for (oc = 0, fi = flList; oc < ts->orderCount; oc++, fi++) {
01787 if (fi->fc == 0)
01788 continue;
01789 free(fi->bnl); fi->bnl = NULL;
01790 free(fi->dnl); fi->dnl = NULL;
01791 switch (fi->type) {
01792 case TR_ADDED:
01793 free(fi->fmd5s); fi->fmd5s = NULL;
01794 free(fi->flinks); fi->flinks = NULL;
01795 free(fi->fps); fi->fps = NULL;
01796 break;
01797 case TR_REMOVED:
01798 free((void *)fi->dil); fi->dil = NULL;
01799 free(fi->fps); fi->fps = NULL;
01800 break;
01801 }
01802 }
01803
01804 fpCacheFree(fpc);
01805 htFree(ht);
01806
01807
01808
01809
01810 if ((ts->transFlags & RPMTRANS_FLAG_BUILD_PROBS) ||
01811 (ts->probs->numProblems && (!okProbs || psTrim(okProbs, ts->probs)))) {
01812 *newProbs = ts->probs;
01813
01814 for (alp = ts->addedPackages.list, fi = flList;
01815 (alp - ts->addedPackages.list) < ts->addedPackages.size;
01816 alp++, fi++) {
01817 headerFree(hdrs[alp - ts->addedPackages.list]);
01818 }
01819
01820 freeFl(ts, flList);
01821 return ts->orderCount;
01822 }
01823
01824
01825
01826
01827
01828 lastFailed = -2;
01829 for (oc = 0, fi = flList; oc < ts->orderCount; oc++, fi++) {
01830 switch (ts->order[oc].type) {
01831 case TR_ADDED:
01832 alp = ts->addedPackages.list + ts->order[oc].u.addedIndex;
01833 i = ts->order[oc].u.addedIndex;
01834
01835 if ((fd = alp->fd) == 0) {
01836 fd = ts->notify(fi->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
01837 alp->key, ts->notifyData);
01838 if (fd) {
01839 Header h;
01840
01841 headerFree(hdrs[i]);
01842 rc = rpmReadPackageHeader(fd, &h, NULL, NULL, NULL);
01843 if (rc) {
01844 (void)ts->notify(fi->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
01845 alp->key, ts->notifyData);
01846 ourrc++;
01847 fd = NULL;
01848 } else {
01849 hdrs[i] = relocateFileList(ts, alp, h, NULL);
01850 headerFree(h);
01851 }
01852 }
01853 }
01854
01855 if (fd) {
01856
01857 if (alp->multiLib)
01858 ts->transFlags |= RPMTRANS_FLAG_MULTILIB;
01859
01860 if (installBinaryPackage(ts, fd, hdrs[i],
01861 alp->key, fi->actions,
01862 fi->fc ? fi->replaced : NULL)) {
01863 ourrc++;
01864 lastFailed = i;
01865 }
01866 } else {
01867 ourrc++;
01868 lastFailed = i;
01869 }
01870
01871 headerFree(hdrs[i]);
01872
01873 if (alp->fd == NULL && fd)
01874 (void)ts->notify(fi->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
01875 alp->key, ts->notifyData);
01876 break;
01877 case TR_REMOVED:
01878 { unsigned int offset = fi->record;
01879 Header dbh;
01880
01881
01882 if (ts->order[oc].u.removed.dependsOnIndex == lastFailed)
01883 break;
01884
01885 { rpmdbMatchIterator mi = NULL;
01886
01887 mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES,
01888 &offset, sizeof(offset));
01889
01890 dbh = rpmdbNextIterator(mi);
01891 if (dbh == NULL) {
01892 rpmdbFreeIterator(mi);
01893 ourrc++;
01894 break;
01895 }
01896 dbh = headerLink(dbh);
01897 rpmdbFreeIterator(mi);
01898 }
01899
01900 if (removeBinaryPackage(ts, offset, dbh, NULL, fi->actions))
01901 ourrc++;
01902
01903 headerFree(dbh);
01904 } break;
01905 }
01906 (void) rpmdbSync(ts->rpmdb);
01907 }
01908
01909 freeFl(ts, flList);
01910
01911 if (ourrc)
01912 return -1;
01913 else
01914 return 0;
01915 }