/*-
* Copyright (c) 2011-2014 Baptiste Daroussin <bapt@FreeBSD.org>
* Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
* Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
* Copyright (c) 2013-2014 Matthew Seaman <matthew@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <err.h>
#include <stdio.h>
#include <pkg.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <getopt.h>
#include "pkgcli.h"
void
usage_register(void)
{
fprintf(stderr, "Usage: pkg register [-dtN] [-i <input-path>]"
" [-f <plist-file>] -m <metadatadir>\n");
fprintf(stderr, " pkg register [-dtN] [-i <input_path>]"
" -M <manifest>\n\n");
fprintf(stderr, "For more information see 'pkg help register'.\n");
}
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 testing_mode = false;
bool reg_in_db = true;
int ch;
int ret = EPKG_OK;
int retcode = EXIT_SUCCESS;
/* options descriptor */
struct option longopts[] = {
{ "automatic", no_argument, NULL, 'A' },
{ "debug", no_argument, NULL, 'd' },
{ "manifest", required_argument, NULL, 'M' },
{ "metadata", required_argument, NULL, 'm' },
{ "no-registration", no_argument, NULL, 'N' },
{ "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(EXIT_FAILURE, "malloc");
while ((ch = getopt_long(argc, argv, "+Adf:i:M:m:Nt", longopts, NULL)) != -1) {
switch (ch) {
case 'A':
case 'd':
pkg_set(pkg, PKG_ATTR_AUTOMATIC, (bool)true);
break;
case 'f':
plist = optarg;
break;
case 'i':
input_path = optarg;
break;
case 'M':
mfile = optarg;
break;
case 'm':
mdir = optarg;
break;
case 'N':
reg_in_db = false;
break;
case 't':
testing_mode = true;
break;
case 1:
location = optarg;
break;
default:
warnx("Unrecognised option -%c", ch);
usage_register();
pkg_free(pkg);
return (EXIT_FAILURE);
}
}
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 (EXIT_FAILURE);
} else if (retcode != EPKG_OK) {
pkg_free(pkg);
return (EXIT_FAILURE);
}
/*
* 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 (EXIT_FAILURE);
}
if (mfile == NULL && mdir == NULL) {
warnx("One of either -m or -M flags is required");
usage_register();
pkg_free(pkg);
return (EXIT_FAILURE);
}
if (testing_mode && input_path != NULL) {
warnx("-i incompatible with -t option");
usage_register();
pkg_free(pkg);
return (EXIT_FAILURE);
}
ret = pkg_load_metadata(pkg, mfile, mdir, plist, input_path, testing_mode);
if (ret != EPKG_OK) {
pkg_free(pkg);
return (EXIT_FAILURE);
}
if (reg_in_db && pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
pkg_free(pkg);
return (EXIT_FAILURE);
}
if (db != NULL && 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 (EXIT_FAILURE);
}
retcode = pkg_add_port(db, pkg, input_path, location, testing_mode);
if (retcode == EPKG_OK && messages != NULL && !quiet) {
fflush(messages->fp);
printf("%s\n", messages->buf);
}
pkg_free(pkg);
if (db != NULL) {
pkgdb_release_lock(db, PKGDB_LOCK_EXCLUSIVE);
pkgdb_close(db);
}
return (retcode != EPKG_OK ? EXIT_FAILURE : EXIT_SUCCESS);
}