2 * Copyright (c) 1990, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Hugh Smith at The University of Guelph.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * @(#)archive.c 8.3 (Berkeley) 4/2/94
37 * $FreeBSD: src/usr.bin/ar/archive.c,v 1.10.6.1 2001/08/02 00:51:00 obrien Exp $
38 * $DragonFly: src/usr.bin/ar/archive.c,v 1.4 2005/01/13 19:57:56 okumoto Exp $
41 #include <sys/param.h>
58 typedef struct ar_hdr HDR
;
59 static char hb
[sizeof(HDR
) + 1]; /* real header */
62 open_archive(int mode
)
70 if ((fd
= open(archive
, mode
, DEFFILEMODE
)) >= 0) {
71 /* POSIX.2 puts create message on stderr. */
72 if (!(options
& AR_C
))
73 warnx("creating archive %s", archive
);
81 if ((fd
= open(archive
, mode
, DEFFILEMODE
)) < 0)
85 * Attempt to place a lock on the opened file - if we get an
86 * error then someone is already working on this library (or
87 * it's going across NFS).
89 opened
: if (flock(fd
, LOCK_EX
|LOCK_NB
) && errno
!= EOPNOTSUPP
)
93 * If not created, O_RDONLY|O_RDWR indicates that it has to be
97 ((mode
& O_ACCMODE
) == O_RDONLY
|| (mode
& O_ACCMODE
) == O_RDWR
)) {
98 if ((nr
= read(fd
, buf
, SARMAG
) != SARMAG
)) {
102 } else if (bcmp(buf
, ARMAG
, SARMAG
))
104 } else if (write(fd
, ARMAG
, SARMAG
) != SARMAG
)
110 close_archive(int fd
)
113 close(fd
); /* Implicit unlock. */
116 /* Convert ar header field to an integer. */
117 #define AR_ATOI(from, to, len, base) { \
118 memmove(buf, from, len); \
120 to = strtol(buf, (char **)NULL, base); \
125 * read the archive header for this member
134 nr
= read(fd
, hb
, sizeof(HDR
));
135 if (nr
!= sizeof(HDR
)) {
143 hdr
= (struct ar_hdr
*)hb
;
144 if (strncmp(hdr
->ar_fmag
, ARFMAG
, sizeof(ARFMAG
) - 1))
147 /* Convert the header into the internal format. */
151 AR_ATOI(hdr
->ar_date
, chdr
.date
, sizeof(hdr
->ar_date
), DECIMAL
);
152 AR_ATOI(hdr
->ar_uid
, chdr
.uid
, sizeof(hdr
->ar_uid
), DECIMAL
);
153 AR_ATOI(hdr
->ar_gid
, chdr
.gid
, sizeof(hdr
->ar_gid
), DECIMAL
);
154 AR_ATOI(hdr
->ar_mode
, chdr
.mode
, sizeof(hdr
->ar_mode
), OCTAL
);
155 AR_ATOI(hdr
->ar_size
, chdr
.size
, sizeof(hdr
->ar_size
), DECIMAL
);
157 /* Leading spaces should never happen. */
158 if (hdr
->ar_name
[0] == ' ')
162 * Long name support. Set the "real" size of the file, and the
163 * long name flag/size.
165 if (!bcmp(hdr
->ar_name
, AR_EFMT1
, sizeof(AR_EFMT1
) - 1)) {
166 chdr
.lname
= len
= atoi(hdr
->ar_name
+ sizeof(AR_EFMT1
) - 1);
167 if (len
<= 0 || len
> MAXNAMLEN
)
169 nr
= read(fd
, chdr
.name
, len
);
179 memmove(chdr
.name
, hdr
->ar_name
, sizeof(hdr
->ar_name
));
181 /* Strip trailing spaces, null terminate. */
182 for (p
= chdr
.name
+ sizeof(hdr
->ar_name
) - 1; *p
== ' '; --p
);
188 static int already_written
;
192 * Write an archive member to a file.
195 put_arobj(CF
*cfp
, struct stat
*sb
)
203 * If passed an sb structure, reading a file from disk. Get stat(2)
204 * information, build a name and construct a header. (Files are named
205 * by their last component in the archive.) If not, then just write
206 * the last header read.
209 name
= basename(cfp
->rname
);
213 * If not truncating names and the name is too long or contains
214 * a space, use extended format 1.
216 lname
= strlen(name
);
217 if (options
& AR_TR
) {
218 if (lname
> OLDARMAXNAME
) {
220 warnx("warning: %s truncated to %.*s",
221 name
, OLDARMAXNAME
, name
);
224 sprintf(hb
, HDR3
, name
,
225 (long)sb
->st_mtimespec
.tv_sec
, sb
->st_uid
,
226 sb
->st_gid
, sb
->st_mode
, sb
->st_size
, ARFMAG
);
228 } else if (lname
> (long)sizeof(hdr
->ar_name
) || strchr(name
, ' '))
229 sprintf(hb
, HDR1
, AR_EFMT1
, lname
,
230 (long)sb
->st_mtimespec
.tv_sec
, sb
->st_uid
,
231 sb
->st_gid
, sb
->st_mode
, sb
->st_size
+ lname
,
235 sprintf(hb
, HDR2
, name
,
236 (long)sb
->st_mtimespec
.tv_sec
, sb
->st_uid
,
237 sb
->st_gid
, sb
->st_mode
, sb
->st_size
, ARFMAG
);
246 if (write(cfp
->wfd
, hb
, sizeof(HDR
)) != sizeof(HDR
))
249 if (write(cfp
->wfd
, name
, lname
) != lname
)
251 already_written
= lname
;
259 * Copy size bytes from one file to another - taking care to handle the
260 * extra byte (for odd size files) when reading archives and writing an
261 * extra byte if necessary when adding files to archive. The length of
262 * the object is the long name plus the object itself; the variable
263 * already_written gets set if a long name was written.
265 * The padding is really unnecessary, and is almost certainly a remnant
266 * of early archive formats where the header included binary data which
267 * a PDP-11 required to start on an even byte boundary. (Or, perhaps,
268 * because 16-bit word addressed copies were faster?) Anyhow, it should
269 * have been ripped out long ago.
272 copy_ar(CF
*cfp
, off_t size
)
274 static char pad
= '\n';
276 int from
, nr
= 0, nw
, off
, to
;
285 while (sz
&& (nr
= read(from
, buf
, MIN(sz
, sizeof(buf
)))) > 0) {
287 for (off
= 0; off
< nr
; nr
-= off
, off
+= nw
)
288 if ((nw
= write(to
, buf
+ off
, nr
)) < 0)
297 if (cfp
->flags
& RPAD
&& (size
+ chdr
.lname
) & 1 &&
298 (nr
= read(from
, buf
, 1)) != 1) {
303 if (cfp
->flags
& WPAD
&& (size
+ already_written
) & 1 &&
304 write(to
, &pad
, 1) != 1)
310 * Skip over an object -- taking care to skip the pad bytes.
317 len
= chdr
.size
+ ( (chdr
.size
+ chdr
.lname
) & 1);
318 if (lseek(fd
, len
, SEEK_CUR
) == (off_t
)-1)