View | Details | Raw Unified | Return to bug 257599 | Differences between
and this patch

Collapse All | Expand All

(-)b/usr.bin/ar/acpyacc.y (-3 / +3 lines)
Lines 1-663 Link Here
1
%{
1
%{
2
/*-
2
/*-
3
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4
 *
4
 *
5
 * Copyright (c) 2008 Kai Wang
5
 * Copyright (c) 2008 Kai Wang
6
 * All rights reserved.
6
 * All rights reserved.
7
 *
7
 *
8
 * Redistribution and use in source and binary forms, with or without
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
9
 * modification, are permitted provided that the following conditions
10
 * are met:
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
15
 *    documentation and/or other materials provided with the distribution.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
27
 * SUCH DAMAGE.
28
 */
28
 */
29
29
30
#include <sys/cdefs.h>
30
#include <sys/cdefs.h>
31
__FBSDID("$FreeBSD$");
31
__FBSDID("$FreeBSD$");
32
32
33
#include <sys/mman.h>
33
#include <sys/mman.h>
34
#include <sys/param.h>
34
#include <sys/param.h>
35
#include <sys/queue.h>
35
#include <sys/queue.h>
36
#include <sys/stat.h>
36
#include <sys/stat.h>
37
#include <archive.h>
37
#include <archive.h>
38
#include <archive_entry.h>
38
#include <archive_entry.h>
39
#include <dirent.h>
39
#include <dirent.h>
40
#include <errno.h>
40
#include <errno.h>
41
#include <fcntl.h>
41
#include <fcntl.h>
42
#include <stdio.h>
42
#include <stdio.h>
43
#include <stdlib.h>
43
#include <stdlib.h>
44
#include <string.h>
44
#include <string.h>
45
#include <sysexits.h>
45
#include <sysexits.h>
46
#include <unistd.h>
46
#include <unistd.h>
47
47
48
#include "ar.h"
48
#include "ar.h"
49
49
50
#define TEMPLATE "arscp.XXXXXXXX"
50
#define TEMPLATE "arscp.XXXXXXXX"
51
51
52
struct list {
52
struct list {
53
	char		*str;
53
	char		*str;
54
	struct list	*next;
54
	struct list	*next;
55
};
55
};
56
56
57
57
58
extern int	yylex(void);
58
extern int	yylex(void);
59
59
60
static void	yyerror(const char *);
60
static void	yyerror(const char *);
61
static void	arscp_addlib(char *archive, struct list *list);
61
static void	arscp_addlib(char *archive, struct list *list);
62
static void	arscp_addmod(struct list *list);
62
static void	arscp_addmod(struct list *list);
63
static void	arscp_clear(void);
63
static void	arscp_clear(void);
64
static int	arscp_copy(int ifd, int ofd);
64
static int	arscp_copy(int ifd, int ofd);
65
static void	arscp_create(char *in, char *out);
65
static void	arscp_create(char *in, char *out);
66
static void	arscp_delete(struct list *list);
66
static void	arscp_delete(struct list *list);
67
static void	arscp_dir(char *archive, struct list *list, char *rlt);
67
static void	arscp_dir(char *archive, struct list *list, char *rlt);
68
static void	arscp_end(int eval);
68
static void	arscp_end(int eval);
69
static void	arscp_extract(struct list *list);
69
static void	arscp_extract(struct list *list);
70
static void	arscp_free_argv(void);
70
static void	arscp_free_argv(void);
71
static void	arscp_free_mlist(struct list *list);
71
static void	arscp_free_mlist(struct list *list);
72
static void	arscp_list(void);
72
static void	arscp_list(void);
73
static struct list *arscp_mlist(struct list *list, char *str);
73
static struct list *arscp_mlist(struct list *list, char *str);
74
static void	arscp_mlist2argv(struct list *list);
74
static void	arscp_mlist2argv(struct list *list);
75
static int	arscp_mlist_len(struct list *list);
75
static int	arscp_mlist_len(struct list *list);
76
static void	arscp_open(char *fname);
76
static void	arscp_open(char *fname);
77
static void	arscp_prompt(void);
77
static void	arscp_prompt(void);
78
static void	arscp_replace(struct list *list);
78
static void	arscp_replace(struct list *list);
79
static void	arscp_save(void);
79
static void	arscp_save(void);
80
static int	arscp_target_exist(void);
80
static int	arscp_target_exist(void);
81
81
82
extern int		 lineno;
82
extern int		 lineno;
83
83
84
static struct bsdar	*bsdar;
84
static struct bsdar	*bsdar;
85
static char		*target;
85
static char		*target;
86
static char		*tmpac;
86
static char		*tmpac;
87
static int		 interactive;
87
static int		 interactive;
88
static int		 verbose;
88
static int		 verbose;
89
89
90
%}
90
%}
91
91
92
%token ADDLIB
92
%token ADDLIB
93
%token ADDMOD
93
%token ADDMOD
94
%token CLEAR
94
%token CLEAR
95
%token CREATE
95
%token CREATE
96
%token DELETE
96
%token DELETE
97
%token DIRECTORY
97
%token DIRECTORY
98
%token END
98
%token END
99
%token EXTRACT
99
%token EXTRACT
100
%token LIST
100
%token LIST
101
%token OPEN
101
%token OPEN
102
%token REPLACE
102
%token REPLACE
103
%token VERBOSE
103
%token VERBOSE
104
%token SAVE
104
%token SAVE
105
%token LP
105
%token LP
106
%token RP
106
%token RP
107
%token COMMA
107
%token COMMA
108
%token EOL
108
%token EOL
109
%token <str> FNAME
109
%token <str> FNAME
110
%type <list> mod_list
110
%type <list> mod_list
111
111
112
%union {
112
%union {
113
	char		*str;
113
	char		*str;
114
	struct list	*list;
114
	struct list	*list;
115
}
115
}
116
116
117
%%
117
%%
118
118
119
begin
119
begin
120
	: { arscp_prompt(); } ar_script
120
	: { arscp_prompt(); } ar_script
121
	;
121
	;
122
122
123
ar_script
123
ar_script
124
	: cmd_list
124
	: cmd_list
125
	|
125
	|
126
	;
126
	;
127
127
128
mod_list
128
mod_list
129
	: FNAME { $$ = arscp_mlist(NULL, $1); }
129
	: FNAME { $$ = arscp_mlist(NULL, $1); }
130
	| mod_list separator FNAME { $$ = arscp_mlist($1, $3); }
130
	| mod_list separator FNAME { $$ = arscp_mlist($1, $3); }
131
	;
131
	;
132
132
133
separator
133
separator
134
	: COMMA
134
	: COMMA
135
	|
135
	|
136
	;
136
	;
137
137
138
cmd_list
138
cmd_list
139
	: rawcmd
139
	: rawcmd
140
	| cmd_list rawcmd
140
	| cmd_list rawcmd
141
	;
141
	;
142
142
143
rawcmd
143
rawcmd
144
	: cmd EOL { arscp_prompt(); }
144
	: cmd EOL { arscp_prompt(); }
145
	;
145
	;
146
146
147
cmd
147
cmd
148
	: addlib_cmd
148
	: addlib_cmd
149
	| addmod_cmd
149
	| addmod_cmd
150
	| clear_cmd
150
	| clear_cmd
151
	| create_cmd
151
	| create_cmd
152
	| delete_cmd
152
	| delete_cmd
153
	| directory_cmd
153
	| directory_cmd
154
	| end_cmd
154
	| end_cmd
155
	| extract_cmd
155
	| extract_cmd
156
	| list_cmd
156
	| list_cmd
157
	| open_cmd
157
	| open_cmd
158
	| replace_cmd
158
	| replace_cmd
159
	| verbose_cmd
159
	| verbose_cmd
160
	| save_cmd
160
	| save_cmd
161
	| invalid_cmd
161
	| invalid_cmd
162
	| empty_cmd
162
	| empty_cmd
163
	| error
163
	| error
164
	;
164
	;
165
165
166
addlib_cmd
166
addlib_cmd
167
	: ADDLIB FNAME LP mod_list RP { arscp_addlib($2, $4); }
167
	: ADDLIB FNAME LP mod_list RP { arscp_addlib($2, $4); }
168
	| ADDLIB FNAME { arscp_addlib($2, NULL); }
168
	| ADDLIB FNAME { arscp_addlib($2, NULL); }
169
	;
169
	;
170
170
171
addmod_cmd
171
addmod_cmd
172
	: ADDMOD mod_list { arscp_addmod($2); }
172
	: ADDMOD mod_list { arscp_addmod($2); }
173
	;
173
	;
174
174
175
clear_cmd
175
clear_cmd
176
	: CLEAR { arscp_clear(); }
176
	: CLEAR { arscp_clear(); }
177
	;
177
	;
178
178
179
create_cmd
179
create_cmd
180
	: CREATE FNAME { arscp_create(NULL, $2); }
180
	: CREATE FNAME { arscp_create(NULL, $2); }
181
	;
181
	;
182
182
183
delete_cmd
183
delete_cmd
184
	: DELETE mod_list { arscp_delete($2); }
184
	: DELETE mod_list { arscp_delete($2); }
185
	;
185
	;
186
186
187
directory_cmd
187
directory_cmd
188
	: DIRECTORY FNAME { arscp_dir($2, NULL, NULL); }
188
	: DIRECTORY FNAME { arscp_dir($2, NULL, NULL); }
189
	| DIRECTORY FNAME LP mod_list RP { arscp_dir($2, $4, NULL); }
189
	| DIRECTORY FNAME LP mod_list RP { arscp_dir($2, $4, NULL); }
190
	| DIRECTORY FNAME LP mod_list RP FNAME { arscp_dir($2, $4, $6); }
190
	| DIRECTORY FNAME LP mod_list RP FNAME { arscp_dir($2, $4, $6); }
191
	;
191
	;
192
192
193
end_cmd
193
end_cmd
194
	: END { arscp_end(EX_OK); }
194
	: END { arscp_end(EXIT_SUCCESS); }
195
	;
195
	;
196
196
197
extract_cmd
197
extract_cmd
198
	: EXTRACT mod_list { arscp_extract($2); }
198
	: EXTRACT mod_list { arscp_extract($2); }
199
	;
199
	;
200
200
201
list_cmd
201
list_cmd
202
	: LIST { arscp_list(); }
202
	: LIST { arscp_list(); }
203
	;
203
	;
204
204
205
open_cmd
205
open_cmd
206
	: OPEN FNAME { arscp_open($2); }
206
	: OPEN FNAME { arscp_open($2); }
207
	;
207
	;
208
208
209
replace_cmd
209
replace_cmd
210
	: REPLACE mod_list { arscp_replace($2); }
210
	: REPLACE mod_list { arscp_replace($2); }
211
	;
211
	;
212
212
213
save_cmd
213
save_cmd
214
	: SAVE { arscp_save(); }
214
	: SAVE { arscp_save(); }
215
	;
215
	;
216
216
217
verbose_cmd
217
verbose_cmd
218
	: VERBOSE { verbose = !verbose; }
218
	: VERBOSE { verbose = !verbose; }
219
	;
219
	;
220
220
221
empty_cmd
221
empty_cmd
222
	:
222
	:
223
	;
223
	;
224
224
225
invalid_cmd
225
invalid_cmd
226
	: FNAME { yyerror(NULL); }
226
	: FNAME { yyerror(NULL); }
227
	;
227
	;
228
228
229
%%
229
%%
230
230
231
/* ARGSUSED */
231
/* ARGSUSED */
232
static void
232
static void
233
yyerror(const char *s)
233
yyerror(const char *s)
234
{
234
{
235
235
236
	(void) s;
236
	(void) s;
237
	printf("Syntax error in archive script, line %d\n", lineno);
237
	printf("Syntax error in archive script, line %d\n", lineno);
238
}
238
}
239
239
240
/*
240
/*
241
 * arscp_open first open an archive and check its validity. If the archive
241
 * arscp_open first open an archive and check its validity. If the archive
242
 * format is valid, it calls arscp_create to create a temporary copy of
242
 * format is valid, it calls arscp_create to create a temporary copy of
243
 * the archive.
243
 * the archive.
244
 */
244
 */
245
static void
245
static void
246
arscp_open(char *fname)
246
arscp_open(char *fname)
247
{
247
{
248
	struct archive		*a;
248
	struct archive		*a;
249
	struct archive_entry	*entry;
249
	struct archive_entry	*entry;
250
	int			 r;
250
	int			 r;
251
251
252
	if ((a = archive_read_new()) == NULL)
252
	if ((a = archive_read_new()) == NULL)
253
		bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_read_new failed");
253
		bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_read_new failed");
254
	archive_read_support_format_ar(a);
254
	archive_read_support_format_ar(a);
255
	AC(archive_read_open_filename(a, fname, DEF_BLKSZ));
255
	AC(archive_read_open_filename(a, fname, DEF_BLKSZ));
256
	if ((r = archive_read_next_header(a, &entry)))
256
	if ((r = archive_read_next_header(a, &entry)))
257
		bsdar_warnc(bsdar, archive_errno(a), "%s",
257
		bsdar_warnc(bsdar, archive_errno(a), "%s",
258
		    archive_error_string(a));
258
		    archive_error_string(a));
259
	AC(archive_read_close(a));
259
	AC(archive_read_close(a));
260
	AC(archive_read_free(a));
260
	AC(archive_read_free(a));
261
	if (r != ARCHIVE_OK)
261
	if (r != ARCHIVE_OK)
262
		return;
262
		return;
263
	arscp_create(fname, fname);
263
	arscp_create(fname, fname);
264
}
264
}
265
265
266
/*
266
/*
267
 * Create archive. in != NULL indicate it's a OPEN cmd, and resulting
267
 * Create archive. in != NULL indicate it's a OPEN cmd, and resulting
268
 * archive is based on modification of an existing one. If in == NULL,
268
 * archive is based on modification of an existing one. If in == NULL,
269
 * we are in CREATE cmd and a new empty archive will be created.
269
 * we are in CREATE cmd and a new empty archive will be created.
270
 */
270
 */
271
static void
271
static void
272
arscp_create(char *in, char *out)
272
arscp_create(char *in, char *out)
273
{
273
{
274
	struct archive		*a;
274
	struct archive		*a;
275
	int			 ifd, ofd;
275
	int			 ifd, ofd;
276
276
277
	/* Delete previously created temporary archive, if any. */
277
	/* Delete previously created temporary archive, if any. */
278
	if (tmpac) {
278
	if (tmpac) {
279
		if (unlink(tmpac) < 0)
279
		if (unlink(tmpac) < 0)
280
			bsdar_errc(bsdar, EX_IOERR, errno, "unlink failed");
280
			bsdar_errc(bsdar, EX_IOERR, errno, "unlink failed");
281
		free(tmpac);
281
		free(tmpac);
282
	}
282
	}
283
283
284
	tmpac = strdup(TEMPLATE);
284
	tmpac = strdup(TEMPLATE);
285
	if (tmpac == NULL)
285
	if (tmpac == NULL)
286
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed");
286
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed");
287
	if ((ofd = mkstemp(tmpac)) < 0)
287
	if ((ofd = mkstemp(tmpac)) < 0)
288
		bsdar_errc(bsdar, EX_IOERR, errno, "mkstemp failed");
288
		bsdar_errc(bsdar, EX_IOERR, errno, "mkstemp failed");
289
289
290
	if (in) {
290
	if (in) {
291
		/*
291
		/*
292
		 * Command OPEN creates a temporary copy of the
292
		 * Command OPEN creates a temporary copy of the
293
		 * input archive.
293
		 * input archive.
294
		 */
294
		 */
295
		if ((ifd = open(in, O_RDONLY)) < 0) {
295
		if ((ifd = open(in, O_RDONLY)) < 0) {
296
			bsdar_warnc(bsdar, errno, "open failed");
296
			bsdar_warnc(bsdar, errno, "open failed");
297
			return;
297
			return;
298
		}
298
		}
299
		if (arscp_copy(ifd, ofd)) {
299
		if (arscp_copy(ifd, ofd)) {
300
			bsdar_warnc(bsdar, 0, "arscp_copy failed");
300
			bsdar_warnc(bsdar, 0, "arscp_copy failed");
301
			return;
301
			return;
302
		}
302
		}
303
		close(ifd);
303
		close(ifd);
304
		close(ofd);
304
		close(ofd);
305
	} else {
305
	} else {
306
		/*
306
		/*
307
		 * Command CREATE creates an "empty" archive.
307
		 * Command CREATE creates an "empty" archive.
308
		 * (archive with only global header)
308
		 * (archive with only global header)
309
		 */
309
		 */
310
		if ((a = archive_write_new()) == NULL)
310
		if ((a = archive_write_new()) == NULL)
311
			bsdar_errc(bsdar, EX_SOFTWARE, 0,
311
			bsdar_errc(bsdar, EX_SOFTWARE, 0,
312
			    "archive_write_new failed");
312
			    "archive_write_new failed");
313
		archive_write_set_format_ar_svr4(a);
313
		archive_write_set_format_ar_svr4(a);
314
		AC(archive_write_open_fd(a, ofd));
314
		AC(archive_write_open_fd(a, ofd));
315
		AC(archive_write_close(a));
315
		AC(archive_write_close(a));
316
		AC(archive_write_free(a));
316
		AC(archive_write_free(a));
317
	}
317
	}
318
318
319
	/* Override previous target, if any. */
319
	/* Override previous target, if any. */
320
	if (target)
320
	if (target)
321
		free(target);
321
		free(target);
322
322
323
	target = out;
323
	target = out;
324
	bsdar->filename = tmpac;
324
	bsdar->filename = tmpac;
325
}
325
}
326
326
327
/* A file copying implementation using mmap. */
327
/* A file copying implementation using mmap. */
328
static int
328
static int
329
arscp_copy(int ifd, int ofd)
329
arscp_copy(int ifd, int ofd)
330
{
330
{
331
	struct stat		 sb;
331
	struct stat		 sb;
332
	char			*buf, *p;
332
	char			*buf, *p;
333
	ssize_t			 w;
333
	ssize_t			 w;
334
	size_t			 bytes;
334
	size_t			 bytes;
335
335
336
	if (fstat(ifd, &sb) < 0) {
336
	if (fstat(ifd, &sb) < 0) {
337
		bsdar_warnc(bsdar, errno, "fstate failed");
337
		bsdar_warnc(bsdar, errno, "fstate failed");
338
		return (1);
338
		return (1);
339
	}
339
	}
340
	if ((p = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, ifd,
340
	if ((p = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, ifd,
341
	    (off_t)0)) == MAP_FAILED) {
341
	    (off_t)0)) == MAP_FAILED) {
342
		bsdar_warnc(bsdar, errno, "mmap failed");
342
		bsdar_warnc(bsdar, errno, "mmap failed");
343
		return (1);
343
		return (1);
344
	}
344
	}
345
	for (buf = p, bytes = sb.st_size; bytes > 0; bytes -= w) {
345
	for (buf = p, bytes = sb.st_size; bytes > 0; bytes -= w) {
346
		w = write(ofd, buf, bytes);
346
		w = write(ofd, buf, bytes);
347
		if (w <= 0) {
347
		if (w <= 0) {
348
			bsdar_warnc(bsdar, errno, "write failed");
348
			bsdar_warnc(bsdar, errno, "write failed");
349
			break;
349
			break;
350
		}
350
		}
351
	}
351
	}
