int version_constraints_satisfied(depend_t * depends, pkg_t * pkg) { pkg_t *temp; int comparison; if (depends->constraint == NONE) return 1; temp = pkg_new(); parse_version(temp, depends->version); comparison = pkg_compare_versions(pkg, temp); free(temp->version); free(temp); if ((depends->constraint == EARLIER) && (comparison < 0)) return 1; else if ((depends->constraint == LATER) && (comparison > 0)) return 1; else if ((depends->constraint == EQUAL) && (comparison == 0)) return 1; else if ((depends->constraint == LATER_EQUAL) && (comparison >= 0)) return 1; else if ((depends->constraint == EARLIER_EQUAL) && (comparison <= 0)) return 1; return 0; }
static tn_array *parse_removed(char *str) { char *p, *q; tn_array *pkgs; pkgs = pkgs_array_new(64); p = q = eatws(str); while ((p = next_tokn(&q, ' ', NULL)) != NULL) { const char *name = NULL, *ver = NULL, *rel = NULL; int32_t epoch = 0; struct pkg *pkg; if (*p == '\0') continue; if ((pkg = pndir_parse_pkgkey(p, strlen(p), NULL)) == NULL) { if (poldek_util_parse_nevr(p, &name, &epoch, &ver, &rel)) { pkg = pkg_new(name, epoch, ver, rel, NULL, NULL); } } if (pkg) n_array_push(pkgs, pkg); } if (n_array_size(pkgs) == 0) { n_array_free(pkgs); pkgs = NULL; } return pkgs; }
static int do_test_pkgmatch(char *capevr, char *evr, int relation, unsigned maflags, int expected) { struct pkg *pkg; struct capreq *req; const char *ver, *rel; int rc; int32_t epoch; if (!poldek_util_parse_evr(n_strdup(capevr), &epoch, &ver, &rel)) return -1; pkg = pkg_new("poo", epoch, ver, rel, NULL, NULL); req = capreq_new_evr(NULL, "poo", n_strdup(evr), relation, 0); rc = pkg_xmatch_req(pkg, req, maflags) ? 1 : 0; msgn_i(1, 2, "%s match%s %s => %s", pkg_evr_snprintf_s(pkg), maflags_snprintf_s(maflags), capreq_snprintf_s(req), rc ? "YES" : "NO"); fail_if(rc != expected, "match %s <=> %s not equal %d", pkg_evr_snprintf_s(pkg), capreq_snprintf_s(req), expected); pkg_free(pkg); capreq_free(req); return rc; }
static int pkg_repo_binary_add_from_manifest(char *buf, const char *origin, const char *digest, long offset, sqlite3 *sqlite, struct pkg_manifest_key **keys, struct pkg **p, bool is_legacy, struct pkg_repo *repo) { int rc = EPKG_OK; struct pkg *pkg; const char *local_origin, *pkg_arch; if (*p == NULL) { rc = pkg_new(p, PKG_REMOTE); if (rc != EPKG_OK) return (EPKG_FATAL); } else { pkg_reset(*p, PKG_REMOTE); } pkg = *p; pkg_manifest_keys_new(keys); rc = pkg_parse_manifest(pkg, buf, offset, *keys); if (rc != EPKG_OK) { goto cleanup; } rc = pkg_is_valid(pkg); if (rc != EPKG_OK) { goto cleanup; } /* Ensure that we have a proper origin and arch*/ pkg_get(pkg, PKG_ORIGIN, &local_origin, PKG_ARCH, &pkg_arch); if (local_origin == NULL || strcmp(local_origin, origin) != 0) { pkg_emit_error("manifest contains origin %s while we wanted to add origin %s", local_origin ? local_origin : "NULL", origin); rc = EPKG_FATAL; goto cleanup; } if (pkg_arch == NULL || !is_valid_abi(pkg_arch, true)) { rc = EPKG_FATAL; pkg_emit_error("repository %s contains packages with wrong ABI: %s", repo->name, pkg_arch); goto cleanup; } pkg_set(pkg, PKG_REPONAME, repo->name); if (is_legacy) { pkg_set(pkg, PKG_OLD_DIGEST, digest); pkg_checksum_calculate(pkg, NULL); } else { pkg_set(pkg, PKG_DIGEST, digest); } rc = pkg_repo_binary_add_pkg(pkg, NULL, sqlite, true); cleanup: return (rc); }
/** * @brief Creates a new FreeBSD package from one installed on a system * @param pkg_name The name of the package to retrieve * @param pkg_db_dir The directory in the database the package is registered in * @todo Make this work through a pkg_db callback * @todo Remove the need for pkg_db_dir by using a struct pkg_repo * @todo move the freebsd_package creation to an internal function * * This creates a package object from an installed package. * It can be used to retrieve information from the pkg_db and deintall * the package. * @return A pkg object or NULL */ struct pkg * pkg_new_freebsd_installed(const char *pkg_name, const char *pkg_db_dir) { struct pkg *pkg; struct freebsd_package *fpkg; struct stat sb; /* check the directory exists and is a directory */ if (lstat(pkg_db_dir, &sb) == -1) return NULL; if (!S_ISDIR(sb.st_mode)) return NULL; pkg = pkg_new(pkg_name, freebsd_get_control_files, freebsd_get_control_file, NULL, freebsd_free); if (pkg == NULL) return NULL; pkg_add_callbacks_data(pkg, freebsd_get_version, freebsd_get_origin); fpkg = freebsd_package_new(); if (fpkg == NULL) { pkg_free(pkg); return NULL; } pkg->data = fpkg; fpkg->pkg_type = fpkg_from_installed; fpkg->db_dir = strdup(pkg_db_dir); if (fpkg->db_dir == NULL) { pkg_free(pkg); return NULL; } return pkg; }
static int pkg_read_manifest_v2(FILE *fs, struct pkg **pkg_p, struct pkg_manifest_key *keys) { struct pkg_section_hdr sec; struct pkg *pkg; void *payload; size_t paylen; int retcode = EPKG_OK; if (pkg_skip_to_section(fs, PKG_FORMAT_SECTION_MANIFEST, &sec) != EPKG_OK) { return (EPKG_FATAL); } if (pkg_section_maybe_uncompress(fs, &sec, &payload, &paylen) != EPKG_OK) { return (EPKG_FATAL); } retcode = pkg_new(pkg_p, PKG_FILE); if (retcode != EPKG_OK) { goto cleanup; } pkg = *pkg_p; retcode = pkg_parse_manifest(pkg, payload, paylen, keys); cleanup: free(payload); return (retcode); }
static int pkg_add_from_manifest(FILE *f, char *buf, const char *origin, long offset, const char *manifest_digest, const char *local_arch, sqlite3 *sqlite, struct pkg_manifest_parser **parser, struct pkg **p) { int rc = EPKG_OK; struct pkg *pkg; const char *local_origin, *pkg_arch; if (buf == NULL && fseek(f, offset, SEEK_SET) == -1) { pkg_emit_errno("fseek", "invalid manifest offset"); return (EPKG_FATAL); } if (*p == NULL) { rc = pkg_new(p, PKG_REMOTE); if (rc != EPKG_OK) return (EPKG_FATAL); } else { pkg_reset(*p, PKG_REMOTE); } pkg = *p; pkg_manifest_parser_new(parser); if (buf == NULL) { rc = pkg_parse_manifest_file_ev(pkg, f, *parser); } else { rc = pkg_parse_manifest_ev(pkg, buf, offset, *parser); } if (rc != EPKG_OK) { goto cleanup; } rc = pkg_is_valid(pkg); if (rc != EPKG_OK) { goto cleanup; } /* Ensure that we have a proper origin and arch*/ pkg_get(pkg, PKG_ORIGIN, &local_origin, PKG_ARCH, &pkg_arch); if (local_origin == NULL || strcmp(local_origin, origin) != 0) { pkg_emit_error("manifest contains origin %s while we wanted to add origin %s", local_origin ? local_origin : "NULL", origin); rc = EPKG_FATAL; goto cleanup; } if (pkg_arch == NULL || strcmp(pkg_arch, local_arch) != 0) { pkg_emit_error("package %s is built for %s arch, and local arch is %s", origin, pkg_arch ? pkg_arch : "NULL", local_arch); rc = EPKG_FATAL; goto cleanup; } rc = pkgdb_repo_add_package(pkg, NULL, sqlite, manifest_digest, true, false); cleanup: return (rc); }
/* * Downloads file from url, installs in package database, return package name. */ int opkg_prepare_url_for_install(const char *url, char **namep) { int err = 0; pkg_t *pkg; pkg = pkg_new(); if (str_starts_with(url, "http://") || str_starts_with(url, "ftp://")) { char *tmp_file; char *file_basec = xstrdup(url); char *file_base = basename(file_basec); sprintf_alloc(&tmp_file, "%s/%s", conf->tmp_dir, file_base); err = opkg_download(url, tmp_file, NULL, NULL, 0); if (err) return err; err = pkg_init_from_file(pkg, tmp_file); if (err) return err; free(tmp_file); free(file_basec); } else if (strcmp(&url[strlen(url) - 4], OPKG_PKG_EXTENSION) == 0 || strcmp(&url[strlen(url) - 4], IPKG_PKG_EXTENSION) == 0 || strcmp(&url[strlen(url) - 4], DPKG_PKG_EXTENSION) == 0) { err = pkg_init_from_file(pkg, url); if (err) return err; opkg_msg(DEBUG2, "Package %s provided by hand (%s).\n", pkg->name, pkg->local_filename); pkg->provided_by_hand = 1; } else { pkg_deinit(pkg); free(pkg); return 0; } pkg->dest = conf->default_dest; pkg->state_want = SW_INSTALL; pkg->state_flag |= SF_PREFER; hash_insert_pkg(pkg, 1); if (namep) { *namep = pkg->name; } return 0; }
/* 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); }
/** * @brief Creates a new FreeBSD package from a FILE pointer * @param fd A pointer to a FILE object containing a FreeBSD Package * * This creates a pkg object from a given file pointer. * It is able to then manipulate the package and install the it to the pkg_db. * @todo Write * @return A new package object or NULL */ struct pkg * pkg_new_freebsd_from_file(FILE *fd) { struct pkg *pkg; struct freebsd_package *fpkg; const char *pkg_name; if (fd == NULL) return NULL; /* Create the new package data object */ fpkg = freebsd_package_new(); if (fpkg == NULL) return NULL; fpkg->fd = fd; fpkg->pkg_type = fpkg_from_file; fpkg->archive = archive_read_new(); archive_read_support_compression_bzip2(fpkg->archive); archive_read_support_compression_gzip(fpkg->archive); archive_read_support_format_tar(fpkg->archive); archive_read_open_stream(fpkg->archive, fd, 10240); /* * Get the +CONTENTS file. * We can't use the callbacks as we need the * package name to use with pkg_new */ freebsd_open_control_files(fpkg); assert(fpkg->control != NULL); freebsd_parse_contents(fpkg); assert(fpkg->contents != NULL); if (fpkg->contents->lines[1].line_type != PKG_LINE_NAME) { /** @todo cleanup */ return NULL; } pkg_name = fpkg->contents->lines[1].data; pkg = pkg_new(pkg_name, freebsd_get_control_files, freebsd_get_control_file, freebsd_get_deps, freebsd_free); if (pkg == NULL) { /** @todo cleanup */ return NULL; } pkg_add_callbacks_data(pkg, freebsd_get_version, freebsd_get_origin); pkg_add_callbacks_install(pkg, freebsd_get_next_file, freebsd_run_script); pkg->data = fpkg; return pkg; }
Pkg *pkg_db_get_installed_matched(PkgDb db, const char *pattern){ Pkg *pkgs; struct dirent *dirn; size_t size; int count = 0; if(db == NULL || db->db_d == NULL || db->d_h == NULL) RETURN_P_ERR(P_ERR_INVALID_DESCRIPTOR, NULL); size = sizeof(Pkg); pkgs = malloc(size); assert(pkgs != NULL); pkgs[0] = NULL; while((dirn = readdir(db->d_h)) != NULL){ if(pattern != NULL){ if(!strncmp(pattern, dirn->d_name, strlen(pattern)) && dirn->d_type == DT_DIR && dirn->d_name[0] != '.'){ size += sizeof(Pkg); pkgs = reallocf(pkgs, size); assert(pkgs != NULL); pkgs[count++] = pkg_new(db->db_d, dirn->d_name); pkgs[count] = NULL; } } else if(dirn->d_type == DT_DIR && dirn->d_name[0] != '.'){ size += sizeof(Pkg); pkgs = reallocf(pkgs, size); assert(pkgs != NULL); pkgs[count++] = pkg_new(db->db_d, dirn->d_name); pkgs[count] = NULL; } } return pkgs; }
/* 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); }
static int pkg_repo_add_from_manifest(char *buf, const char *origin, long offset, const char *manifest_digest, sqlite3 *sqlite, struct pkg_manifest_key **keys, struct pkg **p) { int rc = EPKG_OK; struct pkg *pkg; const char *local_origin, *pkg_arch; if (*p == NULL) { rc = pkg_new(p, PKG_REMOTE); if (rc != EPKG_OK) return (EPKG_FATAL); } else { pkg_reset(*p, PKG_REMOTE); } pkg = *p; pkg_manifest_keys_new(keys); rc = pkg_parse_manifest(pkg, buf, offset, *keys); if (rc != EPKG_OK) { goto cleanup; } rc = pkg_is_valid(pkg); if (rc != EPKG_OK) { goto cleanup; } /* Ensure that we have a proper origin and arch*/ pkg_get(pkg, PKG_ORIGIN, &local_origin, PKG_ARCH, &pkg_arch); if (local_origin == NULL || strcmp(local_origin, origin) != 0) { pkg_emit_error("manifest contains origin %s while we wanted to add origin %s", local_origin ? local_origin : "NULL", origin); rc = EPKG_FATAL; goto cleanup; } if (pkg_arch == NULL || !is_valid_abi(pkg_arch, true)) { rc = EPKG_FATAL; goto cleanup; } rc = pkgdb_repo_add_package(pkg, NULL, sqlite, manifest_digest, true); cleanup: return (rc); }
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; int ret = EPKG_FATAL; pkg_debug(1, "Creating package from stage directory: '%s'", rootdir); if ((ret = pkg_new(&pkg, PKG_FILE)) != EPKG_OK) goto cleanup; if ((ret = pkg_load_metadata(pkg, NULL, md_dir, plist, rootdir, false)) != EPKG_OK) 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; } /* 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: free(pkg); packing_finish(pkg_archive); return (ret); }
static int convert_from_old(const char *pkg_add_dbdir, bool dry_run) { DIR *d; struct dirent *dp; struct pkg *p = NULL; char path[MAXPATHLEN]; struct pkgdb *db = NULL; if ((d = opendir(pkg_add_dbdir)) == NULL) err(EX_NOINPUT, "%s", pkg_add_dbdir); if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) { return (EX_IOERR); } while ((dp = readdir(d)) != NULL) { if (dp->d_type == DT_DIR) { if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue; if (p == NULL) { if (pkg_new(&p, PKG_OLD_FILE) != EPKG_OK) err(EX_OSERR, "malloc"); } else pkg_reset(p, PKG_OLD_FILE); printf("Converting %s...\n", dp->d_name); snprintf(path, MAXPATHLEN, "%s/%s", pkg_add_dbdir, dp->d_name); if (pkg_old_load_from_path(p, path) != EPKG_OK) { fprintf(stderr, "Skipping invalid package: %s\n", path); continue; } pkg_from_old(p); if (!dry_run) pkgdb_register_ports(db, p); } } pkg_free(p); pkgdb_close(db); return (EX_OK); }
int pkg_create_fakeroot(const char *outdir, pkg_formats format, const char *rootdir, const char *metadatadir) { struct pkg *pkg = NULL; struct packing *pkg_archive = NULL; char *manifest = NULL, *manifest_path = NULL; int ret = ENOMEM; /* Load the manifest from the metadata directory */ if (asprintf(&manifest_path, "%s/+MANIFEST", metadatadir) == -1) goto cleanup; pkg_new(&pkg, PKG_FILE); if (pkg == NULL) goto cleanup; ret = pkg_load_manifest_file(pkg, manifest_path); /* Create the archive */ pkg_archive = pkg_create_archive(outdir, pkg, format, 0); if (pkg_archive == NULL) { ret = EPKG_FATAL; /* XXX do better */ goto cleanup; } /* Now traverse the file directories, adding to the archive */ packing_append_tree(pkg_archive, metadatadir, NULL); packing_append_tree(pkg_archive, rootdir, "/"); ret = EPKG_OK; cleanup: if (pkg != NULL) free(pkg); if (manifest_path != NULL) free(manifest_path); if (manifest != NULL) free(manifest); if (ret == EPKG_OK) ret = packing_finish(pkg_archive); return ret; }
int pkg_hash_add_from_file(ipkg_conf_t *conf, const char *file_name, pkg_src_t *src, pkg_dest_t *dest, int is_status_file) { hash_table_t *hash = &conf->pkg_hash; char **raw; char **raw_start; pkg_t *pkg; raw = raw_start = read_raw_pkgs_from_file(file_name); if (!raw) return -ENOMEM; while(*raw){ /* don't worry, we'll increment raw in the parsing function */ pkg = pkg_new(); if (!pkg) return -ENOMEM; if (pkg_parse_raw(pkg, &raw, src, dest) == 0) { if (!pkg->architecture) { char *version_str = pkg_version_str_alloc(pkg); pkg->architecture = pkg_get_default_arch(conf); ipkg_message(conf, IPKG_ERROR, "Package %s version %s has no architecture specified, defaulting to %s.\n", pkg->name, version_str, pkg->architecture); free(version_str); } hash_insert_pkg(hash, pkg, is_status_file,conf); } else { free(pkg); } } /* XXX: CLEANUP: I'd like a cleaner interface for cleaning up memory after read_raw_pkgs_from_file */ raw = raw_start; while (*raw) { free(*raw++); } free(raw_start); return 0; }
struct pkg * pkg_new_freebsd(FILE *fd) { struct pkg *pkg; struct freebsd_package *f_pkg; char *pkg_name; f_pkg = freebsd_get_package(fd); /* Find the package name */ pkg_name = freebsd_get_pkg_name(f_pkg->control[0]->contents); pkg = pkg_new(pkg_name, freebsd_get_control_files, freebsd_get_next_file, freebsd_get_deps, freebsd_free); free(pkg_name); if (pkg == NULL) return NULL; pkg->data = f_pkg; return pkg; }
/* 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; int ret = ENOMEM; pkg_debug(1, "Creating package from stage directory: '%s'", rootdir); if(pkg_new(&pkg, PKG_FILE) != EPKG_OK) { ret = EPKG_FATAL; goto cleanup; } if ((ret = pkg_load_metadata(pkg, manifest, NULL, plist, rootdir, false)) != 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; } if ((ret = pkg_create_from_dir(pkg, rootdir, pkg_archive)) != EPKG_OK) pkg_emit_error("package creation failed"); cleanup: free(pkg); packing_finish(pkg_archive); return (ret); }
int exec_register(int argc, char **argv) { struct pkg *pkg; struct pkgdb *db; struct utsname u; regex_t preg; regmatch_t pmatch[2]; int ch; char *plist = NULL; char *v = NULL; char *arch = NULL; char *mdir = NULL; char *www = NULL; char *input_path = NULL; char fpath[MAXPATHLEN]; const char *desc = NULL; size_t size; bool heuristic = false; bool legacy = false; int retcode = 0; int ret = 0; if (geteuid() != 0) { warnx("registering packages can only be done as root"); return (EX_NOPERM); } pkg_new(&pkg, PKG_INSTALLED); while ((ch = getopt(argc, argv, "a:f:m:i:l")) != -1) { switch (ch) { case 'f': if ((plist = strdup(optarg)) == NULL) errx(1, "cannot allocate memory"); break; case 'm': mdir = strdup(optarg); break; case 'a': arch = strdup(optarg); break; case 'i': if ((input_path = strdup(optarg)) == NULL) errx(1, "cannot allocate memory"); break; case 'l': legacy = true; break; default: printf("%c\n", ch); usage_register(); return (-1); } } if (ret != 0) { pkg_error_warn("can not parse arguments"); return (1); } if (plist == NULL) errx(EX_USAGE, "missing -f flag"); uname(&u); if (arch == NULL) { pkg_set(pkg, PKG_ARCH, u.machine); } else { pkg_set(pkg, PKG_ARCH, arch); free(arch); } if (mdir == NULL) errx(EX_USAGE, "missing -m flag"); snprintf(fpath, MAXPATHLEN, "%s/+MANIFEST", mdir); if ((ret = pkg_load_manifest_file(pkg, fpath)) != EPKG_OK) { pkg_error_warn("can not parse manifest %s", fpath); return (EX_SOFTWARE); } snprintf(fpath, MAXPATHLEN, "%s/+DESC", mdir); pkg_set_from_file(pkg, PKG_DESC, fpath); snprintf(fpath, MAXPATHLEN, "%s/+DISPLAY", mdir); pkg_set_from_file(pkg, PKG_MESSAGE, fpath); snprintf(fpath, MAXPATHLEN, "%s/+MTREE_DIR", mdir); pkg_set_from_file(pkg, PKG_MTREE, mdir); snprintf(fpath, MAXPATHLEN, "%s/+INSTALL", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/+PRE_INSTALL", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/+POST_INSTALL", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/+DEINSTALL", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/+PRE_DEINSTALL", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/+POST_DEINSTALL", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/+UPGRADE", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/+PRE_UPGRADE", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/+POST_UPGRADE", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/pkg-install", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/pkg-pre-install", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/pkg-post-install", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/pkg-pre-deinstall", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/pkg-post-deinstall", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/pkg-upgrade", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/pkg-pre-deupgrade", mdir); pkg_addscript(pkg, fpath); snprintf(fpath, MAXPATHLEN, "%s/pkg-post-deupgrade", mdir); pkg_addscript(pkg, fpath); /* if www is not given then try to determine it from description */ if (www == NULL) { desc = pkg_get(pkg, PKG_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); } if (strstr(u.release, "RELEASE") == NULL) { asprintf(&v, "%s-%d", u.release, __FreeBSD_version); pkg_set(pkg, PKG_OSVERSION, v); free(v); } else { pkg_set(pkg, PKG_OSVERSION, u.release); } /* TODO: missing osversion get it from uname*/ ret += ports_parse_plist(pkg, plist); if (ret != 0) { pkg_error_warn("can not parse plist file"); return (-1); } if (plist != NULL) free(plist); if (pkgdb_open(&db, PKGDB_DEFAULT, R_OK|W_OK) != EPKG_OK) { pkg_error_warn("can not open database"); return (-1); } if (heuristic) pkg_analyse_files(db, pkg); if (input_path != NULL) { pkg_copy_tree(pkg, input_path, "/"); free(input_path); } if (pkgdb_register_pkg(db, pkg) != EPKG_OK) { pkg_error_warn("can not register package"); retcode = 1; } pkgdb_register_finale(db, ret); if (ret != EPKG_OK) { pkg_error_warn("can not register package"); retcode = 1; } if (pkg_get(pkg, PKG_MESSAGE) != NULL && !legacy) printf("%s\n", pkg_get(pkg, PKG_MESSAGE)); pkgdb_close(db); pkg_free(pkg); return (retcode); }
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); */ }
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_file *file = NULL; int i; ATF_REQUIRE_EQ(EPKG_OK, pkg_new(&p, PKG_FILE)); ATF_REQUIRE(p != NULL); ATF_REQUIRE_EQ(EPKG_OK, pkg_parse_manifest(p, manifest)); #if 0 ATF_REQUIRE(strcmp(pkg_get(p, PKG_NAME), "foobar") == 0); ATF_REQUIRE(strcmp(pkg_get(p, PKG_VERSION), "0.3") == 0); ATF_REQUIRE(strcmp(pkg_get(p, PKG_ORIGIN), "foo/bar") == 0); ATF_REQUIRE(strcmp(pkg_get(p, PKG_COMMENT), "A dummy manifest") == 0); ATF_REQUIRE(strcmp(pkg_get(p, PKG_ARCH), "amd64") == 0); ATF_REQUIRE(strcmp(pkg_get(p, PKG_VERSION), "800500") == 0); ATF_REQUIRE(strcmp(pkg_get(p, PKG_WWW), "http://www.foobar.com") == 0); ATF_REQUIRE(strcmp(pkg_get(p, PKG_MAINTAINER), "*****@*****.**") == 0); #endif 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); 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_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); }
ATF_TC_BODY(parse_plist, tc) { struct pkg *p; struct plist *plist; char buf[BUFSIZ]; ATF_REQUIRE_EQ(EPKG_OK, pkg_new(&p, PKG_INSTALLED)); plist = plist_new(p, "/plop"); ATF_REQUIRE(plist != NULL); ATF_REQUIRE(plist->pkg == p); ATF_REQUIRE_EQ(plist->prefix[0], '\0'); strlcpy(buf, "@cwd /myprefix", BUFSIZ); ATF_REQUIRE_EQ(EPKG_OK, plist_parse_line(p, plist, buf)); ATF_REQUIRE_STREQ(p->prefix, "/myprefix"); ATF_REQUIRE_STREQ(plist->prefix, "/myprefix"); ATF_REQUIRE_STREQ(plist->uname, "root"); ATF_REQUIRE_STREQ(plist->gname, "wheel"); strlcpy(buf, "@owner bob", BUFSIZ); ATF_REQUIRE_EQ(EPKG_OK, plist_parse_line(p, plist, buf)); ATF_REQUIRE_STREQ(plist->uname, "bob"); strlcpy(buf, "@group sponge", BUFSIZ); ATF_REQUIRE_EQ(EPKG_OK, plist_parse_line(p, plist, buf)); ATF_REQUIRE_STREQ(plist->gname, "sponge"); strlcpy(buf, "@group", BUFSIZ); ATF_REQUIRE_EQ(EPKG_OK, plist_parse_line(p, plist, buf)); ATF_REQUIRE_STREQ(plist->gname, "wheel"); strlcpy(buf, "@owner", BUFSIZ); ATF_REQUIRE_EQ(EPKG_OK, plist_parse_line(p, plist, buf)); ATF_REQUIRE_STREQ(plist->uname, "root"); strlcpy(buf, "@cwd plop", BUFSIZ); ATF_REQUIRE_EQ(EPKG_OK, plist_parse_line(p, plist, buf)); ATF_REQUIRE_STREQ(plist->prefix, "plop"); strlcpy(buf, "@cwd", BUFSIZ); ATF_REQUIRE_EQ(EPKG_OK, plist_parse_line(p, plist, buf)); ATF_REQUIRE_STREQ(plist->prefix, "/myprefix"); ATF_REQUIRE_STREQ(plist->slash, "/"); strlcpy(buf, "@cwd /another/prefix/", BUFSIZ); ATF_REQUIRE_EQ(EPKG_OK, plist_parse_line(p, plist, buf)); ATF_REQUIRE_STREQ(plist->prefix, "/another/prefix/"); ATF_REQUIRE_STREQ(plist->slash, ""); ATF_REQUIRE_EQ(0, plist->perm); strlcpy(buf, "@mode 0755", BUFSIZ); ATF_REQUIRE_EQ(EPKG_OK, plist_parse_line(p, plist, buf)); ATF_REQUIRE_EQ(0755, plist->perm); strlcpy(buf, "@mode", BUFSIZ); ATF_REQUIRE_EQ(EPKG_OK, plist_parse_line(p, plist, buf)); ATF_REQUIRE_EQ(0, plist->perm); strlcpy(buf, "@blabla", BUFSIZ); ATF_REQUIRE_EQ(EPKG_FATAL, plist_parse_line(p, plist, buf)); strlcpy(buf, "nonexisting/file", BUFSIZ); ATF_REQUIRE_EQ(EPKG_FATAL, plist_parse_line(p, plist, buf)); pkg_free(p); plist_free(plist); }
Pkg pkg_archive_get_pkg(char *a_path, PkgDb db){ Pkg pkg; char *path; char *file, *pkg_n; struct archive_entry *entry; struct archive *a; int r, fd; if(a_path == NULL || db == NULL) RETURN_P_ERR(P_ERR_INVALID_DESCRIPTOR, NULL); pkg_n = pkg_archive_get_pkg_name(a_path); if(pkg_n == NULL) return NULL; asprintf(&path, "%s/%s", db->db_d, pkg_n); assert(path != NULL); r = mkdir(path, DEF_O_MODE); if(r == -1) if(errno != EEXIST && errno != EISDIR){ free((void *)pkg_n); free(path); RETURN_P_ERRNO(NULL); } a = pkg_archive_open(a_path); if(a == NULL) return NULL; for(;;){ r = archive_read_next_header(a, &entry); if(r == ARCHIVE_EOF) break; if(r != ARCHIVE_OK){ free((void *)pkg_n); free(path); RETURN_P_LARCHIVE(NULL, a); } file = (char *)archive_entry_pathname(entry); if(file[0] == '+'){ asprintf((void *)&file, "%s/%s", path, file); assert(file != NULL); fd = open(file, O_CREAT | O_WRONLY, DEF_O_MODE); if(fd == -1){ pkg_archive_close(a); free((void *)pkg_n); free(path); free((void *)file); RETURN_P_ERRNO(NULL); } r = archive_read_data_into_fd(a, fd); close(fd); free((void *)file); if(r == -1){ free((void *)pkg_n); free(path); RETURN_P_LARCHIVE(NULL, a); } } } pkg = pkg_new(db->db_d, pkg_n); pkg_archive_close(a); free((void *)pkg_n); free(path); return pkg; }
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); }
/** * @brief Creates an empty package with no callbacks * @param pkg_name The name of the package * * This is the simplest package constructor. * It is used to create a package with just a name associated with it. * Only pkg_get_name() and pkg_compare() will work with the created package. * @return An empty package */ struct pkg* pkg_new_empty(const char *pkg_name) { return pkg_new(pkg_name, NULL, NULL, NULL, NULL, NULL, NULL, NULL); }
int exec_register(int argc, char **argv) { struct pkg *pkg = NULL; struct pkgdb *db = NULL; const char *plist = NULL; const char *mdir = NULL; const char *mfile = NULL; const char *input_path = NULL; const char *location = NULL; bool legacy = false; bool testing_mode = false; int ch; int ret = EPKG_OK; int retcode = EX_OK; /* options descriptor */ struct option longopts[] = { { "automatic", no_argument, NULL, 'A' }, { "debug", no_argument, NULL, 'd' }, { "legacy", no_argument, NULL, 'l' }, { "manifest", required_argument, NULL, 'M' }, { "metadata", required_argument, NULL, 'm' }, { "plist", required_argument, NULL, 'f' }, { "relocate", required_argument, NULL, 1 }, { "root", required_argument, NULL, 'i' }, { "test", no_argument, NULL, 't' }, { NULL, 0, NULL, 0}, }; if (pkg_new(&pkg, PKG_INSTALLED) != EPKG_OK) err(EX_OSERR, "malloc"); while ((ch = getopt_long(argc, argv, "+Adf:i:lM:m:t", 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': mfile = optarg; break; case 'm': mdir = optarg; break; case 't': testing_mode = true; break; case 1: location = optarg; break; default: warnx("Unrecognised option -%c\n", ch); usage_register(); pkg_free(pkg); 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 register packages"); pkg_free(pkg); return (EX_NOPERM); } else if (retcode != EPKG_OK) { pkg_free(pkg); 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(); pkg_free(pkg); return (EX_USAGE); } if (mfile == NULL && mdir == NULL) { warnx("One of either -m or -M flags is required"); usage_register(); pkg_free(pkg); return (EX_USAGE); } if (testing_mode && input_path != NULL) { warnx("-i incompatible with -t option"); usage_register(); pkg_free(pkg); return (EX_USAGE); } ret = pkg_load_metadata(pkg, mfile, mdir, plist, input_path, testing_mode); if (ret != EPKG_OK) { pkg_free(pkg); return (EX_IOERR); } if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) { pkg_free(pkg); return (EX_IOERR); } if (pkgdb_obtain_lock(db, PKGDB_LOCK_EXCLUSIVE) != EPKG_OK) { pkgdb_close(db); pkg_free(pkg); warnx("Cannot get an exclusive lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } retcode = pkg_add_port(db, pkg, input_path, location, testing_mode); if (!legacy && retcode == EPKG_OK && messages != NULL) { printf("%s\n", utstring_body(messages)); } pkg_free(pkg); return (retcode != EPKG_OK ? EX_SOFTWARE : EX_OK); }