Ejemplo n.º 1
0
Archivo: annotate.c Proyecto: dpl0/pkg
static struct sbuf *
read_input(void)
{
	struct sbuf	*input;
	int		 ch;

	input = sbuf_new_auto();

	for (;;) {
		ch = getc(stdin);
		if (ch == EOF) {
			if (feof(stdin))
				break;
			if (ferror(stdin))
				err(EX_NOINPUT, "Failed to read stdin");
		}
		sbuf_putc(input, ch);
	}
#ifdef __DragonFly__
	sbuf_finish(input);
#else
	if (sbuf_finish(input) != 0)
		err(EX_DATAERR, "Could not read value data");
#endif

	return (input);
}
Ejemplo n.º 2
0
/* construct path to node->name */
static char *
mtree_file_path(fsnode *node)
{
	fsnode *pnode;
	struct sbuf *sb;
	char *res, *rp[MAKEFS_MAX_TREE_DEPTH];
	int depth;

	depth = 0;
	rp[depth] = node->name;
	for (pnode = node->parent; pnode && depth < MAKEFS_MAX_TREE_DEPTH;
	     pnode = pnode->parent) {
		if (strcmp(pnode->name, ".") == 0)
			break;
		rp[++depth] = pnode->name;
	}
	
	sb = sbuf_new_auto();
	if (sb == NULL) {
		errno = ENOMEM;
		return (NULL);
	}
	while (depth > 0) {
		sbuf_cat(sb, rp[depth--]);
		sbuf_putc(sb, '/');
	}
	sbuf_cat(sb, rp[depth]);
	sbuf_finish(sb);
	res = strdup(sbuf_data(sb));
	sbuf_delete(sb);
	if (res == NULL)
		errno = ENOMEM;
	return res;

}
Ejemplo n.º 3
0
void
vfs_mountroot(void)
{
	struct mount *mp;
	struct sbuf *sb;
	struct thread *td;
	time_t timebase;
	int error;

	td = curthread;

	vfs_mountroot_wait();

	sb = sbuf_new_auto();
	vfs_mountroot_conf0(sb);
	sbuf_finish(sb);

	error = vfs_mountroot_devfs(td, &mp);
	while (!error) {
		error = vfs_mountroot_parse(sb, mp);
		if (!error) {
			error = vfs_mountroot_shuffle(td, mp);
			if (!error) {
				sbuf_clear(sb);
				error = vfs_mountroot_readconf(td, sb);
				sbuf_finish(sb);
			}
		}
	}

	sbuf_delete(sb);

	/*
	 * Iterate over all currently mounted file systems and use
	 * the time stamp found to check and/or initialize the RTC.
	 * Call inittodr() only once and pass it the largest of the
	 * timestamps we encounter.
	 */
	timebase = 0;
	mtx_lock(&mountlist_mtx);
	mp = TAILQ_FIRST(&mountlist);
	while (mp != NULL) {
		if (mp->mnt_time > timebase)
			timebase = mp->mnt_time;
		mp = TAILQ_NEXT(mp, mnt_list);
	}
	mtx_unlock(&mountlist_mtx);
	inittodr(timebase);

	/* Keep prison0's root in sync with the global rootvnode. */
	mtx_lock(&prison0.pr_mtx);
	prison0.pr_root = rootvnode;
	vref(prison0.pr_root);
	mtx_unlock(&prison0.pr_mtx);

	mtx_lock(&mountlist_mtx);
	atomic_store_rel_int(&root_mount_complete, 1);
	wakeup(&root_mount_complete);
	mtx_unlock(&mountlist_mtx);
}
Ejemplo n.º 4
0
static void
khttpd_ktr_logging_main(void *arg)
{
	struct sbuf *sbuf;
	struct thread *td;
	int error;

	KHTTPD_ASSERT_CURPROC_IS_KHTTPD();

	td = curthread;

	khttpd_ktr_logging_idx = ktr_idx;

	error = kern_openat(td, AT_FDCWD, KHTTPD_KTR_FILE, UIO_SYSSPACE,
	    O_CREAT | O_TRUNC | O_WRONLY, 0666);
	if (error != 0) {
		log(LOG_WARNING, "khttpd: failed to open ktr file '%s' "
		    "(error %d)", KHTTPD_KTR_FILE, error);
		goto quit;
	}
	kern_close(td, td->td_retval[0]);

	sbuf = sbuf_new_auto();

	while (!khttpd_ktr_logging_shutdown) {
		khttpd_ktr_logging(sbuf);
		pause("khttpd-ktr-flush", hz);
	}

	sbuf_delete(sbuf);

quit:
	khttpd_ktr_logging_thread = NULL;
	kthread_exit();
}
Ejemplo n.º 5
0
Archivo: utils.c Proyecto: baloo/pkgng
void
sbuf_init(struct sbuf **buf)
{
	if (*buf == NULL)
		*buf = sbuf_new_auto();
	else
		sbuf_clear(*buf);
}
Ejemplo n.º 6
0
int
pkg_script_run(struct pkg *pkg, pkg_script_t type)
{
	struct pkg_script *script = NULL;
	pkg_script_t stype;
	struct sbuf *script_cmd = sbuf_new_auto();
	size_t i;

	struct {
		const char *arg;
		const pkg_script_t b;
		const pkg_script_t a;
	} const map[] = {
		/* a implies b with argument arg */
		{"PRE-INSTALL",    PKG_SCRIPT_INSTALL,   PKG_SCRIPT_PRE_INSTALL},
		{"POST-INSTALL",   PKG_SCRIPT_INSTALL,   PKG_SCRIPT_POST_INSTALL},
		{"PRE-UPGRADE",    PKG_SCRIPT_UPGRADE,   PKG_SCRIPT_PRE_UPGRADE},
		{"POST-UPGRADE",   PKG_SCRIPT_UPGRADE,   PKG_SCRIPT_POST_UPGRADE},
		{"DEINSTALL",      PKG_SCRIPT_DEINSTALL, PKG_SCRIPT_PRE_DEINSTALL},
		{"POST-DEINSTALL", PKG_SCRIPT_DEINSTALL, PKG_SCRIPT_POST_DEINSTALL},
	};

	for (i = 0; i < sizeof(map) / sizeof(map[0]); i++) {
		if (map[i].a == type)
			break;
	}

	if (map[i].a != type)
		return (ERROR_BAD_ARG("type"));

	while (pkg_scripts(pkg, &script) == EPKG_OK) {

		stype = pkg_script_type(script);

		if (stype == map[i].a || stype == map[i].b) {
			sbuf_reset(script_cmd);
			sbuf_printf(script_cmd, "PKG_PREFIX=%s\nset -- %s-%s",
				pkg_get(pkg, PKG_PREFIX), pkg_get(pkg, PKG_NAME),
				pkg_get(pkg, PKG_VERSION));

			if (stype == map[i].b) {
				/* add arg **/
				sbuf_cat(script_cmd, " ");
				sbuf_cat(script_cmd, map[i].arg);
			}

			sbuf_cat(script_cmd, "\n");
			sbuf_cat(script_cmd, pkg_script_data(script));
			sbuf_finish(script_cmd);
			system(sbuf_data(script_cmd));

		}
	}

	sbuf_delete(script_cmd);

	return (EPKG_OK);
}
Ejemplo n.º 7
0
int
pkg_delete(struct pkg *pkg, struct pkgdb *db, int force)
{
	struct pkg **rdeps;
	int i, ret;
	struct sbuf *rdep_msg;

	if (pkg == NULL)
		return (ERROR_BAD_ARG("pkg"));

	if (db == NULL)
		return (ERROR_BAD_ARG("db"));

	/*
	 * Ensure that we have all the informations we need
	 */
	if ((ret = pkgdb_loadrdeps(db, pkg)) != EPKG_OK)
		return (ret);
	if ((ret = pkgdb_loadfiles(db, pkg)) != EPKG_OK)
		return (ret);
	if ((ret = pkgdb_loadscripts(db, pkg)) != EPKG_OK)
		return (ret);
	if ((ret = pkgdb_loadmtree(db, pkg)) != EPKG_OK)
		return (ret);

	rdeps = pkg_rdeps(pkg);

	if (rdeps[0] != NULL) {
		rdep_msg = sbuf_new_auto();
		sbuf_printf(rdep_msg, "%s-%s is required by other packages:", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION));
		for (i = 0;rdeps[i] != NULL; i++) {
			sbuf_cat(rdep_msg, " ");
			sbuf_printf(rdep_msg, "%s-%s", pkg_get(rdeps[i], PKG_NAME), pkg_get(rdeps[i], PKG_VERSION));
		}
		if (!force) {
			sbuf_finish(rdep_msg);
			ret = pkg_error_set(EPKG_REQUIRED, "%s", sbuf_get(rdep_msg));
			sbuf_free(rdep_msg);
			return ret;
		}
		sbuf_cat(rdep_msg, ", deleting anyway");
		sbuf_finish(rdep_msg);
		fprintf(stderr, "%s\n", sbuf_get(rdep_msg));
		sbuf_free(rdep_msg);
	}

	if ((ret = pkg_script_pre_deinstall(pkg)) != EPKG_OK)
		return (ret);

	if ((ret = pkg_delete_files(pkg, force)) != EPKG_OK)
		return (ret);

	if ((ret = pkg_script_post_deinstall(pkg)) != EPKG_OK)
		return (ret);

	return (pkgdb_unregister_pkg(db, pkg_get(pkg, PKG_ORIGIN)));
}
Ejemplo n.º 8
0
Archivo: add.c Proyecto: culot/pkgng
int
exec_add(int argc, char **argv)
{
    struct pkgdb *db = NULL;
    struct sbuf *failedpkgs = sbuf_new_auto();
    char path[MAXPATHLEN + 1];
    char *file;
    int retcode = EPKG_OK;
    int i;
    int failedpkgcount = 0;
    struct pkg *p = NULL;

    if (argc < 2) {
        usage_add();
        return (EX_USAGE);
    }

    if (geteuid() != 0) {
        warnx("adding packages can only be done as root");
        return (EX_NOPERM);
    }

    if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
        return (EX_IOERR);
    }

    for (i = 1; i < argc; i++) {
        if (is_url(argv[i]) == EPKG_OK) {
            snprintf(path, sizeof(path), "./%s", basename(argv[i]));
            if ((retcode = pkg_fetch_file(argv[i], path)) != EPKG_OK)
                break;

            file = path;
        } else
            file = argv[i];

        pkg_open(&p, file, NULL);

        if ((retcode = pkg_add(db, file, 0)) != EPKG_OK) {
            sbuf_cat(failedpkgs, argv[i]);
            if (i != argc - 1)
                sbuf_printf(failedpkgs, ", ");
            failedpkgcount++;
        }

    }

    pkgdb_close(db);

    if(failedpkgcount > 0) {
        sbuf_finish(failedpkgs);
        printf("Failed to install the following %d package(s): %s.\n", failedpkgcount, sbuf_data(failedpkgs));
    }
    sbuf_delete(failedpkgs);

    return (retcode == EPKG_OK ? EX_OK : EX_SOFTWARE);
}
Ejemplo n.º 9
0
struct pkgdb_it *
pkgdb_rquery_provide(struct pkgdb *db, const char *provide, const char *repo)
{
	sqlite3_stmt	*stmt;
	struct sbuf	*sql = NULL;
	const char	*reponame = NULL;
	int		 ret;
	const char	 basesql[] = ""
			"SELECT p.id, p.origin, p.name, p.version, p.comment, "
			"p.name || '~' || p.origin as uniqueid, "
			"p.prefix, p.desc, p.arch, p.maintainer, p.www, "
			"p.licenselogic, p.flatsize, p.pkgsize, "
			"p.cksum, p.manifestdigest, p.path AS repopath, '%1$s' AS dbname "
			"FROM '%1$s'.packages AS p, '%1$s'.pkg_provides AS pp, "
			"'%1$s'.provides AS pr "
			"WHERE p.id = pp.package_id "
			"AND pp.provide_id = pr.id "
			"AND pr.name = ?1;";

	assert(db != NULL);
	reponame = pkgdb_get_reponame(db, repo);

	sql = sbuf_new_auto();
	/*
	 * Working on multiple remote repositories
	 */
	if (reponame == NULL) {
		/* duplicate the query via UNION for all the attached
		 * databases */

		ret = pkgdb_sql_all_attached(db->sqlite, sql,
				basesql, " UNION ALL ");
		if (ret != EPKG_OK) {
			sbuf_delete(sql);
			return (NULL);
		}
	} else
		sbuf_printf(sql, basesql, reponame);

	sbuf_finish(sql);

	pkg_debug(4, "Pkgdb: running '%s'", sbuf_get(sql));
	ret = sqlite3_prepare_v2(db->sqlite, sbuf_get(sql), -1, &stmt, NULL);
	if (ret != SQLITE_OK) {
		ERROR_SQLITE(db->sqlite, sbuf_get(sql));
		sbuf_delete(sql);
		return (NULL);
	}

	sbuf_delete(sql);

	sqlite3_bind_text(stmt, 1, provide, -1, SQLITE_TRANSIENT);

	return (pkgdb_it_new(db, stmt, PKG_REMOTE, PKGDB_IT_FLAG_ONCE));
}
Ejemplo n.º 10
0
int
format_exec_cmd(char **dest, const char *in, const char *prefix, const char *plist_file)
{
	struct sbuf *buf = sbuf_new_auto();
	char path[MAXPATHLEN + 1];
	char *cp;

	while (in[0] != '\0') {
		if (in[0] == '%') {
			in++;
			switch(in[0]) {
				case 'D':
					sbuf_cat(buf, prefix);
					break;
				case 'F':
					sbuf_cat(buf, plist_file);
					break;
				case 'f':
					if (prefix[strlen(prefix) - 1] == '/')
						snprintf(path, sizeof(path), "%s%s", prefix, plist_file);
					else
						snprintf(path, sizeof(path), "%s/%s", prefix, plist_file);
					cp = strrchr(path, '/');
					cp ++;
					sbuf_cat(buf, cp);
					break;
				case 'B':
					if (prefix[strlen(prefix) - 1] == '/')
						snprintf(path, sizeof(path), "%s%s", prefix, plist_file);
					else
						snprintf(path, sizeof(path), "%s/%s", prefix, plist_file);
					cp = strrchr(path, '/');
					cp[0] = '\0';
					sbuf_cat(buf, path);
					break;
				default:
					sbuf_putc(buf, in[0]);
					break;
			}

		} else {
			sbuf_putc(buf, in[0]);
		}

		in++;
	}

	sbuf_finish(buf);
	*dest = strdup(sbuf_data(buf));
	sbuf_free(buf);
	
	return (0);
}
Ejemplo n.º 11
0
int
packing_append_tree(struct packing *pack, const char *treepath,
    const char *newroot)
{
	FTS *fts = NULL;
	FTSENT *fts_e = NULL;
	size_t treelen;
	struct sbuf *sb;
	char *paths[2] = { __DECONST(char *, treepath), NULL };

	treelen = strlen(treepath);
	fts = fts_open(paths, FTS_PHYSICAL | FTS_XDEV, NULL);
	if (fts == NULL)
		goto cleanup;

	sb = sbuf_new_auto();
	while ((fts_e = fts_read(fts)) != NULL) {
		switch(fts_e->fts_info) {
		case FTS_D:
		case FTS_DEFAULT:
		case FTS_F:
		case FTS_SL:
		case FTS_SLNONE:
			 /* Entries not within this tree are irrelevant. */
			 if (fts_e->fts_pathlen <= treelen)
				  break;
			 sbuf_clear(sb);
			 /* Strip the prefix to obtain the target path */
			 if (newroot) /* Prepend a root if one is specified */
				  sbuf_cat(sb, newroot);
			 /* +1 = skip trailing slash */
			 sbuf_cat(sb, fts_e->fts_path + treelen + 1);
			 sbuf_finish(sb);
			 packing_append_file(pack, fts_e->fts_name,
			    sbuf_get(sb));
			 break;
		case FTS_DC:
		case FTS_DNR:
		case FTS_ERR:
		case FTS_NS:
			 /* XXX error cases, check fts_e->fts_errno and
			  *     bubble up the call chain */
			 break;
		default:
			 break;
		}
	}
	sbuf_free(sb);
cleanup:
	fts_close(fts);
	return EPKG_OK;
}
Ejemplo n.º 12
0
Archivo: utils.c Proyecto: baloo/pkgng
int
sbuf_set(struct sbuf **buf, const char *str)
{
	if (*buf == NULL)
		*buf = sbuf_new_auto();

	if (str == NULL)
		return (-1);

	sbuf_cpy(*buf, str);
	sbuf_finish(*buf);
	return (0);
}
Ejemplo n.º 13
0
Archivo: query.c Proyecto: baitisj/pkg
int64_t
pkg_repo_binary_stat(struct pkg_repo *repo, pkg_stats_t type)
{
	sqlite3 *sqlite = PRIV_GET(repo);
	sqlite3_stmt	*stmt = NULL;
	int64_t		 stats = 0;
	struct sbuf	*sql = NULL;
	int		 ret;

	sql = sbuf_new_auto();

	switch(type) {
	case PKG_STATS_LOCAL_COUNT:
		goto out;
		break;
	case PKG_STATS_LOCAL_SIZE:
		goto out;
		break;
	case PKG_STATS_REMOTE_UNIQUE:
		sbuf_printf(sql, "SELECT COUNT(id) FROM main.packages;");
		break;
	case PKG_STATS_REMOTE_COUNT:
		sbuf_printf(sql, "SELECT COUNT(id) FROM main.packages;");
		break;
	case PKG_STATS_REMOTE_SIZE:
		sbuf_printf(sql, "SELECT SUM(pkgsize) FROM main.packages;");
		break;
	case PKG_STATS_REMOTE_REPOS:
		goto out;
		break;
	}

	sbuf_finish(sql);
	pkg_debug(4, "binary_repo: running '%s'", sbuf_data(sql));
	ret = sqlite3_prepare_v2(sqlite, sbuf_data(sql), -1, &stmt, NULL);
	if (ret != SQLITE_OK) {
		ERROR_SQLITE(sqlite, sbuf_data(sql));
		goto out;
	}

	while (sqlite3_step(stmt) != SQLITE_DONE) {
		stats = sqlite3_column_int64(stmt, 0);
	}

out:
	sbuf_free(sql);
	if (stmt != NULL)
		sqlite3_finalize(stmt);

	return (stats);
}
Ejemplo n.º 14
0
void
khttpd_ktr_logging_fini(void)
{
	struct sbuf *sbuf;

	KHTTPD_ASSERT_CURPROC_IS_KHTTPD();

	khttpd_ktr_logging_shutdown = TRUE;
	while (khttpd_ktr_logging_thread != NULL)
		pause("khttpd-ktr-flush-fini", hz);

	sbuf = sbuf_new_auto();
	khttpd_ktr_logging(sbuf);
	sbuf_delete(sbuf);
}
Ejemplo n.º 15
0
/*------- API comments for these methods can be found in xenstorevar.h -------*/
struct sbuf *
xs_join(const char *dir, const char *name)
{
	struct sbuf *sb;

	sb = sbuf_new_auto();
	sbuf_cat(sb, dir);
	if (name[0] != '\0') {
		sbuf_putc(sb, '/');
		sbuf_cat(sb, name);
	}
	sbuf_finish(sb);

	return (sb);
}
Ejemplo n.º 16
0
Archivo: query.c Proyecto: baitisj/pkg
struct pkg_repo_it *
pkg_repo_binary_query(struct pkg_repo *repo, const char *pattern, match_t match)
{
	sqlite3 *sqlite = PRIV_GET(repo);
	sqlite3_stmt	*stmt = NULL;
	struct sbuf	*sql = NULL;
	const char	*comp = NULL;
	int		 ret;
	char		 basesql[BUFSIZ] = ""
		"SELECT id, origin, name, name as uniqueid, version, comment, "
		"prefix, desc, arch, maintainer, www, "
		"licenselogic, flatsize, pkgsize, "
		"cksum, manifestdigest, path AS repopath, '%s' AS dbname "
		"FROM packages AS p";

	if (match != MATCH_ALL && (pattern == NULL || pattern[0] == '\0'))
		return (NULL);

	sql = sbuf_new_auto();
	comp = pkgdb_get_pattern_query(pattern, match);
	if (comp && comp[0])
		strlcat(basesql, comp, sizeof(basesql));

	sbuf_printf(sql, basesql, repo->name);

	sbuf_cat(sql, " ORDER BY name;");
	sbuf_finish(sql);

	pkg_debug(4, "Pkgdb: running '%s' query for %s", sbuf_data(sql),
	     pattern == NULL ? "all": pattern);
	ret = sqlite3_prepare_v2(sqlite, sbuf_data(sql), sbuf_len(sql), &stmt,
	    NULL);
	if (ret != SQLITE_OK) {
		ERROR_SQLITE(sqlite, sbuf_data(sql));
		sbuf_delete(sql);
		return (NULL);
	}

	sbuf_delete(sql);

	if (match != MATCH_ALL && match != MATCH_CONDITION)
		sqlite3_bind_text(stmt, 1, pattern, -1, SQLITE_TRANSIENT);

	return (pkg_repo_binary_it_new(repo, stmt, PKGDB_IT_FLAG_ONCE));
}
Ejemplo n.º 17
0
Archivo: query.c Proyecto: baitisj/pkg
struct pkg_repo_it *
pkg_repo_binary_search(struct pkg_repo *repo, const char *pattern, match_t match,
    pkgdb_field field, pkgdb_field sort)
{
	sqlite3 *sqlite = PRIV_GET(repo);
	sqlite3_stmt	*stmt = NULL;
	struct sbuf	*sql = NULL;
	int		 ret;
	const char	*multireposql = ""
		"SELECT id, origin, name, version, comment, "
		"prefix, desc, arch, maintainer, www, "
		"licenselogic, flatsize, pkgsize, "
		"cksum, path AS repopath, '%1$s' AS dbname, '%2$s' AS repourl "
		"FROM packages ";

	if (pattern == NULL || pattern[0] == '\0')
		return (NULL);

	sql = sbuf_new_auto();
	sbuf_printf(sql, multireposql, repo->name, repo->url);

	/* close the UNIONs and build the search query */
	sbuf_cat(sql, "WHERE ");

	pkg_repo_binary_build_search_query(sql, match, field, sort);
	sbuf_cat(sql, ";");
	sbuf_finish(sql);

	pkg_debug(4, "Pkgdb: running '%s'", sbuf_data(sql));
	ret = sqlite3_prepare_v2(sqlite, sbuf_data(sql), -1, &stmt, NULL);
	if (ret != SQLITE_OK) {
		ERROR_SQLITE(sqlite, sbuf_data(sql));
		sbuf_delete(sql);
		return (NULL);
	}

	sbuf_delete(sql);

	sqlite3_bind_text(stmt, 1, pattern, -1, SQLITE_TRANSIENT);

	return (pkg_repo_binary_it_new(repo, stmt, PKGDB_IT_FLAG_ONCE));
}
Ejemplo n.º 18
0
static int
urlencode(const char *src, struct sbuf **dest)
{
	size_t len;
	size_t i;

	if (*dest == NULL)
		*dest = sbuf_new_auto();
	else
		sbuf_clear(*dest);

	len = strlen(src);
	for (i = 0; i < len; i++) {
		if (!isascii(src[i]) || src[i] == '%')
			sbuf_printf(*dest, "%%%.2x", (unsigned char)src[i]);
		else
			sbuf_putc(*dest, src[i]);
	}
	sbuf_finish(*dest);

	return (EPKG_OK);
}
Ejemplo n.º 19
0
static int
urldecode(const char *src, struct sbuf **dest)
{
	size_t len;
	size_t i;
	char c;
	char hex[] = {'\0', '\0', '\0'};

	if (*dest == NULL)
		*dest = sbuf_new_auto();
	else
		sbuf_reset(*dest);

	len = strlen(src);
	for (i = 0; i < len; i++) {
		if (src[i] != '%') {
			sbuf_putc(*dest, src[i]);
		} else {
			if (i + 2 > len) {
				pkg_emit_error("unexpected end of string");
				return (EPKG_FATAL);
			}

			hex[0] = src[++i];
			hex[1] = src[++i];
			errno = 0;
			c = strtol(hex, NULL, 16);
			if (errno != 0) {
				pkg_emit_errno("strtol()", hex);
				return (EPKG_FATAL);
			}
			sbuf_putc(*dest, c);
		}
	}
	sbuf_finish(*dest);

	return (EPKG_OK);
}
Ejemplo n.º 20
0
Archivo: query.c Proyecto: baitisj/pkg
struct pkg_repo_it *
pkg_repo_binary_shlib_require(struct pkg_repo *repo, const char *provide)
{
	sqlite3_stmt	*stmt;
	sqlite3 *sqlite = PRIV_GET(repo);
	struct sbuf	*sql = NULL;
	int		 ret;
	const char	 basesql[] = ""
			"SELECT p.id, p.origin, p.name, p.version, p.comment, "
			"p.name as uniqueid, "
			"p.prefix, p.desc, p.arch, p.maintainer, p.www, "
			"p.licenselogic, p.flatsize, p.pkgsize, "
			"p.cksum, p.manifestdigest, p.path AS repopath, '%s' AS dbname "
			"FROM packages AS p INNER JOIN pkg_shlibs_required AS ps ON "
			"p.id = ps.package_id "
			"WHERE ps.shlib_id = (SELECT id FROM shlibs WHERE name=?1);";

	sql = sbuf_new_auto();
	sbuf_printf(sql, basesql, repo->name);

	sbuf_finish(sql);

	pkg_debug(4, "Pkgdb: running '%s'", sbuf_data(sql));
	ret = sqlite3_prepare_v2(sqlite, sbuf_data(sql), -1, &stmt, NULL);
	if (ret != SQLITE_OK) {
		ERROR_SQLITE(sqlite, sbuf_data(sql));
		sbuf_delete(sql);
		return (NULL);
	}

	sbuf_delete(sql);

	pkg_debug(1, "> loading provides");
	sqlite3_bind_text(stmt, 1, provide, -1, SQLITE_TRANSIENT);

	return (pkg_repo_binary_it_new(repo, stmt, PKGDB_IT_FLAG_ONCE));
}
Ejemplo n.º 21
0
Archivo: utils.c Proyecto: varju/pkgng
struct sbuf *
exec_buf(const char *cmd) {
	FILE *fp;
	char buf[BUFSIZ];
	struct sbuf *res;

	if ((fp = popen(cmd, "r")) == NULL)
		return (NULL);

	res = sbuf_new_auto();
	while (fgets(buf, BUFSIZ, fp) != NULL)
		sbuf_cat(res, buf);

	pclose(fp);

	if (sbuf_len(res) == 0) {
		sbuf_delete(res);
		return (NULL);
	}

	sbuf_finish(res);

	return (res);
}
Ejemplo n.º 22
0
Archivo: utils.c Proyecto: baitisj/pkg
bool
ucl_object_emit_sbuf(const ucl_object_t *obj, enum ucl_emitter emit_type,
                     struct sbuf **buf)
{
	bool ret = false;
	struct ucl_emitter_functions func = {
		.ucl_emitter_append_character = ucl_sbuf_append_character,
		.ucl_emitter_append_len = ucl_sbuf_append_len,
		.ucl_emitter_append_int = ucl_sbuf_append_int,
		.ucl_emitter_append_double = ucl_sbuf_append_double
	};

