예제 #1
0
파일: pkg_config.c 프로젝트: dumbbell/pkg
static void
load_repo_file(const char *repofile, pkg_init_flags flags)
{
	struct ucl_parser *p;
	ucl_object_t *obj = NULL;
	const char *myarch = NULL;
	const char *myarch_legacy = NULL;

	p = ucl_parser_new(0);

	myarch = pkg_object_string(pkg_config_get("ABI"));
	ucl_parser_register_variable (p, "ABI", myarch);

	myarch_legacy = pkg_object_string(pkg_config_get("ALTABI"));
	ucl_parser_register_variable (p, "ALTABI", myarch_legacy);

	pkg_debug(1, "PKgConfig: loading %s", repofile);
	if (!ucl_parser_add_file(p, repofile)) {
		pkg_emit_error("Error parsing: %s: %s", repofile,
		    ucl_parser_get_error(p));
		ucl_parser_free(p);
		return;
	}

	obj = ucl_parser_get_object(p);
	if (obj == NULL)
		return;

	if (obj->type == UCL_OBJECT)
		walk_repo_obj(obj, repofile, flags);

	ucl_object_unref(obj);
}
예제 #2
0
파일: pkg_delete.c 프로젝트: rakhij/pkg
int
pkg_delete_dirs(__unused struct pkgdb *db, struct pkg *pkg, bool force)
{
	struct pkg_dir	*dir = NULL;
	ucl_object_t *obj;
	char		fpath[MAXPATHLEN];

	while (pkg_dirs(pkg, &dir) == EPKG_OK) {
		if (dir->keep == 1)
			continue;

		obj = pkg_annotation_lookup(pkg, "relocated");
		snprintf(fpath, sizeof(fpath), "%s%s",
		    obj ? pkg_object_string(obj) : "" , pkg_dir_path(dir) );

		if (pkg_dir_try(dir)) {
			if (rmdir(fpath) == -1 &&
			    errno != ENOTEMPTY && errno != EBUSY && !force)
				pkg_emit_errno("rmdir", fpath);
		} else {
			if (rmdir(fpath) == -1 && !force)
				pkg_emit_errno("rmdir", fpath);
		}
	}

	return (EPKG_OK);
}
예제 #3
0
파일: utils.c 프로젝트: baitisj/pkg
bool
is_valid_abi(const char *arch, bool emit_error) {
	const char *myarch, *myarch_legacy;

	myarch = pkg_object_string(pkg_config_get("ABI"));
	myarch_legacy = pkg_object_string(pkg_config_get("ALTABI"));

	if (fnmatch(arch, myarch, FNM_CASEFOLD) == FNM_NOMATCH &&
	    strncasecmp(arch, myarch, strlen(myarch)) != 0 &&
	    strncasecmp(arch, myarch_legacy, strlen(myarch_legacy)) != 0) {
		if (emit_error)
			pkg_emit_error("wrong architecture: %s instead of %s",
			    arch, myarch);
		return (false);
	}

	return (true);
}
예제 #4
0
파일: annotate.c 프로젝트: dpl0/pkg
static int
do_show(struct pkg *pkg, const char *tag)
{
	const pkg_object	*annotations, *note;
	pkg_iter		 it = NULL;
	int			 ret = EPKG_OK;

	pkg_get(pkg, PKG_ANNOTATIONS, &annotations);
	while ((note = pkg_object_iterate(annotations, &it)) != NULL) {
		if (strcmp(tag, pkg_object_key(note)) == 0) {
			if (quiet)
				printf("%s\n", pkg_object_string(note));
			else
				pkg_printf("%n-%v: Tag: %S Value: %S\n",
				    pkg, pkg, pkg_object_key(note),
				    pkg_object_string(note));
		}
	}

	return (ret);
}
예제 #5
0
void
pkg_cache_full_clean(void)
{
	const char *cachedir;

	if (!pkg_object_bool(pkg_config_get("AUTOCLEAN")))
		return;

	pkg_debug(1, "Cleaning up cachedir");

	cachedir = pkg_object_string(pkg_config_get("PKG_CACHEDIR"));

	return (rm_rf(cachedir));
}
예제 #6
0
파일: pkg_config.c 프로젝트: dumbbell/pkg
static void
load_repositories(const char *repodir, pkg_init_flags flags)
{
	const pkg_object *reposlist, *cur;
	pkg_iter it = NULL;

	if (repodir != NULL) {
		load_repo_files(repodir, flags);
		return;
	}

	reposlist = pkg_config_get( "REPOS_DIR");
	while ((cur = pkg_object_iterate(reposlist, &it)))
		load_repo_files(pkg_object_string(cur), flags);
}
예제 #7
0
파일: init.c 프로젝트: dpl0/pkg
int
pkg_repo_binary_access(struct pkg_repo *repo, unsigned mode)
{
	const pkg_object	*o;
	const char		*dbdir;
	int			 ret = EPKG_OK;

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

	ret = pkgdb_check_access(mode, dbdir,
		pkg_repo_binary_get_filename(pkg_repo_name(repo)));

	return (ret);
}
예제 #8
0
static void
load_repo_file(const char *repofile)
{
	struct ucl_parser *p;
	ucl_object_t *obj = NULL;
	bool fallback = false;
	const char *myarch = NULL;

	p = ucl_parser_new(0);

	myarch = pkg_object_string(pkg_config_get("ABI"));
	ucl_parser_register_variable (p, "ABI", myarch);

	pkg_debug(1, "PKgConfig: loading %s", repofile);
	if (!ucl_parser_add_file(p, repofile)) {
		pkg_emit_error("Error parsing: %s: %s", repofile,
		    ucl_parser_get_error(p));
		if (errno == ENOENT) {
			ucl_parser_free(p);
			return;
		}
		fallback = true;
	}

	if (fallback) {
		obj = yaml_to_ucl(repofile, NULL, 0);
		if (obj == NULL)
			return;
	}

	if (fallback) {
		pkg_emit_error("%s file is using a deprecated format. "
		    "Please replace it with the following:\n"
		    "====== BEGIN %s ======\n"
		    "%s"
		    "\n====== END %s ======\n",
		    repofile, repofile,
		    ucl_object_emit(obj, UCL_EMIT_YAML),
		    repofile);
	}

	obj = ucl_parser_get_object(p);

	if (obj->type == UCL_OBJECT)
		walk_repo_obj(obj, repofile);

	ucl_object_free(obj);
}
예제 #9
0
파일: pkg_delete.c 프로젝트: rakhij/pkg
int
pkg_delete_files(struct pkg *pkg, unsigned force)
	/* force: 0 ... be careful and vocal about it. 
	 *        1 ... remove files without bothering about checksums.
	 *        2 ... like 1, but remain silent if removal fails.
	 */
{
	struct pkg_file	*file = NULL;
	char		 sha256[SHA256_DIGEST_LENGTH * 2 + 1];
	const char	*path;
	char		fpath[MAXPATHLEN];

	while (pkg_files(pkg, &file) == EPKG_OK) {
		const char *sum = pkg_file_cksum(file);
		ucl_object_t *obj;

		if (file->keep == 1)
			continue;

		path = pkg_file_path(file);
		obj = pkg_annotation_lookup(pkg, "relocated");
		snprintf(fpath, sizeof(fpath), "%s%s",
		    obj ? pkg_object_string(obj) : "" , path );

		/* Regular files and links */
		/* check sha256 */
		if (!force && sum[0] != '\0') {
			if (sha256_file(fpath, sha256) != EPKG_OK)
				continue;
			if (strcmp(sha256, sum)) {
				pkg_emit_error("%s fails original SHA256 "
				    "checksum, not removing", path);
				continue;
			}
		}

		if (unlink(fpath) == -1) {
			if (force < 2)
				pkg_emit_errno("unlink", fpath);
			continue;
		}
	}

	return (EPKG_OK);
}
예제 #10
0
파일: pkg_config.c 프로젝트: dumbbell/pkg
bool
pkg_compiled_for_same_os_major(void)
{
#ifdef OSMAJOR
	const char	*myabi;
	int		 osmajor;

	myabi = pkg_object_string(pkg_config_get("ABI"));
	myabi = strchr(myabi,':');
	myabi++;

	osmajor = (int) strtol(myabi, NULL, 10);

	return (osmajor == OSMAJOR);
#else
	return (true);		/* Can't tell, so assume yes  */
#endif
}
예제 #11
0
파일: fetch.c 프로젝트: Moscarda/pkg
int
pkg_repo_binary_get_cached_name(struct pkg_repo *repo, struct pkg *pkg,
	char *dest, size_t destlen)
{
	const char *ext = NULL;
	const char *cachedir = NULL;
	const char *packagesite;
	struct stat st;

	cachedir = pkg_object_string(pkg_config_get("PKG_CACHEDIR"));

	packagesite = pkg_repo_url(repo);

	if (strncmp(packagesite, "file://", 7) == 0) {
		snprintf(dest, destlen, "%s/%s", packagesite + 7,
		    pkg->repopath);
		return (EPKG_OK);
	}

	if (pkg->repopath != NULL)
		ext = strrchr(pkg->repopath, '.');

	if (ext != NULL) {
		/*
		 * The real naming scheme:
		 * <cachedir>/<name>-<version>-<checksum>.txz
		 */
		pkg_snprintf(dest, destlen, "%S/%n-%v-%z%S",
				cachedir, pkg, pkg, pkg, ext);
		if (stat (dest, &st) == -1 || pkg->pkgsize != st.st_size)
			return (EPKG_FATAL);

	}
	else {
		pkg_snprintf(dest, destlen, "%S/%n-%v-%z",
				cachedir, pkg, pkg, pkg);
	}

	return (EPKG_OK);
}
예제 #12
0
파일: fetch.c 프로젝트: vianaweb/pkg
void
pkg_repo_binary_get_cached_name(struct pkg_repo *repo, struct pkg *pkg,
	char *dest, size_t destlen)
{
	const char *sum, *name, *version, *repourl, *ext = NULL;
	const char *cachedir = NULL;
	struct stat st;

	cachedir = pkg_object_string(pkg_config_get("PKG_CACHEDIR"));

	pkg_get(pkg, PKG_CKSUM, &sum, PKG_NAME, &name, PKG_VERSION, &version,
			PKG_REPOPATH, &repourl);

	if (repourl != NULL)
		ext = strrchr(repourl, '.');

	if (ext != NULL) {
		/*
		 * XXX:
		 * This code tries to skip refetching but it should be removed as soon
		 * as we transfer to new scheme.
		 */
		pkg_snprintf(dest, destlen, "%S/%n-%v-%z",
				cachedir, pkg, pkg, pkg);
		if (stat (dest, &st) != -1)
			return;

		/*
		 * The real naming scheme:
		 * <cachedir>/<name>-<version>-<checksum>.txz
		 */
		pkg_snprintf(dest, destlen, "%S/%n-%v-%z%S",
				cachedir, pkg, pkg, pkg, ext);
	}
	else {
		pkg_snprintf(dest, destlen, "%S/%n-%v-%z",
				cachedir, pkg, pkg, pkg);
	}
}
예제 #13
0
파일: audit.c 프로젝트: grembo/pkg
int
exec_audit(int argc, char **argv)
{
	struct pkg_audit	*audit;
	struct pkgdb		*db = NULL;
	struct pkgdb_it		*it = NULL;
	struct pkg		*pkg = NULL;
	const char		*db_dir;
	char			*name;
	char			*version;
	char			 audit_file_buf[MAXPATHLEN];
	char			*audit_file = audit_file_buf;
	unsigned int		 vuln = 0;
	bool			 fetch = false, recursive = false;
	int			 ch, i;
	int			 ret = EX_OK;
	const char		*portaudit_site = NULL;
	struct sbuf		*sb;
	kh_pkgs_t		*check = NULL;

	db_dir = pkg_object_string(pkg_config_get("PKG_DBDIR"));
	snprintf(audit_file_buf, sizeof(audit_file_buf), "%s/vuln.xml", db_dir);

	struct option longopts[] = {
		{ "fetch",	no_argument,		NULL,	'F' },
		{ "file",	required_argument,	NULL,	'f' },
		{ "recursive",	no_argument,	NULL,	'r' },
		{ "quiet",	no_argument,		NULL,	'q' },
		{ NULL,		0,			NULL,	0   },
	};

	while ((ch = getopt_long(argc, argv, "+Ff:qr", longopts, NULL)) != -1) {
		switch (ch) {
		case 'F':
			fetch = true;
			break;
		case 'f':
			audit_file = optarg;
			break;
		case 'q':
			quiet = true;
			break;
		case 'r':
			recursive = true;
			break;
		default:
			usage_audit();
			return(EX_USAGE);
		}
	}
	argc -= optind;
	argv += optind;

	audit = pkg_audit_new();

	if (fetch == true) {
		portaudit_site = pkg_object_string(pkg_config_get("VULNXML_SITE"));
		if (pkg_audit_fetch(portaudit_site, audit_file) != EPKG_OK) {
			pkg_audit_free(audit);
			return (EX_IOERR);
		}
	}

	if (pkg_audit_load(audit, audit_file) != EPKG_OK) {
		if (errno == ENOENT)
			warnx("vulnxml file %s does not exist. "
					"Try running 'pkg audit -F' first",
					audit_file);
		else
			warn("unable to open vulnxml file %s",
					audit_file);

		pkg_audit_free(audit);
		return (EX_DATAERR);
	}

	check = kh_init_pkgs();
	if (argc >= 1) {
		for (i = 0; i < argc; i ++) {
			name = argv[i];
			version = strrchr(name, '-');
			if (version != NULL) {
				version[0] = '\0';
				version++;
			}
			if (pkg_new(&pkg, PKG_FILE) != EPKG_OK)
				err(EX_OSERR, "malloc");
			if (version != NULL)
				pkg_set(pkg, PKG_NAME, name, PKG_VERSION, version);
			else
				pkg_set(pkg, PKG_NAME, name);
			/* Fake uniqueid */
			pkg_set(pkg, PKG_UNIQUEID, name);
			add_to_check(check, pkg);
			pkg = NULL;
		}
	}
	else {

		/*
		 * if the database doesn't exist it just means there are no
		 * packages to audit.
		 */

		ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL);
		if (ret == EPKG_ENODB) {
			pkg_audit_free(audit);
			kh_destroy_pkgs(check);
			return (EX_OK);
		} else if (ret == EPKG_ENOACCESS) {
			warnx("Insufficient privileges to read the package database");
			pkg_audit_free(audit);
			kh_destroy_pkgs(check);
			return (EX_NOPERM);
		} else if (ret != EPKG_OK) {
			warnx("Error accessing the package database");
			pkg_audit_free(audit);
			kh_destroy_pkgs(check);
			return (EX_IOERR);
		}

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

		if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
			pkgdb_close(db);
			pkg_audit_free(audit);
			kh_destroy_pkgs(check);
			warnx("Cannot get a read lock on a database, it is locked by another process");
			return (EX_TEMPFAIL);
		}

		if ((it = pkgdb_query(db, NULL, MATCH_ALL)) == NULL) {
			warnx("Error accessing the package database");
			ret = EX_IOERR;
		}
		else {
			while ((ret = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_RDEPS))
							== EPKG_OK) {
				add_to_check(check, pkg);
				pkg = NULL;
			}
			ret = EX_OK;
		}
		if (db != NULL) {
			pkgdb_it_free(it);
			pkgdb_release_lock(db, PKGDB_LOCK_READONLY);
			pkgdb_close(db);
		}
		if (ret != EX_OK) {
			pkg_audit_free(audit);
			kh_destroy_pkgs(check);
			return (ret);
		}
	}

	/* Now we have vulnxml loaded and check list formed */
