Line data Source code
1 : /*-
2 : * Copyright (c) 2011-2012 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 : * Copyright (c) 2012-2013 Bryan Drewery <bdrewery@FreeBSD.org>
7 : * All rights reserved.
8 : *
9 : * Redistribution and use in source and binary forms, with or without
10 : * modification, are permitted provided that the following conditions
11 : * are met:
12 : * 1. Redistributions of source code must retain the above copyright
13 : * notice, this list of conditions and the following disclaimer
14 : * in this position and unchanged.
15 : * 2. Redistributions in binary form must reproduce the above copyright
16 : * notice, this list of conditions and the following disclaimer in the
17 : * documentation and/or other materials provided with the distribution.
18 : *
19 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
20 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 : * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
23 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 : */
30 :
31 : #include <sys/types.h>
32 :
33 : #include <err.h>
34 : #include <getopt.h>
35 : #include <libgen.h>
36 : #include <stdbool.h>
37 : #include <stdio.h>
38 : #include <string.h>
39 : #include <sysexits.h>
40 : #include <unistd.h>
41 :
42 : #include <pkg.h>
43 :
44 : #include "pkgcli.h"
45 :
46 : void
47 0 : usage_install(void)
48 : {
49 0 : fprintf(stderr,
50 : "Usage: pkg install [-AfInFMqRUy] [-r reponame] [-Cgix] <pkg-name> ...\n\n");
51 0 : fprintf(stderr, "For more information see 'pkg help install'.\n");
52 0 : }
53 :
54 : int
55 5 : exec_install(int argc, char **argv)
56 : {
57 5 : struct pkgdb *db = NULL;
58 5 : struct pkg_jobs *jobs = NULL;
59 5 : const char *reponame = NULL;
60 : int retcode;
61 5 : int updcode = EPKG_OK;
62 : int ch;
63 : int mode, repo_type;
64 5 : int done = 0;
65 5 : int lock_type = PKGDB_LOCK_ADVISORY;
66 5 : bool rc = true;
67 5 : bool local_only = false;
68 5 : match_t match = MATCH_EXACT;
69 5 : pkg_flags f = PKG_FLAG_NONE | PKG_FLAG_PKG_VERSION_TEST;
70 :
71 5 : struct option longopts[] = {
72 : { "automatic", no_argument, NULL, 'A' },
73 : { "case-sensitive", no_argument, NULL, 'C' },
74 : { "force", no_argument, NULL, 'f' },
75 : { "fetch-only", no_argument, NULL, 'F' },
76 : { "glob", no_argument, NULL, 'g' },
77 : { "case-insensitive", no_argument, NULL, 'i' },
78 : { "no-install-scripts", no_argument, NULL, 'I' },
79 : { "local-only", no_argument, NULL, 'l' },
80 : { "ignore-missing", no_argument, NULL, 'M' },
81 : { "dry-run", no_argument, NULL, 'n' },
82 : { "quiet", no_argument, NULL, 'q' },
83 : { "repository", required_argument, NULL, 'r' },
84 : { "from-root", no_argument, NULL, 'R' },
85 : { "no-repo-update", no_argument, NULL, 'U' },
86 : { "regex", no_argument, NULL, 'x' },
87 : { "yes", no_argument, NULL, 'y' },
88 : { NULL, 0, NULL, 0 },
89 : };
90 :
91 5 : nbactions = nbdone = 0;
92 :
93 5 : if (strcmp(argv[0], "add") == 0) {
94 0 : auto_update = false;
95 0 : local_only = true;
96 0 : yes = true;
97 0 : quiet = true;
98 : }
99 :
100 15 : while ((ch = getopt_long(argc, argv, "+ACfFgiIlMnqr:RUxy", longopts, NULL)) != -1) {
101 5 : switch (ch) {
102 : case 'A':
103 0 : f |= PKG_FLAG_AUTOMATIC;
104 0 : break;
105 : case 'C':
106 0 : pkgdb_set_case_sensitivity(true);
107 0 : break;
108 : case 'f':
109 0 : f |= PKG_FLAG_FORCE;
110 0 : break;
111 : case 'F':
112 0 : f |= PKG_FLAG_SKIP_INSTALL;
113 0 : lock_type = PKGDB_LOCK_READONLY;
114 0 : break;
115 : case 'g':
116 0 : match = MATCH_GLOB;
117 0 : break;
118 : case 'i':
119 0 : pkgdb_set_case_sensitivity(false);
120 0 : break;
121 : case 'I':
122 0 : f |= PKG_FLAG_NOSCRIPT;
123 0 : break;
124 : case 'l':
125 0 : local_only = true;
126 0 : auto_update = false;
127 0 : break;
128 : case 'M':
129 0 : f |= PKG_FLAG_FORCE_MISSING;
130 0 : break;
131 : case 'n':
132 2 : f |= PKG_FLAG_DRY_RUN;
133 2 : lock_type = PKGDB_LOCK_READONLY;
134 2 : dry_run = true;
135 2 : break;
136 : case 'q':
137 0 : quiet = true;
138 0 : break;
139 : case 'r':
140 0 : reponame = optarg;
141 0 : break;
142 : case 'R':
143 0 : f |= PKG_FLAG_RECURSIVE;
144 0 : break;
145 : case 'U':
146 0 : auto_update = false;
147 0 : break;
148 : case 'x':
149 0 : match = MATCH_REGEX;
150 0 : break;
151 : case 'y':
152 3 : yes = true;
153 3 : break;
154 : default:
155 0 : usage_install();
156 0 : return (EX_USAGE);
157 : }
158 : }
159 5 : argc -= optind;
160 5 : argv += optind;
161 :
162 5 : if (argc < 1) {
163 0 : usage_install();
164 0 : return (EX_USAGE);
165 : }
166 :
167 5 : if (dry_run && !auto_update)
168 0 : mode = PKGDB_MODE_READ;
169 : else
170 5 : mode = PKGDB_MODE_READ |
171 : PKGDB_MODE_WRITE |
172 : PKGDB_MODE_CREATE;
173 5 : if (local_only)
174 0 : repo_type = PKGDB_DB_LOCAL;
175 : else
176 5 : repo_type = PKGDB_DB_LOCAL|PKGDB_DB_REPO;
177 :
178 5 : retcode = pkgdb_access(mode, repo_type);
179 :
180 5 : if (retcode == EPKG_ENOACCESS && dry_run) {
181 0 : auto_update = false;
182 0 : retcode = pkgdb_access(PKGDB_MODE_READ,
183 : repo_type);
184 : }
185 :
186 5 : if (retcode == EPKG_ENOACCESS) {
187 0 : warnx("Insufficient privileges to install packages");
188 0 : return (EX_NOPERM);
189 5 : } else if (retcode != EPKG_OK)
190 0 : return (EX_IOERR);
191 : else
192 5 : retcode = EX_SOFTWARE;
193 :
194 : /* first update the remote repositories if needed */
195 5 : if (auto_update &&
196 : (updcode = pkgcli_update(false, false, reponame)) != EPKG_OK)
197 0 : return (updcode);
198 :
199 5 : if (pkgdb_open_all(&db,
200 : local_only ? PKGDB_DEFAULT : PKGDB_MAYBE_REMOTE,
201 : reponame) != EPKG_OK)
202 0 : return (EX_IOERR);
203 :
204 5 : if (pkgdb_obtain_lock(db, lock_type) != EPKG_OK) {
205 0 : pkgdb_close(db);
206 0 : warnx("Cannot get an advisory lock on a database, it is locked by another process");
207 0 : return (EX_TEMPFAIL);
208 : }
209 :
210 5 : if (pkg_jobs_new(&jobs, PKG_JOBS_INSTALL, db) != EPKG_OK)
211 0 : goto cleanup;
212 :
213 5 : if (!local_only && reponame != NULL &&
214 0 : pkg_jobs_set_repository(jobs, reponame) != EPKG_OK)
215 0 : goto cleanup;
216 :
217 5 : pkg_jobs_set_flags(jobs, f);
218 :
219 5 : if (pkg_jobs_add(jobs, match, argv, argc) == EPKG_FATAL)
220 0 : goto cleanup;
221 :
222 5 : if (pkg_jobs_solve(jobs) != EPKG_OK)
223 0 : goto cleanup;
224 :
225 10 : while ((nbactions = pkg_jobs_count(jobs)) > 0) {
226 5 : rc = yes;
227 : /* print a summary before applying the jobs */
228 5 : if (!quiet || dry_run) {
229 5 : print_jobs_summary(jobs,
230 : "The following %d package(s) will be affected (of %d checked):\n\n",
231 : nbactions, pkg_jobs_total(jobs));
232 :
233 5 : if (!dry_run) {
234 3 : rc = query_yesno(false,
235 : "\nProceed with this action? ");
236 : }
237 : else {
238 2 : rc = false;
239 : }
240 : }
241 :
242 5 : if (rc) {
243 3 : retcode = pkg_jobs_apply(jobs);
244 3 : done = 1;
245 3 : if (retcode == EPKG_CONFLICT) {
246 0 : printf("Conflicts with the existing packages "
247 : "have been found.\nOne more solver "
248 : "iteration is needed to resolve them.\n");
249 0 : continue;
250 : }
251 3 : else if (retcode != EPKG_OK)
252 0 : goto cleanup;
253 : }
254 :
255 5 : if (messages != NULL) {
256 0 : sbuf_finish(messages);
257 0 : printf("%s", sbuf_data(messages));
258 : }
259 5 : break;
260 : }
261 :
262 5 : if (done == 0 && rc)
263 0 : printf("The most recent version of packages are already installed\n");
264 :
265 5 : retcode = EX_OK;
266 :
267 : cleanup:
268 5 : pkgdb_release_lock(db, lock_type);
269 5 : pkg_jobs_free(jobs);
270 5 : pkgdb_close(db);
271 :
272 5 : if (!dry_run)
273 3 : pkg_cache_full_clean();
274 :
275 5 : if (!rc && newpkgversion)
276 0 : newpkgversion = false;
277 :
278 5 : return (retcode);
279 : }
|