示例#1
0
/**
 * Print package size (debug purposes only)
 * @param fd			package file handle
 * @param sigh			signature header
 */
static void printSize(FD_t fd, Header sigh)
{
    struct stat st;
    int fdno = Fileno(fd);
    size_t siglen = headerSizeof(sigh, HEADER_MAGIC_YES);
    size_t pad = (8 - (siglen % 8)) % 8; /* 8-byte pad */
    struct rpmtd_s sizetag;
    rpm_loff_t datalen = 0;

    /* Print package component sizes. */
    if (headerGet(sigh, RPMSIGTAG_LONGSIZE, &sizetag, HEADERGET_DEFAULT)) {
	rpm_loff_t *tsize = rpmtdGetUint64(&sizetag);
	datalen = (tsize) ? *tsize : 0;
    } else if (headerGet(sigh, RPMSIGTAG_SIZE, &sizetag, HEADERGET_DEFAULT)) {
	rpm_off_t *tsize = rpmtdGetUint32(&sizetag);
	datalen = (tsize) ? *tsize : 0;
    }
    rpmtdFreeData(&sizetag);

    rpmlog(RPMLOG_DEBUG,
		"Expected size: %12" PRIu64 \
		" = lead(%d)+sigs(%zd)+pad(%zd)+data(%" PRIu64 ")\n",
		RPMLEAD_SIZE+siglen+pad+datalen,
		RPMLEAD_SIZE, siglen, pad, datalen);

    if (fstat(fdno, &st) == 0) {
	rpmlog(RPMLOG_DEBUG,
		"  Actual size: %12" PRIu64 "\n", (rpm_loff_t) st.st_size);
    }
}
示例#2
0
文件: pack.c 项目: ereshetova/rpm
/**
 * @todo Create transaction set *much* earlier.
 */
static rpmRC cpio_doio(FD_t fdo, Header h, CSA_t csa, const char * fmodeMacro)
{
    char *failedFile = NULL;
    FD_t cfd;
    int fsmrc;

    (void) Fflush(fdo);
    cfd = Fdopen(fdDup(Fileno(fdo)), fmodeMacro);
    if (cfd == NULL)
	return RPMRC_FAIL;

    fsmrc = rpmPackageFilesArchive(csa->cpioList, headerIsSource(h), cfd,
		      &csa->cpioArchiveSize, &failedFile);

    if (fsmrc) {
	if (failedFile)
	    rpmlog(RPMLOG_ERR, _("create archive failed on file %s\n"), failedFile);
	else
	    rpmlog(RPMLOG_ERR, _("create archive failed\n"));
    }

    free(failedFile);
    Fclose(cfd);

    return (fsmrc == 0) ? RPMRC_OK : RPMRC_FAIL;
}
示例#3
0
文件: pack.c 项目: nforro/rpm
/**
 * @todo Create transaction set *much* earlier.
 */
static rpmRC cpio_doio(FD_t fdo, Package pkg, const char * fmodeMacro,
			rpm_loff_t *archiveSize)
{
    char *failedFile = NULL;
    FD_t cfd;
    int fsmrc;

    (void) Fflush(fdo);
    cfd = Fdopen(fdDup(Fileno(fdo)), fmodeMacro);
    if (cfd == NULL)
	return RPMRC_FAIL;

    fsmrc = rpmPackageFilesArchive(pkg->cpioList, headerIsSource(pkg->header),
				   cfd, pkg->dpaths,
				   archiveSize, &failedFile);

    if (fsmrc) {
	char *emsg = rpmfileStrerror(fsmrc);
	if (failedFile)
	    rpmlog(RPMLOG_ERR, _("create archive failed on file %s: %s\n"),
		   failedFile, emsg);
	else
	    rpmlog(RPMLOG_ERR, _("create archive failed: %s\n"), emsg);
	free(emsg);
    }

    free(failedFile);
    Fclose(cfd);

    return (fsmrc == 0) ? RPMRC_OK : RPMRC_FAIL;
}
示例#4
0
文件: pack.c 项目: kaltsi/rpm
/**
 * @todo Create transaction set *much* earlier.
 */
