register.c
1 /*- 2 * Copyright (c) 2011-2014 Baptiste Daroussin <bapt@FreeBSD.org> 3 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org> 4 * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com> 5 * Copyright (c) 2013-2014 Matthew Seaman <matthew@FreeBSD.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer 13 * in this position and unchanged. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/param.h> 31 32 #include <err.h> 33 #include <stdio.h> 34 #include <pkg.h> 35 #include <unistd.h> 36 #include <stdlib.h> 37 #include <stdbool.h> 38 #include <getopt.h> 39 40 #include "pkgcli.h" 41 42 void 43 usage_register(void) 44 { 45 fprintf(stderr, "Usage: pkg register [-dtN] [-i <input-path>]" 46 " [-f <plist-file>] -m <metadatadir>\n"); 47 fprintf(stderr, " pkg register [-dtN] [-i <input_path>]" 48 " -M <manifest>\n\n"); 49 fprintf(stderr, "For more information see 'pkg help register'.\n"); 50 } 51 52 int 53 exec_register(int argc, char **argv) 54 { 55 struct pkg *pkg = NULL; 56 struct pkgdb *db = NULL; 57 58 const char *plist = NULL; 59 const char *mdir = NULL; 60 const char *mfile = NULL; 61 const char *input_path = NULL; 62 const char *location = NULL; 63 64 bool testing_mode = false; 65 bool reg_in_db = true; 66 67 int ch; 68 int ret = EPKG_OK; 69 int retcode = EXIT_SUCCESS; 70 71 /* options descriptor */ 72 struct option longopts[] = { 73 { "automatic", no_argument, NULL, 'A' }, 74 { "debug", no_argument, NULL, 'd' }, 75 { "manifest", required_argument, NULL, 'M' }, 76 { "metadata", required_argument, NULL, 'm' }, 77 { "no-registration", no_argument, NULL, 'N' }, 78 { "plist", required_argument, NULL, 'f' }, 79 { "relocate", required_argument, NULL, 1 }, 80 { "root", required_argument, NULL, 'i' }, 81 { "test", no_argument, NULL, 't' }, 82 { NULL, 0, NULL, 0}, 83 }; 84 85 if (pkg_new(&pkg, PKG_INSTALLED) != EPKG_OK) 86 err(EXIT_FAILURE, "malloc"); 87 88 while ((ch = getopt_long(argc, argv, "+Adf:i:M:m:Nt", longopts, NULL)) != -1) { 89 switch (ch) { 90 case 'A': 91 case 'd': 92 pkg_set(pkg, PKG_ATTR_AUTOMATIC, (bool)true); 93 break; 94 case 'f': 95 plist = optarg; 96 break; 97 case 'i': 98 input_path = optarg; 99 break; 100 case 'M': 101 mfile = optarg; 102 break; 103 case 'm': 104 mdir = optarg; 105 break; 106 case 'N': 107 reg_in_db = false; 108 break; 109 case 't': 110 testing_mode = true; 111 break; 112 case 1: 113 location = optarg; 114 break; 115 default: 116 warnx("Unrecognised option -%c", ch); 117 usage_register(); 118 pkg_free(pkg); 119 return (EXIT_FAILURE); 120 } 121 } 122 123 retcode = pkgdb_access(PKGDB_MODE_READ | 124 PKGDB_MODE_WRITE | 125 PKGDB_MODE_CREATE, 126 PKGDB_DB_LOCAL); 127 if (retcode == EPKG_ENOACCESS) { 128 warnx("Insufficient privileges to register packages"); 129 pkg_free(pkg); 130 return (EXIT_FAILURE); 131 } else if (retcode != EPKG_OK) { 132 pkg_free(pkg); 133 return (EXIT_FAILURE); 134 } 135 136 /* 137 * Ideally, the +MANIFEST should be all that is necessary, 138 * since it can contain all of the meta-data supplied by the 139 * other files mentioned below. These are here for backwards 140 * compatibility with the way the ports tree works with 141 * pkg_tools. 142 * 143 * The -M option specifies one manifest file to read the 144 * meta-data from, and overrides the use of legacy meta-data 145 * inputs. 146 * 147 * Dependencies, shlibs, files etc. may be derived by 148 * analysing the package files (maybe discovered as the 149 * content of the staging directory) unless -t (testing_mode) 150 * is used. 151 */ 152 153 if (mfile != NULL && mdir != NULL) { 154 warnx("Cannot use both -m and -M together"); 155 usage_register(); 156 pkg_free(pkg); 157 return (EXIT_FAILURE); 158 } 159 160 161 if (mfile == NULL && mdir == NULL) { 162 warnx("One of either -m or -M flags is required"); 163 usage_register(); 164 pkg_free(pkg); 165 return (EXIT_FAILURE); 166 } 167 168 if (testing_mode && input_path != NULL) { 169 warnx("-i incompatible with -t option"); 170 usage_register(); 171 pkg_free(pkg); 172 return (EXIT_FAILURE); 173 } 174 175 ret = pkg_load_metadata(pkg, mfile, mdir, plist, input_path, testing_mode); 176 if (ret != EPKG_OK) { 177 pkg_free(pkg); 178 return (EXIT_FAILURE); 179 } 180 181 182 if (reg_in_db && pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) { 183 pkg_free(pkg); 184 return (EXIT_FAILURE); 185 } 186 187 if (db != NULL && pkgdb_obtain_lock(db, PKGDB_LOCK_EXCLUSIVE) != EPKG_OK) { 188 pkgdb_close(db); 189 pkg_free(pkg); 190 warnx("Cannot get an exclusive lock on a database, it is locked by another process"); 191 return (EXIT_FAILURE); 192 } 193 194 retcode = pkg_add_port(db, pkg, input_path, location, testing_mode); 195 196 if (retcode == EPKG_OK && messages != NULL) { 197 fflush(messages->fp); 198 printf("%s\n", messages->buf); 199 } 200 201 pkg_free(pkg); 202 if (db != NULL) { 203 pkgdb_release_lock(db, PKGDB_LOCK_EXCLUSIVE); 204 pkgdb_close(db); 205 } 206 207 return (retcode != EPKG_OK ? EXIT_FAILURE : EXIT_SUCCESS); 208 }