00001
00006 #include "system.h"
00007
00008 #include <rpmlib.h>
00009 #include <rpmmacro.h>
00010 #include <rpmurl.h>
00011
00012 #include "psm.h"
00013 #include "rpmlead.h"
00014 #include "signature.h"
00015 #include "misc.h"
00016 #include "rpmdb.h"
00017 #include "debug.h"
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 extern int _fsm_debug;
00030
00031
00032
00033 extern const char * chroot_prefix;
00034
00035
00036 int rpmVersionCompare(Header first, Header second)
00037 {
00038 const char * one, * two;
00039 int_32 * epochOne, * epochTwo;
00040 int rc;
00041
00042 if (!headerGetEntry(first, RPMTAG_EPOCH, NULL, (void **) &epochOne, NULL))
00043 epochOne = NULL;
00044 if (!headerGetEntry(second, RPMTAG_EPOCH, NULL, (void **) &epochTwo,
00045 NULL))
00046 epochTwo = NULL;
00047
00048 if (epochOne && !epochTwo)
00049 return 1;
00050 else if (!epochOne && epochTwo)
00051 return -1;
00052 else if (epochOne && epochTwo) {
00053 if (*epochOne < *epochTwo)
00054 return -1;
00055 else if (*epochOne > *epochTwo)
00056 return 1;
00057 }
00058
00059 (void) headerGetEntry(first, RPMTAG_VERSION, NULL, (void **) &one, NULL);
00060 (void) headerGetEntry(second, RPMTAG_VERSION, NULL, (void **) &two, NULL);
00061
00062 rc = rpmvercmp(one, two);
00063 if (rc)
00064 return rc;
00065
00066 (void) headerGetEntry(first, RPMTAG_RELEASE, NULL, (void **) &one, NULL);
00067 (void) headerGetEntry(second, RPMTAG_RELEASE, NULL, (void **) &two, NULL);
00068
00069 return rpmvercmp(one, two);
00070 }
00071
00072 void loadFi(Header h, TFI_t fi)
00073 {
00074 HGE_t hge;
00075 HFD_t hfd;
00076 uint_32 * uip;
00077 int len;
00078 int rc;
00079 int i;
00080
00081 if (fi->fsm == NULL)
00082 fi->fsm = newFSM();
00083
00084
00085 hge = (fi->type == TR_ADDED)
00086 ? (HGE_t) headerGetEntryMinMemory : (HGE_t) headerGetEntry;
00087 fi->hge = hge;
00088 fi->hae = (HAE_t) headerAddEntry;
00089 fi->hme = (HME_t) headerModifyEntry;
00090 fi->hre = (HRE_t) headerRemoveEntry;
00091 fi->hfd = hfd = headerFreeData;
00092
00093 if (h && fi->h == NULL) fi->h = headerLink(h);
00094
00095
00096 rc = hge(fi->h, RPMTAG_NAME, NULL, (void **) &fi->name, NULL);
00097 fi->name = xstrdup(fi->name);
00098 rc = hge(fi->h, RPMTAG_VERSION, NULL, (void **) &fi->version, NULL);
00099 fi->version = xstrdup(fi->version);
00100 rc = hge(fi->h, RPMTAG_RELEASE, NULL, (void **) &fi->release, NULL);
00101 fi->release = xstrdup(fi->release);
00102
00103
00104 rc = hge(fi->h, RPMTAG_EPOCH, NULL, (void **) &uip, NULL);
00105 fi->epoch = (rc ? *uip : -1);
00106
00107 rc = hge(fi->h, RPMTAG_ARCHIVESIZE, NULL, (void **) &uip, NULL);
00108 fi->archiveSize = (rc ? *uip : 0);
00109
00110 if (!hge(fi->h, RPMTAG_BASENAMES, NULL, (void **) &fi->bnl, &fi->fc)) {
00111 fi->dc = 0;
00112 fi->fc = 0;
00113 return;
00114 }
00115
00116 rc = hge(fi->h, RPMTAG_DIRINDEXES, NULL, (void **) &fi->dil, NULL);
00117 rc = hge(fi->h, RPMTAG_DIRNAMES, NULL, (void **) &fi->dnl, &fi->dc);
00118 rc = hge(fi->h, RPMTAG_FILEMODES, NULL, (void **) &fi->fmodes, NULL);
00119 rc = hge(fi->h, RPMTAG_FILEFLAGS, NULL, (void **) &fi->fflags, NULL);
00120 rc = hge(fi->h, RPMTAG_FILESIZES, NULL, (void **) &fi->fsizes, NULL);
00121 rc = hge(fi->h, RPMTAG_FILESTATES, NULL, (void **) &fi->fstates, NULL);
00122
00123 fi->action = FA_UNKNOWN;
00124 fi->flags = 0;
00125
00126
00127 if (fi->actions == NULL)
00128 fi->actions = xcalloc(fi->fc, sizeof(*fi->actions));
00129
00130 switch (fi->type) {
00131 case TR_ADDED:
00132 fi->mapflags =
00133 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
00134 rc = hge(fi->h, RPMTAG_FILEMD5S, NULL, (void **) &fi->fmd5s, NULL);
00135 rc = hge(fi->h, RPMTAG_FILELINKTOS, NULL, (void **) &fi->flinks, NULL);
00136 rc = hge(fi->h, RPMTAG_FILELANGS, NULL, (void **) &fi->flangs, NULL);
00137 rc = hge(fi->h, RPMTAG_FILEMTIMES, NULL, (void **) &fi->fmtimes, NULL);
00138 rc = hge(fi->h, RPMTAG_FILERDEVS, NULL, (void **) &fi->frdevs, NULL);
00139
00140
00141 fi->replacedSizes = xcalloc(fi->fc, sizeof(*fi->replacedSizes));
00142
00143 break;
00144 case TR_REMOVED:
00145 fi->mapflags =
00146 CPIO_MAP_ABSOLUTE | CPIO_MAP_ADDDOT | CPIO_ALL_HARDLINKS |
00147 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
00148 rc = hge(fi->h, RPMTAG_FILEMD5S, NULL, (void **) &fi->fmd5s, NULL);
00149 rc = hge(fi->h, RPMTAG_FILELINKTOS, NULL, (void **) &fi->flinks, NULL);
00150 fi->fsizes = memcpy(xmalloc(fi->fc * sizeof(*fi->fsizes)),
00151 fi->fsizes, fi->fc * sizeof(*fi->fsizes));
00152 fi->fflags = memcpy(xmalloc(fi->fc * sizeof(*fi->fflags)),
00153 fi->fflags, fi->fc * sizeof(*fi->fflags));
00154 fi->fmodes = memcpy(xmalloc(fi->fc * sizeof(*fi->fmodes)),
00155 fi->fmodes, fi->fc * sizeof(*fi->fmodes));
00156
00157 if (fi->fstates)
00158 fi->fstates = memcpy(xmalloc(fi->fc * sizeof(*fi->fstates)),
00159 fi->fstates, fi->fc * sizeof(*fi->fstates));
00160 else
00161 fi->fstates = xcalloc(1, fi->fc * sizeof(*fi->fstates));
00162 fi->dil = memcpy(xmalloc(fi->fc * sizeof(*fi->dil)),
00163 fi->dil, fi->fc * sizeof(*fi->dil));
00164 fi->h = headerFree(fi->h);
00165 break;
00166 }
00167
00168 fi->dnlmax = -1;
00169 for (i = 0; i < fi->dc; i++) {
00170 if ((len = strlen(fi->dnl[i])) > fi->dnlmax)
00171 fi->dnlmax = len;
00172 }
00173
00174 fi->bnlmax = -1;
00175 for (i = 0; i < fi->fc; i++) {
00176 if ((len = strlen(fi->bnl[i])) > fi->bnlmax)
00177 fi->bnlmax = len;
00178 }
00179
00180 fi->dperms = 0755;
00181 fi->fperms = 0644;
00182
00183
00184 return;
00185
00186 }
00187
00188 void freeFi(TFI_t fi)
00189 {
00190 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
00191
00192 fi->name = _free(fi->name);
00193 fi->version = _free(fi->version);
00194 fi->release = _free(fi->release);
00195 fi->actions = _free(fi->actions);
00196 fi->replacedSizes = _free(fi->replacedSizes);
00197 fi->replaced = _free(fi->replaced);
00198
00199 fi->bnl = hfd(fi->bnl, -1);
00200 fi->dnl = hfd(fi->dnl, -1);
00201 fi->obnl = hfd(fi->obnl, -1);
00202 fi->odnl = hfd(fi->odnl, -1);
00203 fi->flinks = hfd(fi->flinks, -1);
00204 fi->fmd5s = hfd(fi->fmd5s, -1);
00205 fi->fuser = hfd(fi->fuser, -1);
00206 fi->fgroup = hfd(fi->fgroup, -1);
00207 fi->flangs = hfd(fi->flangs, -1);
00208
00209 fi->apath = _free(fi->apath);
00210 fi->fuids = _free(fi->fuids);
00211 fi->fgids = _free(fi->fgids);
00212 fi->fmapflags = _free(fi->fmapflags);
00213
00214 fi->fsm = freeFSM(fi->fsm);
00215
00216 switch (fi->type) {
00217 case TR_ADDED:
00218 break;
00219 case TR_REMOVED:
00220 fi->fsizes = hfd(fi->fsizes, -1);
00221 fi->fflags = hfd(fi->fflags, -1);
00222 fi->fmodes = hfd(fi->fmodes, -1);
00223 fi->fstates = hfd(fi->fstates, -1);
00224 fi->dil = hfd(fi->dil, -1);
00225 break;
00226 }
00227
00228 fi->h = headerFree(fi->h);
00229
00230
00231 return;
00232
00233 }
00234
00235 const char *const fiTypeString(TFI_t fi)
00236 {
00237 switch(fi->type) {
00238 case TR_ADDED: return " install";
00239 case TR_REMOVED: return " erase";
00240 default: return "???";
00241 }
00242
00243 }
00244
00249 static struct tagMacro {
00250 const char * macroname;
00251 rpmTag tag;
00252 } tagMacros[] = {
00253 { "name", RPMTAG_NAME },
00254 { "version", RPMTAG_VERSION },
00255 { "release", RPMTAG_RELEASE },
00256 { "epoch", RPMTAG_EPOCH },
00257 { NULL, 0 }
00258 };
00259
00266 static int rpmInstallLoadMacros(TFI_t fi, Header h)
00267
00268 {
00269 HGE_t hge = (HGE_t) fi->hge;
00270 struct tagMacro * tagm;
00271 union {
00272 void * ptr;
00273 const char ** argv;
00274 const char * str;
00275 int_32 * i32p;
00276 } body;
00277 char numbuf[32];
00278 rpmTagType type;
00279
00280 for (tagm = tagMacros; tagm->macroname != NULL; tagm++) {
00281 if (!hge(h, tagm->tag, &type, (void **) &body, NULL))
00282 continue;
00283 switch (type) {
00284 case RPM_INT32_TYPE:
00285 sprintf(numbuf, "%d", *body.i32p);
00286 addMacro(NULL, tagm->macroname, NULL, numbuf, -1);
00287 break;
00288 case RPM_STRING_TYPE:
00289 addMacro(NULL, tagm->macroname, NULL, body.str, -1);
00290 break;
00291 case RPM_NULL_TYPE:
00292 case RPM_CHAR_TYPE:
00293 case RPM_INT8_TYPE:
00294 case RPM_INT16_TYPE:
00295 case RPM_BIN_TYPE:
00296 case RPM_STRING_ARRAY_TYPE:
00297 case RPM_I18NSTRING_TYPE:
00298 default:
00299 break;
00300 }
00301 }
00302 return 0;
00303 }
00304
00312 static int mergeFiles(TFI_t fi, Header h, Header newH)
00313
00314 {
00315 HGE_t hge = (HGE_t)fi->hge;
00316 HME_t hme = (HME_t)fi->hme;
00317 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
00318 fileAction * actions = fi->actions;
00319 int i, j, k, fc;
00320 rpmTagType type = 0;
00321 int_32 count = 0;
00322 int_32 dirNamesCount, dirCount;
00323 void * data, * newdata;
00324 int_32 * dirIndexes, * newDirIndexes;
00325 uint_32 * fileSizes, fileSize;
00326 const char ** dirNames;
00327 const char ** newDirNames;
00328 static rpmTag mergeTags[] = {
00329 RPMTAG_FILESIZES,
00330 RPMTAG_FILESTATES,
00331 RPMTAG_FILEMODES,
00332 RPMTAG_FILERDEVS,
00333 RPMTAG_FILEMTIMES,
00334 RPMTAG_FILEMD5S,
00335 RPMTAG_FILELINKTOS,
00336 RPMTAG_FILEFLAGS,
00337 RPMTAG_FILEUSERNAME,
00338 RPMTAG_FILEGROUPNAME,
00339 RPMTAG_FILEVERIFYFLAGS,
00340 RPMTAG_FILEDEVICES,
00341 RPMTAG_FILEINODES,
00342 RPMTAG_FILELANGS,
00343 RPMTAG_BASENAMES,
00344 0,
00345 };
00346 static rpmTag requireTags[] = {
00347 RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS,
00348 RPMTAG_PROVIDENAME, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS,
00349 RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS
00350 };
00351
00352 (void) hge(h, RPMTAG_SIZE, NULL, (void **) &fileSizes, NULL);
00353 fileSize = *fileSizes;
00354 (void) hge(newH, RPMTAG_FILESIZES, NULL, (void **) &fileSizes, &count);
00355 for (i = 0, fc = 0; i < count; i++)
00356 if (actions[i] != FA_SKIPMULTILIB) {
00357 fc++;
00358 fileSize += fileSizes[i];
00359 }
00360 (void) hme(h, RPMTAG_SIZE, RPM_INT32_TYPE, &fileSize, 1);
00361
00362 for (i = 0; mergeTags[i]; i++) {
00363 if (!hge(newH, mergeTags[i], &type, (void **) &data, &count))
00364 continue;
00365 switch (type) {
00366 case RPM_CHAR_TYPE:
00367 case RPM_INT8_TYPE:
00368 newdata = xmalloc(fc * sizeof(int_8));
00369 for (j = 0, k = 0; j < count; j++)
00370 if (actions[j] != FA_SKIPMULTILIB)
00371 ((int_8 *) newdata)[k++] = ((int_8 *) data)[j];
00372 (void) headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
00373 free (newdata);
00374 break;
00375 case RPM_INT16_TYPE:
00376 newdata = xmalloc(fc * sizeof(int_16));
00377 for (j = 0, k = 0; j < count; j++)
00378 if (actions[j] != FA_SKIPMULTILIB)
00379 ((int_16 *) newdata)[k++] = ((int_16 *) data)[j];
00380 (void) headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
00381 free (newdata);
00382 break;
00383 case RPM_INT32_TYPE:
00384 newdata = xmalloc(fc * sizeof(int_32));
00385 for (j = 0, k = 0; j < count; j++)
00386 if (actions[j] != FA_SKIPMULTILIB)
00387 ((int_32 *) newdata)[k++] = ((int_32 *) data)[j];
00388 (void) headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
00389 free (newdata);
00390 break;
00391 case RPM_STRING_ARRAY_TYPE:
00392 newdata = xmalloc(fc * sizeof(char *));
00393 for (j = 0, k = 0; j < count; j++)
00394 if (actions[j] != FA_SKIPMULTILIB)
00395 ((char **) newdata)[k++] = ((char **) data)[j];
00396 (void) headerAddOrAppendEntry(h, mergeTags[i], type, newdata, fc);
00397 free (newdata);
00398 break;
00399 default:
00400 rpmError(RPMERR_DATATYPE, _("Data type %d not supported\n"),
00401 (int) type);
00402 return 1;
00403 break;
00404 }
00405 data = hfd(data, type);
00406 }
00407 (void) hge(newH, RPMTAG_DIRINDEXES, NULL, (void **) &newDirIndexes, &count);
00408 (void) hge(newH, RPMTAG_DIRNAMES, NULL, (void **) &newDirNames, NULL);
00409 (void) hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL);
00410 (void) hge(h, RPMTAG_DIRNAMES, NULL, (void **) &data, &dirNamesCount);
00411
00412 dirNames = xcalloc(dirNamesCount + fc, sizeof(char *));
00413 for (i = 0; i < dirNamesCount; i++)
00414 dirNames[i] = ((char **) data)[i];
00415 dirCount = dirNamesCount;
00416 newdata = xmalloc(fc * sizeof(int_32));
00417 for (i = 0, k = 0; i < count; i++) {
00418 if (actions[i] == FA_SKIPMULTILIB)
00419 continue;
00420 for (j = 0; j < dirCount; j++)
00421 if (!strcmp(dirNames[j], newDirNames[newDirIndexes[i]]))
00422 break;
00423 if (j == dirCount)
00424 dirNames[dirCount++] = newDirNames[newDirIndexes[i]];
00425 ((int_32 *) newdata)[k++] = j;
00426 }
00427 (void) headerAddOrAppendEntry(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, newdata, fc);
00428 if (dirCount > dirNamesCount)
00429 (void) headerAddOrAppendEntry(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
00430 dirNames + dirNamesCount,
00431 dirCount - dirNamesCount);
00432 data = hfd(data, -1);
00433 newDirNames = hfd(newDirNames, -1);
00434 free (newdata);
00435 free (dirNames);
00436
00437 for (i = 0; i < 9; i += 3) {
00438 const char **Names, **EVR, **newNames, **newEVR;
00439 rpmTagType nnt, nvt, rnt;
00440 uint_32 *Flags, *newFlags;
00441 int Count = 0, newCount = 0;
00442
00443 if (!hge(newH, requireTags[i], &nnt, (void **) &newNames, &newCount))
00444 continue;
00445
00446 (void) hge(newH, requireTags[i+1], &nvt, (void **) &newEVR, NULL);
00447 (void) hge(newH, requireTags[i+2], NULL, (void **) &newFlags, NULL);
00448 if (hge(h, requireTags[i], &rnt, (void **) &Names, &Count))
00449 {
00450 (void) hge(h, requireTags[i+1], NULL, (void **) &EVR, NULL);
00451 (void) hge(h, requireTags[i+2], NULL, (void **) &Flags, NULL);
00452 for (j = 0; j < newCount; j++)
00453 for (k = 0; k < Count; k++)
00454 if (!strcmp (newNames[j], Names[k])
00455 && !strcmp (newEVR[j], EVR[k])
00456 && (newFlags[j] & RPMSENSE_SENSEMASK) ==
00457 (Flags[k] & RPMSENSE_SENSEMASK))
00458 {
00459 newNames[j] = NULL;
00460 break;
00461 }
00462 }
00463 for (j = 0, k = 0; j < newCount; j++) {
00464 if (!newNames[j] || !isDependsMULTILIB(newFlags[j]))
00465 continue;
00466 if (j != k) {
00467 newNames[k] = newNames[j];
00468 newEVR[k] = newEVR[j];
00469 newFlags[k] = newFlags[j];
00470 }
00471 k++;
00472 }
00473 if (k) {
00474 (void) headerAddOrAppendEntry(h, requireTags[i],
00475 RPM_STRING_ARRAY_TYPE, newNames, k);
00476 (void) headerAddOrAppendEntry(h, requireTags[i+1],
00477 RPM_STRING_ARRAY_TYPE, newEVR, k);
00478 (void) headerAddOrAppendEntry(h, requireTags[i+2], RPM_INT32_TYPE,
00479 newFlags, k);
00480 }
00481 newNames = hfd(newNames, nnt);
00482 newEVR = hfd(newEVR, nvt);
00483 Names = hfd(Names, rnt);
00484 }
00485 return 0;
00486 }
00487
00493 static int markReplacedFiles(PSM_t psm)
00494
00495 {
00496 const rpmTransactionSet ts = psm->ts;
00497 TFI_t fi = psm->fi;
00498 HGE_t hge = (HGE_t)fi->hge;
00499 const struct sharedFileInfo * replaced = fi->replaced;
00500 const struct sharedFileInfo * sfi;
00501 rpmdbMatchIterator mi;
00502 Header h;
00503 unsigned int * offsets;
00504 unsigned int prev;
00505 int num;
00506
00507 if (!(fi->fc > 0 && fi->replaced))
00508 return 0;
00509
00510 num = prev = 0;
00511 for (sfi = replaced; sfi->otherPkg; sfi++) {
00512 if (prev && prev == sfi->otherPkg)
00513 continue;
00514 prev = sfi->otherPkg;
00515 num++;
00516 }
00517 if (num == 0)
00518 return 0;
00519
00520 offsets = alloca(num * sizeof(*offsets));
00521 num = prev = 0;
00522 for (sfi = replaced; sfi->otherPkg; sfi++) {
00523 if (prev && prev == sfi->otherPkg)
00524 continue;
00525 prev = sfi->otherPkg;
00526 offsets[num++] = sfi->otherPkg;
00527 }
00528
00529 mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES, NULL, 0);
00530 (void) rpmdbAppendIterator(mi, offsets, num);
00531 (void) rpmdbSetIteratorRewrite(mi, 1);
00532
00533 sfi = replaced;
00534 while ((h = rpmdbNextIterator(mi)) != NULL) {
00535 char * secStates;
00536 int modified;
00537 int count;
00538
00539 modified = 0;
00540
00541 if (!hge(h, RPMTAG_FILESTATES, NULL, (void **)&secStates, &count))
00542 continue;
00543
00544 prev = rpmdbGetIteratorOffset(mi);
00545 num = 0;
00546 while (sfi->otherPkg && sfi->otherPkg == prev) {
00547 assert(sfi->otherFileNum < count);
00548 if (secStates[sfi->otherFileNum] != RPMFILE_STATE_REPLACED) {
00549 secStates[sfi->otherFileNum] = RPMFILE_STATE_REPLACED;
00550 if (modified == 0) {
00551
00552 modified = 1;
00553 (void) rpmdbSetIteratorModified(mi, modified);
00554 }
00555 num++;
00556 }
00557 sfi++;
00558 }
00559 }
00560 mi = rpmdbFreeIterator(mi);
00561
00562 return 0;
00563 }
00564
00572 static rpmRC chkdir (const char * dpath, const char * dname)
00573
00574 {
00575 struct stat st;
00576 int rc;
00577
00578 if ((rc = Stat(dpath, &st)) < 0) {
00579 int ut = urlPath(dpath, NULL);
00580 switch (ut) {
00581 case URL_IS_PATH:
00582 case URL_IS_UNKNOWN:
00583 if (errno != ENOENT)
00584 break;
00585
00586 case URL_IS_FTP:
00587 case URL_IS_HTTP:
00588 rc = Mkdir(dpath, 0755);
00589 break;
00590 case URL_IS_DASH:
00591 break;
00592 }
00593 if (rc < 0) {
00594 rpmError(RPMERR_CREATE, _("cannot create %%%s %s\n"),
00595 dname, dpath);
00596 return RPMRC_FAIL;
00597 }
00598 }
00599 if ((rc = Access(dpath, W_OK))) {
00600 rpmError(RPMERR_CREATE, _("cannot write to %%%s %s\n"), dname, dpath);
00601 return RPMRC_FAIL;
00602 }
00603 return RPMRC_OK;
00604 }
00605
00606 rpmRC rpmInstallSourcePackage(const char * rootDir, FD_t fd,
00607 const char ** specFilePtr,
00608 rpmCallbackFunction notify, rpmCallbackData notifyData,
00609 char ** cookie)
00610 {
00611 rpmdb rpmdb = NULL;
00612 rpmTransactionSet ts = rpmtransCreateSet(rpmdb, rootDir);
00613 TFI_t fi = xcalloc(sizeof(*fi), 1);
00614 const char * _sourcedir = NULL;
00615 const char * _specdir = NULL;
00616 const char * specFile = NULL;
00617 HGE_t hge;
00618 HFD_t hfd;
00619 Header h = NULL;
00620 struct psm_s psmbuf;
00621 PSM_t psm = &psmbuf;
00622 int isSource;
00623 rpmRC rc;
00624 int i;
00625
00626 ts->notify = notify;
00627
00628 ts->notifyData = notifyData;
00629
00630
00631
00632 rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
00633
00634 if (rc)
00635 goto exit;
00636
00637 if (!isSource) {
00638 rpmError(RPMERR_NOTSRPM, _("source package expected, binary found\n"));
00639 rc = RPMRC_FAIL;
00640 goto exit;
00641 }
00642
00643 (void) rpmtransAddPackage(ts, h, fd, NULL, 0, NULL);
00644 if (ts->addedPackages.list == NULL) {
00645 rc = RPMRC_FAIL;
00646 goto exit;
00647 }
00648
00649 fi->type = TR_ADDED;
00650 fi->ap = ts->addedPackages.list;
00651 loadFi(h, fi);
00652 hge = fi->hge;
00653 hfd = (fi->hfd ? fi->hfd : headerFreeData);
00654 h = headerFree(h);
00655
00656 (void) rpmInstallLoadMacros(fi, fi->h);
00657
00658 memset(psm, 0, sizeof(*psm));
00659 psm->ts = ts;
00660 psm->fi = fi;
00661
00662 if (cookie) {
00663 *cookie = NULL;
00664 if (hge(fi->h, RPMTAG_COOKIE, NULL, (void **) cookie, NULL))
00665 *cookie = xstrdup(*cookie);
00666 }
00667
00668
00669 fi->fmd5s = hfd(fi->fmd5s, -1);
00670
00671
00672 fi->fmapflags = _free(fi->fmapflags);
00673 fi->mapflags = CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
00674
00675 fi->uid = getuid();
00676 fi->gid = getgid();
00677 fi->astriplen = 0;
00678 fi->striplen = 0;
00679
00680 fi->fuids = xcalloc(sizeof(*fi->fuids), fi->fc);
00681 fi->fgids = xcalloc(sizeof(*fi->fgids), fi->fc);
00682 for (i = 0; i < fi->fc; i++) {
00683 fi->fuids[i] = fi->uid;
00684 fi->fgids[i] = fi->gid;
00685 }
00686
00687 for (i = 0; i < fi->fc; i++) {
00688 fi->actions[i] = FA_CREATE;
00689 }
00690
00691 rpmBuildFileList(fi->h, &fi->apath, NULL);
00692
00693 i = fi->fc;
00694 if (headerIsEntry(fi->h, RPMTAG_COOKIE))
00695 for (i = 0; i < fi->fc; i++)
00696 if (fi->fflags[i] & RPMFILE_SPECFILE) break;
00697
00698 if (i == fi->fc) {
00699
00700 for (i = 0; i < fi->fc; i++) {
00701 const char * t = fi->apath[i];
00702 t += strlen(fi->apath[i]) - 5;
00703 if (!strcmp(t, ".spec")) break;
00704 }
00705 }
00706
00707 _sourcedir = rpmGenPath(ts->rootDir, "%{_sourcedir}", "");
00708 rc = chkdir(_sourcedir, "sourcedir");
00709 if (rc) {
00710 rc = RPMRC_FAIL;
00711 goto exit;
00712 }
00713
00714 _specdir = rpmGenPath(ts->rootDir, "%{_specdir}", "");
00715 rc = chkdir(_specdir, "specdir");
00716 if (rc) {
00717 rc = RPMRC_FAIL;
00718 goto exit;
00719 }
00720
00721
00722 if (i < fi->fc) {
00723 int speclen = strlen(_specdir) + 2;
00724 int sourcelen = strlen(_sourcedir) + 2;
00725 char * t;
00726
00727 fi->dnl = hfd(fi->dnl, -1);
00728
00729 fi->dc = 2;
00730 fi->dnl = xmalloc(fi->dc * sizeof(*fi->dnl) + fi->fc * sizeof(*fi->dil) +
00731 speclen + sourcelen);
00732 fi->dil = (int *)(fi->dnl + fi->dc);
00733 memset(fi->dil, 0, fi->fc * sizeof(*fi->dil));
00734 fi->dil[i] = 1;
00735
00736 fi->dnl[0] = t = (char *)(fi->dil + fi->fc);
00737 fi->dnl[1] = t = stpcpy( stpcpy(t, _sourcedir), "/") + 1;
00738
00739 (void) stpcpy( stpcpy(t, _specdir), "/");
00740
00741 t = xmalloc(speclen + strlen(fi->bnl[i]) + 1);
00742 (void) stpcpy( stpcpy( stpcpy(t, _specdir), "/"), fi->bnl[i]);
00743 specFile = t;
00744 } else {
00745 rpmError(RPMERR_NOSPEC, _("source package contains no .spec file\n"));
00746 rc = RPMRC_FAIL;
00747 goto exit;
00748 }
00749
00750 psm->goal = PSM_PKGINSTALL;
00751
00752
00753 rc = psmStage(psm, PSM_PROCESS);
00754
00755 (void) psmStage(psm, PSM_FINI);
00756
00757
00758 if (rc) rc = RPMRC_FAIL;
00759
00760 exit:
00761 if (specFilePtr && specFile && rc == RPMRC_OK)
00762 *specFilePtr = specFile;
00763 else
00764 specFile = _free(specFile);
00765
00766 _specdir = _free(_specdir);
00767 _sourcedir = _free(_sourcedir);
00768
00769 if (h) h = headerFree(h);
00770
00771 if (fi) {
00772 freeFi(fi);
00773 fi = _free(fi);
00774 }
00775 ts = rpmtransFree(ts);
00776
00777 return rc;
00778 }
00779
00780 static char * SCRIPT_PATH =
00781 "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin";
00782
00788 static const char * const tag2sln(int tag)
00789
00790 {
00791 switch (tag) {
00792 case RPMTAG_PREIN: return "%pre";
00793 case RPMTAG_POSTIN: return "%post";
00794 case RPMTAG_PREUN: return "%preun";
00795 case RPMTAG_POSTUN: return "%postun";
00796 case RPMTAG_VERIFYSCRIPT: return "%verify";
00797 }
00798 return "%unknownscript";
00799 }
00800
00819 static int runScript(PSM_t psm, Header h,
00820 const char * sln,
00821 int progArgc, const char ** progArgv,
00822 const char * script, int arg1, int arg2)
00823
00824 {
00825 const rpmTransactionSet ts = psm->ts;
00826 TFI_t fi = psm->fi;
00827 HGE_t hge = fi->hge;
00828 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
00829 const char ** argv = NULL;
00830 int argc = 0;
00831 const char ** prefixes = NULL;
00832 int numPrefixes;
00833 rpmTagType ipt;
00834 const char * oldPrefix;
00835 int maxPrefixLength;
00836 int len;
00837 char * prefixBuf = NULL;
00838 pid_t child;
00839 int status = 0;
00840 const char * fn = NULL;
00841 int i;
00842 int freePrefixes = 0;
00843 FD_t out;
00844 rpmRC rc = RPMRC_OK;
00845 const char *n, *v, *r;
00846
00847 if (!progArgv && !script)
00848 return 0;
00849
00850 if (!progArgv) {
00851 argv = alloca(5 * sizeof(char *));
00852 argv[0] = "/bin/sh";
00853 argc = 1;
00854 } else {
00855 argv = alloca((progArgc + 4) * sizeof(char *));
00856 memcpy(argv, progArgv, progArgc * sizeof(char *));
00857 argc = progArgc;
00858 }
00859
00860 (void) headerNVR(h, &n, &v, &r);
00861 if (hge(h, RPMTAG_INSTPREFIXES, &ipt, (void **) &prefixes, &numPrefixes)) {
00862 freePrefixes = 1;
00863 } else if (hge(h, RPMTAG_INSTALLPREFIX, NULL, (void **) &oldPrefix, NULL)) {
00864 prefixes = &oldPrefix;
00865 numPrefixes = 1;
00866 } else {
00867 numPrefixes = 0;
00868 }
00869
00870 maxPrefixLength = 0;
00871 for (i = 0; i < numPrefixes; i++) {
00872 len = strlen(prefixes[i]);
00873 if (len > maxPrefixLength) maxPrefixLength = len;
00874 }
00875 prefixBuf = alloca(maxPrefixLength + 50);
00876
00877 if (script) {
00878 FD_t fd;
00879 if (makeTempFile((!ts->chrootDone ? ts->rootDir : "/"), &fn, &fd)) {
00880 if (freePrefixes) free(prefixes);
00881 return 1;
00882 }
00883
00884 if (rpmIsDebug() &&
00885 (!strcmp(argv[0], "/bin/sh") || !strcmp(argv[0], "/bin/bash")))
00886 (void) Fwrite("set -x\n", sizeof(char), 7, fd);
00887
00888 (void) Fwrite(script, sizeof(script[0]), strlen(script), fd);
00889 (void) Fclose(fd);
00890
00891 { const char * sn = fn;
00892 if (!ts->chrootDone &&
00893 !(ts->rootDir[0] == '/' && ts->rootDir[1] == '\0'))
00894 {
00895 sn += strlen(ts->rootDir)-1;
00896 }
00897 argv[argc++] = sn;
00898 }
00899
00900 if (arg1 >= 0) {
00901 char *av = alloca(20);
00902 sprintf(av, "%d", arg1);
00903 argv[argc++] = av;
00904 }
00905 if (arg2 >= 0) {
00906 char *av = alloca(20);
00907 sprintf(av, "%d", arg2);
00908 argv[argc++] = av;
00909 }
00910 }
00911
00912 argv[argc] = NULL;
00913
00914 if (ts->scriptFd != NULL) {
00915 if (rpmIsVerbose()) {
00916 out = fdDup(Fileno(ts->scriptFd));
00917 } else {
00918 out = Fopen("/dev/null", "w.fdio");
00919 if (Ferror(out)) {
00920 out = fdDup(Fileno(ts->scriptFd));
00921 }
00922 }
00923 } else {
00924 out = fdDup(STDOUT_FILENO);
00925 #ifdef DYING
00926 out = fdLink(out, "runScript persist");
00927 #endif
00928 }
00929 if (out == NULL) return 1;
00930
00931 if (!(child = fork())) {
00932 const char * rootDir;
00933 int pipes[2];
00934
00935 pipes[0] = pipes[1] = 0;
00936
00937 (void) pipe(pipes);
00938 (void) close(pipes[1]);
00939 (void) dup2(pipes[0], STDIN_FILENO);
00940 (void) close(pipes[0]);
00941
00942
00943 (void) umask(022);
00944
00945 if (ts->scriptFd != NULL) {
00946 if (Fileno(ts->scriptFd) != STDERR_FILENO)
00947 (void) dup2(Fileno(ts->scriptFd), STDERR_FILENO);
00948 if (Fileno(out) != STDOUT_FILENO)
00949 (void) dup2(Fileno(out), STDOUT_FILENO);
00950
00951 if (Fileno(out) > STDERR_FILENO && Fileno(out) != Fileno(ts->scriptFd)) {
00952 (void) Fclose (out);
00953 }
00954 if (Fileno(ts->scriptFd) > STDERR_FILENO) {
00955 (void) Fclose (ts->scriptFd);
00956 }
00957 }
00958
00959 { const char *ipath = rpmExpand("PATH=%{_install_script_path}", NULL);
00960 const char *path = SCRIPT_PATH;
00961
00962 if (ipath && ipath[5] != '%')
00963 path = ipath;
00964 (void) doputenv(path);
00965
00966 ipath = _free(ipath);
00967
00968 }
00969
00970 for (i = 0; i < numPrefixes; i++) {
00971 sprintf(prefixBuf, "RPM_INSTALL_PREFIX%d=%s", i, prefixes[i]);
00972 (void) doputenv(prefixBuf);
00973
00974
00975 if (i == 0) {
00976 sprintf(prefixBuf, "RPM_INSTALL_PREFIX=%s", prefixes[i]);
00977 (void) doputenv(prefixBuf);
00978 }
00979 }
00980
00981 if ((rootDir = ts->rootDir) != NULL)
00982 switch(urlIsURL(rootDir)) {
00983 case URL_IS_PATH:
00984 rootDir += sizeof("file://") - 1;
00985 rootDir = strchr(rootDir, '/');
00986
00987 case URL_IS_UNKNOWN:
00988 if (!ts->chrootDone && !(rootDir[0] == '/' && rootDir[1] == '\0')) {
00989
00990 (void) chroot(rootDir);
00991
00992 }
00993 (void) chdir("/");
00994 (void) execv(argv[0], (char *const *)argv);
00995 break;
00996 default:
00997 break;
00998 }
00999
01000 _exit(-1);
01001
01002 }
01003
01004 if (waitpid(child, &status, 0) < 0) {
01005 rpmError(RPMERR_SCRIPT,
01006 _("execution of %s scriptlet from %s-%s-%s failed, waitpid returned %s\n"),
01007 sln, n, v, r, strerror (errno));
01008
01009 rc = RPMRC_OK;
01010 } else {
01011 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
01012 rpmError(RPMERR_SCRIPT,
01013 _("execution of %s scriptlet from %s-%s-%s failed, exit status %d\n"),
01014 sln, n, v, r, WEXITSTATUS(status));
01015 rc = RPMRC_FAIL;
01016 }
01017 }
01018
01019 if (freePrefixes) prefixes = hfd(prefixes, ipt);
01020
01021 (void) Fclose(out);
01022
01023 if (script) {
01024 if (!rpmIsDebug())
01025 (void) unlink(fn);
01026 fn = _free(fn);
01027 }
01028
01029 return rc;
01030 }
01031
01037 static rpmRC runInstScript(PSM_t psm)
01038
01039 {
01040 TFI_t fi = psm->fi;
01041 HGE_t hge = fi->hge;
01042 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
01043 void ** programArgv;
01044 int programArgc;
01045 const char ** argv;
01046 rpmTagType ptt, stt;
01047 const char * script;
01048 rpmRC rc = RPMRC_OK;
01049
01050
01051
01052
01053
01054 (void) hge(fi->h, psm->progTag, &ptt, (void **) &programArgv, &programArgc);
01055 (void) hge(fi->h, psm->scriptTag, &stt, (void **) &script, NULL);
01056
01057 if (programArgv && ptt == RPM_STRING_TYPE) {
01058 argv = alloca(sizeof(char *));
01059 *argv = (const char *) programArgv;
01060 } else {
01061 argv = (const char **) programArgv;
01062 }
01063
01064 rc = runScript(psm, fi->h, tag2sln(psm->scriptTag), programArgc, argv,
01065 script, psm->scriptArg, -1);
01066
01067 programArgv = hfd(programArgv, ptt);
01068 script = hfd(script, stt);
01069 return RPMRC_OK;
01070 }
01071
01080 static int handleOneTrigger(PSM_t psm, Header sourceH, Header triggeredH,
01081 int arg2, unsigned char * triggersAlreadyRun)
01082
01083 {
01084 const rpmTransactionSet ts = psm->ts;
01085 TFI_t fi = psm->fi;
01086 HGE_t hge = fi->hge;
01087 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
01088 const char ** triggerNames;
01089 const char ** triggerEVR;
01090 const char ** triggerScripts;
01091 const char ** triggerProgs;
01092 int_32 * triggerFlags;
01093 int_32 * triggerIndices;
01094 rpmTagType tnt, tvt, tft;
01095 const char * triggerPackageName;
01096 const char * sourceName;
01097 int numTriggers;
01098 rpmRC rc = RPMRC_OK;
01099 int i;
01100 int skip;
01101
01102 if (!( hge(triggeredH, RPMTAG_TRIGGERNAME, &tnt,
01103 (void **) &triggerNames, &numTriggers) &&
01104 hge(triggeredH, RPMTAG_TRIGGERFLAGS, &tft,
01105 (void **) &triggerFlags, NULL) &&
01106 hge(triggeredH, RPMTAG_TRIGGERVERSION, &tvt,
01107 (void **) &triggerEVR, NULL))
01108 )
01109 return 0;
01110
01111 (void) headerNVR(sourceH, &sourceName, NULL, NULL);
01112
01113 for (i = 0; i < numTriggers; i++) {
01114 rpmTagType tit, tst, tpt;
01115
01116 if (!(triggerFlags[i] & psm->sense)) continue;
01117 if (strcmp(triggerNames[i], sourceName)) continue;
01118
01119
01120
01121
01122
01123
01124
01125 skip = strlen(triggerNames[i]);
01126 if (!strncmp(triggerEVR[i], triggerNames[i], skip) &&
01127 (triggerEVR[i][skip] == '-'))
01128 skip++;
01129 else
01130 skip = 0;
01131
01132 if (!headerMatchesDepFlags(sourceH, triggerNames[i],
01133 triggerEVR[i] + skip, triggerFlags[i]))
01134 continue;
01135
01136 if (!( hge(triggeredH, RPMTAG_TRIGGERINDEX, &tit,
01137 (void **) &triggerIndices, NULL) &&
01138 hge(triggeredH, RPMTAG_TRIGGERSCRIPTS, &tst,
01139 (void **) &triggerScripts, NULL) &&
01140 hge(triggeredH, RPMTAG_TRIGGERSCRIPTPROG, &tpt,
01141 (void **) &triggerProgs, NULL))
01142 )
01143 continue;
01144
01145 (void) headerNVR(triggeredH, &triggerPackageName, NULL, NULL);
01146
01147 { int arg1;
01148 int index;
01149
01150 arg1 = rpmdbCountPackages(ts->rpmdb, triggerPackageName);
01151 if (arg1 < 0) {
01152
01153 rc = RPMRC_FAIL;
01154 } else {
01155 arg1 += psm->countCorrection;
01156 index = triggerIndices[i];
01157 if (triggersAlreadyRun == NULL ||
01158 triggersAlreadyRun[index] == 0)
01159 {
01160 rc = runScript(psm, triggeredH, "%trigger", 1,
01161 triggerProgs + index, triggerScripts[index],
01162 arg1, arg2);
01163 if (triggersAlreadyRun != NULL)
01164 triggersAlreadyRun[index] = 1;
01165 }
01166 }
01167 }
01168
01169 triggerIndices = hfd(triggerIndices, tit);
01170 triggerScripts = hfd(triggerScripts, tst);
01171 triggerProgs = hfd(triggerProgs, tpt);
01172
01173
01174
01175
01176
01177 break;
01178 }
01179
01180 triggerNames = hfd(triggerNames, tnt);
01181 triggerFlags = hfd(triggerFlags, tft);
01182 triggerEVR = hfd(triggerEVR, tvt);
01183
01184 return rc;
01185 }
01186
01192 static int runTriggers(PSM_t psm)
01193
01194 {
01195 const rpmTransactionSet ts = psm->ts;
01196 TFI_t fi = psm->fi;
01197 int numPackage;
01198 rpmRC rc = RPMRC_OK;
01199
01200 numPackage = rpmdbCountPackages(ts->rpmdb, fi->name) + psm->countCorrection;
01201 if (numPackage < 0)
01202 return 1;
01203
01204 { Header triggeredH;
01205 rpmdbMatchIterator mi;
01206 int countCorrection = psm->countCorrection;
01207
01208 psm->countCorrection = 0;
01209 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_TRIGGERNAME, fi->name, 0);
01210 while((triggeredH = rpmdbNextIterator(mi)) != NULL) {
01211 rc |= handleOneTrigger(psm, fi->h, triggeredH, numPackage, NULL);
01212 }
01213
01214 mi = rpmdbFreeIterator(mi);
01215 psm->countCorrection = countCorrection;
01216 }
01217
01218 return rc;
01219 }
01220
01226 static int runImmedTriggers(PSM_t psm)
01227
01228 {
01229 const rpmTransactionSet ts = psm->ts;
01230 TFI_t fi = psm->fi;
01231 HGE_t hge = fi->hge;
01232 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
01233 const char ** triggerNames;
01234 int numTriggers;
01235 int_32 * triggerIndices;
01236 rpmTagType tnt, tit;
01237 int numTriggerIndices;
01238 unsigned char * triggersRun;
01239 rpmRC rc = RPMRC_OK;
01240
01241 if (!( hge(fi->h, RPMTAG_TRIGGERNAME, &tnt,
01242 (void **) &triggerNames, &numTriggers) &&
01243 hge(fi->h, RPMTAG_TRIGGERINDEX, &tit,
01244 (void **) &triggerIndices, &numTriggerIndices))
01245 )
01246 return 0;
01247
01248 triggersRun = alloca(sizeof(*triggersRun) * numTriggerIndices);
01249 memset(triggersRun, 0, sizeof(*triggersRun) * numTriggerIndices);
01250
01251 { Header sourceH = NULL;
01252 int i;
01253
01254 for (i = 0; i < numTriggers; i++) {
01255 rpmdbMatchIterator mi;
01256
01257 if (triggersRun[triggerIndices[i]] != 0) continue;
01258
01259 mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, triggerNames[i], 0);
01260
01261 while((sourceH = rpmdbNextIterator(mi)) != NULL) {
01262 rc |= handleOneTrigger(psm, sourceH, fi->h,
01263 rpmdbGetIteratorCount(mi),
01264 triggersRun);
01265 }
01266
01267 mi = rpmdbFreeIterator(mi);
01268 }
01269 }
01270 triggerIndices = hfd(triggerIndices, tit);
01271 triggerNames = hfd(triggerNames, tnt);
01272 return rc;
01273 }
01274
01275 static const char *const pkgStageString(pkgStage a) {
01276 switch(a) {
01277 case PSM_UNKNOWN: return "unknown";
01278
01279 case PSM_PKGINSTALL: return " install";
01280 case PSM_PKGERASE: return " erase";
01281 case PSM_PKGCOMMIT: return " commit";
01282 case PSM_PKGSAVE: return "repackage";
01283
01284 case PSM_INIT: return "init";
01285 case PSM_PRE: return "pre";
01286 case PSM_PROCESS: return "process";
01287 case PSM_POST: return "post";
01288 case PSM_UNDO: return "undo";
01289 case PSM_FINI: return "fini";
01290
01291 case PSM_CREATE: return "create";
01292 case PSM_NOTIFY: return "notify";
01293 case PSM_DESTROY: return "destroy";
01294 case PSM_COMMIT: return "commit";
01295
01296 case PSM_CHROOT_IN: return "chrootin";
01297 case PSM_CHROOT_OUT: return "chrootout";
01298 case PSM_SCRIPT: return "script";
01299 case PSM_TRIGGERS: return "triggers";
01300 case PSM_IMMED_TRIGGERS: return "immedtriggers";
01301
01302 case PSM_RPMIO_FLAGS: return "rpmioflags";
01303
01304 case PSM_RPMDB_LOAD: return "rpmdbload";
01305 case PSM_RPMDB_ADD: return "rpmdbadd";
01306 case PSM_RPMDB_REMOVE: return "rpmdbremove";
01307
01308 default: return "???";
01309 }
01310
01311 }
01312
01317 int psmStage(PSM_t psm, pkgStage stage)
01318 {
01319 const rpmTransactionSet ts = psm->ts;
01320 TFI_t fi = psm->fi;
01321 HGE_t hge = fi->hge;
01322 HME_t hme = fi->hme;
01323 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
01324 rpmRC rc = psm->rc;
01325 int saveerrno;
01326
01327 switch (stage) {
01328 case PSM_UNKNOWN:
01329 break;
01330 case PSM_INIT:
01331 rpmMessage(RPMMESS_DEBUG, _("%s: %s-%s-%s has %d files, test = %d\n"),
01332 psm->stepName, fi->name, fi->version, fi->release,
01333 fi->fc, (ts->transFlags & RPMTRANS_FLAG_TEST));
01334
01335
01336
01337
01338
01339
01340 psm->npkgs_installed = rpmdbCountPackages(ts->rpmdb, fi->name);
01341 if (psm->npkgs_installed < 0) {
01342 rc = RPMRC_FAIL;
01343 break;
01344 }
01345
01346 if (psm->goal == PSM_PKGINSTALL) {
01347 psm->scriptArg = psm->npkgs_installed + 1;
01348
01349 assert(psm->mi == NULL);
01350 psm->mi = rpmdbInitIterator(ts->rpmdb, RPMTAG_NAME, fi->name, 0);
01351 (void) rpmdbSetIteratorRE(psm->mi, RPMTAG_VERSION,
01352 RPMMIRE_DEFAULT, fi->version);
01353 (void) rpmdbSetIteratorRE(psm->mi, RPMTAG_RELEASE,
01354 RPMMIRE_DEFAULT, fi->release);
01355
01356 while ((psm->oh = rpmdbNextIterator(psm->mi))) {
01357 fi->record = rpmdbGetIteratorOffset(psm->mi);
01358 if (ts->transFlags & RPMTRANS_FLAG_MULTILIB)
01359 psm->oh = headerCopy(psm->oh);
01360 else
01361 psm->oh = NULL;
01362 break;
01363 }
01364 psm->mi = rpmdbFreeIterator(psm->mi);
01365 rc = RPMRC_OK;
01366
01367 if (fi->fc > 0 && fi->fstates == NULL) {
01368 fi->fstates = xmalloc(sizeof(*fi->fstates) * fi->fc);
01369 memset(fi->fstates, RPMFILE_STATE_NORMAL, fi->fc);
01370 }
01371
01372 if (fi->fc <= 0) break;
01373 if (ts->transFlags & RPMTRANS_FLAG_JUSTDB) break;
01374
01375
01376
01377
01378
01379
01380 { const char * p;
01381 rc = hge(fi->h, RPMTAG_DEFAULTPREFIX, NULL, (void **) &p, NULL);
01382 fi->striplen = (rc ? strlen(p) + 1 : 1);
01383 }
01384 fi->mapflags =
01385 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
01386
01387 if (headerIsEntry(fi->h, RPMTAG_ORIGBASENAMES))
01388 buildOrigFileList(fi->h, &fi->apath, NULL);
01389 else
01390 rpmBuildFileList(fi->h, &fi->apath, NULL);
01391
01392 if (fi->fuser == NULL)
01393 (void) hge(fi->h, RPMTAG_FILEUSERNAME, NULL,
01394 (void **) &fi->fuser, NULL);
01395 if (fi->fgroup == NULL)
01396 (void) hge(fi->h, RPMTAG_FILEGROUPNAME, NULL,
01397 (void **) &fi->fgroup, NULL);
01398 if (fi->fuids == NULL)
01399 fi->fuids = xcalloc(sizeof(*fi->fuids), fi->fc);
01400 if (fi->fgids == NULL)
01401 fi->fgids = xcalloc(sizeof(*fi->fgids), fi->fc);
01402 rc = RPMRC_OK;
01403 }
01404 if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
01405 psm->scriptArg = psm->npkgs_installed - 1;
01406
01407
01408 rc = psmStage(psm, PSM_RPMDB_LOAD);
01409 }
01410 if (psm->goal == PSM_PKGSAVE) {
01411
01412 { const char * bfmt = rpmGetPath("%{_repackage_name_fmt}", NULL);
01413 const char * pkgbn =
01414 headerSprintf(fi->h, bfmt, rpmTagTable, rpmHeaderFormats, NULL);
01415
01416 bfmt = _free(bfmt);
01417 psm->pkgURL = rpmGenPath("%{?_repackage_root:%{_repackage_root}}",
01418 "%{?_repackage_dir:%{_repackage_dir}}",
01419 pkgbn);
01420 pkgbn = _free(pkgbn);
01421 (void) urlPath(psm->pkgURL, &psm->pkgfn);
01422 psm->fd = Fopen(psm->pkgfn, "w.ufdio");
01423 if (psm->fd == NULL || Ferror(psm->fd)) {
01424 rc = RPMRC_FAIL;
01425 break;
01426 }
01427 }
01428 }
01429 break;
01430 case PSM_PRE:
01431 if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
01432
01433
01434 rc = psmStage(psm, PSM_CHROOT_IN);
01435
01436 if (psm->goal == PSM_PKGINSTALL) {
01437 psm->scriptTag = RPMTAG_PREIN;
01438 psm->progTag = RPMTAG_PREINPROG;
01439
01440 if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERPREIN)) {
01441
01442 }
01443
01444 if (!(ts->transFlags & RPMTRANS_FLAG_NOPRE)) {
01445 rc = psmStage(psm, PSM_SCRIPT);
01446 if (rc) {
01447 rpmError(RPMERR_SCRIPT,
01448 _("%s: %s scriptlet failed (%d), skipping %s-%s-%s\n"),
01449 psm->stepName, tag2sln(psm->scriptTag), rc,
01450 fi->name, fi->version, fi->release);
01451 break;
01452 }
01453 }
01454 }
01455
01456 if (psm->goal == PSM_PKGERASE) {
01457 psm->scriptTag = RPMTAG_PREUN;
01458 psm->progTag = RPMTAG_PREUNPROG;
01459 psm->sense = RPMSENSE_TRIGGERUN;
01460 psm->countCorrection = -1;
01461
01462 if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERUN)) {
01463
01464 rc = psmStage(psm, PSM_TRIGGERS);
01465 if (rc) break;
01466
01467
01468 rc = psmStage(psm, PSM_IMMED_TRIGGERS);
01469 if (rc) break;
01470 }
01471
01472 if (!(ts->transFlags & RPMTRANS_FLAG_NOPREUN))
01473 rc = psmStage(psm, PSM_SCRIPT);
01474 }
01475 if (psm->goal == PSM_PKGSAVE) {
01476
01477 { void * uh = NULL;
01478 int_32 uht, uhc;
01479
01480 if (headerGetEntry(fi->h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)) {
01481 psm->oh = headerCopyLoad(uh);
01482 uh = hfd(uh, uht);
01483 } else {
01484 psm->oh = headerLink(fi->h);
01485 }
01486 }
01487
01488
01489 if (psm->oh)
01490 { int_32 tid = ts->id;
01491 (void) headerAddEntry(psm->oh, RPMTAG_REMOVETID,
01492 RPM_INT32_TYPE, &tid, 1);
01493 }
01494
01495
01496
01497 rc = psmStage(psm, PSM_RPMIO_FLAGS);
01498
01499
01500
01501 { int archnum = -1;
01502 int osnum = -1;
01503 struct rpmlead lead;
01504
01505 #ifndef DYING
01506 rpmGetArchInfo(NULL, &archnum);
01507 rpmGetOsInfo(NULL, &osnum);
01508 #endif
01509
01510 memset(&lead, 0, sizeof(lead));
01511
01512 lead.major = 4;
01513 lead.minor = 0;
01514 lead.type = RPMLEAD_BINARY;
01515 lead.archnum = archnum;
01516 lead.osnum = osnum;
01517 lead.signature_type = RPMSIGTYPE_HEADERSIG;
01518
01519 { char buf[256];
01520 sprintf(buf, "%s-%s-%s", fi->name, fi->version, fi->release);
01521 strncpy(lead.name, buf, sizeof(lead.name));
01522 }
01523
01524 rc = writeLead(psm->fd, &lead);
01525 if (rc) {
01526 rpmError(RPMERR_NOSPACE, _("Unable to write package: %s\n"),
01527 Fstrerror(psm->fd));
01528 rc = RPMRC_FAIL;
01529 break;
01530 }
01531 }
01532
01533
01534 { Header sig = headerRegenSigHeader(fi->h);
01535 rc = rpmWriteSignature(psm->fd, sig);
01536 sig = rpmFreeSignature(sig);
01537 if (rc) break;
01538 }
01539
01540
01541 rc = headerWrite(psm->fd, psm->oh, HEADER_MAGIC_YES);
01542 if (rc) break;
01543 }
01544 break;
01545 case PSM_PROCESS:
01546 if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
01547
01548 if (psm->goal == PSM_PKGINSTALL) {
01549 struct availablePackage * alp = fi->ap;
01550 int i;
01551
01552 if (fi->fc <= 0) break;
01553 if (ts->transFlags & RPMTRANS_FLAG_JUSTDB) break;
01554
01555 for (i = 0; i < fi->fc; i++) {
01556 uid_t uid;
01557 gid_t gid;
01558
01559 uid = fi->uid;
01560 gid = fi->gid;
01561 if (fi->fuser && unameToUid(fi->fuser[i], &uid)) {
01562 rpmMessage(RPMMESS_WARNING,
01563 _("user %s does not exist - using root\n"),
01564 fi->fuser[i]);
01565 uid = 0;
01566
01567 fi->fmodes[i] &= ~S_ISUID;
01568 }
01569
01570 if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) {
01571 rpmMessage(RPMMESS_WARNING,
01572 _("group %s does not exist - using root\n"),
01573 fi->fgroup[i]);
01574 gid = 0;
01575
01576 fi->fmodes[i] &= ~S_ISGID;
01577 }
01578 if (fi->fuids) fi->fuids[i] = uid;
01579 if (fi->fgids) fi->fgids[i] = gid;
01580 }
01581
01582
01583 rc = psmStage(psm, PSM_RPMIO_FLAGS);
01584
01585 if (alp->fd == NULL) {
01586 rc = RPMRC_FAIL;
01587 break;
01588 }
01589
01590 psm->cfd = Fdopen(fdDup(Fileno(alp->fd)), psm->rpmio_flags);
01591
01592 if (psm->cfd == NULL) {
01593 rc = RPMRC_FAIL;
01594 break;
01595 }
01596
01597 rc = fsmSetup(fi->fsm, FSM_PKGINSTALL, ts, fi,
01598 psm->cfd, NULL, &psm->failedFile);
01599 (void) fsmTeardown(fi->fsm);
01600
01601 saveerrno = errno;
01602 (void) Fclose(psm->cfd);
01603 psm->cfd = NULL;
01604 errno = saveerrno;
01605
01606 if (!rc)
01607 rc = psmStage(psm, PSM_COMMIT);
01608
01609 if (rc) {
01610 rpmError(RPMERR_CPIO,
01611 _("unpacking of archive failed%s%s: %s\n"),
01612 (psm->failedFile != NULL ? _(" on file ") : ""),
01613 (psm->failedFile != NULL ? psm->failedFile : ""),
01614 cpioStrerror(rc));
01615 rc = RPMRC_FAIL;
01616 break;
01617 }
01618 psm->what = RPMCALLBACK_INST_PROGRESS;
01619 psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
01620 psm->total = psm->amount;
01621 (void) psmStage(psm, PSM_NOTIFY);
01622 }
01623 if (psm->goal == PSM_PKGERASE) {
01624
01625 if (fi->fc <= 0) break;
01626 if (ts->transFlags & RPMTRANS_FLAG_JUSTDB) break;
01627 if (ts->transFlags & RPMTRANS_FLAG_APPLYONLY) break;
01628
01629 psm->what = RPMCALLBACK_UNINST_START;
01630 psm->amount = fi->fc;
01631 psm->total = fi->fc;
01632 (void) psmStage(psm, PSM_NOTIFY);
01633
01634 rc = fsmSetup(fi->fsm, FSM_PKGERASE, ts, fi,
01635 NULL, NULL, &psm->failedFile);
01636 (void) fsmTeardown(fi->fsm);
01637
01638 psm->what = RPMCALLBACK_UNINST_STOP;
01639 psm->amount = 0;
01640 psm->total = fi->fc;
01641 (void) psmStage(psm, PSM_NOTIFY);
01642
01643 }
01644 if (psm->goal == PSM_PKGSAVE) {
01645 fileAction * actions = fi->actions;
01646 fileAction action = fi->action;
01647
01648 fi->action = FA_COPYOUT;
01649 fi->actions = NULL;
01650
01651 if (psm->fd == NULL) {
01652 rc = RPMRC_FAIL;
01653 break;
01654 }
01655
01656 (void) Fflush(psm->fd);
01657 psm->cfd = Fdopen(fdDup(Fileno(psm->fd)), psm->rpmio_flags);
01658
01659 if (psm->cfd == NULL) {
01660 rc = RPMRC_FAIL;
01661 break;
01662 }
01663
01664 rc = fsmSetup(fi->fsm, FSM_PKGBUILD, ts, fi, psm->cfd,
01665 NULL, &psm->failedFile);
01666 (void) fsmTeardown(fi->fsm);
01667
01668 saveerrno = errno;
01669 (void) Fclose(psm->cfd);
01670 psm->cfd = NULL;
01671 errno = saveerrno;
01672
01673 fi->action = action;
01674 fi->actions = actions;
01675 }
01676 break;
01677 case PSM_POST:
01678 if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
01679
01680 if (psm->goal == PSM_PKGINSTALL) {
01681 int_32 installTime = (int_32) time(NULL);
01682
01683 if (fi->fstates != NULL && fi->fc > 0)
01684 (void) headerAddEntry(fi->h, RPMTAG_FILESTATES, RPM_CHAR_TYPE,
01685 fi->fstates, fi->fc);
01686
01687 (void) headerAddEntry(fi->h, RPMTAG_INSTALLTIME, RPM_INT32_TYPE,
01688 &installTime, 1);
01689
01690 if (ts->transFlags & RPMTRANS_FLAG_MULTILIB) {
01691 uint_32 multiLib, * newMultiLib, * p;
01692
01693 if (hge(fi->h, RPMTAG_MULTILIBS, NULL,
01694 (void **) &newMultiLib, NULL) &&
01695 hge(psm->oh, RPMTAG_MULTILIBS, NULL,
01696 (void **) &p, NULL))
01697 {
01698 multiLib = *p;
01699 multiLib |= *newMultiLib;
01700 (void) hme(psm->oh, RPMTAG_MULTILIBS, RPM_INT32_TYPE,
01701 &multiLib, 1);
01702 }
01703 rc = mergeFiles(fi, psm->oh, fi->h);
01704 if (rc) break;
01705 }
01706
01707
01708
01709
01710
01711
01712 if (fi->record && !(ts->transFlags & RPMTRANS_FLAG_APPLYONLY)) {
01713 rc = psmStage(psm, PSM_RPMDB_REMOVE);
01714 if (rc) break;
01715 }
01716
01717 rc = psmStage(psm, PSM_RPMDB_ADD);
01718 if (rc) break;
01719
01720 psm->scriptTag = RPMTAG_POSTIN;
01721 psm->progTag = RPMTAG_POSTINPROG;
01722 psm->sense = RPMSENSE_TRIGGERIN;
01723 psm->countCorrection = 0;
01724
01725 if (!(ts->transFlags & RPMTRANS_FLAG_NOPOST)) {
01726 rc = psmStage(psm, PSM_SCRIPT);
01727 if (rc) break;
01728 }
01729 if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERIN)) {
01730
01731 rc = psmStage(psm, PSM_TRIGGERS);
01732 if (rc) break;
01733
01734
01735 rc = psmStage(psm, PSM_IMMED_TRIGGERS);
01736 if (rc) break;
01737 }
01738
01739 if (!(ts->transFlags & RPMTRANS_FLAG_APPLYONLY))
01740 rc = markReplacedFiles(psm);
01741
01742 }
01743 if (psm->goal == PSM_PKGERASE) {
01744
01745 psm->scriptTag = RPMTAG_POSTUN;
01746 psm->progTag = RPMTAG_POSTUNPROG;
01747 psm->sense = RPMSENSE_TRIGGERPOSTUN;
01748 psm->countCorrection = -1;
01749
01750 if (!(ts->transFlags & RPMTRANS_FLAG_NOPOSTUN)) {
01751 rc = psmStage(psm, PSM_SCRIPT);
01752
01753 }
01754
01755 if (!(ts->transFlags & RPMTRANS_FLAG_NOTRIGGERPOSTUN)) {
01756
01757 rc = psmStage(psm, PSM_TRIGGERS);
01758 if (rc) break;
01759 }
01760
01761 if (!(ts->transFlags & RPMTRANS_FLAG_APPLYONLY))
01762 rc = psmStage(psm, PSM_RPMDB_REMOVE);
01763 }
01764 if (psm->goal == PSM_PKGSAVE) {
01765 }
01766
01767
01768 (void) psmStage(psm, PSM_CHROOT_OUT);
01769 break;
01770 case PSM_UNDO:
01771 break;
01772 case PSM_FINI:
01773
01774 (void) psmStage(psm, PSM_CHROOT_OUT);
01775
01776 if (psm->fd) {
01777 saveerrno = errno;
01778 (void) Fclose(psm->fd);
01779 psm->fd = NULL;
01780 errno = saveerrno;
01781 }
01782
01783 if (psm->goal == PSM_PKGSAVE) {
01784 if (!rc) {
01785 rpmMessage(RPMMESS_VERBOSE, _("Wrote: %s\n"),
01786 (psm->pkgURL ? psm->pkgURL : "???"));
01787 }
01788 }
01789
01790 if (rc) {
01791 if (psm->failedFile)
01792 rpmError(RPMERR_CPIO,
01793 _("%s failed on file %s: %s\n"),
01794 psm->stepName, psm->failedFile, cpioStrerror(rc));
01795 else
01796 rpmError(RPMERR_CPIO, _("%s failed: %s\n"),
01797 psm->stepName, cpioStrerror(rc));
01798 }
01799
01800 if (fi->h && (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE))
01801 fi->h = headerFree(fi->h);
01802 psm->oh = headerFree(psm->oh);
01803 psm->pkgURL = _free(psm->pkgURL);
01804 psm->rpmio_flags = _free(psm->rpmio_flags);
01805 psm->failedFile = _free(psm->failedFile);
01806
01807 fi->fgids = _free(fi->fgids);
01808 fi->fuids = _free(fi->fuids);
01809 fi->fgroup = hfd(fi->fgroup, -1);
01810 fi->fuser = hfd(fi->fuser, -1);
01811 fi->apath = _free(fi->apath);
01812 fi->fstates = _free(fi->fstates);
01813 break;
01814
01815 case PSM_PKGINSTALL:
01816 case PSM_PKGERASE:
01817 case PSM_PKGSAVE:
01818 psm->goal = stage;
01819 psm->rc = RPMRC_OK;
01820 psm->stepName = pkgStageString(stage);
01821
01822 rc = psmStage(psm, PSM_INIT);
01823 if (!rc) rc = psmStage(psm, PSM_PRE);
01824 if (!rc) rc = psmStage(psm, PSM_PROCESS);
01825 if (!rc) rc = psmStage(psm, PSM_POST);
01826 (void) psmStage(psm, PSM_FINI);
01827 break;
01828 case PSM_PKGCOMMIT:
01829 break;
01830
01831 case PSM_CREATE:
01832 break;
01833 case PSM_NOTIFY:
01834 if (ts && ts->notify)
01835 (void) ts->notify(fi->h, psm->what, psm->amount, psm->total,
01836 (fi->ap ? fi->ap->key : NULL), ts->notifyData);
01837 break;
01838 case PSM_DESTROY:
01839 break;
01840 case PSM_COMMIT:
01841 if (!(ts->transFlags & RPMTRANS_FLAG_PKGCOMMIT)) break;
01842 if (ts->transFlags & RPMTRANS_FLAG_APPLYONLY) break;
01843
01844 rc = fsmSetup(fi->fsm, FSM_PKGCOMMIT, ts, fi,
01845 NULL, NULL, &psm->failedFile);
01846 (void) fsmTeardown(fi->fsm);
01847 break;
01848
01849 case PSM_CHROOT_IN:
01850
01851 if (ts->rootDir && !ts->chrootDone && !psm->chrootDone) {
01852 static int _loaded = 0;
01853
01854
01855
01856
01857
01858 if (!_loaded) {
01859 (void)getpwnam("root");
01860 endpwent();
01861 _loaded++;
01862 }
01863
01864 (void) chdir("/");
01865
01866 rc = chroot(ts->rootDir);
01867
01868 psm->chrootDone = ts->chrootDone = 1;
01869 if (ts->rpmdb != NULL) ts->rpmdb->db_chrootDone = 1;
01870
01871 chroot_prefix = ts->rootDir;
01872
01873 }
01874 break;
01875 case PSM_CHROOT_OUT:
01876
01877 if (psm->chrootDone) {
01878
01879 rc = chroot(".");
01880
01881 psm->chrootDone = ts->chrootDone = 0;
01882 if (ts->rpmdb != NULL) ts->rpmdb->db_chrootDone = 0;
01883 chroot_prefix = NULL;
01884 (void) chdir(ts->currDir);
01885 }
01886 break;
01887 case PSM_SCRIPT:
01888 rpmMessage(RPMMESS_DEBUG, _("%s: running %s script(s) (if any)\n"),
01889 psm->stepName, tag2sln(psm->scriptTag));
01890 rc = runInstScript(psm);
01891 break;
01892 case PSM_TRIGGERS:
01893
01894 rc = runTriggers(psm);
01895 break;
01896 case PSM_IMMED_TRIGGERS:
01897
01898 rc = runImmedTriggers(psm);
01899 break;
01900
01901 case PSM_RPMIO_FLAGS:
01902 { const char * payload_compressor = NULL;
01903 char * t;
01904
01905 if (!hge(fi->h, RPMTAG_PAYLOADCOMPRESSOR, NULL,
01906 (void **) &payload_compressor, NULL))
01907 payload_compressor = "gzip";
01908 psm->rpmio_flags = t = xmalloc(sizeof("w9.gzdio"));
01909 *t = '\0';
01910 t = stpcpy(t, ((psm->goal == PSM_PKGSAVE) ? "w9" : "r"));
01911 if (!strcmp(payload_compressor, "gzip"))
01912 t = stpcpy(t, ".gzdio");
01913 if (!strcmp(payload_compressor, "bzip2"))
01914 t = stpcpy(t, ".bzdio");
01915 rc = RPMRC_OK;
01916 } break;
01917
01918 case PSM_RPMDB_LOAD:
01919 assert(psm->mi == NULL);
01920 psm->mi = rpmdbInitIterator(ts->rpmdb, RPMDBI_PACKAGES,
01921 &fi->record, sizeof(fi->record));
01922
01923 fi->h = rpmdbNextIterator(psm->mi);
01924 if (fi->h)
01925 fi->h = headerLink(fi->h);
01926 else {
01927 fprintf(stderr, "*** PSM_RDB_LOAD: header #%u not found\n", fi->record);
01928 }
01929 psm->mi = rpmdbFreeIterator(psm->mi);
01930 rc = (fi->h ? RPMRC_OK : RPMRC_FAIL);
01931 break;
01932 case PSM_RPMDB_ADD:
01933 if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
01934 rc = rpmdbAdd(ts->rpmdb, ts->id, fi->h);
01935 #if HAVE_SYSLOG_H
01936 syslog(LOG_NOTICE, "[RPM] %s-%s-%s installed\n", fi->name, fi->version, fi->release);
01937 #endif
01938 break;
01939 case PSM_RPMDB_REMOVE:
01940 if (ts->transFlags & RPMTRANS_FLAG_TEST) break;
01941 rc = rpmdbRemove(ts->rpmdb, ts->id, fi->record);
01942 #if HAVE_SYSLOG_H
01943 syslog(LOG_NOTICE, "[RPM] %s-%s-%s removed\n", fi->name, fi->version, fi->release);
01944 #endif
01945 break;
01946
01947 default:
01948 break;
01949 }
01950
01951
01952 return rc;
01953
01954 }