352
	if (munmap(p, sb.st_size) < 0)
352
	if (munmap(p, sb.st_size) < 0)
353
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "munmap failed");
353
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "munmap failed");
354
	if (bytes > 0)
354
	if (bytes > 0)
355
		return (1);
355
		return (1);
356
356
357
	return (0);
357
	return (0);
358
}
358
}
359
359
360
/*
360
/*
361
 * Add all modules of archive to current archive, if list != NULL,
361
 * Add all modules of archive to current archive, if list != NULL,
362
 * only those modules specified in 'list' will be added.
362
 * only those modules specified in 'list' will be added.
363
 */
363
 */
364
static void
364
static void
365
arscp_addlib(char *archive, struct list *list)
365
arscp_addlib(char *archive, struct list *list)
366
{
366
{
367
367
368
	if (!arscp_target_exist())
368
	if (!arscp_target_exist())
369
		return;
369
		return;
370
	arscp_mlist2argv(list);
370
	arscp_mlist2argv(list);
371
	bsdar->addlib = archive;
371
	bsdar->addlib = archive;
372
	ar_mode_A(bsdar);
372
	ar_mode_A(bsdar);
373
	arscp_free_argv();
373
	arscp_free_argv();
374
	arscp_free_mlist(list);
374
	arscp_free_mlist(list);
375
}
375
}
376
376
377
/* Add modules into current archive. */
377
/* Add modules into current archive. */
378
static void
378
static void
379
arscp_addmod(struct list *list)
379
arscp_addmod(struct list *list)
380
{
380
{
381
381
382
	if (!arscp_target_exist())
382
	if (!arscp_target_exist())
383
		return;
383
		return;
384
	arscp_mlist2argv(list);
384
	arscp_mlist2argv(list);
385
	ar_mode_q(bsdar);
385
	ar_mode_q(bsdar);
386
	arscp_free_argv();
386
	arscp_free_argv();
387
	arscp_free_mlist(list);
387
	arscp_free_mlist(list);
388
}
388
}
389
389
390
/* Delete modules from current archive. */
390
/* Delete modules from current archive. */
391
static void
391
static void
392
arscp_delete(struct list *list)
392
arscp_delete(struct list *list)
393
{
393
{
394
394
395
	if (!arscp_target_exist())
395
	if (!arscp_target_exist())
396
		return;
396
		return;
397
	arscp_mlist2argv(list);
397
	arscp_mlist2argv(list);
398
	ar_mode_d(bsdar);
398
	ar_mode_d(bsdar);
399
	arscp_free_argv();
399
	arscp_free_argv();
400
	arscp_free_mlist(list);
400
	arscp_free_mlist(list);
401
}
401
}
402
402
403
/* Extract modules from current archive. */
403
/* Extract modules from current archive. */
404
static void
404
static void
405
arscp_extract(struct list *list)
405
arscp_extract(struct list *list)
406
{
406
{
407
407
408
	if (!arscp_target_exist())
408
	if (!arscp_target_exist())
409
		return;
409
		return;
410
	arscp_mlist2argv(list);
410
	arscp_mlist2argv(list);
411
	ar_mode_x(bsdar);
411
	ar_mode_x(bsdar);
412
	arscp_free_argv();
412
	arscp_free_argv();
413
	arscp_free_mlist(list);
413
	arscp_free_mlist(list);
414
}
414
}
415
415
416
/* List modules of archive. (Simple Mode) */
416
/* List modules of archive. (Simple Mode) */
417
static void
417
static void
418
arscp_list(void)
418
arscp_list(void)
419
{
419
{
420
420
421
	if (!arscp_target_exist())
421
	if (!arscp_target_exist())
422
		return;
422
		return;
423
	bsdar->argc = 0;
423
	bsdar->argc = 0;
424
	bsdar->argv = NULL;
424
	bsdar->argv = NULL;
425
	/* Always verbose. */
425
	/* Always verbose. */
426
	bsdar->options |= AR_V;
426
	bsdar->options |= AR_V;
427
	ar_mode_t(bsdar);
427
	ar_mode_t(bsdar);
428
	bsdar->options &= ~AR_V;
428
	bsdar->options &= ~AR_V;
429
}
429
}
430
430
431
/* List modules of archive. (Advance Mode) */
431
/* List modules of archive. (Advance Mode) */
432
static void
432
static void
433
arscp_dir(char *archive, struct list *list, char *rlt)
433
arscp_dir(char *archive, struct list *list, char *rlt)
434
{
434
{
435
	FILE	*out;
435
	FILE	*out;
436
436
437
	/* If rlt != NULL, redirect output to it */
437
	/* If rlt != NULL, redirect output to it */
438
	out = NULL;
438
	out = NULL;
439
	if (rlt) {
439
	if (rlt) {
440
		out = stdout;
440
		out = stdout;
441
		if ((stdout = fopen(rlt, "w")) == NULL)
441
		if ((stdout = fopen(rlt, "w")) == NULL)
442
			bsdar_errc(bsdar, EX_IOERR, errno,
442
			bsdar_errc(bsdar, EX_IOERR, errno,
443
			    "fopen %s failed", rlt);
443
			    "fopen %s failed", rlt);
444
	}
444
	}
445
445
446
	bsdar->filename = archive;
446
	bsdar->filename = archive;
447
	if (list)
447
	if (list)
448
		arscp_mlist2argv(list);
448
		arscp_mlist2argv(list);
449
	else {
449
	else {
450
		bsdar->argc = 0;
450
		bsdar->argc = 0;
451
		bsdar->argv = NULL;
451
		bsdar->argv = NULL;
452
	}
452
	}
453
	if (verbose)
453
	if (verbose)
454
		bsdar->options |= AR_V;
454
		bsdar->options |= AR_V;
455
	ar_mode_t(bsdar);
455
	ar_mode_t(bsdar);
456
	bsdar->options &= ~AR_V;
456
	bsdar->options &= ~AR_V;
457
457
458
	if (rlt) {
458
	if (rlt) {
459
		if (fclose(stdout) == EOF)
459
		if (fclose(stdout) == EOF)
460
			bsdar_errc(bsdar, EX_IOERR, errno,
460
			bsdar_errc(bsdar, EX_IOERR, errno,
461
			    "fclose %s failed", rlt);
461
			    "fclose %s failed", rlt);
462
		stdout = out;
462
		stdout = out;
463
		free(rlt);
463
		free(rlt);
464
	}
464
	}
465
	free(archive);
465
	free(archive);
466
	bsdar->filename = tmpac;
466
	bsdar->filename = tmpac;
467
	arscp_free_argv();
467
	arscp_free_argv();
468
	arscp_free_mlist(list);
468
	arscp_free_mlist(list);
469
}
469
}
470
470
471
471
472
/* Replace modules of current archive. */
472
/* Replace modules of current archive. */
473
static void
473
static void
474
arscp_replace(struct list *list)
474
arscp_replace(struct list *list)
475
{
475
{
476
476
477
	if (!arscp_target_exist())
477
	if (!arscp_target_exist())
478
		return;
478
		return;
479
	arscp_mlist2argv(list);
479
	arscp_mlist2argv(list);
480
	ar_mode_r(bsdar);
480
	ar_mode_r(bsdar);
481
	arscp_free_argv();
481
	arscp_free_argv();
482
	arscp_free_mlist(list);
482
	arscp_free_mlist(list);
483
}
483
}
484
484
485
/* Rename the temporary archive to the target archive. */
485
/* Rename the temporary archive to the target archive. */
486
static void
486
static void
487
arscp_save(void)
487
arscp_save(void)
488
{
488
{
489
	mode_t mask;
489
	mode_t mask;
490
490
491
	if (target) {
491
	if (target) {
492
		if (rename(tmpac, target) < 0)
492
		if (rename(tmpac, target) < 0)
493
			bsdar_errc(bsdar, EX_IOERR, errno, "rename failed");
493
			bsdar_errc(bsdar, EX_IOERR, errno, "rename failed");
494
		/*
494
		/*
495
		 * mkstemp creates temp files with mode 0600, here we
495
		 * mkstemp creates temp files with mode 0600, here we
496
		 * set target archive mode per process umask.
496
		 * set target archive mode per process umask.
497
		 */
497
		 */
498
		mask = umask(0);
498
		mask = umask(0);
499
		umask(mask);
499
		umask(mask);
500
		if (chmod(target, 0666 & ~mask) < 0)
500
		if (chmod(target, 0666 & ~mask) < 0)
501
			bsdar_errc(bsdar, EX_IOERR, errno, "chmod failed");
501
			bsdar_errc(bsdar, EX_IOERR, errno, "chmod failed");
502
		free(tmpac);
502
		free(tmpac);
503
		free(target);
503
		free(target);
504
		tmpac = NULL;
504
		tmpac = NULL;
505
		target= NULL;
505
		target= NULL;
506
		bsdar->filename = NULL;
506
		bsdar->filename = NULL;
507
	} else
507
	} else
508
		bsdar_warnc(bsdar, 0, "no open output archive");
508
		bsdar_warnc(bsdar, 0, "no open output archive");
509
}
509
}
510
510
511
/*
511
/*
512
 * Discard all the contents of current archive. This is achieved by
512
 * Discard all the contents of current archive. This is achieved by
513
 * invoking CREATE cmd on current archive.
513
 * invoking CREATE cmd on current archive.
514
 */
514
 */
515
static void
515
static void
516
arscp_clear(void)
516
arscp_clear(void)
517
{
517
{
518
	char		*new_target;
518
	char		*new_target;
519
519
520
	if (target) {
520
	if (target) {
521
		new_target = strdup(target);
521
		new_target = strdup(target);
522
		if (new_target == NULL)
522
		if (new_target == NULL)
523
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed");
523
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed");
524
		arscp_create(NULL, new_target);
524
		arscp_create(NULL, new_target);
525
	}
525
	}
526
}
526
}
527
527
528
/*
528
/*
529
 * Quit ar(1). Note that END cmd will not SAVE current archive
529
 * Quit ar(1). Note that END cmd will not SAVE current archive
530
 * before exit.
530
 * before exit.
531
 */
531
 */
532
static void
532
static void
533
arscp_end(int eval)
533
arscp_end(int eval)
534
{
534
{
535
535
536
	if (target)
536
	if (target)
537
		free(target);
537
		free(target);
538
	if (tmpac) {
538
	if (tmpac) {
539
		if (unlink(tmpac) == -1)
539
		if (unlink(tmpac) == -1)
540
			bsdar_errc(bsdar, EX_IOERR, errno, "unlink %s failed",
540
			bsdar_errc(bsdar, EX_IOERR, errno, "unlink %s failed",
541
			    tmpac);
541
			    tmpac);
542
		free(tmpac);
542
		free(tmpac);
543
	}
543
	}
544
544
545
	exit(eval);
545
	exit(eval);
546
}
546
}
547
547
548
/*
548
/*
549
 * Check if target specified, i.e, whether OPEN or CREATE has been
549
 * Check if target specified, i.e, whether OPEN or CREATE has been
550
 * issued by user.
550
 * issued by user.
551
 */
551
 */
552
static int
552
static int
553
arscp_target_exist(void)
553
arscp_target_exist(void)
554
{
554
{
555
555
556
	if (target)
556
	if (target)
557
		return (1);
557
		return (1);
558
558
559
	bsdar_warnc(bsdar, 0, "no open output archive");
559
	bsdar_warnc(bsdar, 0, "no open output archive");
560
	return (0);
560
	return (0);
561
}
561
}
562
562
563
/* Construct module list. */
563
/* Construct module list. */
564
static struct list *
564
static struct list *
565
arscp_mlist(struct list *list, char *str)
565
arscp_mlist(struct list *list, char *str)
566
{
566
{
567
	struct list *l;
567
	struct list *l;
568
568
569
	l = malloc(sizeof(*l));
569
	l = malloc(sizeof(*l));
570
	if (l == NULL)
570
	if (l == NULL)
571
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
571
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
572
	l->str = str;
572
	l->str = str;
573
	l->next = list;
573
	l->next = list;
574
574
575
	return (l);
575
	return (l);
576
}
576
}
577
577
578
/* Calculate the length of a mlist. */
578
/* Calculate the length of a mlist. */
579
static int
579
static int
580
arscp_mlist_len(struct list *list)
580
arscp_mlist_len(struct list *list)
581
{
581
{
582
	int len;
582
	int len;
583
583
584
	for(len = 0; list; list = list->next)
584
	for(len = 0; list; list = list->next)
585
		len++;
585
		len++;
586
586
587
	return (len);
587
	return (len);
588
}
588
}
589
589
590
/* Free the space allocated for mod_list. */
590
/* Free the space allocated for mod_list. */
591
static void
591
static void
592
arscp_free_mlist(struct list *list)
592
arscp_free_mlist(struct list *list)
593
{
593
{
594
	struct list *l;
594
	struct list *l;
595
595
596
	/* Note that list->str was freed in arscp_free_argv. */
596
	/* Note that list->str was freed in arscp_free_argv. */
597
	for(; list; list = l) {
597
	for(; list; list = l) {
598
		l = list->next;
598
		l = list->next;
599
		free(list);
599
		free(list);
600
	}
600
	}
601
}
601
}
602
602
603
/* Convert mlist to argv array. */
603
/* Convert mlist to argv array. */
604
static void
604
static void
605
arscp_mlist2argv(struct list *list)
605
arscp_mlist2argv(struct list *list)
606
{
606
{
607
	char	**argv;
607
	char	**argv;
608
	int	  i, n;
608
	int	  i, n;
609
609
610
	n = arscp_mlist_len(list);
610
	n = arscp_mlist_len(list);
611
	argv = malloc(n * sizeof(*argv));
611
	argv = malloc(n * sizeof(*argv));
612
	if (argv == NULL)
612
	if (argv == NULL)
613
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
613
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
614
614
615
	/* Note that module names are stored in reverse order in mlist. */
615
	/* Note that module names are stored in reverse order in mlist. */
616
	for(i = n - 1; i >= 0; i--, list = list->next) {
616
	for(i = n - 1; i >= 0; i--, list = list->next) {
617
		if (list == NULL)
617
		if (list == NULL)
618
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "invalid mlist");
618
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "invalid mlist");
619
		argv[i] = list->str;
619
		argv[i] = list->str;
620
	}
620
	}
621
621
622
	bsdar->argc = n;
622
	bsdar->argc = n;
623
	bsdar->argv = argv;
623
	bsdar->argv = argv;
624
}
624
}
625
625
626
/* Free space allocated for argv array and its elements. */
626
/* Free space allocated for argv array and its elements. */
627
static void
627
static void
628
arscp_free_argv(void)
628
arscp_free_argv(void)
629
{
629
{
630
	int i;
630
	int i;
631
631
632
	for(i = 0; i < bsdar->argc; i++)
632
	for(i = 0; i < bsdar->argc; i++)
633
		free(bsdar->argv[i]);
633
		free(bsdar->argv[i]);
634
634
635
	free(bsdar->argv);
635
	free(bsdar->argv);
636
}
636
}
637
637
638
/* Show a prompt if we are in interactive mode */
638
/* Show a prompt if we are in interactive mode */
639
static void
639
static void
640
arscp_prompt(void)
640
arscp_prompt(void)
641
{
641
{
642
642
643
	if (interactive) {
643
	if (interactive) {
644
		printf("AR >");
644
		printf("AR >");
645
		fflush(stdout);
645
		fflush(stdout);
646
	}
646
	}
647
}
647
}
648
648
649
/* Main function for ar script mode. */
649
/* Main function for ar script mode. */
650
void
650
void
651
ar_mode_script(struct bsdar *ar)
651
ar_mode_script(struct bsdar *ar)
652
{
652
{
653
653
654
	bsdar = ar;
654
	bsdar = ar;
655
	interactive = isatty(fileno(stdin));
655
	interactive = isatty(fileno(stdin));
656
	while(yyparse()) {
656
	while(yyparse()) {
657
		if (!interactive)
657
		if (!interactive)
658
			arscp_end(1);
658
			arscp_end(EXIT_FAILURE);
659
	}
659
	}
660
660
661
	/* Script ends without END */
661
	/* Script ends without END */
662
	arscp_end(EX_OK);
662
	arscp_end(EXIT_SUCCESS);
663
}
663
}
(-)b/usr.bin/ar/ar.c (-19 / +24 lines)
Lines 1-422 Link Here
1
/*-
1
/*-
2
 * SPDX-License-Identifier: BSD-3-Clause
2
 * SPDX-License-Identifier: BSD-3-Clause
3
 *
3
 *
4
 * Copyright (c) 2007 Kai Wang
4
 * Copyright (c) 2007 Kai Wang
5
 * Copyright (c) 2007 Tim Kientzle
5
 * Copyright (c) 2007 Tim Kientzle
6
 * Copyright (c) 2007 Joseph Koshy
6
 * Copyright (c) 2007 Joseph Koshy
7
 * All rights reserved.
7
 * All rights reserved.
8
 *
8
 *
9
 * Redistribution and use in source and binary forms, with or without
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
10
 * modification, are permitted provided that the following conditions
11
 * are met:
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
16
 *    documentation and/or other materials provided with the distribution.
17
 *
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
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
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
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
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
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
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
28
 * SUCH DAMAGE.
29
 */
29
 */
30
30
31
/*-
31
/*-
32
 * Copyright (c) 1990, 1993, 1994
32
 * Copyright (c) 1990, 1993, 1994
33
 *	The Regents of the University of California.  All rights reserved.
33
 *	The Regents of the University of California.  All rights reserved.
34
 *
34
 *
35
 * This code is derived from software contributed to Berkeley by
35
 * This code is derived from software contributed to Berkeley by
36
 * Hugh Smith at The University of Guelph.
36
 * Hugh Smith at The University of Guelph.
37
 *
37
 *
38
 * Redistribution and use in source and binary forms, with or without
38
 * Redistribution and use in source and binary forms, with or without
39
 * modification, are permitted provided that the following conditions
39
 * modification, are permitted provided that the following conditions
40
 * are met:
40
 * are met:
41
 * 1. Redistributions of source code must retain the above copyright
41
 * 1. Redistributions of source code must retain the above copyright
42
 *    notice, this list of conditions and the following disclaimer.
42
 *    notice, this list of conditions and the following disclaimer.
43
 * 2. Redistributions in binary form must reproduce the above copyright
43
 * 2. Redistributions in binary form must reproduce the above copyright
44
 *    notice, this list of conditions and the following disclaimer in the
44
 *    notice, this list of conditions and the following disclaimer in the
45
 *    documentation and/or other materials provided with the distribution.
45
 *    documentation and/or other materials provided with the distribution.
46
 * 3. Neither the name of the University nor the names of its contributors
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
47
 *    may be used to endorse or promote products derived from this software
48
 *    without specific prior written permission.
48
 *    without specific prior written permission.
49
 *
49
 *
50
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
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
51
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
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
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
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
59
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60
 * SUCH DAMAGE.
60
 * SUCH DAMAGE.
61
 */
61
 */
