Ejemplo n.º 1
0
int parsePrep(rpmSpec spec)
{
    int nextPart, res, rc;
    StringBuf sb;
    char **lines;
    ARGV_t saveLines = NULL;

    if (spec->prep != NULL) {
	rpmlog(RPMLOG_ERR, _("line %d: second %%prep\n"), spec->lineNum);
	return PART_ERROR;
    }

    spec->prep = newStringBuf();

    /* There are no options to %prep */
    if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
	return PART_NONE;
    } else if (rc < 0) {
	return PART_ERROR;
    }
    
    sb = newStringBuf();
    
    while (! (nextPart = isPart(spec->line))) {
	/* Need to expand the macros inline.  That way we  */
	/* can give good line number information on error. */
	appendStringBuf(sb, spec->line);
	if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
	    nextPart = PART_NONE;
	    break;
	} else if (rc < 0) {
	    goto exit;
	}
    }

    saveLines = argvSplitString(getStringBuf(sb), "\n", ARGV_NONE);
    for (lines = saveLines; *lines; lines++) {
	res = 0;
	if (rstreqn(*lines, "%setup", sizeof("%setup")-1)) {
	    res = doSetupMacro(spec, *lines);
	} else if (rstreqn(*lines, "%patch", sizeof("%patch")-1)) {
	    res = doPatchMacro(spec, *lines);
	} else {
	    appendLineStringBuf(spec->prep, *lines);
	}
	if (res && !spec->force) {
	    /* fixup from RPMRC_FAIL do*Macro() codes for now */
	    nextPart = PART_ERROR; 
	    goto exit;
	}
    }
    res = nextPart;