	if (*buf == NULL)
		*buf = sbuf_new_auto();
	else
		sbuf_clear(*buf);

	func.ud = *buf;

	ret = ucl_object_emit_full(obj, emit_type, &func);
	sbuf_finish(*buf);

	return (ret);
}
Ejemplo n.º 23
0
static void
subst_packagesite(const char *abi)
{
	struct sbuf *newval;
	const char *variable_string;
	const char *oldval;

	if (c[PACKAGESITE].value != NULL)
		oldval = c[PACKAGESITE].value;
	else
		oldval = c[PACKAGESITE].val;

	if ((variable_string = strstr(oldval, "${ABI}")) == NULL)
		return;

	newval = sbuf_new_auto();
	sbuf_bcat(newval, oldval, variable_string - oldval);
	sbuf_cat(newval, abi);
	sbuf_cat(newval, variable_string + strlen("${ABI}"));
	sbuf_finish(newval);

	free(c[PACKAGESITE].value);
	c[PACKAGESITE].value = strdup(sbuf_data(newval));
}
Ejemplo n.º 24
0
/* mtree_resolve() sets errno to indicate why NULL was returned. */
static char *
mtree_resolve(const char *spec, int *istemp)
{
	struct sbuf *sb;
	char *res, *var;
	const char *base, *p, *v;
	size_t len;
	int c, error, quoted, subst;

	len = strlen(spec);
	if (len == 0) {
		errno = EINVAL;
		return (NULL);
	}

	c = (len > 1) ? (spec[0] == spec[len - 1]) ? spec[0] : 0 : 0;
	*istemp = (c == '`') ? 1 : 0;
	subst = (c == '`' || c == '"') ? 1 : 0;
	quoted = (subst || c == '\'') ? 1 : 0;

	if (!subst) {
		res = strdup(spec + quoted);
		if (res != NULL && quoted)
			res[len - 2] = '\0';
		return (res);
	}

	sb = sbuf_new_auto();
	if (sb == NULL) {
		errno = ENOMEM;
		return (NULL);
	}

	base = spec + 1;
	len -= 2;
	error = 0;
	while (len > 0) {
		p = strchr(base, '$');
		if (p == NULL) {
			sbuf_bcat(sb, base, len);
			base += len;
			len = 0;
			continue;
		}
		/* The following is safe. spec always starts with a quote. */
		if (p[-1] == '\\')
			p--;
		if (base != p) {
			sbuf_bcat(sb, base, p - base);
			len -= p - base;
			base = p;
		}
		if (*p == '\\') {
			sbuf_putc(sb, '$');
			base += 2;
			len -= 2;
			continue;
		}
		/* Skip the '$'. */
		base++;
		len--;
		/* Handle ${X} vs $X. */
		v = base;
		if (*base == '{') {
			p = strchr(v, '}');
			if (p == NULL)
				p = v;
		} else
			p = v;
		len -= (p + 1) - base;
		base = p + 1;

		if (v == p) {
			sbuf_putc(sb, *v);
			continue;
		}

		error = ENOMEM;
		var = calloc(p - v, 1);
		if (var == NULL)
			break;

		memcpy(var, v + 1, p - v - 1);
		if (strcmp(var, ".CURDIR") == 0) {
			res = getcwd(NULL, 0);
			if (res == NULL)
				break;
		} else if (strcmp(var, ".PROG") == 0) {
			res = strdup(getprogname());
			if (res == NULL)
				break;
		} else {
			v = getenv(var);
			if (v != NULL) {
				res = strdup(v);
				if (res == NULL)
					break;
			} else
				res = NULL;
		}
		error = 0;

		if (res != NULL) {
			sbuf_cat(sb, res);
			free(res);
		}
		free(var);
	}

	sbuf_finish(sb);
	res = (error == 0) ? strdup(sbuf_data(sb)) : NULL;
	sbuf_delete(sb);
	if (res == NULL)
		errno = ENOMEM;
	return (res);
}
Ejemplo n.º 25
0
static int
pkg_create_from_dir(struct pkg *pkg, const char *root,
    struct packing *pkg_archive)
{
	char		 fpath[MAXPATHLEN];
	struct pkg_file	*file = NULL;
	struct pkg_dir	*dir = NULL;
	char		*m;
	int		 ret;
	const char	*mtree;
	bool		 developer;
	struct stat	 st;
	char		 sha256[SHA256_DIGEST_LENGTH * 2 + 1];
	int64_t		 flatsize = 0;
	ucl_object_t	*obj;