62
62
63
#include <sys/cdefs.h>
63
#include <sys/cdefs.h>
64
__FBSDID("$FreeBSD$");
64
__FBSDID("$FreeBSD$");
65
65
66
#include <sys/queue.h>
66
#include <sys/queue.h>
67
#include <sys/types.h>
67
#include <sys/types.h>
68
#include <archive.h>
68
#include <archive.h>
69
#include <errno.h>
69
#include <errno.h>
70
#include <getopt.h>
70
#include <getopt.h>
71
#include <libgen.h>
71
#include <libgen.h>
72
#include <stdio.h>
72
#include <stdio.h>
73
#include <stdlib.h>
73
#include <stdlib.h>
74
#include <string.h>
74
#include <string.h>
75
#include <sysexits.h>
75
#include <sysexits.h>
76
76
77
#include "ar.h"
77
#include "ar.h"
78
78
79
enum options
79
enum options
80
{
80
{
81
	OPTION_HELP
81
	OPTION_HELP
82
};
82
};
83
83
84
static struct option longopts[] =
84
static struct option longopts[] =
85
{
85
{
86
	{"help", no_argument, NULL, OPTION_HELP},
86
	{"help", no_argument, NULL, OPTION_HELP},
87
	{"version", no_argument, NULL, 'V'},
87
	{"version", no_argument, NULL, 'V'},
88
	{NULL, 0, NULL, 0}
88
	{NULL, 0, NULL, 0}
89
};
89
};
90
90
91
static void	bsdar_usage(void);
91
static void	bsdar_usage(void);
92
static void	ranlib_usage(void);
92
static void	ranlib_usage(void);
93
static void	set_mode(struct bsdar *bsdar, char opt);
93
static void	set_mode(struct bsdar *bsdar, char opt);
94
static void	only_mode(struct bsdar *bsdar, const char *opt,
94
static void	only_mode(struct bsdar *bsdar, const char *opt,
95
		    const char *valid_modes);
95
		    const char *valid_modes);
96
static void	bsdar_version(void);
96
static void	bsdar_version(void);
97
static void	ranlib_version(void);
97
static void	ranlib_version(void);
98
98
99
int
99
int
100
main(int argc, char **argv)
100
main(int argc, char **argv)
101
{
101
{
102
	struct bsdar	*bsdar, bsdar_storage;
102
	struct bsdar	*bsdar, bsdar_storage;
103
	char		*p;
103
	char		*p;
104
	size_t		 len;
104
	size_t		 len;
105
	int		 i, opt, Dflag, Uflag;
105
	int		 exitcode, i, opt, Dflag, Uflag;
106
106
107
	bsdar = &bsdar_storage;
107
	bsdar = &bsdar_storage;
108
	memset(bsdar, 0, sizeof(*bsdar));
108
	memset(bsdar, 0, sizeof(*bsdar));
109
	exitcode = EXIT_SUCCESS;
109
	Dflag = 0;
110
	Dflag = 0;
110
	Uflag = 0;
111
	Uflag = 0;
111
112
112
	if ((bsdar->progname = getprogname()) == NULL)
113
	if ((bsdar->progname = getprogname()) == NULL)
113
		bsdar->progname = "ar";
114
		bsdar->progname = "ar";
114
115
115
	/* Act like ranlib if our name ends in "ranlib"; this
116
	/* Act like ranlib if our name ends in "ranlib"; this
116
	 * accommodates arm-freebsd7.1-ranlib, bsdranlib, etc. */
117
	 * accommodates arm-freebsd7.1-ranlib, bsdranlib, etc. */
117
	len = strlen(bsdar->progname);
118
	len = strlen(bsdar->progname);
118
	if (len >= strlen("ranlib") &&
119
	if (len >= strlen("ranlib") &&
119
	    strcmp(bsdar->progname + len - strlen("ranlib"), "ranlib") == 0) {
120
	    strcmp(bsdar->progname + len - strlen("ranlib"), "ranlib") == 0) {
120
		while ((opt = getopt_long(argc, argv, "tDUV", longopts,
121
		while ((opt = getopt_long(argc, argv, "tDUV", longopts,
121
		    NULL)) != -1) {
122
		    NULL)) != -1) {
122
			switch(opt) {
123
			switch(opt) {
123
			case 't':
124
			case 't':
124
				/* Ignored. */
125
				/* Ignored. */
125
				break;
126
				break;
126
			case 'D':
127
			case 'D':
127
				Dflag = 1;
128
				Dflag = 1;
128
				Uflag = 0;
129
				Uflag = 0;
129
				break;
130
				break;
130
			case 'U':
131
			case 'U':
131
				Uflag = 1;
132
				Uflag = 1;
132
				Dflag = 0;
133
				Dflag = 0;
133
				break;
134
				break;
134
			case 'V':
135
			case 'V':
135
				ranlib_version();
136
				ranlib_version();
136
				break;
137
				break;
137
			case OPTION_HELP:
138
			case OPTION_HELP:
138
				ranlib_usage();
139
				ranlib_usage();
139
			default:
140
			default:
140
				ranlib_usage();
141
				ranlib_usage();
141
			}
142
			}
142
		}
143
		}
143
		argv += optind;
144
		argv += optind;
144
		argc -= optind;
145
		argc -= optind;
145
146
146
		if (*argv == NULL)
147
		if (*argv == NULL)
147
			ranlib_usage();
148
			ranlib_usage();
148
149
149
		/* Enable determinstic mode unless -U is set. */
150
		/* Enable determinstic mode unless -U is set. */
150
		if (Uflag == 0)
151
		if (Uflag == 0)
151
			bsdar->options |= AR_D;
152
			bsdar->options |= AR_D;
152
		bsdar->options |= AR_S;
153
		bsdar->options |= AR_S;
153
		while ((bsdar->filename = *argv++) != NULL)
154
		while ((bsdar->filename = *argv++) != NULL)
154
			ar_mode_s(bsdar);
155
			if (ar_mode_s(bsdar))
156
				exitcode = EXIT_FAILURE;
155
157
156
		exit(EX_OK);
158
		exit(exitcode);
157
	} else {
159
	} else {
158
		if (argc < 2)
160
		if (argc < 2)
159
			bsdar_usage();
161
			bsdar_usage();
160
162
161
		if (*argv[1] != '-') {
163
		if (*argv[1] != '-') {
162
			len = strlen(argv[1]) + 2;
164
			len = strlen(argv[1]) + 2;
163
			if ((p = malloc(len)) == NULL)
165
			if ((p = malloc(len)) == NULL)
164
				bsdar_errc(bsdar, EX_SOFTWARE, errno,
166
				bsdar_errc(bsdar, EX_SOFTWARE, errno,
165
				    "malloc failed");
167
				    "malloc failed");
166
			*p = '-';
168
			*p = '-';
167
			(void)strlcpy(p + 1, argv[1], len - 1);
169
			(void)strlcpy(p + 1, argv[1], len - 1);
168
			argv[1] = p;
170
			argv[1] = p;
169
		}
171
		}
170
	}
172
	}
171
173
172
	while ((opt = getopt_long(argc, argv, "abCcdDfijlMmopqrSsTtUuVvxz",
174
	while ((opt = getopt_long(argc, argv, "abCcdDfijlMmopqrSsTtUuVvxz",
173
	    longopts, NULL)) != -1) {
175
	    longopts, NULL)) != -1) {
174
		switch(opt) {
176
		switch(opt) {
175
		case 'a':
177
		case 'a':
176
			bsdar->options |= AR_A;
178
			bsdar->options |= AR_A;
177
			break;
179
			break;
178
		case 'b':
180
		case 'b':
179
		case 'i':
181
		case 'i':
180
			bsdar->options |= AR_B;
182
			bsdar->options |= AR_B;
181
			break;
183
			break;
182
		case 'C':
184
		case 'C':
183
			bsdar->options |= AR_CC;
185
			bsdar->options |= AR_CC;
184
			break;
186
			break;
185
		case 'c':
187
		case 'c':
186
			bsdar->options |= AR_C;
188
			bsdar->options |= AR_C;
187
			break;
189
			break;
188
		case 'd':
190
		case 'd':
189
			set_mode(bsdar, opt);
191
			set_mode(bsdar, opt);
190
			break;
192
			break;
191
		case 'D':
193
		case 'D':
192
			Dflag = 1;
194
			Dflag = 1;
193
			Uflag = 0;
195
			Uflag = 0;
194
			break;
196
			break;
195
		case 'f':
197
		case 'f':
196
		case 'T':
198
		case 'T':
197
			bsdar->options |= AR_TR;
199
			bsdar->options |= AR_TR;
198
			break;
200
			break;
199
		case 'j':
201
		case 'j':
200
			/* ignored */
202
			/* ignored */
201
			break;
203
			break;
202
		case 'l':
204
		case 'l':
203
			/* ignored, for GNU ar comptibility */
205
			/* ignored, for GNU ar comptibility */
204
			break;
206
			break;
205
		case 'M':
207
		case 'M':
206
			set_mode(bsdar, opt);
208
			set_mode(bsdar, opt);
207
			break;
209
			break;
208
		case 'm':
210
		case 'm':
209
			set_mode(bsdar, opt);
211
			set_mode(bsdar, opt);
210
			break;
212
			break;
211
		case 'o':
213
		case 'o':
212
			bsdar->options |= AR_O;
214
			bsdar->options |= AR_O;
213
			break;
215
			break;
214
		case 'p':
216
		case 'p':
215
			set_mode(bsdar, opt);
217
			set_mode(bsdar, opt);
216
			break;
218
			break;
217
		case 'q':
219
		case 'q':
218
			set_mode(bsdar, opt);
220
			set_mode(bsdar, opt);
219
			break;
221
			break;
220
		case 'r':
222
		case 'r':
221
			set_mode(bsdar, opt);
223
			set_mode(bsdar, opt);
222
			break;
224
			break;
223
		case 'S':
225
		case 'S':
224
			bsdar->options |= AR_SS;
226
			bsdar->options |= AR_SS;
225
			break;
227
			break;
226
		case 's':
228
		case 's':
227
			bsdar->options |= AR_S;
229
			bsdar->options |= AR_S;
228
			break;
230
			break;
229
		case 't':
231
		case 't':
230
			set_mode(bsdar, opt);
232
			set_mode(bsdar, opt);
231
			break;
233
			break;
232
		case 'U':
234
		case 'U':
233
			Uflag = 1;
235
			Uflag = 1;
234
			Dflag = 0;
236
			Dflag = 0;
235
			break;
237
			break;
236
		case 'u':
238
		case 'u':
237
			bsdar->options |= AR_U;
239
			bsdar->options |= AR_U;
238
			break;
240
			break;
239
		case 'V':
241
		case 'V':
240
			bsdar_version();
242
			bsdar_version();
241
			break;
243
			break;
242
		case 'v':
244
		case 'v':
243
			bsdar->options |= AR_V;
245
			bsdar->options |= AR_V;
244
			break;
246
			break;
245
		case 'x':
247
		case 'x':
246
			set_mode(bsdar, opt);
248
			set_mode(bsdar, opt);
247
			break;
249
			break;
248
		case 'z':
250
		case 'z':
249
			/* ignored */
251
			/* ignored */
250
			break;
252
			break;
251
		case OPTION_HELP:
253
		case OPTION_HELP:
252
			bsdar_usage();
254
			bsdar_usage();
253
		default:
255
		default:
254
			bsdar_usage();
256
			bsdar_usage();
255
		}
257
		}
256
	}
258
	}
257
259
258
	argv += optind;
260
	argv += optind;
259
	argc -= optind;
261
	argc -= optind;
260
262
261
	if (*argv == NULL && bsdar->mode != 'M')
263
	if (*argv == NULL && bsdar->mode != 'M')
262
		bsdar_usage();
264
		bsdar_usage();
263
265
264
	if (bsdar->options & AR_A && bsdar->options & AR_B)
266
	if (bsdar->options & AR_A && bsdar->options & AR_B)
265
		bsdar_errc(bsdar, EX_USAGE, 0,
267
		bsdar_errc(bsdar, EXIT_FAILURE, 0,
266
		    "only one of -a and -[bi] options allowed");
268
		    "only one of -a and -[bi] options allowed");
267
269
268
	if (bsdar->options & AR_J && bsdar->options & AR_Z)
270
	if (bsdar->options & AR_J && bsdar->options & AR_Z)
269
		bsdar_errc(bsdar, EX_USAGE, 0,
271
		bsdar_errc(bsdar, EXIT_FAILURE, 0,
270
		    "only one of -j and -z options allowed");
272
		    "only one of -j and -z options allowed");
271
273
272
	if (bsdar->options & AR_S && bsdar->options & AR_SS)
274
	if (bsdar->options & AR_S && bsdar->options & AR_SS)
273
		bsdar_errc(bsdar, EX_USAGE, 0,
275
		bsdar_errc(bsdar, EXIT_FAILURE, 0,
274
		    "only one of -s and -S options allowed");
276
		    "only one of -s and -S options allowed");
275
277
276
	if (bsdar->options & (AR_A | AR_B)) {
278
	if (bsdar->options & (AR_A | AR_B)) {
277
		if (*argv == NULL)
279
		if (*argv == NULL)
278
			bsdar_errc(bsdar, EX_USAGE, 0,
280
			bsdar_errc(bsdar, EXIT_FAILURE, 0,
279
			    "no position operand specified");
281
			    "no position operand specified");
280
		if ((bsdar->posarg = basename(*argv)) == NULL)
282
		if ((bsdar->posarg = basename(*argv)) == NULL)
281
			bsdar_errc(bsdar, EX_SOFTWARE, errno,
283
			bsdar_errc(bsdar, EX_SOFTWARE, errno,
282
			    "basename failed");
284
			    "basename failed");
283
		argc--;
285
		argc--;
284
		argv++;
286
		argv++;
285
	}
287
	}
286
288
287
	/* Set determinstic mode for -D, and by default without -U. */
289
	/* Set determinstic mode for -D, and by default without -U. */
288
	if (Dflag || (Uflag == 0 && (bsdar->mode == 'q' || bsdar->mode == 'r' ||
290
	if (Dflag || (Uflag == 0 && (bsdar->mode == 'q' || bsdar->mode == 'r' ||
289
	    (bsdar->mode == '\0' && bsdar->options & AR_S))))
291
	    (bsdar->mode == '\0' && bsdar->options & AR_S))))
290
		bsdar->options |= AR_D;
292
		bsdar->options |= AR_D;
291
293
292
	if (bsdar->options & AR_A)
294
	if (bsdar->options & AR_A)
293
		only_mode(bsdar, "-a", "mqr");
295
		only_mode(bsdar, "-a", "mqr");
294
	if (bsdar->options & AR_B)
296
	if (bsdar->options & AR_B)
295
		only_mode(bsdar, "-b", "mqr");
297
		only_mode(bsdar, "-b", "mqr");
296
	if (bsdar->options & AR_C)
298
	if (bsdar->options & AR_C)
297
		only_mode(bsdar, "-c", "qr");
299
		only_mode(bsdar, "-c", "qr");
298
	if (bsdar->options & AR_CC)
300
	if (bsdar->options & AR_CC)
299
		only_mode(bsdar, "-C", "x");
301
		only_mode(bsdar, "-C", "x");
300
	if (Dflag)
302
	if (Dflag)
301
		only_mode(bsdar, "-D", "qr");
303
		only_mode(bsdar, "-D", "qr");
302
	if (Uflag)
304
	if (Uflag)
303
		only_mode(bsdar, "-U", "qr");
305
		only_mode(bsdar, "-U", "qr");
304
	if (bsdar->options & AR_O)
306
	if (bsdar->options & AR_O)
305
		only_mode(bsdar, "-o", "x");
307
		only_mode(bsdar, "-o", "x");
306
	if (bsdar->options & AR_SS)
308
	if (bsdar->options & AR_SS)
307
		only_mode(bsdar, "-S", "mqr");
309
		only_mode(bsdar, "-S", "mqr");
308
	if (bsdar->options & AR_U)
310
	if (bsdar->options & AR_U)
309
		only_mode(bsdar, "-u", "qrx");
311
		only_mode(bsdar, "-u", "qrx");
310
312
311
	if (bsdar->mode == 'M') {
313
	if (bsdar->mode == 'M') {
312
		ar_mode_script(bsdar);
314
		ar_mode_script(bsdar);
313
		exit(EX_OK);
315
		exit(EXIT_SUCCESS);
314
	}
316
	}
315
317
316
	if ((bsdar->filename = *argv) == NULL)
318
	if ((bsdar->filename = *argv) == NULL)
317
		bsdar_usage();
319
		bsdar_usage();
318
320
319
	bsdar->argc = --argc;
321
	bsdar->argc = --argc;
320
	bsdar->argv = ++argv;
322
	bsdar->argv = ++argv;
321
323
322
	if ((!bsdar->mode || strchr("ptx", bsdar->mode)) &&
324
	if ((!bsdar->mode || strchr("ptx", bsdar->mode)) &&
323
	    bsdar->options & AR_S) {
325
	    bsdar->options & AR_S) {
324
		ar_mode_s(bsdar);
326
		exitcode = ar_mode_s(bsdar);
325
		if (!bsdar->mode)
327
		if (!bsdar->mode)
326
			exit(EX_OK);
328
			exit(exitcode);
327
	}
329
	}
328
330
329
	switch(bsdar->mode) {
331
	switch(bsdar->mode) {
330
	case 'd':
332
	case 'd':
331
		ar_mode_d(bsdar);
333
		ar_mode_d(bsdar);
332
		break;
334
		break;
333
	case 'm':
335
	case 'm':
334
		ar_mode_m(bsdar);
336
		ar_mode_m(bsdar);
335
		break;
337
		break;
336
	case 'p':
338
	case 'p':
337
		ar_mode_p(bsdar);
339
		ar_mode_p(bsdar);
338
		break;
340
		break;
339
	case 'q':
341
	case 'q':
340
		ar_mode_q(bsdar);
342
		ar_mode_q(bsdar);
341
		break;
343
		break;
342
	case 'r':
344
	case 'r':
343
		ar_mode_r(bsdar);
345
		ar_mode_r(bsdar);
344
		break;
346
		break;
345
	case 't':
347
	case 't':
346
		ar_mode_t(bsdar);
348
		ar_mode_t(bsdar);
347
		break;
349
		break;
348
	case 'x':
350
	case 'x':
349
		ar_mode_x(bsdar);
351
		ar_mode_x(bsdar);
350
		break;
352
		break;
351
	default:
353
	default:
352
		bsdar_usage();
354
		bsdar_usage();
353
		/* NOTREACHED */
355
		/* NOTREACHED */
354
	}
356
	}
355
357
356
	for (i = 0; i < bsdar->argc; i++)
358
	for (i = 0; i < bsdar->argc; i++) {
357
		if (bsdar->argv[i] != NULL)
359
		if (bsdar->argv[i] != NULL) {
358
			bsdar_warnc(bsdar, 0, "%s: not found in archive",
360
			bsdar_warnc(bsdar, 0, "%s: not found in archive",
359
			    bsdar->argv[i]);
361
			    bsdar->argv[i]);
362
			exitcode = EXIT_FAILURE;
363
		}
364
	}
360
365
361
	exit(EX_OK);
366
	exit(exitcode);
362
}
367
}
363
368
364
static void
369
static void
365
set_mode(struct bsdar *bsdar, char opt)
370
set_mode(struct bsdar *bsdar, char opt)
366
{
371
{
367
372
368
	if (bsdar->mode != '\0' && bsdar->mode != opt)
373
	if (bsdar->mode != '\0' && bsdar->mode != opt)
369
		bsdar_errc(bsdar, EX_USAGE, 0,
374
		bsdar_errc(bsdar, EXIT_FAILURE, 0,
370
		    "Can't specify both -%c and -%c", opt, bsdar->mode);
375
		    "Can't specify both -%c and -%c", opt, bsdar->mode);
371
	bsdar->mode = opt;
376
	bsdar->mode = opt;
372
}
377
}
373
378
374
static void
379
static void
375
only_mode(struct bsdar *bsdar, const char *opt, const char *valid_modes)
380
only_mode(struct bsdar *bsdar, const char *opt, const char *valid_modes)
376
{
381
{
377
382
378
	if (strchr(valid_modes, bsdar->mode) == NULL)
383
	if (strchr(valid_modes, bsdar->mode) == NULL)
379
		bsdar_errc(bsdar, EX_USAGE, 0,
384
		bsdar_errc(bsdar, EXIT_FAILURE, 0,
380
		    "Option %s is not permitted in mode -%c", opt, bsdar->mode);
385
		    "Option %s is not permitted in mode -%c", opt, bsdar->mode);
381
}
386
}
382
387
383
static void
388
static void
384
bsdar_usage(void)
389
bsdar_usage(void)
385
{
390
{
386
391
387
	(void)fprintf(stderr, "usage:  ar -d [-Tjsvz] archive file ...\n");
392
	(void)fprintf(stderr, "usage:  ar -d [-Tjsvz] archive file ...\n");
388
	(void)fprintf(stderr, "\tar -m [-Tjsvz] archive file ...\n");
393
	(void)fprintf(stderr, "\tar -m [-Tjsvz] archive file ...\n");
389
	(void)fprintf(stderr, "\tar -m [-Tabijsvz] position archive file ...\n");
394
	(void)fprintf(stderr, "\tar -m [-Tabijsvz] position archive file ...\n");
390
	(void)fprintf(stderr, "\tar -p [-Tv] archive [file ...]\n");
395
	(void)fprintf(stderr, "\tar -p [-Tv] archive [file ...]\n");
391
	(void)fprintf(stderr, "\tar -q [-TcDjsUvz] archive file ...\n");
396
	(void)fprintf(stderr, "\tar -q [-TcDjsUvz] archive file ...\n");
392
	(void)fprintf(stderr, "\tar -r [-TcDjsUuvz] archive file ...\n");
397
	(void)fprintf(stderr, "\tar -r [-TcDjsUuvz] archive file ...\n");
393
	(void)fprintf(stderr, "\tar -r [-TabcDijsUuvz] position archive file ...\n");
398
	(void)fprintf(stderr, "\tar -r [-TabcDijsUuvz] position archive file ...\n");
394
	(void)fprintf(stderr, "\tar -s [-jz] archive\n");
399
	(void)fprintf(stderr, "\tar -s [-jz] archive\n");
395
	(void)fprintf(stderr, "\tar -t [-Tv] archive [file ...]\n");
400
	(void)fprintf(stderr, "\tar -t [-Tv] archive [file ...]\n");
396
	(void)fprintf(stderr, "\tar -x [-CTouv] archive [file ...]\n");
401
	(void)fprintf(stderr, "\tar -x [-CTouv] archive [file ...]\n");
397
	(void)fprintf(stderr, "\tar -V\n");
402
	(void)fprintf(stderr, "\tar -V\n");
398
	exit(EX_USAGE);
403
	exit(EXIT_FAILURE);
399
}
404
}
400
405
401
static void
406
static void
402
ranlib_usage(void)
407
ranlib_usage(void)
403
{
408
{
404
409
405
	(void)fprintf(stderr, "usage:	ranlib [-DtU] archive ...\n");
410
	(void)fprintf(stderr, "usage:	ranlib [-DtU] archive ...\n");
406
	(void)fprintf(stderr, "\tranlib -V\n");
411
	(void)fprintf(stderr, "\tranlib -V\n");
407
	exit(EX_USAGE);
412
	exit(EXIT_FAILURE);
408
}
413
}
409
414
410
static void
415
static void
411
bsdar_version(void)
416
bsdar_version(void)
412
{
417
{
413
	(void)printf("BSD ar %s - %s\n", BSDAR_VERSION, archive_version_string());
418
	(void)printf("BSD ar %s - %s\n", BSDAR_VERSION, archive_version_string());
414
	exit(EX_OK);
419
	exit(EXIT_SUCCESS);
415
}
420
}
416
421
417
static void
422
static void
418
ranlib_version(void)
423
ranlib_version(void)
419
{
424
{
420
	(void)printf("ranlib %s - %s\n", BSDAR_VERSION, archive_version_string());
425
	(void)printf("ranlib %s - %s\n", BSDAR_VERSION, archive_version_string());
421
	exit(EX_OK);
426
	exit(EXIT_SUCCESS);
422
}
427
}
(-)b/usr.bin/ar/ar.h (-10 / +10 lines)
Lines 1-129 Link Here
1
/*-
1
/*-
2
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
2
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3
 *
3
 *
4
 * Copyright (c) 2007 Kai Wang
4
 * Copyright (c) 2007 Kai Wang
5
 * All rights reserved.
5
 * All rights reserved.
6
 *
6
 *
7
 * Redistribution and use in source and binary forms, with or without
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
8
 * modification, are permitted provided that the following conditions
9
 * are met:
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
14
 *    documentation and/or other materials provided with the distribution.
15
 *
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
26
 * SUCH DAMAGE.
27
 *
27
 *
28
 * $FreeBSD$
28
 * $FreeBSD$
29
 */