exit:
    argvFree(saveLines);
    sb = freeStringBuf(sb);

    return nextPart;
}
Ejemplo n.º 2
0
Archivo: pack.c Proyecto: nforro/rpm
static rpmRC addFileToTag(rpmSpec spec, const char * file,
			  Header h, rpmTagVal tag, int append)
{
    StringBuf sb = NULL;
    char buf[BUFSIZ];
    char * fn;
    FILE * f;
    rpmRC rc = RPMRC_FAIL; /* assume failure */

    /* no script file is not an error */
    if (file == NULL)
	return RPMRC_OK;

    fn = rpmGetPath("%{_builddir}/%{?buildsubdir:%{buildsubdir}/}", file, NULL);

    f = fopen(fn, "r");
    if (f == NULL) {
	rpmlog(RPMLOG_ERR,_("Could not open %s file: %s\n"),
			   rpmTagGetName(tag), file);
	goto exit;
    }

    sb = newStringBuf();
    if (append) {
	const char *s = headerGetString(h, tag);
	if (s) {
	    appendLineStringBuf(sb, s);
	    headerDel(h, tag);
	}
    }

    while (fgets(buf, sizeof(buf), f)) {
	char *expanded;
	if (rpmExpandMacros(spec->macros, buf, &expanded, 0) < 0) {
	    rpmlog(RPMLOG_ERR, _("%s: line: %s\n"), fn, buf);
	    goto exit;
	}
	appendStringBuf(sb, expanded);
	free(expanded);
    }
    headerPutString(h, tag, getStringBuf(sb));
    rc = RPMRC_OK;

exit:
    if (f) fclose(f);
    free(fn);
    freeStringBuf(sb);

    return rc;
}
Ejemplo n.º 3
0
Archivo: pack.c Proyecto: kaltsi/rpm
static int addFileToTag(rpmSpec spec, const char * file, Header h, rpmTagVal tag)
{
    StringBuf sb = newStringBuf();
    const char *s = headerGetString(h, tag);

    if (s) {
	appendLineStringBuf(sb, s);
	(void) headerDel(h, tag);
    }

    if ((sb = addFileToTagAux(spec, file, sb)) == NULL)
	return 1;
    
    headerPutString(h, tag, getStringBuf(sb));

    sb = freeStringBuf(sb);
    return 0;
}
Ejemplo n.º 4
0
Archivo: pack.c Proyecto: xrg/RPM
static int addFileToTag(rpmSpec spec, const char * file, Header h, rpmTag tag)
{
    StringBuf sb = newStringBuf();
    const char *s;
    struct rpmtd_s td;

    headerGet(h, tag, &td, HEADERGET_MINMEM);
    if ((s = rpmtdGetString(&td))) {
	appendLineStringBuf(sb, s);
    	rpmtdFreeData(&td);
	(void) headerDel(h, tag);
    }

    if ((sb = addFileToTagAux(spec, file, sb)) == NULL)
	return 1;
    
    headerPutString(h, tag, getStringBuf(sb));

    sb = freeStringBuf(sb);
    return 0;
}
Ejemplo n.º 5
0
static rpmSpec parseSpec(const char *specFile, rpmSpecFlags flags,
                         const char *buildRoot, int recursing)
{
    int parsePart = PART_PREAMBLE;
    int initialPackage = 1;
    rpmSpec spec;

    /* Set up a new Spec structure with no packages. */
    spec = newSpec();

    spec->specFile = rpmGetPath(specFile, NULL);
    pushOFI(spec, spec->specFile);
    /* If buildRoot not specified, use default %{buildroot} */
    if (buildRoot) {
        spec->buildRoot = xstrdup(buildRoot);
    } else {
        spec->buildRoot = rpmGetPath("%{?buildroot:%{buildroot}}", NULL);
    }
    addMacro(NULL, "_docdir", NULL, "%{_defaultdocdir}", RMIL_SPEC);
    addMacro(NULL, "_licensedir", NULL, "%{_defaultlicensedir}", RMIL_SPEC);
    spec->recursing = recursing;
    spec->flags = flags;

    /* All the parse*() functions expect to have a line pre-read */
    /* in the spec's line buffer.  Except for parsePreamble(),   */
    /* which handles the initial entry into a spec file.         */

    while (parsePart != PART_NONE) {
        int goterror = 0;
        switch (parsePart) {
        case PART_ERROR: /* fallthrough */
        default:
            goterror = 1;
            break;
        case PART_PREAMBLE:
            parsePart = parsePreamble(spec, initialPackage);
            initialPackage = 0;
            break;
        case PART_PREP:
            parsePart = parsePrep(spec);
            break;
        case PART_BUILD:
        case PART_INSTALL:
        case PART_CHECK:
        case PART_CLEAN:
            parsePart = parseBuildInstallClean(spec, parsePart);
            break;
        case PART_CHANGELOG:
            parsePart = parseChangelog(spec);
            break;
        case PART_DESCRIPTION:
            parsePart = parseDescription(spec);
            break;

        case PART_PRE:
        case PART_POST:
        case PART_PREUN:
        case PART_POSTUN:
        case PART_PRETRANS:
        case PART_POSTTRANS:
        case PART_VERIFYSCRIPT:
        case PART_TRIGGERPREIN:
        case PART_TRIGGERIN:
        case PART_TRIGGERUN:
        case PART_TRIGGERPOSTUN:
        case PART_FILETRIGGERIN:
        case PART_FILETRIGGERUN:
        case PART_FILETRIGGERPOSTUN:
        case PART_TRANSFILETRIGGERIN:
        case PART_TRANSFILETRIGGERUN:
        case PART_TRANSFILETRIGGERPOSTUN:
            parsePart = parseScript(spec, parsePart);
            break;

        case PART_FILES:
            parsePart = parseFiles(spec);
            break;

        case PART_POLICIES:
            parsePart = parsePolicies(spec);
            break;

        case PART_NONE:		/* XXX avoid gcc whining */
        case PART_LAST:
        case PART_BUILDARCHITECTURES:
            break;
        }

        if (goterror || parsePart >= PART_LAST) {
            goto errxit;
        }

        if (parsePart == PART_BUILDARCHITECTURES) {
            int index;
            int x;

            closeSpec(spec);

            spec->BASpecs = xcalloc(spec->BACount, sizeof(*spec->BASpecs));
            index = 0;
            if (spec->BANames != NULL)
                for (x = 0; x < spec->BACount; x++) {

                    /* Skip if not arch is not compatible. */
                    if (!rpmMachineScore(RPM_MACHTABLE_BUILDARCH, spec->BANames[x]))
                        continue;
                    addMacro(NULL, "_target_cpu", NULL, spec->BANames[x], RMIL_RPMRC);
                    spec->BASpecs[index] = parseSpec(specFile, flags, buildRoot, 1);
                    if (spec->BASpecs[index] == NULL) {
                        spec->BACount = index;
                        goto errxit;
                    }
                    delMacro(NULL, "_target_cpu");
                    index++;
                }

            spec->BACount = index;
            if (! index) {
                rpmlog(RPMLOG_ERR,
                       _("No compatible architectures found for build\n"));
                goto errxit;
            }

            /*
             * Return the 1st child's fully parsed Spec structure.
             * The restart of the parse when encountering BuildArch
             * causes problems for "rpm -q --specfile". This is
             * still a hack because there may be more than 1 arch
             * specified (unlikely but possible.) There's also the
             * further problem that the macro context, particularly
             * %{_target_cpu}, disagrees with the info in the header.
             */
            if (spec->BACount >= 1) {
                rpmSpec nspec = spec->BASpecs[0];
                spec->BASpecs = _free(spec->BASpecs);
                rpmSpecFree(spec);
                spec = nspec;
            }

            goto exit;
        }
    }

    if (spec->clean == NULL) {
        char *body = rpmExpand("%{?buildroot: %{__rm} -rf %{buildroot}}", NULL);
        spec->clean = newStringBuf();
        appendLineStringBuf(spec->clean, body);
        free(body);
    }

    /* Check for description in each package */
    for (Package pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
        if (!headerIsEntry(pkg->header, RPMTAG_DESCRIPTION)) {
            rpmlog(RPMLOG_ERR, _("Package has no %%description: %s\n"),
                   headerGetString(pkg->header, RPMTAG_NAME));
            goto errxit;
        }
    }

    /* Add arch, os and platform, self-provides etc for each package */
    addTargets(spec->packages);

    /* Check for encoding in each package unless disabled */
    if (!(spec->flags & RPMSPEC_NOUTF8)) {
        int badenc = 0;
        for (Package pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
            if (checkForEncoding(pkg->header, 0) != RPMRC_OK) {
                badenc = 1;
            }
        }
        if (badenc)
            goto errxit;
    }

    closeSpec(spec);
exit:
    /* Assemble source header from parsed components */
    initSourceHeader(spec);

    return spec;

errxit:
    rpmSpecFree(spec);
    return NULL;
}
Ejemplo n.º 6
0
int parseSpec(rpmts ts, const char *specFile, const char *rootDir,
		const char *buildRoot, int recursing, const char *passPhrase,
		const char *cookie, int anyarch, int force)
{
    rpmParseState parsePart = PART_PREAMBLE;
    int initialPackage = 1;
    Package pkg;
    rpmSpec spec;
    
    /* Set up a new Spec structure with no packages. */
    spec = newSpec();

    spec->specFile = rpmGetPath(specFile, NULL);
    spec->fileStack = newOpenFileInfo();
    spec->fileStack->fileName = xstrdup(spec->specFile);
    /* If buildRoot not specified, use default %{buildroot} */
    if (buildRoot) {
	spec->buildRoot = xstrdup(buildRoot);
    } else {
	spec->buildRoot = rpmGetPath("%{?buildroot:%{buildroot}}", NULL);
    }
    addMacro(NULL, "_docdir", NULL, "%{_defaultdocdir}", RMIL_SPEC);
    spec->recursing = recursing;
    spec->anyarch = anyarch;
    spec->force = force;

    if (rootDir)
	spec->rootDir = xstrdup(rootDir);
    if (passPhrase)
	spec->passPhrase = xstrdup(passPhrase);
    if (cookie)
	spec->cookie = xstrdup(cookie);

    spec->timeCheck = rpmExpandNumeric("%{_timecheck}");

    /* All the parse*() functions expect to have a line pre-read */
    /* in the spec's line buffer.  Except for parsePreamble(),   */
    /* which handles the initial entry into a spec file.         */
    
    while (parsePart != PART_NONE) {
	int goterror = 0;
	switch (parsePart) {
	/* XXX Trap unexpected RPMRC_FAIL returns for now */
	case RPMRC_FAIL:
	    rpmlog(RPMLOG_ERR, "FIXME: got RPMRC_FAIL from spec parse\n");
	    abort();
	case PART_ERROR: /* fallthrough */
	default:
	    goterror = 1;
	    break;
	case PART_PREAMBLE:
	    parsePart = parsePreamble(spec, initialPackage);
	    initialPackage = 0;
	    break;
	case PART_PREP:
	    parsePart = parsePrep(spec);
	    break;
	case PART_BUILD:
	case PART_INSTALL:
	case PART_CHECK:
	case PART_CLEAN:
	    parsePart = parseBuildInstallClean(spec, parsePart);
	    break;
	case PART_CHANGELOG:
	    parsePart = parseChangelog(spec);
	    break;
	case PART_DESCRIPTION:
	    parsePart = parseDescription(spec);
	    break;

	case PART_PRE:
	case PART_POST:
	case PART_PREUN:
	case PART_POSTUN:
	case PART_PRETRANS:
	case PART_POSTTRANS:
	case PART_VERIFYSCRIPT:
	case PART_TRIGGERPREIN:
	case PART_TRIGGERIN:
	case PART_TRIGGERUN:
	case PART_TRIGGERPOSTUN:
	    parsePart = parseScript(spec, parsePart);
	    break;

	case PART_FILES:
	    parsePart = parseFiles(spec);
	    break;

	case PART_NONE:		/* XXX avoid gcc whining */
	case PART_LAST:
	case PART_BUILDARCHITECTURES:
	    break;
	}

	if (goterror || parsePart >= PART_LAST) {
	    goto errxit;
	}

	if (parsePart == PART_BUILDARCHITECTURES) {
	    int index;
	    int x;

	    closeSpec(spec);

	    spec->BASpecs = xcalloc(spec->BACount, sizeof(*spec->BASpecs));
	    index = 0;
	    if (spec->BANames != NULL)
	    for (x = 0; x < spec->BACount; x++) {

		/* Skip if not arch is not compatible. */
		if (!rpmMachineScore(RPM_MACHTABLE_BUILDARCH, spec->BANames[x]))
		    continue;
		addMacro(NULL, "_target_cpu", NULL, spec->BANames[x], RMIL_RPMRC);
		spec->BASpecs[index] = NULL;
		if (parseSpec(ts, specFile, spec->rootDir, buildRoot, 1,
				  passPhrase, cookie, anyarch, force)
		 || (spec->BASpecs[index] = rpmtsSetSpec(ts, NULL)) == NULL)
		{
			spec->BACount = index;
			goto errxit;
		}
		delMacro(NULL, "_target_cpu");
		index++;
	    }

	    spec->BACount = index;
	    if (! index) {
		rpmlog(RPMLOG_ERR,
			_("No compatible architectures found for build\n"));
		goto errxit;
	    }

	    /*
	     * Return the 1st child's fully parsed Spec structure.
	     * The restart of the parse when encountering BuildArch
	     * causes problems for "rpm -q --specfile". This is
	     * still a hack because there may be more than 1 arch
	     * specified (unlikely but possible.) There's also the
	     * further problem that the macro context, particularly
	     * %{_target_cpu}, disagrees with the info in the header.
	     */
	    if (spec->BACount >= 1) {
		rpmSpec nspec = spec->BASpecs[0];
		spec->BASpecs = _free(spec->BASpecs);
		spec = freeSpec(spec);
		spec = nspec;
	    }

	    (void) rpmtsSetSpec(ts, spec);
	    return 0;
	}
    }

    if (spec->clean == NULL) {
	char *body = rpmExpand("%{?buildroot: %{__rm} -rf %{buildroot}}", NULL);
	spec->clean = newStringBuf();
	appendLineStringBuf(spec->clean, body);
	free(body);
    }

    /* Check for description in each package and add arch and os */
  {
    char *platform = rpmExpand("%{_target_platform}", NULL);
    char *arch = rpmExpand("%{_target_cpu}", NULL);
    char *os = rpmExpand("%{_target_os}", NULL);

    for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
	if (!headerIsEntry(pkg->header, RPMTAG_DESCRIPTION)) {
	    rpmlog(RPMLOG_ERR, _("Package has no %%description: %s\n"),
		   headerGetString(pkg->header, RPMTAG_NAME));
	    goto errxit;
	}

	headerPutString(pkg->header, RPMTAG_OS, os);
	/* noarch subpackages already have arch set here, leave it alone */
	if (!headerIsEntry(pkg->header, RPMTAG_ARCH)) {
	    headerPutString(pkg->header, RPMTAG_ARCH, arch);
	}
	headerPutString(pkg->header, RPMTAG_PLATFORM, platform);

	pkg->ds = rpmdsThis(pkg->header, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL);

    }

    platform = _free(platform);
    arch = _free(arch);
    os = _free(os);
  }

    closeSpec(spec);
    (void) rpmtsSetSpec(ts, spec);

    return 0;

