Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/usr.bin/ar/ar.c
34677 views
1
/*-
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* Copyright (c) 2007 Kai Wang
5
* Copyright (c) 2007 Tim Kientzle
6
* Copyright (c) 2007 Joseph Koshy
7
* All rights reserved.
8
*
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
11
* are met:
12
* 1. Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in the
16
* documentation and/or other materials provided with the distribution.
17
*
18
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
* SUCH DAMAGE.
29
*/
30
31
/*-
32
* Copyright (c) 1990, 1993, 1994
33
* The Regents of the University of California. All rights reserved.
34
*
35
* This code is derived from software contributed to Berkeley by
36
* Hugh Smith at The University of Guelph.
37
*
38
* Redistribution and use in source and binary forms, with or without
39
* modification, are permitted provided that the following conditions
40
* are met:
41
* 1. Redistributions of source code must retain the above copyright
42
* notice, this list of conditions and the following disclaimer.
43
* 2. Redistributions in binary form must reproduce the above copyright
44
* notice, this list of conditions and the following disclaimer in the
45
* documentation and/or other materials provided with the distribution.
46
* 3. Neither the name of the University nor the names of its contributors
47
* may be used to endorse or promote products derived from this software
48
* without specific prior written permission.
49
*
50
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60
* SUCH DAMAGE.
61
*/
62
63
#include <sys/cdefs.h>
64
#include <sys/queue.h>
65
#include <sys/types.h>
66
#include <archive.h>
67
#include <err.h>
68
#include <errno.h>
69
#include <getopt.h>
70
#include <libgen.h>
71
#include <stdio.h>
72
#include <stdlib.h>
73
#include <string.h>
74
75
#include "ar.h"
76
77
enum options
78
{
79
OPTION_HELP
80
};
81
82
static struct option longopts[] =
83
{
84
{"help", no_argument, NULL, OPTION_HELP},
85
{"version", no_argument, NULL, 'V'},
86
{NULL, 0, NULL, 0}
87
};
88
89
static void bsdar_usage(void);
90
static void ranlib_usage(void);
91
static void set_mode(struct bsdar *bsdar, char opt);
92
static void only_mode(struct bsdar *bsdar, const char *opt,
93
const char *valid_modes);
94
static void bsdar_version(void);
95
static void ranlib_version(void);
96
97
int
98
main(int argc, char **argv)
99
{
100
struct bsdar *bsdar, bsdar_storage;
101
char *p;
102
size_t len;
103
int exitcode, i, opt, Dflag, Uflag;
104
105
bsdar = &bsdar_storage;
106
memset(bsdar, 0, sizeof(*bsdar));
107
exitcode = EXIT_SUCCESS;
108
Dflag = 0;
109
Uflag = 0;
110
111
if ((bsdar->progname = getprogname()) == NULL)
112
bsdar->progname = "ar";
113
114
/* Act like ranlib if our name ends in "ranlib"; this
115
* accommodates arm-freebsd7.1-ranlib, bsdranlib, etc. */
116
len = strlen(bsdar->progname);
117
if (len >= strlen("ranlib") &&
118
strcmp(bsdar->progname + len - strlen("ranlib"), "ranlib") == 0) {
119
while ((opt = getopt_long(argc, argv, "tDUV", longopts,
120
NULL)) != -1) {
121
switch(opt) {
122
case 't':
123
/* Ignored. */
124
break;
125
case 'D':
126
Dflag = 1;
127
Uflag = 0;
128
break;
129
case 'U':
130
Uflag = 1;
131
Dflag = 0;
132
break;
133
case 'V':
134
ranlib_version();
135
break;
136
case OPTION_HELP:
137
ranlib_usage();
138
default:
139
ranlib_usage();
140
}
141
}
142
argv += optind;
143
argc -= optind;
144
145
if (*argv == NULL)
146
ranlib_usage();
147
148
/* Enable determinstic mode unless -U is set. */
149
if (Uflag == 0)
150
bsdar->options |= AR_D;
151
bsdar->options |= AR_S;
152
while ((bsdar->filename = *argv++) != NULL)
153
if (ar_write_archive(bsdar, 's'))
154
exitcode = EXIT_FAILURE;
155
156
exit(exitcode);
157
} else {
158
if (argc < 2)
159
bsdar_usage();
160
161
if (*argv[1] != '-') {
162
len = strlen(argv[1]) + 2;
163
if ((p = malloc(len)) == NULL)
164
bsdar_errc(bsdar, errno, "malloc failed");
165
*p = '-';
166
(void)strlcpy(p + 1, argv[1], len - 1);
167
argv[1] = p;
168
}
169
}
170
171
while ((opt = getopt_long(argc, argv, "abCcdDfijlMmopqrSsTtUuVvxz",
172
longopts, NULL)) != -1) {
173
switch(opt) {
174
case 'a':
175
bsdar->options |= AR_A;
176
break;
177
case 'b':
178
case 'i':
179
bsdar->options |= AR_B;
180
break;
181
case 'C':
182
bsdar->options |= AR_CC;
183
break;
184
case 'c':
185
bsdar->options |= AR_C;
186
break;
187
case 'd':
188
set_mode(bsdar, opt);
189
break;
190
case 'D':
191
Dflag = 1;
192
Uflag = 0;
193
break;
194
case 'f':
195
bsdar->options |= AR_TR;
196
break;
197
case 'j':
198
/* ignored */
199
break;
200
case 'l':
201
/* ignored, for GNU ar comptibility */
202
break;
203
case 'M':
204
set_mode(bsdar, opt);
205
break;
206
case 'm':
207
set_mode(bsdar, opt);
208
break;
209
case 'o':
210
bsdar->options |= AR_O;
211
break;
212
case 'p':
213
set_mode(bsdar, opt);
214
break;
215
case 'q':
216
set_mode(bsdar, opt);
217
break;
218
case 'r':
219
set_mode(bsdar, opt);
220
break;
221
case 'S':
222
bsdar->options |= AR_SS;
223
break;
224
case 's':
225
bsdar->options |= AR_S;
226
break;
227
case 'T':
228
/* ignored */
229
break;
230
case 't':
231
set_mode(bsdar, opt);
232
break;
233
case 'U':
234
Uflag = 1;
235
Dflag = 0;
236
break;
237
case 'u':
238
bsdar->options |= AR_U;
239
break;
240
case 'V':
241
bsdar_version();
242
break;
243
case 'v':
244
bsdar->options |= AR_V;
245
break;
246
case 'x':
247
set_mode(bsdar, opt);
248
break;
249
case 'z':
250
/* ignored */
251
break;
252
case OPTION_HELP:
253
bsdar_usage();
254
default:
255
bsdar_usage();
256
}
257
}
258
259
argv += optind;
260
argc -= optind;
261
262
if (*argv == NULL && bsdar->mode != 'M')
263
bsdar_usage();
264
265
if (bsdar->options & AR_A && bsdar->options & AR_B)
266
bsdar_errc(bsdar, 0,
267
"only one of -a and -[bi] options allowed");
268
269
if (bsdar->options & AR_J && bsdar->options & AR_Z)
270
bsdar_errc(bsdar, 0, "only one of -j and -z options allowed");
271
272
if (bsdar->options & AR_S && bsdar->options & AR_SS)
273
bsdar_errc(bsdar, 0, "only one of -s and -S options allowed");
274
275
if (bsdar->options & (AR_A | AR_B)) {
276
if (*argv == NULL)
277
bsdar_errc(bsdar, 0, "no position operand specified");
278
if ((bsdar->posarg = basename(*argv)) == NULL)
279
bsdar_errc(bsdar, errno, "basename failed");
280
argc--;
281
argv++;
282
}
283
284
/* Set determinstic mode for -D, and by default without -U. */
285
if (Dflag || (Uflag == 0 && (bsdar->mode == 'q' || bsdar->mode == 'r' ||
286
(bsdar->mode == '\0' && bsdar->options & AR_S))))
287
bsdar->options |= AR_D;
288
289
if (bsdar->options & AR_A)
290
only_mode(bsdar, "-a", "mqr");
291
if (bsdar->options & AR_B)
292
only_mode(bsdar, "-b", "mqr");
293
if (bsdar->options & AR_C)
294
only_mode(bsdar, "-c", "qr");
295
if (bsdar->options & AR_CC)
296
only_mode(bsdar, "-C", "x");
297
if (Dflag)
298
only_mode(bsdar, "-D", "qr");
299
if (Uflag)
300
only_mode(bsdar, "-U", "qr");
301
if (bsdar->options & AR_O)
302
only_mode(bsdar, "-o", "x");
303
if (bsdar->options & AR_SS)
304
only_mode(bsdar, "-S", "mqr");
305
if (bsdar->options & AR_U)
306
only_mode(bsdar, "-u", "qrx");
307
308
if (bsdar->mode == 'M') {
309
ar_mode_script(bsdar);
310
exit(EXIT_SUCCESS);
311
}
312
313
if ((bsdar->filename = *argv) == NULL)
314
bsdar_usage();
315
316
bsdar->argc = --argc;
317
bsdar->argv = ++argv;
318
319
if ((!bsdar->mode || strchr("ptx", bsdar->mode)) &&
320
bsdar->options & AR_S) {
321
exitcode = ar_write_archive(bsdar, 's');
322
if (!bsdar->mode)
323
exit(exitcode);
324
}
325
326
switch(bsdar->mode) {
327
case 'd': case 'm': case 'q': case 'r':
328
exitcode = ar_write_archive(bsdar, bsdar->mode);
329
break;
330
case 'p': case 't': case 'x':
331
exitcode = ar_read_archive(bsdar, bsdar->mode, stdout);
332
break;
333
default:
334
bsdar_usage();
335
/* NOTREACHED */
336
}
337
338
for (i = 0; i < bsdar->argc; i++) {
339
if (bsdar->argv[i] != NULL) {
340
bsdar_warnc(bsdar, 0, "%s: not found in archive",
341
bsdar->argv[i]);
342
exitcode = EXIT_FAILURE;
343
}
344
}
345
346
exit(exitcode);
347
}
348
349
static void
350
set_mode(struct bsdar *bsdar, char opt)
351
{
352
353
if (bsdar->mode != '\0' && bsdar->mode != opt)
354
bsdar_errc(bsdar, 0, "Can't specify both -%c and -%c", opt,
355
bsdar->mode);
356
bsdar->mode = opt;
357
}
358
359
static void
360
only_mode(struct bsdar *bsdar, const char *opt, const char *valid_modes)
361
{
362
363
if (strchr(valid_modes, bsdar->mode) == NULL)
364
bsdar_errc(bsdar, 0, "Option %s is not permitted in mode -%c",
365
opt, bsdar->mode);
366
}
367
368
static void
369
bsdar_usage(void)
370
{
371
372
(void)fprintf(stderr, "usage: ar -d [-Tjsvz] archive file ...\n");
373
(void)fprintf(stderr, "\tar -m [-Tjsvz] archive file ...\n");
374
(void)fprintf(stderr, "\tar -m [-Tabijsvz] position archive file ...\n");
375
(void)fprintf(stderr, "\tar -p [-Tv] archive [file ...]\n");
376
(void)fprintf(stderr, "\tar -q [-TcDjsUvz] archive file ...\n");
377
(void)fprintf(stderr, "\tar -r [-TcDjsUuvz] archive file ...\n");
378
(void)fprintf(stderr, "\tar -r [-TabcDijsUuvz] position archive file ...\n");
379
(void)fprintf(stderr, "\tar -s [-jz] archive\n");
380
(void)fprintf(stderr, "\tar -t [-Tv] archive [file ...]\n");
381
(void)fprintf(stderr, "\tar -x [-CTouv] archive [file ...]\n");
382
(void)fprintf(stderr, "\tar -V\n");
383
exit(EXIT_FAILURE);
384
}
385
386
static void
387
ranlib_usage(void)
388
{
389
390
(void)fprintf(stderr, "usage: ranlib [-DtU] archive ...\n");
391
(void)fprintf(stderr, "\tranlib -V\n");
392
exit(EXIT_FAILURE);
393
}
394
395
static void
396
bsdar_version(void)
397
{
398
(void)printf("BSD ar %s - %s\n", BSDAR_VERSION, archive_version_string());
399
exit(EXIT_SUCCESS);
400
}
401
402
static void
403
ranlib_version(void)
404
{
405
(void)printf("ranlib %s - %s\n", BSDAR_VERSION, archive_version_string());
406
exit(EXIT_SUCCESS);
407
}
408
409