Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/src/shlib.c
2065 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
size--;
65
}
66
if (*src != '\0') {
67
/* src is longer than buf */
68
return (NULL);
69
}
70
*dst = '\0';
71
72
return (buf);
73
}
74
75
static int
76
pkgs_providing_lib(struct pkgdb *db, const char *libname)
77
{
78
struct pkgdb_it *it = NULL;
79
struct pkg *pkg = NULL;
80
int ret = EPKG_OK;
81
int count = 0;
82
83
if ((it = pkgdb_query_shlib_provide(db, libname)) == NULL) {
84
return (EPKG_FATAL);
85
}
86
87
while ((ret = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC)) == EPKG_OK) {
88
if (count == 0 && !quiet)
89
printf("%s is provided by the following packages:\n",
90
libname);
91
count++;
92
pkg_printf("%n-%v\n", pkg, pkg);
93
}
94
95
if (ret == EPKG_END) {
96
if (count == 0 && !quiet)
97
printf("No packages provide %s.\n", libname);
98
ret = EPKG_OK;
99
}
100
101
pkg_free(pkg);
102
pkgdb_it_free(it);
103
104
return (ret);
105
}
106
107
static int
108
pkgs_requiring_lib(struct pkgdb *db, const char *libname)
109
{
110
struct pkgdb_it *it = NULL;
111
struct pkg *pkg = NULL;
112
int ret = EPKG_OK;
113
int count = 0;
114
115
if ((it = pkgdb_query_shlib_require(db, libname)) == NULL) {
116
return (EPKG_FATAL);
117
}
118
119
while ((ret = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC)) == EPKG_OK) {
120
if (count == 0 && !quiet)
121
printf("%s is linked to by the following packages:\n",
122
libname);
123
count++;
124
pkg_printf("%n-%v\n", pkg, pkg);
125
}
126
127
if (ret == EPKG_END) {
128
if (count == 0 && !quiet)
129
printf("No packages require %s.\n", libname);
130
ret = EPKG_OK;
131
}
132
133
pkg_free(pkg);
134
pkgdb_it_free(it);
135
136
return (ret);
137
}
138
139
int
140
exec_shlib(int argc, char **argv)
141
{
142
struct pkgdb *db = NULL;
143
char libname[MAXPATHLEN];
144
int retcode = EPKG_OK;
145
int ch;
146
bool provides_only = false;
147
bool requires_only = false;
148
149
struct option longopts[] = {
150
{ "provides", no_argument, NULL, 'P' },
151
{ "requires", no_argument, NULL, 'R' },
152
{ "quiet" , no_argument, NULL, 'q' },
153
{ NULL, 0, NULL, 0 },
154
};
155
156
while ((ch = getopt_long(argc, argv, "+qPR", longopts, NULL)) != -1) {
157
switch (ch) {
158
case 'P':
159
provides_only = true;
160
break;
161
case 'R':
162
requires_only = true;
163
break;
164
case 'q':
165
quiet = true;
166
break;
167
default:
168
usage_shlib();
169
return (EXIT_FAILURE);
170
}
171
}
172
argc -= optind;
173
argv += optind;
174
175
if (argc < 1 || (provides_only && requires_only)) {
176
usage_shlib();
177
return (EXIT_FAILURE);
178
}
179
180
if (argc >= 2) {
181
warnx("multiple libraries per run not allowed");
182
return (EXIT_FAILURE);
183
}
184
185
if (sanitize(libname, argv[0], sizeof(libname)) == NULL) {
186
usage_shlib();
187
return (EXIT_FAILURE);
188
}
189
190
retcode = pkgdb_open(&db, PKGDB_DEFAULT);
191
if (retcode != EPKG_OK)
192
return (EXIT_FAILURE);
193
194
if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
195
pkgdb_close(db);
196
warnx("Cannot get a read lock on a database, it is locked by another process");
197
return (EXIT_FAILURE);
198
}
199
200
if (retcode == EPKG_OK && !requires_only)
201
retcode = pkgs_providing_lib(db, libname);
202
203
if (retcode == EPKG_OK && !provides_only)
204
retcode = pkgs_requiring_lib(db, libname);
205
206
if (retcode != EPKG_OK)
207
retcode = (EXIT_FAILURE);
208
209
pkgdb_release_lock(db, PKGDB_LOCK_READONLY);
210
pkgdb_close(db);
211
return (retcode);
212
}
213
214