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