예제 #1
0
파일: pkg_elf.c 프로젝트: varju/pkgng
int
pkg_analyse_files(struct pkgdb *db, struct pkg *pkg)
{
	struct pkg_file *file = NULL;
	int ret = EPKG_OK;
	const char *fpath;
	bool shlibs = false;
	bool autodeps = false;
	bool developer = false;
	int (*action)(void *, struct pkg *, const char *, const char *, bool);

	pkg_config_bool(PKG_CONFIG_SHLIBS, &shlibs);
	pkg_config_bool(PKG_CONFIG_AUTODEPS, &autodeps);
	pkg_config_bool(PKG_CONFIG_DEVELOPER_MODE, &developer);

	if (!autodeps && !shlibs && !developer)
		return (EPKG_OK);

	if (elf_version(EV_CURRENT) == EV_NONE)
		return (EPKG_FATAL);

	if (autodeps)
		action = test_depends;
	else if (shlibs)
		action = add_shlibs_to_pkg;
	else
		action = do_nothing;

	if (autodeps || shlibs) {
		shlib_list_init();

		ret = shlib_list_from_elf_hints(_PATH_ELF_HINTS);
		if (ret != EPKG_OK)
			goto cleanup;
	}

	/* Assume no architecture dependence, for contradiction */
	if (developer)
		pkg->flags &= ~(PKG_CONTAINS_ELF_OBJECTS |
				PKG_CONTAINS_STATIC_LIBS |
				PKG_CONTAINS_H_OR_LA);

	while (pkg_files(pkg, &file) == EPKG_OK) {
		fpath = pkg_file_path(file);
		ret = analyse_elf(pkg, fpath, action, db);
		if (developer) {
			if (ret != EPKG_OK && ret != EPKG_END)
				goto cleanup;
			analyse_fpath(pkg, fpath);
		}
	}

	ret = EPKG_OK;

cleanup:
	if (autodeps || shlibs)
		shlib_list_free();

	return (ret);
}
예제 #2
0
파일: pkg_elf.c 프로젝트: dschossig/pkg
int
pkg_analyse_files(struct pkgdb *db, struct pkg *pkg, const char *stage)
{
	struct pkg_file *file = NULL;
	int ret = EPKG_OK;
	char fpath[MAXPATHLEN];
	bool autodeps = false;
	bool developer = false;
	int (*action)(void *, struct pkg *, const char *, const char *, bool);

	pkg_config_bool(PKG_CONFIG_AUTODEPS, &autodeps);
	pkg_config_bool(PKG_CONFIG_DEVELOPER_MODE, &developer);

	if (elf_version(EV_CURRENT) == EV_NONE)
		return (EPKG_FATAL);

	if (autodeps)
		action = test_depends;
	else
		action = add_shlibs_to_pkg;

	shlib_list_init();

	ret = shlib_list_from_elf_hints(_PATH_ELF_HINTS);
	if (ret != EPKG_OK)
		goto cleanup;

	/* Assume no architecture dependence, for contradiction */
	if (developer)
		pkg->flags &= ~(PKG_CONTAINS_ELF_OBJECTS |
				PKG_CONTAINS_STATIC_LIBS |
				PKG_CONTAINS_H_OR_LA);

	while (pkg_files(pkg, &file) == EPKG_OK) {
		if (stage != NULL)
			snprintf(fpath, sizeof(fpath), "%s/%s", stage, pkg_file_path(file));
		else
			strlcpy(fpath, pkg_file_path(file), sizeof(fpath));

		ret = analyse_elf(pkg, fpath, action, db);
		if (developer) {
			if (ret != EPKG_OK && ret != EPKG_END)
				goto cleanup;
			analyse_fpath(pkg, fpath);
		}
	}

	ret = EPKG_OK;

cleanup:
	shlib_list_free();

	return (ret);
}
예제 #3
0
파일: pkg_event.c 프로젝트: rg1/pkgng
void
pkg_emit_upgrade_finished(struct pkg *p)
{
    struct pkg_event ev;
    bool syslog_enabled = false;
    char *name, *version, *newversion;

    ev.type = PKG_EVENT_UPGRADE_FINISHED;
    ev.e_upgrade_finished.pkg = p;

    pkg_config_bool(PKG_CONFIG_SYSLOG, &syslog_enabled);
    if (syslog_enabled) {
        const char *actions[] = {
            "upgraded", "reinstalled", "downgraded"
        };
        int num_actions = sizeof(actions) / sizeof(*actions);
        int action;

        pkg_get(p, PKG_NAME, &name, PKG_VERSION, &version,
                PKG_NEWVERSION, &newversion);
        action = pkg_version_cmp(version, newversion) + 1;
        if (action >= 0 && action < num_actions)
            syslog(LOG_NOTICE, "%s %s: %s -> %s ",
                   name, actions[action], version, newversion);
    }

    pkg_emit_event(&ev);
}
예제 #4
0
파일: pkg_elf.c 프로젝트: varju/pkgng
int
pkg_register_shlibs(struct pkg *pkg)
{
	struct pkg_file        *file = NULL;
	bool			shlibs;

	pkg_config_bool(PKG_CONFIG_SHLIBS, &shlibs);

	pkg_list_free(pkg, PKG_SHLIBS_REQUIRED);

	if (!shlibs)
		return (EPKG_OK);

	if (elf_version(EV_CURRENT) == EV_NONE)
		return (EPKG_FATAL);

	shlib_list_init();
	if (shlib_list_from_elf_hints(_PATH_ELF_HINTS) != EPKG_OK) {
		shlib_list_free();
		return (EPKG_FATAL);
	}

	while(pkg_files(pkg, &file) == EPKG_OK)
		analyse_elf(pkg, pkg_file_path(file), add_shlibs_to_pkg, NULL);

	shlib_list_free();
	return (EPKG_OK);
}
예제 #5
0
파일: update.c 프로젝트: varju/pkgng
/**
 * Fetch repository calalogues.
 */
