Branch data 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 : :
30 : : #include <err.h>
31 : : #include <errno.h>
32 : : #include <libgen.h>
33 : : #include <stdio.h>
34 : : #include <stdlib.h>
35 : : #include <string.h>
36 : : #include <unistd.h>
37 : : #include <getopt.h>
38 : : #include <xstring.h>
39 : :
40 : : #include <pkg.h>
41 : :
42 : : #include "pkgcli.h"
43 : :
44 : : static int
45 : 320 : is_url(const char * const pattern)
46 : : {
47 [ + - + - ]: 640 : if (strncmp(pattern, "http://", 7) == 0 ||
48 [ + - ]: 320 : strncmp(pattern, "https://", 8) == 0 ||
49 [ + - ]: 320 : strncmp(pattern, "ftp://", 6) == 0 ||
50 : 320 : strncmp(pattern, "file://", 7) == 0)
51 : 0 : return (EPKG_OK);
52 : :
53 : 320 : return (EPKG_FATAL);
54 : 320 : }
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 : 160 : exec_add(int argc, char **argv)
66 : : {
67 : 160 : struct pkgdb *db = NULL;
68 : 160 : xstring *failedpkgs = NULL;
69 : : char path[MAXPATHLEN];
70 : : char *file;
71 : : int retcode;
72 : : int ch;
73 : : int i;
74 : 160 : int failedpkgcount = 0;
75 : 160 : pkg_flags f = PKG_FLAG_NONE;
76 : 160 : struct pkg_manifest_key *keys = NULL;
77 : 160 : const char *location = NULL;
78 : :
79 : : /* options descriptor */
80 : 160 : 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 [ + + ]: 225 : while ((ch = getopt_long(argc, argv, "+IAfqM", longopts, NULL)) != -1) {
91 [ + + - + : 65 : switch (ch) {
+ - - ]
92 : : case 'I':
93 : 13 : f |= PKG_ADD_NOSCRIPT;
94 : 13 : break;
95 : : case 'A':
96 : 13 : f |= PKG_ADD_AUTOMATIC;
97 : 13 : break;
98 : : case 'f':
99 : 0 : f |= PKG_ADD_FORCE;
100 : 0 : force = true;
101 : 0 : break;
102 : : case 'M':
103 : 26 : f |= PKG_ADD_FORCE_MISSING;
104 : 26 : break;
105 : : case 'q':
106 : 13 : quiet = true;
107 : 13 : break;
108 : : case 1:
109 : 0 : location = optarg;
110 : 0 : break;
111 : : default:
112 : 0 : usage_add();
113 : 0 : return (EXIT_FAILURE);
114 : : }
115 : : }
116 : 160 : argc -= optind;
117 : 160 : argv += optind;
118 : :
119 [ - + ]: 160 : if (argc < 1) {
120 : 0 : usage_add();
121 : 0 : return (EXIT_FAILURE);
122 : : }
123 : :
124 : 160 : retcode = pkgdb_access(PKGDB_MODE_READ |
125 : : PKGDB_MODE_WRITE |
126 : : PKGDB_MODE_CREATE,
127 : : PKGDB_DB_LOCAL);
128 [ - + ]: 160 : if (retcode == EPKG_ENOACCESS) {
129 : 0 : warnx("Insufficient privileges to add packages");
130 : 0 : return (EXIT_FAILURE);
131 [ - + ]: 160 : } else if (retcode != EPKG_OK)
132 : 0 : return (EXIT_FAILURE);
133 : :
134 [ - + ]: 160 : if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK)
135 : 0 : return (EXIT_FAILURE);
136 : :
137 [ - + ]: 160 : 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 (EXIT_FAILURE);
141 : : }
142 : :
143 : 160 : failedpkgs = xstring_new();
144 : 160 : pkg_manifest_keys_new(&keys);
145 [ + + ]: 320 : for (i = 0; i < argc; i++) {
146 [ + - ]: 160 : if (is_url(argv[i]) == EPKG_OK) {
147 : 0 : const char *name = strrchr(argv[i], '/');
148 [ # # ]: 0 : if (name == NULL)
149 : 0 : name = argv[i];
150 : : else
151 : 0 : name++;
152 : 0 : snprintf(path, sizeof(path), "%s/%s.XXXXX",
153 [ # # ]: 0 : getenv("TMPDIR") != NULL ? getenv("TMPDIR") : "/tmp", name);
154 [ # # ]: 0 : if ((retcode = pkg_fetch_file(NULL, argv[i], path, 0, 0, 0)) != EPKG_OK)
155 : 0 : break;
156 : :
157 : 0 : file = path;
158 : 0 : } else {
159 : 160 : file = argv[i];
160 : :
161 : : /* Special case: treat a filename of "-" as
162 : : meaning 'read from stdin.' It doesn't make
163 : : sense to have a filename of "-" more than
164 : : once per command line, but we aren't
165 : : testing for that at the moment */
166 : :
167 [ + + + - ]: 160 : if (strcmp(file, "-") != 0 && access(file, F_OK) != 0) {
168 : 0 : warn("%s", file);
169 [ # # ]: 0 : if (errno == ENOENT)
170 : 0 : warnx("Was 'pkg install %s' meant?", file);
171 : 0 : fprintf(failedpkgs->fp, "%s", argv[i]);
172 [ # # ]: 0 : if (i != argc - 1)
173 : 0 : fprintf(failedpkgs->fp, ", ");
174 : 0 : failedpkgcount++;
175 : 0 : continue;
176 : : }
177 : :
178 : : }
179 : :
180 [ + + ]: 160 : if ((retcode = pkg_add(db, file, f, keys, location)) != EPKG_OK) {
181 : 39 : fprintf(failedpkgs->fp, "%s", argv[i]);
182 [ + - ]: 39 : if (i != argc - 1)
183 : 0 : fprintf(failedpkgs->fp, ", ");
184 : 39 : failedpkgcount++;
185 : 39 : }
186 : :
187 [ + - ]: 160 : if (is_url(argv[i]) == EPKG_OK)
188 : 0 : unlink(file);
189 : :
190 : 160 : }
191 : 160 : pkg_manifest_keys_free(keys);
192 : 160 : pkgdb_release_lock(db, PKGDB_LOCK_EXCLUSIVE);
193 : 160 : pkgdb_close(db);
194 : :
195 [ + + ]: 160 : if(failedpkgcount > 0) {
196 : 39 : fflush(failedpkgs->fp);
197 : 39 : printf("\nFailed to install the following %d package(s): %s\n", failedpkgcount, failedpkgs->buf);
198 : 39 : retcode = EPKG_FATAL;
199 : 39 : }
200 : 160 : xstring_free(failedpkgs);
201 : :
202 : 160 : pkg_add_triggers();
203 [ + - ]: 160 : if (messages != NULL) {
204 : 0 : fflush(messages->fp);
205 : 0 : printf("%s", messages->buf);
206 : 0 : }
207 : :
208 : 160 : return (retcode == EPKG_OK ? EXIT_SUCCESS : EXIT_FAILURE);
209 : 160 : }
210 : :
|