errxit:
    spec = freeSpec(spec);
    return PART_ERROR;
}
Ejemplo n.º 7
0
/**
 * Parse %patch line.
 * This supports too many crazy syntaxes:
 * - %patchN is equal to %patch -P<N>
 * - -P<N> -P<N+1>... can be used to apply several patch on a single line
 * - Any trailing arguments are treated as patch numbers
 * - Any combination of the above, except unless at least one -P is specified,
 *   %patch is treated as %patch -P0 so that "%patch 1" is actually
 *   equal to "%patch -P0 -P1".
 *
 * @param spec		build info
 * @param line		current line from spec file
 * @return		RPMRC_OK on success
 */
static rpmRC doPatchMacro(rpmSpec spec, const char *line)
{
    char *opt_b, *opt_P, *opt_d;
    char *buf = NULL;
    int opt_p, opt_R, opt_E, opt_F;
    int argc, c;
    const char **argv = NULL;
    ARGV_t patch, patchnums = NULL;
    rpmRC rc = RPMRC_FAIL; /* assume failure */
    
    struct poptOption const patchOpts[] = {
	{ NULL, 'P', POPT_ARG_STRING, &opt_P, 'P', NULL, NULL },
	{ NULL, 'p', POPT_ARG_INT, &opt_p, 'p', NULL, NULL },
	{ NULL, 'R', POPT_ARG_NONE, &opt_R, 'R', NULL, NULL },
	{ NULL, 'E', POPT_ARG_NONE, &opt_E, 'E', NULL, NULL },
	{ NULL, 'b', POPT_ARG_STRING, &opt_b, 'b', NULL, NULL },
	{ NULL, 'z', POPT_ARG_STRING, &opt_b, 'z', NULL, NULL },
	{ NULL, 'F', POPT_ARG_INT, &opt_F, 'F', NULL, NULL },
	{ NULL, 'd', POPT_ARG_STRING, &opt_d, 'd', NULL, NULL },
	{ NULL, 0, 0, NULL, 0, NULL, NULL }
    };
    poptContext optCon = NULL;

    opt_p = opt_R = opt_E = 0;
    opt_F = rpmExpandNumeric("%{_default_patch_fuzz}");		/* get default fuzz factor for %patch */
    opt_b = opt_d = NULL;

    /* Convert %patchN to %patch -PN to simplify further processing */
    if (! strchr(" \t\n", line[6])) {
	rasprintf(&buf, "%%patch -P %s", line + 6);
    } else {
	if (strstr(line+6, " -P") == NULL)
	    rasprintf(&buf, "%%patch -P %d %s", INT_MAX, line + 6); /* INT_MAX denotes not numbered %patch */
	else
	    buf = xstrdup(line); /* it is not numberless patch because -P is present */
    }
    poptParseArgvString(buf, &argc, &argv);
    free(buf);

    /* 
     * Grab all -P<N> numbers for later processing. Stored as strings
     * at this point so we only have to worry about conversion in one place.
     */
    optCon = poptGetContext(NULL, argc, argv, patchOpts, 0);
    while ((c = poptGetNextOpt(optCon)) > 0) {
	switch (c) {
	case 'P': {
	    char *arg = poptGetOptArg(optCon);
	    if (arg) {
	    	argvAdd(&patchnums, arg);
	    	free(arg);
	    }
	    break;
	}
	default:
	    break;
	}
    }

    if (c < -1) {
	rpmlog(RPMLOG_ERR, _("%s: %s: %s\n"), poptStrerror(c), 
		poptBadOption(optCon, POPT_BADOPTION_NOALIAS), line);
	goto exit;
    }

    /* Any trailing arguments are treated as patch numbers */
    argvAppend(&patchnums, (ARGV_const_t) poptGetArgs(optCon));

    /* Convert to number, generate patch command and append to %prep script */
    for (patch = patchnums; *patch; patch++) {
	uint32_t pnum;
	char *s;
	if (parseUnsignedNum(*patch, &pnum)) {
	    rpmlog(RPMLOG_ERR, _("Invalid patch number %s: %s\n"),
		     *patch, line);
	    goto exit;
	}
	s = doPatch(spec, pnum, opt_p, opt_b, opt_R, opt_E, opt_F, opt_d);
	if (s == NULL) {
	    goto exit;
	}
	appendLineStringBuf(spec->prep, s);
	free(s);
    }
	
    rc = RPMRC_OK;

exit:
    argvFree(patchnums);
    free(argv);
    poptFreeContext(optCon);
    return rc;
}
Ejemplo n.º 8
0
/**
 * Parse %setup macro.
 * @todo FIXME: Option -q broken when not immediately after %setup.
 * @param spec		build info
 * @param line		current line from spec file
 * @return		RPMRC_OK on success
 */