#ifdef HAVE_CAPSICUM
	if (cap_enter() < 0 && errno != ENOSYS) {
		warn("cap_enter() failed");
		pkg_audit_free(audit);
		kh_destroy_pkgs(check);
		return (EPKG_FATAL);
	}
#endif

	if (pkg_audit_process(audit) == EPKG_OK) {
		kh_foreach_value(check, pkg, {
			if (pkg_audit_is_vulnerable(audit, pkg, quiet, &sb)) {
				vuln ++;
				printf("%s", sbuf_data(sb));

				if (recursive) {
					const char *name;
					kh_pkgs_t *seen = kh_init_pkgs();

					pkg_get(pkg, PKG_NAME, &name);
					sbuf_clear(sb);
					sbuf_printf(sb, "Packages that depend on %s: ", name);
					print_recursive_rdeps(check, pkg , sb, seen, true);
					sbuf_finish(sb);
					printf("%s\n\n", sbuf_data(sb));

					kh_destroy_pkgs(seen);
				}
				sbuf_delete(sb);
			}
			pkg_free(pkg);
		});
예제 #14
0
파일: fetch.c 프로젝트: vianaweb/pkg
static int
pkg_repo_binary_try_fetch(struct pkg_repo *repo, struct pkg *pkg,
	bool already_tried, bool mirror, const char *destdir)
{
	char dest[MAXPATHLEN];
	char url[MAXPATHLEN];
	char *dir = NULL;
	int fetched = 0;
	char cksum[SHA256_DIGEST_LENGTH * 2 +1];
	int64_t pkgsize;
	struct stat st;
	char *path = NULL;
	const char *packagesite = NULL, *repourl;

	int retcode = EPKG_OK;
	const char *name, *version, *sum;

	assert((pkg->type & PKG_REMOTE) == PKG_REMOTE);

	pkg_get(pkg, PKG_CKSUM, &sum,
			PKG_NAME, &name, PKG_VERSION, &version, PKG_PKGSIZE, &pkgsize,
			PKG_REPOPATH, &repourl);

	if (mirror) {
		const char *cachedir;

		if (destdir != NULL)
			cachedir = destdir;
		else
			cachedir = pkg_object_string(pkg_config_get("PKG_CACHEDIR"));

		snprintf(dest, sizeof(dest), "%s/%s",
						cachedir, repourl);
	}
	else
		pkg_repo_binary_get_cached_name(repo, pkg, dest, sizeof(dest));

	/* If it is already in the local cachedir, dont bother to
	 * download it */
	if (access(dest, F_OK) == 0)
		goto checksum;

	/* Create the dirs in cachedir */
	dir = strdup(dest);
	if (dir == NULL || (path = dirname(dir)) == NULL) {
		pkg_emit_errno("dirname", dest);
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	if ((retcode = mkdirs(path)) != EPKG_OK)
		goto cleanup;

	/*
	 * In multi-repos the remote URL is stored in pkg[PKG_REPOURL]
	 * For a single attached database the repository URL should be
	 * defined by PACKAGESITE.
	 */
	packagesite = pkg_repo_url(repo);

	if (packagesite == NULL || packagesite[0] == '\0') {
		pkg_emit_error("PACKAGESITE is not defined");
		retcode = 1;
		goto cleanup;
	}

	if (packagesite[strlen(packagesite) - 1] == '/')
		pkg_snprintf(url, sizeof(url), "%S%R", packagesite, pkg);
	else
		pkg_snprintf(url, sizeof(url), "%S/%R", packagesite, pkg);

	if (!mirror && strncasecmp(packagesite, "file://", 7) == 0) {
		pkg_set(pkg, PKG_REPOPATH, url + 7);
		return (EPKG_OK);
	}

	retcode = pkg_fetch_file(repo, url, dest, 0);
	fetched = 1;

	if (retcode != EPKG_OK)
		goto cleanup;

checksum:
	/*	checksum calculation is expensive, if size does not
		match, skip it and assume failed checksum. */
	if (stat(dest, &st) == -1 || pkgsize != st.st_size) {
		if (already_tried) {
			pkg_emit_error("cached package %s-%s: "
				"size mismatch, cannot continue",
				name, version);
			retcode = EPKG_FATAL;
			goto cleanup;
		}

		unlink(dest);
		pkg_emit_error("cached package %s-%s: "
			"size mismatch, fetching from remote",
			name, version);
		return (pkg_repo_binary_try_fetch(repo, pkg, true, mirror, destdir));
	}
	retcode = sha256_file(dest, cksum);
	if (retcode == EPKG_OK) {
		if (strcmp(cksum, sum)) {
			if (already_tried || fetched == 1) {
				pkg_emit_error("%s-%s failed checksum "
				    "from repository", name, version);
				retcode = EPKG_FATAL;
			} else {
				pkg_emit_error("cached package %s-%s: "
				    "checksum mismatch, fetching from remote",
				    name, version);
				unlink(dest);
				return (pkg_repo_binary_try_fetch(repo, pkg, true, mirror, destdir));
			}
		}
	}

cleanup:

	if (retcode != EPKG_OK)
		unlink(dest);
	else if (!mirror && path != NULL) {
		(void)pkg_repo_binary_create_symlink(pkg, dest, path);
	}

	/* allowed even if dir is NULL */
	free(dir);

	return (retcode);
}
예제 #15
0
파일: pkg_elf.c 프로젝트: ctuffli/pkg
static int
analyse_elf(struct pkg *pkg, const char *fpath)
{
	Elf *e = NULL;
	GElf_Ehdr elfhdr;
	Elf_Scn *scn = NULL;
	Elf_Scn *note = NULL;
	Elf_Scn *dynamic = NULL;
	GElf_Shdr shdr;
	Elf_Data *data;
	GElf_Dyn *dyn, dyn_mem;
	struct stat sb;
	int ret = EPKG_OK;

	size_t numdyn = 0;
	size_t sh_link = 0;
	size_t dynidx;
	const char *osname;
	const char *myarch;
	const char *shlib;

	bool is_shlib = false;

	myarch = pkg_object_string(pkg_config_get("ABI"));

	int fd;

	pkg_debug(1, "analysing elf");
	if (lstat(fpath, &sb) != 0)
		pkg_emit_errno("fstat() failed for", fpath);
	/* ignore empty files and non regular files */
	if (sb.st_size == 0 || !S_ISREG(sb.st_mode))
		return (EPKG_END); /* Empty file or sym-link: no results */

	if ((fd = open(fpath, O_RDONLY, 0)) < 0) {
		return (EPKG_FATAL);
	}

	if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
		ret = EPKG_FATAL;
		pkg_emit_error("elf_begin() for %s failed: %s", fpath,
		    elf_errmsg(-1));
		goto cleanup;
	}

	if (elf_kind(e) != ELF_K_ELF) {
		/* Not an elf file: no results */
		ret = EPKG_END;
		goto cleanup;
	}

	if (developer_mode)
		pkg->flags |= PKG_CONTAINS_ELF_OBJECTS;

	if (gelf_getehdr(e, &elfhdr) == NULL) {
		ret = EPKG_FATAL;
		pkg_emit_error("getehdr() failed: %s.", elf_errmsg(-1));
		goto cleanup;
	}

	if (elfhdr.e_type != ET_DYN && elfhdr.e_type != ET_EXEC &&
	    elfhdr.e_type != ET_REL) {
		ret = EPKG_END;
		goto cleanup;
	}

	/* Elf file has sections header */
	while ((scn = elf_nextscn(e, scn)) != NULL) {
		if (gelf_getshdr(scn, &shdr) != &shdr) {
			ret = EPKG_FATAL;
			pkg_emit_error("getshdr() for %s failed: %s", fpath,
					elf_errmsg(-1));
			goto cleanup;
		}
		switch (shdr.sh_type) {
		case SHT_NOTE:
			if ((data = elf_getdata(scn, NULL)) == NULL) {
				ret = EPKG_END; /* Some error occurred, ignore this file */
				goto cleanup;
			}
			else if (data->d_buf != NULL) {
				Elf_Note *en = (Elf_Note *)data->d_buf;
				if (en->n_type == NT_ABI_TAG)
					note = scn;
			}
			break;
		case SHT_DYNAMIC:
			dynamic = scn;
			sh_link = shdr.sh_link;
			numdyn = shdr.sh_size / shdr.sh_entsize;
			break;
		}

		if (note != NULL && dynamic != NULL)
			break;
	}

	/*
	 * note == NULL usually means a shared object for use with dlopen(3)
	 * dynamic == NULL means not a dynamically linked elf
	 */
	if (dynamic == NULL) {
		ret = EPKG_END;
		goto cleanup; /* not a dynamically linked elf: no results */
	}

	if (!shlib_valid_abi(fpath, &elfhdr, myarch)) {
		ret = EPKG_END;
		goto cleanup; /* Invalid ABI */
	}

	if (note != NULL) {
		if ((data = elf_getdata(note, NULL)) == NULL) {
			ret = EPKG_END; /* Some error occurred, ignore this file */
			goto cleanup;
		}
		if (data->d_buf == NULL) {
			ret = EPKG_END; /* No osname available */
			goto cleanup;
		}
		osname = (const char *) data->d_buf + sizeof(Elf_Note);
		if (strncasecmp(osname, "freebsd", sizeof("freebsd")) != 0 &&
		    strncasecmp(osname, "dragonfly", sizeof("dragonfly")) != 0) {
			ret = EPKG_END;	/* Foreign (probably linux) ELF object */
			goto cleanup;
		}
	} else {
		if (elfhdr.e_ident[EI_OSABI] != ELFOSABI_FREEBSD &&
		    !is_old_freebsd_armheader(&elfhdr)) {
			ret = EPKG_END;
			goto cleanup;
		}
	}

	if ((data = elf_getdata(dynamic, NULL)) == NULL) {
		ret = EPKG_END; /* Some error occurred, ignore this file */
		goto cleanup;
	}

	/* First, scan through the data from the .dynamic section to
	   find any RPATH or RUNPATH settings.  These are colon
	   separated paths to prepend to the ld.so search paths from
	   the ELF hints file.  These always seem to come right after
	   the NEEDED shared library entries.

	   NEEDED entries should resolve to a filename for installed
	   executables, but need not resolve for installed shared
	   libraries -- additional info from the apps that link
	   against them would be required.  Shared libraries are
	   distinguished by a DT_SONAME tag */

	rpath_list_init();
	for (dynidx = 0; dynidx < numdyn; dynidx++) {
		if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL) {
			ret = EPKG_FATAL;
			pkg_emit_error("getdyn() failed for %s: %s", fpath,
			    elf_errmsg(-1));
			goto cleanup;
		}

		if (dyn->d_tag == DT_SONAME) {
			is_shlib = true;

			/* The file being scanned is a shared library
			   *provided* by the package. Record this if
			   appropriate */

			pkg_addshlib_provided(pkg, elf_strptr(e, sh_link, dyn->d_un.d_val));
		}

		if (dyn->d_tag != DT_RPATH && dyn->d_tag != DT_RUNPATH)
			continue;
		
		shlib_list_from_rpath(elf_strptr(e, sh_link, dyn->d_un.d_val),
				      bsd_dirname(fpath));
		break;
	}

	/* Now find all of the NEEDED shared libraries. */

	for (dynidx = 0; dynidx < numdyn; dynidx++) {
		if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL) {
			ret = EPKG_FATAL;
			pkg_emit_error("getdyn() failed for %s: %s", fpath,
			    elf_errmsg(-1));
			goto cleanup;
		}

		if (dyn->d_tag != DT_NEEDED)
			continue;

		shlib = elf_strptr(e, sh_link, dyn->d_un.d_val);

		add_shlibs_to_pkg(pkg, fpath, shlib, is_shlib);
	}

