Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/elftoolchain/ar/ar.c
39482 views
1
/*-
2
* Copyright (c) 2007 Kai Wang
3
* Copyright (c) 2007 Tim Kientzle
4
* Copyright (c) 2007 Joseph Koshy
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer
12
* in this position and unchanged.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
18
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
21
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
*/
28
29
/*-
30
* Copyright (c) 1990, 1993, 1994
31
* The Regents of the University of California. All rights reserved.
32
*
33
* This code is derived from software contributed to Berkeley by
34
* Hugh Smith at The University of Guelph.
35
*
36
* Redistribution and use in source and binary forms, with or without
37
* modification, are permitted provided that the following conditions
38
* are met:
39
* 1. Redistributions of source code must retain the above copyright
40
* notice, this list of conditions and the following disclaimer.
41
* 2. Redistributions in binary form must reproduce the above copyright
42
* notice, this list of conditions and the following disclaimer in the
43
* documentation and/or other materials provided with the distribution.
44
* 3. Neither the name of the University nor the names of its contributors
45
* may be used to endorse or promote products derived from this software
46
* without specific prior written permission.
47
*
48
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58
* SUCH DAMAGE.
59
*/
60
61
#include <sys/queue.h>
62
#include <sys/types.h>
63
#include <archive.h>
64
#include <errno.h>
65
#include <getopt.h>
66
#include <libelftc.h>
67
#include <libgen.h>
68
#include <stdio.h>
69
#include <stdlib.h>
70
#include <stdint.h>
71
#include <string.h>
72
73
#include "ar.h"
74
75
ELFTC_VCSID("$Id: ar.c 3629 2018-09-30 19:26:28Z jkoshy $");
76
77
enum options
78
{
79
OPTION_HELP
80
};
81
82
static struct option longopts[] =
83
{
84
{"flavor", required_argument, NULL, 'F'},
85
{"help", no_argument, NULL, OPTION_HELP},
86
{"version", no_argument, NULL, 'V'},
87
{NULL, 0, NULL, 0}
88
};
89
90
static void bsdar_usage(void);
91
static void ranlib_usage(void);
92
static void set_mode(struct bsdar *bsdar, char opt);
93
static void only_mode(struct bsdar *bsdar, const char *opt,
94
const char *valid_modes);
95
static void bsdar_version(void);
96
97
int
98
main(int argc, char **argv)
99
{
100
struct bsdar *bsdar, bsdar_storage;
101
char *arcmd, *argv1_saved;
102
size_t len;
103
int exitcode, i, opt;
104
105
bsdar = &bsdar_storage;
106
memset(bsdar, 0, sizeof(*bsdar));
107
108
exitcode = EXIT_SUCCESS;
109
arcmd = argv1_saved = NULL;
110
bsdar->output = stdout;
111
112
if ((bsdar->progname = ELFTC_GETPROGNAME()) == NULL)
113
bsdar->progname = "ar";
114
115
if (elf_version(EV_CURRENT) == EV_NONE)
116
bsdar_errc(bsdar, 0, "ELF library initialization failed: %s",
117
elf_errmsg(-1));
118
119
/*
120
* Act like ranlib if our name ends in "ranlib"; this
121
* accommodates names like "arm-freebsd7.1-ranlib",
122
* "bsdranlib", etc.
123
*/
124
len = strlen(bsdar->progname);
125
if (len >= strlen("ranlib") &&
126
strcmp(bsdar->progname + len - strlen("ranlib"), "ranlib") == 0) {
127
while ((opt = getopt_long(argc, argv, "tDUV", longopts,
128
NULL)) != -1) {
129
switch(opt) {
130
case 't':
131
/* Ignored. */
132
break;
133
case 'D':
134
bsdar->options |= AR_D;
135
break;
136
case 'U':
137
bsdar->options &= ~AR_D;
138
break;
139
case 'V':
140
bsdar_version();
141
break;
142
case OPTION_HELP:
143
ranlib_usage();
144
default:
145
ranlib_usage();
146
}
147
}
148
argv += optind;
149
argc -= optind;
150
151
if (*argv == NULL)
152
ranlib_usage();
153
154
bsdar->options |= AR_S;
155
while ((bsdar->filename = *argv++) != NULL)
156
exitcode |= ar_write_archive(bsdar, 's');
157
158
exit(exitcode);
159
} else {
160
if (argc < 2)
161
bsdar_usage();
162
163
/*
164
* Tack on a leading '-', for old-style usage.
165
*/
166
if (*argv[1] != '-') {
167
argv1_saved = argv[1];
168
len = strlen(argv[1]) + 2;
169
if ((arcmd = malloc(len)) == NULL)
170
bsdar_errc(bsdar, errno, "malloc failed");
171
(void) snprintf(arcmd, len, "-%s", argv[1]);
172
argv[1] = arcmd;
173
}
174
}
175
176
while ((opt = getopt_long(argc, argv, "abCcdDfF:ijlMmopqrSsTtUuVvxz",
177
longopts, NULL)) != -1) {
178
switch(opt) {
179
case 'a':
180
bsdar->options |= AR_A;
181
break;
182
case 'b':
183
case 'i':
184
bsdar->options |= AR_B;
185
break;
186
case 'C':
187
bsdar->options |= AR_CC;
188
break;
189
case 'c':
190
bsdar->options |= AR_C;
191
break;
192
case 'd':
193
set_mode(bsdar, opt);
194
break;
195
case 'D':
196
bsdar->options |= AR_D;
197
break;
198
case 'F':
199
if (!strcasecmp(optarg, "svr4") ||
200
!strcasecmp(optarg, "gnu"))
201
bsdar->options &= ~AR_BSD;
202
else if (!strcasecmp(optarg, "bsd"))
203
bsdar->options |= AR_BSD;
204
else
205
bsdar_usage();
206
break;
207
case 'f':
208
case 'T':
209
bsdar->options |= AR_TR;
210
break;
211
case 'j':
212
/* ignored */
213
break;
214
case 'l':
215
/* ignored, for GNU ar comptibility */
216
break;
217
case 'M':
218
set_mode(bsdar, opt);
219
break;
220
case 'm':
221
set_mode(bsdar, opt);
222
break;
223
case 'o':
224
bsdar->options |= AR_O;
225
break;
226
case 'p':
227
set_mode(bsdar, opt);
228
break;
229
case 'q':
230
set_mode(bsdar, opt);
231
break;
232
case 'r':
233
set_mode(bsdar, opt);
234
break;
235
case 'S':
236
bsdar->options |= AR_SS;
237
break;
238
case 's':
239
bsdar->options |= AR_S;
240
break;
241
case 't':
242
set_mode(bsdar, opt);
243
break;
244
case 'U':
245
bsdar->options &= ~AR_D;
246
break;
247
case 'u':
248
bsdar->options |= AR_U;
249
break;
250
case 'V':
251
bsdar_version();
252
break;
253
case 'v':
254
bsdar->options |= AR_V;
255
break;
256
case 'x':
257
set_mode(bsdar, opt);
258
break;
259
case 'z':
260
/* ignored */
261
break;
262
case OPTION_HELP:
263
bsdar_usage();
264
default:
265
bsdar_usage();
266
}
267
}
268
269
/* Restore argv[1] if we had modified it. */
270
if (arcmd != NULL) {
271
argv[1] = argv1_saved;
272
free(arcmd);
273
arcmd = argv1_saved = NULL;
274
}
275
276
argv += optind;
277
argc -= optind;
278
279
if (*argv == NULL && bsdar->mode != 'M')
280
bsdar_usage();
281
282
if (bsdar->options & AR_A && bsdar->options & AR_B)
283
bsdar_errc(bsdar, 0,
284
"only one of -a and -[bi] options allowed");
285
286
if (bsdar->options & AR_J && bsdar->options & AR_Z)
287
bsdar_errc(bsdar, 0,
288
"only one of -j and -z options allowed");
289
290
if (bsdar->options & AR_S && bsdar->options & AR_SS)
291
bsdar_errc(bsdar, 0,
292
"only one of -s and -S options allowed");
293
294
if (bsdar->options & (AR_A | AR_B)) {
295
if (*argv == NULL)
296
bsdar_errc(bsdar, 0,
297
"no position operand specified");
298
if ((bsdar->posarg = basename(*argv)) == NULL)
299
bsdar_errc(bsdar, errno,
300
"basename failed");
301
argc--;
302
argv++;
303
}
304
305
if (bsdar->options & AR_A)
306
only_mode(bsdar, "-a", "mqr");
307
if (bsdar->options & AR_B)
308
only_mode(bsdar, "-b", "mqr");
309
if (bsdar->options & AR_C)
310
only_mode(bsdar, "-c", "qr");
311
if (bsdar->options & AR_CC)
312
only_mode(bsdar, "-C", "x");
313
if (bsdar->options & AR_D)
314
only_mode(bsdar, "-D", "qr");
315
if (bsdar->options & AR_O)
316
only_mode(bsdar, "-o", "x");
317
if (bsdar->options & AR_SS)
318
only_mode(bsdar, "-S", "mqr");
319
if (bsdar->options & AR_U)
320
only_mode(bsdar, "-u", "qrx");
321
322
if (bsdar->mode == 'M') {
323
ar_mode_script(bsdar);
324
exit(EXIT_SUCCESS);
325
}
326
327
if ((bsdar->filename = *argv) == NULL)
328
bsdar_usage();
329
330
bsdar->argc = --argc;
331
bsdar->argv = ++argv;
332
333
if ((!bsdar->mode || strchr("ptx", bsdar->mode)) &&
334
bsdar->options & AR_S) {
335
exitcode = ar_write_archive(bsdar, 's');
336
if (!bsdar->mode)
337
exit(exitcode);
338
}
339
340
switch(bsdar->mode) {
341
case 'd': case 'm': case 'q': case 'r':
342
exitcode = ar_write_archive(bsdar, bsdar->mode);
343
break;
344
345
case 'p': case 't': case 'x':
346
exitcode = ar_read_archive(bsdar, bsdar->mode);
347
break;
348
default:
349
bsdar_usage();
350
/* NOTREACHED */
351
}
352
353
for (i = 0; i < bsdar->argc; i++) {
354
if (bsdar->argv[i] != NULL) {
355
bsdar_warnc(bsdar, 0, "%s: not found in archive",
356
bsdar->argv[i]);
357
exitcode = EXIT_FAILURE;
358
}
359
}
360
361
exit(exitcode);
362
}
363
364
static void
365
set_mode(struct bsdar *bsdar, char opt)
366
{
367
368
if (bsdar->mode != '\0' && bsdar->mode != opt)
369
bsdar_errc(bsdar, 0, "Can't specify both -%c and -%c",
370
opt, bsdar->mode);
371
bsdar->mode = opt;
372
}
373
374
static void
375
only_mode(struct bsdar *bsdar, const char *opt, const char *valid_modes)
376
{
377
378
if (strchr(valid_modes, bsdar->mode) == NULL)
379
bsdar_errc(bsdar, 0, "Option %s is not permitted in mode -%c",
380
opt, bsdar->mode);
381
}
382
383
#define AR_USAGE_MESSAGE "\
384
Usage: %s <command> [options] archive file...\n\
385
Manage archives.\n\n\
386
Where <command> is one of:\n\
387
-d Delete members from the archive.\n\
388
-m Move archive members within the archive.\n\
389
-p Write the contents of members to standard output.\n\
390
-q Append files to an archive.\n\
391
-r Replace (add) files to an archive.\n\
392
-s Add an archive symbol to an archive.\n\
393
-t List files in an archive.\n\
394
-x Extract members from an archive.\n\
395
-M Execute MRI librarian commands.\n\
396
-V Print a version identifier and exit.\n\n\
397
Options:\n\
398
-a MEMBER Add members after the specified member.\n\
399
-b MEMBER | -i MEMBER\n\
400
Add members before the specified member.\n\
401
-c Do not print a message when creating a new archive.\n\
402
-f | -T Only use the first fifteen characters of the member name.\n\
403
-j (This option is accepted, but is ignored).\n\
404
-l (This option is accepted, but is ignored).\n\
405
-o Preserve modification times when extracting members.\n\
406
-u Conditionally update or extract members.\n\
407
-v Be verbose.\n\
408
-z (This option is accepted, but is ignored).\n\
409
-C Do not overwrite existing files in the file system.\n\
410
-D Use fixed metadata, for consistent archive checksums.\n\
411
-F FORMAT | --flavor=FORMAT\n\
412
Create archives with the specified format.\n\
413
-S Do not generate an archive symbol table.\n\
414
-U Use original metadata for archive members.\n"
415
416
static void
417
bsdar_usage(void)
418
{
419
(void) fprintf(stderr, AR_USAGE_MESSAGE, ELFTC_GETPROGNAME());
420
exit(EXIT_FAILURE);
421
}
422
423
#define RANLIB_USAGE_MESSAGE "\
424
Usage: %s [options] archive...\n\
425
Update or create archive symbol tables.\n\n\
426
Options:\n\
427
-t (This option is accepted, but ignored).\n\
428
-D Use fixed metadata, for consistent archive checksums.\n\
429
-U Use original metadata, for unique archive checksums.\n\
430
-V Print a version identifier and exit.\n"
431
432
static void
433
ranlib_usage(void)
434
{
435
(void)fprintf(stderr, RANLIB_USAGE_MESSAGE, ELFTC_GETPROGNAME());
436
exit(EXIT_FAILURE);
437
}
438
439
static void
440
bsdar_version(void)
441
{
442
(void)printf("%s (%s, %s)\n", ELFTC_GETPROGNAME(), archive_version_string(),
443
elftc_version());
444
exit(EXIT_SUCCESS);
445
}
446
447