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