cleanup:
	rpath_list_free();

	if (e != NULL)
		elf_end(e);
	close(fd);

	return (ret);
}
예제 #16
0
파일: pkg_old.c 프로젝트: dumbbell/pkg
int
pkg_register_old(struct pkg *pkg)
{
	FILE *fp;
	char *content;
	const char *pkgdbdir, *tmp;
	char path[MAXPATHLEN];
	struct sbuf *install_script = sbuf_new_auto();
	struct sbuf *deinstall_script = sbuf_new_auto();
	struct pkg_dep *dep = NULL;

	pkg_to_old(pkg);
	pkg_old_emit_content(pkg, &content);

	pkgdbdir = pkg_object_string(pkg_config_get("PKG_DBDIR"));
	pkg_snprintf(path, sizeof(path), "%S/%n-%v", pkgdbdir, pkg, pkg);
	mkdir(path, 0755);

	pkg_snprintf(path, sizeof(path), "%S/%n-%v/+CONTENTS", pkgdbdir, pkg, pkg);
	fp = fopen(path, "w");
	fputs(content, fp);
	fclose(fp);

	pkg_snprintf(path, sizeof(path), "%S/%n-%v/+DESC", pkgdbdir, pkg, pkg);
	fp = fopen(path, "w");
	pkg_fprintf(fp, "%e", pkg);
	fclose(fp);

	pkg_snprintf(path, sizeof(path), "%s/%n-%v/+COMMENT", pkgdbdir, pkg, pkg);
	fp = fopen(path, "w");
	pkg_fprintf(fp, "%c\n", pkg);
	fclose(fp);

	if (pkg_has_message(pkg)) {
		pkg_snprintf(path, sizeof(path), "%s/%n-%v/+DISPLAY", pkgdbdir, pkg, pkg);
		fp = fopen(path, "w");
		pkg_fprintf(fp, "%M", pkg);
		fclose(fp);
	}

	sbuf_clear(install_script);
	tmp = pkg_script_get(pkg, PKG_SCRIPT_PRE_INSTALL);
	if (tmp != NULL && *tmp != '\0') {
		if (sbuf_len(install_script) == 0)
			sbuf_cat(install_script, "#!/bin/sh\n\n");
		sbuf_printf(install_script,
		    "if [ \"$2\" = \"PRE-INSTALL\" ]; then\n"
		    "%s\n"
		    "fi\n",
		    tmp);
	}

	tmp = pkg_script_get(pkg, PKG_SCRIPT_INSTALL);
	if (tmp != NULL && *tmp != '\0') {
		if (sbuf_len(install_script) == 0)
			sbuf_cat(install_script, "#!/bin/sh\n\n");
		sbuf_cat(install_script, tmp);
	}

	tmp = pkg_script_get(pkg, PKG_SCRIPT_POST_INSTALL);
	if (tmp != NULL && *tmp != '\0') {
		if (sbuf_len(install_script) == 0)
			sbuf_cat(install_script, "#!/bin/sh\n\n");
		sbuf_printf(install_script,
		    "if [ \"$2\" = \"POST-INSTALL\" ]; then\n"
		    "%s\n"
		    "fi\n",
		    tmp);
	}
	if (sbuf_len(install_script) > 0) {
		sbuf_finish(install_script);
		pkg_snprintf(path, sizeof(path), "%s/%n-%v/+INSTALL", pkgdbdir, pkg, pkg);
		fp = fopen(path, "w");
		fputs(sbuf_data(install_script), fp);
		fclose(fp);
	}

	sbuf_clear(deinstall_script);
	tmp = pkg_script_get(pkg, PKG_SCRIPT_PRE_DEINSTALL);
	if (tmp != NULL && *tmp != '\0') {
		if (sbuf_len(deinstall_script) == 0)
			sbuf_cat(deinstall_script, "#!/bin/sh\n\n");
		sbuf_printf(deinstall_script,
		    "if [ \"$2\" = \"DEINSTALL\" ]; then\n"
		    "%s\n"
		    "fi\n",
		    tmp);
	}

	tmp = pkg_script_get(pkg, PKG_SCRIPT_DEINSTALL);
	if (tmp != NULL && *tmp != '\0') {
		if (sbuf_len(deinstall_script) == 0)
			sbuf_cat(deinstall_script, "#!/bin/sh\n\n");
		sbuf_cat(deinstall_script, tmp);
	}

	tmp = pkg_script_get(pkg, PKG_SCRIPT_POST_DEINSTALL);
	if (tmp != NULL && tmp[0] != '\0') {
		if (sbuf_len(deinstall_script) == 0)
			sbuf_cat(deinstall_script, "#!/bin/sh\n\n");
		sbuf_printf(deinstall_script,
		    "if [ \"$2\" = \"POST-DEINSTALL\" ]; then\n"
		    "%s\n"
		    "fi\n",
		    tmp);
	}
	if (sbuf_len(deinstall_script) > 0) {
		sbuf_finish(deinstall_script);
		pkg_snprintf(path, sizeof(path), "%s/%n-%v/+DEINSTALL", pkgdbdir, pkg, pkg);
		fp = fopen(path, "w");
		fputs(sbuf_data(deinstall_script), fp);
		fclose(fp);
	}

	while (pkg_deps(pkg, &dep)) {
		snprintf(path, sizeof(path), "%s/%s-%s/+REQUIRED_BY", pkgdbdir,
		    pkg_dep_name(dep), pkg_dep_version(dep));
		fp = fopen(path, "a");
		pkg_fprintf(fp, "%n-%v\n", pkg, pkg);
		fclose(fp);
	}

	return (EPKG_OK);
}
예제 #17
0
int
exec_rquery(int argc, char **argv)
{
	struct pkgdb		*db = NULL;
	struct pkgdb_it		*it = NULL;
	struct pkg		*pkg = NULL;
	char			*pkgname = NULL;
	int			 query_flags = PKG_LOAD_BASIC;
	match_t			 match = MATCH_EXACT;
	int			 ch;
	int			 ret = EPKG_OK;
	int			 retcode = EX_OK;
	int			 i;
	char			 multiline = 0;
	char			*condition = NULL;
	const char		*portsdir;
	struct sbuf		*sqlcond = NULL;
	const unsigned int	 q_flags_len = NELEM(accepted_rquery_flags);
	const char		*reponame = NULL;
	bool			 auto_update;
	bool			 onematched = false;
	bool			 old_quiet;
	bool			 index_output = false;

	struct option longopts[] = {
		{ "all",		no_argument,		NULL,	'a' },
		{ "case-sensitive",	no_argument,		NULL,	'C' },
		{ "evaluate",		required_argument,	NULL,	'e' },
		{ "glob",		no_argument,		NULL,	'g' },
		{ "case-insensitive",	no_argument,		NULL,	'i' },
		{ "index-line",		no_argument,		NULL,	'I' },
		{ "repository",		required_argument,	NULL,	'r' },
		{ "no-repo-update",	no_argument,		NULL,	'U' },
		{ "regex",		no_argument,		NULL,	'x' },
		{ NULL,			0,			NULL,	0   },
	};

	portsdir = pkg_object_string(pkg_config_get("PORTSDIR"));

	while ((ch = getopt_long(argc, argv, "+aCgiIxe:r:U", longopts, NULL)) != -1) {
		switch (ch) {
		case 'a':
			match = MATCH_ALL;
			break;
		case 'C':
			pkgdb_set_case_sensitivity(true);
			break;
		case 'e':
			match = MATCH_CONDITION;
			condition = optarg;
			break;
		case 'g':
			match = MATCH_GLOB;
			break;
		case 'i':
			pkgdb_set_case_sensitivity(false);
			break;
		case 'I':
			index_output = true;
			break;
		case 'r':
			reponame = optarg;
			break;
		case 'U':
			auto_update = false;
			break;
		case 'x':
			match = MATCH_REGEX;
			break;
		default:
			usage_rquery();
			return (EX_USAGE);
		}
	}

	argc -= optind;
	argv += optind;

	if (argc == 0 && !index_output) {
		usage_rquery();
		return (EX_USAGE);
	}

	/* Default to all packages if no pkg provided */
	if (!index_output) {
		if (argc == 1 && condition == NULL && match == MATCH_EXACT) {
			match = MATCH_ALL;
		} else if (((argc == 1) ^ (match == MATCH_ALL )) && condition == NULL) {
			usage_rquery();
			return (EX_USAGE);
		}
	} else {
		if (argc == 0)
			match = MATCH_ALL;
	}

	if (!index_output && analyse_query_string(argv[0], accepted_rquery_flags, q_flags_len, &query_flags, &multiline) != EPKG_OK)
		return (EX_USAGE);

	if (condition != NULL) {
		sqlcond = sbuf_new_auto();
		if (format_sql_condition(condition, sqlcond, true) != EPKG_OK)
			return (EX_USAGE);
		sbuf_finish(sqlcond);
	}

	ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_REPO);
	if (ret == EPKG_ENOACCESS) {
		warnx("Insufficient privileges to query the package database");
		return (EX_NOPERM);
	} else if (ret != EPKG_OK)
		return (EX_IOERR);

	/* first update the remote repositories if needed */
	old_quiet = quiet;
	quiet = true;
	if (auto_update && (ret = pkgcli_update(false, false, reponame)) != EPKG_OK)
		return (ret);
	quiet = old_quiet;

	ret = pkgdb_open_all(&db, PKGDB_REMOTE, reponame);
	if (ret != EPKG_OK)
		return (EX_IOERR);

	if (index_output)
		query_flags = PKG_LOAD_BASIC|PKG_LOAD_CATEGORIES|PKG_LOAD_DEPS;

	if (match == MATCH_ALL || match == MATCH_CONDITION) {
		const char *condition_sql = NULL;
		if (match == MATCH_CONDITION && sqlcond)
			condition_sql = sbuf_data(sqlcond);
		if ((it = pkgdb_repo_query(db, condition_sql, match, reponame)) == NULL)
			return (EX_IOERR);

		while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) {
			if (index_output)
				print_index(pkg, portsdir);
			else
				print_query(pkg, argv[0],  multiline);
		}

		if (ret != EPKG_END)
			retcode = EX_SOFTWARE;

		pkgdb_it_free(it);
	} else {
		for (i = (index_output ? 0 : 1); i < argc; i++) {
			pkgname = argv[i];

			if ((it = pkgdb_repo_query(db, pkgname, match, reponame)) == NULL)
				return (EX_IOERR);

			while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) {
				onematched = true;
				if (index_output)
					print_index(pkg, portsdir);
				else
					print_query(pkg, argv[0], multiline);
			}

			if (ret != EPKG_END) {
				retcode = EX_SOFTWARE;
				break;
			}

			pkgdb_it_free(it);
		}
		if (!onematched && retcode == EX_OK)
			retcode = EX_UNAVAILABLE;
	}

	pkg_free(pkg);
	pkgdb_close(db);

	return (retcode);
}
예제 #18
0
파일: pkg_status.c 프로젝트: rakhij/pkg
pkg_status_t
pkg_status(int *count)
{
	pkg_object	*o;
	const char	*progname;
	char		 dbpath[MAXPATHLEN];
	int		 numpkgs = 0;
	sqlite3		*db = NULL;
	sqlite3_stmt	*stmt = NULL;
	const char      *sql = "SELECT COUNT(*) FROM packages";
	bool		 dbsuccess;

	/* Is this executable called pkg, or does pkg exist at
	   $LOCALBASE/sbin/pkg.  Ditto: pkg-static. Portability:
	   assumes setprogname() has been called */

	progname = getprogname();
	if (progname == NULL)
		return (PKG_STATUS_UNINSTALLED);

	if (strcmp(progname, PKG_EXEC_NAME) != 0   &&
	    strcmp(progname, PKG_STATIC_NAME) != 0 &&
	    !is_exec_at_localbase(PKG_EXEC_NAME)   &&
	    !is_exec_at_localbase(PKG_STATIC_NAME))
		return (PKG_STATUS_UNINSTALLED);

	/* Does the local.sqlite pkg database exist, and can we open
	   it for reading? */

	o = pkg_config_get("PKG_DBDIR");
	snprintf(dbpath, sizeof(dbpath), "%s/local.sqlite", pkg_object_string(o));

	if (eaccess(dbpath, R_OK) == -1)
		return (PKG_STATUS_NODB);
	
	/* Try opening the DB and preparing and running a simple query. */

	dbsuccess = (sqlite3_initialize() == SQLITE_OK);
	if (dbsuccess) {
		dbsuccess = (sqlite3_open_v2(dbpath, &db, SQLITE_OPEN_READONLY, NULL) == SQLITE_OK);
		if (dbsuccess) {
			dbsuccess = (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK);
			if (dbsuccess) {
				dbsuccess = (sqlite3_step(stmt) == SQLITE_ROW);
				if (dbsuccess) {
					numpkgs = sqlite3_column_int(stmt, 0);
				}
				sqlite3_finalize(stmt);
			}
			sqlite3_close(db);
		}
		sqlite3_shutdown();
	}

	if (!dbsuccess)
		return (PKG_STATUS_NODB);

	/* Save result, if requested */
	if (count != NULL)
		*count = numpkgs;

	return (numpkgs == 0 ? PKG_STATUS_NOPACKAGES : PKG_STATUS_ACTIVE);
}
예제 #19
0
파일: pkg_create.c 프로젝트: rakhij/pkg
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);
}
예제 #20
0
파일: clean.c 프로젝트: AsherBond/pkg
int
exec_clean(int argc, char **argv)
{
	struct pkgdb	*db = NULL;
	struct pkgdb_it	*it = NULL;
	struct pkg	*p = NULL;
	struct sumlist	*sumlist = NULL, *s, *t;
	FTS		*fts = NULL;
	FTSENT		*ent = NULL;
	struct dl_head	dl = STAILQ_HEAD_INITIALIZER(dl);
	const char	*cachedir, *sum, *name;
	char		*paths[2], csum[PKG_FILE_CKSUM_CHARS + 1],
			link_buf[MAXPATHLEN];
	bool		 all = false;
	bool		 sumloaded = false;
	int		 retcode;
	int		 ch, cnt = 0;
	size_t		 total = 0, slen;
	ssize_t		 link_len;
	char		 size[7];
	struct pkg_manifest_key *keys = NULL;

	struct option longopts[] = {
		{ "all",	no_argument,	NULL,	'a' },
		{ "dry-run",	no_argument,	NULL,	'n' },
		{ "quiet",	no_argument,	NULL,	'q' },
		{ "yes",	no_argument,	NULL,	'y' },
		{ NULL,		0,		NULL,	0   },
	};

	while ((ch = getopt_long(argc, argv, "+anqy", longopts, NULL)) != -1) {
		switch (ch) {
		case 'a':
			all = true;
			break;
		case 'n':
			dry_run = true;
			break;
		case 'q':
			quiet = true;
			break;
		case 'y':
			yes = true;
			break;
		default:
			usage_clean();
			return (EX_USAGE);
		}
	}
	argc -= optind;
	argv += optind;

	cachedir = pkg_object_string(pkg_config_get("PKG_CACHEDIR"));

	paths[0] = __DECONST(char*, cachedir);
	paths[1] = NULL;

	retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_REPO);

	if (retcode == EPKG_ENOACCESS) {
		warnx("Insufficient privileges to clean old packages");
		return (EX_NOPERM);
	} else if (retcode == EPKG_ENODB) {
		warnx("No package database installed.  Nothing to do!");
		return (EX_OK);
	} else if (retcode != EPKG_OK) {
		warnx("Error accessing the package database");
		return (EX_SOFTWARE);
	}

	retcode = EX_SOFTWARE;

	if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK)
		return (EX_IOERR);

	if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
		pkgdb_close(db);
		warnx("Cannot get a read lock on a database, it is locked by another process");
		return (EX_TEMPFAIL);
	}

	if ((fts = fts_open(paths, FTS_PHYSICAL, NULL)) == NULL) {
		warn("fts_open(%s)", cachedir);
		goto cleanup;
	}

	/* Build the list of out-of-date or obsolete packages */

	pkg_manifest_keys_new(&keys);
	while ((ent = fts_read(fts)) != NULL) {
		if (ent->fts_info != FTS_F && ent->fts_info != FTS_SL)
			continue;

		if (all) {
			retcode = add_to_dellist(&dl, ent->fts_path);
			if (retcode == EPKG_OK) {
				total += ent->fts_statp->st_size;
				++cnt;
			}
			continue;
		}

		if (sumlist == NULL && !sumloaded) {
			it = pkgdb_repo_search(db, "*", MATCH_GLOB, FIELD_NAME, FIELD_NONE, NULL);
			while (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK) {
				pkg_get(p, PKG_CKSUM, &sum);
				slen = MIN(strlen(sum), PKG_FILE_CKSUM_CHARS);
				s = calloc(1, sizeof(struct sumlist));
				memcpy(s->sum, sum, slen);
				s->sum[slen] = '\0';
				HASH_ADD_STR(sumlist, sum, s);
			}
		}

		if (ent->fts_info == FTS_SL) {
			/* Dereference the symlink and check it for being
			 * recognized checksum file, or delete the symlink
			 * later. */
			if ((link_len = readlink(ent->fts_name, link_buf,
			    sizeof(link_buf))) == -1)
				continue;
			link_buf[link_len] = '\0';
			name = link_buf;
		} else
			name = ent->fts_name;

		s = NULL;
		if (extract_filename_sum(name, csum))
			HASH_FIND_STR(sumlist, csum, s);
		if (s == NULL) {
			retcode = add_to_dellist(&dl, ent->fts_path);
			if (retcode == EPKG_OK) {
				total += ent->fts_statp->st_size;
				++cnt;
			}
			continue;
		}
	}
	HASH_ITER(hh, sumlist, s, t) {
		HASH_DEL(sumlist, s);
		free(s);
	}