static rpmRC cpio_doio(FD_t fdo, Header h, CSA_t csa,
		const char * fmodeMacro)
{
    rpmts ts = rpmtsCreate();
    rpmfi fi = csa->cpioList;
    rpmte te = NULL;
    rpmfs fs = NULL;
    char *failedFile = NULL;
    FD_t cfd;
    rpmRC rc = RPMRC_OK;
    int xx, i;

    {	char *fmode = rpmExpand(fmodeMacro, NULL);
	if (!(fmode && fmode[0] == 'w'))
	    fmode = xstrdup("w9.gzdio");
	(void) Fflush(fdo);
	cfd = Fdopen(fdDup(Fileno(fdo)), fmode);
	fmode = _free(fmode);
    }
    if (cfd == NULL)
	return RPMRC_FAIL;

    /* make up a transaction element for passing to fsm */
    rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
    te = rpmtsElement(ts, 0);
    fs = rpmteGetFileStates(te);

    fi = rpmfiInit(fi, 0);
    while ((i = rpmfiNext(fi)) >= 0) {
	if (rpmfiFFlags(fi) & RPMFILE_GHOST)
	    rpmfsSetAction(fs, i, FA_SKIP);
	else
	    rpmfsSetAction(fs, i, FA_COPYOUT);
    }

    xx = fsmSetup(rpmfiFSM(fi), FSM_PKGBUILD, ts, te, fi, cfd,
		&csa->cpioArchiveSize, &failedFile);
    if (xx)
	rc = RPMRC_FAIL;
    (void) Fclose(cfd);
    xx = fsmTeardown(rpmfiFSM(fi));
    if (rc == RPMRC_OK && xx) rc = RPMRC_FAIL;

    if (rc) {
	if (failedFile)
	    rpmlog(RPMLOG_ERR, _("create archive failed on file %s: %s\n"),
		failedFile, cpioStrerror(rc));
	else
	    rpmlog(RPMLOG_ERR, _("create archive failed: %s\n"),
		cpioStrerror(rc));
      rc = RPMRC_FAIL;
    }
    rpmtsEmpty(ts);

    failedFile = _free(failedFile);
    ts = rpmtsFree(ts);

    return rc;
}
示例#5
0
文件: rpmts-py.c 项目: kaltsi/rpm
static void *
rpmtsCallback(const void * hd, const rpmCallbackType what,
		         const rpm_loff_t amount, const rpm_loff_t total,
	                 const void * pkgKey, rpmCallbackData data)
{
    Header h = (Header) hd;
    struct rpmtsCallbackType_s * cbInfo = data;
    PyObject * pkgObj = (PyObject *) pkgKey;
    PyObject * args, * result;
    static FD_t fd;

    if (cbInfo->cb == Py_None) return NULL;

    /* Synthesize a python object for callback (if necessary). */
    if (pkgObj == NULL) {
	if (h) {
	    pkgObj = Py_BuildValue("s", headerGetString(h, RPMTAG_NAME));
	} else {
	    pkgObj = Py_None;
	    Py_INCREF(pkgObj);
	}
    } else
	Py_INCREF(pkgObj);

    PyEval_RestoreThread(cbInfo->_save);

    args = Py_BuildValue("(iLLOO)", what, amount, total, pkgObj, cbInfo->data);
    result = PyEval_CallObject(cbInfo->cb, args);
    Py_DECREF(args);
    Py_DECREF(pkgObj);

    if (!result) {
	die(cbInfo->cb);
    }

    if (what == RPMCALLBACK_INST_OPEN_FILE) {
	int fdno;

        if (!PyArg_Parse(result, "i", &fdno)) {
	    die(cbInfo->cb);
	}
	Py_DECREF(result);
	cbInfo->_save = PyEval_SaveThread();

	fd = fdDup(fdno);
	fcntl(Fileno(fd), F_SETFD, FD_CLOEXEC);

	return fd;
    } else
    if (what == RPMCALLBACK_INST_CLOSE_FILE) {
	Fclose (fd);
    }

    Py_DECREF(result);
    cbInfo->_save = PyEval_SaveThread();

    return NULL;
}
示例#6
0
文件: rpmio.c 项目: maxamillion/rpm
off_t fdSize(FD_t fd)
{
    struct stat sb;
    off_t rc = -1; 

    if (fd != NULL && fstat(Fileno(fd), &sb) == 0)
	rc = sb.st_size;
    return rc;
}
示例#7
0
文件: rpmfd-py.c 项目: Distrotech/rpm
static int rpmfd_init(rpmfdObject *s, PyObject *args, PyObject *kwds)
{
    char *kwlist[] = { "obj", "mode", "flags", NULL };
    const char *mode = "r";
    const char *flags = "ufdio";
    char *rpmio_mode = NULL;
    PyObject *fo = NULL;
    FD_t fd = NULL;
    int fdno;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ss", kwlist, 
				     &fo, &mode, &flags))
	return -1;

    rpmio_mode = rstrscat(NULL, mode, ".", flags, NULL);

    if (PyBytes_Check(fo)) {
	fd = openPath(PyBytes_AsString(fo), rpmio_mode);
    } else if (PyUnicode_Check(fo)) {
	PyObject *enc = NULL;
	int rc;
#if PY_MAJOR_VERSION >= 3
	rc = PyUnicode_FSConverter(fo, &enc);
#else
	rc = utf8FromPyObject(fo, &enc);
#endif
	if (rc) {
	    fd = openPath(PyBytes_AsString(enc), rpmio_mode);
	    Py_DECREF(enc);
	}
    } else if (rpmfdObject_Check(fo)) {
	rpmfdObject *fdo = (rpmfdObject *)fo;
	fd = openFd(fdDup(Fileno(fdo->fd)), rpmio_mode);
    } else if ((fdno = PyObject_AsFileDescriptor(fo)) >= 0) {
	fd = openFd(fdDup(fdno), rpmio_mode);
    } else {
	PyErr_SetString(PyExc_TypeError, "path or file object expected");
    }

    if (fd != NULL) {
	Fclose(s->fd); /* in case __init__ was called again */
	free(s->mode);
	free(s->flags);
	s->fd = fd;
	s->mode = rstrdup(mode);
	s->flags = rstrdup(flags);
    } else {
	PyErr_SetString(PyExc_IOError, Fstrerror(fd));
    }

    free(rpmio_mode);
    return (fd == NULL) ? -1 : 0;
}
示例#8
0
文件: rpmfd-py.c 项目: Distrotech/rpm
static PyObject *rpmfd_isatty(rpmfdObject *s)
{
    int fileno;
    if (s->fd == NULL) return err_closed();

    Py_BEGIN_ALLOW_THREADS
    fileno = Fileno(s->fd);
    Py_END_ALLOW_THREADS

    if (Ferror(s->fd)) {
	PyErr_SetString(PyExc_IOError, Fstrerror(s->fd));
	return NULL;
    }
    return PyBool_FromLong(isatty(fileno));
}
示例#9
0
文件: rpmfd-py.c 项目: Distrotech/rpm
static PyObject *rpmfd_fileno(rpmfdObject *s)
{
    int fno;
    if (s->fd == NULL) return err_closed();

    Py_BEGIN_ALLOW_THREADS
    fno = Fileno(s->fd);
    Py_END_ALLOW_THREADS

    if (Ferror(s->fd)) {
	PyErr_SetString(PyExc_IOError, Fstrerror(s->fd));
	return NULL;
    }
    return Py_BuildValue("i", fno);
}
示例#10
0
/**
 * Print package size.
 * @todo rpmio: use fdSize rather than fstat(2) to get file size.
 * @param fd			package file handle
 * @param siglen		signature header size
 * @param pad			signature padding
 * @param datalen		length of header+payload
 * @return 			rpmRC return code
 */