int
pkgcli_update(bool force) {
    const char *packagesite = NULL;
    const char *repo_name;
    bool multi_repos = false;
    struct pkg_config_kv *repokv = NULL;
    int retcode = EPKG_FATAL;
    char name[MAXPATHLEN];

    if (!quiet)
        printf("Updating repository catalogue\n");

    pkg_config_bool(PKG_CONFIG_MULTIREPOS, &multi_repos);

    /* single repository */
    if (!multi_repos) {
        /*
         * Single remote database
         */

        pkg_config_string(PKG_CONFIG_REPO, &packagesite);

        if (packagesite == NULL) {
            warnx("PACKAGESITE is not defined.");
            return (1);
        }

        retcode = pkg_update("repo", packagesite, force);
        if (retcode == EPKG_UPTODATE) {
            if (!quiet)
                printf("Repository catalogue is up-to-date, "
                       "no need to fetch fresh copy\n");
            retcode = EPKG_OK;
        }
    } else {
        /* multiple repositories */
        while (pkg_config_kvlist(PKG_CONFIG_REPOS, &repokv) == EPKG_OK) {
            repo_name = pkg_config_kv_get(repokv, PKG_CONFIG_KV_KEY);
            packagesite = pkg_config_kv_get(repokv, PKG_CONFIG_KV_VALUE);

            snprintf(name, MAXPATHLEN, "repo-%s", repo_name);
            retcode = pkg_update(name, packagesite, force);
            if (retcode == EPKG_UPTODATE) {
                if (!quiet)
                    printf("%s repository catalogue is "
                           "up-to-date, no need to fetch "
                           "fresh copy\n", repo_name);
                retcode = EPKG_OK;
            }
            if (retcode != EPKG_OK)
                break;
        }
    }

    return (retcode);
}
예제 #6
0
파일: pkg_event.c 프로젝트: culot/pkgng
void
pkg_emit_upgrade_finished(struct pkg *p)
{
	struct pkg_event ev;
	bool syslog_enabled = false;
	char *name, *version, *newversion;

	ev.type = PKG_EVENT_UPGRADE_FINISHED;
	ev.e_upgrade_finished.pkg = p;

	pkg_config_bool(PKG_CONFIG_SYSLOG, &syslog_enabled);
	if (syslog_enabled) {
		pkg_get(p, PKG_NAME, &name, PKG_VERSION, &version, PKG_NEWVERSION, &newversion);
		syslog(LOG_NOTICE, "%s upgraded: %s -> %s ", name, version, newversion);
	}

	pkg_emit_event(&ev);
}
예제 #7
0
파일: pkg_event.c 프로젝트: culot/pkgng
void
pkg_emit_install_finished(struct pkg *p)
{
	struct pkg_event ev;
	bool syslog_enabled = false;
	char *name, *version;

	ev.type = PKG_EVENT_INSTALL_FINISHED;
	ev.e_install_finished.pkg = p;

	pkg_config_bool(PKG_CONFIG_SYSLOG, &syslog_enabled);
	if (syslog_enabled) {
		pkg_get(p, PKG_NAME, &name, PKG_VERSION, &version);
		syslog(LOG_NOTICE, "%s-%s installed", name, version);
	}

	pkg_emit_event(&ev);
}
예제 #8
0
파일: utils.c 프로젝트: culot/pkgng
int
print_info(struct pkg * const pkg, unsigned int opt)
{
	struct pkg_dep *dep = NULL;
	struct pkg_file *file = NULL;
	struct pkg_category *cat = NULL;
	struct pkg_license *lic = NULL;
	struct pkg_option *option = NULL;
	bool multirepos_enabled = false;
	char *m;
	char size[7];
	const char *name, *version, *prefix, *origin, *reponame, *repourl;
	const char *maintainer, *www, *comment, *desc;
	int64_t flatsize, newflatsize, newpkgsize;
	lic_t licenselogic;

	pkg_config_bool(PKG_CONFIG_MULTIREPOS, &multirepos_enabled);

	pkg_get(pkg, PKG_NAME, &name, PKG_VERSION, &version, PKG_PREFIX, &prefix,
	    PKG_ORIGIN, &origin, PKG_REPONAME, &reponame, PKG_REPOURL, &repourl,
	    PKG_MAINTAINER, &maintainer, PKG_WWW, &www, PKG_COMMENT, &comment,
	    PKG_DESC, &desc, PKG_FLATSIZE, &flatsize, PKG_NEW_FLATSIZE, &newflatsize,
	    PKG_NEW_PKGSIZE, &newpkgsize, PKG_LICENSE_LOGIC, &licenselogic);

	if (opt & INFO_RAW) {
		pkg_emit_manifest(pkg, &m);
		printf("%s\n", m);
		free(m);
	} else if (opt & INFO_FULL) {
		printf("%-15s: %s\n", "Name", name);
		printf("%-15s: %s\n", "Version", version);
		printf("%-15s: %s\n", "Origin", origin);
		printf("%-15s: %s\n", "Prefix", prefix);

		if ((pkg_type(pkg) == PKG_REMOTE) && multirepos_enabled)
			printf("%-15s: %s [%s]\n", "Repository", reponame, repourl);

                if (!pkg_list_is_empty(pkg, PKG_CATEGORIES)) {
                        printf("%-15s:", "Categories");
                        while (pkg_categories(pkg, &cat) == EPKG_OK)
                                printf(" %s", pkg_category_name(cat));
                        printf("\n");
                }

		if (!pkg_list_is_empty(pkg, PKG_LICENSES)) {
			printf("%-15s:", "Licenses");
			while (pkg_licenses(pkg, &lic) == EPKG_OK) {
				printf(" %s", pkg_license_name(lic));
				if (licenselogic != 1)
					printf(" %c", licenselogic);
				else
					printf(" ");
			}
			printf("\b \n");
		}

		printf("%-15s: %s\n", "Maintainer", maintainer);
		printf("%-15s: %s\n", "WWW", www);
		printf("%-15s: %s\n", "Comment", comment);

                if (!pkg_list_is_empty(pkg, PKG_OPTIONS)) {
                        printf("%-15s: \n", "Options");
                        while (pkg_options(pkg, &option) == EPKG_OK)
                                printf("\t%s: %s\n", pkg_option_opt(option), pkg_option_value(option));
                }

		if (pkg_type(pkg) == PKG_INSTALLED || pkg_type(pkg) == PKG_FILE) {
			humanize_number(size, sizeof(size), flatsize, "B", HN_AUTOSCALE, 0);
			printf("%-15s: %s\n", "Flat size", size);
		} else {
			humanize_number(size, sizeof(size), newflatsize, "B", HN_AUTOSCALE, 0);
			printf("%-15s: %s\n", "Flat size", size);
			humanize_number(size, sizeof(size), newpkgsize, "B", HN_AUTOSCALE, 0);
			printf("%-15s: %s\n", "Pkg size", size);
		}

		printf("%-15s: \n%s\n", "Description", desc);
		printf("\n");
	} else if (opt & INFO_PRINT_DEP) {
		if (!(opt & INFO_QUIET))
			printf("%s-%s depends on:\n", name, version);

                while (pkg_deps(pkg, &dep) == EPKG_OK) {
                        printf("%s-%s\n", pkg_dep_get(dep, PKG_DEP_NAME), pkg_dep_get(dep, PKG_DEP_VERSION));
                }

                if (!(opt & INFO_QUIET))
                        printf("\n");
	} else if (opt & INFO_PRINT_RDEP) {
		if (!(opt & INFO_QUIET))
			printf("%s-%s is required by:\n", name, version);

                while (pkg_rdeps(pkg, &dep) == EPKG_OK) {
                        printf("%s-%s\n", pkg_dep_get(dep, PKG_DEP_NAME), pkg_dep_get(dep, PKG_DEP_VERSION));
                }

                if (!(opt & INFO_QUIET))
                        printf("\n");
	} else if (opt & INFO_LIST_FILES) {
		if (!(opt & INFO_QUIET))
			printf("%s-%s owns the following files:\n", name, version);

                while (pkg_files(pkg, &file) == EPKG_OK) {
                        printf("%s\n", pkg_file_get(file, PKG_FILE_PATH));
                }

                if (!(opt & INFO_QUIET))
                        printf("\n");
        } else if (opt & INFO_SIZE) {
		if (pkg_type(pkg) == PKG_INSTALLED) {
			humanize_number(size, sizeof(size), flatsize, "B", HN_AUTOSCALE, 0);
			printf("%s-%s size is: %s\n", name, version, size);
		} else {
			humanize_number(size, sizeof(size), newflatsize, "B", HN_AUTOSCALE, 0);
			printf("%s-%s flat size is: %s\n", name, version, size);
			humanize_number(size, sizeof(size), newpkgsize, "B", HN_AUTOSCALE, 0);
			printf("%s-%s package size is: %s\n", name, version, size);
		}
        } else if (opt & INFO_ORIGIN) {
                if (opt & INFO_QUIET)
                        printf("%s\n", origin);
                else
                        printf("%s-%s: %s\n", name, version, origin);
        } else if (opt & INFO_PREFIX) {
                if (opt & INFO_QUIET)
                        printf("%s\n", prefix);
                else
                        printf("%s-%s: %s\n", name, version, prefix);
        } else {
                if (opt & INFO_QUIET)
                        printf("%s-%s\n", name, version);
                else {
			if ((pkg_type(pkg) == PKG_REMOTE) && multirepos_enabled)
				printf("%s-%s [repository: %s]: %s\n", name, version, reponame, comment);
			else
				printf("%s-%s: %s\n", name, version, comment);
		}
        }

        return (0);
}
예제 #9
0
파일: register.c 프로젝트: gsamat/pkgng
int
exec_register(int argc, char **argv)
{
	struct pkg *pkg = NULL;
	struct pkgdb *db = NULL;

	regex_t preg;
	regmatch_t pmatch[2];

	int ch;
	char *plist = NULL;
	char *arch = NULL;
	char myarch[BUFSIZ];
	char *mdir = NULL;
	char *www = NULL;
	char *input_path = NULL;
	char fpath[MAXPATHLEN + 1];

	const char *message;
	const char *desc = NULL;
	size_t size;

	bool legacy = false;
	bool developer = false;

	int i;
	int ret = EPKG_OK, retcode = EX_OK;

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

	pkg_config_bool(PKG_CONFIG_DEVELOPER_MODE, &developer);

	pkg_new(&pkg, PKG_INSTALLED);
	while ((ch = getopt(argc, argv, "f:m:i:ld")) != -1) {
		switch (ch) {
		case 'f':
			if ((plist = strdup(optarg)) == NULL)
				err(1, "cannot allocate memory");

			break;
		case 'm':
			if ((mdir = strdup(optarg)) == NULL)
				err(1, "cannot allocate memory");
			break;
		case 'd':
			pkg_set(pkg, PKG_AUTOMATIC, true);
			break;
		case 'i':
			if ((input_path = strdup(optarg)) == NULL)
				err(1, "cannot allocate memory");
			break;
		case 'l':
			legacy = true;
			break;
		default:
			printf("%c\n", ch);
			usage_register();
			return (EX_USAGE);
		}
	}

	if (plist == NULL)
		errx(EX_USAGE, "missing -f flag");

	if (mdir == NULL)
		errx(EX_USAGE, "missing -m flag");

	snprintf(fpath, sizeof(fpath), "%s/+MANIFEST", mdir);
	if ((ret = pkg_load_manifest_file(pkg, fpath)) != EPKG_OK) {
		return (EX_IOERR);
	}

	snprintf(fpath, sizeof(fpath), "%s/+DESC", mdir);
	pkg_set_from_file(pkg, PKG_DESC, fpath);

	snprintf(fpath, sizeof(fpath), "%s/+DISPLAY", mdir);
	if (access(fpath, F_OK) == 0)
		 pkg_set_from_file(pkg, PKG_MESSAGE, fpath);

	snprintf(fpath, sizeof(fpath), "%s/+MTREE_DIRS", mdir);
	if (access(fpath, F_OK) == 0)
		pkg_set_from_file(pkg, PKG_MTREE, fpath);

	for (i = 0; scripts[i] != NULL; i++) {
		snprintf(fpath, sizeof(fpath), "%s/%s", mdir, scripts[i]);
		if (access(fpath, F_OK) == 0)
			pkg_addscript_file(pkg, fpath);
	}

	/* if www is not given then try to determine it from description */
	if (www == NULL) {
		pkg_get(pkg, PKG_DESC, &desc);
		regcomp(&preg, "^WWW:[[:space:]]*(.*)$", REG_EXTENDED|REG_ICASE|REG_NEWLINE);
		if (regexec(&preg, desc, 2, pmatch, 0) == 0) {
			size = pmatch[1].rm_eo - pmatch[1].rm_so;
			www = strndup(&desc[pmatch[1].rm_so], size);
			pkg_set(pkg, PKG_WWW, www);
			free(www);
		} else {
			pkg_set(pkg, PKG_WWW, "UNKNOWN");
		}
		regfree(&preg);
	} else {
		pkg_set(pkg, PKG_WWW, www);
		free(www);
	}

	ret += ports_parse_plist(pkg, plist, input_path);

	if (ret != EPKG_OK) {
		return (EX_IOERR);
	}

	if (plist != NULL)
		free(plist);

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

	pkg_analyse_files(db, pkg);

	pkg_get(pkg, PKG_ARCH, &arch);
	if (arch == NULL) {
		/*
		 * do not take the one from configuration on purpose
		 * but the real abi of the package.
		 */
		pkg_get_myarch(myarch, BUFSIZ);
		if (developer)
			pkg_suggest_arch(pkg, myarch, true);
		pkg_set(pkg, PKG_ARCH, myarch);
	} else {
		if (developer)
			pkg_suggest_arch(pkg, arch, false);
	}

	if (input_path != NULL) {
		pkg_copy_tree(pkg, input_path, "/");
		free(input_path);
	}

	if (pkgdb_register_ports(db, pkg) != EPKG_OK)
		retcode = EX_SOFTWARE;

	pkg_get(pkg, PKG_MESSAGE, &message);
	if (message != NULL && !legacy)
		printf("%s\n", message);

	pkgdb_close(db);
	pkg_free(pkg);

	return (retcode);
}
예제 #10
0
파일: install.c 프로젝트: yaneurabeya/pkgng
int
exec_install(int argc, char **argv)
{
	struct pkgdb *db = NULL;
	struct pkg_jobs *jobs = NULL;
	const char *reponame = NULL;
	int retcode;
	int updcode = EPKG_OK;
	int ch;
	bool yes;
	bool auto_update;
	match_t match = MATCH_EXACT;
	bool dry_run = false;
	nbactions = nbdone = 0;
	pkg_flags f = PKG_FLAG_NONE | PKG_FLAG_PKG_VERSION_TEST;

	pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);
	pkg_config_bool(PKG_CONFIG_REPO_AUTOUPDATE, &auto_update);

	while ((ch = getopt(argc, argv, "AfgIiFnqRr:Uxy")) != -1) {
		switch (ch) {
		case 'A':
			f |= PKG_FLAG_AUTOMATIC;
			break;
		case 'f':
			f |= PKG_FLAG_FORCE;
			break;
		case 'g':
			match = MATCH_GLOB;
			break;
		case 'I':
			f |= PKG_FLAG_NOSCRIPT;
			break;
		case 'F':
			f |= PKG_FLAG_SKIP_INSTALL;
			break;
		case 'i':
			pkgdb_set_case_sensitivity(false);
			break;
		case 'U':
			auto_update = false;
			break;
		case 'n':
			f |= PKG_FLAG_DRY_RUN;
			dry_run = true;
			break;
		case 'q':
			quiet = true;
			break;
		case 'R':
			f |= PKG_FLAG_RECURSIVE;
			break;
		case 'r':
			reponame = optarg;
			break;
		case 'x':
			match = MATCH_REGEX;
			break;
		case 'y':
			yes = true;
			break;
		default:
			usage_install();
			return (EX_USAGE);
		}
	}
	argc -= optind;
	argv += optind;

	if (argc < 1) {
		usage_install();
		return (EX_USAGE);
	}

	if (dry_run && !auto_update)
		retcode = pkgdb_access(PKGDB_MODE_READ,
				       PKGDB_DB_LOCAL   |
				       PKGDB_DB_REPO);
	else
		retcode = pkgdb_access(PKGDB_MODE_READ  |
				       PKGDB_MODE_WRITE |
				       PKGDB_MODE_CREATE,
				       PKGDB_DB_LOCAL   |
				       PKGDB_DB_REPO);


	if (retcode == EPKG_ENOACCESS && dry_run) {
		auto_update = false;
		retcode = pkgdb_access(PKGDB_MODE_READ,
				       PKGDB_DB_LOCAL|PKGDB_DB_REPO);
	}

	if (retcode == EPKG_ENOACCESS) {
		warnx("Insufficient privileges to install packages");
		return (EX_NOPERM);
	} else if (retcode != EPKG_OK)
		return (EX_IOERR);
	else
		retcode = EX_SOFTWARE;

	/* first update the remote repositories if needed */
	if (auto_update && (updcode = pkgcli_update(false)) != EPKG_OK)
		return (updcode);

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

	if (pkg_jobs_new(&jobs, PKG_JOBS_INSTALL, db) != EPKG_OK)
		goto cleanup;

	if (reponame != NULL && pkg_jobs_set_repository(jobs, reponame) != EPKG_OK)
		goto cleanup;

	pkg_jobs_set_flags(jobs, f);

	if (pkg_jobs_add(jobs, match, argv, argc) == EPKG_FATAL)
		goto cleanup;

	if (pkg_jobs_solve(jobs) != EPKG_OK)
		goto cleanup;

	if ((nbactions = pkg_jobs_count(jobs)) > 0) {
		/* print a summary before applying the jobs */
		if (!quiet || dry_run) {
			print_jobs_summary(jobs,
			    "The following %d packages will be installed:\n\n",
			    nbactions);

			if (!yes && !dry_run)
				yes = query_yesno(
				    "\nProceed with installing packages [y/N]: ");
			if (dry_run)
				yes = false;
		}

		if (yes && pkg_jobs_apply(jobs) != EPKG_OK)
			goto cleanup;

		if (messages != NULL) {
			sbuf_finish(messages);
			printf("%s", sbuf_data(messages));
		}
	}

	retcode = EX_OK;

