Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/src/shlib.c
2645 views
1
/*-
2
* Copyright (c) 2012-2014 Matthew Seaman <[email protected]>
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer
10
* in this position and unchanged.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
*/
26
27
#include <sys/param.h>
28
29
#include <err.h>
30
#include <getopt.h>
31
#include <stdio.h>
32
#include <pkg.h>
33
#include <libgen.h>
34
#include <stdlib.h>
35
#include <string.h>
36
#include <unistd.h>
37
#include <ctype.h>
38
39
#include "pkgcli.h"
40
41
void
42
usage_shlib(void)
43
{
44
fprintf(stderr, "Usage: pkg shlib [-q] [-P|R] <library>\n\n");
45
fprintf(stderr, "For more information see 'pkg help shlib'.\n");
46
}
47
48
char *
49
sanitize(char *buf, const char *src, size_t size)
50
{
51
const char *sep;
52
char *dst = buf;
53
54
/* skip path */
55
if ((sep = strrchr(src, '/')) != NULL)
56
src = sep + 1;
57
/* copy src to dst */
58
while (size > 1) {
59
if (isspace((unsigned char)*src)) {
60
/* whitespace is not allowed */
61
return (NULL);
62
}
63
*dst++ = *src++;
64
if (*src == '\0')
65
break;
66
size--;
67
}
68
if (*src != '\0') {
69
/* src is longer than buf */
70
return (NULL);
71
}
72
*dst = '\0';
73
74
return (buf);
75
}
76
77
static int
78
pkgs_providing_lib(struct pkgdb *db, const char *libname)
79
{
80
struct pkgdb_it *it = NULL;
81
struct pkg *pkg = NULL;
82
int ret = EPKG_OK;
83
int count = 0;
84
85
if ((it = pkgdb_query_shlib_provide(db, libname)) == NULL) {
86
return (EPKG_FATAL);
87
}
88
89
while ((ret = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC)) == EPKG_OK) {
90
if (count == 0 && !quiet)
91
printf("%s is provided by the following packages:\n",
92
libname);
93
count++;
94
pkg_printf("%n-%v\n", pkg, pkg);
95
}
96
97
if (ret == EPKG_END) {
98
if (count == 0 && !quiet)
99
printf("No packages provide %s.\n", libname);
100
ret = EPKG_OK;
101
}
102
103
pkg_free(pkg);
104
pkgdb_it_free(it);
105
106
return (ret);
107
}
108
109
static int
110
pkgs_requiring_lib(struct pkgdb *db, const char *libname)
111
{
112
struct pkgdb_it *it = NULL;
113
struct pkg *pkg = NULL;
114
int ret = EPKG_OK;
115
int count = 0;
116
117
if ((it = pkgdb_query_shlib_require(db, libname)) == NULL) {
118
return (EPKG_FATAL);
119
}
120
121
while ((ret = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC)) == EPKG_OK) {
122
if (count == 0 && !quiet)
123
printf("%s is linked to by the following packages:\n",
124
libname);
125
count++;
126
pkg_printf("%n-%v\n", pkg, pkg);
127
}
128
129
if (ret == EPKG_END) {
130
if (count == 0 && !quiet)
131
printf("No packages require %s.\n", libname);
132
ret = EPKG_OK;
133
}
134
135
pkg_free(pkg);
136
pkgdb_it_free(it);
137
138
return (ret);
139
}
140
141
int
142
exec_shlib(int argc, char **argv)
143
{
144
struct pkgdb *db = NULL;
145
char libname[MAXPATHLEN];
146
int retcode = EPKG_OK;
147
int ch;
148
bool provides_only = false;
149
bool requires_only = false;
150
151
struct option longopts[] = {
152
{ "provides", no_argument, NULL, 'P' },
153
{ "requires", no_argument, NULL, 'R' },
154
{ "quiet" , no_argument, NULL, 'q' },
155
{ NULL, 0, NULL, 0 },
156
};
157
158
while ((ch = getopt_long(argc, argv, "+qPR", longopts, NULL)) != -1) {
159
switch (ch) {
160
case 'P':
161
provides_only = true;
162
break;
163
case 'R':
164
requires_only = true;
165
break;
166
case 'q':
167
quiet = true;
168
break;
169
default:
170
usage_shlib();
171
return (EXIT_FAILURE);
172
}
173
}
174
argc -= optind;
175
argv += optind;
176
177
if (argc < 1 || (provides_only && requires_only)) {
178
usage_shlib();
179
return (EXIT_FAILURE);
180
}
181
182
if (argc >= 2) {
183
warnx("multiple libraries per run not allowed");
184
return (EXIT_FAILURE);
185
}
186
187
if (sanitize(libname, argv[0], sizeof(libname)) == NULL) {
188
usage_shlib();
189
return (EXIT_FAILURE);
190
}
191
192
retcode = pkgdb_open(&db, PKGDB_DEFAULT);
193
if (retcode != EPKG_OK)
194
return (EXIT_FAILURE);
195
196
if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
197
pkgdb_close(db);
198
warnx("Cannot get a read lock on a database, it is locked by another process");
199
return (EXIT_FAILURE);
200
}
201
202
if (retcode == EPKG_OK && !requires_only)
203
retcode = pkgs_providing_lib(db, libname);
204
205
if (retcode == EPKG_OK && !provides_only)
206
retcode = pkgs_requiring_lib(db, libname);
207
208
if (retcode != EPKG_OK)
209
retcode = (EXIT_FAILURE);
210
211
pkgdb_release_lock(db, PKGDB_LOCK_READONLY);
212
pkgdb_close(db);
213
return (retcode);
214
}
215
216