	if (pkg_is_valid(pkg) != EPKG_OK) {
		pkg_emit_error("the package is not valid");
		return (EPKG_FATAL);
	}

	obj = pkg_annotation_lookup(pkg, "relocated");

	/*
	 * Get / compute size / checksum if not provided in the manifest
	 */
	while (pkg_files(pkg, &file) == EPKG_OK) {
		const char *pkg_path = pkg_file_path(file);
		const char *pkg_sum = pkg_file_cksum(file);

		snprintf(fpath, sizeof(fpath), "%s%s%s", root ? root : "",
		    obj ? pkg_object_string(obj) : "", pkg_path);

		if (lstat(fpath, &st) != 0 || S_ISLNK(st.st_mode))
			continue;

		if (file->size == 0)
			file->size = (int64_t)st.st_size;
		flatsize += file->size;

		if (pkg_sum == NULL || pkg_sum[0] == '\0') {
			if (pkg->type == PKG_OLD_FILE) {
				if (md5_file(fpath, sha256) != EPKG_OK)
					return (EPKG_FATAL);
			} else {
				if (sha256_file(fpath, sha256) != EPKG_OK)
					return (EPKG_FATAL);
			}
			strlcpy(file->sum, sha256, sizeof(file->sum));
		}
	}
	pkg_set(pkg, PKG_FLATSIZE, flatsize);