static inline rpmRC printSize(FD_t fd, size_t siglen, size_t pad, rpm_loff_t datalen)
{
    struct stat st;
    int fdno = Fileno(fd);

    if (fstat(fdno, &st) < 0)
	return RPMRC_FAIL;

    rpmlog(RPMLOG_DEBUG,
		"Expected size: %12" PRIu64 \
		" = lead(%d)+sigs(%zd)+pad(%zd)+data(%" PRIu64 ")\n",
		RPMLEAD_SIZE+siglen+pad+datalen,
		RPMLEAD_SIZE, siglen, pad, datalen);
    rpmlog(RPMLOG_DEBUG,
		"  Actual size: %12" PRIu64 "\n", (rpm_loff_t) st.st_size);

    return RPMRC_OK;
}
示例#11
0
文件: rpmio.c 项目: akozumpl/rpm
static FD_t ufdOpen(const char * url, int flags, mode_t mode)
{
    FD_t fd = NULL;
    const char * path;
    urltype urlType = urlPath(url, &path);

if (_rpmio_debug)
fprintf(stderr, "*** ufdOpen(%s,0x%x,0%o)\n", url, (unsigned)flags, (unsigned)mode);

    switch (urlType) {
    case URL_IS_FTP:
    case URL_IS_HTTPS:
    case URL_IS_HTTP:
    case URL_IS_HKP:
	fd = urlOpen(url, flags, mode);
	/* we're dealing with local file when urlOpen() returns */
	urlType = URL_IS_UNKNOWN;
	break;
    case URL_IS_DASH:
	if ((flags & O_ACCMODE) == O_RDWR) {
	    fd = NULL;
	} else {
	    fd = fdDup((flags & O_ACCMODE) == O_WRONLY ?
			STDOUT_FILENO : STDIN_FILENO);
	}
	break;
    case URL_IS_PATH:
    case URL_IS_UNKNOWN:
    default:
	fd = fdOpen(path, flags, mode);
	break;
    }

    if (fd == NULL) return NULL;

    fdSetIo(fd, ufdio);
    fd->urlType = urlType;

    if (Fileno(fd) < 0) {
	(void) fdClose(fd);
	return NULL;
    }
    return fd;
}
示例#12
0
rpmRC rpmwfInit(rpmwf wf, const char * fn, const char * fmode)
{
if (_rpmwf_debug)
fprintf(stderr, "==> rpmwfInit(%p, %s, %s)\n", wf, fn, fmode);
    if (fn == NULL)
	fn = wf->fn;
assert(fn != NULL);

/*@-globs@*/
    wf->fd = Fopen(fn, fmode);
/*@=globs@*/
    if (wf->fd == NULL || Ferror(wf->fd)) {
	(void) rpmwfFini(wf);
	return RPMRC_NOTFOUND;
    }

    if (fmode && *fmode == 'r') {
	wf->b = mmap(NULL, wf->nb, PROT_READ, MAP_SHARED, Fileno(wf->fd), 0L);

	if (wf->b == (void *)-1) {
	    wf->b = NULL;
	    (void) rpmwfFini(wf);
	    return RPMRC_NOTFOUND;
	}

	wf->l = (char *) wf->b;
assert(wf->l != NULL);
	wf->nl = 96;

	wf->s = wf->l + wf->nl;
	wf->ns = hSize((rpmuint32_t *)wf->s);
	wf->ns += ((8 - (wf->ns % 8)) % 8);	/* padding */

	wf->h = wf->s + wf->ns;
	wf->nh = hSize((rpmuint32_t *)wf->h);

	wf->p = wf->h + wf->nh;
	wf->np = wf->nb;
	wf->np -= wf->nl + wf->ns + wf->nh;
    }

    return RPMRC_OK;
}
示例#13
0
文件: fsm.c 项目: nforro/rpm
static void wfd_close(FD_t *wfdp)
{
    if (wfdp && *wfdp) {
	int myerrno = errno;
	static int oneshot = 0;
	static int flush_io = 0;
	if (!oneshot) {
	    flush_io = rpmExpandNumeric("%{?_flush_io}");
	    oneshot = 1;
	}
	if (flush_io) {
	    int fdno = Fileno(*wfdp);
	    fsync(fdno);
	}
	Fclose(*wfdp);
	*wfdp = NULL;
	errno = myerrno;
    }
}
示例#14
0
static FILE *
open_logfile(const char *fn){
	FILE *ret;

	if( (ret = fopen(fn,"wb")) ){
		int fd;

		setlinebuf(ret);
		if((fd = Fileno(ret)) < 0){
			fclose(ret);
			ret = NULL;
		}else if(set_fd_close_on_exec(fd)){
			fclose(ret);
			ret = NULL;
		}
		// We don't necessarily want the performance hit from
		// unbuffered logging...maybe make it an option somehow? FIXME
		/*else if(set_fd_nonblocking(fd)){
			fclose(ret);
			ret = NULL;
		}*/
	}
	return ret;
}
示例#15
0
文件: rpmio.c 项目: akozumpl/rpm
/* XXX this is naive */
int Fcntl(FD_t fd, int op, void *lip)
{
    return fcntl(Fileno(fd), op, lip);
}
示例#16
0
int rpmiobSlurp(const char * fn, rpmiob * iobp)
{
    static size_t blenmax = (128 * BUFSIZ);	/* XXX 1Mb with glibc */
    rpmuint8_t * b = NULL;
    size_t blen = 0;
    struct stat sb;
    FD_t fd;
    int rc = 0;
    int xx;

    fd = Fopen(fn, "r.ufdio");
    if (fd == NULL || Ferror(fd)) {
        rc = 2;
        goto exit;
    }
    sb.st_size = 0;
    if ((xx = Fstat(fd, &sb)) < 0 || sb.st_size == 0)
        sb.st_size = blenmax;
#if defined(__linux__)
    /* XXX st->st_size = 0 for /proc files on linux, see stat(2). */
    /* XXX glibc mmap'd libio no workie for /proc files on linux?!? */
    if (sb.st_size == 0 && !strncmp(fn, "/proc/", sizeof("/proc/")-1)) {
        blen = blenmax;
        b = xmalloc(blen+1);
        b[0] = (rpmuint8_t) '\0';

        xx = read(Fileno(fd), b, blen);
        blen = (size_t) (xx >= 0 ? xx : 0);
    } else
#endif
    {
        blen = sb.st_size;
        b = xmalloc(blen+1);
        b[0] = (rpmuint8_t) '\0';

        blen = Fread(b, sizeof(*b), blen, fd);
        if (Ferror(fd)) {
            rc = 1;
            goto exit;
        }
    }
    if (blen < (size_t)sb.st_size)
        b = xrealloc(b, blen+1);
    b[blen] = (rpmuint8_t) '\0';

exit:
    if (fd != NULL) (void) Fclose(fd);

    if (rc == 0) {
        if (iobp != NULL) {
            /* XXX use rpmiobNew() if/when lazy iop->b alloc is implemented. */
            rpmiob iob = rpmiobGetPool(_rpmiobPool);
            iob->b = b;
            iob->blen = blen;
            iob->allocated = blen;
            *iobp = iob;
        }
    } else {
        if (iobp)
            *iobp = NULL;
        b = _free(b);
    }

    return rc;
}
示例#17
0
文件: pack.c 项目: kaltsi/rpm
static rpmRC writeRPM(Header *hdrp, unsigned char ** pkgidp, const char *fileName,
	     CSA_t csa, char **cookie)
{
    FD_t fd = NULL;
    FD_t ifd = NULL;
    ssize_t count;
    char * sigtarget = NULL;;
    char * rpmio_flags = NULL;
    char * SHA1 = NULL;
    const char *s;
    char *buf = NULL;
    Header h;
    Header sig = NULL;
    int xx;
    rpmRC rc = RPMRC_OK;
    struct rpmtd_s td;
    rpmTagVal sizetag;
    rpmTagVal payloadtag;

    /* Transfer header reference form *hdrp to h. */
    h = headerLink(*hdrp);
    *hdrp = headerFree(*hdrp);

    if (pkgidp)
	*pkgidp = NULL;

    /* Save payload information */
    if (headerIsSource(h))
	rpmio_flags = rpmExpand("%{?_source_payload}", NULL);
    else 
	rpmio_flags = rpmExpand("%{?_binary_payload}", NULL);

    if (!(rpmio_flags && *rpmio_flags)) {
	rpmio_flags = _free(rpmio_flags);
	rpmio_flags = xstrdup("w9.gzdio");
    }
    s = strchr(rpmio_flags, '.');
    if (s) {
	const char *compr = NULL;
	headerPutString(h, RPMTAG_PAYLOADFORMAT, "cpio");

	if (rstreq(s+1, "ufdio")) {
	    compr = NULL;
	} else if (rstreq(s+1, "gzdio")) {
	    compr = "gzip";
#if HAVE_BZLIB_H
	} else if (rstreq(s+1, "bzdio")) {
	    compr = "bzip2";
	    /* Add prereq on rpm version that understands bzip2 payloads */
	    (void) rpmlibNeedsFeature(h, "PayloadIsBzip2", "3.0.5-1");
#endif
#if HAVE_LZMA_H
	} else if (rstreq(s+1, "xzdio")) {
	    compr = "xz";
	    (void) rpmlibNeedsFeature(h, "PayloadIsXz", "5.2-1");
	} else if (rstreq(s+1, "lzdio")) {
	    compr = "lzma";
	    (void) rpmlibNeedsFeature(h, "PayloadIsLzma", "4.4.6-1");
#endif
	} else {
	    rpmlog(RPMLOG_ERR, _("Unknown payload compression: %s\n"),
		   rpmio_flags);
	    rc = RPMRC_FAIL;
	    goto exit;
	}

	if (compr)
	    headerPutString(h, RPMTAG_PAYLOADCOMPRESSOR, compr);
	buf = xstrdup(rpmio_flags);
	buf[s - rpmio_flags] = '\0';
	headerPutString(h, RPMTAG_PAYLOADFLAGS, buf+1);
	free(buf);
    }

    /* Create and add the cookie */
    if (cookie) {
	rasprintf(cookie, "%s %d", buildHost(), (int) (*getBuildTime()));
	headerPutString(h, RPMTAG_COOKIE, *cookie);
    }
    
    /* Reallocate the header into one contiguous region. */
    h = headerReload(h, RPMTAG_HEADERIMMUTABLE);
    if (h == NULL) {	/* XXX can't happen */
	rc = RPMRC_FAIL;
	rpmlog(RPMLOG_ERR, _("Unable to create immutable header region.\n"));
	goto exit;
    }
    /* Re-reference reallocated header. */
    *hdrp = headerLink(h);

    /*
     * Write the header+archive into a temp file so that the size of
     * archive (after compression) can be added to the header.
     */
    fd = rpmMkTempFile(NULL, &sigtarget);
    if (fd == NULL || Ferror(fd)) {
	rc = RPMRC_FAIL;
	rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n"));
	goto exit;
    }

    fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
    if (headerWrite(fd, h, HEADER_MAGIC_YES)) {
	rc = RPMRC_FAIL;
	rpmlog(RPMLOG_ERR, _("Unable to write temp header\n"));
    } else { /* Write the archive and get the size */
	(void) Fflush(fd);
	fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&SHA1, NULL, 1);
	if (csa->cpioList != NULL) {
	    rc = cpio_doio(fd, h, csa, rpmio_flags);
	} else if (Fileno(csa->cpioFdIn) >= 0) {
	    rc = cpio_copy(fd, csa);
	} else {
	    rc = RPMRC_FAIL;
	    rpmlog(RPMLOG_ERR, _("Bad CSA data\n"));
	}
    }

    if (rc != RPMRC_OK)
	goto exit;

    (void) Fclose(fd);
    fd = NULL;
    (void) unlink(fileName);

    /* Generate the signature */
    (void) fflush(stdout);
    sig = rpmNewSignature();

    /*
     * There should be rpmlib() dependency on this, but that doesn't
     * really do much good as these are signature tags that get read
     * way before dependency checking has a chance to figure out anything.
     * On the positive side, not inserting the 32bit tag at all means
     * older rpm will just bail out with error message on attempt to read
     * such a package.
     */
    if (csa->cpioArchiveSize < UINT32_MAX) {
	sizetag = RPMSIGTAG_SIZE;
	payloadtag = RPMSIGTAG_PAYLOADSIZE;
    } else {
	sizetag = RPMSIGTAG_LONGSIZE;
	payloadtag = RPMSIGTAG_LONGARCHIVESIZE;
    }
    (void) rpmGenDigest(sig, sigtarget, sizetag);
    (void) rpmGenDigest(sig, sigtarget, RPMSIGTAG_MD5);

    if (SHA1) {
	/* XXX can't use rpmtdFromFoo() on RPMSIGTAG_* items */
	rpmtdReset(&td);
	td.tag = RPMSIGTAG_SHA1;
	td.type = RPM_STRING_TYPE;
	td.data = SHA1;
	td.count = 1;
	headerPut(sig, &td, HEADERPUT_DEFAULT);
	SHA1 = _free(SHA1);
    }

    {	
	/* XXX can't use headerPutType() on legacy RPMSIGTAG_* items */
	rpmtdReset(&td);
	td.tag = payloadtag;
	td.count = 1;
	if (payloadtag == RPMSIGTAG_PAYLOADSIZE) {
	    rpm_off_t asize = csa->cpioArchiveSize;
	    td.type = RPM_INT32_TYPE;
	    td.data = &asize;
	    headerPut(sig, &td, HEADERPUT_DEFAULT);
	} else {
	    rpm_loff_t asize = csa->cpioArchiveSize;
	    td.type = RPM_INT64_TYPE;
	    td.data = &asize;
	    headerPut(sig, &td, HEADERPUT_DEFAULT);
	}
    }

    /* Reallocate the signature into one contiguous region. */
    sig = headerReload(sig, RPMTAG_HEADERSIGNATURES);
    if (sig == NULL) {	/* XXX can't happen */
	rc = RPMRC_FAIL;
	rpmlog(RPMLOG_ERR, _("Unable to reload signature header.\n"));
	goto exit;
    }

    /* Open the output file */
    fd = Fopen(fileName, "w.ufdio");
    if (fd == NULL || Ferror(fd)) {
	rc = RPMRC_FAIL;
	rpmlog(RPMLOG_ERR, _("Could not open %s: %s\n"),
		fileName, Fstrerror(fd));
	goto exit;
    }

    /* Write the lead section into the package. */
    {	
	rpmlead lead = rpmLeadFromHeader(h);
	rc = rpmLeadWrite(fd, lead);
	lead = rpmLeadFree(lead);
	if (rc != RPMRC_OK) {
	    rc = RPMRC_FAIL;
	    rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"),
		 Fstrerror(fd));
	    goto exit;
	}
    }

    /* Write the signature section into the package. */
    if (rpmWriteSignature(fd, sig)) {
	rc = RPMRC_FAIL;
	goto exit;
    }

    /* Append the header and archive */
    ifd = Fopen(sigtarget, "r.ufdio");
    if (ifd == NULL || Ferror(ifd)) {
	rc = RPMRC_FAIL;
	rpmlog(RPMLOG_ERR, _("Unable to open sigtarget %s: %s\n"),
		sigtarget, Fstrerror(ifd));
	goto exit;
    }

    /* Add signatures to header, and write header into the package. */
    /* XXX header+payload digests/signatures might be checked again here. */
    {	Header nh = headerRead(ifd, HEADER_MAGIC_YES);

	if (nh == NULL) {
	    rc = RPMRC_FAIL;
	    rpmlog(RPMLOG_ERR, _("Unable to read header from %s: %s\n"),
			sigtarget, Fstrerror(ifd));
	    goto exit;
	}

#ifdef	NOTYET
	(void) headerMergeLegacySigs(nh, sig);
#endif

	xx = headerWrite(fd, nh, HEADER_MAGIC_YES);
	nh = headerFree(nh);

	if (xx) {
	    rc = RPMRC_FAIL;
	    rpmlog(RPMLOG_ERR, _("Unable to write header to %s: %s\n"),
			fileName, Fstrerror(fd));
	    goto exit;
	}
    }
	
    /* Write the payload into the package. */
    buf = xmalloc(BUFSIZ);
    while ((count = Fread(buf, 1, BUFSIZ, ifd)) > 0) {
	if (count == -1) {
	    free(buf);
	    rc = RPMRC_FAIL;
	    rpmlog(RPMLOG_ERR, _("Unable to read payload from %s: %s\n"),
		     sigtarget, Fstrerror(ifd));
	    goto exit;
	}
	if (Fwrite(buf, sizeof(buf[0]), count, fd) != count) {
	    free(buf);
	    rc = RPMRC_FAIL;
	    rpmlog(RPMLOG_ERR, _("Unable to write payload to %s: %s\n"),
		     fileName, Fstrerror(fd));
	    goto exit;
	}
    }
    free(buf);
    rc = RPMRC_OK;

