Esempio n. 1
0
File: pkgdb.c Progetto: flz/pkgng
int
pkgdb_compact(struct pkgdb *db)
{
	int64_t page_count = 0;
	int64_t freelist_count = 0;
	char *errmsg;
	int retcode = EPKG_OK;

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

	if (get_pragma(db->sqlite, "PRAGMA page_count;", &page_count) != EPKG_OK)
		return (EPKG_FATAL);

	if (get_pragma(db->sqlite, "PRAGMA freelist_count;", &freelist_count) !=
		EPKG_OK)
		return (EPKG_FATAL);

	/*
	 * Only compact if we will save 25% (or more) of the current used space.
	 */
	if (freelist_count / (float)page_count < 0.25)
		return (EPKG_OK);

	if (sqlite3_exec(db->sqlite, "VACUUM;", NULL, NULL, &errmsg) != SQLITE_OK){
		retcode = pkg_error_set(EPKG_FATAL, "%s", errmsg);
		sqlite3_free(errmsg);
	}

	return (retcode);
}
Esempio n. 2
0
grn_query *
grn_query_open(grn_ctx *ctx, const char *str, unsigned int str_len,
               grn_operator default_op, int max_exprs)
{
  grn_query *q;
  int max_cells = max_exprs * 4;
  if (!(q = GRN_MALLOC(sizeof(grn_query) + max_cells * sizeof(grn_cell) + str_len + 1))) {
    GRN_LOG(ctx, GRN_LOG_ALERT, "grn_query_open malloc fail");
    return NULL;
  }
  q->header.type = GRN_QUERY;
  q->str = (char *)&q->cell_pool[max_cells];
  memcpy(q->str, str, str_len);
  q->str[str_len] = '\0';
  q->cur = q->str;
  q->str_end = q->str + str_len;
  q->default_op = default_op;
  q->encoding = ctx->encoding;
  q->max_exprs = max_exprs;
  q->max_cells = max_cells;
  q->cur_cell = 0;
  q->cur_expr = 0;
  q->escalation_threshold = GRN_DEFAULT_MATCH_ESCALATION_THRESHOLD;
  q->escalation_decaystep = DEFAULT_DECAYSTEP;
  q->weight_offset = 0;
  q->opt.weight_vector = NULL;
  q->weight_set = NULL;
  get_pragma(ctx, q);
  q->expr = get_expr(ctx, q);
  q->opt.vector_size = DEFAULT_WEIGHT_VECTOR_SIZE;
  q->opt.func = q->weight_set ? section_weight_cb : NULL;
  q->opt.func_arg = q->weight_set;
  q->snip_conds = NULL;
  return q;
}
Esempio n. 3
0
int
pkg_update(const char *name, const char *packagesite, bool force)
{
	char url[MAXPATHLEN];
	struct archive *a = NULL;
	struct archive_entry *ae = NULL;
	char repofile[MAXPATHLEN];
	char repofile_unchecked[MAXPATHLEN];
	char tmp[MAXPATHLEN];
	const char *dbdir = NULL;
	const char *repokey;
	unsigned char *sig = NULL;
	int siglen = 0;
	int fd, rc = EPKG_FATAL, ret;
	struct stat st;
	time_t t = 0;
	sqlite3 *sqlite;
	char *archreq = NULL;
	const char *myarch;
	int64_t res;
	const char *tmpdir;

	snprintf(url, MAXPATHLEN, "%s/repo.txz", packagesite);

	tmpdir = getenv("TMPDIR");
	if (tmpdir == NULL)
		tmpdir = "/tmp";
	strlcpy(tmp, tmpdir, sizeof(tmp));
	strlcat(tmp, "/repo.txz.XXXXXX", sizeof(tmp));

	fd = mkstemp(tmp);
	if (fd == -1) {
		pkg_emit_error("Could not create temporary file %s, "
		    "aborting update.\n", tmp);
		return (EPKG_FATAL);
	}

	if (pkg_config_string(PKG_CONFIG_DBDIR, &dbdir) != EPKG_OK) {
		pkg_emit_error("Cant get dbdir config entry");
		return (EPKG_FATAL);
	}

	snprintf(repofile, sizeof(repofile), "%s/%s.sqlite", dbdir, name);
	if (force)
		t = 0;		/* Always fetch */
	else {
		if (stat(repofile, &st) != -1) {
			t = st.st_mtime;
			/* add 1 minute to the timestamp because
			 * repo.sqlite is always newer than repo.txz,
			 * 1 minute should be enough.
			 */
			t += 60;
		}
	}

	rc = pkg_fetch_file_to_fd(url, fd, t);
	close(fd);
	if (rc != EPKG_OK) {
		goto cleanup;
	}

	if (eaccess(repofile, W_OK) == -1) {
		pkg_emit_error("Insufficient privilege to update %s\n",
			       repofile);
		rc = EPKG_ENOACCESS;
		goto cleanup;
	}

	a = archive_read_new();
	archive_read_support_compression_all(a);
	archive_read_support_format_tar(a);

	archive_read_open_filename(a, tmp, 4096);

	while (archive_read_next_header(a, &ae) == ARCHIVE_OK) {
		if (strcmp(archive_entry_pathname(ae), "repo.sqlite") == 0) {
			snprintf(repofile_unchecked, sizeof(repofile_unchecked),
			    "%s.unchecked", repofile);
			archive_entry_set_pathname(ae, repofile_unchecked);

			/*
			 * The repo should be owned by root and not writable
			 */
			archive_entry_set_uid(ae, 0);
			archive_entry_set_gid(ae, 0);
			archive_entry_set_perm(ae, 0644);

			archive_read_extract(a, ae, EXTRACT_ARCHIVE_FLAGS);
		}
		if (strcmp(archive_entry_pathname(ae), "signature") == 0) {
			siglen = archive_entry_size(ae);
			sig = malloc(siglen);
			archive_read_data(a, sig, siglen);
		}
	}

	if (pkg_config_string(PKG_CONFIG_REPOKEY, &repokey) != EPKG_OK) {
		free(sig);
		
		return (EPKG_FATAL);
	}

	if (repokey != NULL) {
		if (sig != NULL) {
			ret = rsa_verify(repofile_unchecked, repokey,
			    sig, siglen - 1);
			if (ret != EPKG_OK) {
				pkg_emit_error("Invalid signature, "
				    "removing repository.\n");
				unlink(repofile_unchecked);
				free(sig);
				rc = EPKG_FATAL;
				goto cleanup;
			}
			free(sig);
		} else {
			pkg_emit_error("No signature found in the repository.  "
			    "Can not validate against %s key.", repokey);
			rc = EPKG_FATAL;
			unlink(repofile_unchecked);
			goto cleanup;
		}
	}

	/* check is the repository is for valid architecture */
	sqlite3_initialize();

	if (sqlite3_open(repofile_unchecked, &sqlite) != SQLITE_OK) {
		unlink(repofile_unchecked);
		pkg_emit_error("Corrupted repository");
		rc = EPKG_FATAL;
		goto cleanup;
	}

	pkg_config_string(PKG_CONFIG_ABI, &myarch);

	archreq = sqlite3_mprintf("select count(arch) from packages "
	    "where arch not GLOB '%q'", myarch);
	if (get_pragma(sqlite, archreq, &res) != EPKG_OK) {
		sqlite3_free(archreq);
		pkg_emit_error("Unable to query repository");
		rc = EPKG_FATAL;
		sqlite3_close(sqlite);
		goto cleanup;
	}

	if (res > 0) {
		pkg_emit_error("At least one of the packages provided by"
		    "the repository is not compatible with your abi: %s",
		    myarch);
		rc = EPKG_FATAL;
		sqlite3_close(sqlite);
		goto cleanup;
	}

	sqlite3_close(sqlite);
	sqlite3_shutdown();


	if (rename(repofile_unchecked, repofile) != 0) {
		pkg_emit_errno("rename", "");
		rc = EPKG_FATAL;
		goto cleanup;
	}

	if ((rc = remote_add_indexes(name)) != EPKG_OK)
		goto cleanup;

	rc = EPKG_OK;

	cleanup:
	if (a != NULL)
		archive_read_finish(a);

	(void)unlink(tmp);

	return (rc);
}
Esempio n. 4
0
File: update.c Progetto: renchap/pkg
int
pkg_update(struct pkg_repo *repo, bool force)
{
	char repofile[MAXPATHLEN];

	const char *dbdir = NULL;
	struct stat st;
	time_t t = 0;
	sqlite3 *sqlite = NULL;
	char *req = NULL;
	int64_t res;

	sqlite3_initialize();

	if (pkg_config_string(PKG_CONFIG_DBDIR, &dbdir) != EPKG_OK) {
		pkg_emit_error("Cant get dbdir config entry");
		return (EPKG_FATAL);
	}

	snprintf(repofile, sizeof(repofile), "%s/%s.sqlite", dbdir, pkg_repo_name(repo));

	if (stat(repofile, &st) != -1)
		t = force ? 0 : st.st_mtime;

	if (t != 0) {
		if (sqlite3_open(repofile, &sqlite) != SQLITE_OK) {
			pkg_emit_error("Unable to open local database");
			return (EPKG_FATAL);
		}

		if (get_pragma(sqlite, "SELECT count(name) FROM sqlite_master "
		    "WHERE type='table' AND name='repodata';", &res) != EPKG_OK) {
			pkg_emit_error("Unable to query repository");
			sqlite3_close(sqlite);
			return (EPKG_FATAL);
		}

		if (res != 1) {
			t = 0;

			if (sqlite != NULL) {
				sqlite3_close(sqlite);
				sqlite = NULL;
			}
		}
	}

	if (t != 0) {
		req = sqlite3_mprintf("select count(key) from repodata "
		    "WHERE key = \"packagesite\" and value = '%q'", pkg_repo_url(repo));

		if (get_pragma(sqlite, req, &res) != EPKG_OK) {
			sqlite3_free(req);
			pkg_emit_error("Unable to query repository");
			sqlite3_close(sqlite);
			return (EPKG_FATAL);
		}
		sqlite3_free(req);
		if (res != 1) {
			t = 0;

			if (sqlite != NULL) {
				sqlite3_close(sqlite);
				sqlite = NULL;
			}
			unlink(repofile);
		}
	}

	res = pkg_update_incremental(repofile, repo, &t);
	if (res != EPKG_OK && res != EPKG_UPTODATE) {
		pkg_emit_notice("No digest falling back on legacy catalog format");

		/* Still try to do full upgrade */
		if ((res = pkg_update_full(repofile, repo, &t)) != EPKG_OK)
			goto cleanup;
	}

	res = EPKG_OK;
cleanup:
	/* Set mtime from http request if possible */
	if (t != 0) {
		struct timeval ftimes[2] = {
			{
			.tv_sec = t,
			.tv_usec = 0
			},
			{
			.tv_sec = t,
			.tv_usec = 0
			}
		};
Esempio n. 5
0
File: init.c Progetto: dpl0/pkg
int
pkg_repo_binary_open(struct pkg_repo *repo, unsigned mode)
{
	char filepath[MAXPATHLEN];
	struct statfs stfs;
	const char *dbdir = NULL;
	sqlite3 *sqlite = NULL;
	int flags;
	int64_t res;
	struct pkg_repo_it *it;
	struct pkg *pkg = NULL;
	const char *digest;

	sqlite3_initialize();
	dbdir = pkg_object_string(pkg_config_get("PKG_DBDIR"));

	/*
	 * Fall back on unix-dotfile locking strategy if on a network filesystem
	 */
	if (statfs(dbdir, &stfs) == 0) {
		if ((stfs.f_flags & MNT_LOCAL) != MNT_LOCAL)
			sqlite3_vfs_register(sqlite3_vfs_find("unix-dotfile"), 1);
	}

	snprintf(filepath, sizeof(filepath), "%s/%s.meta",
		dbdir, pkg_repo_name(repo));

	/* Open metafile */
	if (access(filepath, R_OK) != -1) {
		if (pkg_repo_meta_load(filepath, &repo->meta) != EPKG_OK)
			return (EPKG_FATAL);
	}

	snprintf(filepath, sizeof(filepath), "%s/%s",
		dbdir, pkg_repo_binary_get_filename(pkg_repo_name(repo)));

	/* Always want read mode here */
	if (access(filepath, R_OK | mode) != 0)
		return (EPKG_ENOACCESS);

	flags = (mode & W_OK) != 0 ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY;
	if (sqlite3_open_v2(filepath, &sqlite, flags, NULL) != SQLITE_OK)
		return (EPKG_FATAL);

	/* Sanitise sqlite database */
	if (get_pragma(sqlite, "SELECT count(name) FROM sqlite_master "
		"WHERE type='table' AND name='repodata';", &res, false) != EPKG_OK) {
		pkg_emit_error("Unable to query repository");
		sqlite3_close(sqlite);
		return (EPKG_FATAL);
	}

	if (res != 1) {
		pkg_emit_notice("Repository %s contains no repodata table, "
			"need to re-create database", repo->name);
		sqlite3_close(sqlite);
		return (EPKG_FATAL);
	}

	/* Check package site */
	char *req = sqlite3_mprintf("select count(key) from repodata "
		"WHERE key = \"packagesite\" and value = '%q'", pkg_repo_url(repo));

	res = 0;
	get_pragma(sqlite, req, &res, true);
	sqlite3_free(req);
	if (res != 1) {
		pkg_emit_notice("Repository %s has a wrong packagesite, need to "
			"re-create database", repo->name);
		sqlite3_close(sqlite);
		return (EPKG_FATAL);
	}

	/* Check version */
	if (pkg_repo_binary_check_version(repo, sqlite) != EPKG_OK) {
		pkg_emit_error("need to re-create repo %s to upgrade schema version",
			repo->name);
		sqlite3_close(sqlite);
		if (mode & W_OK)
			unlink(filepath);
		return (EPKG_REPOSCHEMA);
	}

	repo->priv = sqlite;
	/* Check digests format */
	if ((it = pkg_repo_binary_query(repo, NULL, MATCH_ALL)) == NULL)
		return (EPKG_OK);

	if (it->ops->next(it, &pkg, PKG_LOAD_BASIC) != EPKG_OK) {
		it->ops->free(it);
		return (EPKG_OK);
	}
	it->ops->free(it);
	pkg_get(pkg, PKG_DIGEST, &digest);
	if (digest == NULL || !pkg_checksum_is_valid(digest, strlen(digest))) {
		pkg_emit_notice("Repository %s has incompatible checksum format, need to "
			"re-create database", repo->name);
		pkg_free(pkg);
		sqlite3_close(sqlite);
		repo->priv = NULL;
		return (EPKG_FATAL);
	}
	pkg_free(pkg);

	return (EPKG_OK);
}