Line data Source code
1 : /*-
2 : * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
3 : * Copyright (c) 2013-2014 Matthew Seaman <matthew@FreeBSD.org>
4 : * Copyright (c) 2012-2013 Bryan Drewery <bdrewery@FreeBSD.org>
5 : * Copyright (c) 2014 Vsevolod Stakhov <vsevolod@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/types.h>
31 :
32 : #include <err.h>
33 : #include <getopt.h>
34 : #include <libgen.h>
35 : #include <stdbool.h>
36 : #include <stdio.h>
37 : #include <string.h>
38 : #include <sysexits.h>
39 : #include <unistd.h>
40 :
41 : #include <pkg.h>
42 :
43 : #include "pkgcli.h"
44 :
45 : void
46 0 : usage_fetch(void)
47 : {
48 0 : fprintf(stderr, "Usage: pkg fetch [-r reponame] [-o destdir] [-dqUy] "
49 : "[-Cgix] <pkg-name> <...>\n");
50 0 : fprintf(stderr, " pkg fetch [-r reponame] [-dqUy] -a\n");
51 0 : fprintf(stderr, " pkg fetch [-r reponame] [-dqUy] -u\n\n");
52 0 : fprintf(stderr, "For more information see 'pkg help fetch'.\n");
53 0 : }
54 :
55 : int
56 0 : exec_fetch(int argc, char **argv)
57 : {
58 0 : struct pkgdb *db = NULL;
59 0 : struct pkg_jobs *jobs = NULL;
60 0 : const char *reponame = NULL;
61 0 : const char *destdir = NULL;
62 : int ch;
63 0 : int retcode = EX_SOFTWARE;
64 0 : bool upgrades_for_installed = false, rc, csum_only = false;
65 : unsigned mode;
66 0 : match_t match = MATCH_EXACT;
67 0 : pkg_flags f = PKG_FLAG_NONE;
68 :
69 0 : struct option longopts[] = {
70 : { "all", no_argument, NULL, 'a' },
71 : { "case-sensitive", no_argument, NULL, 'C' },
72 : { "dependencies", no_argument, NULL, 'd' },
73 : { "glob", no_argument, NULL, 'g' },
74 : { "case-insensitive", no_argument, NULL, 'i' },
75 : { "quiet", no_argument, NULL, 'q' },
76 : { "repository", required_argument, NULL, 'r' },
77 : { "available-updates", no_argument, NULL, 'u' },
78 : { "no-repo-update", no_argument, NULL, 'U' },
79 : { "regex", no_argument, NULL, 'x' },
80 : { "yes", no_argument, NULL, 'y' },
81 : { "output", required_argument, NULL, 'o' },
82 : { NULL, 0, NULL, 0 },
83 : };
84 :
85 0 : while ((ch = getopt_long(argc, argv, "+aCdgiqr:Uuxyo:", longopts, NULL)) != -1) {
86 0 : switch (ch) {
87 : case 'a':
88 0 : match = MATCH_ALL;
89 0 : break;
90 : case 'C':
91 0 : pkgdb_set_case_sensitivity(true);
92 0 : break;
93 : case 'd':
94 0 : f |= PKG_FLAG_WITH_DEPS | PKG_FLAG_RECURSIVE;
95 0 : break;
96 : case 'g':
97 0 : match = MATCH_GLOB;
98 0 : break;
99 : case 'i':
100 0 : pkgdb_set_case_sensitivity(false);
101 0 : break;
102 : case 'q':
103 0 : quiet = true;
104 0 : break;
105 : case 'r':
106 0 : reponame = optarg;
107 0 : break;
108 : case 'u':
109 0 : f |= PKG_FLAG_UPGRADES_FOR_INSTALLED;
110 0 : upgrades_for_installed = true;
111 0 : break;
112 : case 'U':
113 0 : auto_update = false;
114 0 : break;
115 : case 'x':
116 0 : match = MATCH_REGEX;
117 0 : break;
118 : case 'y':
119 0 : yes = true;
120 0 : break;
121 : case 'o':
122 0 : f |= PKG_FLAG_FETCH_MIRROR;
123 0 : destdir = optarg;
124 0 : break;
125 : default:
126 0 : usage_fetch();
127 0 : return (EX_USAGE);
128 : }
129 : }
130 0 : argc -= optind;
131 0 : argv += optind;
132 :
133 0 : if (argc < 1 && match != MATCH_ALL && !upgrades_for_installed) {
134 0 : usage_fetch();
135 0 : return (EX_USAGE);
136 : }
137 :
138 0 : if (match == MATCH_ALL && upgrades_for_installed) {
139 0 : usage_fetch();
140 0 : return (EX_USAGE);
141 : }
142 :
143 0 : if (auto_update)
144 0 : mode = PKGDB_MODE_READ|PKGDB_MODE_WRITE|PKGDB_MODE_CREATE;
145 : else
146 0 : mode = PKGDB_MODE_READ;
147 :
148 0 : retcode = pkgdb_access(mode, PKGDB_DB_REPO);
149 :
150 0 : if (retcode == EPKG_ENOACCESS) {
151 0 : warnx("Insufficient privileges to access repo catalogue");
152 0 : return (EX_NOPERM);
153 0 : } else if (retcode != EPKG_OK)
154 0 : return (EX_IOERR);
155 :
156 0 : if (upgrades_for_installed) {
157 0 : retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL);
158 :
159 0 : if (retcode == EPKG_ENOACCESS) {
160 0 : warnx("Insufficient privileges to access the package database");
161 0 : return (EX_NOPERM);
162 0 : } else if (retcode != EPKG_OK)
163 0 : return (EX_IOERR);
164 : }
165 :
166 : /* first update the remote repositories if needed */
167 0 : if (auto_update &&
168 : (retcode = pkgcli_update(false, false, reponame)) != EPKG_OK)
169 0 : return (retcode);
170 :
171 0 : if (pkgdb_open_all(&db, PKGDB_REMOTE, reponame) != EPKG_OK)
172 0 : return (EX_IOERR);
173 :
174 0 : if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
175 0 : pkgdb_close(db);
176 0 : warnx("Cannot get a read lock on a database, it is locked by another process");
177 0 : return (EX_TEMPFAIL);
178 : }
179 :
180 :
181 0 : if (pkg_jobs_new(&jobs, PKG_JOBS_FETCH, db) != EPKG_OK)
182 0 : goto cleanup;
183 :
184 0 : if (reponame != NULL && pkg_jobs_set_repository(jobs, reponame) != EPKG_OK)
185 0 : goto cleanup;
186 :
187 0 : if (destdir != NULL && pkg_jobs_set_destdir(jobs, destdir) != EPKG_OK)
188 0 : goto cleanup;
189 :
190 0 : pkg_jobs_set_flags(jobs, f);
191 :
192 0 : if (!upgrades_for_installed &&
193 0 : pkg_jobs_add(jobs, match, argv, argc) != EPKG_OK)
194 0 : goto cleanup;
195 :
196 0 : if (pkg_jobs_solve(jobs) != EPKG_OK)
197 0 : goto cleanup;
198 :
199 0 : if (pkg_jobs_count(jobs) == 0)
200 0 : goto cleanup;
201 :
202 0 : if (!quiet) {
203 0 : rc = print_jobs_summary(jobs, "The following packages will be fetched:\n\n");
204 :
205 0 : if (rc != 0)
206 0 : rc = query_yesno(false, "\nProceed with fetching "
207 : "packages? ");
208 : else {
209 0 : printf("No packages are required to be fetched.\n");
210 0 : rc = query_yesno(false, "Check the integrity of packages "
211 : "downloaded? ");
212 0 : csum_only = true;
213 : }
214 : }
215 : else {
216 0 : rc = true;
217 : }
218 :
219 0 : if (!rc || (retcode = pkg_jobs_apply(jobs)) != EPKG_OK)
220 : goto cleanup;
221 :
222 0 : if (csum_only && !quiet)
223 0 : printf("Integrity check was successful.\n");
224 :
225 0 : retcode = EX_OK;
226 :
227 : cleanup:
228 0 : pkg_jobs_free(jobs);
229 0 : pkgdb_release_lock(db, PKGDB_LOCK_READONLY);
230 0 : pkgdb_close(db);
231 :
232 0 : return (retcode);
233 : }
|