	if (pkg->type == PKG_OLD_FILE) {
		const char *desc, *display, *comment;
		char oldcomment[BUFSIZ];

		pkg_old_emit_content(pkg, &m);
		packing_append_buffer(pkg_archive, m, "+CONTENTS", strlen(m));
		free(m);

		pkg_get(pkg, PKG_DESC, &desc, PKG_MESSAGE, &display, PKG_COMMENT, &comment);
		packing_append_buffer(pkg_archive, desc, "+DESC", strlen(desc));
		packing_append_buffer(pkg_archive, display, "+DISPLAY", strlen(display));
		snprintf(oldcomment, sizeof(oldcomment), "%s\n", comment);
		packing_append_buffer(pkg_archive, oldcomment, "+COMMENT", strlen(oldcomment));
	} else {
		/*
		 * Register shared libraries used by the package if
		 * SHLIBS enabled in conf.  Deletes shlib info if not.
		 */
		struct sbuf *b = sbuf_new_auto();

		pkg_register_shlibs(pkg, root);

		pkg_emit_manifest_sbuf(pkg, b, PKG_MANIFEST_EMIT_COMPACT, NULL);
		packing_append_buffer(pkg_archive, sbuf_data(b), "+COMPACT_MANIFEST", sbuf_len(b));
		sbuf_clear(b);
		pkg_emit_manifest_sbuf(pkg, b, 0, NULL);
		sbuf_finish(b);
		packing_append_buffer(pkg_archive, sbuf_data(b), "+MANIFEST", sbuf_len(b));
		sbuf_delete(b);
	}