29
 */
30
30
31
#define	BSDAR_VERSION	"1.1.0"
31
#define	BSDAR_VERSION	"1.1.0"
32
32
33
/*
33
/*
34
 * ar(1) options.
34
 * ar(1) options.
35
 */
35
 */
36
#define AR_A	0x0001		/* position-after */
36
#define AR_A	0x0001		/* position-after */
37
#define AR_B	0x0002		/* position-before */
37
#define AR_B	0x0002		/* position-before */
38
#define AR_C	0x0004		/* creating new archive */
38
#define AR_C	0x0004		/* creating new archive */
39
#define AR_CC	0x0008		/* do not overwrite when extracting */
39
#define AR_CC	0x0008		/* do not overwrite when extracting */
40
#define AR_J	0x0010		/* bzip2 compression */
40
#define AR_J	0x0010		/* bzip2 compression */
41
#define AR_O	0x0020		/* preserve original mtime when extracting */
41
#define AR_O	0x0020		/* preserve original mtime when extracting */
42
#define AR_S	0x0040		/* write archive symbol table */
42
#define AR_S	0x0040		/* write archive symbol table */
43
#define AR_SS	0x0080		/* do not write archive symbol table */
43
#define AR_SS	0x0080		/* do not write archive symbol table */
44
#define AR_TR	0x0100		/* only keep first 15 chars for member name */
44
#define AR_TR	0x0100		/* only keep first 15 chars for member name */
45
#define AR_U	0x0200		/* only extract or update newer members.*/
45
#define AR_U	0x0200		/* only extract or update newer members.*/
46
#define AR_V	0x0400		/* verbose mode */
46
#define AR_V	0x0400		/* verbose mode */
47
#define AR_Z	0x0800		/* gzip compression */
47
#define AR_Z	0x0800		/* gzip compression */
48
#define AR_D	0x1000		/* insert dummy mode, mtime, uid and gid */
48
#define AR_D	0x1000		/* insert dummy mode, mtime, uid and gid */
49
49
50
#define DEF_BLKSZ 10240		/* default block size */
50
#define DEF_BLKSZ 10240		/* default block size */
51
51
52
/*
52
/*
53
 * Convenient wrapper for general libarchive error handling.
53
 * Convenient wrapper for general libarchive error handling.
54
 */
54
 */
55
#define	AC(CALL) do {							\
55
#define	AC(CALL) do {							\
56
	if ((CALL))							\
56
	if ((CALL))							\
57
		bsdar_errc(bsdar, EX_SOFTWARE, archive_errno(a), "%s",	\
57
		bsdar_errc(bsdar, EXIT_FAILURE, archive_errno(a), "%s",	\
58
		    archive_error_string(a));				\
58
		    archive_error_string(a));				\
59
} while (0)
59
} while (0)
60
60
61
/*
61
/*
62
 * In-memory representation of archive member(object).
62
 * In-memory representation of archive member(object).
63
 */
63
 */
64
struct ar_obj {
64
struct ar_obj {
65
	char		 *name;		/* member name */
65
	char		 *name;		/* member name */
66
	void		 *maddr;	/* mmap start address */
66
	void		 *maddr;	/* mmap start address */
67
	uid_t		  uid;		/* user id */
67
	uid_t		  uid;		/* user id */
68
	gid_t		  gid;		/* group id */
68
	gid_t		  gid;		/* group id */
69
	mode_t		  md;		/* octal file permissions */
69
	mode_t		  md;		/* octal file permissions */
70
	size_t		  size;		/* member size */
70
	size_t		  size;		/* member size */
71
	time_t		  mtime;	/* modification time */
71
	time_t		  mtime;	/* modification time */
72
	int		  fd;		/* file descriptor */
72
	int		  fd;		/* file descriptor */
73
	dev_t		  dev;		/* inode's device */
73
	dev_t		  dev;		/* inode's device */
74
	ino_t		  ino;		/* inode's number */
74
	ino_t		  ino;		/* inode's number */
75
75
76
	TAILQ_ENTRY(ar_obj) objs;
76
	TAILQ_ENTRY(ar_obj) objs;
77
};
77
};
78
78
79
/*
79
/*
80
 * Structure encapsulates the "global" data for "ar" program.
80
 * Structure encapsulates the "global" data for "ar" program.
81
 */
81
 */
82
struct bsdar {
82
struct bsdar {
83
	const char	 *filename;	/* archive name. */
83
	const char	 *filename;	/* archive name. */
84
	const char	 *addlib;	/* target of ADDLIB. */
84
	const char	 *addlib;	/* target of ADDLIB. */
85
	const char	 *posarg;	/* position arg for modifiers -a, -b. */
85
	const char	 *posarg;	/* position arg for modifiers -a, -b. */
86
	char		  mode;		/* program mode */
86
	char		  mode;		/* program mode */
87
	int		  options;	/* command line options */
87
	int		  options;	/* command line options */
88
88
89
	const char	 *progname;	/* program name */
89
	const char	 *progname;	/* program name */
90
	int		  argc;
90
	int		  argc;
91
	char		**argv;
91
	char		**argv;
92
92
93
	/*
93
	/*
94
	 * Fields for the archive string table.
94
	 * Fields for the archive string table.
95
	 */
95
	 */
96
	char		 *as;		/* buffer for archive string table. */
96
	char		 *as;		/* buffer for archive string table. */
97
	size_t		  as_sz;	/* current size of as table. */
97
	size_t		  as_sz;	/* current size of as table. */
98
	size_t		  as_cap;	/* capacity of as table buffer. */
98
	size_t		  as_cap;	/* capacity of as table buffer. */
99
99
100
	/*
100
	/*
101
	 * Fields for the archive symbol table.
101
	 * Fields for the archive symbol table.
102
	 */
102
	 */
103
	uint64_t	  s_cnt;	/* current number of symbols. */
103
	uint64_t	  s_cnt;	/* current number of symbols. */
104
	uint64_t	 *s_so;		/* symbol offset table. */
104
	uint64_t	 *s_so;		/* symbol offset table. */
105
	uint64_t	  s_so_max;     /* maximum symbol offset. */
105
	uint64_t	  s_so_max;     /* maximum symbol offset. */
106
	size_t		  s_so_cap;	/* capacity of so table buffer. */
106
	size_t		  s_so_cap;	/* capacity of so table buffer. */
107
107
108
	char		 *s_sn;		/* symbol name table */
108
	char		 *s_sn;		/* symbol name table */
109
	size_t		  s_sn_cap;	/* capacity of sn table buffer. */
109
	size_t		  s_sn_cap;	/* capacity of sn table buffer. */
110
	size_t		  s_sn_sz;	/* current size of sn table. */
110
	size_t		  s_sn_sz;	/* current size of sn table. */
111
	/* Current member's offset (relative to the end of pseudo members.) */
111
	/* Current member's offset (relative to the end of pseudo members.) */
112
	off_t		  rela_off;
112
	off_t		  rela_off;
113
113
114
	TAILQ_HEAD(, ar_obj) v_obj;	/* object(member) list */
114
	TAILQ_HEAD(, ar_obj) v_obj;	/* object(member) list */
115
};
115
};
116
116
117
void	bsdar_errc(struct bsdar *, int _eval, int _code,
117
void	bsdar_errc(struct bsdar *, int _eval, int _code,
118
	    const char *fmt, ...) __dead2;
118
	    const char *fmt, ...) __dead2;
119
void	bsdar_warnc(struct bsdar *, int _code, const char *fmt, ...);
119
void	bsdar_warnc(struct bsdar *, int _code, const char *fmt, ...);
120
void	ar_mode_d(struct bsdar *bsdar);
120
int	ar_mode_d(struct bsdar *bsdar);
121
void	ar_mode_m(struct bsdar *bsdar);
121
int	ar_mode_m(struct bsdar *bsdar);
122
void	ar_mode_p(struct bsdar *bsdar);
122
int	ar_mode_p(struct bsdar *bsdar);
123
void	ar_mode_q(struct bsdar *bsdar);
123
int	ar_mode_q(struct bsdar *bsdar);
124
void	ar_mode_r(struct bsdar *bsdar);
124
int	ar_mode_r(struct bsdar *bsdar);
125
void	ar_mode_s(struct bsdar *bsdar);
125
int	ar_mode_s(struct bsdar *bsdar);
126
void	ar_mode_t(struct bsdar *bsdar);
126
int	ar_mode_t(struct bsdar *bsdar);
127
void	ar_mode_x(struct bsdar *bsdar);
127
int	ar_mode_x(struct bsdar *bsdar);
128
void	ar_mode_A(struct bsdar *bsdar);
128
int	ar_mode_A(struct bsdar *bsdar);
129
void	ar_mode_script(struct bsdar *ar);
129
void	ar_mode_script(struct bsdar *ar);
(-)b/usr.bin/ar/read.c (-13 / +19 lines)
Lines 1-216 Link Here
1
/*-
1
/*-
2
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
2
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3
 *
3
 *
4
 * Copyright (c) 2007 Kai Wang
4
 * Copyright (c) 2007 Kai Wang
5
 * Copyright (c) 2007 Tim Kientzle
5
 * Copyright (c) 2007 Tim Kientzle
6
 * All rights reserved.
6
 * All rights reserved.
7
 *
7
 *
8
 * Redistribution and use in source and binary forms, with or without
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
9
 * modification, are permitted provided that the following conditions
10
 * are met:
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
15
 *    documentation and/or other materials provided with the distribution.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
27
 * SUCH DAMAGE.
28
 */
28
 */
29
29
30
#include <sys/cdefs.h>
30
#include <sys/cdefs.h>
31
__FBSDID("$FreeBSD$");
31
__FBSDID("$FreeBSD$");
32
32
33
#include <sys/queue.h>
33
#include <sys/queue.h>
34
#include <sys/stat.h>
34
#include <sys/stat.h>
35
#include <archive.h>
35
#include <archive.h>
36
#include <archive_entry.h>
36
#include <archive_entry.h>
37
#include <errno.h>
37
#include <errno.h>
38
#include <libgen.h>
38
#include <libgen.h>
39
#include <stdio.h>
39
#include <stdio.h>
40
#include <stdlib.h>
40
#include <string.h>
41
#include <string.h>
41
#include <sysexits.h>
42
42
43
#include "ar.h"
43
#include "ar.h"
44
44
45
static void read_archive(struct bsdar *bsdar, char mode);
45
static int read_archive(struct bsdar *bsdar, char mode);
46
46
47
void
47
int
48
ar_mode_p(struct bsdar *bsdar)
48
ar_mode_p(struct bsdar *bsdar)
49
{
49
{
50
50
51
	read_archive(bsdar, 'p');
51
	return (read_archive(bsdar, 'p'));
52
}
52
}
53
53
54
void
54
int
55
ar_mode_t(struct bsdar *bsdar)
55
ar_mode_t(struct bsdar *bsdar)
56
{
56
{
57
57
58
	read_archive(bsdar, 't');
58
	return (read_archive(bsdar, 't'));
59
}
59
}
60
60
61
void
61
int
62
ar_mode_x(struct bsdar *bsdar)
62
ar_mode_x(struct bsdar *bsdar)
63
{
63
{
64
64
65
	read_archive(bsdar, 'x');
65
	return (read_archive(bsdar, 'x'));
66
}
66
}
67
67
68
/*
68
/*
69
 * Handle read modes: 'x', 't' and 'p'.
69
 * Handle read modes: 'x', 't' and 'p'.
70
 */
70
 */
71
static void
71
static int
72
read_archive(struct bsdar *bsdar, char mode)
72
read_archive(struct bsdar *bsdar, char mode)
73
{
73
{
74
	struct archive		 *a;
74
	struct archive		 *a;
75
	struct archive_entry	 *entry;
75
	struct archive_entry	 *entry;
76
	struct stat		  sb;
76
	struct stat		  sb;
77
	struct tm		 *tp;
77
	struct tm		 *tp;
78
	const char		 *bname;
78
	const char		 *bname;
79
	const char		 *name;
79
	const char		 *name;
80
	mode_t			  md;
80
	mode_t			  md;
81
	size_t			  size;
81
	size_t			  size;
82
	time_t			  mtime;
82
	time_t			  mtime;
83
	uid_t			  uid;
83
	uid_t			  uid;
84
	gid_t			  gid;
84
	gid_t			  gid;
85
	char			**av;
85
	char			**av;
86
	char			  buf[25];
86
	char			  buf[25];
87
	char			  find;
87
	char			  find;
88
	int			  flags, r, i;
88
	int			  exitcode, flags, r, i;
89
89
90
	if ((a = archive_read_new()) == NULL)
90
	if ((a = archive_read_new()) == NULL)
91
		bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_read_new failed");
91
		bsdar_errc(bsdar, EXIT_FAILURE, 0, "archive_read_new failed");
92
	archive_read_support_format_ar(a);
92
	archive_read_support_format_ar(a);
93
	AC(archive_read_open_filename(a, bsdar->filename, DEF_BLKSZ));
93
	AC(archive_read_open_filename(a, bsdar->filename, DEF_BLKSZ));
94
94
95
	exitcode = EXIT_SUCCESS;
96
95
	for (;;) {
97
	for (;;) {
96
		r = archive_read_next_header(a, &entry);
98
		r = archive_read_next_header(a, &entry);
97
		if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY ||
99
		if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY ||
98
		    r == ARCHIVE_FATAL)
100
		    r == ARCHIVE_FATAL)
99
			bsdar_warnc(bsdar, archive_errno(a), "%s",
101
			bsdar_warnc(bsdar, archive_errno(a), "%s",
100
			    archive_error_string(a));
102
			    archive_error_string(a));
101
		if (r == ARCHIVE_EOF || r == ARCHIVE_FATAL)
103
		if (r == ARCHIVE_EOF || r == ARCHIVE_FATAL)
102
			break;
104
			break;
103
		if (r == ARCHIVE_RETRY) {
105
		if (r == ARCHIVE_RETRY) {
104
			bsdar_warnc(bsdar, 0, "Retrying...");
106
			bsdar_warnc(bsdar, 0, "Retrying...");
105
			continue;
107
			continue;
106
		}
108
		}
107
109
108
		if ((name = archive_entry_pathname(entry)) == NULL)
110
		if ((name = archive_entry_pathname(entry)) == NULL)
109
			break;
111
			break;
110
112
111
		/* Skip pseudo members. */
113
		/* Skip pseudo members. */
112
		if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0 ||
114
		if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0 ||
113
		    strcmp(name, "/SYM64/") == 0)
115
		    strcmp(name, "/SYM64/") == 0)