exit:
    rpmio_flags = _free(rpmio_flags);
    SHA1 = _free(SHA1);
    h = headerFree(h);

    /* XXX Fish the pkgid out of the signature header. */
    if (sig != NULL && pkgidp != NULL) {
	struct rpmtd_s md5tag;
	headerGet(sig, RPMSIGTAG_MD5, &md5tag, HEADERGET_DEFAULT);
	if (rpmtdType(&md5tag) == RPM_BIN_TYPE &&
	    			md5tag.count == 16 && md5tag.data != NULL) {
	    *pkgidp = md5tag.data;
	}
    }

    sig = rpmFreeSignature(sig);
    if (ifd) {
	(void) Fclose(ifd);
	ifd = NULL;
    }
    if (fd) {
	(void) Fclose(fd);
	fd = NULL;
    }
    if (sigtarget) {
	(void) unlink(sigtarget);
	sigtarget = _free(sigtarget);
    }

    if (rc == RPMRC_OK)
	rpmlog(RPMLOG_NOTICE, _("Wrote: %s\n"), fileName);
    else
	(void) unlink(fileName);

    return rc;
}
示例#18
0
文件: rpmio.c 项目: akozumpl/rpm
static long fdTell(FD_t fd)
{
    return lseek(Fileno(fd), 0, SEEK_CUR);
}
示例#19
0
/**
 * Run an external script.
 */