	pkg_get(pkg, PKG_MTREE, &mtree);
	if (mtree != NULL)
		packing_append_buffer(pkg_archive, mtree, "+MTREE_DIRS",
		    strlen(mtree));

	while (pkg_files(pkg, &file) == EPKG_OK) {
		const char *pkg_path = pkg_file_path(file);

		snprintf(fpath, sizeof(fpath), "%s%s%s", root ? root : "",
		    obj ? pkg_object_string(obj) : "", pkg_path);

		ret = packing_append_file_attr(pkg_archive, fpath, pkg_path,
		    file->uname, file->gname, file->perm);
		developer = pkg_object_bool(pkg_config_get("DEVELOPER_MODE"));
		if (developer && ret != EPKG_OK)
			return (ret);
	}

	while (pkg_dirs(pkg, &dir) == EPKG_OK) {
		const char *pkg_path = pkg_dir_path(dir);

		snprintf(fpath, sizeof(fpath), "%s%s%s", root ? root : "",
		    obj ? pkg_object_string(obj) : "", pkg_path);

		ret = packing_append_file_attr(pkg_archive, fpath, pkg_path,
		    dir->uname, dir->gname, dir->perm);
		developer = pkg_object_bool(pkg_config_get("DEVELOPER_MODE"));
		if (developer && ret != EPKG_OK)
			return (ret);
	}

