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 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : * 1. Redistributions of source code must retain the above copyright
10 : * notice, this list of conditions and the following disclaimer
11 : * in this position and unchanged.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : *
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 : * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 :
28 : #include <sys/param.h>
29 : #include <sys/sbuf.h>
30 :
31 : #include <err.h>
32 : #include <errno.h>
33 : #include <libgen.h>
34 : #include <stdio.h>
35 : #include <string.h>
36 : #include <sysexits.h>
37 : #include <unistd.h>
38 : #include <getopt.h>
39 :
40 : #include <pkg.h>
41 :
42 : #include "pkgcli.h"
43 :
44 : static int
45 20 : is_url(const char * const pattern)
46 : {
47 40 : if (strncmp(pattern, "http://", 7) == 0 ||
48 40 : strncmp(pattern, "https://", 8) == 0 ||
49 40 : strncmp(pattern, "ftp://", 6) == 0 ||
50 20 : strncmp(pattern, "file://", 7) == 0)
51 0 : return (EPKG_OK);
52 :
53 20 : return (EPKG_FATAL);
54 : }
55 :
56 : void
57 0 : usage_add(void)
58 : {
59 0 : fprintf(stderr, "Usage: pkg add [-IAfqM] <pkg-name> ...\n");
60 0 : fprintf(stderr, " pkg add [-IAfqM] <protocol>://<path>/<pkg-name> ...\n\n");
61 0 : fprintf(stderr, "For more information see 'pkg help add'.\n");
62 0 : }
63 :
64 : int
65 10 : exec_add(int argc, char **argv)
66 : {
67 10 : struct pkgdb *db = NULL;
68 10 : struct sbuf *failedpkgs = NULL;
69 : char path[MAXPATHLEN];
70 : char *file;
71 : int retcode;
72 : int ch;
73 : int i;
74 10 : int failedpkgcount = 0;
75 10 : pkg_flags f = PKG_FLAG_NONE;
76 10 : struct pkg_manifest_key *keys = NULL;
77 10 : const char *location = NULL;
78 :
79 : /* options descriptor */
80 10 : struct option longopts[] = {
81 : { "no-scripts", no_argument, NULL, 'I' },
82 : { "automatic", no_argument, NULL, 'A' },
83 : { "force", no_argument, NULL, 'f' },
84 : { "accept-missing", no_argument, NULL, 'M' },
85 : { "quiet", no_argument, NULL, 'q' },
86 : { "relocate", required_argument, NULL, 1 },
87 : { NULL, 0, NULL, 0 }
88 : };
89 :
90 25 : while ((ch = getopt_long(argc, argv, "+IAfqM", longopts, NULL)) != -1) {
91 5 : switch (ch) {
92 : case 'I':
93 1 : f |= PKG_ADD_NOSCRIPT;
94 1 : break;
95 : case 'A':
96 1 : f |= PKG_ADD_AUTOMATIC;
97 1 : break;
98 : case 'f':
99 0 : f |= PKG_ADD_FORCE;
100 0 : force = true;
101 0 : break;
102 : case 'M':
103 2 : f |= PKG_ADD_FORCE_MISSING;
104 2 : break;
105 : case 'q':
106 1 : quiet = true;
107 1 : break;
108 : case 1:
109 0 : location = optarg;
110 0 : break;
111 : default:
112 0 : usage_add();
113 0 : return (EX_USAGE);
114 : }
115 : }
116 10 : argc -= optind;
117 10 : argv += optind;
118 :
119 10 : if (argc < 1) {
120 0 : usage_add();
121 0 : return (EX_USAGE);
122 : }
123 :
124 10 : retcode = pkgdb_access(PKGDB_MODE_READ |
125 : PKGDB_MODE_WRITE |
126 : PKGDB_MODE_CREATE,
127 : PKGDB_DB_LOCAL);
128 10 : if (retcode == EPKG_ENOACCESS) {
129 0 : warnx("Insufficient privileges to add packages");
130 0 : return (EX_NOPERM);
131 10 : } else if (retcode != EPKG_OK)
132 0 : return (EX_IOERR);
133 :
134 10 : if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK)
135 0 : return (EX_IOERR);
136 :
137 10 : if (pkgdb_obtain_lock(db, PKGDB_LOCK_EXCLUSIVE) != EPKG_OK) {
138 0 : pkgdb_close(db);
139 0 : warnx("Cannot get an exclusive lock on a database, it is locked by another process");
140 0 : return (EX_TEMPFAIL);
141 : }
142 :
143 10 : failedpkgs = sbuf_new_auto();
144 10 : pkg_manifest_keys_new(&keys);
145 20 : for (i = 0; i < argc; i++) {
146 10 : if (is_url(argv[i]) == EPKG_OK) {
147 0 : snprintf(path, sizeof(path), "%s/%s.XXXXX",
148 0 : getenv("TMPDIR") != NULL ? getenv("TMPDIR") : "/tmp", basename(argv[i]));
149 0 : if ((retcode = pkg_fetch_file(NULL, argv[i], path, 0, 0, 0)) != EPKG_OK)
150 0 : break;
151 :
152 0 : file = path;
153 : } else {
154 10 : file = argv[i];
155 :
156 : /* Special case: treat a filename of "-" as
157 : meaning 'read from stdin.' It doesn't make
158 : sense to have a filename of "-" more than
159 : once per command line, but we aren't
160 : testing for that at the moment */
161 :
162 10 : if (strcmp(file, "-") != 0 && access(file, F_OK) != 0) {
163 0 : warn("%s", file);
164 0 : if (errno == ENOENT)
165 0 : warnx("Was 'pkg install %s' meant?", file);
166 0 : sbuf_cat(failedpkgs, argv[i]);
167 0 : if (i != argc - 1)
168 0 : sbuf_printf(failedpkgs, ", ");
169 0 : failedpkgcount++;
170 0 : continue;
171 : }
172 :
173 : }
174 :
175 10 : if ((retcode = pkg_add(db, file, f, keys, location)) != EPKG_OK) {
176 2 : sbuf_cat(failedpkgs, argv[i]);
177 2 : if (i != argc - 1)
178 0 : sbuf_printf(failedpkgs, ", ");
179 2 : failedpkgcount++;
180 : }
181 :
182 10 : if (is_url(argv[i]) == EPKG_OK)
183 0 : unlink(file);
184 :
185 : }
186 10 : pkg_manifest_keys_free(keys);
187 10 : pkgdb_release_lock(db, PKGDB_LOCK_EXCLUSIVE);
188 10 : pkgdb_close(db);
189 :
190 10 : if(failedpkgcount > 0) {
191 2 : sbuf_finish(failedpkgs);
192 2 : printf("\nFailed to install the following %d package(s): %s\n", failedpkgcount, sbuf_data(failedpkgs));
193 2 : retcode = EPKG_FATAL;
194 : }
195 10 : sbuf_delete(failedpkgs);
196 :
197 10 : if (messages != NULL) {
198 0 : sbuf_finish(messages);
199 0 : printf("%s", sbuf_data(messages));
200 : }
201 :
202 10 : return (retcode == EPKG_OK ? EX_OK : EX_SOFTWARE);
203 : }
204 :
|