int pkg_old_load_from_path(struct pkg *pkg, const char *path) { char *desc; char *www; char fpath[MAXPATHLEN]; regex_t preg; regmatch_t pmatch[2]; int i; size_t size; char myarch[BUFSIZ]; if (!is_dir(path)) return (EPKG_FATAL); snprintf(fpath, sizeof(fpath), "%s/+CONTENTS", path); if (ports_parse_plist(pkg, fpath, NULL) != EPKG_OK) return (EPKG_FATAL); snprintf(fpath, sizeof(fpath), "%s/+COMMENT", path); if (access(fpath, F_OK) == 0) pkg_set_from_file(pkg, PKG_COMMENT, fpath, true); snprintf(fpath, sizeof(fpath), "%s/+DESC", path); if (access(fpath, F_OK) == 0) pkg_set_from_file(pkg, PKG_DESC, fpath, false); snprintf(fpath, sizeof(fpath), "%s/+DISPLAY", path); if (access(fpath, F_OK) == 0) pkg_set_from_file(pkg, PKG_MESSAGE, fpath, false); snprintf(fpath, sizeof(fpath), "%s/+MTREE_DIRS", path); 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", path, scripts[i]); if (access(fpath, F_OK) == 0) pkg_addscript_file(pkg, fpath); } pkg_get_myarch(myarch, BUFSIZ); pkg_set(pkg, PKG_ARCH, myarch); pkg_set(pkg, PKG_MAINTAINER, "unknown"); 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); return (EPKG_OK); }
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; }
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_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); }