static rpmRC runExtScript(rpmPlugins plugins, ARGV_const_t prefixes,
                          const char *sname, rpmlogLvl lvl, FD_t scriptFd,
                          ARGV_t * argvp, const char *script, int arg1, int arg2)
{
    FD_t out = NULL;
    char * fn = NULL;
    pid_t pid, reaped;
    int status;
    rpmRC rc = RPMRC_FAIL;

    rpmlog(RPMLOG_DEBUG, "%s: scriptlet start\n", sname);

    if (script) {
        fn = writeScript(*argvp[0], script);
        if (fn == NULL) {
            rpmlog(RPMLOG_ERR,
                   _("Couldn't create temporary file for %s: %s\n"),
                   sname, strerror(errno));
            goto exit;
        }

        argvAdd(argvp, fn);
        if (arg1 >= 0) {
            argvAddNum(argvp, arg1);
        }
        if (arg2 >= 0) {
            argvAddNum(argvp, arg2);
        }
    }

    if (scriptFd != NULL) {
        if (rpmIsVerbose()) {
            out = fdDup(Fileno(scriptFd));
        } else {
            out = Fopen("/dev/null", "w.fdio");
            if (Ferror(out)) {
                out = fdDup(Fileno(scriptFd));
            }
        }
    } else {
        out = fdDup(STDOUT_FILENO);
    }
    if (out == NULL) {
        rpmlog(RPMLOG_ERR, _("Couldn't duplicate file descriptor: %s: %s\n"),
               sname, strerror(errno));
        goto exit;
    }

    pid = fork();
    if (pid == (pid_t) -1) {
        rpmlog(RPMLOG_ERR, _("Couldn't fork %s: %s\n"),
               sname, strerror(errno));
        goto exit;
    } else if (pid == 0) {/* Child */
        rpmlog(RPMLOG_DEBUG, "%s: execv(%s) pid %d\n",
               sname, *argvp[0], (unsigned)getpid());

        /* Run scriptlet post fork hook for all plugins */
        if (rpmpluginsCallScriptletForkPost(plugins, *argvp[0], RPMSCRIPTLET_FORK | RPMSCRIPTLET_EXEC) != RPMRC_FAIL) {
            doScriptExec(*argvp, prefixes, scriptFd, out);
        } else {
            _exit(126); /* exit 126 for compatibility with bash(1) */
        }
    }

    do {
        reaped = waitpid(pid, &status, 0);
    } while (reaped == -1 && errno == EINTR);

    rpmlog(RPMLOG_DEBUG, "%s: waitpid(%d) rc %d status %x\n",
           sname, (unsigned)pid, (unsigned)reaped, status);

    if (reaped < 0) {
        rpmlog(lvl, _("%s scriptlet failed, waitpid(%d) rc %d: %s\n"),
               sname, pid, reaped, strerror(errno));
    } else if (!WIFEXITED(status) || WEXITSTATUS(status)) {
        if (WIFSIGNALED(status)) {
            rpmlog(lvl, _("%s scriptlet failed, signal %d\n"),
                   sname, WTERMSIG(status));
        } else {
            rpmlog(lvl, _("%s scriptlet failed, exit status %d\n"),
                   sname, WEXITSTATUS(status));
        }
    } else {
        /* if we get this far we're clear */
        rc = RPMRC_OK;
    }

exit:
    if (out)
        Fclose(out);	/* XXX dup'd STDOUT_FILENO */

    if (fn) {
        if (!rpmIsDebug())
            unlink(fn);
        free(fn);
    }
    return rc;
}
示例#20
0
static void doScriptExec(ARGV_const_t argv, ARGV_const_t prefixes,
                         FD_t scriptFd, FD_t out)
{
    int pipes[2];
    int flag;
    int fdno;
    int xx;
    int open_max;

    (void) signal(SIGPIPE, SIG_DFL);
    pipes[0] = pipes[1] = 0;
    /* make stdin inaccessible */
    xx = pipe(pipes);
    xx = close(pipes[1]);
    xx = dup2(pipes[0], STDIN_FILENO);
    xx = close(pipes[0]);

    /* XXX Force FD_CLOEXEC on all inherited fdno's. */
    open_max = sysconf(_SC_OPEN_MAX);
    if (open_max == -1) {
        open_max = 1024;
    }
    for (fdno = 3; fdno < open_max; fdno++) {
        flag = fcntl(fdno, F_GETFD);
        if (flag == -1 || (flag & FD_CLOEXEC))
            continue;
        xx = fcntl(fdno, F_SETFD, FD_CLOEXEC);
        /* XXX W2DO? debug msg for inheirited fdno w/o FD_CLOEXEC */
    }

    if (scriptFd != NULL) {
        int sfdno = Fileno(scriptFd);
        int ofdno = Fileno(out);
        if (sfdno != STDERR_FILENO)
            xx = dup2(sfdno, STDERR_FILENO);
        if (ofdno != STDOUT_FILENO)
            xx = dup2(ofdno, STDOUT_FILENO);
        /* make sure we don't close stdin/stderr/stdout by mistake! */
        if (ofdno > STDERR_FILENO && ofdno != sfdno)
            xx = Fclose (out);
        if (sfdno > STDERR_FILENO && ofdno != sfdno)
            xx = Fclose (scriptFd);
    }

    {   char *ipath = rpmExpand("%{_install_script_path}", NULL);
        const char *path = SCRIPT_PATH;

        if (ipath && ipath[5] != '%')
            path = ipath;

        xx = setenv("PATH", path, 1);
        free(ipath);
    }

    for (ARGV_const_t pf = prefixes; pf && *pf; pf++) {
        char *name = NULL;
        int num = (pf - prefixes);

        rasprintf(&name, "RPM_INSTALL_PREFIX%d", num);
        setenv(name, *pf, 1);
        free(name);

        /* scripts might still be using the old style prefix */
        if (num == 0) {
            setenv("RPM_INSTALL_PREFIX", *pf, 1);
        }
    }

    if (chdir("/") == 0) {
        /* XXX Don't mtrace into children. */
        unsetenv("MALLOC_CHECK_");

        if (xx == 0) {
            xx = execv(argv[0], argv);
        }
    }
    _exit(127); /* exit 127 for compatibility with bash(1) */
}