static int doSetupMacro(rpmSpec spec, const char *line)
{
    char *buf = NULL;
    StringBuf before = newStringBuf();
    StringBuf after = newStringBuf();
    poptContext optCon = NULL;
    int argc;
    const char ** argv = NULL;
    int arg;
    const char * optArg;
    int xx;
    rpmRC rc = RPMRC_FAIL;
    uint32_t num;
    int leaveDirs = 0, skipDefaultAction = 0;
    int createDir = 0, quietly = 0;
    const char * dirName = NULL;
    struct poptOption optionsTable[] = {
	    { NULL, 'a', POPT_ARG_STRING, NULL, 'a',	NULL, NULL},
	    { NULL, 'b', POPT_ARG_STRING, NULL, 'b',	NULL, NULL},
	    { NULL, 'c', 0, &createDir, 0,		NULL, NULL},
	    { NULL, 'D', 0, &leaveDirs, 0,		NULL, NULL},
	    { NULL, 'n', POPT_ARG_STRING, &dirName, 0,	NULL, NULL},
	    { NULL, 'T', 0, &skipDefaultAction, 0,	NULL, NULL},
	    { NULL, 'q', 0, &quietly, 0,		NULL, NULL},
	    { 0, 0, 0, 0, 0,	NULL, NULL}
    };

    if ((xx = poptParseArgvString(line, &argc, &argv))) {
	rpmlog(RPMLOG_ERR, _("Error parsing %%setup: %s\n"), poptStrerror(xx));
	goto exit;
    }

    optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
    while ((arg = poptGetNextOpt(optCon)) > 0) {
	optArg = poptGetOptArg(optCon);

	/* We only parse -a and -b here */

	if (parseUnsignedNum(optArg, &num)) {
	    rpmlog(RPMLOG_ERR, _("line %d: Bad arg to %%setup: %s\n"),
		     spec->lineNum, (optArg ? optArg : "???"));
	    goto exit;
	}

	{   char *chptr = doUntar(spec, num, quietly);
	    if (chptr == NULL)
		goto exit;

	    appendLineStringBuf((arg == 'a' ? after : before), chptr);
	    free(chptr);
	}
    }

    if (arg < -1) {
	rpmlog(RPMLOG_ERR, _("line %d: Bad %%setup option %s: %s\n"),
		 spec->lineNum,
		 poptBadOption(optCon, POPT_BADOPTION_NOALIAS), 
		 poptStrerror(arg));
	goto exit;
    }

    if (dirName) {
	spec->buildSubdir = xstrdup(dirName);
    } else {
	rasprintf(&spec->buildSubdir, "%s-%s", 
		  headerGetString(spec->packages->header, RPMTAG_NAME),
		  headerGetString(spec->packages->header, RPMTAG_VERSION));
    }
    addMacro(spec->macros, "buildsubdir", NULL, spec->buildSubdir, RMIL_SPEC);
    
    /* cd to the build dir */
    {	char * buildDir = rpmGenPath(spec->rootDir, "%{_builddir}", "");

	rasprintf(&buf, "cd '%s'", buildDir);
	appendLineStringBuf(spec->prep, buf);
	free(buf);
	free(buildDir);
    }
    
    /* delete any old sources */
    if (!leaveDirs) {
	rasprintf(&buf, "rm -rf '%s'", spec->buildSubdir);
	appendLineStringBuf(spec->prep, buf);
	free(buf);
    }

    /* if necessary, create and cd into the proper dir */
    if (createDir) {
	rasprintf(&buf, RPM_MKDIR_P " %s\ncd '%s'",
		spec->buildSubdir, spec->buildSubdir);
	appendLineStringBuf(spec->prep, buf);
	free(buf);
    }

    /* do the default action */
   if (!createDir && !skipDefaultAction) {
	char *chptr = doUntar(spec, 0, quietly);
	if (!chptr)
	    goto exit;
	appendLineStringBuf(spec->prep, chptr);
	free(chptr);
    }

    appendStringBuf(spec->prep, getStringBuf(before));

    if (!createDir) {
	rasprintf(&buf, "cd '%s'", spec->buildSubdir);
	appendLineStringBuf(spec->prep, buf);
	free(buf);
    }

    if (createDir && !skipDefaultAction) {
	char *chptr = doUntar(spec, 0, quietly);
	if (chptr == NULL)
	    goto exit;
	appendLineStringBuf(spec->prep, chptr);
	free(chptr);
    }
    
    appendStringBuf(spec->prep, getStringBuf(after));

    /* Fix the permissions of the setup build tree */
    {	char *fix = rpmExpand("%{_fixperms} .", NULL);
	if (fix && *fix != '%') {
	    appendLineStringBuf(spec->prep, fix);
	}
	free(fix);
    }
    rc = RPMRC_OK;

exit:
    freeStringBuf(before);
    freeStringBuf(after);
    poptFreeContext(optCon);
    free(argv);

    return rc;
}