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