/* The "no concessions to old pkg_tools" variant: just get everything * from the manifest */ int pkg_create_from_manifest(const char *outdir, pkg_formats format, const char *rootdir, const char *manifest, const char *plist) { struct pkg *pkg = NULL; struct packing *pkg_archive = NULL; char arch[BUFSIZ]; int ret = ENOMEM; struct pkg_manifest_key *keys = NULL; pkg_debug(1, "Creating package from stage directory: '%s'", rootdir); if(pkg_new(&pkg, PKG_FILE) != EPKG_OK) { ret = EPKG_FATAL; goto cleanup; } pkg_manifest_keys_new(&keys); if ((ret = pkg_parse_manifest_file(pkg, manifest, keys)) != EPKG_OK) { ret = EPKG_FATAL; goto cleanup; } /* if no arch autodetermine it */ if (pkg->abi == NULL) { pkg_get_myarch(arch, BUFSIZ); pkg->abi = strdup(arch); } if (plist != NULL && ports_parse_plist(pkg, plist, rootdir) != EPKG_OK) { ret = EPKG_FATAL; goto cleanup; } /* Create the archive */ pkg_archive = pkg_create_archive(outdir, pkg, format, 0); if (pkg_archive == NULL) { ret = EPKG_FATAL; /* XXX do better */ goto cleanup; } pkg_create_from_dir(pkg, rootdir, pkg_archive); ret = EPKG_OK; cleanup: free(pkg); pkg_manifest_keys_free(keys); packing_finish(pkg_archive); return (ret); }
/* The "no concessions to old pkg_tools" variant: just get everything * from the manifest */ int pkg_create_from_manifest(const char *outdir, pkg_formats format, const char *rootdir, const char *manifest, bool old) { struct pkg *pkg = NULL; struct packing *pkg_archive = NULL; char arch[BUFSIZ]; int ret = ENOMEM; char *buf; struct pkg_manifest_key *keys = NULL; pkg_debug(1, "Creating package from stage directory: '%s'", rootdir); if(pkg_new(&pkg, old ? PKG_OLD_FILE : PKG_FILE) != EPKG_OK) { ret = EPKG_FATAL; goto cleanup; } pkg_manifest_keys_new(&keys); if ((ret = pkg_parse_manifest_file(pkg, manifest, keys)) != EPKG_OK) { ret = EPKG_FATAL; goto cleanup; } /* if no arch autodetermine it */ pkg_get(pkg, PKG_ARCH, &buf); if (buf == NULL) { pkg_get_myarch(arch, BUFSIZ); pkg_set(pkg, PKG_ARCH, arch); } /* Create the archive */ pkg_archive = pkg_create_archive(outdir, pkg, format, 0); if (pkg_archive == NULL) { ret = EPKG_FATAL; /* XXX do better */ goto cleanup; } pkg_create_from_dir(pkg, rootdir, pkg_archive); ret = EPKG_OK; cleanup: free(pkg); pkg_manifest_keys_free(keys); if (ret == EPKG_OK) ret = packing_finish(pkg_archive); return (ret); }
int pkg_create_staged(const char *outdir, pkg_formats format, const char *rootdir, const char *md_dir, char *plist, bool old) { struct pkg *pkg = NULL; struct pkg_file *file = NULL; struct pkg_dir *dir = NULL; struct packing *pkg_archive = NULL; char *manifest = NULL; char path[MAXPATHLEN]; char arch[BUFSIZ]; int ret = ENOMEM; char *buf; int i; regex_t preg; regmatch_t pmatch[2]; size_t size; char *www = NULL; struct pkg_manifest_key *keys = NULL; pkg_debug(1, "Creating package from stage directory: '%s'", rootdir); /* Load the manifest from the metadata directory */ if (snprintf(path, sizeof(path), "%s/+MANIFEST", md_dir) == -1) goto cleanup; if(pkg_new(&pkg, old ? PKG_OLD_FILE : PKG_FILE) != EPKG_OK) { ret = EPKG_FATAL; goto cleanup; } pkg_manifest_keys_new(&keys); if ((ret = pkg_parse_manifest_file(pkg, path, keys)) != EPKG_OK) { ret = EPKG_FATAL; goto cleanup; } /* if no descriptions provided then try to get it from a file */ pkg_get(pkg, PKG_DESC, &buf); if (buf == NULL) { if (snprintf(path, sizeof(path), "%s/+DESC", md_dir) == -1) goto cleanup; if (access(path, F_OK) == 0) { pkg_debug(1, "Taking description from: '%s'", path); pkg_set_from_file(pkg, PKG_DESC, path, false); } } /* if no message try to get it from a file */ pkg_get(pkg, PKG_MESSAGE, &buf); if (buf == NULL) { ret = snprintf(path, sizeof(path), "%s/+DISPLAY", md_dir); if (ret == -1) goto cleanup; if (access(path, F_OK) == 0) { pkg_debug(1, "Taking message from: '%s'", path); pkg_set_from_file(pkg, PKG_MESSAGE, path, false); } } /* if no arch autodetermine it */ pkg_get(pkg, PKG_ARCH, &buf); if (buf == NULL) { pkg_get_myarch(arch, BUFSIZ); pkg_set(pkg, PKG_ARCH, arch); } /* if no mtree try to get it from a file */ pkg_get(pkg, PKG_MTREE, &buf); if (buf == NULL) { ret = snprintf(path, sizeof(path), "%s/+MTREE_DIRS", md_dir); if (ret == -1) goto cleanup; if (access(path, F_OK) == 0) { pkg_debug(1, "Taking mtree definition from: '%s'", path); pkg_set_from_file(pkg, PKG_MTREE, path, false); } } for (i = 0; scripts[i] != NULL; i++) { snprintf(path, sizeof(path), "%s/%s", md_dir, scripts[i]); if (access(path, F_OK) == 0) pkg_addscript_file(pkg, path); } if (plist != NULL && ports_parse_plist(pkg, plist, rootdir) != EPKG_OK) { ret = EPKG_FATAL; goto cleanup; } /* if www is not given then try to determine it from description */ if (www != NULL) { pkg_set(pkg, PKG_WWW, www); free(www); } pkg_get(pkg, PKG_WWW, &www); if (www == NULL) { pkg_get(pkg, PKG_DESC, &buf); if (buf == NULL) { pkg_emit_error("No www or desc defined in manifest"); ret = EPKG_FATAL; goto cleanup; } regcomp(&preg, "^WWW:[[:space:]]*(.*)$", REG_EXTENDED|REG_ICASE|REG_NEWLINE); if (regexec(&preg, buf, 2, pmatch, 0) == 0) { size = pmatch[1].rm_eo - pmatch[1].rm_so; www = strndup(&buf[pmatch[1].rm_so], size); pkg_set(pkg, PKG_WWW, www); free(www); } else { pkg_set(pkg, PKG_WWW, "UNKNOWN"); } regfree(&preg); } /* Create the archive */ pkg_archive = pkg_create_archive(outdir, pkg, format, 0); if (pkg_archive == NULL) { ret = EPKG_FATAL; /* XXX do better */ goto cleanup; } /* XXX: autoplist support doesn't work right with meta-ports */ if (0 && pkg_files(pkg, &file) != EPKG_OK && pkg_dirs(pkg, &dir) != EPKG_OK) { /* Now traverse the file directories, adding to the archive */ packing_append_tree(pkg_archive, md_dir, NULL); packing_append_tree(pkg_archive, rootdir, "/"); } else { pkg_create_from_dir(pkg, rootdir, pkg_archive); } ret = EPKG_OK; cleanup: free(pkg); free(manifest); pkg_manifest_keys_free(keys); if (ret == EPKG_OK) ret = packing_finish(pkg_archive); return ret; }
void test_manifest(void) { struct pkg *p = NULL; struct pkg_dep *dep = NULL; struct pkg_conflict *conflict = NULL; struct pkg_option *option = NULL; struct pkg_category *category = NULL; struct pkg_file *file = NULL; struct pkg_manifest_key *keys = NULL; const char *pkg_str; int64_t pkg_int; int i; pkg_manifest_keys_new(&keys); ATF_REQUIRE(keys != NULL); ATF_REQUIRE_EQ(EPKG_OK, pkg_new(&p, PKG_FILE)); ATF_REQUIRE(p != NULL); ATF_REQUIRE_EQ(EPKG_OK, pkg_parse_manifest(p, manifest, strlen(manifest), keys)); pkg_manifest_keys_free(keys); ATF_REQUIRE(pkg_get(p, PKG_NAME, &pkg_str) == EPKG_OK); ATF_REQUIRE(strcmp(pkg_str, "foobar") == 0); ATF_REQUIRE(pkg_get(p, PKG_VERSION, &pkg_str) == EPKG_OK); ATF_REQUIRE(strcmp(pkg_str, "0.3") == 0); ATF_REQUIRE(pkg_get(p, PKG_ORIGIN, &pkg_str) == EPKG_OK); ATF_REQUIRE(strcmp(pkg_str, "foo/bar") == 0); ATF_REQUIRE(pkg_get(p, PKG_COMMENT, &pkg_str) == EPKG_OK); ATF_REQUIRE(strcmp(pkg_str, "A dummy manifest") == 0); ATF_REQUIRE(pkg_get(p, PKG_ARCH, &pkg_str) == EPKG_OK); ATF_REQUIRE(strcmp(pkg_str, "amd64") == 0); ATF_REQUIRE(pkg_get(p, PKG_WWW, &pkg_str) == EPKG_OK); ATF_REQUIRE(strcmp(pkg_str, "http://www.foobar.com") == 0); ATF_REQUIRE(pkg_get(p, PKG_MAINTAINER, &pkg_str) == EPKG_OK); ATF_REQUIRE(strcmp(pkg_str, "*****@*****.**") == 0); ATF_REQUIRE(pkg_get(p, PKG_PREFIX, &pkg_str) == EPKG_OK); ATF_REQUIRE(strcmp(pkg_str, "/opt/prefix") == 0); ATF_REQUIRE(pkg_get(p, PKG_DESC, &pkg_str) == EPKG_OK); ATF_REQUIRE(strcmp(pkg_str, "port description") == 0); ATF_REQUIRE(pkg_get(p, PKG_MESSAGE, &pkg_str) == EPKG_OK); ATF_REQUIRE(strcmp(pkg_str, "pkg message") == 0); ATF_REQUIRE(pkg_get(p, PKG_FLATSIZE, &pkg_int) == EPKG_OK); ATF_REQUIRE(pkg_int == 10000); i = 0; while (pkg_deps(p, &dep) == EPKG_OK) { if (i == 0) { ATF_REQUIRE(strcmp(pkg_dep_name(dep), "depfoo") == 0); ATF_REQUIRE(strcmp(pkg_dep_origin(dep), "dep/foo") == 0); ATF_REQUIRE(strcmp(pkg_dep_version(dep), "1.2") == 0); } else if (i == 1) { ATF_REQUIRE(strcmp(pkg_dep_name(dep), "depbar") == 0); ATF_REQUIRE(strcmp(pkg_dep_origin(dep), "dep/bar") == 0); ATF_REQUIRE(strcmp(pkg_dep_version(dep), "3.4") == 0); } i++; } ATF_REQUIRE(i == 2); i = 0; #if 0 while (pkg_conflicts(p, &conflict) == EPKG_OK) { if (i == 0) { ATF_REQUIRE(strcmp(pkg_conflict_glob(conflict), "foo-*") == 0); } else if (i == 1) { ATF_REQUIRE(strcmp(pkg_conflict_glob(conflict), "bar-*") == 0); } i++; } ATF_REQUIRE(i == 2); #endif i = 0; while (pkg_options(p, &option) == EPKG_OK) { if (i == 0) { ATF_REQUIRE(strcmp(pkg_option_opt(option), "foo") == 0); ATF_REQUIRE(strcmp(pkg_option_value(option), "true") == 0); } else if (i == 1) { ATF_REQUIRE(strcmp(pkg_option_opt(option), "bar") == 0); ATF_REQUIRE(strcmp(pkg_option_value(option), "false") == 0); } i++; } ATF_REQUIRE(i == 2); i = 0; while (pkg_categories(p, &category) == EPKG_OK) { if (i == 0) { ATF_REQUIRE(strcmp(pkg_category_name(category), "foo") == 0); } else if (i == 1) { ATF_REQUIRE(strcmp(pkg_category_name(category), "bar") == 0); } i++; } ATF_REQUIRE(i == 2); ATF_REQUIRE(pkg_files(p, &file) == EPKG_OK); ATF_REQUIRE(strcmp(pkg_file_path(file), "/usr/local/bin/foo") == 0); #if 0 ATF_REQUIRE(strcmp(pkg_file_sha256(file), "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b") == 0); #endif pkg_free(p); /* p = NULL; ATF_REQUIRE(pkg_new(&p, PKG_FILE) == EPKG_OK); ATF_REQUIRE(pkg_parse_manifest(p, wrong_manifest1) == EPKG_FATAL); pkg_free(p); p = NULL; ATF_REQUIRE(pkg_new(&p, PKG_FILE) == EPKG_OK); ATF_REQUIRE(pkg_parse_manifest(p, wrong_manifest2) == EPKG_FATAL); pkg_free(p); p = NULL; ATF_REQUIRE(pkg_new(&p, PKG_FILE) == EPKG_OK); ATF_REQUIRE(pkg_parse_manifest(p, wrong_manifest3) == EPKG_FATAL); pkg_free(p); p = NULL; ATF_REQUIRE(pkg_new(&p, PKG_FILE) == EPKG_OK); ATF_REQUIRE(pkg_parse_manifest(p, wrong_manifest4) == EPKG_FATAL); pkg_free(p); */ }
int exec_query(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; struct pkg_manifest_key *keys = NULL; char *pkgname = NULL; int query_flags = PKG_LOAD_BASIC; match_t match = MATCH_EXACT; int ch; int ret; int retcode = EX_OK; int i; char multiline = 0; char *condition = NULL; struct sbuf *sqlcond = NULL; const unsigned int q_flags_len = NELEM(accepted_query_flags); struct option longopts[] = { { "all", no_argument, NULL, 'a' }, { "case-sensitive", no_argument, NULL, 'C' }, { "evaluate", required_argument, NULL, 'e' }, { "file", required_argument, NULL, 'F' }, { "glob", no_argument, NULL, 'g' }, { "case-insensitive", no_argument, NULL, 'i' }, { "regex", no_argument, NULL, 'x' }, { NULL, 0, NULL, 0 }, }; while ((ch = getopt_long(argc, argv, "+aCe:F:gix", longopts, NULL)) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'C': pkgdb_set_case_sensitivity(true); break; case 'e': match = MATCH_CONDITION; condition = optarg; break; case 'F': pkgname = optarg; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'x': match = MATCH_REGEX; break; default: usage_query(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc == 0) { usage_query(); return (EX_USAGE); } /* Default to all packages if no pkg provided */ if (argc == 1 && pkgname == NULL && condition == NULL && match == MATCH_EXACT) { match = MATCH_ALL; } else if (((argc == 1) ^ (match == MATCH_ALL)) && pkgname == NULL && condition == NULL) { usage_query(); return (EX_USAGE); } if (analyse_query_string(argv[0], accepted_query_flags, q_flags_len, &query_flags, &multiline) != EPKG_OK) return (EX_USAGE); if (pkgname != NULL) { pkg_manifest_keys_new(&keys); if (pkg_open(&pkg, pkgname, keys, 0) != EPKG_OK) { return (EX_IOERR); } pkg_manifest_keys_free(keys); print_query(pkg, argv[0], multiline); pkg_free(pkg); return (EX_OK); } if (condition != NULL) { sqlcond = sbuf_new_auto(); if (format_sql_condition(condition, sqlcond, false) != EPKG_OK) { sbuf_delete(sqlcond); return (EX_USAGE); } sbuf_finish(sqlcond); } ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL); if (ret == EPKG_ENOACCESS) { warnx("Insufficient privileges to query the package database"); return (EX_NOPERM); } else if (ret == EPKG_ENODB) { if (!quiet) warnx("No packages installed"); return (EX_OK); } else if (ret != EPKG_OK) return (EX_IOERR); ret = pkgdb_open(&db, PKGDB_DEFAULT); if (ret != EPKG_OK) return (EX_IOERR); if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get a read lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } if (match == MATCH_ALL || match == MATCH_CONDITION) { const char *condition_sql = NULL; if (match == MATCH_CONDITION && sqlcond) condition_sql = sbuf_data(sqlcond); if ((it = pkgdb_query(db, condition_sql, match)) == NULL) return (EX_IOERR); while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) print_query(pkg, argv[0], multiline); if (ret != EPKG_END) retcode = EX_SOFTWARE; pkgdb_it_free(it); } else { int nprinted = 0; for (i = 1; i < argc; i++) { pkgname = argv[i]; if ((it = pkgdb_query(db, pkgname, match)) == NULL) { retcode = EX_IOERR; goto cleanup; } while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) { nprinted++; print_query(pkg, argv[0], multiline); } if (ret != EPKG_END) { retcode = EX_SOFTWARE; break; } pkgdb_it_free(it); } if (nprinted == 0 && retcode == EX_OK) { /* ensure to return a non-zero status when no package were found. */ retcode = EX_UNAVAILABLE; } } cleanup: pkg_free(pkg); pkgdb_release_lock(db, PKGDB_LOCK_READONLY); pkgdb_close(db); return (retcode); }
int exec_register(int argc, char **argv) { struct pkg *pkg = NULL; struct pkgdb *db = NULL; struct pkg_manifest_key *keys = NULL; regex_t preg; regmatch_t pmatch[2]; char *arch = NULL; char myarch[BUFSIZ]; char *www = NULL; char fpath[MAXPATHLEN]; const char *plist = NULL; const char *mdir = NULL; const char *mfile = NULL; const char *input_path = NULL; const char *desc = NULL; const char *location = NULL; size_t size; bool developer; bool legacy = false; bool old = false; bool __unused metadata_only = false; bool testing_mode = false; int ch; int i; int ret = EPKG_OK; int retcode = EX_OK; /* options descriptor */ struct option longopts[] = { { "automatic", no_argument, NULL, 'A' }, { "plist", required_argument, NULL, 'f' }, { "root", required_argument, NULL, 'i' }, { "legacy", no_argument, NULL, 'l' }, { "manifest", required_argument, NULL, 'M' }, { "metadata", required_argument, NULL, 'm' }, { "old", no_argument, NULL, 'O' }, { "test", no_argument, NULL, 't' }, { "relocate", required_argument, NULL, 1 }, { NULL, 0, NULL, 0}, }; developer = pkg_object_bool(pkg_config_get("DEVELOPER_MODE")); if (pkg_new(&pkg, PKG_INSTALLED) != EPKG_OK) err(EX_OSERR, "malloc"); while ((ch = getopt_long(argc, argv, "Adf:i:lM:m:Ot", longopts, NULL)) != -1) { switch (ch) { case 'A': case 'd': pkg_set(pkg, PKG_AUTOMATIC, (bool)true); break; case 'f': plist = optarg; break; case 'i': input_path = optarg; break; case 'l': legacy = true; break; case 'M': metadata_only = true; mfile = optarg; break; case 'm': mdir = optarg; break; case 'O': old = true; break; case 't': testing_mode = true; break; case 1: location = optarg; break; default: warnx("Unrecognised option -%c\n", ch); usage_register(); return (EX_USAGE); } } if (!old) { retcode = pkgdb_access(PKGDB_MODE_READ | PKGDB_MODE_WRITE | PKGDB_MODE_CREATE, PKGDB_DB_LOCAL); if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to register packages"); return (EX_NOPERM); } else if (retcode != EPKG_OK) return (EX_IOERR); else retcode = EX_OK; } /* * Ideally, the +MANIFEST should be all that is necessary, * since it can contain all of the meta-data supplied by the * other files mentioned below. These are here for backwards * compatibility with the way the ports tree works with * pkg_tools. * * The -M option specifies one manifest file to read the * meta-data from, and overrides the use of legacy meta-data * inputs. * * Dependencies, shlibs, files etc. may be derived by * analysing the package files (maybe discovered as the * content of the staging directory) unless -t (testing_mode) * is used. */ if (mfile != NULL && mdir != NULL) { warnx("Cannot use both -m and -M together"); usage_register(); return (EX_USAGE); } if (mfile == NULL && mdir == NULL) { warnx("One of either -m or -M flags is required"); usage_register(); return (EX_USAGE); } if (mfile != NULL && plist != NULL) { warnx("-M incompatible with -f option"); usage_register(); return (EX_USAGE); } if (testing_mode && input_path != NULL) { warnx("-i incompatible with -t option"); usage_register(); return (EX_USAGE); } pkg_manifest_keys_new(&keys); if (mfile != NULL) { ret = pkg_parse_manifest_file(pkg, mfile, keys); pkg_manifest_keys_free(keys); if (ret != EPKG_OK) return (EX_IOERR); } else { snprintf(fpath, sizeof(fpath), "%s/+MANIFEST", mdir); ret = pkg_parse_manifest_file(pkg, fpath, keys); pkg_manifest_keys_free(keys); if (ret != EPKG_OK) return (EX_IOERR); snprintf(fpath, sizeof(fpath), "%s/+DESC", mdir); pkg_set_from_file(pkg, PKG_DESC, fpath, false); snprintf(fpath, sizeof(fpath), "%s/+DISPLAY", mdir); if (access(fpath, F_OK) == 0) pkg_set_from_file(pkg, PKG_MESSAGE, fpath, false); snprintf(fpath, sizeof(fpath), "%s/+MTREE_DIRS", mdir); if (access(fpath, F_OK) == 0) pkg_set_from_file(pkg, PKG_MTREE, fpath, false); 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 != NULL) { pkg_set(pkg, PKG_WWW, www); free(www); } pkg_get(pkg, PKG_WWW, &www); /* * 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); } if (plist != NULL) ret += ports_parse_plist(pkg, plist, input_path); } if (ret != EPKG_OK) { return (EX_IOERR); } if (!old) { if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) return (EX_IOERR); if (pkgdb_obtain_lock(db, PKGDB_LOCK_EXCLUSIVE) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an exclusive lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } } /* * testing_mode allows updating the local package database * without any check that the files etc. listed in the meta * data actually exist on the system. Inappropriate use of * testing_mode can really screw things up. */ if (!testing_mode) pkg_analyse_files(db, pkg, input_path); 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 (!testing_mode && input_path != NULL) pkg_copy_tree(pkg, input_path, location ? location : "/"); if (location != NULL) pkg_addannotation(pkg, "relocated", location); if (old) { if (pkg_register_old(pkg) != EPKG_OK) retcode = EX_SOFTWARE; } else { if (pkgdb_register_ports(db, pkg) != EPKG_OK) retcode = EX_SOFTWARE; } if (!legacy && pkg_has_message(pkg)) pkg_printf("%M\n", pkg); if (!old) { pkgdb_release_lock(db, PKGDB_LOCK_EXCLUSIVE); pkgdb_close(db); } pkg_free(pkg); return (retcode); }
int exec_info(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; int query_flags; struct pkg *pkg = NULL; uint64_t opt = INFO_TAG_NAMEVER; match_t match = MATCH_GLOB; char *pkgname; char *pkgversion = NULL, *pkgversion2 = NULL; const char *file = NULL; int ch, fd; int ret = EPKG_OK; int retcode = 0; bool gotone = false; int i, j; int sign = 0; int sign2 = 0; int open_flags = 0; bool pkg_exists = false; bool origin_search = false; bool e_flag = false; struct pkg_manifest_key *keys = NULL; #ifdef HAVE_CAPSICUM cap_rights_t rights; #endif struct option longopts[] = { { "all", no_argument, NULL, 'a' }, { "annotations", no_argument, NULL, 'A' }, { "provided-shlibs", no_argument, NULL, 'b' }, { "required-shlibs", no_argument, NULL, 'B' }, { "case-sensitive", no_argument, NULL, 'C' }, { "dependencies", no_argument, NULL, 'd' }, { "pkg-message", no_argument, NULL, 'D' }, { "exists", no_argument, NULL, 'e' }, { "show-name-only", no_argument, NULL, 'E' }, { "full", no_argument, NULL, 'f' }, { "file", required_argument, NULL, 'F' }, { "glob", no_argument, NULL, 'g' }, { "case-insensitive", no_argument, NULL, 'i' }, { "comment", no_argument, NULL, 'I' }, { "locked", no_argument, NULL, 'k' }, { "list-files", no_argument, NULL, 'l' }, { "origin", no_argument, NULL, 'o' }, { "by-origin", no_argument, NULL, 'O' }, { "prefix", no_argument, NULL, 'p' }, { "quiet", no_argument, NULL, 'q' }, { "required-by", no_argument, NULL, 'r' }, { "raw", no_argument, NULL, 'R' }, { "size", no_argument, NULL, 's' }, { "regex", no_argument, NULL, 'x' }, { "raw-format", required_argument, NULL, 1 }, { NULL, 0, NULL, 0 }, }; /* TODO: exclusive opts ? */ while ((ch = getopt_long(argc, argv, "+aAbBCdDeEfF:giIkloOpqrRsx", longopts, NULL)) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'A': opt |= INFO_ANNOTATIONS; break; case 'b': opt |= INFO_SHLIBS_PROVIDED; break; case 'B': opt |= INFO_SHLIBS_REQUIRED; break; case 'C': pkgdb_set_case_sensitivity(true); break; case 'd': opt |= INFO_DEPS; break; case 'D': opt |= INFO_MESSAGE; break; case 'e': pkg_exists = true;; retcode = 1; break; case 'E': /* ports compatibility */ e_flag = true; break; case 'f': opt |= INFO_FULL; break; case 'F': file = optarg; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'I': opt |= INFO_COMMENT; break; case 'k': opt |= INFO_LOCKED; break; case 'l': opt |= INFO_FILES; break; case 'o': opt |= INFO_ORIGIN; break; case 'O': origin_search = true; /* only for ports compat */ break; case 'p': opt |= INFO_PREFIX; break; case 'q': quiet = true; break; case 'r': opt |= INFO_RDEPS; break; case 'R': opt |= INFO_RAW; break; case 's': opt |= INFO_FLATSIZE; break; case 'x': match = MATCH_REGEX; break; case 1: if (strcasecmp(optarg, "json") == 0) opt |= INFO_RAW_JSON; else if (strcasecmp(optarg, "json-compact") == 0) opt |= INFO_RAW_JSON_COMPACT; else if (strcasecmp(optarg, "yaml") == 0) opt |= INFO_RAW_YAML; else if (strcasecmp(optarg, "ucl") == 0) opt |= INFO_RAW_UCL; else errx(EX_USAGE, "Invalid format '%s' for the " "raw output, expecting json, json-compact " "or yaml", optarg); break; default: usage_info(); return(EX_USAGE); } } if (argc == 1 || (argc == 2 && quiet)) match = MATCH_ALL; argc -= optind; argv += optind; if (argc == 0 && file == NULL && match != MATCH_ALL) { /* which -O bsd.*.mk always execpt clean output */ if (origin_search) return (EX_OK); usage_info(); return (EX_USAGE); } /* When no other data is requested, default is to print * 'name-ver comment' For -O, just print name-ver */ if (!origin_search && (opt & INFO_ALL) == 0 && match == MATCH_ALL && !quiet) opt |= INFO_COMMENT; /* Special compatibility: handle -O and -q -O */ if (origin_search) { if (quiet) { opt = INFO_TAG_NAMEVER; quiet = false; } else { opt = INFO_TAG_NAMEVER|INFO_COMMENT; } } if (match == MATCH_ALL && opt == INFO_TAG_NAMEVER) quiet = false; if (file != NULL) { if ((fd = open(file, O_RDONLY)) == -1) { warn("Unable to open %s", file); return (EX_IOERR); } #ifdef HAVE_CAPSICUM cap_rights_init(&rights, CAP_READ, CAP_FSTAT); if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS ) { warn("cap_rights_limit() failed"); close(fd); return (EX_SOFTWARE); } if (cap_enter() < 0 && errno != ENOSYS) { warn("cap_enter() failed"); close(fd); return (EX_SOFTWARE); } #endif if (opt == INFO_TAG_NAMEVER) opt |= INFO_FULL; pkg_manifest_keys_new(&keys); if (opt & INFO_RAW) { if ((opt & (INFO_RAW_JSON|INFO_RAW_JSON_COMPACT|INFO_RAW_UCL)) == 0) opt |= INFO_RAW_YAML; } if ((opt & (INFO_RAW | INFO_FILES | INFO_DIRS)) == 0) open_flags = PKG_OPEN_MANIFEST_COMPACT; if (pkg_open_fd(&pkg, fd, keys, open_flags) != EPKG_OK) { close(fd); return (1); } pkg_manifest_keys_free(keys); print_info(pkg, opt); close(fd); pkg_free(pkg); return (EX_OK); } ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL); if (ret == EPKG_ENOACCESS) { warnx("Insufficient privileges to query the package database"); return (EX_NOPERM); } else if (ret == EPKG_ENODB) { if (match == MATCH_ALL) return (EX_OK); if (origin_search) return (EX_OK); if (!quiet) warnx("No packages installed"); return (EX_UNAVAILABLE); } else if (ret != EPKG_OK) return (EX_IOERR); ret = pkgdb_open(&db, PKGDB_DEFAULT); if (ret != EPKG_OK) return (EX_IOERR); if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get a read lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } i = 0; do { gotone = false; pkgname = argv[i]; /* * allow to search for origin with a trailing / * likes audio/linux-vsound depending on ${PORTSDIR}/audio/sox/ */ if (argc > 0 && pkgname[strlen(pkgname) -1] == '/') pkgname[strlen(pkgname) -1] = '\0'; if (argc > 0) { j=0; while (pkgname[j] != '\0') { if (pkgname[j] == '<') { if (pkgversion) { pkgversion2 = pkgname + j; sign2 = LT; pkgversion2[0] = '\0'; pkgversion2++; if (pkgversion2[0] == '=') { pkgversion2++; sign=LE; j++; } } else { pkgversion = pkgname + j; sign = LT; pkgversion[0] = '\0'; pkgversion++; if (pkgversion[0] == '=') { pkgversion++; sign=LE; j++; } } } else if (pkgname[j] == '>') { if (pkgversion) { pkgversion2 = pkgname + j; sign2 = GT; pkgversion2[0] = '\0'; pkgversion2++; if (pkgversion2[0] == '=') { pkgversion2++; sign=GE; j++; } } else { pkgversion = pkgname + j; sign = GT; pkgversion[0] = '\0'; pkgversion++; if (pkgversion[0] == '=') { pkgversion++; sign=GE; j++; } } } else if (pkgname[j] == '=') { if (pkgversion) { pkgversion2 = pkgname + j; sign2 = EQ; pkgversion2[0] = '\0'; pkgversion2++; if (pkgversion2[0] == '=') { pkgversion2++; sign=EQ; j++; } } else { pkgversion = pkgname + j; sign = EQ; pkgversion[0] = '\0'; pkgversion++; if (pkgversion[0] == '=') { pkgversion++; sign=EQ; j++; } } } j++; } } if (match != MATCH_ALL && pkgname[0] == '\0') { fprintf(stderr, "Pattern must not be empty.\n"); i++; continue; } if ((it = pkgdb_query(db, pkgname, match)) == NULL) { goto cleanup; } /* this is place for compatibility hacks */ /* ports infrastructure expects pkg info -q -O to * always return 0 even if the ports doesn't exists */ if (origin_search) gotone = true; /* end of compatibility hacks */ /* * only show full version in case of match glob with a * single argument specified which does not contains * any glob pattern */ if (argc == 1 && !origin_search && !quiet && !e_flag && match == MATCH_GLOB && strcspn(pkgname, "*[]{}()") == strlen(pkgname) && opt == INFO_TAG_NAMEVER) opt |= INFO_FULL; query_flags = info_flags(opt, false); while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) { gotone = true; const char *version; pkg_get(pkg, PKG_VERSION, &version); if (pkgversion != NULL) { switch (pkg_version_cmp(version, pkgversion)) { case -1: if (sign != LT && sign != LE) { gotone = false; continue; } break; case 0: if (sign != LE && sign != GE && sign != EQ) { gotone = false; continue; } break; case 1: if (sign != GT && sign != GE) { gotone = false; continue; } break; } } if (pkgversion2 != NULL) { switch (pkg_version_cmp(version, pkgversion2)) { case -1: if (sign2 != LT && sign2 != LE) { gotone = false; continue; } break; case 0: if (sign2 != LE && sign2 != GE && sign2 != EQ) { gotone = false; continue; } break; case 1: if (sign2 != GT && sign2 != GE) { gotone = false; continue; } break; } } if (pkg_exists) retcode = EX_OK; else print_info(pkg, opt); } if (ret != EPKG_END) { retcode = EX_IOERR; } if (retcode == EX_OK && !gotone && match != MATCH_ALL) { if (!quiet) warnx("No package(s) matching %s", argv[i]); retcode = EX_SOFTWARE; } pkgdb_it_free(it); i++; } while (i < argc); cleanup: pkg_free(pkg); pkgdb_release_lock(db, PKGDB_LOCK_READONLY); pkgdb_close(db); return (retcode); }
int exec_add(int argc, char **argv) { struct pkgdb *db = NULL; struct sbuf *failedpkgs = NULL; char path[MAXPATHLEN]; char *file; int retcode; int ch; int i; int failedpkgcount = 0; pkg_flags f = PKG_FLAG_NONE; struct pkg_manifest_key *keys = NULL; const char *location = NULL; /* options descriptor */ struct option longopts[] = { { "no-scripts", no_argument, NULL, 'I' }, { "automatic", no_argument, NULL, 'A' }, { "force", no_argument, NULL, 'f' }, { "accept-missing", no_argument, NULL, 'M' }, { "quiet", no_argument, NULL, 'q' }, { "relocate", required_argument, NULL, 1 }, { NULL, 0, NULL, 0 } }; while ((ch = getopt_long(argc, argv, "IAfqM", longopts, NULL)) != -1) { switch (ch) { case 'I': f |= PKG_ADD_NOSCRIPT; break; case 'A': f |= PKG_ADD_AUTOMATIC; break; case 'f': f |= PKG_ADD_FORCE; force = true; break; case 'M': f |= PKG_ADD_FORCE_MISSING; break; case 'q': quiet = true; break; case 1: location = optarg; break; default: usage_add(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc < 1) { usage_add(); return (EX_USAGE); } retcode = pkgdb_access(PKGDB_MODE_READ | PKGDB_MODE_WRITE | PKGDB_MODE_CREATE, PKGDB_DB_LOCAL); if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to add packages"); return (EX_NOPERM); } else if (retcode != EPKG_OK) return (EX_IOERR); if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) return (EX_IOERR); if (pkgdb_obtain_lock(db, PKGDB_LOCK_EXCLUSIVE) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an exclusive lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } failedpkgs = sbuf_new_auto(); pkg_manifest_keys_new(&keys); for (i = 0; i < argc; i++) { if (is_url(argv[i]) == EPKG_OK) { snprintf(path, sizeof(path), "%s/%s.XXXXX", getenv("TMPDIR") != NULL ? getenv("TMPDIR") : "/tmp", basename(argv[i])); if ((retcode = pkg_fetch_file(NULL, argv[i], path, 0)) != EPKG_OK) break; file = path; } else { file = argv[i]; /* Special case: treat a filename of "-" as meaning 'read from stdin.' It doesn't make sense to have a filename of "-" more than once per command line, but we aren't testing for that at the moment */ if (strcmp(file, "-") != 0 && access(file, F_OK) != 0) { warn("%s", file); if (errno == ENOENT) warnx("Was 'pkg install %s' meant?", file); sbuf_cat(failedpkgs, argv[i]); if (i != argc - 1) sbuf_printf(failedpkgs, ", "); failedpkgcount++; continue; } } if ((retcode = pkg_add(db, file, f, keys, location)) != EPKG_OK) { sbuf_cat(failedpkgs, argv[i]); if (i != argc - 1) sbuf_printf(failedpkgs, ", "); failedpkgcount++; } if (is_url(argv[i]) == EPKG_OK) unlink(file); } pkg_manifest_keys_free(keys); pkgdb_release_lock(db, PKGDB_LOCK_EXCLUSIVE); pkgdb_close(db); if(failedpkgcount > 0) { sbuf_finish(failedpkgs); printf("\nFailed to install the following %d package(s): %s\n", failedpkgcount, sbuf_data(failedpkgs)); retcode = EPKG_FATAL; } sbuf_delete(failedpkgs); if (messages != NULL) { sbuf_finish(messages); printf("%s", sbuf_data(messages)); } return (retcode == EPKG_OK ? EX_OK : EX_SOFTWARE); }
int pkg_create_staged(const char *outdir, pkg_formats format, const char *rootdir, const char *md_dir, char *plist) { struct pkg *pkg = NULL; struct pkg_file *file = NULL; struct pkg_dir *dir = NULL; struct packing *pkg_archive = NULL; char *manifest = NULL; char arch[BUFSIZ]; int ret = ENOMEM; int i, mfd; regex_t preg; regmatch_t pmatch[2]; size_t size; struct pkg_manifest_key *keys = NULL; pkg_debug(1, "Creating package from stage directory: '%s'", rootdir); if ((mfd = open(md_dir, O_DIRECTORY)) == -1) { pkg_emit_errno("open", md_dir); goto cleanup; } if(pkg_new(&pkg, PKG_FILE) != EPKG_OK) { ret = EPKG_FATAL; goto cleanup; } pkg_manifest_keys_new(&keys); /* Load the manifest from the metadata directory */ if ((ret = pkg_parse_manifest_fileat(mfd, pkg, "+MANIFEST", keys)) != EPKG_OK) { ret = EPKG_FATAL; goto cleanup; } /* if no descriptions provided then try to get it from a file */ if (pkg->desc == NULL) pkg_load_from_file(mfd, pkg, PKG_DESC, "+DESC"); /* if no message try to get it from a file */ if (pkg->message == NULL) { /* Try ucl version first */ if (pkg_load_message_from_file(mfd, pkg, "+DISPLAY.ucl", true) != EPKG_OK) { pkg_load_message_from_file(mfd, pkg, "+DISPLAY", false); } } /* if no arch autodetermine it */ if (pkg->abi == NULL) { pkg_get_myarch(arch, BUFSIZ); pkg->abi = strdup(arch); } for (i = 0; scripts[i] != NULL; i++) { if (faccessat(mfd, scripts[i], F_OK, 0) == 0) pkg_addscript_fileat(mfd, pkg, scripts[i]); } if (plist != NULL && ports_parse_plist(pkg, plist, rootdir) != EPKG_OK) { ret = EPKG_FATAL; goto cleanup; } if (pkg->www == NULL) { if (pkg->desc == NULL) { pkg_emit_error("No www or desc defined in manifest"); ret = EPKG_FATAL; goto cleanup; } regcomp(&preg, "^WWW:[[:space:]]*(.*)$", REG_EXTENDED|REG_ICASE|REG_NEWLINE); if (regexec(&preg, pkg->desc, 2, pmatch, 0) == 0) { size = pmatch[1].rm_eo - pmatch[1].rm_so; pkg->www = strndup(&pkg->desc[pmatch[1].rm_so], size); } else { pkg->www = strdup("UNKNOWN"); } regfree(&preg); } /* Create the archive */ pkg_archive = pkg_create_archive(outdir, pkg, format, 0); if (pkg_archive == NULL) { ret = EPKG_FATAL; /* XXX do better */ goto cleanup; } /* XXX: autoplist support doesn't work right with meta-ports */ if (0 && pkg_files(pkg, &file) != EPKG_OK && pkg_dirs(pkg, &dir) != EPKG_OK) { /* Now traverse the file directories, adding to the archive */ packing_append_tree(pkg_archive, md_dir, NULL); packing_append_tree(pkg_archive, rootdir, "/"); ret = EPKG_OK; } else { ret = pkg_create_from_dir(pkg, rootdir, pkg_archive); } cleanup: if (mfd != -1) close(mfd); free(pkg); free(manifest); pkg_manifest_keys_free(keys); packing_finish(pkg_archive); return (ret); }
int exec_query(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; struct pkg_manifest_key *keys = NULL; char *pkgname = NULL; int query_flags = PKG_LOAD_BASIC; match_t match = MATCH_EXACT; int ch; int ret; int retcode = EX_OK; int i; char multiline = 0; char *condition = NULL; struct sbuf *sqlcond = NULL; const unsigned int q_flags_len = (sizeof(accepted_query_flags)/sizeof(accepted_query_flags[0])); while ((ch = getopt(argc, argv, "agixF:e:")) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'x': match = MATCH_REGEX; break; case 'F': pkgname = optarg; break; case 'e': match = MATCH_CONDITION; condition = optarg; break; default: usage_query(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc == 0) { usage_query(); return (EX_USAGE); } /* Default to all packages if no pkg provided */ if (argc == 1 && pkgname == NULL && condition == NULL && match == MATCH_EXACT) { match = MATCH_ALL; } else if ((argc == 1) ^ (match == MATCH_ALL) && pkgname == NULL && condition == NULL) { usage_query(); return (EX_USAGE); } if (analyse_query_string(argv[0], accepted_query_flags, q_flags_len, &query_flags, &multiline) != EPKG_OK) return (EX_USAGE); if (pkgname != NULL) { pkg_manifest_keys_new(&keys); if (pkg_open(&pkg, pkgname, keys, 0) != EPKG_OK) { return (EX_IOERR); } pkg_manifest_keys_free(keys); print_query(pkg, argv[0], multiline); pkg_free(pkg); return (EX_OK); } if (condition != NULL) { sqlcond = sbuf_new_auto(); if (format_sql_condition(condition, sqlcond, false) != EPKG_OK) { sbuf_delete(sqlcond); return (EX_USAGE); } sbuf_finish(sqlcond); } ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL); if (ret == EPKG_ENOACCESS) { warnx("Insufficient privilege to query package database"); return (EX_NOPERM); } else if (ret == EPKG_ENODB) { if (!quiet) warnx("No packages installed"); return (EX_OK); } else if (ret != EPKG_OK) return (EX_IOERR); ret = pkgdb_open(&db, PKGDB_DEFAULT); if (ret != EPKG_OK) return (EX_IOERR); if (match == MATCH_ALL || match == MATCH_CONDITION) { const char *condition_sql = NULL; if (match == MATCH_CONDITION && sqlcond) condition_sql = sbuf_data(sqlcond); if ((it = pkgdb_query(db, condition_sql, match)) == NULL) return (EX_IOERR); while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) print_query(pkg, argv[0], multiline); if (ret != EPKG_END) retcode = EX_SOFTWARE; pkgdb_it_free(it); } else { int nprinted = 0; for (i = 1; i < argc; i++) { pkgname = argv[i]; if ((it = pkgdb_query(db, pkgname, match)) == NULL) return (EX_IOERR); while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) { nprinted++; print_query(pkg, argv[0], multiline); } if (ret != EPKG_END) { retcode = EX_SOFTWARE; break; } pkgdb_it_free(it); } if (nprinted == 0 && retcode == EX_OK) { /* ensure to return a non-zero status when no package were found. */ retcode = EX_UNAVAILABLE; } } pkg_free(pkg); pkgdb_close(db); return (retcode); }
int exec_add(int argc, char **argv) { struct pkgdb *db = NULL; struct sbuf *failedpkgs = NULL; char path[MAXPATHLEN + 1]; char *file; int retcode; int ch; int i; int failedpkgcount = 0; pkg_flags f = PKG_FLAG_NONE; struct pkg_manifest_key *keys = NULL; while ((ch = getopt(argc, argv, "IAfq")) != -1) { switch (ch) { case 'I': f |= PKG_ADD_NOSCRIPT; break; case 'A': f |= PKG_FLAG_AUTOMATIC; break; case 'f': f |= PKG_FLAG_FORCE; break; case 'q': quiet = true; break; default: usage_add(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc < 1) { usage_add(); return (EX_USAGE); } retcode = pkgdb_access(PKGDB_MODE_READ | PKGDB_MODE_WRITE | PKGDB_MODE_CREATE, PKGDB_DB_LOCAL); if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privilege to add packages"); return (EX_NOPERM); } else if (retcode != EPKG_OK) return (EX_IOERR); if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) return (EX_IOERR); failedpkgs = sbuf_new_auto(); pkg_manifest_keys_new(&keys); for (i = 0; i < argc; i++) { if (is_url(argv[i]) == EPKG_OK) { snprintf(path, sizeof(path), "./%s", basename(argv[i])); if ((retcode = pkg_fetch_file(NULL, argv[i], path, 0)) != EPKG_OK) break; file = path; } else { file = argv[i]; if (access(file, F_OK) != 0) { warn("%s",file); if (errno == ENOENT) warnx("Did you mean 'pkg install %s'?", file); sbuf_cat(failedpkgs, argv[i]); if (i != argc - 1) sbuf_printf(failedpkgs, ", "); failedpkgcount++; continue; } } if ((retcode = pkg_add(db, file, f, keys)) != EPKG_OK) { sbuf_cat(failedpkgs, argv[i]); if (i != argc - 1) sbuf_printf(failedpkgs, ", "); failedpkgcount++; } } pkg_manifest_keys_free(keys); pkgdb_close(db); if(failedpkgcount > 0) { sbuf_finish(failedpkgs); printf("\nFailed to install the following %d package(s): %s\n", failedpkgcount, sbuf_data(failedpkgs)); retcode = EPKG_FATAL; } sbuf_delete(failedpkgs); if (messages != NULL) { sbuf_finish(messages); printf("%s", sbuf_data(messages)); } return (retcode == EPKG_OK ? EX_OK : EX_SOFTWARE); }
int pkg_load_metadata(struct pkg *pkg, const char *mfile, const char *md_dir, const char *plist, const char *rootdir, bool testing) { struct pkg_manifest_key *keys = NULL; char arch[BUFSIZ]; regex_t preg; regmatch_t pmatch[2]; int i, ret = EPKG_OK; int mfd = -1; size_t size; bool defaultarch = false; if (md_dir != NULL && (mfd = open(md_dir, O_DIRECTORY|O_CLOEXEC)) == -1) { pkg_emit_errno("open", md_dir); goto cleanup; } pkg_manifest_keys_new(&keys); if (mfile != NULL) { ret = pkg_parse_manifest_file(pkg, mfile, keys); } /* Load the manifest from the metadata directory */ if (mfile == NULL && mfd != -1 && (ret = pkg_parse_manifest_fileat(mfd, pkg, "+MANIFEST", keys)) != EPKG_OK) { ret = EPKG_FATAL; goto cleanup; } /* if no descriptions provided then try to get it from a file */ if (mfd != -1 && pkg->desc == NULL) pkg_load_from_file(mfd, pkg, PKG_DESC, "+DESC"); /* if no message try to get it from a file */ if (mfd != -1 && pkg->message == NULL) { /* Try ucl version first */ pkg_load_message_from_file(mfd, pkg, "+DISPLAY"); } /* if no arch autodetermine it */ if (pkg->abi == NULL) { pkg_get_myarch(arch, BUFSIZ); pkg->abi = strdup(arch); defaultarch = true; } for (i = 0; scripts[i] != NULL; i++) { if (faccessat(mfd, scripts[i], F_OK, 0) == 0) pkg_addscript_fileat(mfd, pkg, scripts[i]); } if (plist != NULL && ports_parse_plist(pkg, plist, rootdir) != EPKG_OK) { ret = EPKG_FATAL; goto cleanup; } if (pkg->www == NULL) { if (pkg->desc == NULL) { pkg_emit_error("No www or desc defined in manifest"); ret = EPKG_FATAL; goto cleanup; } regcomp(&preg, "^WWW:[[:space:]]*(.*)$", REG_EXTENDED|REG_ICASE|REG_NEWLINE); if (regexec(&preg, pkg->desc, 2, pmatch, 0) == 0) { size = pmatch[1].rm_eo - pmatch[1].rm_so; pkg->www = strndup(&pkg->desc[pmatch[1].rm_so], size); } else { pkg->www = strdup("UNKNOWN"); } regfree(&preg); } if (!testing) pkg_analyse_files(NULL, pkg, rootdir); if (developer_mode) pkg_suggest_arch(pkg, pkg->abi, defaultarch); cleanup: if (mfd != -1) close(mfd); pkg_manifest_keys_free(keys); return (ret); }
void read_pkg_file(void *data) { struct thd_data *d = (struct thd_data*) data; struct pkg_result *r; struct pkg_manifest_key *keys = NULL; FTSENT *fts_ent = NULL; char fts_accpath[MAXPATHLEN + 1]; char fts_path[MAXPATHLEN + 1]; char fts_name[MAXPATHLEN + 1]; off_t st_size; int fts_info, flags; char *ext = NULL; char *pkg_path; pkg_manifest_keys_new(&keys); for (;;) { fts_ent = NULL; /* * Get a file to read from. * Copy the data we need from the fts entry localy because as soon as * we unlock the fts_m mutex, we can not access it. */ pthread_mutex_lock(&d->fts_m); if (!d->stop) fts_ent = fts_read(d->fts); if (fts_ent != NULL) { strlcpy(fts_accpath, fts_ent->fts_accpath, sizeof(fts_accpath)); strlcpy(fts_path, fts_ent->fts_path, sizeof(fts_path)); strlcpy(fts_name, fts_ent->fts_name, sizeof(fts_name)); st_size = fts_ent->fts_statp->st_size; fts_info = fts_ent->fts_info; } pthread_mutex_unlock(&d->fts_m); // There is no more jobs, exit the main loop. if (fts_ent == NULL) break; /* skip everything that is not a file */ if (fts_info != FTS_F) continue; ext = strrchr(fts_name, '.'); if (ext == NULL) continue; if (strcmp(ext, ".tgz") != 0 && strcmp(ext, ".tbz") != 0 && strcmp(ext, ".txz") != 0 && strcmp(ext, ".tar") != 0) continue; *ext = '\0'; if (strcmp(fts_name, repo_db_archive) == 0 || strcmp(fts_name, repo_packagesite_archive) == 0 || strcmp(fts_name, repo_filesite_archive) == 0 || strcmp(fts_name, repo_digests_archive) == 0) continue; *ext = '.'; pkg_path = fts_path; pkg_path += strlen(d->root_path); while (pkg_path[0] == '/') pkg_path++; r = calloc(1, sizeof(struct pkg_result)); strlcpy(r->path, pkg_path, sizeof(r->path)); if (d->read_files) flags = PKG_OPEN_MANIFEST_ONLY; else flags = PKG_OPEN_MANIFEST_ONLY | PKG_OPEN_MANIFEST_COMPACT; if (pkg_open(&r->pkg, fts_accpath, keys, flags) != EPKG_OK) { r->retcode = EPKG_WARN; } else { sha256_file(fts_accpath, r->cksum); pkg_set(r->pkg, PKG_CKSUM, r->cksum, PKG_REPOPATH, pkg_path, PKG_PKGSIZE, st_size); } /* Add result to the FIFO and notify */ pthread_mutex_lock(&d->results_m); while (d->num_results >= d->max_results) { pthread_cond_wait(&d->has_room, &d->results_m); } LL_APPEND(d->results, r); d->num_results++; pthread_cond_signal(&d->has_result); pthread_mutex_unlock(&d->results_m); } /* * This thread is about to exit. * Notify the main thread that we are done. */ pthread_mutex_lock(&d->results_m); d->thd_finished++; pthread_cond_signal(&d->has_result); pthread_mutex_unlock(&d->results_m); pkg_manifest_keys_free(keys); }
int exec_clean(int argc, char **argv) { struct pkgdb *db = NULL; kh_sum_t *sumlist = NULL; dl_list dl; const char *cachedir; bool all = false; int retcode; int ch; int cachefd = -1; size_t total = 0; char size[8]; char *cksum; struct pkg_manifest_key *keys = NULL; #ifdef HAVE_CAPSICUM cap_rights_t rights; #endif struct option longopts[] = { { "all", no_argument, NULL, 'a' }, { "dry-run", no_argument, NULL, 'n' }, { "quiet", no_argument, NULL, 'q' }, { "yes", no_argument, NULL, 'y' }, { NULL, 0, NULL, 0 }, }; while ((ch = getopt_long(argc, argv, "+anqy", longopts, NULL)) != -1) { switch (ch) { case 'a': all = true; break; case 'n': dry_run = true; break; case 'q': quiet = true; break; case 'y': yes = true; break; default: usage_clean(); return (EX_USAGE); } } argc -= optind; argv += optind; cachedir = pkg_object_string(pkg_config_get("PKG_CACHEDIR")); cachefd = open(cachedir, O_DIRECTORY); if (cachefd == -1) { warn("Impossible to open %s", cachedir); return (EX_IOERR); } retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_REPO); if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to clean old packages"); close(cachefd); return (EX_NOPERM); } else if (retcode == EPKG_ENODB) { warnx("No package database installed. Nothing to do!"); close(cachefd); return (EX_OK); } else if (retcode != EPKG_OK) { warnx("Error accessing the package database"); close(cachefd); return (EX_SOFTWARE); } retcode = EX_SOFTWARE; if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) { close(cachefd); return (EX_IOERR); } if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) { pkgdb_close(db); close(cachefd); warnx("Cannot get a read lock on a database, it is locked by " "another process"); return (EX_TEMPFAIL); } #ifdef HAVE_CAPSICUM cap_rights_init(&rights, CAP_READ, CAP_LOOKUP, CAP_FSTATFS, CAP_FSTAT, CAP_UNLINKAT); if (cap_rights_limit(cachefd, &rights) < 0 && errno != ENOSYS ) { warn("cap_rights_limit() failed"); close(cachefd); return (EX_SOFTWARE); } if (cap_enter() < 0 && errno != ENOSYS) { warn("cap_enter() failed"); close(cachefd); return (EX_SOFTWARE); } #endif kv_init(dl); /* Build the list of out-of-date or obsolete packages */ pkg_manifest_keys_new(&keys); recursive_analysis(cachefd, db, cachedir, cachedir, &dl, &sumlist, all, &total); if (sumlist != NULL) { kh_foreach_value(sumlist, cksum, free(cksum)); kh_destroy_sum(sumlist); } if (kv_size(dl) == 0) { if (!quiet) printf("Nothing to do.\n"); retcode = EX_OK; goto cleanup; } humanize_number(size, sizeof(size), total, "B", HN_AUTOSCALE, HN_IEC_PREFIXES); if (!quiet) printf("The cleanup will free %s\n", size); if (!dry_run) { if (query_yesno(false, "\nProceed with cleaning the cache? ")) { retcode = delete_dellist(cachefd, cachedir, &dl, kv_size(dl)); } } else { retcode = EX_OK; } cleanup: pkgdb_release_lock(db, PKGDB_LOCK_READONLY); pkgdb_close(db); pkg_manifest_keys_free(keys); free_dellist(&dl); if (cachefd != -1) close(cachefd); return (retcode); }