예제 #21
0
파일: clean.c 프로젝트: grembo/pkg
int
exec_clean(int argc, char **argv)
{
	struct pkgdb	*db = NULL;
	kh_sum_t	*sumlist = NULL;
	dl_list		 dl;
	const char	*cachedir;
	bool		 all = false;
	int		 retcode;
	int		 ch;
	int		 cachefd = -1;
	size_t		 total = 0;
	char		 size[8];
	char		*cksum;
	struct pkg_manifest_key *keys = NULL;
#ifdef HAVE_CAPSICUM
	cap_rights_t rights;
#endif

	struct option longopts[] = {
		{ "all",	no_argument,	NULL,	'a' },
		{ "dry-run",	no_argument,	NULL,	'n' },
		{ "quiet",	no_argument,	NULL,	'q' },
		{ "yes",	no_argument,	NULL,	'y' },
		{ NULL,		0,		NULL,	0   },
	};

	while ((ch = getopt_long(argc, argv, "+anqy", longopts, NULL)) != -1) {
		switch (ch) {
		case 'a':
			all = true;
			break;
		case 'n':
			dry_run = true;
			break;
		case 'q':
			quiet = true;
			break;
		case 'y':
			yes = true;
			break;
		default:
			usage_clean();
			return (EX_USAGE);
		}
	}
	argc -= optind;
	argv += optind;

	cachedir = pkg_object_string(pkg_config_get("PKG_CACHEDIR"));
	cachefd = open(cachedir, O_DIRECTORY);
	if (cachefd == -1) {
		warn("Impossible to open %s", cachedir);
		return (EX_IOERR);
	}

	retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_REPO);

	if (retcode == EPKG_ENOACCESS) {
		warnx("Insufficient privileges to clean old packages");
		close(cachefd);
		return (EX_NOPERM);
	} else if (retcode == EPKG_ENODB) {
		warnx("No package database installed.  Nothing to do!");
		close(cachefd);
		return (EX_OK);
	} else if (retcode != EPKG_OK) {
		warnx("Error accessing the package database");
		close(cachefd);
		return (EX_SOFTWARE);
	}

	retcode = EX_SOFTWARE;

	if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) {
		close(cachefd);
		return (EX_IOERR);
	}

	if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
		pkgdb_close(db);
		close(cachefd);
		warnx("Cannot get a read lock on a database, it is locked by "
		    "another process");
		return (EX_TEMPFAIL);
	}

