示例#1
0
int
pkgdb_dump(struct pkgdb *db, const char *dest)
{
	sqlite3	*backup;
	int	 ret;

	if (eaccess(dest, W_OK)) {
		if (errno != ENOENT) {
			pkg_fatal_errno("Unable to access '%s'", dest);
		}

		/* Could we create the Sqlite DB file? */
		if (eaccess(bsd_dirname(dest), W_OK)) {
			pkg_fatal_errno("Unable to access '%s'",
			    bsd_dirname(dest));
		}
	}

	ret = sqlite3_open(dest, &backup);

	if (ret != SQLITE_OK) {
		ERROR_SQLITE(backup, "sqlite3_open");
		sqlite3_close(backup);
		return (EPKG_FATAL);
	}

	pkg_emit_backup();
	ret = copy_database(db->sqlite, backup);

	sqlite3_close(backup);

	return (ret == SQLITE_OK? EPKG_OK : EPKG_FATAL);
}
示例#2
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);
}