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