114
			continue;
116
			continue;
115
117
116
		if (bsdar->argc > 0) {
118
		if (bsdar->argc > 0) {
117
			find = 0;
119
			find = 0;
118
			for(i = 0; i < bsdar->argc; i++) {
120
			for(i = 0; i < bsdar->argc; i++) {
119
				av = &bsdar->argv[i];
121
				av = &bsdar->argv[i];
120
				if (*av == NULL)
122
				if (*av == NULL)
121
					continue;
123
					continue;
122
				if ((bname = basename(*av)) == NULL)
124
				if ((bname = basename(*av)) == NULL)
123
					bsdar_errc(bsdar, EX_SOFTWARE, errno,
125
					bsdar_errc(bsdar, EXIT_FAILURE, errno,
124
					    "basename failed");
126
					    "basename failed");
125
				if (strcmp(bname, name) != 0)
127
				if (strcmp(bname, name) != 0)
126
					continue;
128
					continue;
127
129
128
				*av = NULL;
130
				*av = NULL;
129
				find = 1;
131
				find = 1;
130
				break;
132
				break;
131
			}
133
			}
132
			if (!find)
134
			if (!find)
133
				continue;
135
				continue;
134
		}
136
		}
135
137
136
		if (mode == 't') {
138
		if (mode == 't') {
137
			if (bsdar->options & AR_V) {
139
			if (bsdar->options & AR_V) {
138
				md = archive_entry_mode(entry);
140
				md = archive_entry_mode(entry);
139
				uid = archive_entry_uid(entry);
141
				uid = archive_entry_uid(entry);
140
				gid = archive_entry_gid(entry);
142
				gid = archive_entry_gid(entry);
141
				size = archive_entry_size(entry);
143
				size = archive_entry_size(entry);
142
				mtime = archive_entry_mtime(entry);
144
				mtime = archive_entry_mtime(entry);
143
				(void)strmode(md, buf);
145
				(void)strmode(md, buf);
144
				(void)fprintf(stdout, "%s %6d/%-6d %8ju ",
146
				(void)fprintf(stdout, "%s %6d/%-6d %8ju ",
145
				    buf + 1, uid, gid, (uintmax_t)size);
147
				    buf + 1, uid, gid, (uintmax_t)size);
146
				tp = localtime(&mtime);
148
				tp = localtime(&mtime);
147
				(void)strftime(buf, sizeof(buf),
149
				(void)strftime(buf, sizeof(buf),
148
				    "%b %e %H:%M %Y", tp);
150
				    "%b %e %H:%M %Y", tp);
149
				(void)fprintf(stdout, "%s %s", buf, name);
151
				(void)fprintf(stdout, "%s %s", buf, name);
150
			} else
152
			} else
151
				(void)fprintf(stdout, "%s", name);
153
				(void)fprintf(stdout, "%s", name);
152
			r = archive_read_data_skip(a);
154
			r = archive_read_data_skip(a);
153
			if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY ||
155
			if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY ||
154
			    r == ARCHIVE_FATAL) {
156
			    r == ARCHIVE_FATAL) {
155
				(void)fprintf(stdout, "\n");
157
				(void)fprintf(stdout, "\n");
156
				bsdar_warnc(bsdar, archive_errno(a), "%s",
158
				bsdar_warnc(bsdar, archive_errno(a), "%s",
157
				    archive_error_string(a));
159
				    archive_error_string(a));
158
			}
160
			}
159
161
160
			if (r == ARCHIVE_FATAL)
162
			if (r == ARCHIVE_FATAL)
161
				break;
163
				break;
162
164
163
			(void)fprintf(stdout, "\n");
165
			(void)fprintf(stdout, "\n");
164
		} else {
166
		} else {
165
			/* mode == 'x' || mode = 'p' */
167
			/* mode == 'x' || mode = 'p' */
166
			if (mode == 'p') {
168
			if (mode == 'p') {
167
				if (bsdar->options & AR_V) {
169
				if (bsdar->options & AR_V) {
168
					(void)fprintf(stdout, "\n<%s>\n\n",
170
					(void)fprintf(stdout, "\n<%s>\n\n",
169
					    name);
171
					    name);
170
					fflush(stdout);
172
					fflush(stdout);
171
				}
173
				}
172
				r = archive_read_data_into_fd(a, 1);
174
				r = archive_read_data_into_fd(a, 1);
173
			} else {
175
			} else {
174
				/* mode == 'x' */
176
				/* mode == 'x' */
175
				if (stat(name, &sb) != 0) {
177
				if (stat(name, &sb) != 0) {
176
					if (errno != ENOENT) {
178
					if (errno != ENOENT) {
177
						bsdar_warnc(bsdar, 0,
179
						bsdar_warnc(bsdar, 0,
178
						    "stat %s failed",
180
						    "stat %s failed",
179
						    bsdar->filename);
181
						    bsdar->filename);
180
						continue;
182
						continue;
181
					}
183
					}
182
				} else {
184
				} else {
183
					/* stat success, file exist */
185
					/* stat success, file exist */
184
					if (bsdar->options & AR_CC)
186
					if (bsdar->options & AR_CC)
185
						continue;
187
						continue;
186
					if (bsdar->options & AR_U &&
188
					if (bsdar->options & AR_U &&
187
					    archive_entry_mtime(entry) <=
189
					    archive_entry_mtime(entry) <=
188
					    sb.st_mtime)
190
					    sb.st_mtime)
189
						continue;
191
						continue;
190
				}
192
				}
191
193
192
				if (bsdar->options & AR_V)
194
				if (bsdar->options & AR_V)
193
					(void)fprintf(stdout, "x - %s\n", name);
195
					(void)fprintf(stdout, "x - %s\n", name);
194
				/* Disallow absolute paths. */
196
				/* Disallow absolute paths. */
195
				if (name[0] == '/') {
197
				if (name[0] == '/') {
196
					bsdar_warnc(bsdar, 0,
198
					bsdar_warnc(bsdar, 0,
197
					    "Absolute path '%s'", name);
199
					    "Absolute path '%s'", name);
198
					continue;
200
					continue;
199
				}
201
				}
200
				/* Basic path security flags. */
202
				/* Basic path security flags. */
201
				flags = ARCHIVE_EXTRACT_SECURE_SYMLINKS |
203
				flags = ARCHIVE_EXTRACT_SECURE_SYMLINKS |
202
				    ARCHIVE_EXTRACT_SECURE_NODOTDOT;
204
				    ARCHIVE_EXTRACT_SECURE_NODOTDOT;
203
				if (bsdar->options & AR_O)
205
				if (bsdar->options & AR_O)
204
					flags |= ARCHIVE_EXTRACT_TIME;
206
					flags |= ARCHIVE_EXTRACT_TIME;
205
207
206
				r = archive_read_extract(a, entry, flags);
208
				r = archive_read_extract(a, entry, flags);
207
			}
209
			}
208
210
209
			if (r)
211
			if (r) {
210
				bsdar_warnc(bsdar, archive_errno(a), "%s",
212
				bsdar_warnc(bsdar, archive_errno(a), "%s",
211
				    archive_error_string(a));
213
				    archive_error_string(a));
214
				exitcode = EXIT_FAILURE;
215
			}
212
		}
216
		}
213
	}
217
	}
214
	AC(archive_read_close(a));
218
	AC(archive_read_close(a));
215
	AC(archive_read_free(a));
219
	AC(archive_read_free(a));
220
221
	return (exitcode);
216
}
222
}
(-)b/usr.bin/ar/write.c (-20 / +29 lines)
Lines 1-952 Link Here
1
/*-
1
/*-
2
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
2
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3
 *
3
 *
4
 * Copyright (c) 2007 Kai Wang
4
 * Copyright (c) 2007 Kai Wang
5
 * All rights reserved.
5
 * All rights reserved.
6
 *
6
 *
7
 * Redistribution and use in source and binary forms, with or without
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
8
 * modification, are permitted provided that the following conditions
9
 * are met:
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
14
 *    documentation and/or other materials provided with the distribution.
15
 *
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
26
 * SUCH DAMAGE.
27
 */
27
 */
28
28
29
#include <sys/cdefs.h>
29
#include <sys/cdefs.h>
30
__FBSDID("$FreeBSD$");
30
__FBSDID("$FreeBSD$");
31
31
32
#include <sys/endian.h>
32
#include <sys/endian.h>
33
#include <sys/mman.h>
33
#include <sys/mman.h>
34
#include <sys/queue.h>
34
#include <sys/queue.h>
35
#include <sys/stat.h>
35
#include <sys/stat.h>
36
#include <archive.h>
36
#include <archive.h>
37
#include <archive_entry.h>
37
#include <archive_entry.h>
38
#include <errno.h>
38
#include <errno.h>
39
#include <fcntl.h>
39
#include <fcntl.h>
40
#include <gelf.h>
40
#include <gelf.h>
41
#include <libgen.h>
41
#include <libgen.h>
42
#include <stdio.h>
42
#include <stdio.h>
43
#include <stdlib.h>
43
#include <stdlib.h>
44
#include <string.h>
44
#include <string.h>
45
#include <sysexits.h>
45
#include <sysexits.h>
46
#include <unistd.h>
46
#include <unistd.h>
47
47
48
#include "ar.h"
48
#include "ar.h"
49
49
50
#define _ARMAG_LEN 8		/* length of ar magic string */
50
#define _ARMAG_LEN 8		/* length of ar magic string */
51
#define _ARHDR_LEN 60		/* length of ar header */
51
#define _ARHDR_LEN 60		/* length of ar header */
52
#define _INIT_AS_CAP 128	/* initial archive string table size */
52
#define _INIT_AS_CAP 128	/* initial archive string table size */
53
#define _INIT_SYMOFF_CAP (256*(sizeof(uint64_t))) /* initial so table size */
53
#define _INIT_SYMOFF_CAP (256*(sizeof(uint64_t))) /* initial so table size */
54
#define _INIT_SYMNAME_CAP 1024			  /* initial sn table size */
54
#define _INIT_SYMNAME_CAP 1024			  /* initial sn table size */
55
#define _MAXNAMELEN_SVR4 15	/* max member name length in svr4 variant */
55
#define _MAXNAMELEN_SVR4 15	/* max member name length in svr4 variant */
56
#define _TRUNCATE_LEN 15	/* number of bytes to keep for member name */
56
#define _TRUNCATE_LEN 15	/* number of bytes to keep for member name */
57
57
58
static void	add_to_ar_str_table(struct bsdar *bsdar, const char *name);
58
static void	add_to_ar_str_table(struct bsdar *bsdar, const char *name);
59
static void	add_to_ar_sym_table(struct bsdar *bsdar, const char *name);
59
static void	add_to_ar_sym_table(struct bsdar *bsdar, const char *name);
60
static struct ar_obj	*create_obj_from_file(struct bsdar *bsdar,
60
static struct ar_obj	*create_obj_from_file(struct bsdar *bsdar,
61
		    const char *name, time_t mtime);
61
		    const char *name, time_t mtime);
62
static void	create_symtab_entry(struct bsdar *bsdar, void *maddr,
62
static void	create_symtab_entry(struct bsdar *bsdar, void *maddr,
63
		    size_t size);
63
		    size_t size);
64
static void	free_obj(struct bsdar *bsdar, struct ar_obj *obj);
64
static void	free_obj(struct bsdar *bsdar, struct ar_obj *obj);
65
static void	insert_obj(struct bsdar *bsdar, struct ar_obj *obj,
65
static void	insert_obj(struct bsdar *bsdar, struct ar_obj *obj,
66
		    struct ar_obj *pos);
66
		    struct ar_obj *pos);
67
static void	prefault_buffer(const char *buf, size_t s);
67
static void	prefault_buffer(const char *buf, size_t s);
68
static void	read_objs(struct bsdar *bsdar, const char *archive,
68
static void	read_objs(struct bsdar *bsdar, const char *archive,
69
		    int checkargv);
69
		    int checkargv);
70
static void	write_archive(struct bsdar *bsdar, char mode);
70
static int	write_archive(struct bsdar *bsdar, char mode);
71
static void	write_cleanup(struct bsdar *bsdar);
71
static void	write_cleanup(struct bsdar *bsdar);
72
static void	write_data(struct bsdar *bsdar, struct archive *a,
72
static void	write_data(struct bsdar *bsdar, struct archive *a,
73
		    const void *buf, size_t s);
73
		    const void *buf, size_t s);
74
static void	write_objs(struct bsdar *bsdar);
74
static void	write_objs(struct bsdar *bsdar);
75
75
76
void
76
int
77
ar_mode_d(struct bsdar *bsdar)
77
ar_mode_d(struct bsdar *bsdar)
78
{
78
{
79
79
80
	write_archive(bsdar, 'd');
80
	return (write_archive(bsdar, 'd'));
81
}
81
}
82
82
83
void
83
int
84
ar_mode_m(struct bsdar *bsdar)
84
ar_mode_m(struct bsdar *bsdar)
85
{
85
{
86
86
87
	write_archive(bsdar, 'm');
87
	return (write_archive(bsdar, 'm'));
88
}
88
}
89
89
90
void
90
int
91
ar_mode_q(struct bsdar *bsdar)
91
ar_mode_q(struct bsdar *bsdar)
92
{
92
{
93
93
94
	write_archive(bsdar, 'q');
94
	return (write_archive(bsdar, 'q'));
95
}
95
}
96
96
97
void
97
int
98
ar_mode_r(struct bsdar *bsdar)
98
ar_mode_r(struct bsdar *bsdar)
99
{
99
{
100
100
101
	write_archive(bsdar, 'r');
101
	return (write_archive(bsdar, 'r'));
102
}
102
}
103
103
104
void
104
int
105
ar_mode_s(struct bsdar *bsdar)
105
ar_mode_s(struct bsdar *bsdar)
106
{
106
{
107
107
108
	write_archive(bsdar, 's');
108
	return (write_archive(bsdar, 's'));
109
}
109
}
110
110
111
void
111
int
112
ar_mode_A(struct bsdar *bsdar)
112
ar_mode_A(struct bsdar *bsdar)
113
{
113
{
114
114
115
	write_archive(bsdar, 'A');
115
	return (write_archive(bsdar, 'A'));
116
}
116
}
117
117
118
/*
118
/*
119
 * Create object from file, return created obj upon success, or NULL
119
 * Create object from file, return created obj upon success, or NULL
120
 * when an error occurs or the member is not newer than existing
120
 * when an error occurs or the member is not newer than existing
121
 * one while -u is specified.
121
 * one while -u is specified.
122
 */
122
 */
123
static struct ar_obj *
123
static struct ar_obj *
124
create_obj_from_file(struct bsdar *bsdar, const char *name, time_t mtime)
124
create_obj_from_file(struct bsdar *bsdar, const char *name, time_t mtime)
125
{
125
{
126
	struct ar_obj		*obj;
126
	struct ar_obj		*obj;
127
	struct stat		 sb;
127
	struct stat		 sb;
128
	const char		*bname;
128
	const char		*bname;
129
	char			*tmpname;
129
	char			*tmpname;
130
130
131
	if (name == NULL)
131
	if (name == NULL)
132
		return (NULL);
132
		return (NULL);
133
133
134
	obj = malloc(sizeof(struct ar_obj));
134
	obj = malloc(sizeof(struct ar_obj));
135
	if (obj == NULL)
135
	if (obj == NULL)
136
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
136
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
137
	if ((obj->fd = open(name, O_RDONLY, 0)) < 0) {
137
	if ((obj->fd = open(name, O_RDONLY, 0)) < 0) {
138
		bsdar_warnc(bsdar, errno, "can't open file: %s", name);
138
		bsdar_warnc(bsdar, errno, "can't open file: %s", name);
139
		free(obj);
139
		free(obj);
140
		return (NULL);
140
		return (NULL);
141
	}
141
	}
142
142
143
	tmpname = strdup(name);
143
	tmpname = strdup(name);
144
	if (tmpname == NULL)
144
	if (tmpname == NULL)
145
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed");
145
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed");
146
	if ((bname = basename(tmpname)) == NULL)
146
	if ((bname = basename(tmpname)) == NULL)
147
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "basename failed");
147
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "basename failed");
148
	if (bsdar->options & AR_TR && strlen(bname) > _TRUNCATE_LEN) {
148
	if (bsdar->options & AR_TR && strlen(bname) > _TRUNCATE_LEN) {
149
		if ((obj->name = malloc(_TRUNCATE_LEN + 1)) == NULL)
149
		if ((obj->name = malloc(_TRUNCATE_LEN + 1)) == NULL)
150
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
150
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
151
		(void)strncpy(obj->name, bname, _TRUNCATE_LEN);
151
		(void)strncpy(obj->name, bname, _TRUNCATE_LEN);
152
		obj->name[_TRUNCATE_LEN] = '\0';
152
		obj->name[_TRUNCATE_LEN] = '\0';
153
	} else
153
	} else
154
		if ((obj->name = strdup(bname)) == NULL)
154
		if ((obj->name = strdup(bname)) == NULL)
155
		    bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed");
155
		    bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed");
156
	free(tmpname);
156
	free(tmpname);
157
157
158
	if (fstat(obj->fd, &sb) < 0) {
158
	if (fstat(obj->fd, &sb) < 0) {
159
		bsdar_warnc(bsdar, errno, "can't fstat file: %s", obj->name);
159
		bsdar_warnc(bsdar, errno, "can't fstat file: %s", obj->name);
160
		goto giveup;
160
		goto giveup;
161
	}
161
	}
162
	if (!S_ISREG(sb.st_mode)) {
162
	if (!S_ISREG(sb.st_mode)) {
163
		bsdar_warnc(bsdar, 0, "%s is not an ordinary file", obj->name);
163
		bsdar_warnc(bsdar, 0, "%s is not an ordinary file", obj->name);
164
		goto giveup;
164
		goto giveup;
165
	}
165
	}
166
166
167
	/*
167
	/*
168
	 * When option '-u' is specified and member is not newer than the
168
	 * When option '-u' is specified and member is not newer than the
169
	 * existing one, the replace will not happen. While if mtime == 0,
169
	 * existing one, the replace will not happen. While if mtime == 0,
170
	 * which indicates that this is to "replace a none exist member",
170
	 * which indicates that this is to "replace a none exist member",
171
	 * the replace will proceed regardless of '-u'.
171
	 * the replace will proceed regardless of '-u'.
172
	 */
172
	 */
173
	if (mtime != 0 && bsdar->options & AR_U && sb.st_mtime <= mtime)
173
	if (mtime != 0 && bsdar->options & AR_U && sb.st_mtime <= mtime)
174
		goto giveup;
174
		goto giveup;
175
175
176
	/*
176
	/*
177
	 * When option '-D' is specified, mtime and UID / GID from the file
177
	 * When option '-D' is specified, mtime and UID / GID from the file
178
	 * will be replaced with 0, and file mode with 644. This ensures that
178
	 * will be replaced with 0, and file mode with 644. This ensures that
179
	 * checksums will match for two archives containing the exact same
179
	 * checksums will match for two archives containing the exact same
180
	 * files.
180
	 * files.
181
	 */
