/* XXX DWRITE uses rdnb for I/O length. */
fsm->rdnb = PHYS_HDR_SIZE + sizeof(CPIO_TRAILER);
- rc = fsmStage(fsm, FSM_DWRITE);
+ rc = fsmNext(fsm, FSM_DWRITE);
/*
* GNU cpio pads to 512 bytes here, but we don't. This may matter for
* tape device(s) and/or concatenated cpio archives. <shrug>
*/
if (!rc)
- rc = fsmStage(fsm, FSM_PAD);
+ rc = fsmNext(fsm, FSM_PAD);
return rc;
}
/* XXX DWRITE uses rdnb for I/O length. */
fsm->rdnb = PHYS_HDR_SIZE + len;
- rc = fsmStage(fsm, FSM_DWRITE);
+ rc = fsmNext(fsm, FSM_DWRITE);
if (!rc && fsm->rdnb != fsm->wrnb)
rc = CPIOERR_WRITE_FAILED;
if (!rc)
- rc = fsmStage(fsm, FSM_PAD);
+ rc = fsmNext(fsm, FSM_PAD);
return rc;
}
int rc = 0;
fsm->wrlen = PHYS_HDR_SIZE;
- rc = fsmStage(fsm, FSM_DREAD);
+ rc = fsmNext(fsm, FSM_DREAD);
if (!rc && fsm->rdnb != fsm->wrlen)
rc = CPIOERR_READ_FAILED;
if (rc) return rc;
{ char * t = xmalloc(nameSize + 1);
fsm->wrlen = nameSize;
- rc = fsmStage(fsm, FSM_DREAD);
+ rc = fsmNext(fsm, FSM_DREAD);
if (!rc && fsm->rdnb != fsm->wrlen)
rc = CPIOERR_BAD_HEADER;
if (rc) {
#include "rpmfi.h"
#include "rpmte.h"
#include "rpmts.h"
+#include "rpmsq.h"
#include "debug.h"
}
/*@=boundsread@*/
+static void * fsmThread(void * arg)
+ /*@modifies arg @*/
+{
+ FSM_t fsm = arg;
+ return ((void *) fsmStage(fsm, fsm->nstage));
+}
+
+int fsmNext(FSM_t fsm, fileStage nstage)
+ /*@modifies fsm @*/
+{
+ fsm->nstage = nstage;
+ return rpmsqThread(fsmThread, fsm);
+}
+
/** \ingroup payload
* Save hard link in chain.
* @param fsm file state machine data
fsm->li->linkIndex = j;
fsm->path = _free(fsm->path);
fsm->ix = ix;
- rc = fsmStage(fsm, FSM_MAP);
+ rc = fsmNext(fsm, FSM_MAP);
return rc;
}
/*@=boundsread@*/
int left = st->st_size;
int rc = 0;
- rc = fsmStage(fsm, FSM_WOPEN);
+ rc = fsmNext(fsm, FSM_WOPEN);
if (rc)
goto exit;
while (left) {
fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left);
- rc = fsmStage(fsm, FSM_DREAD);
+ rc = fsmNext(fsm, FSM_DREAD);
if (rc)
goto exit;
- rc = fsmStage(fsm, FSM_WRITE);
+ rc = fsmNext(fsm, FSM_WRITE);
if (rc)
goto exit;
/* don't call this with fileSize == fileComplete */
if (!rc && left)
- (void) fsmStage(fsm, FSM_NOTIFY);
+ (void) fsmNext(fsm, FSM_NOTIFY);
}
if (st->st_size > 0 && (fsm->fmd5sum || fsm->md5sum)) {
}
exit:
- (void) fsmStage(fsm, FSM_WCLOSE);
+ (void) fsmNext(fsm, FSM_WCLOSE);
return rc;
}
(fi->apath ? fi->apath[fsm->ix] + fi->striplen : fi->bnl[fsm->ix]);
}
- rc = fsmStage(fsm, FSM_HWRITE);
+ rc = fsmNext(fsm, FSM_HWRITE);
fsm->path = path;
if (rc) goto exit;
size_t nmapped;
#endif
- rc = fsmStage(fsm, FSM_ROPEN);
+ rc = fsmNext(fsm, FSM_ROPEN);
if (rc) goto exit;
/* XXX unbuffered mmap generates *lots* of fdio debugging */
#endif
{
fsm->rdlen = (left > fsm->rdsize ? fsm->rdsize : left),
- rc = fsmStage(fsm, FSM_READ);
+ rc = fsmNext(fsm, FSM_READ);
if (rc) goto exit;
}
/* XXX DWRITE uses rdnb for I/O length. */
- rc = fsmStage(fsm, FSM_DWRITE);
+ rc = fsmNext(fsm, FSM_DWRITE);
if (rc) goto exit;
left -= fsm->wrnb;
strcpy(fsm->rdbuf, symbuf); /* XXX restore readlink buffer. */
/*@=boundswrite@*/
fsm->rdnb = strlen(symbuf);
- rc = fsmStage(fsm, FSM_DWRITE);
+ rc = fsmNext(fsm, FSM_DWRITE);
if (rc) goto exit;
}
- rc = fsmStage(fsm, FSM_PAD);
+ rc = fsmNext(fsm, FSM_PAD);
if (rc) goto exit;
rc = 0;
exit:
if (fsm->rfd != NULL)
- (void) fsmStage(fsm, FSM_RCLOSE);
+ (void) fsmNext(fsm, FSM_RCLOSE);
/*@-dependenttrans@*/
fsm->opath = opath;
fsm->path = path;
if (fsm->li->filex[i] < 0) continue;
fsm->ix = fsm->li->filex[i];
- rc = fsmStage(fsm, FSM_MAP);
+ rc = fsmNext(fsm, FSM_MAP);
/* Write data after last link. */
rc = writeFile(fsm, (i == 0));
fsm->ix = -1;
fsm->ix = fsm->li->filex[fsm->li->createdPath];
- rc = fsmStage(fsm, FSM_MAP);
+ rc = fsmNext(fsm, FSM_MAP);
fsm->opath = fsm->path;
fsm->path = NULL;
/*@-branchstate@*/
fsm->ix = fsm->li->filex[i];
fsm->path = _free(fsm->path);
- rc = fsmStage(fsm, FSM_MAP);
+ rc = fsmNext(fsm, FSM_MAP);
if (XFA_SKIPPING(fsm->action)) continue;
- rc = fsmStage(fsm, FSM_VERIFY);
+ rc = fsmUNSAFE(fsm, FSM_VERIFY);
if (!rc) continue;
if (rc != CPIOERR_LSTAT_FAILED) break;
/* XXX link(fsm->opath, fsm->path) */
- rc = fsmStage(fsm, FSM_LINK);
+ rc = fsmNext(fsm, FSM_LINK);
if (fsm->failedFile && rc != 0 && *fsm->failedFile == NULL) {
ec = rc;
/*@-boundswrite@*/
for (i = 0; i < fsm->li->nlink; i++) {
if (fsm->li->filex[i] < 0) continue;
fsm->ix = fsm->li->filex[i];
- rc = fsmStage(fsm, FSM_MAP);
+ rc = fsmNext(fsm, FSM_MAP);
if (!XFA_SKIPPING(fsm->action))
- rc = fsmStage(fsm, FSM_COMMIT);
+ rc = fsmNext(fsm, FSM_COMMIT);
fsm->path = _free(fsm->path);
fsm->li->filex[i] = -1;
}
do {
if (*te == '/') {
*te = '\0';
- rc = fsmStage(fsm, FSM_RMDIR);
+ rc = fsmNext(fsm, FSM_RMDIR);
*te = '/';
}
if (rc)
rpmfi fi = fsmGetFi(fsm);
*te = '\0';
st->st_mode = S_IFDIR | (fi->dperms & 07777);
- rc = fsmStage(fsm, FSM_MKDIR);
+ rc = fsmNext(fsm, FSM_MKDIR);
if (!rc)
rpmMessage(RPMMESS_DEBUG,
_("%s directory created with perms %04o.\n"),
case FSM_PKGINSTALL:
while (1) {
/* Clean fsm, free'ing memory. Read next archive header. */
- rc = fsmStage(fsm, FSM_INIT);
+ rc = fsmUNSAFE(fsm, FSM_INIT);
/* Exit on end-of-payload. */
if (rc == CPIOERR_HDR_TRAILER) {
/* Exit on error. */
if (rc) {
fsm->postpone = 1;
- (void) fsmStage(fsm, FSM_UNDO);
+ (void) fsmNext(fsm, FSM_UNDO);
/*@loopbreak@*/ break;
}
/* Extract file from archive. */
- rc = fsmStage(fsm, FSM_PROCESS);
+ rc = fsmNext(fsm, FSM_PROCESS);
if (rc) {
- (void) fsmStage(fsm, FSM_UNDO);
+ (void) fsmNext(fsm, FSM_UNDO);
/*@loopbreak@*/ break;
}
/* Notify on success. */
- (void) fsmStage(fsm, FSM_NOTIFY);
+ (void) fsmNext(fsm, FSM_NOTIFY);
- rc = fsmStage(fsm, FSM_FINI);
+ rc = fsmNext(fsm, FSM_FINI);
if (rc) {
/*@loopbreak@*/ break;
}
case FSM_PKGCOMMIT:
while (1) {
/* Clean fsm, free'ing memory. */
- rc = fsmStage(fsm, FSM_INIT);
+ rc = fsmUNSAFE(fsm, FSM_INIT);
/* Exit on end-of-payload. */
if (rc == CPIOERR_HDR_TRAILER) {
}
/* Rename/erase next item. */
- if (fsmStage(fsm, FSM_FINI))
+ if (fsmNext(fsm, FSM_FINI))
/*@loopbreak@*/ break;
}
break;
case FSM_PKGBUILD:
while (1) {
- rc = fsmStage(fsm, FSM_INIT);
+ rc = fsmUNSAFE(fsm, FSM_INIT);
/* Exit on end-of-payload. */
if (rc == CPIOERR_HDR_TRAILER) {
/* Exit on error. */
if (rc) {
fsm->postpone = 1;
- (void) fsmStage(fsm, FSM_UNDO);
+ (void) fsmNext(fsm, FSM_UNDO);
/*@loopbreak@*/ break;
}
/* Copy file into archive. */
- rc = fsmStage(fsm, FSM_PROCESS);
+ rc = fsmNext(fsm, FSM_PROCESS);
if (rc) {
- (void) fsmStage(fsm, FSM_UNDO);
+ (void) fsmNext(fsm, FSM_UNDO);
/*@loopbreak@*/ break;
}
/* Notify on success. */
- (void) fsmStage(fsm, FSM_NOTIFY);
+ (void) fsmNext(fsm, FSM_NOTIFY);
- if (fsmStage(fsm, FSM_FINI))
+ if (fsmNext(fsm, FSM_FINI))
/*@loopbreak@*/ break;
}
}
if (!rc)
- rc = fsmStage(fsm, FSM_TRAILER);
+ rc = fsmNext(fsm, FSM_TRAILER);
break;
case FSM_CREATE:
/* Detect and create directories not explicitly in package. */
if (fsm->goal == FSM_PKGINSTALL) {
- rc = fsmStage(fsm, FSM_MKDIRS);
+ rc = fsmNext(fsm, FSM_MKDIRS);
if (!rc) fsm->mkdirsdone = 1;
}
if (fsm->goal == FSM_PKGINSTALL) {
/* Read next header from payload, checking for end-of-payload. */
- rc = fsmStage(fsm, FSM_NEXT);
+ rc = fsmUNSAFE(fsm, FSM_NEXT);
}
if (rc) break;
}
/* Generate file path. */
- rc = fsmStage(fsm, FSM_MAP);
+ rc = fsmNext(fsm, FSM_MAP);
if (rc) break;
/* Perform lstat/stat for disk file. */
case FSM_PROCESS:
if (fsm->postpone) {
if (fsm->goal == FSM_PKGINSTALL)
- rc = fsmStage(fsm, FSM_EAT);
+ rc = fsmNext(fsm, FSM_EAT);
break;
}
const char * path = fsm->path;
if (fsm->osuffix)
fsm->path = fsmFsPath(fsm, st, NULL, NULL);
- rc = fsmStage(fsm, FSM_VERIFY);
+ rc = fsmUNSAFE(fsm, FSM_VERIFY);
if (rc == 0 && fsm->osuffix) {
const char * opath = fsm->opath;
fsm->opath = fsm->path;
fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix);
- rc = fsmStage(fsm, FSM_RENAME);
+ rc = fsmNext(fsm, FSM_RENAME);
if (!rc)
rpmMessage(RPMMESS_WARNING,
_("%s saved as %s\n"), fsm->opath, fsm->path);
rc = expandRegular(fsm);
} else if (S_ISDIR(st->st_mode)) {
mode_t st_mode = st->st_mode;
- rc = fsmStage(fsm, FSM_VERIFY);
+ rc = fsmUNSAFE(fsm, FSM_VERIFY);
if (rc == CPIOERR_LSTAT_FAILED) {
st->st_mode &= ~07777; /* XXX abuse st->st_mode */
st->st_mode |= 00700;
- rc = fsmStage(fsm, FSM_MKDIR);
+ rc = fsmNext(fsm, FSM_MKDIR);
st->st_mode = st_mode; /* XXX restore st->st_mode */
}
} else if (S_ISLNK(st->st_mode)) {
}
fsm->wrlen = st->st_size;
- rc = fsmStage(fsm, FSM_DREAD);
+ rc = fsmNext(fsm, FSM_DREAD);
if (!rc && fsm->rdnb != fsm->wrlen)
rc = CPIOERR_READ_FAILED;
if (rc) break;
/*@-dependenttrans@*/
fsm->opath = fsm->wrbuf;
/*@=dependenttrans@*/
- rc = fsmStage(fsm, FSM_VERIFY);
+ rc = fsmUNSAFE(fsm, FSM_VERIFY);
if (rc == CPIOERR_LSTAT_FAILED)
- rc = fsmStage(fsm, FSM_SYMLINK);
+ rc = fsmNext(fsm, FSM_SYMLINK);
fsm->opath = opath; /* XXX restore fsm->path */
} else if (S_ISFIFO(st->st_mode)) {
mode_t st_mode = st->st_mode;
/* This mimics cpio S_ISSOCK() behavior but probably isnt' right */
- rc = fsmStage(fsm, FSM_VERIFY);
+ rc = fsmUNSAFE(fsm, FSM_VERIFY);
if (rc == CPIOERR_LSTAT_FAILED) {
st->st_mode = 0000; /* XXX abuse st->st_mode */
- rc = fsmStage(fsm, FSM_MKFIFO);
+ rc = fsmNext(fsm, FSM_MKFIFO);
st->st_mode = st_mode; /* XXX restore st->st_mode */
}
} else if (S_ISCHR(st->st_mode) ||
S_ISBLK(st->st_mode) ||
/*@-unrecog@*/ S_ISSOCK(st->st_mode) /*@=unrecog@*/)
{
- rc = fsmStage(fsm, FSM_VERIFY);
+ rc = fsmUNSAFE(fsm, FSM_VERIFY);
if (rc == CPIOERR_LSTAT_FAILED)
- rc = fsmStage(fsm, FSM_MKNOD);
+ rc = fsmNext(fsm, FSM_MKNOD);
} else {
/* XXX Special case /dev/log, which shouldn't be packaged anyways */
if (!IS_DEV_LOG(fsm->path))
if (fsm->postpone)
break;
if (fsm->goal == FSM_PKGINSTALL) {
- (void) fsmStage(fsm,
+ (void) fsmNext(fsm,
(S_ISDIR(st->st_mode) ? FSM_RMDIR : FSM_UNLINK));
#ifdef NOTYET /* XXX remove only dirs just created, not all. */
if (fsm->dnlx)
- (void) fsmStage(fsm, FSM_RMDIRS);
+ (void) fsmNext(fsm, FSM_RMDIRS);
#endif
errno = saveerrno;
}
if (!fsm->postpone && fsm->commit) {
if (fsm->goal == FSM_PKGINSTALL)
rc = ((!S_ISDIR(st->st_mode) && st->st_nlink > 1)
- ? fsmCommitLinks(fsm) : fsmStage(fsm, FSM_COMMIT));
+ ? fsmCommitLinks(fsm) : fsmNext(fsm, FSM_COMMIT));
if (fsm->goal == FSM_PKGCOMMIT)
- rc = fsmStage(fsm, FSM_COMMIT);
+ rc = fsmNext(fsm, FSM_COMMIT);
if (fsm->goal == FSM_PKGERASE)
- rc = fsmStage(fsm, FSM_COMMIT);
+ rc = fsmNext(fsm, FSM_COMMIT);
}
fsm->path = _free(fsm->path);
fsm->opath = _free(fsm->opath);
const char * path = fsm->path;
fsm->opath = fsmFsPath(fsm, st, NULL, NULL);
fsm->path = fsmFsPath(fsm, st, NULL, fsm->osuffix);
- rc = fsmStage(fsm, FSM_RENAME);
+ rc = fsmNext(fsm, FSM_RENAME);
if (!rc) {
rpmMessage(RPMMESS_WARNING, _("%s saved as %s\n"),
fsm->opath, fsm->path);
if (fsm->action == FA_ERASE) {
rpmfi fi = fsmGetFi(fsm);
if (S_ISDIR(st->st_mode)) {
- rc = fsmStage(fsm, FSM_RMDIR);
+ rc = fsmNext(fsm, FSM_RMDIR);
if (!rc) break;
switch (errno) {
case ENOENT: /* XXX rmdir("/") linux 2.2.x kernel hack */
/*@innerbreak@*/ break;
}
} else {
- rc = fsmStage(fsm, FSM_UNLINK);
+ rc = fsmNext(fsm, FSM_UNLINK);
if (!rc) break;
if (!(errno == ENOENT && (fsm->fflags & RPMFILE_MISSINGOK)))
rpmError(
{
fsm->opath = fsm->path;
fsm->path = fsmFsPath(fsm, st, NULL, fsm->nsuffix);
- rc = fsmStage(fsm, FSM_RENAME);
+ rc = fsmNext(fsm, FSM_RENAME);
if (!rc && fsm->nsuffix) {
const char * opath = fsmFsPath(fsm, st, NULL, NULL);
rpmMessage(RPMMESS_WARNING, _("%s created as %s\n"),
}
if (S_ISLNK(st->st_mode)) {
if (!rc && !getuid())
- rc = fsmStage(fsm, FSM_LCHOWN);
+ rc = fsmNext(fsm, FSM_LCHOWN);
} else {
if (!rc && !getuid())
- rc = fsmStage(fsm, FSM_CHOWN);
+ rc = fsmNext(fsm, FSM_CHOWN);
if (!rc)
- rc = fsmStage(fsm, FSM_CHMOD);
+ rc = fsmNext(fsm, FSM_CHMOD);
if (!rc) {
time_t mtime = st->st_mtime;
rpmfi fi = fsmGetFi(fsm);
if (fi->fmtimes)
st->st_mtime = fi->fmtimes[fsm->ix];
- rc = fsmStage(fsm, FSM_UTIME);
+ rc = fsmNext(fsm, FSM_UTIME);
st->st_mtime = mtime;
}
}
}
/* Notify on success. */
- if (!rc) rc = fsmStage(fsm, FSM_NOTIFY);
+ if (!rc) rc = fsmNext(fsm, FSM_NOTIFY);
else if (fsm->failedFile && *fsm->failedFile == NULL) {
/*@-boundswrite@*/
*fsm->failedFile = fsm->path;
rc = CPIOERR_MISSING_HARDLINK;
if (fsm->failedFile && *fsm->failedFile == NULL) {
fsm->ix = fsm->li->filex[i];
- if (!fsmStage(fsm, FSM_MAP)) {
+ if (!fsmNext(fsm, FSM_MAP)) {
/*@-boundswrite@*/
*fsm->failedFile = fsm->path;
/*@=boundswrite@*/
*/
fsm->opath = fsm->path;
fsm->path = path;
- rc = fsmStage(fsm, FSM_RENAME);
+ rc = fsmNext(fsm, FSM_RENAME);
if (!rc)
- (void) fsmStage(fsm, FSM_UNLINK);
+ (void) fsmNext(fsm, FSM_UNLINK);
else
rc = CPIOERR_UNLINK_FAILED;
fsm->path = fsm->opath;
}
/* XXX shouldn't do this with commit/undo. */
rc = 0;
- if (fsm->stage == FSM_PROCESS) rc = fsmStage(fsm, FSM_UNLINK);
+ if (fsm->stage == FSM_PROCESS) rc = fsmNext(fsm, FSM_UNLINK);
if (rc == 0) rc = CPIOERR_LSTAT_FAILED;
return (rc ? rc : CPIOERR_LSTAT_FAILED); /* XXX HACK */
/*@notreached@*/ break;
rc = CPIOERR_HDR_TRAILER;
}
if (!rc)
- rc = fsmStage(fsm, FSM_POS);
+ rc = fsmNext(fsm, FSM_POS);
break;
case FSM_EAT:
for (left = st->st_size; left > 0; left -= fsm->rdnb) {
fsm->wrlen = (left > fsm->wrsize ? fsm->wrsize : left);
- rc = fsmStage(fsm, FSM_DREAD);
+ rc = fsmNext(fsm, FSM_DREAD);
if (rc)
/*@loopbreak@*/ break;
}
left = (modulo - (fdGetCpioPos(fsm->cfd) % modulo)) % modulo;
if (left) {
fsm->wrlen = left;
- (void) fsmStage(fsm, FSM_DREAD);
+ (void) fsmNext(fsm, FSM_DREAD);
}
break;
case FSM_PAD:
/*@=boundswrite@*/
/* XXX DWRITE uses rdnb for I/O length. */
fsm->rdnb = left;
- (void) fsmStage(fsm, FSM_DWRITE);
+ (void) fsmNext(fsm, FSM_DWRITE);
}
break;
case FSM_TRAILER:
rc = cpioTrailerWrite(fsm);
break;
case FSM_HREAD:
- rc = fsmStage(fsm, FSM_POS);
+ rc = fsmNext(fsm, FSM_POS);
if (!rc)
rc = cpioHeaderRead(fsm, st); /* Read next payload header. */
break;
case FSM_ROPEN:
fsm->rfd = Fopen(fsm->path, "r.ufdio");
if (fsm->rfd == NULL || Ferror(fsm->rfd)) {
- if (fsm->rfd != NULL) (void) fsmStage(fsm, FSM_RCLOSE);
+ if (fsm->rfd != NULL) (void) fsmNext(fsm, FSM_RCLOSE);
fsm->rfd = NULL;
rc = CPIOERR_OPEN_FAILED;
break;
case FSM_WOPEN:
fsm->wfd = Fopen(fsm->path, "w.ufdio");
if (fsm->wfd == NULL || Ferror(fsm->wfd)) {
- if (fsm->wfd != NULL) (void) fsmStage(fsm, FSM_WCLOSE);
+ if (fsm->wfd != NULL) (void) fsmNext(fsm, FSM_WCLOSE);
fsm->wfd = NULL;
rc = CPIOERR_OPEN_FAILED;
}
fileAction action; /*!< File disposition. */
fileStage goal; /*!< Package state machine goal. */
fileStage stage; /*!< External file stage. */
+ fileStage nstage; /*!< Next file stage. */
struct stat sb; /*!< Current file stat(2) info. */
struct stat osb; /*!< Original file stat(2) info. */
};
/*@modifies fsm @*/;
/*@=exportlocal@*/
+int fsmNext(FSM_t fsm, fileStage nstage)
+ /*@modifies fsm @*/;
+
/**
* File state machine driver.
* @param fsm file state machine data
/*@globals errno, fileSystem, internalState @*/
/*@modifies fsm, errno, fileSystem, internalState @*/;
+#define fsmUNSAFE fsmStage
+
#ifdef __cplusplus
}
#endif
extern int _rpmps_debug;
/*@unchecked@*/
+extern int _rpmsq_debug;
+
+/*@unchecked@*/
extern int _rpmte_debug;
/*@unchecked@*/
N_("debug rpmio I/O"), NULL},
{ "rpmpsdebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_rpmps_debug, -1,
NULL, NULL},
+ { "rpmsqdebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_rpmsq_debug, -1,
+ NULL, NULL},
{ "rpmtedebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_rpmte_debug, -1,
NULL, NULL},
{ "rpmtsdebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_rpmts_debug, -1,
if (progArgv == NULL && script == NULL)
return rc;
- psm->sq.child = 0;
- psm->sq.reaped = 0;
- psm->sq.status = 0;
psm->sq.reaper = 1;
/* XXX FIXME: except for %verifyscript, rpmteNEVR can be used. */
rpmMessage(RPMMESS_DEBUG, _("%s: %s(%s-%s-%s)\texecv(%s) pid %d\n"),
psm->stepName, sln, n, v, r,
argv[0], (unsigned)getpid());
-/*@-modfilesys@*/
-if (_psm_debug)
-fprintf(stderr, " Exec: %s \"%s\"\n", sln, argv[0]);
-/*@=modfilesys@*/
unsetenv("MALLOC_CHECK_");
xx = execv(argv[0], (char *const *)argv);
break;
return rpmpsmLink(psm, msg);
}
+static void * rpmpsmThread(void * arg)
+ /*@modifies psm @*/
+{
+ rpmpsm psm = arg;
+ return ((void *) rpmpsmStage(psm, psm->nstage));
+}
+
+static int rpmpsmNext(rpmpsm psm, pkgStage nstage)
+ /*@modifies psm @*/
+{
+ psm->nstage = nstage;
+ return rpmsqThread(rpmpsmThread, psm);
+}
+
/**
* @todo Packages w/o files never get a callback, hence don't get displayed
* on install with -v.
psm->scriptArg = psm->npkgs_installed - 1;
/* Retrieve installed header. */
- rc = rpmpsmStage(psm, PSM_RPMDB_LOAD);
+ rc = rpmpsmNext(psm, PSM_RPMDB_LOAD);
if (rc == RPMRC_OK)
if (psm->te)
psm->te->h = headerLink(fi->h);
#endif
/* Change root directory if requested and not already done. */
- rc = rpmpsmStage(psm, PSM_CHROOT_IN);
+ rc = rpmpsmNext(psm, PSM_CHROOT_IN);
if (psm->goal == PSM_PKGINSTALL) {
psm->scriptTag = RPMTAG_PREIN;
}
if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPRE)) {
- rc = rpmpsmStage(psm, PSM_SCRIPT);
+ rc = rpmpsmNext(psm, PSM_SCRIPT);
if (rc != RPMRC_OK) {
rpmError(RPMERR_SCRIPT,
_("%s: %s scriptlet failed (%d), skipping %s\n"),
if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERUN)) {
/* Run triggers in this package other package(s) set off. */
- rc = rpmpsmStage(psm, PSM_IMMED_TRIGGERS);
+ rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
if (rc) break;
/* Run triggers in other package(s) this package sets off. */
- rc = rpmpsmStage(psm, PSM_TRIGGERS);
+ rc = rpmpsmNext(psm, PSM_TRIGGERS);
if (rc) break;
}
if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPREUN))
- rc = rpmpsmStage(psm, PSM_SCRIPT);
+ rc = rpmpsmNext(psm, PSM_SCRIPT);
}
if (psm->goal == PSM_PKGSAVE) {
int noArchiveSize = 0;
/* Retrieve type of payload compression. */
/*@-nullstate@*/ /* FIX: psm->oh may be NULL */
- rc = rpmpsmStage(psm, PSM_RPMIO_FLAGS);
+ rc = rpmpsmNext(psm, PSM_RPMIO_FLAGS);
/*@=nullstate@*/
/* Write the lead section into the package. */
}
/* Retrieve type of payload compression. */
- rc = rpmpsmStage(psm, PSM_RPMIO_FLAGS);
+ rc = rpmpsmNext(psm, PSM_RPMIO_FLAGS);
if (rpmteFd(fi->te) == NULL) { /* XXX can't happen */
rc = RPMRC_FAIL;
/*@=mods@*/
if (!rc)
- rc = rpmpsmStage(psm, PSM_COMMIT);
+ rc = rpmpsmNext(psm, PSM_COMMIT);
/* XXX make sure progress is closed out */
psm->what = RPMCALLBACK_INST_PROGRESS;
psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
psm->total = psm->amount;
- xx = rpmpsmStage(psm, PSM_NOTIFY);
+ xx = rpmpsmNext(psm, PSM_NOTIFY);
if (rc) {
rpmError(RPMERR_CPIO,
psm->what = RPMCALLBACK_UNPACK_ERROR;
psm->amount = 0;
psm->total = 0;
- xx = rpmpsmStage(psm, PSM_NOTIFY);
+ xx = rpmpsmNext(psm, PSM_NOTIFY);
break;
}
psm->what = RPMCALLBACK_UNINST_START;
psm->amount = fc; /* XXX W2DO? looks wrong. */
psm->total = fc;
- xx = rpmpsmStage(psm, PSM_NOTIFY);
+ xx = rpmpsmNext(psm, PSM_NOTIFY);
rc = fsmSetup(fi->fsm, FSM_PKGERASE, ts, fi,
NULL, NULL, &psm->failedFile);
psm->what = RPMCALLBACK_UNINST_STOP;
psm->amount = 0; /* XXX W2DO? looks wrong. */
psm->total = fc;
- xx = rpmpsmStage(psm, PSM_NOTIFY);
+ xx = rpmpsmNext(psm, PSM_NOTIFY);
}
if (psm->goal == PSM_PKGSAVE) {
psm->what = RPMCALLBACK_INST_PROGRESS;
psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
psm->total = psm->amount;
- xx = rpmpsmStage(psm, PSM_NOTIFY);
+ xx = rpmpsmNext(psm, PSM_NOTIFY);
fi->action = action;
fi->actions = actions;
* the database before adding the new one.
*/
if (fi->record && !(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY)) {
- rc = rpmpsmStage(psm, PSM_RPMDB_REMOVE);
+ rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
if (rc) break;
}
- rc = rpmpsmStage(psm, PSM_RPMDB_ADD);
+ rc = rpmpsmNext(psm, PSM_RPMDB_ADD);
if (rc) break;
psm->scriptTag = RPMTAG_POSTIN;
psm->countCorrection = 0;
if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOST)) {
- rc = rpmpsmStage(psm, PSM_SCRIPT);
+ rc = rpmpsmNext(psm, PSM_SCRIPT);
if (rc) break;
}
if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERIN)) {
/* Run triggers in other package(s) this package sets off. */
- rc = rpmpsmStage(psm, PSM_TRIGGERS);
+ rc = rpmpsmNext(psm, PSM_TRIGGERS);
if (rc) break;
/* Run triggers in this package other package(s) set off. */
- rc = rpmpsmStage(psm, PSM_IMMED_TRIGGERS);
+ rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
if (rc) break;
}
psm->countCorrection = -1;
if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOSTUN)) {
- rc = rpmpsmStage(psm, PSM_SCRIPT);
+ rc = rpmpsmNext(psm, PSM_SCRIPT);
/* XXX WTFO? postun failures don't cause erasure failure. */
}
if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPOSTUN)) {
/* Run triggers in other package(s) this package sets off. */
- rc = rpmpsmStage(psm, PSM_TRIGGERS);
+ rc = rpmpsmNext(psm, PSM_TRIGGERS);
if (rc) break;
}
if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY))
- rc = rpmpsmStage(psm, PSM_RPMDB_REMOVE);
+ rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
}
if (psm->goal == PSM_PKGSAVE) {
}
/* Restore root directory if changed. */
- xx = rpmpsmStage(psm, PSM_CHROOT_OUT);
+ xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
break;
case PSM_UNDO:
break;
case PSM_FINI:
/* Restore root directory if changed. */
- xx = rpmpsmStage(psm, PSM_CHROOT_OUT);
+ xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
if (psm->fd != NULL) {
saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
psm->amount = 0;
psm->total = 0;
/*@-nullstate@*/ /* FIX: psm->fd may be NULL. */
- xx = rpmpsmStage(psm, PSM_NOTIFY);
+ xx = rpmpsmNext(psm, PSM_NOTIFY);
/*@=nullstate@*/
}
psm->rc = RPMRC_OK;
psm->stepName = pkgStageString(stage);
- rc = rpmpsmStage(psm, PSM_INIT);
- if (!rc) rc = rpmpsmStage(psm, PSM_PRE);
- if (!rc) rc = rpmpsmStage(psm, PSM_PROCESS);
- if (!rc) rc = rpmpsmStage(psm, PSM_POST);
- xx = rpmpsmStage(psm, PSM_FINI);
+ rc = rpmpsmNext(psm, PSM_INIT);
+ if (!rc) rc = rpmpsmNext(psm, PSM_PRE);
+ if (!rc) rc = rpmpsmNext(psm, PSM_PROCESS);
+ if (!rc) rc = rpmpsmNext(psm, PSM_POST);
+ xx = rpmpsmNext(psm, PSM_FINI);
break;
case PSM_PKGCOMMIT:
break;
rpmRC rc;
pkgStage goal;
/*@unused@*/
- pkgStage stage;
+ pkgStage stage; /*!< Current psm stage. */
+ pkgStage nstage; /*!< Next psm stage. */
/*@refs@*/
int nrefs; /*!< Reference count. */
int rpmsqInsert(void * elem, void * prev)
{
- sigset_t newMask, oldMask;
rpmsq sq = (rpmsq) elem;
int ret = -1;
fprintf(stderr, " Insert(%p): %p\n", ME(), sq);
/*@=modfilesys@*/
#endif
- ret = sigemptyset (&newMask);
- ret = sigaddset (&newMask, SIGCHLD);
- ret = sigprocmask(SIG_BLOCK, &newMask, &oldMask);
+ ret = sighold(SIGCHLD);
if (ret == 0) {
sq->child = 0;
sq->reaped = 0;
sq->status = 0;
+ sq->reaper = 1;
+ sq->pipes[0] = sq->pipes[1] = -1;
sq->id = ME();
- (void) pthread_mutex_init(&sq->mutex, NULL);
- (void) pthread_cond_init(&sq->cond, NULL);
+ ret = pthread_mutex_init(&sq->mutex, NULL);
+ ret = pthread_cond_init(&sq->cond, NULL);
insque(elem, (prev ? prev : rpmsqQueue));
- ret = sigprocmask(SIG_SETMASK, &oldMask, NULL);
+ ret = sigrelse(SIGCHLD);
}
}
- return 0;
+ return ret;
}
int rpmsqRemove(void * elem)
{
- sigset_t newMask, oldMask;
rpmsq sq = (rpmsq) elem;
int ret = -1;
fprintf(stderr, " Remove(%p): %p\n", ME(), sq);
/*@=modfilesys@*/
#endif
- ret = sigemptyset (&newMask);
- ret = sigaddset (&newMask, SIGCHLD);
- ret = sigprocmask(SIG_BLOCK, &newMask, &oldMask);
+ ret = sighold (SIGCHLD);
if (ret == 0) {
remque(elem);
- (void) pthread_cond_destroy(&sq->cond);
- (void) pthread_mutex_destroy(&sq->mutex);
+ ret = pthread_cond_destroy(&sq->cond);
+ ret = pthread_mutex_destroy(&sq->mutex);
sq->id = NULL;
- sq->child = 0;
- sq->reaped = 0;
+ if (sq->pipes[1]) close(sq->pipes[1]);
+ if (sq->pipes[0]) close(sq->pipes[0]);
+ sq->pipes[0] = sq->pipes[1] = -1;
+ sq->reaper = 1;
sq->status = 0;
- ret = sigprocmask(SIG_SETMASK, &oldMask, NULL);
+ sq->reaped = 0;
+ sq->child = 0;
+ ret = sigrelse(SIGCHLD);
}
}
return ret;
/*@-fullinitblock@*/
static struct rpmsig_s {
int signum;
- void (*handler) (int signum);
+ void (*handler) (int signum, siginfo_t * info, void * context);
int active;
struct sigaction oact;
} rpmsigTbl[] = {
- { SIGINT, rpmsqHandler },
+ { SIGINT, rpmsqAction },
#define rpmsigTbl_sigint (&rpmsigTbl[0])
- { SIGQUIT, rpmsqHandler },
+ { SIGQUIT, rpmsqAction },
#define rpmsigTbl_sigquit (&rpmsigTbl[1])
- { SIGCHLD, rpmsqHandler },
+ { SIGCHLD, rpmsqAction },
#define rpmsigTbl_sigchld (&rpmsigTbl[2])
- { SIGHUP, rpmsqHandler },
+ { SIGHUP, rpmsqAction },
#define rpmsigTbl_sighup (&rpmsigTbl[3])
- { SIGTERM, rpmsqHandler },
+ { SIGTERM, rpmsqAction },
#define rpmsigTbl_sigterm (&rpmsigTbl[4])
- { SIGPIPE, rpmsqHandler },
+ { SIGPIPE, rpmsqAction },
#define rpmsigTbl_sigpipe (&rpmsigTbl[5])
{ -1, NULL },
};
/*@=fullinitblock@*/
/*@-incondefs@*/
-void rpmsqHandler(int signum)
+void rpmsqAction(int signum, siginfo_t * info, void * context)
{
int save = errno;
rpmsig tbl;
sq != NULL && sq != rpmsqQueue;
sq = sq->q_forw)
{
- int same_thread;
if (sq->child != reaped)
/*@innercontinue@*/ continue;
- same_thread = SAME_THREAD(ME(), rpmsqQueue->id);
-#ifdef _RPMSQ_DEBUG_XXX
-/*@-modfilesys@*/
-if (_rpmsq_debug)
-fprintf(stderr, " Reap(%p): %p child %d id %p same %d\n", ME(), sq, sq->child, sq->id, same_thread);
-/*@=modfilesys@*/
-#endif
sq->reaped = reaped;
sq->status = status;
-
-#ifdef HACK
- if (!SAME_THREAD(ME(), sq->id))
-#endif
- {
-
-#ifdef _RPMSQ_DEBUG_XXX
-/*@-modfilesys@*/
-if (_rpmsq_debug)
-fprintf(stderr, " Signal(%p): %p child %d id %p\n", ME(), sq, sq->child, sq->id);
-/*@=modfilesys@*/
-#endif
- (void) pthread_cond_signal(&sq->cond);
- }
-
+ (void) pthread_cond_signal(&sq->cond);
/*@innerbreak@*/ break;
}
}
}
/*@=incondefs@*/
-int rpmsqEnable(int signum, /*@null@*/ sighandler_t handler)
+int rpmsqEnable(int signum, /*@null@*/ rpmsqAction_t handler)
{
int tblsignum = (signum >= 0 ? signum : -signum);
struct sigaction sa;
if (signum >= 0) { /* Enable. */
if (ADD_REF(tbl) <= 0) {
- tbl->active = 1; /* XXX just in case */
(void) sigdelset(&rpmsqCaught, tbl->signum);
- sa.sa_flags = 0;
sigemptyset (&sa.sa_mask);
- sa.sa_handler = (handler != NULL ? handler : tbl->handler);
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = (handler != NULL ? handler : tbl->handler);
if (sigaction(tbl->signum, &sa, &tbl->oact) < 0) {
SUB_REF(tbl);
break;
}
+ tbl->active = 1; /* XXX just in case */
+ if (handler != NULL)
+ tbl->handler = handler;
}
} else { /* Disable. */
if (SUB_REF(tbl) <= 0) {
- tbl->active = 0; /* XXX just in case */
if (sigaction(tbl->signum, &tbl->oact, NULL) < 0)
break;
+ tbl->active = 0; /* XXX just in case */
+ tbl->handler = (handler != NULL ? handler : rpmsqAction);
}
}
ret = tbl->active;
pid_t rpmsqFork(rpmsq sq)
{
- sigset_t newMask, oldMask;
pid_t pid;
- int pipes[2];
int xx;
if (sq->reaper) {
xx = rpmsqEnable(SIGCHLD, NULL);
}
- xx = pipe(pipes);
+ xx = pipe(sq->pipes);
- xx = sigemptyset (&newMask);
- xx = sigaddset (&newMask, SIGCHLD);
- xx = sigprocmask (SIG_BLOCK, &newMask, &oldMask);
+ xx = sighold(SIGCHLD);
pid = fork();
if (pid < (pid_t) 0) { /* fork failed. */
- close(pipes[0]);
- close(pipes[1]);
+ xx = close(sq->pipes[0]);
+ xx = close(sq->pipes[1]);
+ sq->pipes[0] = sq->pipes[1] = -1;
goto out;
} else if (pid == (pid_t) 0) { /* Child. */
int yy;
/* Block to permit parent to wait. */
- close(pipes[1]);
- xx = read(pipes[0], &yy, sizeof(yy));
- close(pipes[0]);
+ xx = close(sq->pipes[1]);
+ xx = read(sq->pipes[0], &yy, sizeof(yy));
+ xx = close(sq->pipes[0]);
+ sq->pipes[0] = sq->pipes[1] = -1;
#ifdef _RPMSQ_DEBUG
/*@-modfilesys@*/
#endif
/* Unblock child. */
- close(pipes[0]);
- close(pipes[1]);
+ xx = close(sq->pipes[0]);
+ xx = close(sq->pipes[1]);
+ sq->pipes[0] = sq->pipes[1] = -1;
}
out:
- xx = sigprocmask (SIG_SETMASK, &oldMask, NULL);
+ xx = sigrelse(SIGCHLD);
return sq->child;
}
/*@globals fileSystem, internalState @*/
/*@modifies fileSystem, internalState @*/
{
- sigset_t newMask, oldMask;
-#ifdef HACK
- int same_thread = SAME_THREAD(ME(), rpmsqQueue->id);
-#else
int same_thread = 0;
-#endif
int ret = 0;
int xx;
- if (same_thread) {
- ret = sigemptyset (&newMask);
- ret = sigaddset (&newMask, SIGCHLD);
- ret = sigprocmask(SIG_BLOCK, &newMask, &oldMask);
- } else {
- }
+ if (same_thread) ret = sighold(SIGCHLD);
/*@-infloops@*/
while (ret == 0 && sq->reaped != sq->child) {
if (same_thread) {
- ret = sigsuspend(&oldMask);
+ ret = sigpause(SIGCHLD);
} else {
ret = pthread_mutex_lock(&sq->mutex);
ret = pthread_cond_wait(&sq->cond, &sq->mutex);
}
/*@=infloops@*/
- if (same_thread) {
- xx = sigprocmask(SIG_SETMASK, &oldMask, NULL);
- } else {
- }
+ if (same_thread) xx = sigrelse(SIGCHLD);
#ifdef _RPMSQ_DEBUG
/*@-modfilesys@*/
pid_t rpmsqWait(rpmsq sq)
{
- int same_thread = SAME_THREAD(ME(), rpmsqQueue->id);
#ifdef _RPMSQ_DEBUG
/*@-modfilesys@*/
if (_rpmsq_debug)
-fprintf(stderr, " Wait(%p): %p child %d reaper %d same %d\n", ME(), sq, sq->child, sq->reaper, same_thread);
+fprintf(stderr, " Wait(%p): %p child %d reaper %d\n", ME(), sq, sq->child, sq->reaper);
/*@=modfilesys@*/
#endif
return sq->reaped;
}
+int rpmsqThread(void * (*start) (void * arg), void * arg)
+{
+ pthread_t pth;
+ int ret;
+
+ ret = pthread_create(&pth, NULL, start, arg);
+ if (ret == 0) {
+fprintf(stderr, " Thread(%p): %p\n", ME(), pth);
+ ret = pthread_join(pth, NULL);
+ }
+ return ret;
+}
+
/**
* SIGCHLD cancellation handler.
*/
typedef struct rpmsqElem * rpmsq;
+typedef void (*rpmsqAction_t) (int signum, siginfo_t *info, void *context)
+ /*@*/;
+
/*@-redecl@*/
/*@unchecked@*/
extern int _rpmsq_debug;
volatile pid_t reaped; /*!< Reaped waitpid(3) return. */
volatile int status; /*!< Reaped waitpid(3) status. */
int reaper; /*!< Register SIGCHLD handler? */
+ int pipes[2];
void * id; /*!< Blocking thread id (pthread_t). */
pthread_mutex_t mutex;
pthread_cond_t cond;
/**
*/
-void rpmsqHandler(int signum)
+void rpmsqAction(int signum, siginfo_t * info, void * context)
/*@globals rpmsqCaught, fileSystem @*/
/*@modifies rpmsqCaught, fileSystem @*/;
/**
* Enable or disable a signal handler.
* @param signum signal to enable (or disable if negative)
- * @param handler signal handler (or NULL to use rpmsqHandler())
+ * @param handler sa_sigaction handler (or NULL to use rpmsqHandler())
* @return no. of refs, -1 on error
*/
-int rpmsqEnable(int signum, /*@null@*/ sighandler_t handler)
+int rpmsqEnable(int signum, /*@null@*/ rpmsqAction_t handler)
/*@globals rpmsqCaught, fileSystem, internalState @*/
/*@modifies rpmsqCaught, fileSystem, internalState @*/;
/*@modifies sq, fileSystem, internalState @*/;
/**
+ * Call a function in a thread synchronously.
+ * @param start function
+ * @param arg function argument
+ * @return 0 on success
+ */
+int rpmsqThread(void * (*start) (void * arg), void * arg)
+ /*@globals fileSystem, internalState @*/
+ /*@modifies fileSystem, internalState @*/;
+
+/**
* Execute a command, returning its status.
*/
int rpmsqExecve (const char ** argv)