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
00408 for (j = 0; j < numValid; j++)
00409 if (!strcmp(validRelocations[j], relocations[i].oldPath))
00410 break;
00411
00412 if (j == numValid && !allowBadRelocate && actions)
00413 psAppend(probs, RPMPROB_BADRELOCATE, alp,
00414 relocations[i].oldPath, NULL, NULL, 0);
00415 del =
00416 strlen(relocations[i].newPath) - strlen(relocations[i].oldPath);
00417
00418
00419 if (del > reldel)
00420 reldel = del;
00421 } else {
00422 relocations[i].newPath = NULL;
00423 }
00424 }
00425
00426
00427 for (i = 0; i < numRelocations; i++) {
00428 int madeSwap;
00429 madeSwap = 0;
00430 for (j = 1; j < numRelocations; j++) {
00431 rpmRelocation tmpReloc;
00432 if (relocations[j - 1].oldPath == NULL ||
00433 relocations[j ].oldPath == NULL ||
00434 strcmp(relocations[j - 1].oldPath, relocations[j].oldPath) <= 0)
00435 continue;
00436 tmpReloc = relocations[j - 1];
00437 relocations[j - 1] = relocations[j];
00438 relocations[j] = tmpReloc;
00439 madeSwap = 1;
00440 }
00441 if (!madeSwap) break;
00442 }
00443
00444 if (!_printed) {
00445 _printed = 1;
00446 rpmMessage(RPMMESS_DEBUG, _("========== relocations\n"));
00447 for (i = 0; i < numRelocations; i++) {
00448 if (relocations[i].oldPath == NULL) continue;
00449 if (relocations[i].newPath == NULL)
00450 rpmMessage(RPMMESS_DEBUG, _("%5d exclude %s\n"),
00451 i, relocations[i].oldPath);
00452 else
00453 rpmMessage(RPMMESS_DEBUG, _("%5d relocate %s -> %s\n"),
00454 i, relocations[i].oldPath, relocations[i].newPath);
00455 }
00456 }
00457
00458
00459 if (numValid) {
00460 const char ** actualRelocations;
00461 int numActual;
00462
00463 actualRelocations = xmalloc(numValid * sizeof(*actualRelocations));
00464 numActual = 0;
00465 for (i = 0; i < numValid; i++) {
00466 for (j = 0; j < numRelocations; j++) {
00467 if (relocations[j].oldPath == NULL ||
00468 strcmp(validRelocations[i], relocations[j].oldPath))
00469 continue;
00470
00471 if (relocations[j].newPath) {
00472 actualRelocations[numActual] = relocations[j].newPath;
00473 numActual++;
00474 }
00475 break;
00476 }
00477 if (j == numRelocations) {
00478 actualRelocations[numActual] = validRelocations[i];
00479 numActual++;
00480 }
00481 }
00482
00483 if (numActual)
00484 (void) hae(h, RPMTAG_INSTPREFIXES, RPM_STRING_ARRAY_TYPE,
00485 (void **) actualRelocations, numActual);
00486
00487 actualRelocations = _free(actualRelocations);
00488 validRelocations = hfd(validRelocations, validType);
00489 }
00490
00491 (void) hge(h, RPMTAG_BASENAMES, NULL, (void **) &baseNames, &fileCount);
00492 (void) hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL);
00493 (void) hge(h, RPMTAG_DIRNAMES, NULL, (void **) &dirNames, &dirCount);
00494 (void) hge(h, RPMTAG_FILEFLAGS, NULL, (void **) &fFlags, NULL);
00495 (void) hge(h, RPMTAG_FILEMODES, NULL, (void **) &fModes, NULL);
00496
00497 skipDirList = alloca(dirCount * sizeof(*skipDirList));
00498 memset(skipDirList, 0, dirCount * sizeof(*skipDirList));
00499
00500 newDirIndexes = alloca(sizeof(*newDirIndexes) * fileCount);
00501 memcpy(newDirIndexes, dirIndexes, sizeof(*newDirIndexes) * fileCount);
00502 dirIndexes = newDirIndexes;
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 for (i = fileCount - 1; i >= 0; i--) {
00513 fileTypes ft;
00514 int fnlen;
00515
00516
00517
00518
00519
00520 if (alp->multiLib && !isFileMULTILIB((fFlags[i]))) {
00521 if (actions) {
00522 actions[i] = FA_SKIPMULTILIB;
00523 rpmMessage(RPMMESS_DEBUG, _("excluding multilib path %s%s\n"),
00524 dirNames[dirIndexes[i]], baseNames[i]);
00525 }
00526 continue;
00527 }
00528
00529 len = reldel +
00530 strlen(dirNames[dirIndexes[i]]) + strlen(baseNames[i]) + 1;
00531 if (len >= fileAlloced) {
00532 fileAlloced = len * 2;
00533 fn = xrealloc(fn, fileAlloced);
00534 }
00535 *fn = '\0';
00536 fnlen = stpcpy( stpcpy(fn, dirNames[dirIndexes[i]]), baseNames[i]) - fn;
00537
00538
00539
00540
00541
00542
00543
00544
00545 for (j = numRelocations - 1; j >= 0; j--) {
00546 if (relocations[j].oldPath == NULL) continue;
00547 len = strcmp(relocations[j].oldPath, "/")
00548 ? strlen(relocations[j].oldPath)
00549 : 0;
00550
00551 if (fnlen < len)
00552 continue;
00553
00554
00555
00556
00557 if (!(fn[len] == '/' || fnlen == len))
00558 continue;
00559
00560 if (strncmp(relocations[j].oldPath, fn, len))
00561 continue;
00562 break;
00563 }
00564 if (j < 0) continue;
00565
00566 ft = whatis(fModes[i]);
00567
00568
00569 if (relocations[j].newPath == NULL) {
00570 if (ft == XDIR) {
00571
00572 for (j = dirIndexes[i]; j < dirCount; j++) {
00573 len = strlen(dirNames[j]) - 1;
00574 while (len > 0 && dirNames[j][len-1] == '/') len--;
00575 if (fnlen != len)
00576 continue;
00577 if (strncmp(fn, dirNames[j], fnlen))
00578 continue;
00579 break;
00580 }
00581 if (j < dirCount)
00582 skipDirList[j] = 1;
00583 }
00584 if (actions) {
00585 actions[i] = FA_SKIPNSTATE;
00586 rpmMessage(RPMMESS_DEBUG, _("excluding %s %s\n"),
00587 ftstring(ft), fn);
00588 }
00589 continue;
00590 }
00591
00592
00593 if (fnlen != len) continue;
00594
00595 if (actions)
00596 rpmMessage(RPMMESS_DEBUG, _("relocating %s to %s\n"),
00597 fn, relocations[j].newPath);
00598 nrelocated++;
00599
00600 strcpy(fn, relocations[j].newPath);
00601 { char * te = strrchr(fn, '/');
00602 if (te) {
00603 if (te > fn) te++;
00604 fnlen = te - fn;
00605 } else
00606 te = fn + strlen(fn);
00607
00608 if (strcmp(baseNames[i], te))
00609 baseNames[i] = alloca_strdup(te);
00610 *te = '\0';
00611
00612 }
00613
00614
00615 for (j = 0; j < dirCount; j++) {
00616 if (fnlen != strlen(dirNames[j]))
00617 continue;
00618 if (strncmp(fn, dirNames[j], fnlen))
00619 continue;
00620 break;
00621 }
00622
00623 if (j < dirCount) {
00624 dirIndexes[i] = j;
00625 continue;
00626 }
00627
00628
00629 if (!haveRelocatedFile) {
00630 const char ** newDirList;
00631
00632 haveRelocatedFile = 1;
00633 newDirList = xmalloc((dirCount + 1) * sizeof(*newDirList));
00634 for (j = 0; j < dirCount; j++)
00635 newDirList[j] = alloca_strdup(dirNames[j]);
00636 dirNames = hfd(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
00652 if (relocations[j].oldPath == NULL) continue;
00653 len = strcmp(relocations[j].oldPath, "/")
00654 ? strlen(relocations[j].oldPath)
00655 : 0;
00656
00657 if (len && strncmp(relocations[j].oldPath, dirNames[i], len))
00658 continue;
00659
00660
00661
00662
00663
00664 if (dirNames[i][len] != '/')
00665 continue;
00666
00667 if (relocations[j].newPath) {
00668 const char * s = relocations[j].newPath;
00669 char * t = alloca(strlen(s) + strlen(dirNames[i]) - len + 1);
00670
00671 (void) stpcpy( stpcpy(t, s) , dirNames[i] + len);
00672 if (actions)
00673 rpmMessage(RPMMESS_DEBUG,
00674 _("relocating directory %s to %s\n"), dirNames[i], t);
00675 dirNames[i] = t;
00676 nrelocated++;
00677 }
00678 }
00679 }
00680
00681
00682 if (nrelocated) {
00683 int c;
00684 void * p;
00685 rpmTagType t;
00686
00687 p = NULL;
00688 (void) hge(h, RPMTAG_BASENAMES, &t, &p, &c);
00689 (void) hae(h, RPMTAG_ORIGBASENAMES, t, p, c);
00690 p = hfd(p, t);
00691
00692 p = NULL;
00693 (void) hge(h, RPMTAG_DIRNAMES, &t, &p, &c);
00694 (void) hae(h, RPMTAG_ORIGDIRNAMES, t, p, c);
00695 p = hfd(p, t);
00696
00697 p = NULL;
00698 (void) hge(h, RPMTAG_DIRINDEXES, &t, &p, &c);
00699 (void) hae(h, RPMTAG_ORIGDIRINDEXES, t, p, c);
00700 p = hfd(p, t);
00701
00702 (void) hme(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
00703 baseNames, fileCount);
00704 fi->bnl = hfd(fi->bnl, RPM_STRING_ARRAY_TYPE);
00705 (void) hge(h, RPMTAG_BASENAMES, NULL, (void **) &fi->bnl, &fi->fc);
00706
00707 (void) hme(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
00708 dirNames, dirCount);
00709 fi->dnl = hfd(fi->dnl, RPM_STRING_ARRAY_TYPE);
00710 (void) hge(h, RPMTAG_DIRNAMES, NULL, (void **) &fi->dnl, &fi->dc);
00711
00712 (void) hme(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE,
00713 dirIndexes, fileCount);
00714 (void) hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &fi->dil, NULL);
00715 }
00716
00717 baseNames = hfd(baseNames, RPM_STRING_ARRAY_TYPE);
00718 dirNames = hfd(dirNames, RPM_STRING_ARRAY_TYPE);
00719 fn = _free(fn);
00720
00721 return h;
00722 }
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733 static int psTrim(rpmProblemSet filter, rpmProblemSet target)
00734
00735 {
00736 rpmProblem f = filter->probs;
00737 rpmProblem t = target->probs;
00738 int gotProblems = 0;
00739
00740 while ((f - filter->probs) < filter->numProblems) {
00741 if (!f->ignoreProblem) {
00742 f++;
00743 continue;
00744 }
00745 while ((t - target->probs) < target->numProblems) {
00746
00747 if (f->h == t->h && f->type == t->type && t->key == f->key &&
00748 XSTRCMP(f->str1, t->str1))
00749 break;
00750
00751 t++;
00752 gotProblems = 1;
00753 }
00754
00755 if ((t - target->probs) == target->numProblems) {
00756
00757 break;
00758 }
00759
00760 t->ignoreProblem = f->ignoreProblem;
00761 t++, f++;
00762 }
00763
00764 if ((t - target->probs) < target->numProblems)
00765 gotProblems = 1;
00766
00767 return gotProblems;
00768 }
00769
00770 static int sharedCmp(const void * one, const void * two)
00771
00772 {
00773 const struct sharedFileInfo * a = one;
00774 const struct sharedFileInfo * b = two;
00775
00776 if (a->otherPkg < b->otherPkg)
00777 return -1;
00778 else if (a->otherPkg > b->otherPkg)
00779 return 1;
00780
00781 return 0;
00782 }
00783
00784 static fileAction decideFileFate(const char * dirName,
00785 const char * baseName, short dbMode,
00786 const char * dbMd5, const char * dbLink, short newMode,
00787 const char * newMd5, const char * newLink, int newFlags,
00788 int brokenMd5, rpmtransFlags transFlags)
00789
00790 {
00791 char buffer[1024];
00792 const char * dbAttr, * newAttr;
00793 fileTypes dbWhat, newWhat, diskWhat;
00794 struct stat sb;
00795 int i, rc;
00796 int save = (newFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SAVE;
00797 char * filespec = alloca(strlen(dirName) + strlen(baseName) + 1);
00798
00799 (void) stpcpy( stpcpy(filespec, dirName), baseName);
00800
00801 if (lstat(filespec, &sb)) {
00802
00803
00804
00805
00806 if (!(transFlags & RPMTRANS_FLAG_ALLFILES) &&
00807 (newFlags & RPMFILE_MISSINGOK)) {
00808 rpmMessage(RPMMESS_DEBUG, _("%s skipped due to missingok flag\n"),
00809 filespec);
00810 return FA_SKIP;
00811 } else {
00812 return FA_CREATE;
00813 }
00814 }
00815
00816 diskWhat = whatis(sb.st_mode);
00817 dbWhat = whatis(dbMode);
00818 newWhat = whatis(newMode);
00819
00820
00821
00822 if (newWhat == XDIR) {
00823 return FA_CREATE;
00824 }
00825
00826 if (diskWhat != newWhat) {
00827 return save;
00828 } else if (newWhat != dbWhat && diskWhat != dbWhat) {
00829 return save;
00830 } else if (dbWhat != newWhat) {
00831 return FA_CREATE;
00832 } else if (dbWhat != LINK && dbWhat != REG) {
00833 return FA_CREATE;
00834 }
00835
00836 if (dbWhat == REG) {
00837 if (brokenMd5)
00838 rc = mdfileBroken(filespec, buffer);
00839 else
00840 rc = mdfile(filespec, buffer);
00841
00842 if (rc) {
00843
00844 return FA_CREATE;
00845 }
00846 dbAttr = dbMd5;
00847 newAttr = newMd5;
00848 } else {
00849 memset(buffer, 0, sizeof(buffer));
00850 i = readlink(filespec, buffer, sizeof(buffer) - 1);
00851 if (i == -1) {
00852
00853 return FA_CREATE;
00854 }
00855 dbAttr = dbLink;
00856 newAttr = newLink;
00857 }
00858
00859
00860
00861
00862 if (!strcmp(dbAttr, buffer)) {
00863
00864 return FA_CREATE;
00865 }
00866
00867 if (!strcmp(dbAttr, newAttr)) {
00868
00869 return FA_SKIP;
00870 }
00871
00872
00873
00874
00875
00876
00877
00878 return save;
00879 }
00880
00881 static int filecmp(short mode1, const char * md51, const char * link1,
00882 short mode2, const char * md52, const char * link2)
00883
00884 {
00885 fileTypes what1 = whatis(mode1);
00886 fileTypes what2 = whatis(mode2);
00887
00888 if (what1 != what2) return 1;
00889
00890 if (what1 == LINK)
00891 return strcmp(link1, link2);
00892 else if (what1 == REG)
00893 return strcmp(md51, md52);
00894
00895 return 0;
00896 }
00897
00898 static int handleInstInstalledFiles(TFI_t fi, rpmdb db,
00899 struct sharedFileInfo * shared,
00900 int sharedCount, int reportConflicts,
00901 rpmProblemSet probs,
00902 rpmtransFlags transFlags)
00903
00904 {
00905 HGE_t hge = fi->hge;
00906 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
00907 rpmTagType oltype, omtype;
00908 Header h;
00909 int i;
00910 const char ** otherMd5s;
00911 const char ** otherLinks;
00912 const char * otherStates;
00913 uint_32 * otherFlags;
00914 uint_32 * otherSizes;
00915 uint_16 * otherModes;
00916 int numReplaced = 0;
00917
00918 rpmdbMatchIterator mi;
00919
00920 mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, &shared->otherPkg, sizeof(shared->otherPkg));
00921 h = rpmdbNextIterator(mi);
00922 if (h == NULL) {
00923 mi = rpmdbFreeIterator(mi);
00924 return 1;
00925 }
00926
00927 (void) hge(h, RPMTAG_FILEMD5S, &omtype, (void **) &otherMd5s, NULL);
00928 (void) hge(h, RPMTAG_FILELINKTOS, &oltype, (void **) &otherLinks, NULL);
00929 (void) hge(h, RPMTAG_FILESTATES, NULL, (void **) &otherStates, NULL);
00930 (void) hge(h, RPMTAG_FILEMODES, NULL, (void **) &otherModes, NULL);
00931 (void) hge(h, RPMTAG_FILEFLAGS, NULL, (void **) &otherFlags, NULL);
00932 (void) hge(h, RPMTAG_FILESIZES, NULL, (void **) &otherSizes, NULL);
00933
00934 fi->replaced = xmalloc(sharedCount * sizeof(*fi->replaced));
00935
00936 for (i = 0; i < sharedCount; i++, shared++) {
00937 int otherFileNum, fileNum;
00938 otherFileNum = shared->otherFileNum;
00939 fileNum = shared->pkgFileNum;
00940
00941
00942 if (otherStates && otherStates[otherFileNum] != RPMFILE_STATE_NORMAL)
00943 continue;
00944
00945 if (XFA_SKIPPING(fi->actions[fileNum]))
00946 continue;
00947
00948 if (filecmp(otherModes[otherFileNum],
00949 otherMd5s[otherFileNum],
00950 otherLinks[otherFileNum],
00951 fi->fmodes[fileNum],
00952 fi->fmd5s[fileNum],
00953 fi->flinks[fileNum])) {
00954 if (reportConflicts)
00955 psAppend(probs, RPMPROB_FILE_CONFLICT, fi->ap,
00956 fi->dnl[fi->dil[fileNum]], fi->bnl[fileNum], h, 0);
00957 if (!(otherFlags[otherFileNum] | fi->fflags[fileNum])
00958 & RPMFILE_CONFIG) {
00959
00960 if (!shared->isRemoved)
00961 fi->replaced[numReplaced++] = *shared;
00962
00963 }
00964 }
00965
00966 if ((otherFlags[otherFileNum] | fi->fflags[fileNum]) & RPMFILE_CONFIG) {
00967 fi->actions[fileNum] = decideFileFate(
00968 fi->dnl[fi->dil[fileNum]],
00969 fi->bnl[fileNum],
00970 otherModes[otherFileNum],
00971 otherMd5s[otherFileNum],
00972 otherLinks[otherFileNum],
00973 fi->fmodes[fileNum],
00974 fi->fmd5s[fileNum],
00975 fi->flinks[fileNum],
00976 fi->fflags[fileNum],
00977 !headerIsEntry(h, RPMTAG_RPMVERSION),
00978 transFlags);
00979 }
00980
00981 fi->replacedSizes[fileNum] = otherSizes[otherFileNum];
00982 }
00983
00984 otherMd5s = hfd(otherMd5s, omtype);
00985 otherLinks = hfd(otherLinks, oltype);
00986 mi = rpmdbFreeIterator(mi);
00987
00988 fi->replaced = xrealloc(fi->replaced,
00989 sizeof(*fi->replaced) * (numReplaced + 1));
00990 fi->replaced[numReplaced].otherPkg = 0;
00991
00992 return 0;
00993 }
00994
00995 static int handleRmvdInstalledFiles(TFI_t fi, rpmdb db,
00996 struct sharedFileInfo * shared,
00997 int sharedCount)
00998
00999 {
01000 HGE_t hge = fi->hge;
01001 Header h;
01002 const char * otherStates;
01003 int i;
01004
01005 rpmdbMatchIterator mi;
01006
01007 mi = rpmdbInitIterator(db, RPMDBI_PACKAGES,
01008 &shared->otherPkg, sizeof(shared->otherPkg));
01009 h = rpmdbNextIterator(mi);
01010 if (h == NULL) {
01011 mi = rpmdbFreeIterator(mi);
01012 return 1;
01013 }
01014
01015 (void) hge(h, RPMTAG_FILESTATES, NULL, (void **) &otherStates, NULL);
01016
01017 for (i = 0; i < sharedCount; i++, shared++) {
01018 int otherFileNum, fileNum;
01019 otherFileNum = shared->otherFileNum;
01020 fileNum = shared->pkgFileNum;
01021
01022 if (otherStates[otherFileNum] != RPMFILE_STATE_NORMAL)
01023 continue;
01024
01025 fi->actions[fileNum] = FA_SKIP;
01026 }
01027
01028 mi = rpmdbFreeIterator(mi);
01029
01030 return 0;
01031 }
01032
01036 static void handleOverlappedFiles(TFI_t fi, hashTable ht,
01037 rpmProblemSet probs, struct diskspaceInfo * dsl)
01038
01039 {
01040 int i, j;
01041 struct diskspaceInfo * ds = NULL;
01042 uint_32 fixupSize = 0;
01043 char * filespec = NULL;
01044 int fileSpecAlloced = 0;
01045
01046 for (i = 0; i < fi->fc; i++) {
01047 int otherPkgNum, otherFileNum;
01048 const TFI_t * recs;
01049 int numRecs;
01050
01051 if (XFA_SKIPPING(fi->actions[i]))
01052 continue;
01053
01054 j = strlen(fi->dnl[fi->dil[i]]) + strlen(fi->bnl[i]) + 1;
01055 if (j > fileSpecAlloced) {
01056 fileSpecAlloced = j * 2;
01057 filespec = xrealloc(filespec, fileSpecAlloced);
01058 }
01059
01060 (void) stpcpy( stpcpy( filespec, fi->dnl[fi->dil[i]]), fi->bnl[i]);
01061
01062 if (dsl) {
01063 ds = dsl;
01064 while (ds->bsize && ds->dev != fi->fps[i].entry->dev) ds++;
01065 if (!ds->bsize) ds = NULL;
01066 fixupSize = 0;
01067 }
01068
01069
01070
01071
01072
01073
01074
01075 (void) htGetEntry(ht, &fi->fps[i], (const void ***) &recs, &numRecs, NULL);
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098 for (j = 0; j < numRecs && recs[j] != fi; j++)
01099 {};
01100
01101
01102 otherFileNum = -1;
01103 for (otherPkgNum = j - 1; otherPkgNum >= 0; otherPkgNum--) {
01104
01105 if (fi->type == TR_ADDED && recs[otherPkgNum]->type != TR_ADDED)
01106 continue;
01107
01108
01109 for (otherFileNum = 0; otherFileNum < recs[otherPkgNum]->fc;
01110 otherFileNum++) {
01111
01112
01113 if ((fi->fps + i) == (recs[otherPkgNum]->fps + otherFileNum))
01114 break;
01115
01116
01117
01118 if (FP_EQUAL(fi->fps[i], recs[otherPkgNum]->fps[otherFileNum]))
01119 break;
01120
01121
01122 }
01123
01124 if (recs[otherPkgNum]->actions[otherFileNum] != FA_UNKNOWN)
01125 break;
01126 }
01127
01128 switch (fi->type) {
01129 case TR_ADDED:
01130 { struct stat sb;
01131 if (otherPkgNum < 0) {
01132
01133 if (fi->actions[i] != FA_UNKNOWN)
01134 break;
01135 if ((fi->fflags[i] & RPMFILE_CONFIG) &&
01136 !lstat(filespec, &sb)) {
01137
01138 fi->actions[i] = (fi->fflags[i] & RPMFILE_NOREPLACE)
01139 ? FA_ALTNAME : FA_BACKUP;
01140 } else {
01141 fi->actions[i] = FA_CREATE;
01142 }
01143 break;
01144 }
01145
01146
01147 if (probs && filecmp(recs[otherPkgNum]->fmodes[otherFileNum],
01148 recs[otherPkgNum]->fmd5s[otherFileNum],
01149 recs[otherPkgNum]->flinks[otherFileNum],
01150 fi->fmodes[i],
01151 fi->fmd5s[i],
01152 fi->flinks[i])) {
01153 psAppend(probs, RPMPROB_NEW_FILE_CONFLICT, fi->ap,
01154 filespec, NULL, recs[otherPkgNum]->ap->h, 0);
01155 }
01156
01157
01158 fixupSize = recs[otherPkgNum]->fsizes[otherFileNum];
01159
01160 if ((fi->fflags[i] & RPMFILE_CONFIG) && !lstat(filespec, &sb)) {
01161
01162 fi->actions[i] = (fi->fflags[i] & RPMFILE_NOREPLACE)
01163 ? FA_ALTNAME : FA_SKIP;
01164 } else {
01165 fi->actions[i] = FA_CREATE;
01166 }
01167 } break;
01168 case TR_REMOVED:
01169 if (otherPkgNum >= 0) {
01170
01171 if (recs[otherPkgNum]->actions[otherFileNum] != FA_ERASE) {
01172
01173 fi->actions[i] = FA_SKIP;
01174 break;
01175 }
01176
01177 recs[otherPkgNum]->actions[otherFileNum] = FA_SKIP;
01178 }
01179 if (XFA_SKIPPING(fi->actions[i]))
01180 break;
01181 if (fi->fstates && fi->fstates[i] != RPMFILE_STATE_NORMAL)
01182 break;
01183 if (!(S_ISREG(fi->fmodes[i]) && (fi->fflags[i] & RPMFILE_CONFIG))) {
01184 fi->actions[i] = FA_ERASE;
01185 break;
01186 }
01187
01188
01189 { char mdsum[50];
01190 if (!mdfile(filespec, mdsum) && strcmp(fi->fmd5s[i], mdsum)) {
01191 fi->actions[i] = FA_BACKUP;
01192 break;
01193 }
01194 }
01195 fi->actions[i] = FA_ERASE;
01196 break;
01197 }
01198
01199 if (ds) {
01200 uint_32 s = BLOCK_ROUND(fi->fsizes[i], ds->bsize);
01201
01202 switch (fi->actions[i]) {
01203 case FA_BACKUP:
01204 case FA_SAVE:
01205 case FA_ALTNAME:
01206 ds->ineeded++;
01207 ds->bneeded += s;
01208 break;
01209
01210
01211
01212
01213
01214
01215 case FA_CREATE:
01216 ds->bneeded += s;
01217 ds->bneeded -= BLOCK_ROUND(fi->replacedSizes[i], ds->bsize);
01218 break;
01219
01220 case FA_ERASE:
01221 ds->ineeded--;
01222 ds->bneeded -= s;
01223 break;
01224
01225 default:
01226 break;
01227 }
01228
01229 ds->bneeded -= BLOCK_ROUND(fixupSize, ds->bsize);
01230 }
01231 }
01232 if (filespec) free(filespec);
01233 }
01234
01235 static int ensureOlder(struct availablePackage * alp, Header old,
01236 rpmProblemSet probs)
01237
01238 {
01239 int result, rc = 0;
01240
01241 if (old == NULL) return 1;
01242
01243 result = rpmVersionCompare(old, alp->h);
01244 if (result <= 0)
01245 rc = 0;
01246 else if (result > 0) {
01247 rc = 1;
01248 psAppend(probs, RPMPROB_OLDPACKAGE, alp, NULL, NULL, old, 0);
01249 }
01250
01251 return rc;
01252 }
01253
01254 static void skipFiles(const rpmTransactionSet ts, TFI_t fi)
01255
01256 {
01257 int noDocs = (ts->transFlags & RPMTRANS_FLAG_NODOCS);
01258 char ** netsharedPaths = NULL;
01259 const char ** languages;
01260 const char * dn, * bn;
01261 int dnlen, bnlen, ix;
01262 const char * s;
01263 int * drc;
01264 char * dff;
01265 int i, j;
01266
01267 if (!noDocs)
01268 noDocs = rpmExpandNumeric("%{_excludedocs}");
01269
01270 { const char *tmpPath = rpmExpand("%{_netsharedpath}", NULL);
01271 if (tmpPath && *tmpPath != '%')
01272 netsharedPaths = splitString(tmpPath, strlen(tmpPath), ':');
01273 tmpPath = _free(tmpPath);
01274 }
01275
01276 {
01277 char *tmp;
01278
01279 tmp = getenv("RPM_INSTALL_LANG");
01280 if (tmp && *tmp) {
01281 s = malloc(strlen(tmp)+1);
01282 strcpy(s, tmp);
01283 } else {
01284 s = rpmExpand("%{_install_langs}", NULL);
01285 }
01286 }
01287 if (!(s && *s != '%'))
01288 s = _free(s);
01289 if (s) {
01290 languages = (const char **) splitString(s, strlen(s), ':');
01291 s = _free(s);
01292 } else
01293 languages = NULL;
01294
01295
01296 drc = alloca(fi->dc * sizeof(*drc));
01297 memset(drc, 0, fi->dc * sizeof(*drc));
01298 dff = alloca(fi->dc * sizeof(*dff));
01299 memset(dff, 0, fi->dc * sizeof(*dff));
01300
01301 for (i = 0; i < fi->fc; i++) {
01302 char **nsp;
01303
01304 bn = fi->bnl[i];
01305 bnlen = strlen(bn);
01306 ix = fi->dil[i];
01307 dn = fi->dnl[ix];
01308 dnlen = strlen(dn);
01309
01310 drc[ix]++;
01311
01312
01313 if (XFA_SKIPPING(fi->actions[i])) {
01314 drc[ix]--;
01315 continue;
01316 }
01317
01318
01319
01320
01321
01322
01323 for (nsp = netsharedPaths; nsp && *nsp; nsp++) {
01324 int len;
01325
01326 len = strlen(*nsp);
01327 if (dnlen >= len) {
01328 if (strncmp(dn, *nsp, len)) continue;
01329
01330 if (!(dn[len] == '/' || dn[len] == '\0')) continue;
01331 } else {
01332 if (len < (dnlen + bnlen)) continue;
01333 if (strncmp(dn, *nsp, dnlen)) continue;
01334 if (strncmp(bn, (*nsp) + dnlen, bnlen)) continue;
01335 len = dnlen + bnlen;
01336
01337 if (!((*nsp)[len] == '/' || (*nsp)[len] == '\0')) continue;
01338 }
01339
01340 break;
01341 }
01342
01343 if (nsp && *nsp) {
01344 drc[ix]--; dff[ix] = 1;
01345 fi->actions[i] = FA_SKIPNETSHARED;
01346 continue;
01347 }
01348
01349
01350
01351
01352 if (fi->flangs && languages && *fi->flangs[i]) {
01353 const char **lang, *l, *le;
01354 for (lang = languages; *lang != '\0'; lang++) {
01355 if (!strcmp(*lang, "all"))
01356 break;
01357 for (l = fi->flangs[i]; *l != '\0'; l = le) {
01358 for (le = l; *le != '\0' && *le != '|'; le++)
01359 {};
01360 if ((le-l) > 0 && !strncmp(*lang, l, (le-l)))
01361 break;
01362 if (*le == '|') le++;
01363 }
01364 if (*l != '\0')
01365 break;
01366 }
01367 if (*lang == NULL) {
01368 drc[ix]--; dff[ix] = 1;
01369 fi->actions[i] = FA_SKIPNSTATE;
01370 continue;
01371 }
01372 }
01373
01374
01375
01376
01377 if (noDocs && (fi->fflags[i] & RPMFILE_DOC)) {
01378 drc[ix]--; dff[ix] = 1;
01379 fi->actions[i] = FA_SKIPNSTATE;
01380 continue;
01381 }
01382 }
01383
01384
01385 for (j = 0; j < fi->dc; j++) {
01386
01387 if (drc[j]) continue;
01388 if (!dff[j]) continue;
01389
01390
01391 dn = fi->dnl[j]; dnlen = strlen(dn) - 1;
01392 bn = dn + dnlen; bnlen = 0;
01393 while (bn > dn && bn[-1] != '/') {
01394 bnlen++;
01395 dnlen--;
01396 bn--;
01397 }
01398
01399
01400 for (i = 0; i < fi->fc; i++) {
01401 const char * dir;
01402
01403 if (XFA_SKIPPING(fi->actions[i]))
01404 continue;
01405 if (whatis(fi->fmodes[i]) != XDIR)
01406 continue;
01407 dir = fi->dnl[fi->dil[i]];
01408 if (strlen(dir) != dnlen)
01409 continue;
01410 if (strncmp(dir, dn, dnlen))
01411 continue;
01412 if (strlen(fi->bnl[i]) != bnlen)
01413 continue;
01414 if (strncmp(fi->bnl[i], bn, bnlen))
01415 continue;
01416 rpmMessage(RPMMESS_DEBUG, _("excluding directory %s\n"), dn);
01417 fi->actions[i] = FA_SKIPNSTATE;
01418 break;
01419 }
01420 }
01421
01422 if (netsharedPaths) freeSplitString(netsharedPaths);
01423 #ifdef DYING
01424 fi->flangs = _free(fi->flangs);
01425 #endif
01426 if (languages) freeSplitString((char **)languages);
01427 }
01428
01432 struct tsIterator_s {
01433 rpmTransactionSet ts;
01434 int reverse;
01435 int ocsave;
01436 int oc;
01437 };
01438
01444 static int tsGetOc(void * a)
01445
01446 {
01447 struct tsIterator_s * iter = a;
01448 int oc = iter->ocsave;
01449 return oc;
01450 }
01451
01457 static struct availablePackage * tsGetAlp(void * a)
01458
01459 {
01460 struct tsIterator_s * iter = a;
01461 struct availablePackage * alp = NULL;
01462 int oc = iter->ocsave;
01463
01464 if (oc != -1) {
01465 rpmTransactionSet ts = iter->ts;
01466 TFI_t fi = ts->flList + oc;
01467 if (ts->addedPackages.list && fi->type == TR_ADDED)
01468 alp = ts->addedPackages.list + ts->order[oc].u.addedIndex;
01469 }
01470 return alp;
01471 }
01472
01478 static void * tsFreeIterator( const void * a)
01479
01480 {
01481 return _free(a);
01482 }
01483
01489 static void * tsInitIterator( const void * a)
01490
01491 {
01492 rpmTransactionSet ts = (void *)a;
01493 struct tsIterator_s * iter = NULL;
01494
01495 iter = xcalloc(1, sizeof(*iter));
01496 iter->ts = ts;
01497 iter->reverse = ((ts->transFlags & RPMTRANS_FLAG_REVERSE) ? 1 : 0);
01498 iter->oc = (iter->reverse ? (ts->orderCount - 1) : 0);
01499 iter->ocsave = iter->oc;
01500 return iter;
01501 }
01502
01508 static TFI_t tsNextIterator(void * a)
01509
01510 {
01511 struct tsIterator_s * iter = a;
01512 rpmTransactionSet ts = iter->ts;
01513 TFI_t fi = NULL;
01514 int oc = -1;
01515
01516 if (iter->reverse) {
01517 if (iter->oc >= 0) oc = iter->oc--;
01518 } else {
01519 if (iter->oc < ts->orderCount) oc = iter->oc++;
01520 }
01521 iter->ocsave = oc;
01522 if (oc != -1)
01523 fi = ts->flList + oc;
01524 return fi;
01525 }
01526
01527 #define NOTIFY(_ts, _al) if ((_ts)->notify) (void) (_ts)->notify _al
01528
01529 int rpmRunTransactions( rpmTransactionSet ts,
01530 rpmCallbackFunction notify, rpmCallbackData notifyData,
01531 rpmProblemSet okProbs, rpmProblemSet * newProbs,
01532 rpmtransFlags transFlags, rpmprobFilterFlags ignoreSet)
01533 {
01534 int i, j;
01535 int ourrc = 0;
01536 struct availablePackage * alp;
01537 #ifdef DYING
01538 Header * hdrs;
01539 #endif
01540 int totalFileCount = 0;
01541 hashTable ht;
01542 TFI_t fi;
01543 struct diskspaceInfo * dip;
01544 struct sharedFileInfo * shared, * sharedList;
01545 int numShared;
01546 int nexti;
01547 int lastFailed;
01548 int oc;
01549 fingerPrintCache fpc;
01550 struct psm_s psmbuf;
01551 PSM_t psm = &psmbuf;
01552 void * tsi;
01553
01554
01555
01556 ts->transFlags = transFlags;
01557 if (ts->transFlags & RPMTRANS_FLAG_NOSCRIPTS)
01558 ts->transFlags |= (_noTransScripts | _noTransTriggers);
01559 if (ts->transFlags & RPMTRANS_FLAG_NOTRIGGERS)
01560 ts->transFlags |= _noTransTriggers;
01561
01562
01563 if (ts->transFlags & (RPMTRANS_FLAG_JUSTDB | RPMTRANS_FLAG_MULTILIB))
01564 ts->transFlags |= (_noTransScripts | _noTransTriggers);
01565
01566 ts->notify = notify;
01567 ts->notifyData = notifyData;
01568
01569 ts->probs = *newProbs = psCreate();
01570
01571 ts->ignoreSet = ignoreSet;
01572 ts->currDir = _free(ts->currDir);
01573 ts->currDir = currentDirectory();
01574 ts->chrootDone = 0;
01575 if (ts->rpmdb) ts->rpmdb->db_chrootDone = 0;
01576 ts->id = (int_32) time(NULL);
01577
01578 memset(psm, 0, sizeof(*psm));
01579
01580 psm->ts = ts;
01581
01582
01583
01584 if (!(ts->ignoreSet & RPMPROB_FILTER_DISKSPACE) &&
01585 !rpmGetFilesystemList(&ts->filesystems, &ts->filesystemCount)) {
01586 struct stat sb;
01587
01588 ts->di = _free(ts->di);
01589 dip = ts->di = xcalloc(sizeof(*ts->di), ts->filesystemCount + 1);
01590
01591 for (i = 0; (i < ts->filesystemCount) && dip; i++)
01592 if (strncmp(ts->filesystems[i], "/mnt/", 5)) {
01593 #if STATFS_IN_SYS_STATVFS
01594 struct statvfs sfb;
01595 memset(&sfb, 0, sizeof(sfb));
01596 if (statvfs(ts->filesystems[i], &sfb))
01597 #else
01598 struct statfs sfb;
01599 # if STAT_STATFS4
01600
01601
01602
01603
01604
01605 memset(&sfb, 0, sizeof(sfb));
01606 if (statfs(ts->filesystems[i], &sfb, sizeof(sfb), 0))
01607 # else
01608 memset(&sfb, 0, sizeof(sfb));
01609 if (statfs(ts->filesystems[i], &sfb))
01610 # endif
01611 #endif
01612 {
01613 dip = NULL;
01614 } else {
01615 ts->di[i].bsize = sfb.f_bsize;
01616 ts->di[i].bneeded = 0;
01617 ts->di[i].ineeded = 0;
01618 #ifdef STATFS_HAS_F_BAVAIL
01619 ts->di[i].bavail = sfb.f_bavail;
01620 #else
01621
01622
01623
01624
01625 ts->di[i].bavail = sfb.f_blocks - sfb.f_bfree;
01626 #endif
01627
01628 ts->di[i].iavail = !(sfb.f_ffree == 0 && sfb.f_files == 0)
01629 ? sfb.f_ffree : -1;
01630
01631 (void) stat(ts->filesystems[i], &sb);
01632 ts->di[i].dev = sb.st_dev;
01633 }
01634 }
01635
01636 if (dip) ts->di[i].bsize = 0;
01637 }
01638
01639 #ifdef DYING
01640 hdrs = alloca(sizeof(*hdrs) * ts->addedPackages.size);
01641 #endif
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652 if (ts->addedPackages.list != NULL)
01653 for (alp = ts->addedPackages.list;
01654 (alp - ts->addedPackages.list) < ts->addedPackages.size;
01655 alp++)
01656 {
01657 if (!archOkay(alp->h) && !(ts->ignoreSet & RPMPROB_FILTER_IGNOREARCH))
01658 psAppend(ts->probs, RPMPROB_BADARCH, alp, NULL, NULL, NULL, 0);
01659
01660 if (!osOkay(alp->h) && !(ts->ignoreSet & RPMPROB_FILTER_IGNOREOS))
01661 psAppend(ts->probs, RPMPROB_BADOS, alp, NULL, NULL, NULL, 0);
01662
01663 if (!(ts->ignoreSet & RPMPROB_FILTER_OLDPACKAGE)) {
01664 rpmdbMatchIterator mi;
01665 Header oldH;
01666 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, alp->name, 0);
01667 while ((oldH = rpmdbNextIterator(mi)) != NULL)
01668 (void) ensureOlder(alp, oldH, ts->probs);
01669 mi = rpmdbFreeIterator(mi);
01670 }
01671
01672
01673 if (!(ts->ignoreSet & RPMPROB_FILTER_REPLACEPKG) && !alp->multiLib) {
01674 rpmdbMatchIterator mi;
01675 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, alp->name, 0);
01676 (void) rpmdbSetIteratorRE(mi, RPMTAG_VERSION,
01677 RPMMIRE_DEFAULT, alp->version);
01678 (void) rpmdbSetIteratorRE(mi, RPMTAG_RELEASE,
01679 RPMMIRE_DEFAULT, alp->release);
01680
01681 while (rpmdbNextIterator(mi) != NULL) {
01682 psAppend(ts->probs, RPMPROB_PKG_INSTALLED, alp,
01683 NULL, NULL, NULL, 0);
01684 break;
01685 }
01686 mi = rpmdbFreeIterator(mi);
01687 }
01688
01689 totalFileCount += alp->filesCount;
01690
01691 }
01692
01693
01694
01695 if (ts->numRemovedPackages > 0) {
01696 rpmdbMatchIterator mi;
01697 Header h;
01698 int fileCount;
01699
01700 mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES, NULL, 0);
01701 (void) rpmdbAppendIterator(mi, ts->removedPackages, ts->numRemovedPackages);
01702 while ((h = rpmdbNextIterator(mi)) != NULL) {
01703 if (headerGetEntry(h, RPMTAG_BASENAMES, NULL, NULL, &fileCount))
01704 totalFileCount += fileCount;
01705 }
01706 mi = rpmdbFreeIterator(mi);
01707 }
01708
01709
01710
01711
01712 ts->flEntries = ts->addedPackages.size + ts->numRemovedPackages;
01713 ts->flList = xcalloc(ts->flEntries, sizeof(*ts->flList));
01714
01715
01716
01717
01718
01719
01720 tsi = tsInitIterator(ts);
01721 while ((fi = tsNextIterator(tsi)) != NULL) {
01722 oc = tsGetOc(tsi);
01723 fi->magic = TFIMAGIC;
01724
01725
01726 fi->type = ts->order[oc].type;
01727 switch (fi->type) {
01728 case TR_ADDED:
01729 i = ts->order[oc].u.addedIndex;
01730
01731 fi->ap = tsGetAlp(tsi);
01732 fi->record = 0;
01733 loadFi(fi->ap->h, fi);
01734 if (fi->fc == 0) {
01735 #ifdef DYING
01736 hdrs[i] = headerLink(fi->h);
01737 #endif
01738 continue;
01739 }
01740
01741 #ifdef DYING
01742
01743 fi->actions = xcalloc(fi->fc, sizeof(*fi->actions));
01744 hdrs[i] = relocateFileList(ts, fi, fi->ap, fi->h, fi->actions);
01745 #else
01746 { Header foo = relocateFileList(ts, fi, fi->ap, fi->h, fi->actions);
01747 foo = headerFree(foo);
01748 }
01749 #endif
01750
01751
01752 skipFiles(ts, fi);
01753 break;
01754 case TR_REMOVED:
01755 fi->ap = NULL;
01756 fi->record = ts->order[oc].u.removed.dboffset;
01757 { rpmdbMatchIterator mi;
01758
01759 mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES,
01760 &fi->record, sizeof(fi->record));
01761 if ((fi->h = rpmdbNextIterator(mi)) != NULL)
01762 fi->h = headerLink(fi->h);
01763 mi = rpmdbFreeIterator(mi);
01764 }
01765 if (fi->h == NULL) {
01766
01767 continue;
01768 }
01769
01770 loadFi(fi->h, fi);
01771 break;
01772 }
01773
01774 if (fi->fc)
01775 fi->fps = xmalloc(fi->fc * sizeof(*fi->fps));
01776 }
01777 tsi = tsFreeIterator(tsi);
01778
01779 #ifdef DYING
01780
01781 (void) rpmdbOpenAll(ts->rpmdb);
01782 #endif
01783
01784 if (!ts->chrootDone) {
01785 (void) chdir("/");
01786
01787 (void) chroot(ts->rootDir);
01788
01789 ts->chrootDone = 1;
01790 if (ts->rpmdb) ts->rpmdb->db_chrootDone = 1;
01791
01792 chroot_prefix = ts->rootDir;
01793
01794 }
01795
01796 ht = htCreate(totalFileCount * 2, 0, 0, fpHashFunction, fpEqual);
01797 fpc = fpCacheCreate(totalFileCount);
01798
01799
01800
01801
01802 tsi = tsInitIterator(ts);
01803 while ((fi = tsNextIterator(tsi)) != NULL) {
01804 fpLookupList(fpc, fi->dnl, fi->bnl, fi->dil, fi->fc, fi->fps);
01805 for (i = 0; i < fi->fc; i++) {
01806 if (XFA_SKIPPING(fi->actions[i]))
01807 continue;
01808
01809 htAddEntry(ht, fi->fps + i, fi);
01810
01811 }
01812 }
01813 tsi = tsFreeIterator(tsi);
01814
01815
01816 NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_START, 6, ts->flEntries,
01817 NULL, ts->notifyData));
01818
01819
01820
01821
01822
01823 tsi = tsInitIterator(ts);
01824 while ((fi = tsNextIterator(tsi)) != NULL) {
01825 dbiIndexSet * matches;
01826 int knownBad;
01827
01828
01829 NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_PROGRESS, (fi - ts->flList),
01830 ts->flEntries, NULL, ts->notifyData));
01831
01832
01833 if (fi->fc == 0) continue;
01834
01835
01836 matches = xcalloc(sizeof(*matches), fi->fc);
01837 if (rpmdbFindFpList(ts->rpmdb, fi->fps, matches, fi->fc))
01838 return 1;
01839
01840 numShared = 0;
01841 for (i = 0; i < fi->fc; i++)
01842 numShared += dbiIndexSetCount(matches[i]);
01843
01844
01845 shared = sharedList = xmalloc((numShared + 1) * sizeof(*sharedList));
01846 for (i = 0; i < fi->fc; i++) {
01847
01848
01849
01850
01851 for (j = 0; j < dbiIndexSetCount(matches[i]); j++) {
01852 int k, ro;
01853 ro = dbiIndexRecordOffset(matches[i], j);
01854 knownBad = 0;
01855 for (k = 0; ro != knownBad && k < ts->orderCount; k++) {
01856 switch (ts->order[k].type) {
01857 case TR_REMOVED:
01858 if (ts->order[k].u.removed.dboffset == ro)
01859 knownBad = ro;
01860 break;
01861 case TR_ADDED:
01862 break;
01863 }
01864 }
01865
01866 shared->pkgFileNum = i;
01867 shared->otherPkg = dbiIndexRecordOffset(matches[i], j);
01868 shared->otherFileNum = dbiIndexRecordFileNumber(matches[i], j);
01869 shared->isRemoved = (knownBad == ro);
01870 shared++;
01871 }
01872 matches[i] = dbiFreeIndexSet(matches[i]);
01873 }
01874 numShared = shared - sharedList;
01875 shared->otherPkg = -1;
01876 matches = _free(matches);
01877
01878
01879 qsort(sharedList, numShared, sizeof(*shared), sharedCmp);
01880
01881
01882 for (i = 0; i < numShared; i = nexti) {
01883 int beingRemoved;
01884
01885 shared = sharedList + i;
01886
01887
01888 for (nexti = i + 1; nexti < numShared; nexti++) {
01889 if (sharedList[nexti].otherPkg != shared->otherPkg)
01890 break;
01891 }
01892
01893
01894 beingRemoved = 0;
01895 for (j = 0; j < ts->numRemovedPackages; j++) {
01896 if (ts->removedPackages[j] != shared->otherPkg)
01897 continue;
01898 beingRemoved = 1;
01899 break;
01900 }
01901
01902
01903 switch (fi->type) {
01904 case TR_ADDED:
01905 (void) handleInstInstalledFiles(fi, ts->rpmdb, shared, nexti - i,
01906 !(beingRemoved || (ts->ignoreSet & RPMPROB_FILTER_REPLACEOLDFILES)),
01907 ts->probs, ts->transFlags);
01908 break;
01909 case TR_REMOVED:
01910 if (!beingRemoved)
01911 (void) handleRmvdInstalledFiles(fi, ts->rpmdb, shared, nexti - i);
01912 break;
01913 }
01914 }
01915
01916 free(sharedList);
01917
01918
01919 handleOverlappedFiles(fi, ht,
01920 ((ts->ignoreSet & RPMPROB_FILTER_REPLACENEWFILES)
01921 ? NULL : ts->probs), ts->di);
01922
01923
01924 switch (fi->type) {
01925 case TR_ADDED:
01926 if (!(ts->di && fi->fc))
01927 break;
01928 for (i = 0; i < ts->filesystemCount; i++) {
01929
01930 dip = ts->di + i;
01931
01932
01933 if (dip->iavail <= 0)
01934 continue;
01935
01936 if (adj_fs_blocks(dip->bneeded) > dip->bavail)
01937 psAppend(ts->probs, RPMPROB_DISKSPACE, fi->ap,
01938 ts->filesystems[i], NULL, NULL,
01939 (adj_fs_blocks(dip->bneeded) - dip->bavail) * dip->bsize);
01940
01941 if (adj_fs_blocks(dip->ineeded) > dip->iavail)
01942 psAppend(ts->probs, RPMPROB_DISKNODES, fi->ap,
01943 ts->filesystems[i], NULL, NULL,
01944 (adj_fs_blocks(dip->ineeded) - dip->iavail));
01945 }
01946 break;
01947 case TR_REMOVED:
01948 break;
01949 }
01950 }
01951 tsi = tsFreeIterator(tsi);
01952
01953 if (ts->chrootDone) {
01954
01955 (void) chroot(".");
01956
01957 ts->chrootDone = 0;
01958 if (ts->rpmdb) ts->rpmdb->db_chrootDone = 0;
01959 chroot_prefix = NULL;
01960 (void) chdir(ts->currDir);
01961 }
01962
01963
01964 NOTIFY(ts, (NULL, RPMCALLBACK_TRANS_STOP, 6, ts->flEntries,
01965 NULL, ts->notifyData));
01966
01967
01968
01969
01970
01971
01972 tsi = tsInitIterator(ts);
01973 while ((fi = tsNextIterator(tsi)) != NULL) {
01974 psm->fi = fi;
01975 if (fi->fc == 0)
01976 continue;
01977 fi->fps = _free(fi->fps);
01978 }
01979 tsi = tsFreeIterator(tsi);
01980
01981 fpCacheFree(fpc);
01982 htFree(ht);
01983
01984
01985
01986
01987 if ((ts->transFlags & RPMTRANS_FLAG_BUILD_PROBS) ||
01988 (ts->probs->numProblems && (!okProbs || psTrim(okProbs, ts->probs))))
01989 {
01990 *newProbs = ts->probs;
01991
01992 #ifdef DYING
01993 for (alp = ts->addedPackages.list, fi = ts->flList;
01994 (alp - ts->addedPackages.list) < ts->addedPackages.size;
01995 alp++, fi++)
01996 {
01997 hdrs[alp - ts->addedPackages.list] =
01998 headerFree(hdrs[alp - ts->addedPackages.list]);
01999 }
02000 #endif
02001
02002 ts->flList = freeFl(ts, ts->flList);
02003 ts->flEntries = 0;
02004
02005 return ts->orderCount;
02006
02007 }
02008
02009
02010
02011
02012 if (ts->transFlags & (RPMTRANS_FLAG_DIRSTASH | RPMTRANS_FLAG_REPACKAGE)) {
02013 tsi = tsInitIterator(ts);
02014 while ((fi = tsNextIterator(tsi)) != NULL) {
02015 psm->fi = fi;
02016 switch (fi->type) {
02017 case TR_ADDED:
02018 break;
02019 case TR_REMOVED:
02020 if (ts->transFlags & RPMTRANS_FLAG_REPACKAGE)
02021 (void) psmStage(psm, PSM_PKGSAVE);
02022 break;
02023 }
02024 }
02025 tsi = tsFreeIterator(tsi);
02026 }
02027
02028
02029
02030
02031
02032 lastFailed = -2;
02033 tsi = tsInitIterator(ts);
02034 while ((fi = tsNextIterator(tsi)) != NULL) {
02035 Header h;
02036 int gotfd;
02037
02038 gotfd = 0;
02039 psm->fi = fi;
02040 switch (fi->type)
02041 {
02042 case TR_ADDED:
02043 alp = tsGetAlp(tsi);
02044 assert(alp == fi->ap);
02045 i = alp - ts->addedPackages.list;
02046
02047 h = headerLink(fi->h);
02048 if (alp->fd == NULL) {
02049 alp->fd = ts->notify(fi->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
02050 alp->key, ts->notifyData);
02051 if (alp->fd) {
02052 rpmRC rpmrc;
02053
02054 #ifdef DYING
02055 hdrs[i] = headerFree(hdrs[i]);
02056 #else
02057 h = headerFree(h);
02058 #endif
02059
02060 rpmrc = rpmReadPackageHeader(alp->fd, &h, NULL, NULL, NULL);
02061
02062 if (!(rpmrc == RPMRC_OK || rpmrc == RPMRC_BADSIZE)) {
02063 (void)ts->notify(fi->h, RPMCALLBACK_INST_CLOSE_FILE,
02064 0, 0, alp->key, ts->notifyData);
02065 alp->fd = NULL;
02066 ourrc++;
02067 } else {
02068 #ifdef DYING
02069 hdrs[i] = relocateFileList(ts, fi, alp, h, NULL);
02070 h = headerFree(h);
02071 #else
02072 Header foo = relocateFileList(ts, fi, alp, h, NULL);
02073 h = headerFree(h);
02074 h = headerLink(foo);
02075 foo = headerFree(foo);
02076 #endif
02077 }
02078 if (alp->fd) gotfd = 1;
02079 }
02080 }
02081
02082 if (alp->fd) {
02083 Header hsave = NULL;
02084
02085 if (fi->h) {
02086 hsave = headerLink(fi->h);
02087 fi->h = headerFree(fi->h);
02088 }
02089 #ifdef DYING
02090 fi->h = headerLink(hdrs[i]);
02091 #else
02092 fi->h = headerLink(h);
02093 #endif
02094 if (alp->multiLib)
02095 ts->transFlags |= RPMTRANS_FLAG_MULTILIB;
02096
02097 assert(alp == fi->ap);
02098 if (psmStage(psm, PSM_PKGINSTALL)) {
02099 ourrc++;
02100 lastFailed = i;
02101 }
02102 fi->h = headerFree(fi->h);
02103 if (hsave) {
02104 fi->h = headerLink(hsave);
02105 hsave = headerFree(hsave);
02106 }
02107 } else {
02108 ourrc++;
02109 lastFailed = i;
02110 }
02111
02112 #ifdef DYING
02113 hdrs[i] = headerFree(hdrs[i]);
02114 #else
02115 h = headerFree(h);
02116 #endif
02117
02118 if (gotfd) {
02119 (void)ts->notify(fi->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
02120 alp->key, ts->notifyData);
02121 alp->fd = NULL;
02122 }
02123 break;
02124 case TR_REMOVED:
02125 oc = tsGetOc(tsi);
02126
02127 if (ts->order[oc].u.removed.dependsOnIndex == lastFailed)
02128 break;
02129
02130 if (psmStage(psm, PSM_PKGERASE))
02131 ourrc++;
02132
02133 break;
02134 }
02135 (void) rpmdbSync(ts->rpmdb);
02136 }
02137 tsi = tsFreeIterator(tsi);
02138
02139 ts->flList = freeFl(ts, ts->flList);
02140 ts->flEntries = 0;
02141
02142
02143 if (ourrc)
02144 return -1;
02145 else
02146 return 0;
02147
02148 }