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