	return (EPKG_OK);
}
Ejemplo n.º 26
0
Archivo: utils.c Proyecto: baloo/pkgng
int
format_exec_cmd(char **dest, const char *in, const char *prefix, const char *plist_file, char *line)
{
	struct sbuf *buf = sbuf_new_auto();
	char path[MAXPATHLEN + 1];
	char *cp;

	while (in[0] != '\0') {
		if (in[0] == '%') {
			in++;
			switch(in[0]) {
				case 'D':
					sbuf_cat(buf, prefix);
					break;
				case 'F':
					if (plist_file == NULL) {
						pkg_emit_error("No files defined %%F couldn't be expanded, ignoring %s", in);
						sbuf_finish(buf);
						sbuf_free(buf);
						return (EPKG_FATAL);
					}
					sbuf_cat(buf, plist_file);
					break;
				case 'f':
					if (plist_file == NULL) {
						pkg_emit_error("No files defined %%f couldn't be expanded, ignoring %s", in);
						sbuf_finish(buf);
						sbuf_free(buf);
						return (EPKG_FATAL);
					}
					if (prefix[strlen(prefix) - 1] == '/')
						snprintf(path, sizeof(path), "%s%s", prefix, plist_file);
					else
						snprintf(path, sizeof(path), "%s/%s", prefix, plist_file);
					cp = strrchr(path, '/');
					cp ++;
					sbuf_cat(buf, cp);
					break;
				case 'B':
					if (plist_file == NULL) {
						pkg_emit_error("No files defined %%B couldn't be expanded, ignoring %s", in);
						sbuf_finish(buf);
						sbuf_free(buf);
						return (EPKG_FATAL);
					}
					if (prefix[strlen(prefix) - 1] == '/')
						snprintf(path, sizeof(path), "%s%s", prefix, plist_file);
					else
						snprintf(path, sizeof(path), "%s/%s", prefix, plist_file);
					cp = strrchr(path, '/');
					cp[0] = '\0';
					sbuf_cat(buf, path);
					break;
				case '%':
					sbuf_putc(buf, '%');
					break;
				case '@':
					if (line != NULL) {
						sbuf_cat(buf, line);
						break;
					}

					/*
					 * no break here because if line is not
					 * given (default exec) %@ does not
					 * exists
					 */
				default:
					sbuf_putc(buf, '%');
					sbuf_putc(buf, in[0]);
					break;
			}

		} else {
			sbuf_putc(buf, in[0]);
		}

		in++;
	}

	sbuf_finish(buf);
	*dest = strdup(sbuf_data(buf));
	sbuf_free(buf);
	
	return (EPKG_OK);
}
Ejemplo n.º 27
0
Archivo: query.c Proyecto: culot/pkgng
static void
print_query(struct pkg *pkg, char *qstr, char multiline)
{
	struct sbuf *output = sbuf_new_auto();
	struct pkg_dep *dep = NULL;
	struct pkg_category *cat = NULL;
	struct pkg_option *option = NULL;
	struct pkg_file *file = NULL;
	struct pkg_dir *dir = NULL;
	struct pkg_license *lic = NULL;
	struct pkg_user *user = NULL;
	struct pkg_group *group = NULL;
	struct pkg_script *scripts = NULL;

	switch (multiline) {
		case 'd':
			while (pkg_deps(pkg, &dep) == EPKG_OK) {
				format_str(pkg, output, qstr, dep);
				printf("%s\n", sbuf_get(output));
				break;
		}
		case 'r':
			while (pkg_rdeps(pkg, &dep) == EPKG_OK) {
				format_str(pkg, output, qstr, dep);
				printf("%s\n", sbuf_get(output));
			}
			break;
		case 'C':
			while (pkg_categories(pkg, &cat) == EPKG_OK) {
				format_str(pkg, output, qstr, cat);
				printf("%s\n", sbuf_get(output));
			}
			break;
		case 'O':
			while (pkg_options(pkg, &option) == EPKG_OK) {
				format_str(pkg, output, qstr, option);
				printf("%s\n", sbuf_get(output));
			}
			break;
		case 'F':
			while (pkg_files(pkg, &file) == EPKG_OK) {
				format_str(pkg, output, qstr, file);
				printf("%s\n", sbuf_get(output));
			}
			break;
		case 'D':
			while (pkg_dirs(pkg, &dir) == EPKG_OK) {
				format_str(pkg, output, qstr, dir);
				printf("%s\n", sbuf_get(output));
			}
			break;
		case 'L':
			while (pkg_licenses(pkg, &lic) == EPKG_OK) {
				format_str(pkg, output, qstr, lic);
				printf("%s\n", sbuf_get(output));
			}
			break;
		case 'U':
			while (pkg_users(pkg, &user) == EPKG_OK) {
				format_str(pkg, output, qstr, user);
				printf("%s\n", sbuf_get(output));
			}
			break;
		case 'G':
			while (pkg_users(pkg, &user) == EPKG_OK) {
				format_str(pkg, output, qstr, group);
				printf("%s\n", sbuf_get(output));
			}
			break;
		case 'S':
			while (pkg_scripts(pkg, &scripts) == EPKG_OK) {
				format_str(pkg, output, qstr, scripts);
				printf("%s\n", sbuf_get(output));
			}
			break;
		default:
			format_str(pkg, output, qstr, dep);
			printf("%s\n", sbuf_get(output));
			break;
	}
	sbuf_delete(output);
}
Ejemplo n.º 28
0
struct pkgdb_it *
pkgdb_rquery(struct pkgdb *db, const char *pattern, match_t match,
             const char *repo)
{
    sqlite3_stmt	*stmt = NULL;
    struct sbuf	*sql = NULL;
    const char	*reponame = NULL;
    const char	*comp = NULL;
    int		 ret;
    char		 basesql[BUFSIZ] = ""
                                   "SELECT id, origin, name, version, comment, "
                                   "prefix, desc, arch, maintainer, www, "
                                   "licenselogic, flatsize, pkgsize, "
                                   "cksum, manifestdigest, path AS repopath, '%1$s' AS dbname "
                                   "FROM '%1$s'.packages p";

    assert(db != NULL);
    assert(match == MATCH_ALL || (pattern != NULL && pattern[0] != '\0'));

    /*
     * If we have no remote repos loaded, we just return nothing instead of failing
     * an assert deep inside pkgdb_get_reponame
     */
    if (db->type != PKGDB_REMOTE)
        return (NULL);

    reponame = pkgdb_get_reponame(db, repo);

    sql = sbuf_new_auto();
    comp = pkgdb_get_pattern_query(pattern, match);
    if (comp && comp[0])
        strlcat(basesql, comp, sizeof(basesql));

    /*
     * Working on multiple remote repositories
     */
    if (reponame == NULL) {
        /* duplicate the query via UNION for all the attached
         * databases */

        ret = pkgdb_sql_all_attached(db->sqlite, sql,
                                     basesql, " UNION ALL ");
        if (ret != EPKG_OK) {
            sbuf_delete(sql);
            return (NULL);
        }
    } else
        sbuf_printf(sql, basesql, reponame, reponame);

    sbuf_cat(sql, " ORDER BY name;");
    sbuf_finish(sql);

    pkg_debug(4, "Pkgdb: running '%s'", sbuf_get(sql));
    ret = sqlite3_prepare_v2(db->sqlite, sbuf_get(sql), sbuf_size(sql), &stmt, NULL);
    if (ret != SQLITE_OK) {
        ERROR_SQLITE(db->sqlite);
        sbuf_delete(sql);
        return (NULL);
    }

    sbuf_delete(sql);

    if (match != MATCH_ALL && match != MATCH_CONDITION)
        sqlite3_bind_text(stmt, 1, pattern, -1, SQLITE_TRANSIENT);

    return (pkgdb_it_new(db, stmt, PKG_REMOTE, PKGDB_IT_FLAG_ONCE));
}
Ejemplo n.º 29
0
int
write_userconfig(char const * file)
{
	int             fd;
	int             i, j;
	struct sbuf	*buf;
	FILE           *fp;

	if (file == NULL)
		file = _PATH_PW_CONF;

	if ((fd = open(file, O_CREAT|O_RDWR|O_TRUNC|O_EXLOCK, 0644)) == -1)
		return (0);

	if ((fp = fdopen(fd, "w")) == NULL) {
		close(fd);
		return (0);
	}
			
	buf = sbuf_new_auto();
	for (i = _UC_NONE; i < _UC_FIELDS; i++) {
		int             quote = 1;

		sbuf_clear(buf);
		switch (i) {
		case _UC_DEFAULTPWD:
			sbuf_cat(buf, boolean_str(config.default_password));
			break;
		case _UC_REUSEUID:
			sbuf_cat(buf, boolean_str(config.reuse_uids));
			break;
		case _UC_REUSEGID:
			sbuf_cat(buf, boolean_str(config.reuse_gids));
			break;
		case _UC_NISPASSWD:
			sbuf_cat(buf, config.nispasswd ?  config.nispasswd :
			    "");
			quote = 0;
			break;
		case _UC_DOTDIR:
			sbuf_cat(buf, config.dotdir ?  config.dotdir :
			    boolean_str(0));
			break;
		case _UC_NEWMAIL:
			sbuf_cat(buf, config.newmail ?  config.newmail :
			    boolean_str(0));
			break;
		case _UC_LOGFILE:
			sbuf_cat(buf, config.logfile ?  config.logfile :
			    boolean_str(0));
			break;
		case _UC_HOMEROOT:
			sbuf_cat(buf, config.home);
			break;
		case _UC_HOMEMODE:
			sbuf_printf(buf, "%04o", config.homemode);
			quote = 0;
			break;
		case _UC_SHELLPATH:
			sbuf_cat(buf, config.shelldir);
			break;
		case _UC_SHELLS:
			for (j = 0; j < _UC_MAXSHELLS &&
			    system_shells[j] != NULL; j++)
				sbuf_printf(buf, "%s\"%s\"", j ?
				    "," : "", system_shells[j]);
			quote = 0;
			break;
		case _UC_DEFAULTSHELL:
			sbuf_cat(buf, config.shell_default ?
			    config.shell_default : bourne_shell);
			break;
		case _UC_DEFAULTGROUP:
			sbuf_cat(buf, config.default_group ?
			    config.default_group : "");
			break;
		case _UC_EXTRAGROUPS:
			for (j = 0; config.groups != NULL &&
			    j < (int)config.groups->sl_cur; j++)
				sbuf_printf(buf, "%s\"%s\"", j ?
				    "," : "", config.groups->sl_str[j]);
			quote = 0;
			break;
		case _UC_DEFAULTCLASS:
			sbuf_cat(buf, config.default_class ?
			    config.default_class : "");
			break;
		case _UC_MINUID:
			sbuf_printf(buf, "%u", config.min_uid);
			quote = 0;
			break;
		case _UC_MAXUID:
			sbuf_printf(buf, "%u", config.max_uid);
			quote = 0;
			break;
		case _UC_MINGID:
			sbuf_printf(buf, "%u", config.min_gid);
			quote = 0;
			break;
		case _UC_MAXGID:
			sbuf_printf(buf, "%u", config.max_gid);
			quote = 0;
			break;
		case _UC_EXPIRE:
			sbuf_printf(buf, "%d", config.expire_days);
			quote = 0;
			break;
		case _UC_PASSWORD:
			sbuf_printf(buf, "%d", config.password_days);
			quote = 0;
			break;
		case _UC_NONE:
			break;
		}
		sbuf_finish(buf);

		if (comments[i])
			fputs(comments[i], fp);

		if (*kwds[i]) {
			if (quote)
				fprintf(fp, "%s = \"%s\"\n", kwds[i],
				    sbuf_data(buf));
			else
				fprintf(fp, "%s = %s\n", kwds[i], sbuf_data(buf));
#if debugging
			printf("WROTE: %s = %s\n", kwds[i], sbuf_data(buf));
#endif
		}
	}
	sbuf_delete(buf);
	return (fclose(fp) != EOF);
}
Ejemplo n.º 30
0
static int
do_extract(struct archive *a, struct archive_entry *ae, const char *location,
    int nfiles, struct pkg *pkg, struct pkg *local)
{
	int	retcode = EPKG_OK;
	int	ret = 0, cur_file = 0;
	char	path[MAXPATHLEN], pathname[MAXPATHLEN], rpath[MAXPATHLEN];
	struct stat st;
	const struct stat *aest;
	bool renamed = false;
	const struct pkg_file *rf;
	struct pkg_config_file *rcf;
	struct sbuf *newconf;
	bool automerge = pkg_object_bool(pkg_config_get("AUTOMERGE"));
	unsigned long set, clear;

#ifndef HAVE_ARC4RANDOM
	srand(time(NULL));
#endif

	if (nfiles == 0)
		return (EPKG_OK);

	pkg_emit_extract_begin(pkg);
	pkg_emit_progress_start(NULL);

	newconf = sbuf_new_auto();

	do {
		ret = ARCHIVE_OK;
		sbuf_clear(newconf);
		rf = NULL;
		rcf = NULL;
		pkg_absolutepath(archive_entry_pathname(ae), path, sizeof(path));
		snprintf(pathname, sizeof(pathname), "%s%s%s",
		    location ? location : "", *path == '/' ? "" : "/",
		    path
		);
		strlcpy(rpath, pathname, sizeof(rpath));

		aest = archive_entry_stat(ae);
		archive_entry_fflags(ae, &set, &clear);
		if (lstat(rpath, &st) != -1) {
			/*
			 * We have an existing file on the path, so handle it
			 */
			if (!S_ISDIR(aest->st_mode)) {
				pkg_debug(2, "Old version found, renaming");
				pkg_add_file_random_suffix(rpath, sizeof(rpath), 12);
				renamed = true;
			}

			if (!S_ISDIR(st.st_mode) && S_ISDIR(aest->st_mode)) {
				if (S_ISLNK(st.st_mode)) {
					if (stat(rpath, &st) == -1) {
						pkg_emit_error("Dead symlink %s", rpath);
					} else {
						pkg_debug(2, "Directory is a symlink, use it");
						pkg_emit_progress_tick(cur_file++, nfiles);
						continue;
					}
				}
			}
		}

		archive_entry_set_pathname(ae, rpath);

		/* load in memory the content of config files */
		if (pkg_is_config_file(pkg, path, &rf, &rcf)) {
			pkg_debug(1, "Populating config_file %s", pathname);
			size_t len = archive_entry_size(ae);
			rcf->content = malloc(len);
			archive_read_data(a, rcf->content, len);
			if (renamed && (!automerge || local == NULL))
				strlcat(pathname, ".pkgnew", sizeof(pathname));
		}

		/*
		 * check if the file is already provided by previous package
		 */
		if (!automerge)
			attempt_to_merge(renamed, rcf, local, pathname, path, newconf);

		if (sbuf_len(newconf) == 0 && (rcf == NULL || rcf->content == NULL)) {
			pkg_debug(1, "Extracting: %s", archive_entry_pathname(ae));
			int install_as_user = (getenv("INSTALL_AS_USER") != NULL);
			int extract_flags = EXTRACT_ARCHIVE_FLAGS;
			if (install_as_user) {
				/* when installing as user don't try to set file ownership */
				extract_flags &= ~ARCHIVE_EXTRACT_OWNER;
			}
			ret = archive_read_extract(a, ae, extract_flags);
		} else {
			if (sbuf_len(newconf) == 0) {
				sbuf_cat(newconf, rcf->content);
				sbuf_finish(newconf);
			}
			pkg_debug(2, "Writing conf in %s", pathname);
			unlink(rpath);
			FILE *f = fopen(rpath, "w+");
			fprintf(f, "%s", sbuf_data(newconf));
			fclose(f);
		}

		if (ret != ARCHIVE_OK) {
			/*
			 * show error except when the failure is during
			 * extracting a directory and that the directory already
			 * exists.
			 * this allow to install packages linux_base from
			 * package for example
			 */
			if (archive_entry_filetype(ae) != AE_IFDIR ||
			    !is_dir(pathname)) {
				pkg_emit_error("archive_read_extract(): %s",
				    archive_error_string(a));
				retcode = EPKG_FATAL;
				goto cleanup;
			}
		}
		/* Reapply modes to the directories to work around a problem on FreeBSD 9 */
		if (archive_entry_filetype(ae) == AE_IFDIR)
			chmod(pathname, aest->st_mode);

		pkg_emit_progress_tick(cur_file++, nfiles);

		/* Rename old file */
		if (renamed) {

			pkg_debug(1, "Renaming %s -> %s", rpath, pathname);
#ifdef HAVE_CHFLAGS
			bool old = false;
			if (set & NOCHANGESFLAGS)
				chflags(rpath, 0);

			if (lstat(pathname, &st) != -1) {
				old = true;
				if (st.st_flags & NOCHANGESFLAGS)
					chflags(pathname, 0);
			}
#endif

			if (rename(rpath, pathname) == -1) {
#ifdef HAVE_CHFLAGS
				/* restore flags */
				if (old)
					chflags(pathname, st.st_flags);
#endif
				pkg_emit_error("cannot rename %s to %s: %s", rpath, pathname,
					strerror(errno));
				retcode = EPKG_FATAL;
				goto cleanup;
			}
#ifdef HAVE_CHFLAGS
			/* Restore flags */
			chflags(pathname, set);
#endif
		}

		if (string_end_with(pathname, ".pkgnew"))
			pkg_emit_notice("New configuration file: %s", pathname);

		renamed = false;
	} while ((ret = archive_read_next_header(a, &ae)) == ARCHIVE_OK);

	if (ret != ARCHIVE_EOF) {
		pkg_emit_error("archive_read_next_header(): %s",
		    archive_error_string(a));
		retcode = EPKG_FATAL;
	}

cleanup:

	pkg_emit_progress_tick(nfiles, nfiles);
	pkg_emit_extract_finished(pkg);

	if (renamed && retcode == EPKG_FATAL) {
#ifdef HAVE_CHFLAGS
		if (set & NOCHANGESFLAGS)
			chflags(rpath, set & ~NOCHANGESFLAGS);
#endif
		unlink(rpath);
	}

	return (retcode);
}