181
	 */
182
	if (bsdar->options & AR_D) {
182
	if (bsdar->options & AR_D) {
183
		obj->uid = 0;
183
		obj->uid = 0;
184
		obj->gid = 0;
184
		obj->gid = 0;
185
		obj->mtime = 0;
185
		obj->mtime = 0;
186
		obj->md = S_IFREG | 0644;
186
		obj->md = S_IFREG | 0644;
187
	} else {
187
	} else {
188
		obj->uid = sb.st_uid;
188
		obj->uid = sb.st_uid;
189
		obj->gid = sb.st_gid;
189
		obj->gid = sb.st_gid;
190
		obj->mtime = sb.st_mtime;
190
		obj->mtime = sb.st_mtime;
191
		obj->md = sb.st_mode;
191
		obj->md = sb.st_mode;
192
	}
192
	}
193
	obj->size = sb.st_size;
193
	obj->size = sb.st_size;
194
	obj->dev = sb.st_dev;
194
	obj->dev = sb.st_dev;
195
	obj->ino = sb.st_ino;
195
	obj->ino = sb.st_ino;
196
196
197
	if (obj->size == 0) {
197
	if (obj->size == 0) {
198
		obj->maddr = NULL;
198
		obj->maddr = NULL;
199
		return (obj);
199
		return (obj);
200
	}
200
	}
201
201
202
	if ((obj->maddr = mmap(NULL, obj->size, PROT_READ,
202
	if ((obj->maddr = mmap(NULL, obj->size, PROT_READ,
203
	    MAP_PRIVATE, obj->fd, (off_t)0)) == MAP_FAILED) {
203
	    MAP_PRIVATE, obj->fd, (off_t)0)) == MAP_FAILED) {
204
		bsdar_warnc(bsdar, errno, "can't mmap file: %s", obj->name);
204
		bsdar_warnc(bsdar, errno, "can't mmap file: %s", obj->name);
205
		goto giveup;
205
		goto giveup;
206
	}
206
	}
207
	if (close(obj->fd) < 0)
207
	if (close(obj->fd) < 0)
208
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "close failed: %s",
208
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "close failed: %s",
209
		    obj->name);
209
		    obj->name);
210
210
211
	return (obj);
211
	return (obj);
212
212
213
giveup:
213
giveup:
214
	if (close(obj->fd) < 0)
214
	if (close(obj->fd) < 0)
215
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "close failed: %s",
215
		bsdar_errc(bsdar, EX_SOFTWARE, errno, "close failed: %s",
216
		    obj->name);
216
		    obj->name);
217
	free(obj->name);
217
	free(obj->name);
218
	free(obj);
218
	free(obj);
219
	return (NULL);
219
	return (NULL);
220
}
220
}
221
221
222
/*
222
/*
223
 * Free object itself and its associated allocations.
223
 * Free object itself and its associated allocations.
224
 */
224
 */
225
static void
225
static void
226
free_obj(struct bsdar *bsdar, struct ar_obj *obj)
226
free_obj(struct bsdar *bsdar, struct ar_obj *obj)
227
{
227
{
228
	if (obj->fd == -1)
228
	if (obj->fd == -1)
229
		free(obj->maddr);
229
		free(obj->maddr);
230
	else
230
	else
231
		if (obj->maddr != NULL && munmap(obj->maddr, obj->size))
231
		if (obj->maddr != NULL && munmap(obj->maddr, obj->size))
232
			bsdar_warnc(bsdar, errno,
232
			bsdar_warnc(bsdar, errno,
233
			    "can't munmap file: %s", obj->name);
233
			    "can't munmap file: %s", obj->name);
234
	free(obj->name);
234
	free(obj->name);
235
	free(obj);
235
	free(obj);
236
}
236
}
237
237
238
/*
238
/*
239
 * Insert obj to the tail, or before/after the pos obj.
239
 * Insert obj to the tail, or before/after the pos obj.
240
 */
240
 */
241
static void
241
static void
242
insert_obj(struct bsdar *bsdar, struct ar_obj *obj, struct ar_obj *pos)
242
insert_obj(struct bsdar *bsdar, struct ar_obj *obj, struct ar_obj *pos)
243
{
243
{
244
	if (obj == NULL)
244
	if (obj == NULL)
245
		bsdar_errc(bsdar, EX_SOFTWARE, 0, "try to insert a null obj");
245
		bsdar_errc(bsdar, EX_SOFTWARE, 0, "try to insert a null obj");
246
246
247
	if (pos == NULL || obj == pos)
247
	if (pos == NULL || obj == pos)
248
		/*
248
		/*
249
		 * If the object to move happens to be the position obj,
249
		 * If the object to move happens to be the position obj,
250
		 * or if there is not a pos obj, move it to tail.
250
		 * or if there is not a pos obj, move it to tail.
251
		 */
251
		 */
252
		goto tail;
252
		goto tail;
253
253
254
	if (bsdar->options & AR_B) {
254
	if (bsdar->options & AR_B) {
255
		TAILQ_INSERT_BEFORE(pos, obj, objs);
255
		TAILQ_INSERT_BEFORE(pos, obj, objs);
256
		return;
256
		return;
257
	}
257
	}
258
	if (bsdar->options & AR_A) {
258
	if (bsdar->options & AR_A) {
259
		TAILQ_INSERT_AFTER(&bsdar->v_obj, pos, obj, objs);
259
		TAILQ_INSERT_AFTER(&bsdar->v_obj, pos, obj, objs);
260
		return;
260
		return;
261
	}
261
	}
262
262
263
tail:
263
tail:
264
	TAILQ_INSERT_TAIL(&bsdar->v_obj, obj, objs);
264
	TAILQ_INSERT_TAIL(&bsdar->v_obj, obj, objs);
265
265
266
}
266
}
267
267
268
/*
268
/*
269
 * Read objects from archive into v_obj list. Note that checkargv is
269
 * Read objects from archive into v_obj list. Note that checkargv is
270
 * set when read_objs is used to read objects from the target of
270
 * set when read_objs is used to read objects from the target of
271
 * ADDLIB command (ar script mode), in this case argv array possibly
271
 * ADDLIB command (ar script mode), in this case argv array possibly
272
 * specifies the members ADDLIB want.
272
 * specifies the members ADDLIB want.
273
 */
273
 */
274
static void
274
static void
275
read_objs(struct bsdar *bsdar, const char *archive, int checkargv)
275
read_objs(struct bsdar *bsdar, const char *archive, int checkargv)
276
{
276
{
277
	struct archive		 *a;
277
	struct archive		 *a;
278
	struct archive_entry	 *entry;
278
	struct archive_entry	 *entry;
279
	struct ar_obj		 *obj;
279
	struct ar_obj		 *obj;
280
	const char		 *name;
280
	const char		 *name;
281
	const char		 *bname;
281
	const char		 *bname;
282
	char			 *buff;
282
	char			 *buff;
283
	char			**av;
283
	char			**av;
284
	size_t			  size;
284
	size_t			  size;
285
	int			  i, r, find;
285
	int			  i, r, find;
286
286
287
	if ((a = archive_read_new()) == NULL)
287
	if ((a = archive_read_new()) == NULL)
288
		bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_read_new failed");
288
		bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_read_new failed");
289
	archive_read_support_format_ar(a);
289
	archive_read_support_format_ar(a);
290
	AC(archive_read_open_filename(a, archive, DEF_BLKSZ));
290
	AC(archive_read_open_filename(a, archive, DEF_BLKSZ));
291
	for (;;) {
291
	for (;;) {
292
		r = archive_read_next_header(a, &entry);
292
		r = archive_read_next_header(a, &entry);
293
		if (r == ARCHIVE_FATAL)
293
		if (r == ARCHIVE_FATAL)
294
			bsdar_errc(bsdar, EX_DATAERR, archive_errno(a), "%s",
294
			bsdar_errc(bsdar, EX_DATAERR, archive_errno(a), "%s",
295
			    archive_error_string(a));
295
			    archive_error_string(a));
296
		if (r == ARCHIVE_EOF)
296
		if (r == ARCHIVE_EOF)
297
			break;
297
			break;
298
		if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY)
298
		if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY)
299
			bsdar_warnc(bsdar, archive_errno(a), "%s",
299
			bsdar_warnc(bsdar, archive_errno(a), "%s",
300
			    archive_error_string(a));
300
			    archive_error_string(a));
301
		if (r == ARCHIVE_RETRY) {
301
		if (r == ARCHIVE_RETRY) {
302
			bsdar_warnc(bsdar, 0, "Retrying...");
302
			bsdar_warnc(bsdar, 0, "Retrying...");
303
			continue;
303
			continue;
304
		}
304
		}
305
305
306
		name = archive_entry_pathname(entry);
306
		name = archive_entry_pathname(entry);
307
307
308
		/*
308
		/*
309
		 * skip pseudo members.
309
		 * skip pseudo members.
310
		 */
310
		 */
311
		if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0)
311
		if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0)
312
			continue;
312
			continue;
313
313
314
		/*
314
		/*
315
		 * If checkargv is set, only read those members specified
315
		 * If checkargv is set, only read those members specified
316
		 * in argv.
316
		 * in argv.
317
		 */
317
		 */
318
		if (checkargv && bsdar->argc > 0) {
318
		if (checkargv && bsdar->argc > 0) {
319
			find = 0;
319
			find = 0;
320
			for(i = 0; i < bsdar->argc; i++) {
320
			for(i = 0; i < bsdar->argc; i++) {
321
				av = &bsdar->argv[i];
321
				av = &bsdar->argv[i];
322
				if (*av == NULL)
322
				if (*av == NULL)
323
					continue;
323
					continue;
324
				if ((bname = basename(*av)) == NULL)
324
				if ((bname = basename(*av)) == NULL)
325
					bsdar_errc(bsdar, EX_SOFTWARE, errno,
325
					bsdar_errc(bsdar, EX_SOFTWARE, errno,
326
					    "basename failed");
326
					    "basename failed");
327
				if (strcmp(bname, name) != 0)
327
				if (strcmp(bname, name) != 0)
328
					continue;
328
					continue;
329
329
330
				*av = NULL;
330
				*av = NULL;
331
				find = 1;
331
				find = 1;
332
				break;
332
				break;
333
			}
333
			}
334
			if (!find)
334
			if (!find)
335
				continue;
335
				continue;
336
		}
336
		}
337
337
338
		size = archive_entry_size(entry);
338
		size = archive_entry_size(entry);
339
339
340
		if (size > 0) {
340
		if (size > 0) {
341
			if ((buff = malloc(size)) == NULL)
341
			if ((buff = malloc(size)) == NULL)
342
				bsdar_errc(bsdar, EX_SOFTWARE, errno,
342
				bsdar_errc(bsdar, EX_SOFTWARE, errno,
343
				    "malloc failed");
343
				    "malloc failed");
344
			if (archive_read_data(a, buff, size) != (ssize_t)size) {
344
			if (archive_read_data(a, buff, size) != (ssize_t)size) {
345
				bsdar_warnc(bsdar, archive_errno(a), "%s",
345
				bsdar_warnc(bsdar, archive_errno(a), "%s",
346
				    archive_error_string(a));
346
				    archive_error_string(a));
347
				free(buff);
347
				free(buff);
348
				continue;
348
				continue;
349
			}
349
			}
350
		} else
350
		} else
351
			buff = NULL;
351
			buff = NULL;
352
352
353
		obj = malloc(sizeof(struct ar_obj));
353
		obj = malloc(sizeof(struct ar_obj));
354
		if (obj == NULL)
354
		if (obj == NULL)
355
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
355
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
356
		obj->maddr = buff;
356
		obj->maddr = buff;
357
		if ((obj->name = strdup(name)) == NULL)
357
		if ((obj->name = strdup(name)) == NULL)
358
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed");
358
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed");
359
		obj->size = size;
359
		obj->size = size;
360
		obj->uid = archive_entry_uid(entry);
360
		obj->uid = archive_entry_uid(entry);
361
		obj->gid = archive_entry_gid(entry);
361
		obj->gid = archive_entry_gid(entry);
362
		obj->md = archive_entry_mode(entry);
362
		obj->md = archive_entry_mode(entry);
363
		obj->mtime = archive_entry_mtime(entry);
363
		obj->mtime = archive_entry_mtime(entry);
364
		obj->dev = 0;
364
		obj->dev = 0;
365
		obj->ino = 0;
365
		obj->ino = 0;
366
366
367
		/*
367
		/*
368
		 * Objects from archive have obj->fd set to -1,
368
		 * Objects from archive have obj->fd set to -1,
369
		 * for the ease of cleaning up.
369
		 * for the ease of cleaning up.
370
		 */
370
		 */
371
		obj->fd = -1;
371
		obj->fd = -1;
372
		TAILQ_INSERT_TAIL(&bsdar->v_obj, obj, objs);
372
		TAILQ_INSERT_TAIL(&bsdar->v_obj, obj, objs);
373
	}
373
	}
374
	AC(archive_read_close(a));
374
	AC(archive_read_close(a));
375
	AC(archive_read_free(a));
375
	AC(archive_read_free(a));
376
}
376
}
377
377
378
/*
378
/*
379
 * Determine the constitution of resulting archive.
379
 * Determine the constitution of resulting archive.
380
 */
380
 */
381
static void
381
static int
382
write_archive(struct bsdar *bsdar, char mode)
382
write_archive(struct bsdar *bsdar, char mode)
383
{
383
{
384
	struct ar_obj		 *nobj, *obj, *obj_temp, *pos;
384
	struct ar_obj		 *nobj, *obj, *obj_temp, *pos;
385
	struct stat		  sb;
385
	struct stat		  sb;
386
	const char		 *bname;
386
	const char		 *bname;
387
	char			**av;
387
	char			**av;
388
	int			  i;
388
	int			  exitcode, i;
389
389
390
	TAILQ_INIT(&bsdar->v_obj);
390
	TAILQ_INIT(&bsdar->v_obj);
391
	exitcode = EXIT_SUCCESS;
391
	nobj = NULL;
392
	nobj = NULL;
392
	pos = NULL;
393
	pos = NULL;
393
	memset(&sb, 0, sizeof(sb));
394
	memset(&sb, 0, sizeof(sb));
394
395
395
	/*
396
	/*
396
	 * Test if the specified archive exists, to figure out
397
	 * Test if the specified archive exists, to figure out
397
	 * whether we are creating one here.
398
	 * whether we are creating one here.
398
	 */
399
	 */
399
	if (stat(bsdar->filename, &sb) != 0) {
400
	if (stat(bsdar->filename, &sb) != 0) {
400
		if (errno != ENOENT) {
401
		if (errno != ENOENT) {
401
			bsdar_warnc(bsdar, 0, "stat %s failed",
402
			bsdar_warnc(bsdar, 0, "stat %s failed",
402
			    bsdar->filename);
403
			    bsdar->filename);
403
			return;
404
			return (EXIT_FAILURE);
404
		}
405
		}
405
406
406
		/* We do not create archive in mode 'd', 'm' and 's'.  */
407
		/* We do not create archive in mode 'd', 'm' and 's'.  */
407
		if (mode != 'r' && mode != 'q') {
408
		if (mode != 'r' && mode != 'q') {
408
			bsdar_warnc(bsdar, 0, "%s: no such file",
409
			bsdar_warnc(bsdar, 0, "%s: no such file",
409
			    bsdar->filename);
410
			    bsdar->filename);
410
			return;
411
			return (EXIT_FAILURE);
411
		}
412
		}
412
413
413
		/* Issue a warning if -c is not specified when creating. */
414
		/* Issue a warning if -c is not specified when creating. */
414
		if (!(bsdar->options & AR_C))
415
		if (!(bsdar->options & AR_C))
415
			bsdar_warnc(bsdar, 0, "creating %s", bsdar->filename);
416
			bsdar_warnc(bsdar, 0, "creating %s", bsdar->filename);
416
		goto new_archive;
417
		goto new_archive;
417
	}
418
	}
418
419
419
	/*
420
	/*
420
	 * First read members from existing archive.
421
	 * First read members from existing archive.
421
	 */
422
	 */
422
	read_objs(bsdar, bsdar->filename, 0);
423
	read_objs(bsdar, bsdar->filename, 0);
423
424
424
	/*
425
	/*
425
	 * For mode 's', no member will be moved, deleted or replaced.
426
	 * For mode 's', no member will be moved, deleted or replaced.
426
	 */
427
	 */
427
	if (mode == 's')
428
	if (mode == 's')
428
		goto write_objs;
429
		goto write_objs;
429
430
430
	/*
431
	/*
431
	 * For mode 'q', we don't need to adjust existing members either.
432
	 * For mode 'q', we don't need to adjust existing members either.
432
	 * Also, -a, -b and -i are ignored in this mode. New members are
433
	 * Also, -a, -b and -i are ignored in this mode. New members are
433
	 * always inserted at tail.
434
	 * always inserted at tail.
434
	 */
435
	 */
435
	if (mode == 'q')
436
	if (mode == 'q')
436
		goto new_archive;
437
		goto new_archive;
437
438
438
	/*
439
	/*
439
	 * Mode 'A' adds the contents of another archive to the tail of
440
	 * Mode 'A' adds the contents of another archive to the tail of
440
	 * current archive. Note that mode 'A' is a special mode for the
441
	 * current archive. Note that mode 'A' is a special mode for the
441
	 * ADDLIB command of the ar script mode. Currently there is no
442
	 * ADDLIB command of the ar script mode. Currently there is no
442
	 * access to this function from the ar command line mode.
443
	 * access to this function from the ar command line mode.
443
	 */
444
	 */
444
	if (mode == 'A') {
445
	if (mode == 'A') {
445
		/*
446
		/*
446
		 * Read objects from the target archive of ADDLIB command.
447
		 * Read objects from the target archive of ADDLIB command.
447
		 * If there are members specified in argv, read those members
448
		 * If there are members specified in argv, read those members
448
		 * only, otherwise the entire archive will be read.
449
		 * only, otherwise the entire archive will be read.
449
		 */
450
		 */
450
		read_objs(bsdar, bsdar->addlib, 1);
451
		read_objs(bsdar, bsdar->addlib, 1);
451
		goto write_objs;
452
		goto write_objs;
452
	}
453
	}
453
454
454
	/*
455
	/*
455
	 * Try to find the position member specified by user.
456
	 * Try to find the position member specified by user.
456
	 */
457
	 */
457
	if (bsdar->options & AR_A || bsdar->options & AR_B) {
458
	if (bsdar->options & AR_A || bsdar->options & AR_B) {
458
		TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
459
		TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
459
			if (strcmp(obj->name, bsdar->posarg) == 0) {
460
			if (strcmp(obj->name, bsdar->posarg) == 0) {
460
				pos = obj;
461
				pos = obj;
461
				break;
462
				break;
462
			}
463
			}
463
		}
464
		}
464
465
465
		/*
466
		/*
466
		 * If can't find `pos' specified by user,
467
		 * If can't find `pos' specified by user,
467
		 * silently insert objects at tail.
468
		 * silently insert objects at tail.
468
		 */
469
		 */
469
		if (pos == NULL)
470
		if (pos == NULL)
470
			bsdar->options &= ~(AR_A | AR_B);
471
			bsdar->options &= ~(AR_A | AR_B);
471
	}
472
	}
