Line data Source code
1 : /*-
2 : * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
3 : * Copyright (c) 2014 Matthew Seaman <matthew@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 : #ifdef HAVE_CONFIG_H
29 : #include "pkg_config.h"
30 : #endif
31 :
32 : #ifdef HAVE_CAPSICUM
33 : #include <sys/capability.h>
34 : #endif
35 :
36 : #include <sys/queue.h>
37 :
38 : #define _WITH_GETLINE
39 : #include <err.h>
40 : #include <errno.h>
41 : #include <getopt.h>
42 : #include <pkg.h>
43 : #include <stdio.h>
44 : #include <string.h>
45 : #include <sysexits.h>
46 : #include <unistd.h>
47 :
48 : #include "pkgcli.h"
49 :
50 : struct installed_ports {
51 : char *origin;
52 : SLIST_ENTRY(installed_ports) next;
53 : };
54 :
55 : void
56 0 : usage_updating(void)
57 : {
58 0 : fprintf(stderr, "Usage: pkg updating [-i] [-d YYYYMMDD] [-f file] [portname ...]\n");
59 0 : fprintf(stderr, "For more information see 'pkg help updating'.\n");
60 :
61 0 : }
62 :
63 : int
64 0 : exec_updating(int argc, char **argv)
65 : {
66 0 : char *date = NULL;
67 0 : char *dateline = NULL;
68 0 : char *updatingfile = NULL;
69 0 : bool caseinsensitive = false;
70 : struct installed_ports *port;
71 : SLIST_HEAD(,installed_ports) origins;
72 : int ch;
73 0 : char *line = NULL;
74 0 : size_t linecap = 0;
75 : ssize_t linelen;
76 : char *tmp;
77 0 : int head = 0;
78 0 : int found = 0;
79 0 : struct pkgdb *db = NULL;
80 0 : struct pkg *pkg = NULL;
81 0 : struct pkgdb_it *it = NULL;
82 : FILE *fd;
83 0 : int retcode = EXIT_SUCCESS;
84 : #ifdef HAVE_CAPSICUM
85 : cap_rights_t rights;
86 : #endif
87 :
88 0 : struct option longopts[] = {
89 : { "date", required_argument, NULL, 'd' },
90 : { "file", required_argument, NULL, 'f' },
91 : { "case-insensitive", no_argument, NULL, 'i' },
92 : { NULL, 0, NULL, 0 },
93 : };
94 :
95 0 : while ((ch = getopt_long(argc, argv, "+d:f:i", longopts, NULL)) != -1) {
96 0 : switch (ch) {
97 : case 'd':
98 0 : date = optarg;
99 0 : break;
100 : case 'f':
101 0 : updatingfile = optarg;
102 0 : break;
103 : case 'i':
104 0 : caseinsensitive = true;
105 0 : break;
106 : default:
107 0 : usage_updating();
108 0 : return (EX_USAGE);
109 : }
110 : }
111 0 : argc -= optind;
112 0 : argv += optind;
113 :
114 : /* checking date format */
115 0 : if (date != NULL)
116 0 : if (strlen(date) != 8 || strspn(date, "0123456789") != 8)
117 0 : err(EX_DATAERR, "Invalid date format");
118 :
119 0 : if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK)
120 0 : return (EX_IOERR);
121 :
122 0 : if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
123 0 : pkgdb_close(db);
124 0 : warnx("Cannot get a read lock on a database, it is locked by another process");
125 0 : return (EX_TEMPFAIL);
126 : }
127 :
128 0 : if (updatingfile == NULL) {
129 0 : const char *portsdir = pkg_object_string(pkg_config_get("PORTSDIR"));
130 0 : if (portsdir == NULL) {
131 0 : retcode = EX_CONFIG;
132 0 : goto cleanup;
133 : }
134 0 : asprintf(&updatingfile, "%s/UPDATING", portsdir);
135 : }
136 :
137 0 : fd = fopen(updatingfile, "r");
138 0 : if (fd == NULL) {
139 0 : warnx("Unable to open: %s", updatingfile);
140 0 : goto cleanup;
141 : }
142 :
143 : #ifdef HAVE_CAPSICUM
144 0 : cap_rights_init(&rights, CAP_READ);
145 0 : if (cap_rights_limit(fileno(fd), &rights) < 0 && errno != ENOSYS ) {
146 0 : warn("cap_rights_limit() failed");
147 0 : fclose(fd);
148 0 : return (EX_SOFTWARE);
149 : }
150 :
151 0 : if (cap_enter() < 0 && errno != ENOSYS) {
152 0 : warn("cap_enter() failed");
153 0 : fclose(fd);
154 0 : return (EX_SOFTWARE);
155 : }
156 : #endif
157 :
158 0 : SLIST_INIT(&origins);
159 0 : if (argc == 0) {
160 0 : if ((it = pkgdb_query(db, NULL, MATCH_ALL)) == NULL) {
161 0 : retcode = EX_UNAVAILABLE;
162 0 : fclose(fd);
163 0 : goto cleanup;
164 : }
165 :
166 0 : while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC) == EPKG_OK) {
167 0 : port = malloc(sizeof(struct installed_ports));
168 0 : pkg_asprintf(&port->origin, "%o", pkg);
169 0 : SLIST_INSERT_HEAD(&origins, port, next);
170 : }
171 : } else {
172 0 : while (*argv) {
173 0 : port = malloc(sizeof(struct installed_ports));
174 0 : port->origin = strdup(*argv);
175 0 : SLIST_INSERT_HEAD(&origins, port, next);
176 0 : argv++;
177 : }
178 : }
179 :
180 0 : while ((linelen = getline(&line, &linecap, fd)) > 0) {
181 0 : if (strspn(line, "0123456789:") == 9) {
182 0 : dateline = strdup(line);
183 0 : found = 0;
184 0 : head = 1;
185 0 : } else if (head == 0) {
186 0 : continue;
187 : }
188 :
189 0 : tmp = NULL;
190 0 : if (found == 0) {
191 0 : if (strstr(line, "AFFECTS") != NULL) {
192 0 : SLIST_FOREACH(port, &origins, next) {
193 0 : if (caseinsensitive) {
194 0 : if ((tmp = strcasestr(line, port->origin)) != NULL) {
195 0 : break;
196 : }
197 : } else {
198 0 : if ((tmp = strstr(line, port->origin)) != NULL) {
199 0 : break;
200 : }
201 : }
202 : }
203 0 : if (tmp != NULL) {
204 0 : if ((date != NULL) && strncmp(dateline, date, 8) < 0)
205 0 : continue;
206 0 : printf("%s%s",dateline, line);
207 0 : found = 1;
208 : }
209 : }
210 : } else {
211 0 : printf("%s",line);
212 : }
213 : }
214 0 : fclose(fd);
215 :
216 : cleanup:
217 0 : pkgdb_it_free(it);
218 0 : pkgdb_release_lock(db, PKGDB_LOCK_READONLY);
219 0 : pkgdb_close(db);
220 0 : pkg_free(pkg);
221 0 : free(dateline);
222 :
223 0 : return (retcode);
224 : }
|