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