cleanup:
	pkg_jobs_free(jobs);
	pkgdb_close(db);

	if (!yes && newpkgversion)
		newpkgversion = false;

	return (retcode);
}
예제 #11
0
파일: pkg_create.c 프로젝트: z0nt/pkgng
static int
pkg_create_from_dir(struct pkg *pkg, const char *root,
                    struct packing *pkg_archive)
{
    char		 fpath[MAXPATHLEN + 1];
    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];

    if (pkg_is_valid(pkg) != EPKG_OK) {
        pkg_emit_error("the package is not valid");
        return (EPKG_FATAL);
    }
    /*
     * if the checksum is not provided in the manifest recompute it
     */
    while (pkg_files(pkg, &file) == EPKG_OK) {
        const char *pkg_path = pkg_file_path(file);
        const char *pkg_sum = pkg_file_cksum(file);

        if (root != NULL)
            snprintf(fpath, sizeof(fpath), "%s%s", root, pkg_path);
        else
            strlcpy(fpath, pkg_path, sizeof(fpath));

        if ((pkg_sum == NULL || pkg_sum[0] == '\0') &&
                lstat(fpath, &st) == 0 && !S_ISLNK(st.st_mode)) {
            if (sha256_file(fpath, sha256) != EPKG_OK)
                return (EPKG_FATAL);
            strlcpy(file->sum, sha256, sizeof(file->sum));
        }
    }

    /*
     * Register shared libraries used by the package if SHLIBS
     * enabled in conf.  Deletes shlib info if not.
     */
    pkg_register_shlibs(pkg);

    pkg_emit_manifest(pkg, &m);
    packing_append_buffer(pkg_archive, m, "+MANIFEST", strlen(m));
    free(m);

    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);

        if (root != NULL)
            snprintf(fpath, sizeof(fpath), "%s%s", root, pkg_path);
        else
            strlcpy(fpath, pkg_path, sizeof(fpath));

        ret = packing_append_file_attr(pkg_archive, fpath, pkg_path,
                                       file->uname, file->gname, file->perm);
        pkg_config_bool(PKG_CONFIG_DEVELOPER_MODE, &developer);
        if (developer && ret != EPKG_OK)
            return (ret);
    }

    while (pkg_dirs(pkg, &dir) == EPKG_OK) {
        const char *pkg_path = pkg_dir_path(dir);
        if (root != NULL)
            snprintf(fpath, sizeof(fpath), "%s%s", root, pkg_path);
        else
            strlcpy(fpath, pkg_dir_path(dir), sizeof(fpath));

        ret = packing_append_file_attr(pkg_archive, fpath, pkg_path,
                                       dir->uname, dir->gname, dir->perm);
        pkg_config_bool(PKG_CONFIG_DEVELOPER_MODE, &developer);
        if (developer && ret != EPKG_OK)
            return (ret);
    }

    return (EPKG_OK);
}
예제 #12
0
파일: update.c 프로젝트: culot/pkgng
int
exec_update(int argc, char **argv)
{
	char url[MAXPATHLEN];
	const char *packagesite = NULL;
	const char *repo_name;
	struct pkg_config_kv *repokv = NULL;
	int retcode = EPKG_OK;
	bool multi_repos = false;

	(void)argv;
	if (argc != 1) {
		usage_update();
		return (EX_USAGE);
	}

	if (geteuid() != 0) {
		warnx("updating the remote database can only be done as root");
		return (EX_NOPERM);
	}

	/* 
	 * Fetch remote databases.
	 */

	pkg_config_bool(PKG_CONFIG_MULTIREPOS, &multi_repos);

	/* single repository */
	if (!multi_repos) {
		/*
		 * Single remote database
		 */
		
		pkg_config_string(PKG_CONFIG_REPO, &packagesite);
		
		if (packagesite == NULL) {
			warnx("PACKAGESITE is not defined.");
			return (1);
		}

		if (packagesite[strlen(packagesite) - 1] == '/')
			snprintf(url, MAXPATHLEN, "%srepo.txz", packagesite);
		else
			snprintf(url, MAXPATHLEN, "%s/repo.txz", packagesite);

		retcode = update_from_remote_repo("repo", url);
	} else {
		/* multiple repositories */
		while (pkg_config_list(PKG_CONFIG_REPOS, &repokv) == EPKG_OK) {
			repo_name = pkg_config_kv_get(repokv, PKG_CONFIG_KV_KEY);
			packagesite = pkg_config_kv_get(repokv, PKG_CONFIG_KV_VALUE);

			if (packagesite[strlen(packagesite) - 1] == '/')
				snprintf(url, MAXPATHLEN, "%srepo.txz", packagesite);
			else
				snprintf(url, MAXPATHLEN, "%s/repo.txz", packagesite);

			retcode = update_from_remote_repo(repo_name, url);
		}
	}

	return (retcode);
}
예제 #13
0
파일: pkg_elf.c 프로젝트: dschossig/pkg
static int
analyse_elf(struct pkg *pkg, const char *fpath,
	int (action)(void *, struct pkg *, const char *, const char *, bool),
	void *actdata)
{
	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 *shlib;

	bool developer = false;
	bool is_shlib = false;

	pkg_config_bool(PKG_CONFIG_DEVELOPER_MODE, &developer);

	int fd;

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

	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:
			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 (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) {
			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, basename(fpath));
		}

		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), 
				      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);

		action(actdata, pkg, fpath, shlib, is_shlib);
	}