472
473
473
	for (i = 0; i < bsdar->argc; i++) {
474
	for (i = 0; i < bsdar->argc; i++) {
474
		av = &bsdar->argv[i];
475
		av = &bsdar->argv[i];
475
476
476
		TAILQ_FOREACH_SAFE(obj, &bsdar->v_obj, objs, obj_temp) {
477
		TAILQ_FOREACH_SAFE(obj, &bsdar->v_obj, objs, obj_temp) {
477
			if ((bname = basename(*av)) == NULL)
478
			if ((bname = basename(*av)) == NULL)
478
				bsdar_errc(bsdar, EX_SOFTWARE, errno,
479
				bsdar_errc(bsdar, EX_SOFTWARE, errno,
479
				    "basename failed");
480
				    "basename failed");
480
			if (bsdar->options & AR_TR) {
481
			if (bsdar->options & AR_TR) {
481
				if (strncmp(bname, obj->name, _TRUNCATE_LEN))
482
				if (strncmp(bname, obj->name, _TRUNCATE_LEN))
482
					continue;
483
					continue;
483
			} else
484
			} else
484
				if (strcmp(bname, obj->name) != 0)
485
				if (strcmp(bname, obj->name) != 0)
485
					continue;
486
					continue;
486
487
487
			if (mode == 'r') {
488
			if (mode == 'r') {
488
				/*
489
				/*
489
				 * if the new member is not qualified
490
				 * if the new member is not qualified
490
				 * to replace the old one, skip it.
491
				 * to replace the old one, skip it.
491
				 */
492
				 */
492
				nobj = create_obj_from_file(bsdar, *av,
493
				nobj = create_obj_from_file(bsdar, *av,
493
				    obj->mtime);
494
				    obj->mtime);
494
				if (nobj == NULL)
495
				if (nobj == NULL) {
496
					exitcode = EXIT_FAILURE;
495
					goto skip_obj;
497
					goto skip_obj;
498
				}
496
			}
499
			}
497
500
498
			if (bsdar->options & AR_V)
501
			if (bsdar->options & AR_V)
499
				(void)fprintf(stdout, "%c - %s\n", mode,
502
				(void)fprintf(stdout, "%c - %s\n", mode,
500
				    *av);
503
				    *av);
501
504
502
			TAILQ_REMOVE(&bsdar->v_obj, obj, objs);
505
			TAILQ_REMOVE(&bsdar->v_obj, obj, objs);
503
			if (mode == 'd' || mode == 'r')
506
			if (mode == 'd' || mode == 'r')
504
				free_obj(bsdar, obj);
507
				free_obj(bsdar, obj);
505
508
506
			if (mode == 'm')
509
			if (mode == 'm')
507
				insert_obj(bsdar, obj, pos);
510
				insert_obj(bsdar, obj, pos);
508
			if (mode == 'r')
511
			if (mode == 'r')
509
				insert_obj(bsdar, nobj, pos);
512
				insert_obj(bsdar, nobj, pos);
510
513
511
		skip_obj:
514
		skip_obj:
512
			*av = NULL;
515
			*av = NULL;
513
			break;
516
			break;
514
		}
517
		}
515
518
516
	}
519
	}
517
520
518
new_archive:
521
new_archive:
519
	/*
522
	/*
520
	 * When operating in mode 'r', directly add those user specified
523
	 * When operating in mode 'r', directly add those user specified
521
	 * objects which do not exist in current archive. When operating
524
	 * objects which do not exist in current archive. When operating
522
	 * in mode 'q', all objects specified in command line args are
525
	 * in mode 'q', all objects specified in command line args are
523
	 * appended to the archive, without comparing with existing ones.
526
	 * appended to the archive, without comparing with existing ones.
524
	 */
527
	 */
525
	for (i = 0; i < bsdar->argc; i++) {
528
	for (i = 0; i < bsdar->argc; i++) {
526
		av = &bsdar->argv[i];
529
		av = &bsdar->argv[i];
527
		if (*av != NULL && (mode == 'r' || mode == 'q')) {
530
		if (*av != NULL && (mode == 'r' || mode == 'q')) {
528
			nobj = create_obj_from_file(bsdar, *av, 0);
531
			nobj = create_obj_from_file(bsdar, *av, 0);
529
			if (nobj != NULL)
532
			if (nobj == NULL) {
530
				insert_obj(bsdar, nobj, pos);
533
				exitcode = EXIT_FAILURE;
534
				*av = NULL;
535
				continue;
536
			}
537
			insert_obj(bsdar, nobj, pos);
531
			if (bsdar->options & AR_V && nobj != NULL)
538
			if (bsdar->options & AR_V && nobj != NULL)
532
				(void)fprintf(stdout, "a - %s\n", *av);
539
				(void)fprintf(stdout, "a - %s\n", *av);
533
			*av = NULL;
540
			*av = NULL;
534
		}
541
		}
535
	}
542
	}
536
543
537
write_objs:
544
write_objs:
538
	write_objs(bsdar);
545
	write_objs(bsdar);
539
	write_cleanup(bsdar);
546
	write_cleanup(bsdar);
547
548
	return (exitcode);
540
}
549
}
541
550
542
/*
551
/*
543
 * Memory cleaning up.
552
 * Memory cleaning up.
544
 */
553
 */
545
static void
554
static void
546
write_cleanup(struct bsdar *bsdar)
555
write_cleanup(struct bsdar *bsdar)
547
{
556
{
548
	struct ar_obj		*obj, *obj_temp;
557
	struct ar_obj		*obj, *obj_temp;
549
558
550
	TAILQ_FOREACH_SAFE(obj, &bsdar->v_obj, objs, obj_temp) {
559
	TAILQ_FOREACH_SAFE(obj, &bsdar->v_obj, objs, obj_temp) {
551
		TAILQ_REMOVE(&bsdar->v_obj, obj, objs);
560
		TAILQ_REMOVE(&bsdar->v_obj, obj, objs);
552
		free_obj(bsdar, obj);
561
		free_obj(bsdar, obj);
553
	}
562
	}
554
563
555
	free(bsdar->as);
564
	free(bsdar->as);
556
	free(bsdar->s_so);
565
	free(bsdar->s_so);
557
	free(bsdar->s_sn);
566
	free(bsdar->s_sn);
558
	bsdar->as = NULL;
567
	bsdar->as = NULL;
559
	bsdar->s_so = NULL;
568
	bsdar->s_so = NULL;
560
	bsdar->s_so_max = 0;
569
	bsdar->s_so_max = 0;
561
	bsdar->s_sn = NULL;
570
	bsdar->s_sn = NULL;
562
}
571
}
563
572
564
/*
573
/*
565
 * Fault in the buffer prior to writing as a workaround for poor performance
574
 * Fault in the buffer prior to writing as a workaround for poor performance
566
 * due to interaction with kernel fs deadlock avoidance code. See the comment
575
 * due to interaction with kernel fs deadlock avoidance code. See the comment
567
 * above vn_io_fault_doio() in sys/kern/vfs_vnops.c for details of the issue.
576
 * above vn_io_fault_doio() in sys/kern/vfs_vnops.c for details of the issue.
568
 */
577
 */
569
static void
578
static void
570
prefault_buffer(const char *buf, size_t s)
579
prefault_buffer(const char *buf, size_t s)
571
{
580
{
572
	volatile const char *p;
581
	volatile const char *p;
573
	size_t page_size;
582
	size_t page_size;
574
583
575
	if (s == 0)
584
	if (s == 0)
576
		return;
585
		return;
577
	page_size = sysconf(_SC_PAGESIZE);
586
	page_size = sysconf(_SC_PAGESIZE);
578
	for (p = buf; p < buf + s; p += page_size)
587
	for (p = buf; p < buf + s; p += page_size)
579
		*p;
588
		*p;
580
	/*
589
	/*
581
	 * Ensure we touch the last page as well, in case the buffer is not
590
	 * Ensure we touch the last page as well, in case the buffer is not
582
	 * page-aligned.
591
	 * page-aligned.
583
	 */
592
	 */
584
	*(volatile const char *)(buf + s - 1);
593
	*(volatile const char *)(buf + s - 1);
585
}
594
}
586
595
587
/*
596
/*
588
 * Wrapper for archive_write_data().
597
 * Wrapper for archive_write_data().
589
 */
598
 */
590
static void
599
static void
591
write_data(struct bsdar *bsdar, struct archive *a, const void *buf, size_t s)
600
write_data(struct bsdar *bsdar, struct archive *a, const void *buf, size_t s)
592
{
601
{
593
	ssize_t written;
602
	ssize_t written;
594
603
595
	prefault_buffer(buf, s);
604
	prefault_buffer(buf, s);
596
	while (s > 0) {
605
	while (s > 0) {
597
		written = archive_write_data(a, buf, s);
606
		written = archive_write_data(a, buf, s);
598
		if (written < 0)
607
		if (written < 0)
599
			bsdar_errc(bsdar, EX_SOFTWARE, archive_errno(a), "%s",
608
			bsdar_errc(bsdar, EX_SOFTWARE, archive_errno(a), "%s",
600
			    archive_error_string(a));
609
			    archive_error_string(a));
601
		buf = (const char *)buf + written;
610
		buf = (const char *)buf + written;
602
		s -= written;
611
		s -= written;
603
	}
612
	}
604
}
613
}
605
614
606
/*
615
/*
607
 * Write the resulting archive members.
616
 * Write the resulting archive members.
608
 */
617
 */
609
static void
618
static void
610
write_objs(struct bsdar *bsdar)
619
write_objs(struct bsdar *bsdar)
611
{
620
{
612
	struct ar_obj		*obj;
621
	struct ar_obj		*obj;
613
	struct archive		*a;
622
	struct archive		*a;
614
	struct archive_entry	*entry;
623
	struct archive_entry	*entry;
615
	size_t s_sz;		/* size of archive symbol table. */
624
	size_t s_sz;		/* size of archive symbol table. */
616
	size_t pm_sz;		/* size of pseudo members */
625
	size_t pm_sz;		/* size of pseudo members */
617
	size_t w_sz;		/* size of words in symbol table */
626
	size_t w_sz;		/* size of words in symbol table */
618
	size_t			 i;
627
	size_t			 i;
619
	uint64_t		 nr;
628
	uint64_t		 nr;
620
	uint32_t		 nr32;
629
	uint32_t		 nr32;
621
630
622
	if (elf_version(EV_CURRENT) == EV_NONE)
631
	if (elf_version(EV_CURRENT) == EV_NONE)
623
		bsdar_errc(bsdar, EX_SOFTWARE, 0,
632
		bsdar_errc(bsdar, EX_SOFTWARE, 0,
624
		    "ELF library initialization failed: %s", elf_errmsg(-1));
633
		    "ELF library initialization failed: %s", elf_errmsg(-1));
625
634
626
	bsdar->rela_off = 0;
635
	bsdar->rela_off = 0;
627
636
628
	/* Create archive symbol table and archive string table, if need. */
637
	/* Create archive symbol table and archive string table, if need. */
629
	TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
638
	TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
630
		if (!(bsdar->options & AR_SS) && obj->maddr != NULL)
639
		if (!(bsdar->options & AR_SS) && obj->maddr != NULL)
631
			create_symtab_entry(bsdar, obj->maddr, obj->size);
640
			create_symtab_entry(bsdar, obj->maddr, obj->size);
632
		if (strlen(obj->name) > _MAXNAMELEN_SVR4)
641
		if (strlen(obj->name) > _MAXNAMELEN_SVR4)
633
			add_to_ar_str_table(bsdar, obj->name);
642
			add_to_ar_str_table(bsdar, obj->name);
634
		bsdar->rela_off += _ARHDR_LEN + obj->size + obj->size % 2;
643
		bsdar->rela_off += _ARHDR_LEN + obj->size + obj->size % 2;
635
	}
644
	}
636
645
637
	/*
646
	/*
638
	 * Pad the symbol name string table. It is treated specially because
647
	 * Pad the symbol name string table. It is treated specially because
639
	 * symbol name table should be padded by a '\0', not the common '\n'
648
	 * symbol name table should be padded by a '\0', not the common '\n'
640
	 * for other members. The size of sn table includes the pad bit.
649
	 * for other members. The size of sn table includes the pad bit.
641
	 */
650
	 */
642
	if (bsdar->s_cnt != 0 && bsdar->s_sn_sz % 2 != 0)
651
	if (bsdar->s_cnt != 0 && bsdar->s_sn_sz % 2 != 0)
643
		bsdar->s_sn[bsdar->s_sn_sz++] = '\0';
652
		bsdar->s_sn[bsdar->s_sn_sz++] = '\0';
644
653
645
	/*
654
	/*
646
	 * Archive string table is padded by a "\n" as the normal members.
655
	 * Archive string table is padded by a "\n" as the normal members.
647
	 * The difference is that the size of archive string table counts
656
	 * The difference is that the size of archive string table counts
648
	 * in the pad bit, while normal members' size fields do not.
657
	 * in the pad bit, while normal members' size fields do not.
649
	 */
658
	 */
650
	if (bsdar->as != NULL && bsdar->as_sz % 2 != 0)
659
	if (bsdar->as != NULL && bsdar->as_sz % 2 != 0)
651
		bsdar->as[bsdar->as_sz++] = '\n';
660
		bsdar->as[bsdar->as_sz++] = '\n';
652
661
653
	/*
662
	/*
654
	 * If there is a symbol table, calculate the size of pseudo members,
663
	 * If there is a symbol table, calculate the size of pseudo members,
655
	 * convert previously stored relative offsets to absolute ones, and
664
	 * convert previously stored relative offsets to absolute ones, and
656
	 * then make them Big Endian.
665
	 * then make them Big Endian.
657
	 *
666
	 *
658
	 * absolute_offset = htobe32(relative_offset + size_of_pseudo_members)
667
	 * absolute_offset = htobe32(relative_offset + size_of_pseudo_members)
659
	 */
668
	 */
660
	w_sz = sizeof(uint32_t);
669
	w_sz = sizeof(uint32_t);
661
	if (bsdar->s_cnt != 0) {
670
	if (bsdar->s_cnt != 0) {
662
		s_sz = (bsdar->s_cnt + 1) * sizeof(uint32_t) + bsdar->s_sn_sz;
671
		s_sz = (bsdar->s_cnt + 1) * sizeof(uint32_t) + bsdar->s_sn_sz;
663
		pm_sz = _ARMAG_LEN + (_ARHDR_LEN + s_sz);
672
		pm_sz = _ARMAG_LEN + (_ARHDR_LEN + s_sz);
664
		if (bsdar->as != NULL)
673
		if (bsdar->as != NULL)
665
			pm_sz += _ARHDR_LEN + bsdar->as_sz;
674
			pm_sz += _ARHDR_LEN + bsdar->as_sz;
666
		/* Use the 64-bit word size format if necessary. */
675
		/* Use the 64-bit word size format if necessary. */
667
		if (bsdar->s_so_max > UINT32_MAX - pm_sz) {
676
		if (bsdar->s_so_max > UINT32_MAX - pm_sz) {
668
			w_sz = sizeof(uint64_t);
677
			w_sz = sizeof(uint64_t);
669
			pm_sz -= s_sz;
678
			pm_sz -= s_sz;
670
			s_sz = (bsdar->s_cnt + 1) * sizeof(uint64_t) +
679
			s_sz = (bsdar->s_cnt + 1) * sizeof(uint64_t) +
671
			    bsdar->s_sn_sz;
680
			    bsdar->s_sn_sz;
672
			pm_sz += s_sz;
681
			pm_sz += s_sz;
673
			/* Convert to big-endian. */
682
			/* Convert to big-endian. */
674
			for (i = 0; i < bsdar->s_cnt; i++)
683
			for (i = 0; i < bsdar->s_cnt; i++)
675
				bsdar->s_so[i] =
684
				bsdar->s_so[i] =
676
				    htobe64(bsdar->s_so[i] + pm_sz);
685
				    htobe64(bsdar->s_so[i] + pm_sz);
677
		} else {
686
		} else {
678
			/*
687
			/*
679
			 * Convert to big-endian and shuffle in-place to
688
			 * Convert to big-endian and shuffle in-place to
680
			 * the front of the allocation. XXX UB
689
			 * the front of the allocation. XXX UB
681
			 */
690
			 */
682
			for (i = 0; i < bsdar->s_cnt; i++)
691
			for (i = 0; i < bsdar->s_cnt; i++)
683
				((uint32_t *)(bsdar->s_so))[i] =
692
				((uint32_t *)(bsdar->s_so))[i] =
684
				    htobe32(bsdar->s_so[i] + pm_sz);
693
				    htobe32(bsdar->s_so[i] + pm_sz);
685
		}
694
		}
686
	}
695
	}
687
696
688
	if ((a = archive_write_new()) == NULL)
697
	if ((a = archive_write_new()) == NULL)
689
		bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_write_new failed");
698
		bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_write_new failed");
690
699
691
	archive_write_set_format_ar_svr4(a);
700
	archive_write_set_format_ar_svr4(a);
692
701
693
	AC(archive_write_open_filename(a, bsdar->filename));
702
	AC(archive_write_open_filename(a, bsdar->filename));
694
703
695
	/*
704
	/*
696
	 * write the archive symbol table, if there is one.
705
	 * write the archive symbol table, if there is one.
697
	 * If options -s is explicitly specified or we are invoked
706
	 * If options -s is explicitly specified or we are invoked
698
	 * as ranlib, write the symbol table even if it is empty.
707
	 * as ranlib, write the symbol table even if it is empty.
699
	 */
708
	 */
700
	if ((bsdar->s_cnt != 0 && !(bsdar->options & AR_SS)) ||
709
	if ((bsdar->s_cnt != 0 && !(bsdar->options & AR_SS)) ||
701
	    bsdar->options & AR_S) {
710
	    bsdar->options & AR_S) {
702
		entry = archive_entry_new();
711
		entry = archive_entry_new();
703
		if (entry == NULL)
712
		if (entry == NULL)
704
			bsdar_errc(bsdar, EX_SOFTWARE, 0,
713
			bsdar_errc(bsdar, EX_SOFTWARE, 0,
705
			    "archive_entry_new failed");
714
			    "archive_entry_new failed");
706
		if (w_sz == sizeof(uint64_t))
715
		if (w_sz == sizeof(uint64_t))
707
			archive_entry_copy_pathname(entry, "/SYM64/");
716
			archive_entry_copy_pathname(entry, "/SYM64/");
708
		else
717
		else
709
			archive_entry_copy_pathname(entry, "/");
718
			archive_entry_copy_pathname(entry, "/");
710
		if ((bsdar->options & AR_D) == 0)
719
		if ((bsdar->options & AR_D) == 0)
711
			archive_entry_set_mtime(entry, time(NULL), 0);
720
			archive_entry_set_mtime(entry, time(NULL), 0);
712
		archive_entry_set_size(entry, (bsdar->s_cnt + 1) * w_sz +
721
		archive_entry_set_size(entry, (bsdar->s_cnt + 1) * w_sz +
713
		    bsdar->s_sn_sz);
722
		    bsdar->s_sn_sz);
714
		AC(archive_write_header(a, entry));
723
		AC(archive_write_header(a, entry));
715
		if (w_sz == sizeof(uint64_t)) {
724
		if (w_sz == sizeof(uint64_t)) {
716
			nr = htobe64(bsdar->s_cnt);
725
			nr = htobe64(bsdar->s_cnt);
717
			write_data(bsdar, a, &nr, sizeof(nr));
726
			write_data(bsdar, a, &nr, sizeof(nr));
718
		} else {
727
		} else {
719
			nr32 = htobe32((uint32_t)bsdar->s_cnt);
728
			nr32 = htobe32((uint32_t)bsdar->s_cnt);
720
			write_data(bsdar, a, &nr32, sizeof(nr32));
729
			write_data(bsdar, a, &nr32, sizeof(nr32));
721
		}
730
		}
722
		write_data(bsdar, a, bsdar->s_so, w_sz * bsdar->s_cnt);
731
		write_data(bsdar, a, bsdar->s_so, w_sz * bsdar->s_cnt);
723
		write_data(bsdar, a, bsdar->s_sn, bsdar->s_sn_sz);
732
		write_data(bsdar, a, bsdar->s_sn, bsdar->s_sn_sz);
724
		archive_entry_free(entry);
733
		archive_entry_free(entry);
725
	}
734
	}