#ifdef HAVE_CAPSICUM
		cap_rights_init(&rights, CAP_READ, CAP_LOOKUP, CAP_FSTATFS,
		    CAP_FSTAT, CAP_UNLINKAT);
		if (cap_rights_limit(cachefd, &rights) < 0 && errno != ENOSYS ) {
			warn("cap_rights_limit() failed");
			close(cachefd);
			return (EX_SOFTWARE);
		}

		if (cap_enter() < 0 && errno != ENOSYS) {
			warn("cap_enter() failed");
			close(cachefd);
			return (EX_SOFTWARE);
		}
#endif

	kv_init(dl);

	/* Build the list of out-of-date or obsolete packages */

	pkg_manifest_keys_new(&keys);
	recursive_analysis(cachefd, db, cachedir, cachedir, &dl, &sumlist, all,
	    &total);
	if (sumlist != NULL) {
		kh_foreach_value(sumlist, cksum, free(cksum));
		kh_destroy_sum(sumlist);
	}

	if (kv_size(dl) == 0) {
		if (!quiet)
			printf("Nothing to do.\n");
		retcode = EX_OK;
		goto cleanup;
	}

	humanize_number(size, sizeof(size), total, "B",
	    HN_AUTOSCALE, HN_IEC_PREFIXES);

	if (!quiet)
		printf("The cleanup will free %s\n", size);
	if (!dry_run) {
			if (query_yesno(false,
			  "\nProceed with cleaning the cache? ")) {
				retcode = delete_dellist(cachefd, cachedir, &dl, kv_size(dl));
			}
	} else {
		retcode = EX_OK;
	}