cleanup:
	rpath_list_free();

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

	return (ret);
}
예제 #14
0
파일: upgrade.c 프로젝트: afb/pkgng
int
exec_upgrade(int argc, char **argv)
{
	struct pkgdb *db = NULL;
	struct pkg_jobs *jobs = NULL;
	const char *reponame = NULL;
	int retcode;
	int updcode;
	int ch;
	bool yes;
	bool dry_run = false;
	bool auto_update;
	nbactions = nbdone = 0;
	pkg_flags f = PKG_FLAG_NONE | PKG_FLAG_PKG_VERSION_TEST;

	pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);
	pkg_config_bool(PKG_CONFIG_REPO_AUTOUPDATE, &auto_update);


	while ((ch = getopt(argc, argv, "fLnqFr:Uy")) != -1) {
		switch (ch) {
		case 'f':
			f |= PKG_FLAG_FORCE;
			break;
		case 'I':
			f |= PKG_FLAG_NOSCRIPT;
			break;
		case 'L':
			warnx("!!! The -L flag is deprecated and will be removed. Please use -U now.");
			/* FALLTHROUGH */
		case 'U':
			auto_update = false;
			break;
		case 'n':
			f |= PKG_FLAG_DRY_RUN;
			dry_run = true;
			break;
		case 'F':
			f |= PKG_FLAG_SKIP_INSTALL;
			break;
		case 'q':
			quiet = true;
			break;
		case 'r':
			reponame = optarg;
			break;
		case 'y':
			yes = true;
			break;
		default:
			usage_upgrade();
			return (EX_USAGE);
			/* NOTREACHED */
		}
	}
	argc -= optind;
	argv += optind;

	if (argc != 0) {
		usage_upgrade();
		return (EX_USAGE);
	}

	if (dry_run)
		retcode = pkgdb_access(PKGDB_MODE_READ,
				       PKGDB_DB_LOCAL|PKGDB_DB_REPO);
	else
		retcode = pkgdb_access(PKGDB_MODE_READ  |
				       PKGDB_MODE_WRITE |
				       PKGDB_MODE_CREATE,
				       PKGDB_DB_LOCAL|PKGDB_DB_REPO);

	if (retcode == EPKG_ENOACCESS) {
		warnx("Insufficient privilege to upgrade packages");
		return (EX_NOPERM);
	} else if (retcode != EPKG_OK)
		return (EX_IOERR);
	else
		retcode = EX_SOFTWARE;
	
	/* first update the remote repositories if needed */
	if (!dry_run && auto_update && 
	    (updcode = pkgcli_update(false)) != EPKG_OK)
		return (updcode);

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

	if (pkg_jobs_new(&jobs, PKG_JOBS_UPGRADE, db) != EPKG_OK)
		goto cleanup;

	if (reponame != NULL && pkg_jobs_set_repository(jobs, reponame) != EPKG_OK)
		goto cleanup;

	pkg_jobs_set_flags(jobs, f);

	if (pkg_jobs_solve(jobs) != EPKG_OK)
		goto cleanup;

	if ((nbactions = pkg_jobs_count(jobs)) == 0) {
		if (!quiet)
			printf("Nothing to do\n");
		retcode = EXIT_SUCCESS;
		goto cleanup;
	}

	if (!quiet || dry_run) {
		print_jobs_summary(jobs,
		    "Uprgades have been requested for the following %d "
		    "packages:\n\n", nbactions);

		if (!yes && !dry_run)
			yes = query_yesno("\nProceed with upgrading "
			          "packages [y/N]: ");
		if (dry_run)
			yes = false;
	}

	if (yes && pkg_jobs_apply(jobs) != EPKG_OK)
		goto cleanup;

	if (messages != NULL) {
		sbuf_finish(messages);
		printf("%s", sbuf_data(messages));
	}

	retcode = EXIT_SUCCESS;

	cleanup:
	pkg_jobs_free(jobs);
	pkgdb_close(db);

	return (retcode);
}
예제 #15
0
파일: utils.c 프로젝트: varju/pkgng
void
print_info(struct pkg * const pkg, unsigned int options)
{
	struct pkg_category *cat    = NULL;
	struct pkg_dep	    *dep    = NULL;
	struct pkg_dir	    *dir    = NULL;
	struct pkg_file	    *file   = NULL;
	struct pkg_group    *group  = NULL;
	struct pkg_license  *lic    = NULL;
	struct pkg_option   *option = NULL;
	struct pkg_shlib    *shlib  = NULL;
	struct pkg_user	    *user   = NULL;
	bool multirepos_enabled = false;
	bool print_tag = false;
	bool show_locks = false;
	char size[7];
	const char *name, *version, *prefix, *origin, *reponame, *repourl;
	const char *maintainer, *www, *comment, *desc, *message, *arch;
	const char *repopath;
	const char *tab;
	char *m;
	unsigned opt;
	int64_t flatsize, newflatsize, newpkgsize;
	lic_t licenselogic;
	bool locked;
	int cout = 0;		/* Number of characters output */
	int info_num;		/* Number of different data items to print */

	pkg_config_bool(PKG_CONFIG_MULTIREPOS, &multirepos_enabled);

	pkg_get(pkg,
		PKG_NAME,          &name,
		PKG_VERSION,       &version,
		PKG_PREFIX,        &prefix,
		PKG_ORIGIN,        &origin,
		PKG_REPONAME,      &reponame,
		PKG_REPOURL,       &repourl,
		PKG_MAINTAINER,    &maintainer,
		PKG_WWW,           &www,
		PKG_COMMENT,       &comment,
		PKG_DESC,          &desc,
		PKG_FLATSIZE,      &flatsize,
		PKG_NEW_FLATSIZE,  &newflatsize,
		PKG_NEW_PKGSIZE,   &newpkgsize,
		PKG_LICENSE_LOGIC, &licenselogic,
		PKG_MESSAGE,       &message,
		PKG_ARCH,	   &arch,
		PKG_REPOPATH,	   &repopath,
		PKG_LOCKED,	   &locked);

	if (!multirepos_enabled)
		pkg_config_string(PKG_CONFIG_REPO, &repourl);

	if (options & INFO_RAW) { /* Not for remote packages */
		if (pkg_type(pkg) != PKG_REMOTE) {
			pkg_emit_manifest(pkg, &m);
			printf("%s\n", m);
			free(m);
		}
		return;
	}

	/* Show locking status when requested to display it and the
	   package is locally installed */
	if (pkg_type(pkg) == PKG_INSTALLED && (options & INFO_LOCKED) != 0)
		show_locks = true;

	if (!quiet) {
		/* Print a tag-line identifying the package -- either
		   NAMEVER, ORIGIN or NAME (in that order of
		   preference).  This may be the only output from this
		   function */

		if (options & INFO_TAG_NAMEVER)
			cout = printf("%s-%s", name, version);
		else if (options & INFO_TAG_ORIGIN)
			cout = printf("%s", origin);
		else if (options & INFO_TAG_NAME)
			cout = printf("%s", name);
	}

	/* Don't display a tab if quiet, retains compatibility. */
	tab = quiet ? "" : "\t";

	/* If we printed a tag, and there are no other items to print,
	   then just return now. If there's only one single-line item
	   to print, show it at column 32 on the same line. If there's
	   one multi-line item to print, start a new line. If there is
	   more than one item to print per pkg, use 'key : value'
	   style to show on a new line.  */

	info_num = 0;
	for (opt = 0x1U; opt <= INFO_LASTFIELD; opt <<= 1) 
		if ((opt & options) != 0)
			info_num++;

	if (info_num == 0 && cout > 0) {
		printf("\n");
		return;
	}

	if (info_num == 1) {
		/* Only one item to print */
		print_tag = false;
		if (!quiet) {
			if (options & INFO_MULTILINE)
				printf(":\n");
			else {
				if (cout < 31)
					cout = 31 - cout;
				else
					cout = 1;
				printf("%*s", cout, " ");
			}
		}
	} else {
		/* Several items to print */
		print_tag = true;
		if (!quiet)
			printf("\n");
	}

	for (opt = 0x1; opt <= INFO_LASTFIELD; opt <<= 1) {
		if ((opt & options) == 0)
			continue;

		switch (opt) {
		case INFO_NAME:
			if (print_tag)
				printf("%-15s: ", "Name");
			printf("%s\n", name);
			break;
		case INFO_VERSION:
			if (print_tag)
				printf("%-15s: ", "Version");
			printf("%s\n", version);
			break;
		case INFO_ORIGIN:
			if (print_tag)
				printf("%-15s: ", "Origin");
			printf("%s\n", origin);
			break;
		case INFO_PREFIX:
			if (print_tag)
				printf("%-15s: ", "Prefix");
			printf("%s\n", prefix);
			break;
		case INFO_REPOSITORY:
			if (pkg_type(pkg) == PKG_REMOTE &&
			    repourl != NULL && repourl[0] != '\0') {
				if (print_tag)
					printf("%-15s: ", "Repository");
				printf("%s [%s]\n", reponame, repourl);
			} else if (!print_tag)
				printf("\n");
			break;
		case INFO_CATEGORIES:
			if (pkg_list_count(pkg, PKG_CATEGORIES) > 0) {
				if (print_tag)
					printf("%-15s: ", "Categories");
				if (pkg_categories(pkg, &cat) == EPKG_OK)
					printf("%s", pkg_category_name(cat));
				while (pkg_categories(pkg, &cat) == EPKG_OK)
					printf(" %s", pkg_category_name(cat));
				printf("\n");
			} else if (!print_tag)
				printf("\n");
			break;
		case INFO_LICENSES:
			if (pkg_list_count(pkg, PKG_LICENSES) > 0) {
				if (print_tag)
					printf("%-15s: ", "Licenses");
				if (pkg_licenses(pkg, &lic) == EPKG_OK)
					printf("%s", pkg_license_name(lic));
				while (pkg_licenses(pkg, &lic) == EPKG_OK) {
					if (licenselogic != 1)
						printf(" %c", licenselogic);
					printf(" %s", pkg_license_name(lic));
				}
				printf("\n");				
			} else if (!print_tag)
				printf("\n");
			break;
		case INFO_MAINTAINER:
			if (print_tag)
				printf("%-15s: ", "Maintainer");
			printf("%s\n", maintainer);
			break;
		case INFO_WWW:	
			if (print_tag)
				printf("%-15s: ", "WWW");
			printf("%s\n", www);
			break;
		case INFO_COMMENT:
			if (print_tag)
				printf("%-15s: ", "Comment");
			printf("%s\n", comment);
			break;
		case INFO_OPTIONS:
			if (pkg_list_count(pkg, PKG_OPTIONS) > 0) {
				if (print_tag)
					printf("%-15s:\n", "Options");
				while (pkg_options(pkg, &option) == EPKG_OK)
					printf("%s%-15s: %s\n",
					       tab,
					       pkg_option_opt(option),
					       pkg_option_value(option));
			}
			break;
		case INFO_SHLIBS_REQUIRED:
			if (pkg_list_count(pkg, PKG_SHLIBS_REQUIRED) > 0) {
				if (print_tag)
					printf("%-15s:\n", "Shared Libs required");
				while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK)
					printf("%s%s\n", tab, pkg_shlib_name(shlib));
			}
			break;
		case INFO_SHLIBS_PROVIDED:
			if (pkg_list_count(pkg, PKG_SHLIBS_PROVIDED) > 0) {
				if (print_tag)
					printf("%-15s:\n", "Shared Libs provided");
				while (pkg_shlibs_provided(pkg, &shlib) == EPKG_OK)
					printf("%s%s\n", tab, pkg_shlib_name(shlib));
			}
			break;
		case INFO_FLATSIZE:
			if (pkg_type(pkg) == PKG_INSTALLED ||
			    pkg_type(pkg) == PKG_FILE)
				humanize_number(size, sizeof(size),
						flatsize,"B",
						HN_AUTOSCALE, 0);
			else
				humanize_number(size, sizeof(size),
						newflatsize,"B",
						HN_AUTOSCALE, 0);

			if (print_tag)
				printf("%-15s: ", "Flat size");
			printf("%s\n", size);
			break;
		case INFO_PKGSIZE: /* Remote pkgs only */
			if (pkg_type(pkg) == PKG_REMOTE) {
				humanize_number(size, sizeof(size),
						newpkgsize,"B",
						HN_AUTOSCALE, 0);
				if (print_tag)
					printf("%-15s: ", "Pkg size");
				printf("%s\n", size);
			} else if (!print_tag)
				printf("\n");
			break;
		case INFO_DESCR:
			if (print_tag)
				printf("%-15s:\n", "Description");
			printf("%s\n", desc);
			break;
		case INFO_MESSAGE:
			if (message) {
				if (print_tag)
					printf("%-15s:\n", "Message");
				printf("%s\n", message);
			}
			break;
		case INFO_DEPS:
			if (pkg_list_count(pkg, PKG_DEPS) > 0) {
				if (print_tag)
					printf("%-15s:\n", "Depends on");
				while (pkg_deps(pkg, &dep) == EPKG_OK) {
					printf("%s%s-%s",
					       tab,
					       pkg_dep_name(dep),
					       pkg_dep_version(dep));
					if (show_locks && pkg_dep_is_locked(dep))
						printf(" (*)");
					printf("\n");
				}
			}
			break;
		case INFO_RDEPS:
			if (pkg_list_count(pkg, PKG_RDEPS) > 0) {
				if (print_tag)
					printf("%-15s:\n", "Required by");
				while (pkg_rdeps(pkg, &dep) == EPKG_OK) {
					printf("%s%s-%s",
					       tab,
					       pkg_dep_name(dep),
					       pkg_dep_version(dep));
					if (show_locks && pkg_dep_is_locked(dep))
						printf(" (*)");
					printf("\n");
				}
			}
			break;
		case INFO_FILES: /* Installed pkgs only */
			if (pkg_type(pkg) != PKG_REMOTE &&
			    pkg_list_count(pkg, PKG_FILES) > 0) {
				if (print_tag)
					printf("%-15s:\n", "Files");
				while (pkg_files(pkg, &file) == EPKG_OK)
					printf("%s%s\n",
					       tab,
					       pkg_file_path(file));
			}
			break;
		case INFO_DIRS:	/* Installed pkgs only */
			if (pkg_type(pkg) != PKG_REMOTE &&
			    pkg_list_count(pkg, PKG_DIRS) > 0) {
				if (print_tag)
					printf("%-15s:\n", "Directories");
				while (pkg_dirs(pkg, &dir) == EPKG_OK)
					printf("%s%s\n",
					       tab,
					       pkg_dir_path(dir));
			}
			break;
		case INFO_USERS: /* Installed pkgs only */
			if (pkg_type(pkg) != PKG_REMOTE &&
			    pkg_list_count(pkg, PKG_USERS) > 0) {
				if (print_tag)
					printf("%-15s: ", "Users");
				if (pkg_users(pkg, &user) == EPKG_OK)
					printf("%s", pkg_user_name(user));
				while (pkg_users(pkg, &user) == EPKG_OK)
					printf(" %s", pkg_user_name(user));
				printf("\n");
			}
			break;
		case INFO_GROUPS: /* Installed pkgs only */
			if (pkg_type(pkg) != PKG_REMOTE &&
			    pkg_list_count(pkg, PKG_GROUPS) > 0) {
				if (print_tag)
					printf("%-15s: ", "Groups");
				if (pkg_groups(pkg, &group) == EPKG_OK)
					printf("%s", pkg_group_name(group));
				while (pkg_groups(pkg, &group) == EPKG_OK)
					printf(" %s", pkg_group_name(group));
				printf("\n");
			}
			break;
		case INFO_ARCH:
			if (print_tag)
				printf("%-15s: ", "Architecture");
			printf("%s\n", arch);
			break;
		case INFO_REPOURL:
			if (pkg_type(pkg) == PKG_REMOTE &&
			    repourl != NULL && repourl[0] != '\0') {
				if (print_tag)
					printf("%-15s: ", "Pkg URL");
				if (repourl[strlen(repourl) -1] == '/')
					printf("%s%s\n", repourl, repopath);
				else
					printf("%s/%s\n", repourl, repopath);
			} else if (!print_tag)
				printf("\n");
			break;
		case INFO_LOCKED:
			if (print_tag)
				printf("%-15s: ", "Locked");
			printf("%s\n", locked ? "yes" : "no");
			break;
		}
	}
}
예제 #16
0
int
exec_autoremove(__unused int argc, __unused char **argv)
{
	struct pkgdb *db = NULL;
	struct pkg_jobs *jobs = NULL;
	int retcode;
	int ch;
	bool yes = false;
	bool dry_run = false;
	nbactions = nbdone = 0;
	pkg_flags f = PKG_FLAG_FORCE;

	pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);

	while ((ch = getopt(argc, argv, "ynq")) != -1) {
		switch (ch) {
		case 'q':
			quiet = true;
			break;
		case 'y':
			yes = true;
			break;
		case 'n':
			f |= PKG_FLAG_DRY_RUN;
			dry_run = true;
			break;
		default:
			break;
		}
        }
	argc -= optind;
	argv += optind;

	if (argc != 0) {
		usage_autoremove();
		return (EX_USAGE);
	}

	if (dry_run) 
		retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL);
	else
		retcode = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE,
				       PKGDB_DB_LOCAL);

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

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

	/* Always force packages to be removed */
	if (pkg_jobs_new(&jobs, PKG_JOBS_AUTOREMOVE, db) != EPKG_OK) {
		pkgdb_close(db);
		return (EX_IOERR);
	}

	pkg_jobs_set_flags(jobs, f);

	if ((retcode = pkg_jobs_solve(jobs)) != EPKG_OK) {
		retcode = EX_SOFTWARE;
		goto cleanup;
	}

	if ((nbactions = pkg_jobs_count(jobs)) == 0) {
		printf("Nothing to do.\n");
		goto cleanup;
	}

	if (!quiet || dry_run) {
		print_jobs_summary(jobs,
		    "Deinstallation has been requested for the following %d packages:\n\n", nbactions);
		if (!yes && !dry_run)
			yes = query_yesno(
		            "\nProceed with deinstalling packages [y/N]: ");
		if (dry_run)
			yes = false;
	}
	if (!yes || (retcode = pkg_jobs_apply(jobs)) != EPKG_OK) {
		retcode = EX_SOFTWARE;
		goto cleanup;
	}

	pkgdb_compact(db);

	retcode = EX_OK;