726
735
727
	/* write the archive string table, if any. */
736
	/* write the archive string table, if any. */
728
	if (bsdar->as != NULL) {
737
	if (bsdar->as != NULL) {
729
		entry = archive_entry_new();
738
		entry = archive_entry_new();
730
		if (entry == NULL)
739
		if (entry == NULL)
731
			bsdar_errc(bsdar, EX_SOFTWARE, 0,
740
			bsdar_errc(bsdar, EX_SOFTWARE, 0,
732
			    "archive_entry_new failed");
741
			    "archive_entry_new failed");
733
		archive_entry_copy_pathname(entry, "//");
742
		archive_entry_copy_pathname(entry, "//");
734
		archive_entry_set_size(entry, bsdar->as_sz);
743
		archive_entry_set_size(entry, bsdar->as_sz);
735
		AC(archive_write_header(a, entry));
744
		AC(archive_write_header(a, entry));
736
		write_data(bsdar, a, bsdar->as, bsdar->as_sz);
745
		write_data(bsdar, a, bsdar->as, bsdar->as_sz);
737
		archive_entry_free(entry);
746
		archive_entry_free(entry);
738
	}
747
	}
739
748
740
	/* write normal members. */
749
	/* write normal members. */
741
	TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
750
	TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
742
		entry = archive_entry_new();
751
		entry = archive_entry_new();
743
		if (entry == NULL)
752
		if (entry == NULL)
744
			bsdar_errc(bsdar, EX_SOFTWARE, 0,
753
			bsdar_errc(bsdar, EX_SOFTWARE, 0,
745
			    "archive_entry_new failed");
754
			    "archive_entry_new failed");
746
		archive_entry_copy_pathname(entry, obj->name);
755
		archive_entry_copy_pathname(entry, obj->name);
747
		archive_entry_set_uid(entry, obj->uid);
756
		archive_entry_set_uid(entry, obj->uid);
748
		archive_entry_set_gid(entry, obj->gid);
757
		archive_entry_set_gid(entry, obj->gid);
749
		archive_entry_set_mode(entry, obj->md);
758
		archive_entry_set_mode(entry, obj->md);
750
		archive_entry_set_size(entry, obj->size);
759
		archive_entry_set_size(entry, obj->size);
751
		archive_entry_set_mtime(entry, obj->mtime, 0);
760
		archive_entry_set_mtime(entry, obj->mtime, 0);
752
		archive_entry_set_dev(entry, obj->dev);
761
		archive_entry_set_dev(entry, obj->dev);
753
		archive_entry_set_ino(entry, obj->ino);
762
		archive_entry_set_ino(entry, obj->ino);
754
		archive_entry_set_filetype(entry, AE_IFREG);
763
		archive_entry_set_filetype(entry, AE_IFREG);
755
		AC(archive_write_header(a, entry));
764
		AC(archive_write_header(a, entry));
756
		write_data(bsdar, a, obj->maddr, obj->size);
765
		write_data(bsdar, a, obj->maddr, obj->size);
757
		archive_entry_free(entry);
766
		archive_entry_free(entry);
758
	}
767
	}
759
768
760
	AC(archive_write_close(a));
769
	AC(archive_write_close(a));
761
	AC(archive_write_free(a));
770
	AC(archive_write_free(a));
762
}
771
}
763
772
764
/*
773
/*
765
 * Extract global symbols from ELF binary members.
774
 * Extract global symbols from ELF binary members.
766
 */
775
 */
767
static void
776
static void
768
create_symtab_entry(struct bsdar *bsdar, void *maddr, size_t size)
777
create_symtab_entry(struct bsdar *bsdar, void *maddr, size_t size)
769
{
778
{
770
	Elf		*e;
779
	Elf		*e;
771
	Elf_Scn		*scn;
780
	Elf_Scn		*scn;
772
	GElf_Shdr	 shdr;
781
	GElf_Shdr	 shdr;
773
	GElf_Sym	 sym;
782
	GElf_Sym	 sym;
774
	Elf_Data	*data;
783
	Elf_Data	*data;
775
	char		*name;
784
	char		*name;
776
	size_t		 n, shstrndx;
785
	size_t		 n, shstrndx;
777
	int		 elferr, tabndx, len, i;
786
	int		 elferr, tabndx, len, i;
778
787
779
	if ((e = elf_memory(maddr, size)) == NULL) {
788
	if ((e = elf_memory(maddr, size)) == NULL) {
780
		bsdar_warnc(bsdar, 0, "elf_memory() failed: %s",
789
		bsdar_warnc(bsdar, 0, "elf_memory() failed: %s",
781
		     elf_errmsg(-1));
790
		     elf_errmsg(-1));
782
		return;
791
		return;
783
	}
792
	}
784
	if (elf_kind(e) != ELF_K_ELF) {
793
	if (elf_kind(e) != ELF_K_ELF) {
785
		/* Silently ignore non-elf member. */
794
		/* Silently ignore non-elf member. */
786
		elf_end(e);
795
		elf_end(e);
787
		return;
796
		return;
788
	}
797
	}
789
	if (elf_getshstrndx(e, &shstrndx) == 0) {
798
	if (elf_getshstrndx(e, &shstrndx) == 0) {
790
		bsdar_warnc(bsdar, EX_SOFTWARE, 0, "elf_getshstrndx failed: %s",
799
		bsdar_warnc(bsdar, EX_SOFTWARE, 0, "elf_getshstrndx failed: %s",
791
		     elf_errmsg(-1));
800
		     elf_errmsg(-1));
792
		elf_end(e);
801
		elf_end(e);
793
		return;
802
		return;
794
	}
803
	}
795
804
796
	tabndx = -1;
805
	tabndx = -1;
797
	scn = NULL;
806
	scn = NULL;
798
	while ((scn = elf_nextscn(e, scn)) != NULL) {
807
	while ((scn = elf_nextscn(e, scn)) != NULL) {
799
		if (gelf_getshdr(scn, &shdr) != &shdr) {
808
		if (gelf_getshdr(scn, &shdr) != &shdr) {
800
			bsdar_warnc(bsdar, 0,
809
			bsdar_warnc(bsdar, 0,
801
			    "elf_getshdr failed: %s", elf_errmsg(-1));
810
			    "elf_getshdr failed: %s", elf_errmsg(-1));
802
			continue;
811
			continue;
803
		}
812
		}
804
		if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL) {
813
		if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL) {
805
			bsdar_warnc(bsdar, 0,
814
			bsdar_warnc(bsdar, 0,
806
			    "elf_strptr failed: %s", elf_errmsg(-1));
815
			    "elf_strptr failed: %s", elf_errmsg(-1));
807
			continue;
816
			continue;
808
		}
817
		}
809
		if (strcmp(name, ".strtab") == 0) {
818
		if (strcmp(name, ".strtab") == 0) {
810
			tabndx = elf_ndxscn(scn);
819
			tabndx = elf_ndxscn(scn);
811
			break;
820
			break;
812
		}
821
		}
813
	}
822
	}
814
	elferr = elf_errno();
823
	elferr = elf_errno();
815
	if (elferr != 0)
824
	if (elferr != 0)
816
		bsdar_warnc(bsdar, 0, "elf_nextscn failed: %s",
825
		bsdar_warnc(bsdar, 0, "elf_nextscn failed: %s",
817
		     elf_errmsg(elferr));
826
		     elf_errmsg(elferr));
818
	if (tabndx == -1) {
827
	if (tabndx == -1) {
819
		bsdar_warnc(bsdar, 0, "can't find .strtab section");
828
		bsdar_warnc(bsdar, 0, "can't find .strtab section");
820
		elf_end(e);
829
		elf_end(e);
821
		return;
830
		return;
822
	}
831
	}
823
832
824
	scn = NULL;
833
	scn = NULL;
825
	while ((scn = elf_nextscn(e, scn)) != NULL) {
834
	while ((scn = elf_nextscn(e, scn)) != NULL) {
826
		if (gelf_getshdr(scn, &shdr) != &shdr) {
835
		if (gelf_getshdr(scn, &shdr) != &shdr) {
827
			bsdar_warnc(bsdar, EX_SOFTWARE, 0,
836
			bsdar_warnc(bsdar, EX_SOFTWARE, 0,
828
			    "elf_getshdr failed: %s", elf_errmsg(-1));
837
			    "elf_getshdr failed: %s", elf_errmsg(-1));
829
			continue;
838
			continue;
830
		}
839
		}
831
		if (shdr.sh_type != SHT_SYMTAB)
840
		if (shdr.sh_type != SHT_SYMTAB)
832
			continue;
841
			continue;
833
842
834
		data = NULL;
843
		data = NULL;
835
		n = 0;
844
		n = 0;
836
		while (n < shdr.sh_size &&
845
		while (n < shdr.sh_size &&
837
		    (data = elf_getdata(scn, data)) != NULL) {
846
		    (data = elf_getdata(scn, data)) != NULL) {
838
			len = data->d_size / shdr.sh_entsize;
847
			len = data->d_size / shdr.sh_entsize;
839
			for (i = 0; i < len; i++) {
848
			for (i = 0; i < len; i++) {
840
				if (gelf_getsym(data, i, &sym) != &sym) {
849
				if (gelf_getsym(data, i, &sym) != &sym) {
841
					bsdar_warnc(bsdar, EX_SOFTWARE, 0,
850
					bsdar_warnc(bsdar, EX_SOFTWARE, 0,
842
					    "gelf_getsym failed: %s",
851
					    "gelf_getsym failed: %s",
843
					     elf_errmsg(-1));
852
					     elf_errmsg(-1));
844
					continue;
853
					continue;
845
				}
854
				}
846
855
847
				/* keep only global or weak symbols */
856
				/* keep only global or weak symbols */
848
				if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL &&
857
				if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL &&
849
				    GELF_ST_BIND(sym.st_info) != STB_WEAK)
858
				    GELF_ST_BIND(sym.st_info) != STB_WEAK)
850
					continue;
859
					continue;
851
860
852
				/* keep only defined symbols */
861
				/* keep only defined symbols */
853
				if (sym.st_shndx == SHN_UNDEF)
862
				if (sym.st_shndx == SHN_UNDEF)
854
					continue;
863
					continue;
855
864
856
				if ((name = elf_strptr(e, tabndx,
865
				if ((name = elf_strptr(e, tabndx,
857
				    sym.st_name)) == NULL) {
866
				    sym.st_name)) == NULL) {
858
					bsdar_warnc(bsdar, EX_SOFTWARE, 0,
867
					bsdar_warnc(bsdar, EX_SOFTWARE, 0,
859
					    "elf_strptr failed: %s",
868
					    "elf_strptr failed: %s",
860
					     elf_errmsg(-1));
869
					     elf_errmsg(-1));
861
					continue;
870
					continue;
862
				}
871
				}
863
872
864
				add_to_ar_sym_table(bsdar, name);
873
				add_to_ar_sym_table(bsdar, name);
865
			}
874
			}
866
		}
875
		}
867
	}
876
	}
868
	elferr = elf_errno();
877
	elferr = elf_errno();
869
	if (elferr != 0)
878
	if (elferr != 0)
870
		bsdar_warnc(bsdar, EX_SOFTWARE, 0, "elf_nextscn failed: %s",
879
		bsdar_warnc(bsdar, EX_SOFTWARE, 0, "elf_nextscn failed: %s",
871
		     elf_errmsg(elferr));
880
		     elf_errmsg(elferr));
872
881
873
	elf_end(e);
882
	elf_end(e);
874
}
883
}
875
884
876
/*
885
/*
877
 * Append to the archive string table buffer.
886
 * Append to the archive string table buffer.
878
 */
887
 */
879
static void
888
static void
880
add_to_ar_str_table(struct bsdar *bsdar, const char *name)
889
add_to_ar_str_table(struct bsdar *bsdar, const char *name)
881
{
890
{
882
891
883
	if (bsdar->as == NULL) {
892
	if (bsdar->as == NULL) {
884
		bsdar->as_cap = _INIT_AS_CAP;
893
		bsdar->as_cap = _INIT_AS_CAP;
885
		bsdar->as_sz = 0;
894
		bsdar->as_sz = 0;
886
		if ((bsdar->as = malloc(bsdar->as_cap)) == NULL)
895
		if ((bsdar->as = malloc(bsdar->as_cap)) == NULL)
887
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
896
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
888
	}
897
	}
889
898
890
	/*
899
	/*
891
	 * The space required for holding one member name in as table includes:
900
	 * The space required for holding one member name in as table includes:
892
	 * strlen(name) + (1 for '/') + (1 for '\n') + (possibly 1 for padding).
901
	 * strlen(name) + (1 for '/') + (1 for '\n') + (possibly 1 for padding).
893
	 */
902
	 */
894
	while (bsdar->as_sz + strlen(name) + 3 > bsdar->as_cap) {
903
	while (bsdar->as_sz + strlen(name) + 3 > bsdar->as_cap) {
895
		bsdar->as_cap *= 2;
904
		bsdar->as_cap *= 2;
896
		bsdar->as = realloc(bsdar->as, bsdar->as_cap);
905
		bsdar->as = realloc(bsdar->as, bsdar->as_cap);
897
		if (bsdar->as == NULL)
906
		if (bsdar->as == NULL)
898
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "realloc failed");
907
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "realloc failed");
899
	}
908
	}
900
	strncpy(&bsdar->as[bsdar->as_sz], name, strlen(name));
909
	strncpy(&bsdar->as[bsdar->as_sz], name, strlen(name));
901
	bsdar->as_sz += strlen(name);
910
	bsdar->as_sz += strlen(name);
902
	bsdar->as[bsdar->as_sz++] = '/';
911
	bsdar->as[bsdar->as_sz++] = '/';
903
	bsdar->as[bsdar->as_sz++] = '\n';
912
	bsdar->as[bsdar->as_sz++] = '\n';
904
}
913
}
905
914
906
/*
915
/*
907
 * Append to the archive symbol table buffer.
916
 * Append to the archive symbol table buffer.
908
 */
917
 */
909
static void
918
static void
910
add_to_ar_sym_table(struct bsdar *bsdar, const char *name)
919
add_to_ar_sym_table(struct bsdar *bsdar, const char *name)
911
{
920
{
912
921
913
	if (bsdar->s_so == NULL) {
922
	if (bsdar->s_so == NULL) {
914
		if ((bsdar->s_so = malloc(_INIT_SYMOFF_CAP)) ==
923
		if ((bsdar->s_so = malloc(_INIT_SYMOFF_CAP)) ==
915
		    NULL)
924
		    NULL)
916
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
925
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
917
		bsdar->s_so_cap = _INIT_SYMOFF_CAP;
926
		bsdar->s_so_cap = _INIT_SYMOFF_CAP;
918
		bsdar->s_cnt = 0;
927
		bsdar->s_cnt = 0;
919
	}
928
	}
920
929
921
	if (bsdar->s_sn == NULL) {
930
	if (bsdar->s_sn == NULL) {
922
		if ((bsdar->s_sn = malloc(_INIT_SYMNAME_CAP)) == NULL)
931
		if ((bsdar->s_sn = malloc(_INIT_SYMNAME_CAP)) == NULL)
923
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
932
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed");
924
		bsdar->s_sn_cap = _INIT_SYMNAME_CAP;
933
		bsdar->s_sn_cap = _INIT_SYMNAME_CAP;
925
		bsdar->s_sn_sz = 0;
934
		bsdar->s_sn_sz = 0;
926
	}
935
	}
927
936
928
	if (bsdar->s_cnt * sizeof(uint64_t) >= bsdar->s_so_cap) {
937
	if (bsdar->s_cnt * sizeof(uint64_t) >= bsdar->s_so_cap) {
929
		bsdar->s_so_cap *= 2;
938
		bsdar->s_so_cap *= 2;
930
		bsdar->s_so = realloc(bsdar->s_so, bsdar->s_so_cap);
939
		bsdar->s_so = realloc(bsdar->s_so, bsdar->s_so_cap);
931
		if (bsdar->s_so == NULL)
940
		if (bsdar->s_so == NULL)
932
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "realloc failed");
941
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "realloc failed");
933
	}
942
	}
934
	bsdar->s_so[bsdar->s_cnt] = bsdar->rela_off;
943
	bsdar->s_so[bsdar->s_cnt] = bsdar->rela_off;
935
	if ((uint64_t)bsdar->rela_off > bsdar->s_so_max)
944
	if ((uint64_t)bsdar->rela_off > bsdar->s_so_max)
936
		bsdar->s_so_max = (uint64_t)bsdar->rela_off;
945
		bsdar->s_so_max = (uint64_t)bsdar->rela_off;
937
	bsdar->s_cnt++;
946
	bsdar->s_cnt++;
938
947
939
	/*
948
	/*
940
	 * The space required for holding one symbol name in sn table includes:
949
	 * The space required for holding one symbol name in sn table includes:
941
	 * strlen(name) + (1 for '\n') + (possibly 1 for padding).
950
	 * strlen(name) + (1 for '\n') + (possibly 1 for padding).
942
	 */
951
	 */
943
	while (bsdar->s_sn_sz + strlen(name) + 2 > bsdar->s_sn_cap) {
952
	while (bsdar->s_sn_sz + strlen(name) + 2 > bsdar->s_sn_cap) {
944
		bsdar->s_sn_cap *= 2;
953
		bsdar->s_sn_cap *= 2;
945
		bsdar->s_sn = realloc(bsdar->s_sn, bsdar->s_sn_cap);
954
		bsdar->s_sn = realloc(bsdar->s_sn, bsdar->s_sn_cap);
946
		if (bsdar->s_sn == NULL)
955
		if (bsdar->s_sn == NULL)
947
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "realloc failed");
956
			bsdar_errc(bsdar, EX_SOFTWARE, errno, "realloc failed");
948
	}
957
	}
949
	strncpy(&bsdar->s_sn[bsdar->s_sn_sz], name, strlen(name));
958
	strncpy(&bsdar->s_sn[bsdar->s_sn_sz], name, strlen(name));
950
	bsdar->s_sn_sz += strlen(name);
959
	bsdar->s_sn_sz += strlen(name);
951
	bsdar->s_sn[bsdar->s_sn_sz++] = '\0';
960
	bsdar->s_sn[bsdar->s_sn_sz++] = '\0';
952
}
961
}

Return to bug 257599