cleanup:
	pkgdb_release_lock(db, PKGDB_LOCK_READONLY);
	pkgdb_close(db);
	pkg_manifest_keys_free(keys);
	free_dellist(&dl);

	if (cachefd != -1)
		close(cachefd);

	return (retcode);
}
예제 #22
0
파일: init.c 프로젝트: 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);
}
예제 #23
0
파일: ssh.c 프로젝트: AMDmi3/pkg
int
pkg_sshserve(int fd)
{
	struct stat st;
	char *line = NULL;
	char *file, *age;
	size_t linecap = 0, r;
	ssize_t linelen;
	time_t mtime = 0;
	const char *errstr;
	int ffd;
	char buf[BUFSIZ];
	char fpath[MAXPATHLEN];
	char rpath[MAXPATHLEN];
	const char *restricted = NULL;

	restricted = pkg_object_string(pkg_config_get("SSH_RESTRICT_DIR"));

	printf("ok: pkg "PKGVERSION"\n");
	for (;;) {
		if ((linelen = getline(&line, &linecap, stdin)) < 0)
			break;

		if (linelen == 0)
			continue;

		/* trim cr */
		if (line[linelen - 1] == '\n')
			line[linelen - 1] = '\0';

		if (strcmp(line, "quit") == 0)
			return (EPKG_OK);

		if (strncmp(line, "get ", 4) != 0) {
			printf("ko: unknown command '%s'\n", line);
			continue;
		}

		file = line + 4;

		if (*file == '/')
			file++;
		else if (*file == '\0') {
			printf("ko: bad command get, expecting 'get file age'\n");
			continue;
		}

		pkg_debug(1, "SSH server> file requested: %s", file);

		age = file;
		while (!isspace(*age)) {
			if (*age == '\0') {
				age = NULL;
				break;
			}
			age++;
		}

		if (age == NULL) {
			printf("ko: bad command get, expecting 'get file age'\n");
			continue;
		}

		*age = '\0';
		age++;

		while (isspace(*age)) {
			if (*age == '\0') {
				age = NULL;
				break;
			}
			age++;
		}

		if (age == NULL) {
			printf("ko: bad command get, expecting 'get file age'\n");
			continue;
		}

		mtime = strtonum(age, 0, LONG_MAX, &errstr);
		if (errstr) {
			printf("ko: bad number %s: %s\n", age, errstr);
			continue;
		}

#ifdef HAVE_CAPSICUM
		if (!cap_sandboxed() && restricted != NULL) {
#else
		if (restricted != NULL) {
#endif
			chdir(restricted);
			if (realpath(file, fpath) == NULL ||
			    realpath(restricted, rpath) == NULL ||
			    strncmp(fpath, rpath, strlen(rpath)) != 0) {
				printf("ko: file not found\n");
				continue;
			}
		}

		if (fstatat(fd, file, &st, 0) == -1) {
			pkg_debug(1, "SSH server> fstatat failed");
			printf("ko: file not found\n");
			continue;
		}

		if (!S_ISREG(st.st_mode)) {
			printf("ko: not a file\n");
			continue;
		}

		if (st.st_mtime <= mtime) {
			printf("ok: 0\n");
			continue;
		}

		if ((ffd = openat(fd, file, O_RDONLY)) == -1) {
			printf("ko: file not found\n");
			continue;
		}

		printf("ok: %" PRIdMAX "\n", (intmax_t)st.st_size);
		pkg_debug(1, "SSH server> sending ok: %" PRIdMAX "", (intmax_t)st.st_size);

		while ((r = read(ffd, buf, sizeof(buf))) > 0) {
			pkg_debug(1, "SSH server> sending data");
			fwrite(buf, 1, r, stdout);
		}

		pkg_debug(1, "SSH server> finished");

		close(ffd);
	}

	free(line);

	return (EPKG_OK);
}
예제 #24
0
int
exec_alias(int argc, char **argv)
{
	const pkg_object *all_aliases;
	const pkg_object *alias;
	pkg_iter it = NULL;
	int ch;
	int ret = EX_OK;
	bool list = false;

	struct option longopts[] = {
		{ "quiet",	no_argument,	NULL, 'q' },
		{ "list",	no_argument,	NULL, 'l' },
		{ NULL,		0,		NULL, 0 },
	};

	while ((ch = getopt_long(argc, argv, "+ql", longopts, NULL)) != -1) {
		switch (ch) {
		case 'q':
			quiet = true;
			break;
		case 'l':
			list = true;
			break;
		default:
			usage_alias();
			return (EX_USAGE);
		}
	}

	argc -= optind;
	argv += optind;

	all_aliases = pkg_config_get("ALIAS");

	if (argc == 0) {
		if (!quiet && list)
			printf("%s\n", "ALIAS");
		else if (!quiet)
			printf("%-20s %s\n", "ALIAS", "ARGUMENTS");
		while ((alias = pkg_object_iterate(all_aliases, &it))) {
			if (list)
				printf("%s\n", pkg_object_key(alias));
			else
				printf("%-20s '%s'\n", pkg_object_key(alias), pkg_object_string(alias));
		}
		return (ret);
	}

	for (int i = 0; i < argc; i++) {
		it = NULL;
		while ((alias = pkg_object_iterate(all_aliases, &it))) {
			if (strcmp(argv[i], pkg_object_key(alias)) == 0)
				break;
		}
		if (alias) {
			if (list)
				printf("%s\n", argv[i]);
			else
				printf("%-20s '%s'\n", argv[i], pkg_object_string(alias));
		} else {
			warnx("No such alias: '%s'", argv[i]);
			ret = EX_UNAVAILABLE;
		}
	}

	return (ret);
}
예제 #25
0
파일: pkg_config.c 프로젝트: dumbbell/pkg
int
pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags)
{
	struct ucl_parser *p = NULL;
	size_t i;
	const char *val = NULL;
	const char *buf, *walk, *value, *key, *k;
	const char *evkey = NULL;
	const char *nsname = NULL;
	const char *evpipe = NULL;
	const ucl_object_t *cur, *object;
	ucl_object_t *obj = NULL, *o, *ncfg;
	ucl_object_iter_t it = NULL;
	struct sbuf *ukey = NULL;
	bool fatal_errors = false;

	k = NULL;
	o = NULL;

	pkg_get_myarch(myabi, BUFSIZ);
	pkg_get_myarch_legacy(myabi_legacy, BUFSIZ);
	if (parsed != false) {
		pkg_emit_error("pkg_init() must only be called once");
		return (EPKG_FATAL);
	}

	if (((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4) &&
	    ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6)) {
		pkg_emit_error("Invalid flags for pkg_init()");
		return (EPKG_FATAL);
	}

	config = ucl_object_typed_new(UCL_OBJECT);

	for (i = 0; i < c_size; i++) {
		switch (c[i].type) {
		case PKG_STRING:
			obj = ucl_object_fromstring_common(
			    c[i].def != NULL ? c[i].def : "", 0, UCL_STRING_TRIM);
			ucl_object_insert_key(config, obj,
			    c[i].key, strlen(c[i].key), false);
			break;
		case PKG_INT:
			ucl_object_insert_key(config,
			    ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_INT),
			    c[i].key, strlen(c[i].key), false);
			break;
		case PKG_BOOL:
			ucl_object_insert_key(config,
			    ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_BOOLEAN),
			    c[i].key, strlen(c[i].key), false);
			break;
		case PKG_OBJECT:
			obj = ucl_object_typed_new(UCL_OBJECT);
			if (c[i].def != NULL) {
				walk = buf = c[i].def;
				while ((buf = strchr(buf, ',')) != NULL) {
					key = walk;
					value = walk;
					while (*value != ',') {
						if (*value == '=')
							break;
						value++;
					}
					ucl_object_insert_key(obj,
					    ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM),
					    key, value - key, false);
					buf++;
					walk = buf;
				}
				key = walk;
				value = walk;
				while (*value != ',') {
					if (*value == '=')
						break;
					value++;
				}
				if (o == NULL)
					o = ucl_object_typed_new(UCL_OBJECT);
				ucl_object_insert_key(o,
				    ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM),
				    key, value - key, false);
			}
			ucl_object_insert_key(config, obj,
			    c[i].key, strlen(c[i].key), false);
			break;
		case PKG_ARRAY:
			obj = ucl_object_typed_new(UCL_ARRAY);
			if (c[i].def != NULL) {
				walk = buf = c[i].def;
				while ((buf = strchr(buf, ',')) != NULL) {
					ucl_array_append(obj,
					    ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM));
					buf++;
					walk = buf;
				}
				ucl_array_append(obj,
				    ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM));
			}
			ucl_object_insert_key(config, obj,
			    c[i].key, strlen(c[i].key), false);
			break;
		}
	}

	if (path == NULL)
		path = PREFIX"/etc/pkg.conf";

	p = ucl_parser_new(0);

	errno = 0;
	obj = NULL;
	if (!ucl_parser_add_file(p, path)) {
		if (errno != ENOENT)
			pkg_emit_error("Invalid configuration file: %s", ucl_parser_get_error(p));
	} else {
		obj = ucl_parser_get_object(p);

	}

	ncfg = NULL;
	while (obj != NULL && (cur = ucl_iterate_object(obj, &it, true))) {
		sbuf_init(&ukey);
		key = ucl_object_key(cur);
		for (i = 0; key[i] != '\0'; i++)
			sbuf_putc(ukey, toupper(key[i]));
		sbuf_finish(ukey);
		object = ucl_object_find_keyl(config, sbuf_data(ukey), sbuf_len(ukey));

		if (strncasecmp(sbuf_data(ukey), "PACKAGESITE", sbuf_len(ukey))
		    == 0 || strncasecmp(sbuf_data(ukey), "PUBKEY",
		    sbuf_len(ukey)) == 0 || strncasecmp(sbuf_data(ukey),
		    "MIRROR_TYPE", sbuf_len(ukey)) == 0) {
			pkg_emit_error("%s in pkg.conf is no longer "
			    "supported.  Convert to the new repository style."
			    "  See pkg.conf(5)", sbuf_data(ukey));
			fatal_errors = true;
			continue;
		}

		/* ignore unknown keys */
		if (object == NULL)
			continue;

		if (object->type != cur->type) {
			pkg_emit_error("Malformed key %s, ignoring", key);
			continue;
		}

		if (ncfg == NULL)
			ncfg = ucl_object_typed_new(UCL_OBJECT);
		ucl_object_insert_key(ncfg, ucl_object_copy(cur), sbuf_data(ukey), sbuf_len(ukey), true);
	}

	if (fatal_errors) {
		ucl_object_unref(ncfg);
		ucl_parser_free(p);
		return (EPKG_FATAL);
	}

	if (ncfg != NULL) {
		it = NULL;
		while (( cur = ucl_iterate_object(ncfg, &it, true))) {
			key = ucl_object_key(cur);
			ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true);
		}
		ucl_object_unref(ncfg);
	}

	ncfg = NULL;
	it = NULL;
	while ((cur = ucl_iterate_object(config, &it, true))) {
		o = NULL;
		key = ucl_object_key(cur);
		val = getenv(key);
		if (val == NULL)
			continue;
		switch (cur->type) {
		case UCL_STRING:
			o = ucl_object_fromstring_common(val, 0, UCL_STRING_TRIM);
			break;
		case UCL_INT:
			o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_INT);
			if (o->type != UCL_INT) {
				pkg_emit_error("Invalid type for environment "
				    "variable %s, got %s, while expecting an integer",
				    key, val);
				ucl_object_unref(o);
				continue;
			}
			break;
		case UCL_BOOLEAN:
			o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_BOOLEAN);
			if (o->type != UCL_BOOLEAN) {
				pkg_emit_error("Invalid type for environment "
				    "variable %s, got %s, while expecting a boolean",
				    key, val);
				ucl_object_unref(o);
				continue;
			}
			break;
		case UCL_OBJECT:
			o = ucl_object_typed_new(UCL_OBJECT);
			walk = buf = val;
			while ((buf = strchr(buf, ',')) != NULL) {
				k = walk;
				value = walk;
				while (*value != ',') {
					if (*value == '=')
						break;
					value++;
				}
				ucl_object_insert_key(o,
				    ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM),
				    k, value - k, false);
				buf++;
				walk = buf;
			}
			key = walk;
			value = walk;
			while (*value != '\0') {
				if (*value == '=')
					break;
				value++;
			}
			ucl_object_insert_key(o,
			    ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM),
			    k, value - k, false);
			break;
		case UCL_ARRAY:
			o = ucl_object_typed_new(UCL_ARRAY);
			walk = buf = val;
			while ((buf = strchr(buf, ',')) != NULL) {
				ucl_array_append(o,
				    ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM));
				buf++;
				walk = buf;
			}
			ucl_array_append(o,
			    ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM));
			break;
		default:
			/* ignore other types */
			break;
		}
		if (o != NULL) {
			if (ncfg == NULL)
				ncfg = ucl_object_typed_new(UCL_OBJECT);
			ucl_object_insert_key(ncfg, o, key, strlen(key), true);
		}
	}

	if (ncfg != NULL) {
		it = NULL;
		while (( cur = ucl_iterate_object(ncfg, &it, true))) {
			key = ucl_object_key(cur);
			ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true);
		}
		ucl_object_unref(ncfg);
	}

	disable_plugins_if_static();

	parsed = true;
	ucl_object_unref(obj);
	ucl_parser_free(p);

	if (strcmp(pkg_object_string(pkg_config_get("ABI")), "unknown") == 0) {
		pkg_emit_error("Unable to determine ABI");
		return (EPKG_FATAL);
	}

	pkg_debug(1, "%s", "pkg initialized");

	/* Start the event pipe */
	evpipe = pkg_object_string(pkg_config_get("EVENT_PIPE"));
	if (evpipe != NULL)
		connect_evpipe(evpipe);

	debug_level = pkg_object_int(pkg_config_get("DEBUG_LEVEL"));

	it = NULL;
	object = ucl_object_find_key(config, "PKG_ENV");
	while ((cur = ucl_iterate_object(object, &it, true))) {
		evkey = ucl_object_key(cur);
		pkg_debug(1, "Setting env var: %s", evkey);
		if (evkey != NULL && evkey[0] != '\0')
			setenv(evkey, ucl_object_tostring_forced(cur), 1);
	}

	/* load the repositories */
	load_repositories(reposdir, flags);

	setenv("HTTP_USER_AGENT", "pkg/"PKGVERSION, 1);

	/* bypass resolv.conf with specified NAMESERVER if any */
	nsname = pkg_object_string(pkg_config_get("NAMESERVER"));
	if (nsname != NULL)
		set_nameserver(ucl_object_tostring_forced(o));

	return (EPKG_OK);
}
예제 #26
0
파일: fetch.c 프로젝트: Moscarda/pkg
static int
pkg_repo_binary_try_fetch(struct pkg_repo *repo, struct pkg *pkg,
	bool already_tried, bool mirror, const char *destdir)
{
	char dest[MAXPATHLEN];
	char url[MAXPATHLEN];
	char *dir = NULL;
	bool fetched = false;
	struct stat st;
	char *path = NULL;
	const char *packagesite = NULL;
	ssize_t offset = -1;

	int retcode = EPKG_OK;

	assert((pkg->type & PKG_REMOTE) == PKG_REMOTE);

	if (mirror) {
		const char *cachedir;

		if (destdir != NULL)
			cachedir = destdir;
		else
			cachedir = pkg_object_string(pkg_config_get("PKG_CACHEDIR"));

		snprintf(dest, sizeof(dest), "%s/%s", cachedir, pkg->repopath);
	}
	else
		pkg_repo_binary_get_cached_name(repo, pkg, dest, sizeof(dest));

	/* If it is already in the local cachedir, dont bother to
	 * download it */
	if (stat(dest, &st) == 0) {
		/* try to resume */
		if (pkg->pkgsize > st.st_size) {
			offset = st.st_size;
			pkg_debug(1, "Resuming fetch");
		} else {
			goto checksum;
		}
	}

	/* Create the dirs in cachedir */
	dir = strdup(dest);
	if (dir == NULL || (path = dirname(dir)) == NULL) {
		pkg_emit_errno("dirname", dest);
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	if ((retcode = mkdirs(path)) != EPKG_OK)
		goto cleanup;

	/*
	 * In multi-repos the remote URL is stored in pkg[PKG_REPOURL]
	 * For a single attached database the repository URL should be
	 * defined by URL.
	 */
	packagesite = pkg_repo_url(repo);

	if (packagesite == NULL || packagesite[0] == '\0') {
		pkg_emit_error("URL is not defined");
		retcode = 1;
		goto cleanup;
	}

	if (packagesite[strlen(packagesite) - 1] == '/')
		pkg_snprintf(url, sizeof(url), "%S%R", packagesite, pkg);
	else
		pkg_snprintf(url, sizeof(url), "%S/%R", packagesite, pkg);

	if (!mirror && strncasecmp(packagesite, "file://", 7) == 0) {
		free(dir);
		return (EPKG_OK);
	}

	retcode = pkg_fetch_file(repo, url, dest, 0, offset, pkg->pkgsize);
	fetched = true;

	if (retcode != EPKG_OK)
		goto cleanup;

checksum:
	/*	checksum calculation is expensive, if size does not
		match, skip it and assume failed checksum. */
	if (stat(dest, &st) == -1 || pkg->pkgsize != st.st_size) {
		if (already_tried) {
			pkg_emit_error("cached package %s-%s: "
			    "size mismatch, cannot continue",
			    pkg->name, pkg->version);
			retcode = EPKG_FATAL;
			goto cleanup;
		}

		unlink(dest);
		free(dir);
		pkg_emit_error("cached package %s-%s: "
		    "size mismatch, fetching from remote",
		    pkg->name, pkg->version);
		return (pkg_repo_binary_try_fetch(repo, pkg, true, mirror, destdir));
	}
	if (pkg_checksum_validate_file(dest, pkg->sum) != 0) {
		if (already_tried || fetched) {
			pkg_emit_error("%s-%s failed checksum "
			    "from repository", pkg->name, pkg->version);
			retcode = EPKG_FATAL;
		} else {
			pkg_emit_error("cached package %s-%s: "
			    "checksum mismatch, fetching from remote",
			    pkg->name, pkg->version);
			unlink(dest);
			return (pkg_repo_binary_try_fetch(repo, pkg, true, mirror, destdir));
		}
	}

cleanup:

	if (retcode != EPKG_OK)
		unlink(dest);
	else if (!mirror && path != NULL) {
		(void)pkg_repo_binary_create_symlink(pkg, dest, path);
	}

	/* allowed even if dir is NULL */
	free(dir);

	return (retcode);
}
예제 #27
0
파일: update.c 프로젝트: zxombie/pkg
static int
pkg_repo_binary_add_pkg(struct pkg *pkg, const char *pkg_path,
		sqlite3 *sqlite, bool forced)
{
	const char *name, *version, *origin, *comment, *desc;
	const char *arch, *maintainer, *www, *prefix, *sum, *rpath;
	const char *olddigest, *manifestdigest;
	int64_t			 flatsize, pkgsize;
	int64_t			 licenselogic;
	int			 ret;
	struct pkg_dep		*dep      = NULL;
	struct pkg_option	*option   = NULL;
	struct pkg_shlib	*shlib    = NULL;
	const pkg_object	*obj, *licenses, *categories, *annotations;
	pkg_iter		 it;
	int64_t			 package_id;

	pkg_get(pkg, PKG_ORIGIN, &origin, PKG_NAME, &name,
			    PKG_VERSION, &version, PKG_COMMENT, &comment,
			    PKG_DESC, &desc, PKG_ARCH, &arch,
			    PKG_MAINTAINER, &maintainer, PKG_WWW, &www,
			    PKG_PREFIX, &prefix, PKG_FLATSIZE, &flatsize,
			    PKG_LICENSE_LOGIC, &licenselogic, PKG_CKSUM, &sum,
			    PKG_PKGSIZE, &pkgsize, PKG_REPOPATH, &rpath,
			    PKG_LICENSES, &licenses, PKG_CATEGORIES, &categories,
			    PKG_ANNOTATIONS, &annotations, PKG_OLD_DIGEST, &olddigest,
			    PKG_DIGEST, &manifestdigest);

try_again:
	if ((ret = pkg_repo_binary_run_prstatement(PKG, origin, name, version,
			comment, desc, arch, maintainer, www, prefix,
			pkgsize, flatsize, (int64_t)licenselogic, sum,
			rpath, manifestdigest, olddigest)) != SQLITE_DONE) {
		if (ret == SQLITE_CONSTRAINT) {
			switch(pkg_repo_binary_delete_conflicting(origin,
					version, pkg_path, forced)) {
			case EPKG_FATAL: /* sqlite error */
				ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(PKG));
				return (EPKG_FATAL);
				break;
			case EPKG_END: /* repo already has newer */
				return (EPKG_END);
				break;
			default: /* conflict cleared, try again */
				goto try_again;
				break;
			}
		} else {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(PKG));
			return (EPKG_FATAL);
		}
	}
	package_id = sqlite3_last_insert_rowid(sqlite);

	if (pkg_repo_binary_run_prstatement (FTS_APPEND, package_id,
			name, version, origin) != SQLITE_DONE) {
		ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(FTS_APPEND));
		return (EPKG_FATAL);
	}

	dep = NULL;
	while (pkg_deps(pkg, &dep) == EPKG_OK) {
		if (pkg_repo_binary_run_prstatement(DEPS,
				pkg_dep_origin(dep),
				pkg_dep_name(dep),
				pkg_dep_version(dep),
				package_id) != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(DEPS));
			return (EPKG_FATAL);
		}
	}

	it = NULL;
	while ((obj = pkg_object_iterate(categories, &it))) {
		ret = pkg_repo_binary_run_prstatement(CAT1, pkg_object_string(obj));
		if (ret == SQLITE_DONE)
			ret = pkg_repo_binary_run_prstatement(CAT2, package_id,
			    pkg_object_string(obj));
		if (ret != SQLITE_DONE)
		{
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(CAT2));
			return (EPKG_FATAL);
		}
	}

	it = NULL;
	while ((obj = pkg_object_iterate(licenses, &it))) {
		ret = pkg_repo_binary_run_prstatement(LIC1, pkg_object_string(obj));
		if (ret == SQLITE_DONE)
			ret = pkg_repo_binary_run_prstatement(LIC2, package_id,
			    pkg_object_string(obj));
		if (ret != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(LIC2));
			return (EPKG_FATAL);
		}
	}
	option = NULL;
	while (pkg_options(pkg, &option) == EPKG_OK) {
		ret = pkg_repo_binary_run_prstatement(OPT1, pkg_option_opt(option));
		if (ret == SQLITE_DONE)
		    ret = pkg_repo_binary_run_prstatement(OPT2, pkg_option_opt(option),
				pkg_option_value(option), package_id);
		if(ret != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(OPT2));
			return (EPKG_FATAL);
		}
	}

	shlib = NULL;
	while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
		const char *shlib_name = pkg_shlib_name(shlib);

		ret = pkg_repo_binary_run_prstatement(SHLIB1, shlib_name);
		if (ret == SQLITE_DONE)
			ret = pkg_repo_binary_run_prstatement(SHLIB_REQD, package_id,
					shlib_name);
		if (ret != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(SHLIB_REQD));
			return (EPKG_FATAL);
		}
	}

	shlib = NULL;
	while (pkg_shlibs_provided(pkg, &shlib) == EPKG_OK) {
		const char *shlib_name = pkg_shlib_name(shlib);

		ret = pkg_repo_binary_run_prstatement(SHLIB1, shlib_name);
		if (ret == SQLITE_DONE)
			ret = pkg_repo_binary_run_prstatement(SHLIB_PROV, package_id,
					shlib_name);
		if (ret != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(SHLIB_PROV));
			return (EPKG_FATAL);
		}
	}

	it = NULL;
	while ((obj = pkg_object_iterate(annotations, &it))) {
		const char *note_tag = pkg_object_key(obj);
		const char *note_val = pkg_object_string(obj);

		ret = pkg_repo_binary_run_prstatement(ANNOTATE1, note_tag);
		if (ret == SQLITE_DONE)
			ret = pkg_repo_binary_run_prstatement(ANNOTATE1, note_val);
		if (ret == SQLITE_DONE)
			ret = pkg_repo_binary_run_prstatement(ANNOTATE2, package_id,
				  note_tag, note_val);
		if (ret != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(ANNOTATE2));
			return (EPKG_FATAL);
		}
	}

	return (EPKG_OK);
}
예제 #28
0
파일: init.c 프로젝트: dpl0/pkg
int
pkg_repo_binary_create(struct pkg_repo *repo)
{
	char filepath[MAXPATHLEN];
	struct statfs stfs;
	const char *dbdir = NULL;
	sqlite3 *sqlite = NULL;
	int retcode;

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

	snprintf(filepath, sizeof(filepath), "%s/%s",
		dbdir, pkg_repo_binary_get_filename(pkg_repo_name(repo)));
	/* Should never ever happen */
	if (access(filepath, R_OK) == 0)
		return (EPKG_CONFLICT);

	/*
	 * 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);
	}

	/* Open for read/write/create */
	if (sqlite3_open(filepath, &sqlite) != SQLITE_OK)
		return (EPKG_FATAL);

	retcode = sql_exec(sqlite, binary_repo_initsql, REPO_SCHEMA_VERSION);

	if (retcode == EPKG_OK) {
		sqlite3_stmt *stmt;
		const char sql[] = ""
						"INSERT OR REPLACE INTO repodata (key, value) "
						"VALUES (\"packagesite\", ?1);";

		/* register the packagesite */
		if (sql_exec(sqlite, "CREATE TABLE IF NOT EXISTS repodata ("
			"   key TEXT UNIQUE NOT NULL,"
			"   value TEXT NOT NULL"
			");") != EPKG_OK) {
			pkg_emit_error("Unable to register the packagesite in the "
				"database");
			retcode = EPKG_FATAL;
			goto cleanup;
		}

		if (sqlite3_prepare_v2(sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
			ERROR_SQLITE(sqlite, sql);
			retcode = EPKG_FATAL;
			goto cleanup;
		}

		sqlite3_bind_text(stmt, 1, pkg_repo_url(repo), -1, SQLITE_STATIC);

		if (sqlite3_step(stmt) != SQLITE_DONE) {
			ERROR_SQLITE(sqlite, sql);
			sqlite3_finalize(stmt);
			retcode = EPKG_FATAL;
			goto cleanup;
		}

		sqlite3_finalize(stmt);
	}

cleanup:
	sqlite3_close(sqlite);

	return (retcode);
}