cleanup:
	pkg_jobs_free(jobs);
	pkgdb_close(db);

	return (retcode);
}
예제 #17
0
int
pkg_delete(struct pkg *pkg, struct pkgdb *db, unsigned flags)
{
	struct pkg_dep	*rdep = NULL;
	int		 ret;
	bool		 handle_rc = false;
	const char	*origin;

	assert(pkg != NULL);
	assert(db != NULL);

	/*
	 * Do not trust the existing entries as it may have changed if we
	 * delete packages in batch.
	 */
	pkg_list_free(pkg, PKG_RDEPS);

	/*
	 * Ensure that we have all the informations we need
	 */
	if ((ret = pkgdb_load_rdeps(db, pkg)) != EPKG_OK)
		return (ret);
	if ((ret = pkgdb_load_files(db, pkg)) != EPKG_OK)
		return (ret);
	if ((ret = pkgdb_load_dirs(db, pkg)) != EPKG_OK)
		return (ret);
	if ((ret = pkgdb_load_scripts(db, pkg)) != EPKG_OK)
		return (ret);
	if ((ret = pkgdb_load_mtree(db, pkg)) != EPKG_OK)
		return (ret);

	if (flags & PKG_DELETE_UPGRADE)
		pkg_emit_upgrade_begin(pkg);
	else
		pkg_emit_deinstall_begin(pkg);

	/* If the package is locked */
	if (pkg_is_locked(pkg)) {
		pkg_emit_locked(pkg);
		return (EPKG_LOCKED);
	}

	/* If there are dependencies */
	if (pkg_rdeps(pkg, &rdep) == EPKG_OK) {
		pkg_emit_required(pkg, flags & PKG_DELETE_FORCE);
		if ((flags & PKG_DELETE_FORCE) == 0)
			return (EPKG_REQUIRED);
	}

	/*
	 * stop the different related services if the users do want that
	 * and that the service is running
	 */
	pkg_config_bool(PKG_CONFIG_HANDLE_RC_SCRIPTS, &handle_rc);
	if (handle_rc)
		pkg_start_stop_rc_scripts(pkg, PKG_RC_STOP);

	if ((flags & PKG_DELETE_NOSCRIPT) == 0) {
		if (flags & PKG_DELETE_UPGRADE) {
			ret = pkg_script_run(pkg, PKG_SCRIPT_PRE_UPGRADE);
			if (ret != EPKG_OK)
				return (ret);
		} else {
			ret = pkg_script_run(pkg, PKG_SCRIPT_PRE_DEINSTALL);
			if (ret != EPKG_OK)
				return (ret);
		}
	}

	if ((ret = pkg_delete_files(pkg, flags & PKG_DELETE_FORCE ? 1 : 0))
            != EPKG_OK)
		return (ret);

	if ((flags & (PKG_DELETE_NOSCRIPT | PKG_DELETE_UPGRADE)) == 0) {
		ret = pkg_script_run(pkg, PKG_SCRIPT_POST_DEINSTALL);
		if (ret != EPKG_OK)
			return (ret);
	}

	ret = pkg_delete_dirs(db, pkg, flags & PKG_DELETE_FORCE);
	if (ret != EPKG_OK)
		return (ret);

	if ((flags & PKG_DELETE_UPGRADE) == 0)
		pkg_emit_deinstall_finished(pkg);

	pkg_get(pkg, PKG_ORIGIN, &origin);

	return (pkgdb_unregister_pkg(db, origin));
}
예제 #18
0
파일: pkg_add.c 프로젝트: niamtokik/pkgng
int
pkg_add(struct pkgdb *db, const char *path, unsigned flags)
{
    const char	*arch;
    const char	*myarch;
    const char	*origin;
    struct archive	*a;
    struct archive_entry *ae;
    struct pkg	*pkg = NULL;
    struct pkg_dep	*dep = NULL;
    struct pkg      *pkg_inst = NULL;
    bool		 extract = true;
    bool		 handle_rc = false;
    char		 dpath[MAXPATHLEN + 1];
    const char	*basedir;
    const char	*ext;
    char		*mtree;
    char		*prefix;
    int		 retcode = EPKG_OK;
    int		 ret;

    assert(path != NULL);

    /*
     * Open the package archive file, read all the meta files and set the
     * current archive_entry to the first non-meta file.
     * If there is no non-meta files, EPKG_END is returned.
     */
    ret = pkg_open2(&pkg, &a, &ae, path);
    if (ret == EPKG_END)
        extract = false;
    else if (ret != EPKG_OK) {
        retcode = ret;
        goto cleanup;
    }
    if ((flags & PKG_ADD_UPGRADE) == 0)
        pkg_emit_install_begin(pkg);

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

    if (flags & PKG_ADD_AUTOMATIC)
        pkg_set(pkg, PKG_AUTOMATIC, true);

    /*
     * Check the architecture
     */

    pkg_config_string(PKG_CONFIG_ABI, &myarch);
    pkg_get(pkg, PKG_ARCH, &arch, PKG_ORIGIN, &origin);

    if (fnmatch(myarch, arch, FNM_CASEFOLD) == FNM_NOMATCH &&
            strncmp(arch, myarch, strlen(myarch)) != 0) {
        pkg_emit_error("wrong architecture: %s instead of %s",
                       arch, myarch);
        if ((flags & PKG_ADD_FORCE) == 0) {
            retcode = EPKG_FATAL;
            goto cleanup;
        }
    }

    /*
     * Check if the package is already installed
     */

    ret = pkg_try_installed(db, origin, &pkg_inst, PKG_LOAD_BASIC);
    if (ret == EPKG_OK) {
        pkg_emit_already_installed(pkg_inst);
        retcode = EPKG_INSTALLED;
        goto cleanup;
    } else if (ret != EPKG_END) {
        retcode = ret;
        goto cleanup;
    }

    /*
     * Check for dependencies
     */

    basedir = dirname(path);
    if ((ext = strrchr(path, '.')) == NULL) {
        pkg_emit_error("%s has no extension", path);
        retcode = EPKG_FATAL;
        goto cleanup;
    }

    while (pkg_deps(pkg, &dep) == EPKG_OK) {
        if (pkg_is_installed(db, pkg_dep_origin(dep)) != EPKG_OK) {
            const char *dep_name = pkg_dep_name(dep);
            const char *dep_ver = pkg_dep_version(dep);

            snprintf(dpath, sizeof(dpath), "%s/%s-%s%s", basedir,
                     dep_name, dep_ver, ext);

            if ((flags & PKG_ADD_UPGRADE) == 0 &&
                    access(dpath, F_OK) == 0) {
                ret = pkg_add(db, dpath, PKG_ADD_AUTOMATIC);
                if (ret != EPKG_OK) {
                    retcode = EPKG_FATAL;
                    goto cleanup;
                }
            } else {
                retcode = EPKG_FATAL;
                pkg_emit_missing_dep(pkg, dep);
                goto cleanup;
            }
        }
    }

    /* register the package before installing it in case there are
     * problems that could be caught here. */
    if ((flags & PKG_ADD_UPGRADE) == 0)
        retcode = pkgdb_register_pkg(db, pkg, 0);
    else
        retcode = pkgdb_register_pkg(db, pkg, 1);

    if (retcode != EPKG_OK)
        goto cleanup;

    pkg_get(pkg, PKG_PREFIX, &prefix, PKG_MTREE, &mtree);
    if ((retcode = do_extract_mtree(mtree, prefix)) != EPKG_OK)
        goto cleanup_reg;

    /*
     * Execute pre-install scripts
     */
    if ((flags & (PKG_ADD_NOSCRIPT | PKG_ADD_USE_UPGRADE_SCRIPTS)) == 0)
        pkg_script_run(pkg, PKG_SCRIPT_PRE_INSTALL);

    /* add the user and group if necessary */
    /* pkg_add_user_group(pkg); */

    /*
     * Extract the files on disk.
     */
    if (extract && (retcode = do_extract(a, ae)) != EPKG_OK) {
        /* If the add failed, clean up */
        pkg_delete_files(pkg, 1);
        pkg_delete_dirs(db, pkg, 1);
        goto cleanup_reg;
    }

    /*
     * Execute post install scripts
     */
    if ((flags & PKG_ADD_NOSCRIPT) == 0) {
        if (flags & PKG_ADD_USE_UPGRADE_SCRIPTS)
            pkg_script_run(pkg, PKG_SCRIPT_POST_UPGRADE);
        else
            pkg_script_run(pkg, PKG_SCRIPT_POST_INSTALL);
    }

    /*
     * start the different related services if the users do want that
     * and that the service is running
     */

    pkg_config_bool(PKG_CONFIG_HANDLE_RC_SCRIPTS, &handle_rc);
    if (handle_rc)
        pkg_start_stop_rc_scripts(pkg, PKG_RC_START);

cleanup_reg:
    if ((flags & PKG_ADD_UPGRADE) == 0)
        pkgdb_register_finale(db, retcode);

    if (retcode == EPKG_OK && (flags & PKG_ADD_UPGRADE) == 0)
        pkg_emit_install_finished(pkg);

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

    pkg_free(pkg);
    pkg_free(pkg_inst);

    return (retcode);
}
예제 #19
0
파일: clean.c 프로젝트: HonestQiao/pkgng
int
exec_clean(int argc, char **argv)
{
	struct pkgdb	*db = NULL;
	struct pkgdb_it	*it = NULL;
	struct pkg	*pkg = NULL;
	struct pkg	*p = NULL;
	FTS		*fts = NULL;
	FTSENT		*ent = NULL;
	struct dl_head	dl = STAILQ_HEAD_INITIALIZER(dl);
	const char	*cachedir;
	char		*paths[2];
	char		*repopath;
	bool		 dry_run = false;
	bool		 yes;
	int		 retcode = EX_SOFTWARE;
	int		 ret;
	int		 ch;

	pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);

	while ((ch = getopt(argc, argv, "nqy")) != -1) {
		switch (ch) {
		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;

	if (pkg_config_string(PKG_CONFIG_CACHEDIR, &cachedir) != EPKG_OK) {
		warnx("Cannot get cachedir config entry");
		return 1;
	}

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

	if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) {
		goto cleanup;
	}

	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 */

	while ((ent = fts_read(fts)) != NULL) {
		const char *origin, *pkgrepopath;

		if (ent->fts_info != FTS_F)
			continue;

		repopath = ent->fts_path + strlen(cachedir);
		if (repopath[0] == '/')
			repopath++;

		if (pkg_open(&pkg, ent->fts_path) != EPKG_OK) {
			if (!quiet)
				warnx("skipping %s", ent->fts_path);
			continue;
		}

		pkg_get(pkg, PKG_ORIGIN, &origin);
		it = pkgdb_search(db, origin, MATCH_EXACT, FIELD_ORIGIN,
		    FIELD_NONE, NULL);

		if (it == NULL) {
			if (!quiet)
				warnx("skipping %s", ent->fts_path);
			continue;
		}

		if ((ret = pkgdb_it_next(it, &p, PKG_LOAD_BASIC)) ==
		    EPKG_FATAL) {
			if (!quiet)
				warnx("skipping %s", ent->fts_path);
			continue;
		}

		pkg_get(p, PKG_REPOPATH, &pkgrepopath);
		if (ret == EPKG_END) {
			ret = add_to_dellist(&dl, REMOVED, ent->fts_path,
					     origin, NULL, NULL);
		} else if (strcmp(repopath, pkgrepopath)) {
			const char	*newname;
			const char	*newversion;

			pkg_get(p, 
				PKG_NAME,    &newname,
				PKG_VERSION, &newversion);

			ret = add_to_dellist(&dl, OUT_OF_DATE, ent->fts_path,
					     origin, newname, newversion);
		} else {
			char local_cksum[SHA256_DIGEST_LENGTH * 2 +1];
			const char *cksum;

			pkg_get(p, PKG_CKSUM, &cksum);

			if (hash_file(ent->fts_path, local_cksum) == EPKG_OK) {

				if (strcmp(cksum, local_cksum) != 0) {
					ret = add_to_dellist(&dl, CKSUM_MISMATCH, ent->fts_path,
						     origin, NULL, NULL);
				}
			}
		}

		if (ret != EPKG_OK && ret != EPKG_END) {
			retcode = EX_OSERR; /* out of memory */
			goto cleanup;
		}

		pkgdb_it_free(it);
	}

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

	if (dry_run || !yes || !quiet)
		display_dellist(&dl, cachedir);

	if (!dry_run) {
		if (!yes)
			yes = query_yesno(
				"\nProceed with cleaning cache [y/N]: ");
		if (yes)
			retcode = delete_dellist(&dl);
	} else 
		retcode = EX_OK;

cleanup:
	free_dellist(&dl);

	pkg_free(pkg);
	pkg_free(p);
	if (fts != NULL)
		fts_close(fts);
	if (db != NULL)
		pkgdb_close(db);

	return (retcode);
}
예제 #20
0
int
exec_fetch(int argc, char **argv)
{
	struct pkgdb	*db = NULL;
	struct pkg_jobs	*jobs = NULL;
	const char	*reponame = NULL;
	int		 ch;
	int		 retcode = EX_SOFTWARE;
	bool		 auto_update;
	bool		 upgrades_for_installed = false;
	bool		 yes;
	unsigned	 mode;
	match_t		 match = MATCH_EXACT;
	pkg_flags	 f = PKG_FLAG_NONE;

	pkg_config_bool(PKG_CONFIG_REPO_AUTOUPDATE, &auto_update);
	pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);

	while ((ch = getopt(argc, argv, "adgiqr:Uuxy")) != -1) {
		switch (ch) {
		case 'a':
			match = MATCH_ALL;
			break;
		case 'd':
			f |= PKG_FLAG_WITH_DEPS;
			break;
		case 'g':
			match = MATCH_GLOB;
			break;
		case 'i':
			pkgdb_set_case_sensitivity(false);
			break;
		case 'U':
			auto_update = false;
			break;
		case 'q':
			quiet = true;
			break;
		case 'r':
			reponame = optarg;
			break;
		case 'u':
			f |= PKG_FLAG_UPGRADES_FOR_INSTALLED;
			upgrades_for_installed = true;
			break;
		case 'x':
			match = MATCH_REGEX;
			break;
		case 'y':
			yes = true;
			break;
		default:
			usage_fetch();
			return (EX_USAGE);
		}
	}
	argc -= optind;
	argv += optind;
	
	if (argc < 1 && match != MATCH_ALL && !upgrades_for_installed) {
		usage_fetch();
		return (EX_USAGE);
	}

        if (match == MATCH_ALL && upgrades_for_installed) {
		usage_fetch();
		return (EX_USAGE);
	}

	/* TODO: Allow the user to specify an output directory via -o
	   outdir */

	if (auto_update)
		mode = PKGDB_MODE_READ|PKGDB_MODE_WRITE|PKGDB_MODE_CREATE;
	else
		mode = PKGDB_MODE_READ;

	retcode = pkgdb_access(mode, PKGDB_DB_REPO);

	if (retcode == EPKG_ENOACCESS) {
		warnx("Insufficient privileges to access repo catalogue");
		return (EX_NOPERM);
	} else if (retcode != EPKG_OK)
		return (EX_IOERR);

	if (upgrades_for_installed) {
		retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL);

		if (retcode == EPKG_ENOACCESS) {
			warnx("Insufficient privileges to access the package database");
			return (EX_NOPERM);
		} else if (retcode != EPKG_OK)
			return (EX_IOERR);
	}

	/* first update the remote repositories if needed */
	if (auto_update && (retcode = pkgcli_update(false)) != EPKG_OK)
		return (retcode);

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

	if (pkg_jobs_new(&jobs, PKG_JOBS_FETCH, db) != EPKG_OK)
		goto cleanup;

	if (reponame != NULL && pkg_jobs_set_repository(jobs, reponame) != EPKG_OK)
		goto cleanup;

	pkg_jobs_set_flags(jobs, f);

	if (!upgrades_for_installed &&
	    pkg_jobs_add(jobs, match, argv, argc) != EPKG_OK)
		goto cleanup;

	if (pkg_jobs_solve(jobs) != EPKG_OK)
		goto cleanup;

	if (pkg_jobs_count(jobs) == 0)
		goto cleanup;

	if (!quiet) {
		print_jobs_summary(jobs, "The following packages will be fetched:\n\n");

		if (!yes)
			yes = query_yesno("\nProceed with fetching packages [y/N]: ");
	}
	
	if (!yes || pkg_jobs_apply(jobs) != EPKG_OK)
		goto cleanup;

	retcode = EX_OK;

