FD_t rpmMkTempFile(const char * prefix, char **fn) { const char *tpmacro = "%{_tmppath}"; /* always set from rpmrc */ char *tempfn; static int _initialized = 0; FD_t tfd = NULL; if (!prefix) prefix = ""; /* Create the temp directory if it doesn't already exist. */ if (!_initialized) { _initialized = 1; tempfn = rpmGenPath(prefix, tpmacro, NULL); if (rpmioMkpath(tempfn, 0755, (uid_t) -1, (gid_t) -1)) goto exit; free(tempfn); } tempfn = rpmGetPath(prefix, tpmacro, "/rpm-tmp.XXXXXX", NULL); tfd = rpmMkTemp(tempfn); if (tfd == NULL || Ferror(tfd)) { rpmlog(RPMLOG_ERR, _("error creating temporary file %s: %m\n"), tempfn); goto exit; } exit: if (tfd != NULL && fn) *fn = tempfn; else free(tempfn); return tfd; }
int rpmMkdirs(const char *root, const char *pathstr) { ARGV_t dirs = NULL; int rc = 0; argvSplit(&dirs, pathstr, ":"); for (char **d = dirs; *d; d++) { char *path = rpmGetPath(root ? root : "", *d, NULL); if ((rc = rpmioMkpath(path, 0755, -1, -1)) != 0) { const char *msg = _("failed to create directory"); /* try to be more informative if the failing part was a macro */ if (**d == '%') { rpmlog(RPMLOG_ERR, "%s %s: %s: %m\n", msg, *d, path); } else { rpmlog(RPMLOG_ERR, "%s %s: %m\n", msg, path); } } free(path); if (rc) break; } argvFree(dirs); return rc; }
rpmtxn rpmtxnBegin(rpmts ts, rpmtxnFlags flags) { static const char * const rpmlock_path_default = "%{?_rpmlock_path}"; rpmtxn txn = NULL; if (ts == NULL) return NULL; if (ts->lockPath == NULL) { const char *rootDir = rpmtsRootDir(ts); char *t; if (!rootDir || rpmChrootDone()) rootDir = "/"; t = rpmGenPath(rootDir, rpmlock_path_default, NULL); if (t == NULL || *t == '\0' || *t == '%') { free(t); t = xstrdup(RPMLOCK_PATH); } ts->lockPath = xstrdup(t); (void) rpmioMkpath(dirname(t), 0755, getuid(), getgid()); free(t); } if (ts->lock == NULL) ts->lock = rpmlockNew(ts->lockPath, _("transaction")); if (rpmlockAcquire(ts->lock)) { txn = xcalloc(1, sizeof(*txn)); txn->lock = ts->lock; txn->flags = flags; txn->ts = rpmtsLink(ts); } return txn; }
/* * There is no function for creating unique temporary fifos so create * unique temporary directory and then create fifo in it. */ static char *mkTempFifo(void) { char *tmppath = NULL, *tmpdir = NULL, *fifofn = NULL; mode_t mode; tmppath = rpmExpand("%{_tmppath}", NULL); if (rpmioMkpath(tmppath, 0755, (uid_t) -1, (gid_t) -1)) goto exit; tmpdir = rpmGetPath(tmppath, "/rpm-tmp.XXXXXX", NULL); mode = umask(0077); tmpdir = mkdtemp(tmpdir); umask(mode); if (tmpdir == NULL) { rpmlog(RPMLOG_ERR, _("error creating temp directory %s: %m\n"), tmpdir); tmpdir = _free(tmpdir); goto exit; } fifofn = rpmGetPath(tmpdir, "/fifo", NULL); if (mkfifo(fifofn, 0600) == -1) { rpmlog(RPMLOG_ERR, _("error creating fifo %s: %m\n"), fifofn); fifofn = _free(fifofn); } exit: if (fifofn == NULL && tmpdir != NULL) unlink(tmpdir); free(tmppath); free(tmpdir); return fifofn; }
static int db3open(rpmdb rpmdb, rpmTag rpmtag, dbiIndex * dbip) { extern const struct _dbiVec db3vec; const char * root; const char * home; char * dbhome; const char * dbfile; const char * dbsubfile; dbiIndex dbi = NULL; int rc = 0; int xx; DB * db = NULL; DB_ENV * dbenv = NULL; DB_TXN * txnid = NULL; uint32_t oflags; int _printit; if (dbip) *dbip = NULL; /* * Parse db configuration parameters. */ if ((dbi = db3New(rpmdb, rpmtag)) == NULL) return 1; dbi->dbi_api = DB_VERSION_MAJOR; /* * Get the prefix/root component and directory path. */ root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root); if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone) root = NULL; home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home); dbhome = rpmGenPath(root, home, NULL); if (dbi->dbi_temporary) { dbfile = NULL; dbsubfile = NULL; } else { #ifdef HACK /* XXX necessary to support dbsubfile */ dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename); dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : rpmTagGetName(dbi->dbi_rpmtag)); #else dbfile = (dbi->dbi_file ? dbi->dbi_file : rpmTagGetName(dbi->dbi_rpmtag)); dbsubfile = NULL; #endif } oflags = (dbi->dbi_oeflags | dbi->dbi_oflags); oflags &= ~DB_TRUNCATE; /* XXX this is dangerous */ #if 0 /* XXX rpmdb: illegal flag combination specified to DB->open */ if ( dbi->dbi_mode & O_EXCL) oflags |= DB_EXCL; #endif /* * Map open mode flags onto configured database/environment flags. */ if (dbi->dbi_temporary) { oflags |= DB_CREATE; dbi->dbi_oeflags |= DB_CREATE; oflags &= ~DB_RDONLY; dbi->dbi_oflags &= ~DB_RDONLY; } else { if ((dbi->dbi_mode & O_ACCMODE) == O_RDONLY) oflags |= DB_RDONLY; if (dbi->dbi_mode & O_CREAT) { oflags |= DB_CREATE; dbi->dbi_oeflags |= DB_CREATE; } #ifdef DANGEROUS if ( dbi->dbi_mode & O_TRUNC) oflags |= DB_TRUNCATE; #endif } /* * Create the /var/lib/rpm directory if it doesn't exist (root only). */ (void) rpmioMkpath(dbhome, 0755, getuid(), getgid()); /* * Avoid incompatible DB_CREATE/DB_RDONLY flags on DBENV->open. */ if (dbi->dbi_use_dbenv) { if (access(dbhome, W_OK) == -1) { /* dbhome is unwritable, don't attempt DB_CREATE on DB->open ... */ oflags &= ~DB_CREATE; /* ... but DBENV->open might still need DB_CREATE ... */ if (dbi->dbi_eflags & DB_PRIVATE) { dbi->dbi_eflags &= ~DB_JOINENV; } else { dbi->dbi_eflags |= DB_JOINENV; dbi->dbi_oeflags &= ~DB_CREATE; dbi->dbi_oeflags &= ~DB_THREAD; /* ... but, unless DB_PRIVATE is used, skip DBENV. */ dbi->dbi_use_dbenv = 0; } /* ... DB_RDONLY maps dbhome perms across files ... */ if (dbi->dbi_temporary) { oflags |= DB_CREATE; dbi->dbi_oeflags |= DB_CREATE; oflags &= ~DB_RDONLY; dbi->dbi_oflags &= ~DB_RDONLY; } else { oflags |= DB_RDONLY; /* ... and DB_WRITECURSOR won't be needed ... */ dbi->dbi_oflags |= DB_RDONLY; } } else { /* dbhome is writable, check for persistent dbenv. */ char * dbf = rpmGetPath(dbhome, "/__db.001", NULL); if (access(dbf, F_OK) == -1) { /* ... non-existent (or unwritable) DBENV, will create ... */ dbi->dbi_oeflags |= DB_CREATE; dbi->dbi_eflags &= ~DB_JOINENV; } else { /* ... pre-existent (or bogus) DBENV, will join ... */ if (dbi->dbi_eflags & DB_PRIVATE) { dbi->dbi_eflags &= ~DB_JOINENV; } else { dbi->dbi_eflags |= DB_JOINENV; dbi->dbi_oeflags &= ~DB_CREATE; dbi->dbi_oeflags &= ~DB_THREAD; } } dbf = _free(dbf); } } /* * Avoid incompatible DB_CREATE/DB_RDONLY flags on DB->open. */ if ((oflags & DB_CREATE) && (oflags & DB_RDONLY)) { /* dbhome is writable, and DB->open flags may conflict. */ const char * dbfn = (dbfile ? dbfile : rpmTagGetName(dbi->dbi_rpmtag)); char * dbf = rpmGetPath(dbhome, "/", dbfn, NULL); if (access(dbf, F_OK) == -1) { /* File does not exist, DB->open might create ... */ oflags &= ~DB_RDONLY; } else { /* File exists, DB->open need not create ... */ oflags &= ~DB_CREATE; } /* Only writers need DB_WRITECURSOR ... */ if (!(oflags & DB_RDONLY) && access(dbf, W_OK) == 0) { dbi->dbi_oflags &= ~DB_RDONLY; } else { dbi->dbi_oflags |= DB_RDONLY; } dbf = _free(dbf); } /* * Turn off verify-on-close if opening read-only. */ if (oflags & DB_RDONLY) dbi->dbi_verify_on_close = 0; if (dbi->dbi_use_dbenv) { if (rpmdb->db_dbenv == NULL) { rc = db_init(dbi, dbhome, dbfile, dbsubfile, &dbenv); if (rc == 0) { rpmdb->db_dbenv = dbenv; rpmdb->db_opens = 1; } } else { dbenv = rpmdb->db_dbenv; rpmdb->db_opens++; } } { char *dbiflags = prDbiOpenFlags(oflags, 0); rpmlog(RPMLOG_DEBUG, "opening db index %s/%s %s mode=0x%x\n", dbhome, (dbfile ? dbfile : rpmTagGetName(dbi->dbi_rpmtag)), dbiflags, dbi->dbi_mode); free(dbiflags); } if (rc == 0) { static int _lockdbfd = 0; rc = db_create(&db, dbenv, dbi->dbi_cflags); rc = cvtdberr(dbi, "db_create", rc, _debug); if (rc == 0 && db != NULL) { if (rc == 0 && rpmdb->db_malloc && rpmdb->db_realloc && rpmdb->db_free) { rc = db->set_alloc(db, rpmdb->db_malloc, rpmdb->db_realloc, rpmdb->db_free); rc = cvtdberr(dbi, "db->set_alloc", rc, _debug); } /* 4.1: db->set_cache_priority(???) */ if (rc == 0 && !dbi->dbi_use_dbenv && dbi->dbi_cachesize) { rc = db->set_cachesize(db, 0, dbi->dbi_cachesize, 0); rc = cvtdberr(dbi, "db->set_cachesize", rc, _debug); } /* 4.1: db->set_encrypt(???) */ /* 4.1: db->set_errcall(dbenv, rpmdb->db_errcall); */ /* 4.1: db->set_errfile(dbenv, rpmdb->db_errfile); */ /* 4.1: db->set_errpfx(dbenv, rpmdb->db_errpfx); */ /* 4.1: db->set_feedback(???) */ if (rc == 0 && dbi->dbi_lorder) { rc = db->set_lorder(db, dbi->dbi_lorder); rc = cvtdberr(dbi, "db->set_lorder", rc, _debug); } if (rc == 0 && dbi->dbi_pagesize) { rc = db->set_pagesize(db, dbi->dbi_pagesize); rc = cvtdberr(dbi, "db->set_pagesize", rc, _debug); } /* 4.1: db->set_paniccall(???) */ if (rc == 0 && oflags & DB_CREATE) { switch(dbi->dbi_type) { default: case DB_HASH: if (dbi->dbi_h_ffactor) { rc = db->set_h_ffactor(db, dbi->dbi_h_ffactor); rc = cvtdberr(dbi, "db->set_h_ffactor", rc, _debug); if (rc) break; } if (dbi->dbi_h_nelem) { rc = db->set_h_nelem(db, dbi->dbi_h_nelem); rc = cvtdberr(dbi, "db->set_h_nelem", rc, _debug); if (rc) break; } if (dbi->dbi_h_flags) { rc = db->set_flags(db, dbi->dbi_h_flags); rc = cvtdberr(dbi, "db->set_h_flags", rc, _debug); if (rc) break; } if (dbi->dbi_h_hash_fcn) { rc = db->set_h_hash(db, dbi->dbi_h_hash_fcn); rc = cvtdberr(dbi, "db->set_h_hash", rc, _debug); if (rc) break; } if (dbi->dbi_h_dup_compare_fcn) { rc = db->set_dup_compare(db, dbi->dbi_h_dup_compare_fcn); rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug); if (rc) break; } break; case DB_BTREE: /* 4.1: db->set_append_recno(???) */ if (dbi->dbi_bt_flags) { rc = db->set_flags(db, dbi->dbi_bt_flags); rc = cvtdberr(dbi, "db->set_bt_flags", rc, _debug); if (rc) break; } if (dbi->dbi_bt_minkey) { rc = db->set_bt_minkey(db, dbi->dbi_bt_minkey); rc = cvtdberr(dbi, "db->set_bt_minkey", rc, _debug); if (rc) break; } if (dbi->dbi_bt_compare_fcn) { rc = db->set_bt_compare(db, dbi->dbi_bt_compare_fcn); rc = cvtdberr(dbi, "db->set_bt_compare", rc, _debug); if (rc) break; } if (dbi->dbi_bt_dup_compare_fcn) { rc = db->set_dup_compare(db, dbi->dbi_bt_dup_compare_fcn); rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug); if (rc) break; } if (dbi->dbi_bt_prefix_fcn) { rc = db->set_bt_prefix(db, dbi->dbi_bt_prefix_fcn); rc = cvtdberr(dbi, "db->set_bt_prefix", rc, _debug); if (rc) break; } break; case DB_RECNO: if (dbi->dbi_re_delim) { /* 4.1: db->set_append_recno(???) */ rc = db->set_re_delim(db, dbi->dbi_re_delim); rc = cvtdberr(dbi, "db->set_re_selim", rc, _debug); if (rc) break; } if (dbi->dbi_re_len) { rc = db->set_re_len(db, dbi->dbi_re_len); rc = cvtdberr(dbi, "db->set_re_len", rc, _debug); if (rc) break; } if (dbi->dbi_re_pad) { rc = db->set_re_pad(db, dbi->dbi_re_pad); rc = cvtdberr(dbi, "db->set_re_pad", rc, _debug); if (rc) break; } if (dbi->dbi_re_source) { rc = db->set_re_source(db, dbi->dbi_re_source); rc = cvtdberr(dbi, "db->set_re_source", rc, _debug); if (rc) break; } break; case DB_QUEUE: if (dbi->dbi_q_extentsize) { rc = db->set_q_extentsize(db, dbi->dbi_q_extentsize); rc = cvtdberr(dbi, "db->set_q_extentsize", rc, _debug); if (rc) break; } break; } } if (rc == 0) { char * fullpath; const char * dbpath; fullpath = rpmGetPath(dbhome, "/", dbfile ? dbfile : "", NULL); #ifdef HACK /* XXX necessary to support dbsubfile */ dbpath = (!dbi->dbi_use_dbenv && !dbi->dbi_temporary) ? fullpath : dbfile; #else dbpath = (!dbi->dbi_temporary) ? fullpath : dbfile; #endif rc = (db->open)(db, txnid, dbpath, dbsubfile, dbi->dbi_type, oflags, dbi->dbi_perms); if (rc == 0 && dbi->dbi_type == DB_UNKNOWN) { DBTYPE dbi_type = DB_UNKNOWN; xx = db->get_type(db, &dbi_type); if (xx == 0) dbi->dbi_type = dbi_type; } free(fullpath); } /* XXX return rc == errno without printing */ _printit = (rc > 0 ? 0 : _debug); xx = cvtdberr(dbi, "db->open", rc, _printit); dbi->dbi_txnid = NULL; /* * Lock a file using fcntl(2). Traditionally this is Packages, * the file used to store metadata of installed header(s), * as Packages is always opened, and should be opened first, * for any rpmdb access. * * If no DBENV is used, then access is protected with a * shared/exclusive locking scheme, as always. * * With a DBENV, the fcntl(2) lock is necessary only to keep * the riff-raff from playing where they don't belong, as * the DBENV should provide it's own locking scheme. So try to * acquire a lock, but permit failures, as some other * DBENV player may already have acquired the lock. * * With NPTL posix mutexes, revert to fcntl lock on non-functioning * glibc/kernel combinations. */ if (rc == 0 && dbi->dbi_lockdbfd && !((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) && (!dbi->dbi_use_dbenv || _lockdbfd++ == 0)) { int fdno = -1; if (!(db->fd(db, &fdno) == 0 && fdno >= 0)) { rc = 1; } else { struct flock l; memset(&l, 0, sizeof(l)); l.l_whence = 0; l.l_start = 0; l.l_len = 0; l.l_type = (dbi->dbi_mode & O_ACCMODE) == O_RDONLY ? F_RDLCK : F_WRLCK; l.l_pid = 0; rc = fcntl(fdno, F_SETLK, (void *) &l); if (rc) { /* Warning iff using non-private CDB locking. */ rc = ((dbi->dbi_use_dbenv && (dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_eflags & DB_PRIVATE)) ? 0 : 1); rpmlog( (rc ? RPMLOG_ERR : RPMLOG_WARNING), _("cannot get %s lock on %s/%s\n"), ((dbi->dbi_mode & O_ACCMODE) == O_RDONLY) ? _("shared") : _("exclusive"), dbhome, (dbfile ? dbfile : "")); } else if (dbfile) { rpmlog(RPMLOG_DEBUG, "locked db index %s/%s\n", dbhome, dbfile); } } } } } dbi->dbi_db = db; if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) { dbi->dbi_vec = &db3vec; *dbip = dbi; } else { dbi->dbi_verify_on_close = 0; (void) db3close(dbi, 0); } free(dbhome); return rc; }
/** * 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 0 on success */ static int doSetupMacro(Spec spec, const char * line) /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ /*@modifies spec->buildSubdir, spec->macros, spec->prep, spec->packages->header, rpmGlobalMacroContext, fileSystem, internalState @*/ { char buf[BUFSIZ]; rpmiob before = NULL; rpmiob after = NULL; poptContext optCon; int argc; const char ** argv; int arg; const char * optArg; int rc; rpmuint32_t num; rpmRC ec = RPMRC_FAIL; /* XXX assume failure */ /*@-mods@*/ leaveDirs = skipDefaultAction = 0; createDir = quietly = 0; dirName = NULL; /*@=mods@*/ if ((rc = poptParseArgvString(line, &argc, &argv))) { rpmlog(RPMLOG_ERR, _("Error parsing %%setup: %s\n"), poptStrerror(rc)); goto exit; } before = rpmiobNew(0); after = rpmiobNew(0); optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); while ((arg = poptGetNextOpt(optCon)) > 0) { optArg = poptGetOptArg(optCon); /* We only parse -a and -b here */ if (parseNum(optArg, &num)) { rpmlog(RPMLOG_ERR, _("line %d: Bad arg to %%setup: %s\n"), spec->lineNum, (optArg ? optArg : "???")); optCon = poptFreeContext(optCon); argv = _free(argv); goto exit; } { const char *chptr = doUntar(spec, num, quietly); if (chptr == NULL) goto exit; (void) rpmiobAppend((arg == 'a' ? after : before), chptr, 1); } } if (arg < -1) { rpmlog(RPMLOG_ERR, _("line %d: Bad %%setup option %s: %s\n"), spec->lineNum, poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(arg)); optCon = poptFreeContext(optCon); argv = _free(argv); goto exit; } if (dirName) { spec->buildSubdir = xstrdup(dirName); } else { const char *N, *V; (void) headerNEVRA(spec->packages->header, &N, NULL, &V, NULL, NULL); (void) snprintf(buf, sizeof(buf), "%s-%s", N, V); buf[sizeof(buf)-1] = '\0'; N = _free(N); V = _free(V); spec->buildSubdir = xstrdup(buf); } addMacro(spec->macros, "buildsubdir", NULL, spec->buildSubdir, RMIL_SPEC); optCon = poptFreeContext(optCon); argv = _free(argv); /* cd to the build dir */ { const char * buildDirURL = rpmGenPath(spec->rootURL, "%{_builddir}", ""); const char *buildDir; (void) urlPath(buildDirURL, &buildDir); rc = rpmioMkpath(buildDir, 0755, -1, -1); sprintf(buf, "cd '%s'", buildDir); spec->prep = rpmiobAppend(spec->prep, buf, 1); buildDirURL = _free(buildDirURL); } /* delete any old sources */ if (!leaveDirs) { sprintf(buf, "rm -rf '%s'", spec->buildSubdir); spec->prep = rpmiobAppend(spec->prep, buf, 1); } /* check if source is a ruby gem */ { struct Source *sp; for (sp = spec->sources; sp != NULL; sp = sp->next) { if ((sp->flags & RPMFILE_SOURCE) && (sp->num == 0)) { break; } } if (sp != NULL) { char *t = strrchr(sp->source, '.'); if(t && !strcasecmp(t, ".gem")) createDir = 1; } } /* if necessary, create and cd into the proper dir */ if (createDir) { char *mkdir_p; mkdir_p = rpmExpand("%{?__mkdir_p}%{!?__mkdir_p:mkdir -p}", NULL); if (!mkdir_p) mkdir_p = xstrdup("mkdir -p"); sprintf(buf, "%s '%s'\ncd '%s'", mkdir_p, spec->buildSubdir, spec->buildSubdir); mkdir_p = _free(mkdir_p); spec->prep = rpmiobAppend(spec->prep, buf, 1); } /* do the default action */ if (!createDir && !skipDefaultAction) { const char *chptr = doUntar(spec, 0, quietly); if (chptr == NULL) goto exit; spec->prep = rpmiobAppend(spec->prep, chptr, 1); } spec->prep = rpmiobAppend(spec->prep, rpmiobStr(before), 0); if (!createDir) { sprintf(buf, "cd '%s'", spec->buildSubdir); spec->prep = rpmiobAppend(spec->prep, buf, 1); } if (createDir && !skipDefaultAction) { const char * chptr = doUntar(spec, 0, quietly); if (chptr == NULL) goto exit; spec->prep = rpmiobAppend(spec->prep, chptr, 1); } spec->prep = rpmiobAppend(spec->prep, rpmiobStr(after), 0); /* XXX FIXME: owner & group fixes were conditioned on !geteuid() */ /* Fix the owner, group, and permissions of the setup build tree */ { /*@observer@*/ static const char *fixmacs[] = { "%{_fixowner}", "%{_fixgroup}", "%{_fixperms}", NULL }; const char ** fm; for (fm = fixmacs; *fm; fm++) { const char *fix; fix = rpmExpand(*fm, " .", NULL); if (fix && *fix != '%') spec->prep = rpmiobAppend(spec->prep, fix, 1); fix = _free(fix); } } ec = RPMRC_OK; exit: before = rpmiobFree(before); after = rpmiobFree(after); return ec; }