cleanup:
	pkg_jobs_free(jobs);
	pkgdb_close(db);

	return (retcode);
}
예제 #21
0
파일: delete.c 프로젝트: rg1/pkgng
int
exec_delete(int argc, char **argv)
{
	struct pkg_jobs *jobs = NULL;
	struct pkgdb *db = NULL;
	match_t match = MATCH_EXACT;
	int ch;
	bool force = false;
	bool yes;
	bool dry_run = false;
	int retcode = EX_SOFTWARE;
	nbactions = nbdone = 0;
	pkg_flags f = PKG_FLAG_NONE;
	int i;

	pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);

	while ((ch = getopt(argc, argv, "aDfginqRxy")) != -1) {
		switch (ch) {
		case 'a':
			match = MATCH_ALL;
			break;
		case 'D':
			f |= PKG_FLAG_NOSCRIPT;
			break;
		case 'f':
			f |= PKG_FLAG_FORCE;
			force = true;
			break;
		case 'g':
			match = MATCH_GLOB;
			break;
		case 'i':
			pkgdb_set_case_sensitivity(false);
			break;
		case 'n':
			f |= PKG_FLAG_DRY_RUN;
			dry_run = true;
			break;
		case 'q':
			quiet = true;
			break;
		case 'R':
			f |= PKG_FLAG_RECURSIVE;
			break;
		case 'x':
			match = MATCH_REGEX;
			break;
		case 'y':
			yes = true;
			break;
		default:
			usage_delete();
			return (EX_USAGE);
		}
	}

	argc -= optind;
	argv += optind;

	if (argc < 1 && match != MATCH_ALL) {
		usage_delete();
		return (EX_USAGE);
	}

	retcode = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE,
			       PKGDB_DB_LOCAL);
	if (retcode == EPKG_ENODB) {
		warnx("No packages installed.  Nothing to do!");
		return (EX_OK);
	} else if (retcode == EPKG_ENOACCESS) {
		warnx("Insufficient privilege to delete packages");
		return (EX_NOPERM);
	} else if (retcode != EPKG_OK) {
		warnx("Error accessing package database");
		return (EX_SOFTWARE);
	}

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

	if (pkg_jobs_new(&jobs, PKG_JOBS_DEINSTALL, db) != EPKG_OK) {
		pkgdb_close(db);
		return (EX_IOERR);
	}

	pkg_jobs_set_flags(jobs, f);

	if (match == MATCH_EXACT) {
		for (i = 0; i < argc; i++) {
			if (strchr(argv[i], '*') != NULL) {
				match = MATCH_GLOB;
				break;
			}
		}
	}

	if (pkg_jobs_add(jobs, match, argv, argc) == EPKG_FATAL)
		goto cleanup;

	if (pkg_jobs_solve(jobs) != EPKG_OK)
		goto cleanup;

	if ((pkg_jobs_find(jobs, "ports-mgmt/pkg", NULL) == EPKG_OK)
	     && !force) {
		warnx("You are about to delete 'ports-mgmt/pkg' which is really "
		    "dangerous, you can't do that without specifying -f");
		goto cleanup;
	}

	/* check if we have something to deinstall */
	if ((nbactions = pkg_jobs_count(jobs)) == 0) {
		if (argc == 0) {
			if (!quiet)
				printf("Nothing to do.\n");
			retcode = EX_OK;
		} else {
			fprintf(stderr, "Package(s) not found!\n");
			retcode = EX_DATAERR;
		}
		goto cleanup;
	}

	if (!quiet || dry_run) {
		print_jobs_summary(jobs,
		    "Deinstallation has been requested for the following %d packages:\n\n", nbactions);
		if (!yes && !dry_run)
			yes = query_yesno(
		            "\nProceed with deinstalling packages [y/N]: ");
		if (dry_run)
			yes = false;
	}
	if (!yes || (retcode = pkg_jobs_apply(jobs)) != EPKG_OK)
		goto cleanup;

	pkgdb_compact(db);

	retcode = EX_OK;

cleanup:
	pkg_jobs_free(jobs);
	pkgdb_close(db);

	return (retcode);
}
예제 #22
0
파일: check.c 프로젝트: HonestQiao/pkgng
int
exec_check(int argc, char **argv)
{
	struct pkg *pkg = NULL;
	struct pkgdb_it *it = NULL;
	struct pkgdb *db = NULL;
	match_t match = MATCH_EXACT;
	int flags = PKG_LOAD_BASIC;
	int ret;
	int ch;
	bool yes = false;
	bool dcheck = false;
	bool checksums = false;
	bool recompute = false;
	bool reanalyse_shlibs = false;
	bool shlibs;
	int nbpkgs = 0;
	int i;
	int verbose = 0;

	struct deps_head dh = STAILQ_HEAD_INITIALIZER(dh);

	while ((ch = getopt(argc, argv, "yagdBxsrv")) != -1) {
		switch (ch) {
		case 'a':
			match = MATCH_ALL;
			break;
		case 'x':
			match = MATCH_REGEX;
			break;
		case 'g':
			match = MATCH_GLOB;
			break;
		case 'y':
			yes = true;
			break;
		case 'd':
			dcheck = true;
			flags |= PKG_LOAD_DEPS;
			break;
		case 'B':
			pkg_config_bool(PKG_CONFIG_SHLIBS, &shlibs);
			if (!shlibs)
				errx(EX_USAGE, "reanalyzing shlibs requires SHLIBS"
					       " in pkg.conf.");
			reanalyse_shlibs = true;
			flags |= PKG_LOAD_FILES;
			break;
		case 's':
			checksums = true;
			flags |= PKG_LOAD_FILES;
			break;
		case 'r':
			recompute = true;
			flags |= PKG_LOAD_FILES;
			if (geteuid() != 0)
				errx(EX_USAGE, "recomputing the checksums"
				    " and size can only be done as root");
			break;
		case 'v':
			verbose = 1;
			break;
		default:
			usage_check();
			return (EX_USAGE);
		}
	}
	argc -= optind;
	argv += optind;

	/* Default to all packages if no pkg provided */
	if (argc == 0 && (dcheck || checksums || recompute || reanalyse_shlibs)) {
		match = MATCH_ALL;
	} else if ((argc == 0 && match != MATCH_ALL) || !(dcheck || checksums || recompute || reanalyse_shlibs)) {
		usage_check();
		return (EX_USAGE);
	}

	ret = pkgdb_open(&db, PKGDB_DEFAULT);
	if (ret == EPKG_ENODB) {
		if (geteuid() == 0)
			return (EX_IOERR);

		return (EX_OK);
	}

	if (ret != EPKG_OK)
		return (EX_IOERR);

	i = 0;
	do {
		if ((it = pkgdb_query(db, argv[i], match)) == NULL) {
			pkgdb_close(db);
			return (EX_IOERR);
		}

		while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) {
			const char *pkgname = NULL;
			pkg_get(pkg, PKG_NAME, &pkgname);
			/* check for missing dependencies */
			if (dcheck) {
				if (verbose)
					printf("Checking dependencies: %s\n", pkgname);
				nbpkgs += check_deps(db, pkg, &dh);
			}
			if (checksums) {
				if (verbose)
					printf("Checking checksums: %s\n", pkgname);
				pkg_test_filesum(pkg);
			}
			if (recompute) {
				if (verbose)
					printf("Recomputing size and checksums: %s\n", pkgname);
				pkg_recompute(db, pkg);
			}
			if (reanalyse_shlibs) {
				if (verbose)
					printf("Reanalyzing files for shlibs: %s\n", pkgname);
				if (pkgdb_reanalyse_shlibs(db, pkg) != EPKG_OK)
					printf("Failed to reanalyse for shlibs: %s\n", pkgname);
			}
		}

		if (geteuid() == 0 && nbpkgs > 0) {
			if (yes == false)
				pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);

			printf("\n>>> Missing package dependencies were detected.\n");
			printf(">>> Found %d issue(s) in total with your package database.\n\n", nbpkgs);
			ret = fix_deps(db, &dh, nbpkgs, yes);
			if (ret == EPKG_OK)
				check_summary(db, &dh);
			else if (ret == EPKG_ENODB) {
				db = NULL;
				return (EX_IOERR);
			}
		}
		pkgdb_it_free(it);
		i++;
	} while (i < argc);

	deps_free(&dh);
	pkg_free(pkg);
	pkgdb_close(db);

	return (EX_OK);
}
예제 #23
0
파일: set.c 프로젝트: ocochard/pkgng
int
exec_set(int argc, char **argv)
{
	struct pkgdb *db = NULL;
	struct pkgdb_it *it = NULL;
	struct pkg *pkg = NULL;
	int ch;
	int i;
	bool yes_flag = false;
	bool yes = yes_flag;
	match_t match = MATCH_EXACT;
	int newautomatic = -1;
	bool automatic = false;
	const char *errstr;
	const char *name;
	const char *version;
	char *neworigin = NULL;
	char *oldorigin = NULL;
	unsigned int loads = PKG_LOAD_BASIC;
	unsigned int sets = 0;
	int retcode;

	while ((ch = getopt(argc, argv, "ayA:kxgo:")) != -1) {
		switch (ch) {
		case 'y':
			yes_flag = true;
			break;
		case 'a':
			match = MATCH_ALL;
			break;
		case 'x':
			match = MATCH_REGEX;
			break;
		case 'g':
			match = MATCH_GLOB;
			break;
		case 'A':
			sets |= AUTOMATIC;
			newautomatic = strtonum(optarg, 0, 1, &errstr);
			if (errstr)
				errx(EX_USAGE, "Wrong value for -A. "
				    "Expecting 0 or 1, got: %s (%s)",
				    optarg, errstr);
			break;
		case 'o':
			sets |= ORIGIN;
			loads |= PKG_LOAD_DEPS;
			match = MATCH_ALL;
			oldorigin = strdup(optarg);
			neworigin = strrchr(oldorigin, ':');
			if (neworigin == NULL) {
				free(oldorigin);
				errx(EX_USAGE, "Wrong format for -o. "
				    "Expecting oldorigin:neworigin, got: %s",
				    optarg);
			}
			*neworigin = '\0';
			neworigin++;
			if (strrchr(oldorigin, '/') == NULL ||
			    strrchr(neworigin, '/') == NULL) {
				free(oldorigin);
				errx(EX_USAGE,
				    "Bad origin format, got: %s", optarg);
			}
			break;
		default:
			if (oldorigin != NULL)
				free(oldorigin);
			
			usage_set();
			return (EX_USAGE);
		}
	}

	argc -= optind;
	argv += optind;

	if ((argc < 1 && match != MATCH_ALL) || (newautomatic == -1 && neworigin == NULL)) {
		usage_set();
		return (EX_USAGE);
	}

	retcode = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE,
			       PKGDB_DB_LOCAL);
	if (retcode == EPKG_ENODB) {
		if (match == MATCH_ALL)
			return (EX_OK);
		if (!quiet)
			warnx("No packages installed.  Nothing to do!");
		return (EX_OK);
	} else if (retcode == EPKG_ENOACCESS) {
		warnx("Insufficient privilege to modify package database");
		return (EX_NOPERM);
	} else if (retcode != EPKG_OK) {
		warnx("Error accessing package database");
		return (EX_SOFTWARE);
	}

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

	if (!yes_flag)
		pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes_flag);

	if (oldorigin != NULL) {
		yes = yes_flag;
		match = MATCH_ALL;
		if ((it = pkgdb_query(db, oldorigin, MATCH_EXACT)) == NULL) {
			pkgdb_close(db);
			return (EX_IOERR);
		}

		if (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC) != EPKG_OK) {
			pkg = NULL;
/*			fprintf(stderr, "%s not installed\n", oldorigin);
			free(oldorigin);
			pkgdb_it_free(it);
			pkgdb_close(db);
			return (EX_SOFTWARE);*/
		}
		if (pkg != NULL)
			pkg_get(pkg, PKG_NAME, &name, PKG_VERSION, &version);
		if (!yes) {
			if (pkg != NULL)
				yes = query_yesno("Change origin from %s to %s for %s-%s? [y/N]: ",
				    oldorigin, neworigin, name, version);
			else
				yes = query_yesno("Change origin from %s to %s for all dependencies? "
				    "[y/N]: ", oldorigin, neworigin);
		}
		if (pkg != NULL && yes) {
			if (pkgdb_set(db, pkg, PKG_SET_ORIGIN, neworigin) != EPKG_OK)
				return (EX_IOERR);
		}
		pkgdb_it_free(it);
	}
	i = 0;
	do {
		if ((it = pkgdb_query(db, argv[i], match)) == NULL) {
			free(oldorigin);
			pkgdb_close(db);
			return (EX_IOERR);
		}

		while (pkgdb_it_next(it, &pkg, loads) == EPKG_OK) {
			yes = yes_flag;
			if ((sets & AUTOMATIC) == AUTOMATIC) {
				pkg_get(pkg, PKG_AUTOMATIC, &automatic);
				if (automatic == newautomatic)
					continue;
				if (!yes) {
					pkg_get(pkg, PKG_NAME, &name, PKG_VERSION, &version);
					if (newautomatic)
						yes = query_yesno("Mark %s-%s as automatically installed? [y/N]: ", name, version);
					else
						yes = query_yesno("Mark %s-%s as not automatically installed? [y/N]: ", name, version);
				}
				if (yes)
					pkgdb_set(db, pkg, PKG_SET_AUTOMATIC, newautomatic);
			}
			if ((sets & ORIGIN) == ORIGIN) {
				struct pkg_dep *d = NULL;
				while (pkg_deps(pkg, &d) == EPKG_OK) {
					/*
					 * Do not query user when he has already
					 * been queried.
					 */
					if (pkgdb_set(db, pkg, PKG_SET_DEPORIGIN, oldorigin, neworigin) != EPKG_OK)
						return (EX_IOERR);
				}
			}
		}
		pkgdb_it_free(it);
		i++;
	} while (i < argc);

	free(oldorigin);
	pkg_free(pkg);
	pkgdb_close(db);

	return (EX_OK);
}
예제 #24
0
파일: install.c 프로젝트: infofarmer/pkgng
int
exec_install(int argc, char **argv)
{
	struct pkg *pkg = NULL;
	struct pkgdb_it *it = NULL;
	struct pkgdb *db = NULL;
	struct pkg_jobs *jobs = NULL;
	const char *reponame = NULL;
	int retcode = 1;
	int ch;
	bool yes = false;
	int64_t dlsize = 0;
	int64_t oldsize = 0, newsize = 0;
	char size[7];
	match_t match = MATCH_EXACT;

	while ((ch = getopt(argc, argv, "ygxXr:")) != -1) {
		switch (ch) {
			case 'y':
				yes = true;
				break;
			case 'g':
				match = MATCH_GLOB;
				break;
			case 'x':
				match = MATCH_REGEX;
				break;
			case 'X':
				match = MATCH_EREGEX;
				break;
			case 'r':
				reponame = optarg;
				break;
			default:
				usage_install();
				return (EX_USAGE);
		}
	}
	argc -= optind;
	argv += optind;

	if (argc < 1) {
		usage_install();
		return (EX_USAGE);
	}

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

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

	if (pkg_jobs_new(&jobs, PKG_JOBS_INSTALL, db) != EPKG_OK) {
		goto cleanup;
	}

	if ((it = pkgdb_query_installs(db, match, argc, argv, reponame)) == NULL)
		goto cleanup;

	while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_DEPS) == EPKG_OK) {
		pkg_jobs_add(jobs, pkg);
		pkg = NULL;
	}
	pkgdb_it_free(it);

	if (pkg_jobs_is_empty(jobs)) {
		printf("Nothing to do\n");
		retcode = 0;
		goto cleanup;
	}

	/* print a summary before applying the jobs */
	pkg = NULL;
	printf("The following packages will be installed:\n");

	while (pkg_jobs(jobs, &pkg) == EPKG_OK) {
		const char *name, *version, *newversion;
		int64_t flatsize, newflatsize, pkgsize;
		pkg_get(pkg, PKG_NEWVERSION, &newversion, PKG_NAME, &name,
		    PKG_VERSION, &version, PKG_FLATSIZE, &flatsize,
		    PKG_NEW_FLATSIZE, &newflatsize, PKG_NEW_PKGSIZE, &pkgsize);
		dlsize += pkgsize;
		if (newversion != NULL) {
			printf("\tUpgrading %s: %s -> %s\n", name, version, newversion);
			oldsize += flatsize;
			newsize += flatsize;
		} else {
			newsize += flatsize;
			printf("\tInstalling %s: %s\n", name, version);
		}
	}

	if (oldsize > newsize) {
		newsize *= -1;
		humanize_number(size, sizeof(size), oldsize - newsize, "B", HN_AUTOSCALE, 0);
		printf("\nthe installation will save %s\n", size);
	} else {
		humanize_number(size, sizeof(size), newsize - oldsize, "B", HN_AUTOSCALE, 0);
		printf("\nthe installation will require %s more space\n", size);
	}
	humanize_number(size, sizeof(size), dlsize, "B", HN_AUTOSCALE, 0);
	printf("%s to be downloaded\n", size);

	if (yes == false) 
		pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);
	if (yes == false)
		yes = query_yesno("\nProceed with installing packages [y/N]: ");

	if (yes == true)
		if (pkg_jobs_apply(jobs, 0) != EPKG_OK)
			goto cleanup;

	retcode = 0;

	cleanup:
	pkg_jobs_free(jobs);
	pkgdb_close(db);

	return (retcode);
}
예제 #25
0
파일: pkg_repo.c 프로젝트: HonestQiao/pkgng
int
pkg_repo_fetch(struct pkg *pkg)
{
	char dest[MAXPATHLEN + 1];
	char url[MAXPATHLEN + 1];
	int fetched = 0;
	char cksum[SHA256_DIGEST_LENGTH * 2 +1];
	char *path = NULL;
	const char *packagesite = NULL;
	const char *cachedir = NULL;
	bool multirepos_enabled = false;
	int retcode = EPKG_OK;
	const char *repopath, *repourl, *sum, *name, *version;

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

	if (pkg_config_string(PKG_CONFIG_CACHEDIR, &cachedir) != EPKG_OK)
		return (EPKG_FATAL);

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

	snprintf(dest, sizeof(dest), "%s/%s", cachedir, repopath);

	/* 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 */
	if ((path = dirname(dest)) == 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.
	 */
	pkg_config_bool(PKG_CONFIG_MULTIREPOS, &multirepos_enabled);

	if (multirepos_enabled) {
		packagesite = repourl;
	} else {
		pkg_config_string(PKG_CONFIG_REPO, &packagesite);
	}

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

	if (packagesite[strlen(packagesite) - 1] == '/')
		snprintf(url, sizeof(url), "%s%s", packagesite, repopath);
	else
		snprintf(url, sizeof(url), "%s/%s", packagesite, repopath);

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

	if (retcode != EPKG_OK)
		goto cleanup;

	checksum:
	retcode = sha256_file(dest, cksum);
	if (retcode == EPKG_OK)
		if (strcmp(cksum, sum)) {
			if (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_fetch(pkg));
			}
		}

	cleanup:
	if (retcode != EPKG_OK)
		unlink(dest);

	return (retcode);
}
예제 #26
0
파일: check.c 프로젝트: yaneurabeya/pkgng
int
exec_check(int argc, char **argv)
{
	struct pkg *pkg = NULL;
	struct pkgdb_it *it = NULL;
	struct pkgdb *db = NULL;
	match_t match = MATCH_EXACT;
	int flags = PKG_LOAD_BASIC;
	int ret, rc = EX_OK;
	int ch;
	bool yes;
	bool dcheck = false;
	bool checksums = false;
	bool recompute = false;
	bool reanalyse_shlibs = false;
	bool noinstall = false;
	int nbpkgs = 0;
	int i;
	int verbose = 0;

	pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);

	struct deps_head dh = STAILQ_HEAD_INITIALIZER(dh);

	while ((ch = getopt(argc, argv, "yagidnBxsrv")) != -1) {
		switch (ch) {
		case 'a':
			match = MATCH_ALL;
			break;
		case 'B':
			reanalyse_shlibs = true;
			flags |= PKG_LOAD_FILES;
			break;
		case 'd':
			dcheck = true;
			flags |= PKG_LOAD_DEPS;
			break;
		case 'g':
			match = MATCH_GLOB;
			break;
		case 'i':
			pkgdb_set_case_sensitivity(false);
			break;
		case 'n':
			noinstall = true;
			break;
		case 'r':
			recompute = true;
			flags |= PKG_LOAD_FILES;
			break;
		case 's':
			checksums = true;
			flags |= PKG_LOAD_FILES;
			break;
		case 'v':
			verbose = 1;
			break;
		case 'x':
			match = MATCH_REGEX;
			break;
		case 'y':
			yes = true;
			break;
		default:
			usage_check();
			return (EX_USAGE);
		}
	}
	argc -= optind;
	argv += optind;

	/* Default to all packages if no pkg provided */
	if (argc == 0 && (dcheck || checksums || recompute || reanalyse_shlibs)) {
		match = MATCH_ALL;
	} else if ((argc == 0 && match != MATCH_ALL) || !(dcheck || checksums || recompute || reanalyse_shlibs)) {
		usage_check();
		return (EX_USAGE);
	}

	if (recompute || reanalyse_shlibs)
		ret = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE,
				   PKGDB_DB_LOCAL);
	else
		ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL);

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

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

	i = 0;
	do {
		if ((it = pkgdb_query(db, argv[i], match)) == NULL) {
			pkgdb_close(db);
			return (EX_IOERR);
		}

		while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) {
			/* check for missing dependencies */
			if (dcheck) {
				if (verbose)
					pkg_printf("Checking dependencies: %n\n", pkg);
				nbpkgs += check_deps(db, pkg, &dh, noinstall);
				if (noinstall && nbpkgs > 0) {
					rc = EX_UNAVAILABLE;
				}
			}
			if (checksums) {
				if (verbose)
					pkg_printf("Checking checksums: %n\n", pkg);
				if (pkg_test_filesum(pkg) != EPKG_OK) {
					rc = EX_DATAERR;
				}
			}
			if (recompute) {
				if (verbose)
					pkg_printf("Recomputing size and checksums: %n\n", pkg);
				if (pkg_recompute(db, pkg) != EPKG_OK) {
					rc = EX_DATAERR;
				}
			}
			if (reanalyse_shlibs) {
				if (verbose)
					pkg_printf("Reanalyzing files for shlibs: %n\n", pkg);
				if (pkgdb_reanalyse_shlibs(db, pkg) != EPKG_OK) {
					pkg_printf("Failed to reanalyse for shlibs: %n\n", pkg);
					rc = EX_UNAVAILABLE;
				}
			}
		}

		if (dcheck && nbpkgs > 0 && !noinstall) {
			printf("\n>>> Missing package dependencies were detected.\n");
			printf(">>> Found %d issue(s) in the package database.\n\n", nbpkgs);

			ret = fix_deps(db, &dh, nbpkgs, yes);
			if (ret == EPKG_OK)
				check_summary(db, &dh);
			else if (ret == EPKG_ENODB) {
				db = NULL;
				return (EX_IOERR);
			}
		}
		pkgdb_it_free(it);
		i++;
	} while (i < argc);

	deps_free(&dh);
	pkg_free(pkg);
	pkgdb_close(db);

	return (rc);
}
예제 #27
0
파일: pkg_add.c 프로젝트: juliandunn/pkg
int
pkg_add(struct pkgdb *db, const char *path, unsigned flags, struct pkg_manifest_key *keys)
{
	const char	*arch;
	const char	*origin;
	const char	*name;
	struct archive	*a;
	struct archive_entry *ae;
	struct pkg	*pkg = NULL;
	struct pkg_dep	*dep = NULL;
	struct pkg      *pkg_inst = NULL;
	bool		 extract = true;
	bool		 handle_rc = false;
	bool		 disable_mtree;
	char		 dpath[MAXPATHLEN];
	const char	*basedir;
	const char	*ext;
	char		*mtree;
	char		*prefix;
	int		 retcode = EPKG_OK;
	int		 ret;

	assert(path != NULL);

	/*
	 * Open the package archive file, read all the meta files and set the
	 * current archive_entry to the first non-meta file.
	 * If there is no non-meta files, EPKG_END is returned.
	 */
	ret = pkg_open2(&pkg, &a, &ae, path, keys, 0);
	if (ret == EPKG_END)
		extract = false;
	else if (ret != EPKG_OK) {
		retcode = ret;
		goto cleanup;
	}
	if ((flags & PKG_ADD_UPGRADE) == 0)
		pkg_emit_install_begin(pkg);

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

	if (flags & PKG_ADD_AUTOMATIC)
		pkg_set(pkg, PKG_AUTOMATIC, (int64_t)true);

	/*
	 * Check the architecture
	 */

	pkg_get(pkg, PKG_ARCH, &arch, PKG_ORIGIN, &origin, PKG_NAME, &name);

	if (!is_valid_abi(arch, true)) {
		if ((flags & PKG_ADD_FORCE) == 0) {
			retcode = EPKG_FATAL;
			goto cleanup;
		}
	}

	/*
	 * Check if the package is already installed
	 */

	ret = pkg_try_installed(db, origin, &pkg_inst, PKG_LOAD_BASIC);
	if (ret == EPKG_OK) {
		if ((flags & PKG_FLAG_FORCE) == 0) {
			pkg_emit_already_installed(pkg_inst);
			retcode = EPKG_INSTALLED;
			pkg_free(pkg_inst);
			pkg_inst = NULL;
			goto cleanup;
		}
		else {
			pkg_emit_notice("package %s is already installed, forced install", name);
			pkg_free(pkg_inst);
			pkg_inst = NULL;
		}
	} else if (ret != EPKG_END) {
		retcode = ret;
		goto cleanup;
	}

	/*
	 * Check for dependencies by searching the same directory as
	 * the package archive we're reading.  Of course, if we're
	 * reading from a file descriptor or a unix domain socket or
	 * somesuch, there's no valid directory to search.
	 */

	if (pkg_type(pkg) == PKG_FILE) {
		basedir = dirname(path);
		if ((ext = strrchr(path, '.')) == NULL) {
			pkg_emit_error("%s has no extension", path);
			retcode = EPKG_FATAL;
			goto cleanup;
		}
	} else {
		basedir = NULL;
		ext = NULL;
	}

	while (pkg_deps(pkg, &dep) == EPKG_OK) {
		if (pkg_is_installed(db, pkg_dep_origin(dep)) == EPKG_OK)
			continue;

		if (basedir != NULL) {
			const char *dep_name = pkg_dep_name(dep);
			const char *dep_ver = pkg_dep_version(dep);

			snprintf(dpath, sizeof(dpath), "%s/%s-%s%s", basedir,
			    dep_name, dep_ver, ext);

			if ((flags & PKG_ADD_UPGRADE) == 0 &&
			    access(dpath, F_OK) == 0) {
				ret = pkg_add(db, dpath, PKG_ADD_AUTOMATIC, keys);
				if (ret != EPKG_OK) {
					retcode = EPKG_FATAL;
					goto cleanup;
				}
			} else {
				pkg_emit_error("Missing dependency matching '%s'",
				    pkg_dep_get(dep, PKG_DEP_ORIGIN));
				retcode = EPKG_FATAL;
				goto cleanup;
			}
		} else {
			retcode = EPKG_FATAL;
			pkg_emit_missing_dep(pkg, dep);
			goto cleanup;
		}
	}

	/* register the package before installing it in case there are
	 * problems that could be caught here. */
	retcode = pkgdb_register_pkg(db, pkg, flags & PKG_ADD_UPGRADE, flags & PKG_FLAG_FORCE);

	if (retcode != EPKG_OK)
		goto cleanup;

	/* MTREE replicates much of the standard functionality
	 * inplicit in the way pkg works.  It has to remain available
	 * in the ports for compatibility with the old pkg_tools, but
	 * ultimately, MTREE should be made redundant.  Use this for
	 * experimantal purposes and to develop MTREE-free versions of
	 * packages. */

	pkg_config_bool(PKG_CONFIG_DISABLE_MTREE, &disable_mtree);
	if (!disable_mtree) {
		pkg_get(pkg, PKG_PREFIX, &prefix, PKG_MTREE, &mtree);
		if ((retcode = do_extract_mtree(mtree, prefix)) != EPKG_OK)
			goto cleanup_reg;
	}

	/*
	 * Execute pre-install scripts
	 */
	if ((flags & (PKG_ADD_NOSCRIPT | PKG_ADD_USE_UPGRADE_SCRIPTS)) == 0)
		pkg_script_run(pkg, PKG_SCRIPT_PRE_INSTALL);

	/* add the user and group if necessary */
	/* pkg_add_user_group(pkg); */

	/*
	 * Extract the files on disk.
	 */
	if (extract && (retcode = do_extract(a, ae)) != EPKG_OK) {
		/* If the add failed, clean up (silently) */
		pkg_delete_files(pkg, 2);
		pkg_delete_dirs(db, pkg, 1);
		goto cleanup_reg;
	}

	/*
	 * Execute post install scripts
	 */
	if ((flags & PKG_ADD_NOSCRIPT) == 0) {
		if ((flags & PKG_ADD_USE_UPGRADE_SCRIPTS) == PKG_ADD_USE_UPGRADE_SCRIPTS)
			pkg_script_run(pkg, PKG_SCRIPT_POST_UPGRADE);
		else
			pkg_script_run(pkg, PKG_SCRIPT_POST_INSTALL);
	}

	/*
	 * start the different related services if the users do want that
	 * and that the service is running
	 */

	pkg_config_bool(PKG_CONFIG_HANDLE_RC_SCRIPTS, &handle_rc);
	if (handle_rc)
		pkg_start_stop_rc_scripts(pkg, PKG_RC_START);

	cleanup_reg:
	if ((flags & PKG_ADD_UPGRADE) == 0)
		pkgdb_register_finale(db, retcode);

	if (retcode == EPKG_OK && (flags & PKG_ADD_UPGRADE) == 0)
		pkg_emit_install_finished(pkg);

	cleanup:
	if (a != NULL) {
		archive_read_close(a);
		archive_read_free(a);
	}

	pkg_free(pkg);

	if (pkg_inst != NULL)
		pkg_free(pkg_inst);

	return (retcode);
}
예제 #28
0
파일: pkg_elf.c 프로젝트: varju/pkgng
static int
test_depends(void *actdata, struct pkg *pkg, const char *fpath,
	     const char *name, bool is_shlib)
{
	struct pkgdb *db = actdata;
	struct pkg_dep *dep = NULL;
	struct pkgdb_it *it = NULL;
	struct pkg *d;
	const char *deporigin, *depname, *depversion;
	bool deplocked;
	char pathbuf[MAXPATHLEN];
	bool found;
	bool shlibs = false;

	assert(db != NULL);

	pkg_config_bool(PKG_CONFIG_SHLIBS, &shlibs);

	switch(filter_system_shlibs(name, pathbuf, sizeof(pathbuf))) {
	case EPKG_OK:		/* A non-system library */
		break;
	case EPKG_END:		/* A system library */
		return (EPKG_OK);
	default:
		/* Ignore link resolution errors if we're analysing a
		   shared library. */
		if (is_shlib)
			return (EPKG_OK);

		warnx("(%s-%s) %s - shared library %s not found",
		      pkg_name(pkg), pkg_version(pkg), fpath, name);
		return (EPKG_FATAL);
	}

	if (shlibs)
		pkg_addshlib_required(pkg, name);

	if ((it = pkgdb_query_which(db, pathbuf)) == NULL)
		return (EPKG_OK);

	d = NULL;
	if (pkgdb_it_next(it, &d, PKG_LOAD_BASIC) == EPKG_OK) {
		found = false;
		pkg_get(d, PKG_ORIGIN,  &deporigin,
			   PKG_NAME,    &depname,
			   PKG_VERSION, &depversion,
			   PKG_LOCKED,  &deplocked);

		dep = NULL;
		found = false;
		while (pkg_deps(pkg, &dep) == EPKG_OK) {
			if (strcmp(pkg_dep_origin(dep), deporigin) == 0) {
				found = true;
				break;
			}
		}
		if (!found) {
			pkg_emit_error("adding forgotten depends (%s): %s-%s",
			    pathbuf, depname, depversion);
			pkg_adddep(pkg, depname, deporigin, depversion,
			    deplocked);
		}
		pkg_free(d);
	}

	pkgdb_it_free(it);
	return (EPKG_OK);
}
예제 #29
0
파일: fetch.c 프로젝트: baloo/pkgng
int
exec_fetch(int argc, char **argv)
{
	struct pkg *pkg = NULL;
	struct pkgdb_it *it = NULL;
	struct pkgdb *db = NULL;
	struct pkg_jobs *jobs = NULL;
	const char *reponame = NULL;
	int retcode = EXIT_FAILURE;
	int ch;
	int flags = PKG_LOAD_BASIC;
	bool yes = false;
	bool auto_update = true;
	match_t match = MATCH_EXACT;

	while ((ch = getopt(argc, argv, "ygxXr:qaLd")) != -1) {
		switch (ch) {
		case 'y':
			yes = true;
			break;
		case 'a':
			match = MATCH_ALL;
			break;
		case 'g':
			match = MATCH_GLOB;
			break;
		case 'x':
			match = MATCH_REGEX;
			break;
		case 'X':
			match = MATCH_EREGEX;
			break;
		case 'r':
			reponame = optarg;
			break;
		case 'q':
			quiet = true;
			break;
		case 'L':
			auto_update = false;
			break;
		case 'd':
			flags |= PKG_LOAD_DEPS;
			break;
		default:
			usage_fetch();
			return (EX_USAGE);
		}
	}
	argc -= optind;
	argv += optind;
	
	if (argc < 1 && match != MATCH_ALL) {
		usage_fetch();
		return (EX_USAGE);
	}

	/* TODO: Allow the user to specify an output directory via -o outdir */
	if (geteuid() != 0) {
		warnx("Fetching packages can only be done as root");
		return (EX_NOPERM);
	}

	/* first update the remote repositories if needed */
	if (auto_update && (retcode = pkgcli_update()) != EPKG_OK)
		return (retcode);

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

	if (pkg_jobs_new(&jobs, PKG_JOBS_FETCH, db) != EPKG_OK) {
		goto cleanup;
	}

	if ((it = pkgdb_query_fetch(db, match, argc, argv, reponame, flags)) == NULL)
		goto cleanup;

	while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) {
		pkg_jobs_add(jobs, pkg);
		pkg = NULL;
	}
	
	pkgdb_it_free(it);

	if (pkg_jobs_is_empty(jobs))
		goto cleanup;

	if (!quiet) {
		print_jobs_summary(jobs, PKG_JOBS_FETCH, "The following packages will be fetched:\n\n");
		
		if (!yes)
			pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes);
		if (!yes)
			yes = query_yesno("\nProceed with fetching packages [y/N]: ");
	}
	
	if (yes)
		if (pkg_jobs_apply(jobs, 0) != EPKG_OK)
			goto cleanup;

	retcode = EXIT_SUCCESS;

	cleanup:
	pkg_jobs_free(jobs);
	pkgdb_close(db);

	return (retcode);
}
예제 #30
0
파일: fetch.c 프로젝트: alepharchives/pkgng
int
pkg_fetch_file_to_fd(const char *url, int dest, time_t t)
{
	FILE *remote = NULL;
	struct url *u;
	struct url_stat st;
	off_t done = 0;
	off_t r;

	int64_t max_retry, retry;
	time_t begin_dl;
	time_t now;
	time_t last = 0;
	char buf[10240];
	int retcode = EPKG_OK;
	bool srv = false;
	char zone[MAXHOSTNAMELEN + 12];
	struct dns_srvinfo *mirrors, *current;

	current = mirrors = NULL;

	fetchTimeout = 30;

	if (pkg_config_int64(PKG_CONFIG_FETCH_RETRY, &max_retry) == EPKG_FATAL)
		max_retry = 3;

	retry = max_retry;

	u = fetchParseURL(url);
	while (remote == NULL) {
		if (retry == max_retry) {
			pkg_config_bool(PKG_CONFIG_SRV_MIRROR, &srv);
			if (srv) {
				if (strcmp(u->scheme, "file") != 0) {
					snprintf(zone, sizeof(zone),
					    "_%s._tcp.%s", u->scheme, u->host);
					mirrors = dns_getsrvinfo(zone);
					current = mirrors;
				}
			}
		}

		if (mirrors != NULL)
			strlcpy(u->host, current->host, sizeof(u->host));

		remote = fetchXGet(u, &st, "");
		if (remote == NULL) {
			--retry;
			if (retry <= 0) {
				pkg_emit_error("%s: %s", url,
				    fetchLastErrString);
				retcode = EPKG_FATAL;
				goto cleanup;
			}
			if (mirrors == NULL) {
				sleep(1);
			} else {
				current = current->next;
				if (current == NULL)
					current = mirrors;
			}
		}
	}
	if (t != 0) {
		if (st.mtime <= t) {
			retcode = EPKG_UPTODATE;
			goto cleanup;
		}
	}

	begin_dl = time(NULL);
	while (done < st.size) {
		if ((r = fread(buf, 1, sizeof(buf), remote)) < 1)
			break;

		if (write(dest, buf, r) != r) {
			pkg_emit_errno("write", "");
			retcode = EPKG_FATAL;
			goto cleanup;
		}

		done += r;
		now = time(NULL);
		/* Only call the callback every second */
		if (now > last || done == st.size) {
			pkg_emit_fetching(url, st.size, done, (now - begin_dl));
			last = now;
		}
	}

	if (ferror(remote)) {
		pkg_emit_error("%s: %s", url, fetchLastErrString);
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	cleanup:

	if (remote != NULL)
		fclose(remote);

	fetchFreeURL(u);

	return (retcode);
}